This commit was generated by cvs2svn to compensate for changes in r338,
authorMarc Fiuczynski <mef@cs.princeton.edu>
Fri, 21 Jan 2005 03:33:53 +0000 (03:33 +0000)
committerMarc Fiuczynski <mef@cs.princeton.edu>
Fri, 21 Jan 2005 03:33:53 +0000 (03:33 +0000)
which included commits to RCS files with non-trunk default branches.

2246 files changed:
Documentation/CodingStyle
Documentation/DocBook/Makefile
Documentation/DocBook/gadget.tmpl
Documentation/DocBook/mousedrivers.tmpl
Documentation/DocBook/usb.tmpl
Documentation/IPMI.txt
Documentation/ManagementStyle [new file with mode: 0644]
Documentation/RCU/RTFP.txt [new file with mode: 0644]
Documentation/RCU/UP.txt [new file with mode: 0644]
Documentation/RCU/arrayRCU.txt [new file with mode: 0644]
Documentation/RCU/checklist.txt [new file with mode: 0644]
Documentation/RCU/listRCU.txt [new file with mode: 0644]
Documentation/RCU/rcu.txt [new file with mode: 0644]
Documentation/arm/IXP2000 [new file with mode: 0644]
Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt [new file with mode: 0644]
Documentation/arm/Samsung-S3C24XX/GPIO.txt [new file with mode: 0644]
Documentation/arm/Samsung-S3C24XX/Overview.txt [new file with mode: 0644]
Documentation/crypto/api-intro.txt
Documentation/driver-model/bus.txt
Documentation/filesystems/Locking
Documentation/filesystems/ext2.txt
Documentation/filesystems/ext3.txt
Documentation/filesystems/tmpfs.txt
Documentation/filesystems/vfs.txt
Documentation/filesystems/xfs.txt
Documentation/firmware_class/firmware_sample_firmware_class.c
Documentation/firmware_class/hotplug-script
Documentation/i2c/sysfs-interface
Documentation/i2o/README [new file with mode: 0644]
Documentation/i2o/ioctl [new file with mode: 0644]
Documentation/input/joystick-parport.txt
Documentation/kbuild/makefiles.txt
Documentation/networking/gen_stats.txt [new file with mode: 0644]
Documentation/networking/netdevices.txt
Documentation/powerpc/hvcs.txt
Documentation/sched-stats.txt [new file with mode: 0644]
Documentation/scsi/ChangeLog.megaraid
Documentation/scsi/megaraid.txt [new file with mode: 0644]
Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
Documentation/sysctl/kernel.txt
Documentation/time_interpolators.txt [new file with mode: 0644]
Documentation/tty.txt [new file with mode: 0644]
Documentation/usb/sn9c102.txt
Documentation/vm/overcommit-accounting
Documentation/watchdog/pcwd-watchdog.txt
Documentation/x86_64/boot-options.txt
arch/alpha/Kconfig.debug [new file with mode: 0644]
arch/alpha/boot/Makefile
arch/alpha/kernel/Makefile
arch/alpha/kernel/alpha_ksyms.c
arch/alpha/kernel/io.c [new file with mode: 0644]
arch/alpha/kernel/irq_impl.h
arch/alpha/kernel/pci-noop.c
arch/alpha/kernel/pci.c
arch/alpha/kernel/pci_iommu.c
arch/alpha/kernel/srmcons.c
arch/alpha/kernel/sys_alcor.c
arch/alpha/kernel/sys_cabriolet.c
arch/alpha/kernel/sys_eb64p.c
arch/alpha/kernel/sys_jensen.c
arch/alpha/kernel/sys_marvel.c
arch/alpha/kernel/sys_miata.c
arch/alpha/kernel/sys_mikasa.c
arch/alpha/kernel/sys_nautilus.c
arch/alpha/kernel/sys_noritake.c
arch/alpha/kernel/sys_rawhide.c
arch/alpha/kernel/sys_rx164.c
arch/alpha/kernel/sys_sable.c
arch/alpha/kernel/sys_sio.c
arch/alpha/kernel/sys_titan.c
arch/alpha/kernel/sys_wildfire.c
arch/alpha/kernel/vmlinux.lds.S
arch/alpha/lib/Makefile
arch/arm/Kconfig.debug [new file with mode: 0644]
arch/arm/boot/compressed/big-endian.S [new file with mode: 0644]
arch/arm/boot/compressed/misc.c
arch/arm/configs/ebsa110_defconfig
arch/arm/configs/enp2611_defconfig [new file with mode: 0644]
arch/arm/configs/ep80219_defconfig [new file with mode: 0644]
arch/arm/configs/h7201_defconfig [new file with mode: 0644]
arch/arm/configs/h7202_defconfig [new file with mode: 0644]
arch/arm/configs/iq31244_defconfig [new file with mode: 0644]
arch/arm/configs/iq80321_defconfig
arch/arm/configs/iq80331_defconfig [new file with mode: 0644]
arch/arm/configs/ixdp2400_defconfig [new file with mode: 0644]
arch/arm/configs/ixdp2401_defconfig [new file with mode: 0644]
arch/arm/configs/ixdp2800_defconfig [new file with mode: 0644]
arch/arm/configs/ixdp2801_defconfig [new file with mode: 0644]
arch/arm/configs/ixp4xx_defconfig
arch/arm/configs/mx1ads_defconfig [new file with mode: 0644]
arch/arm/configs/s3c2410_defconfig
arch/arm/kernel/apm.c
arch/arm/kernel/calls.S
arch/arm/kernel/iwmmxt.S [new file with mode: 0644]
arch/arm/kernel/vmlinux.lds.S
arch/arm/lib/getuser.S
arch/arm/lib/putuser.S
arch/arm/mach-h720x/Kconfig [new file with mode: 0644]
arch/arm/mach-h720x/Makefile [new file with mode: 0644]
arch/arm/mach-h720x/common.c [new file with mode: 0644]
arch/arm/mach-h720x/cpu-h7201.c [new file with mode: 0644]
arch/arm/mach-h720x/cpu-h7202.c [new file with mode: 0644]
arch/arm/mach-h720x/h7201-eval.c [new file with mode: 0644]
arch/arm/mach-h720x/h7202-eval.c [new file with mode: 0644]
arch/arm/mach-imx/Kconfig [new file with mode: 0644]
arch/arm/mach-imx/Makefile [new file with mode: 0644]
arch/arm/mach-imx/dma.c [new file with mode: 0644]
arch/arm/mach-imx/generic.c [new file with mode: 0644]
arch/arm/mach-imx/generic.h [new file with mode: 0644]
arch/arm/mach-imx/irq.c [new file with mode: 0644]
arch/arm/mach-imx/leds-mx1ads.c [new file with mode: 0644]
arch/arm/mach-imx/leds.c [new file with mode: 0644]
arch/arm/mach-imx/leds.h [new file with mode: 0644]
arch/arm/mach-imx/mx1ads.c [new file with mode: 0644]
arch/arm/mach-imx/time.c [new file with mode: 0644]
arch/arm/mach-iop3xx/Kconfig
arch/arm/mach-iop3xx/Makefile
arch/arm/mach-iop3xx/common.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iop321-irq.c
arch/arm/mach-iop3xx/iop321-mm.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iop321-pci.c
arch/arm/mach-iop3xx/iop321-setup.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iop331-irq.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iop331-mm.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iop331-pci.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iop331-setup.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iop331-time.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iq31244-mm.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iq31244-pci.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iq80321-mm.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iq80321-pci.c
arch/arm/mach-iop3xx/iq80331-mm.c [new file with mode: 0644]
arch/arm/mach-iop3xx/iq80331-pci.c [new file with mode: 0644]
arch/arm/mach-ixp2000/Kconfig [new file with mode: 0644]
arch/arm/mach-ixp2000/Makefile [new file with mode: 0644]
arch/arm/mach-ixp2000/core.c [new file with mode: 0644]
arch/arm/mach-ixp2000/enp2611.c [new file with mode: 0644]
arch/arm/mach-ixp2000/ixdp2400.c [new file with mode: 0644]
arch/arm/mach-ixp2000/ixdp2800.c [new file with mode: 0644]
arch/arm/mach-ixp2000/ixdp2x00.c [new file with mode: 0644]
arch/arm/mach-ixp2000/ixdp2x01.c [new file with mode: 0644]
arch/arm/mach-ixp2000/pci.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-lh7a40x/time.c
arch/arm/mach-omap/board-h2.c [new file with mode: 0644]
arch/arm/mach-omap/board-h3.c [new file with mode: 0644]
arch/arm/mach-omap/clocks.c
arch/arm/mach-omap/common.c
arch/arm/mach-omap/fpga.c
arch/arm/mach-omap/leds-h2p2-debug.c [new file with mode: 0644]
arch/arm/mach-omap/leds.c
arch/arm/mach-omap/leds.h
arch/arm/mach-omap/mcbsp.c [new file with mode: 0644]
arch/arm/mach-omap/ocpi.c
arch/arm/mach-omap/usb.c [new file with mode: 0644]
arch/arm/mach-pxa/irq.c
arch/arm/mach-pxa/leds-mainstone.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/sleep.S
arch/arm/mach-pxa/time.c
arch/arm/mach-s3c2410/clock.c [new file with mode: 0644]
arch/arm/mach-s3c2410/clock.h [new file with mode: 0644]
arch/arm/mach-s3c2410/cpu.c [new file with mode: 0644]
arch/arm/mach-s3c2410/cpu.h [new file with mode: 0644]
arch/arm/mach-s3c2410/devs.c [new file with mode: 0644]
arch/arm/mach-s3c2410/devs.h [new file with mode: 0644]
arch/arm/mach-s3c2410/dma.c [new file with mode: 0644]
arch/arm/mach-s3c2410/gpio.c
arch/arm/mach-s3c2410/irq.c
arch/arm/mach-s3c2410/mach-smdk2410.c
arch/arm/mach-s3c2410/s3c2440-dsc.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2440.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2440.h [new file with mode: 0644]
arch/arm/mach-s3c2410/time.c
arch/arm/mach-s3c2410/usb-simtec.c [new file with mode: 0644]
arch/arm/mach-s3c2410/usb-simtec.h [new file with mode: 0644]
arch/arm/mach-sa1100/pm.c
arch/arm/mm/Makefile
arch/arm/mm/abort-ev5tj.S
arch/arm/mm/cache-v3.S
arch/arm/mm/cache-v4.S
arch/arm/mm/cache-v4wb.S
arch/arm/mm/cache-v4wt.S
arch/arm/mm/copypage-v6.c
arch/arm/mm/flush.c [new file with mode: 0644]
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-syms.c
arch/arm/mm/proc-v6.S
arch/arm/nwfpe/fpa11_cpdt.c
arch/arm/oprofile/op_model_xscale.c
arch/arm26/Kconfig.debug [new file with mode: 0644]
arch/arm26/Makefile
arch/arm26/boot/Makefile
arch/arm26/kernel/Makefile
arch/arm26/kernel/armksyms.c
arch/arm26/kernel/signal.c
arch/arm26/kernel/sys_arm.c
arch/arm26/kernel/time.c
arch/arm26/kernel/vmlinux-arm26-xip.lds.in
arch/arm26/kernel/vmlinux-arm26.lds.in
arch/cris/Kconfig.debug [new file with mode: 0644]
arch/cris/arch-v10/mm/init.c
arch/cris/arch-v10/vmlinux.lds.S
arch/cris/kernel/crisksyms.c
arch/h8300/Kconfig.debug [new file with mode: 0644]
arch/h8300/kernel/asm-offsets.c
arch/h8300/kernel/ints.c
arch/h8300/kernel/time.c
arch/h8300/lib/checksum.c
arch/h8300/platform/h8s/ints.c
arch/i386/Kconfig.debug [new file with mode: 0644]
arch/i386/kernel/cpu/centaur.c
arch/i386/kernel/cpu/cpufreq/Kconfig
arch/i386/kernel/cpu/cpufreq/acpi.c
arch/i386/kernel/cpu/mtrr/mtrr.h
arch/i386/kernel/ioport.c
arch/i386/kernel/kprobes.c [new file with mode: 0644]
arch/i386/kernel/pci-dma.c
arch/i386/kernel/time.c
arch/i386/kernel/timers/timer_pit.c
arch/i386/kernel/vsyscall.lds.S [new file with mode: 0644]
arch/i386/lib/mmx.c
arch/i386/mach-es7000/es7000plat.c
arch/i386/mm/mmap.c
arch/i386/oprofile/op_model_athlon.c
arch/i386/oprofile/op_model_ppro.c
arch/i386/pci/common.c
arch/i386/pci/i386.c
arch/i386/pci/mmconfig.c
arch/i386/pci/numa.c
arch/i386/pci/pcbios.c
arch/i386/power/Makefile
arch/ia64/Kconfig.debug [new file with mode: 0644]
arch/ia64/configs/bigsur_defconfig [new file with mode: 0644]
arch/ia64/configs/generic_defconfig
arch/ia64/configs/tiger_defconfig [new file with mode: 0644]
arch/ia64/configs/zx1_defconfig
arch/ia64/hp/common/sba_iommu.c
arch/ia64/hp/sim/simserial.c
arch/ia64/ia32/elfcore32.h
arch/ia64/ia32/ia32_ldt.c
arch/ia64/kernel/acpi-ext.c
arch/ia64/kernel/asm-offsets.c
arch/ia64/kernel/cyclone.c
arch/ia64/kernel/mca_drv.c [new file with mode: 0644]
arch/ia64/kernel/mca_drv.h [new file with mode: 0644]
arch/ia64/kernel/mca_drv_asm.S [new file with mode: 0644]
arch/ia64/kernel/minstate.h
arch/ia64/kernel/patch.c
arch/ia64/kernel/salinfo.c
arch/ia64/kernel/sigframe.h
arch/ia64/kernel/sys_ia64.c
arch/ia64/kernel/unaligned.c
arch/ia64/kernel/vmlinux.lds.S
arch/ia64/lib/csum_partial_copy.c
arch/ia64/lib/io.c
arch/ia64/lib/swiotlb.c
arch/ia64/mm/extable.c
arch/ia64/oprofile/Kconfig
arch/ia64/oprofile/Makefile
arch/ia64/oprofile/init.c
arch/ia64/oprofile/perfmon.c [new file with mode: 0644]
arch/ia64/sn/kernel/sn2/Makefile
arch/ia64/sn/kernel/sn2/sn_hwperf.c [new file with mode: 0644]
arch/ia64/sn/kernel/sn2/sn_proc_fs.c
arch/ia64/sn/kernel/sn2/timer.c
arch/m32r/Kconfig [new file with mode: 0644]
arch/m32r/Makefile [new file with mode: 0644]
arch/m32r/boot/Makefile [new file with mode: 0644]
arch/m32r/boot/compressed/Makefile [new file with mode: 0644]
arch/m32r/boot/compressed/boot.h [new file with mode: 0644]
arch/m32r/boot/compressed/head.S [new file with mode: 0644]
arch/m32r/boot/compressed/install.sh [new file with mode: 0644]
arch/m32r/boot/compressed/m32r_sio.c [new file with mode: 0644]
arch/m32r/boot/compressed/misc.c [new file with mode: 0644]
arch/m32r/boot/compressed/vmlinux.lds.S [new file with mode: 0644]
arch/m32r/boot/compressed/vmlinux.scr [new file with mode: 0644]
arch/m32r/boot/setup.S [new file with mode: 0644]
arch/m32r/defconfig [new file with mode: 0644]
arch/m32r/kernel/Makefile [new file with mode: 0644]
arch/m32r/kernel/align.c [new file with mode: 0644]
arch/m32r/kernel/entry.S [new file with mode: 0644]
arch/m32r/kernel/head.S [new file with mode: 0644]
arch/m32r/kernel/init_task.c [new file with mode: 0644]
arch/m32r/kernel/io_m32700ut.c [new file with mode: 0644]
arch/m32r/kernel/io_mappi.c [new file with mode: 0644]
arch/m32r/kernel/io_mappi2.c [new file with mode: 0644]
arch/m32r/kernel/io_oaks32r.c [new file with mode: 0644]
arch/m32r/kernel/io_opsput.c [new file with mode: 0644]
arch/m32r/kernel/io_usrv.c [new file with mode: 0644]
arch/m32r/kernel/irq.c [new file with mode: 0644]
arch/m32r/kernel/m32r_ksyms.c [new file with mode: 0644]
arch/m32r/kernel/module.c [new file with mode: 0644]
arch/m32r/kernel/process.c [new file with mode: 0644]
arch/m32r/kernel/ptrace.c [new file with mode: 0644]
arch/m32r/kernel/semaphore.c [new file with mode: 0644]
arch/m32r/kernel/setup.c [new file with mode: 0644]
arch/m32r/kernel/setup_m32700ut.c [new file with mode: 0644]
arch/m32r/kernel/setup_mappi.c [new file with mode: 0644]
arch/m32r/kernel/setup_mappi2.c [new file with mode: 0644]
arch/m32r/kernel/setup_oaks32r.c [new file with mode: 0644]
arch/m32r/kernel/setup_opsput.c [new file with mode: 0644]
arch/m32r/kernel/setup_usrv.c [new file with mode: 0644]
arch/m32r/kernel/signal.c [new file with mode: 0644]
arch/m32r/kernel/smp.c [new file with mode: 0644]
arch/m32r/kernel/smpboot.c [new file with mode: 0644]
arch/m32r/kernel/sys_m32r.c [new file with mode: 0644]
arch/m32r/kernel/time.c [new file with mode: 0644]
arch/m32r/kernel/traps.c [new file with mode: 0644]
arch/m32r/kernel/vmlinux.lds.S [new file with mode: 0644]
arch/m32r/lib/Makefile [new file with mode: 0644]
arch/m32r/lib/ashxdi3.S [new file with mode: 0644]
arch/m32r/lib/checksum.S [new file with mode: 0644]
arch/m32r/lib/csum_partial_copy.c [new file with mode: 0644]
arch/m32r/lib/delay.c [new file with mode: 0644]
arch/m32r/lib/getuser.S [new file with mode: 0644]
arch/m32r/lib/memcpy.S [new file with mode: 0644]
arch/m32r/lib/memset.S [new file with mode: 0644]
arch/m32r/lib/putuser.S [new file with mode: 0644]
arch/m32r/lib/strlen.S [new file with mode: 0644]
arch/m32r/lib/usercopy.c [new file with mode: 0644]
arch/m32r/m32700ut/defconfig.m32700ut.smp [new file with mode: 0644]
arch/m32r/m32700ut/defconfig.m32700ut.up [new file with mode: 0644]
arch/m32r/m32700ut/dot.gdbinit_200MHz_16MB [new file with mode: 0644]
arch/m32r/m32700ut/dot.gdbinit_300MHz_32MB [new file with mode: 0644]
arch/m32r/mappi/defconfig.nommu [new file with mode: 0644]
arch/m32r/mappi/defconfig.smp [new file with mode: 0644]
arch/m32r/mappi/defconfig.up [new file with mode: 0644]
arch/m32r/mappi/dot.gdbinit [new file with mode: 0644]
arch/m32r/mappi/dot.gdbinit.nommu [new file with mode: 0644]
arch/m32r/mappi/dot.gdbinit.smp [new file with mode: 0644]
arch/m32r/mm/Makefile [new file with mode: 0644]
arch/m32r/mm/cache.c [new file with mode: 0644]
arch/m32r/mm/discontig.c [new file with mode: 0644]
arch/m32r/mm/extable.c [new file with mode: 0644]
arch/m32r/mm/fault-nommu.c [new file with mode: 0644]
arch/m32r/mm/fault.c [new file with mode: 0644]
arch/m32r/mm/init.c [new file with mode: 0644]
arch/m32r/mm/ioremap-nommu.c [new file with mode: 0644]
arch/m32r/mm/ioremap.c [new file with mode: 0644]
arch/m32r/mm/mmu.S [new file with mode: 0644]
arch/m32r/mm/page.S [new file with mode: 0644]
arch/m32r/oaks32r/defconfig.nommu [new file with mode: 0644]
arch/m32r/oaks32r/dot.gdbinit.nommu [new file with mode: 0644]
arch/m32r/oprofile/Kconfig [new file with mode: 0644]
arch/m32r/oprofile/Makefile [new file with mode: 0644]
arch/m32r/oprofile/init.c [new file with mode: 0644]
arch/m32r/opsput/defconfig.opsput [new file with mode: 0644]
arch/m32r/opsput/dot.gdbinit [new file with mode: 0644]
arch/m68k/Kconfig.debug [new file with mode: 0644]
arch/m68k/kernel/Makefile
arch/m68k/kernel/m68k_ksyms.c
arch/m68k/kernel/time.c
arch/m68knommu/Kconfig.debug [new file with mode: 0644]
arch/m68knommu/kernel/Makefile
arch/m68knommu/kernel/asm-offsets.c
arch/m68knommu/kernel/signal.c
arch/m68knommu/kernel/time.c
arch/m68knommu/kernel/vmlinux.lds.S
arch/m68knommu/platform/5307/timers.c
arch/mips/Kconfig.debug [new file with mode: 0644]
arch/mips/au1000/common/time.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/mips-boards/generic/time.c
arch/mips/mm/fault.c
arch/mips/pci/fixup-atlas.c
arch/mips/pci/fixup-cobalt.c
arch/mips/pci/fixup-ddb5074.c
arch/mips/pci/fixup-ddb5477.c
arch/mips/pci/fixup-ip32.c
arch/mips/pci/fixup-lasat.c
arch/mips/pci/fixup-malta.c
arch/mips/pci/fixup-mpc30x.c
arch/mips/pci/fixup-sni.c
arch/mips/pci/pci-ip27.c
arch/mips/pci/pci-sb1250.c
arch/mips/pmc-sierra/yosemite/ht.c
arch/mips/sgi-ip27/ip27-memory.c
arch/parisc/Kconfig.debug [new file with mode: 0644]
arch/parisc/kernel/pci.c
arch/parisc/kernel/time.c
arch/parisc/lib/debuglocks.c
arch/ppc/Kconfig.debug [new file with mode: 0644]
arch/ppc/amiga/config.c
arch/ppc/boot/common/ns16550.c
arch/ppc/boot/common/serial_stub.c
arch/ppc/boot/common/util.S
arch/ppc/boot/include/nonstdio.h
arch/ppc/boot/include/serial.h [new file with mode: 0644]
arch/ppc/boot/lib/Makefile
arch/ppc/boot/openfirmware/coffmain.c
arch/ppc/boot/openfirmware/common.c
arch/ppc/boot/openfirmware/misc.S
arch/ppc/boot/simple/chrpmap.c [new file with mode: 0644]
arch/ppc/boot/simple/misc-embedded.c
arch/ppc/boot/simple/misc-prep.c
arch/ppc/boot/simple/misc-spruce.c
arch/ppc/boot/simple/pibs.c [new file with mode: 0644]
arch/ppc/boot/simple/prepmap.c [new file with mode: 0644]
arch/ppc/boot/simple/relocate.S
arch/ppc/boot/utils/mkbugboot.c
arch/ppc/boot/utils/mktree.c
arch/ppc/configs/mvme5100_defconfig
arch/ppc/kernel/cpu_setup_6xx.S
arch/ppc/kernel/cpu_setup_power4.S
arch/ppc/kernel/dma-mapping.c
arch/ppc/kernel/head_booke.h [new file with mode: 0644]
arch/ppc/kernel/head_e500.S
arch/ppc/kernel/idle.c
arch/ppc/kernel/idle_6xx.S
arch/ppc/kernel/idle_power4.S
arch/ppc/kernel/pci.c
arch/ppc/kernel/ppc_htab.c
arch/ppc/kernel/vector.S
arch/ppc/lib/checksum.S
arch/ppc/lib/rheap.c
arch/ppc/math-emu/op-common.h
arch/ppc/mm/44x_mmu.c
arch/ppc/mm/4xx_mmu.c
arch/ppc/platforms/85xx/mpc8540_ads.c
arch/ppc/platforms/85xx/mpc85xx_cds_common.c
arch/ppc/platforms/85xx/sbc8560.c
arch/ppc/platforms/chrp_setup.c
arch/ppc/platforms/chrp_smp.c
arch/ppc/platforms/k2.c
arch/ppc/platforms/lite5200.c
arch/ppc/platforms/lopec.c [new file with mode: 0644]
arch/ppc/platforms/lopec.h [new file with mode: 0644]
arch/ppc/platforms/mcpn765.c
arch/ppc/platforms/mcpn765.h
arch/ppc/platforms/mpc5200.c
arch/ppc/platforms/mvme5100.c [new file with mode: 0644]
arch/ppc/platforms/mvme5100.h
arch/ppc/platforms/pcore.c
arch/ppc/platforms/pmac_pci.c
arch/ppc/platforms/pmac_smp.c
arch/ppc/platforms/pmac_time.c
arch/ppc/platforms/powerpmc250.h
arch/ppc/platforms/pq2ads.c [new file with mode: 0644]
arch/ppc/platforms/pq2ads.h
arch/ppc/platforms/prep_pci.c
arch/ppc/platforms/prpmc750.c
arch/ppc/platforms/prpmc750.h
arch/ppc/platforms/prpmc800.c
arch/ppc/platforms/prpmc800.h
arch/ppc/platforms/residual.c
arch/ppc/platforms/spruce.c
arch/ppc/syslib/cpm2_pic.c
arch/ppc/syslib/cpm2_pic.h
arch/ppc/syslib/hawk_common.c
arch/ppc/syslib/ibm44x_common.c
arch/ppc/syslib/ibm44x_common.h
arch/ppc/syslib/m8260_pci.h
arch/ppc/syslib/m8xx_wdt.c [new file with mode: 0644]
arch/ppc/syslib/m8xx_wdt.h [new file with mode: 0644]
arch/ppc/syslib/mpc52xx_pic.c
arch/ppc/syslib/mpc52xx_setup.c
arch/ppc/syslib/open_pic2.c
arch/ppc/syslib/ppc4xx_setup.c
arch/ppc/syslib/ppc85xx_setup.c
arch/ppc/syslib/todc_time.c
arch/ppc64/Kconfig.debug [new file with mode: 0644]
arch/ppc64/boot/Makefile
arch/ppc64/boot/main.c
arch/ppc64/boot/zImage.lds
arch/ppc64/configs/g5_defconfig
arch/ppc64/configs/pSeries_defconfig
arch/ppc64/kernel/btext.c
arch/ppc64/kernel/hvconsole.c
arch/ppc64/kernel/hvcserver.c
arch/ppc64/kernel/iSeries_htab.c
arch/ppc64/kernel/iSeries_pci.c
arch/ppc64/kernel/iSeries_pci_reset.c
arch/ppc64/kernel/iSeries_setup.h
arch/ppc64/kernel/idle_power4.S
arch/ppc64/kernel/iomap.c [new file with mode: 0644]
arch/ppc64/kernel/lmb.c
arch/ppc64/kernel/nvram.c
arch/ppc64/kernel/open_pic_u3.c
arch/ppc64/kernel/pSeries_iommu.c
arch/ppc64/kernel/pSeries_lpar.c
arch/ppc64/kernel/pSeries_setup.c [new file with mode: 0644]
arch/ppc64/kernel/pci.c
arch/ppc64/kernel/pci_dn.c
arch/ppc64/kernel/pci_iommu.c
arch/ppc64/kernel/pmac_feature.c
arch/ppc64/kernel/pmac_low_i2c.c
arch/ppc64/kernel/pmac_pci.c
arch/ppc64/kernel/pmac_setup.c
arch/ppc64/kernel/pmac_time.c
arch/ppc64/kernel/prom_init.c [new file with mode: 0644]
arch/ppc64/kernel/u3_iommu.c [new file with mode: 0644]
arch/ppc64/kernel/vector.S
arch/ppc64/kernel/vmlinux.lds.S
arch/ppc64/lib/checksum.S
arch/ppc64/lib/locks.c
arch/ppc64/mm/hash_low.S
arch/ppc64/mm/hash_native.c [new file with mode: 0644]
arch/ppc64/mm/imalloc.c
arch/ppc64/mm/mmap.c
arch/ppc64/mm/slb.c
arch/ppc64/mm/slb_low.S
arch/ppc64/mm/stab.c [new file with mode: 0644]
arch/ppc64/oprofile/op_impl.h
arch/ppc64/oprofile/op_model_rs64.c
arch/s390/Kconfig.debug [new file with mode: 0644]
arch/s390/appldata/appldata_mem.c
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/ebcdic.c
arch/s390/kernel/irq.c [new file with mode: 0644]
arch/s390/kernel/profile.c
arch/s390/kernel/s390_ext.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kernel/vtime.c
arch/s390/lib/string.c
arch/sh/Kconfig.debug [new file with mode: 0644]
arch/sh/boards/mpc1211/pci.c
arch/sh/boards/overdrive/galileo.c
arch/sh/drivers/pci/fixups-dreamcast.c
arch/sh/drivers/pci/pci-st40.c
arch/sh/kernel/signal.c
arch/sh/mm/fault-nommu.c
arch/sh/mm/fault.c
arch/sh/mm/tlb-sh4.c
arch/sh64/Kconfig
arch/sh64/Kconfig.debug [new file with mode: 0644]
arch/sh64/kernel/irq.c
arch/sh64/kernel/pci_sh5.c
arch/sh64/kernel/process.c
arch/sh64/kernel/ptrace.c
arch/sh64/kernel/sh_ksyms.c
arch/sh64/kernel/signal.c
arch/sh64/kernel/time.c
arch/sh64/kernel/vmlinux.lds.S
arch/sh64/mm/fault.c
arch/sh64/mm/init.c
arch/sparc/Kconfig.debug [new file with mode: 0644]
arch/sparc/boot/Makefile
arch/sparc/kernel/Makefile
arch/sparc/kernel/entry.S
arch/sparc/kernel/pcic.c
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/vmlinux.lds.S
arch/sparc/mm/srmmu.c
arch/sparc64/Kconfig.debug [new file with mode: 0644]
arch/sparc64/boot/Makefile
arch/sparc64/kernel/Makefile
arch/sparc64/kernel/binfmt_elf32.c
arch/sparc64/kernel/chmc.c
arch/sparc64/kernel/etrap.S
arch/sparc64/kernel/kprobes.c [new file with mode: 0644]
arch/sparc64/kernel/pci_common.c
arch/sparc64/kernel/pci_impl.h
arch/sparc64/kernel/pci_iommu.c
arch/sparc64/kernel/pci_sabre.c
arch/sparc64/kernel/ttable.S
arch/sparc64/kernel/vmlinux.lds.S
arch/sparc64/lib/PeeCeeI.c
arch/sparc64/lib/U1copy_from_user.S [new file with mode: 0644]
arch/sparc64/lib/U1copy_to_user.S [new file with mode: 0644]
arch/sparc64/lib/U1memcpy.S [new file with mode: 0644]
arch/sparc64/lib/U3copy_from_user.S
arch/sparc64/lib/U3copy_to_user.S
arch/sparc64/lib/U3memcpy.S
arch/sparc64/lib/U3patch.S [new file with mode: 0644]
arch/sparc64/lib/atomic.S
arch/sparc64/lib/bitops.S
arch/sparc64/lib/copy_in_user.S [new file with mode: 0644]
arch/sparc64/lib/copy_page.S
arch/sparc64/lib/delay.c [new file with mode: 0644]
arch/sparc64/lib/iomap.c [new file with mode: 0644]
arch/sparc64/lib/ipcsum.S
arch/sparc64/lib/memmove.S [new file with mode: 0644]
arch/sparc64/lib/strlen.S
arch/sparc64/lib/strncmp.S
arch/sparc64/lib/strncpy_from_user.S
arch/sparc64/lib/user_fixup.c [new file with mode: 0644]
arch/sparc64/lib/xor.S
arch/sparc64/solaris/misc.c
arch/um/Kconfig.debug [new file with mode: 0644]
arch/um/Makefile-tt
arch/um/drivers/cow.h
arch/um/drivers/cow_sys.h [new file with mode: 0644]
arch/um/drivers/cow_user.c
arch/um/include/irq_kern.h
arch/um/include/mem_kern.h
arch/um/kernel/dyn.lds.S [new file with mode: 0644]
arch/um/kernel/main.c [new file with mode: 0644]
arch/um/kernel/physmem.c
arch/um/kernel/signal_user.c
arch/um/kernel/skas/tlb.c
arch/um/kernel/skas/uaccess.c
arch/um/kernel/tt/uaccess.c
arch/um/kernel/uml.lds.S [new file with mode: 0644]
arch/um/os-Linux/time.c [new file with mode: 0644]
arch/um/os-Linux/user_syms.c
arch/um/sys-i386/syscalls.c
arch/v850/Kconfig.debug [new file with mode: 0644]
arch/v850/kernel/Makefile
arch/v850/kernel/asm-consts.c
arch/v850/kernel/rte_mb_a_pci.c
arch/v850/kernel/signal.c
arch/v850/kernel/v850_ksyms.c
arch/x86_64/Kconfig.debug [new file with mode: 0644]
arch/x86_64/boot/Makefile
arch/x86_64/boot/video.S
arch/x86_64/kernel/aperture.c
arch/x86_64/kernel/apic.c
arch/x86_64/kernel/asm-offsets.c
arch/x86_64/kernel/cpufreq/Kconfig
arch/x86_64/kernel/cpufreq/Makefile
arch/x86_64/kernel/early_printk.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/ioport.c
arch/x86_64/kernel/nmi.c
arch/x86_64/kernel/pci-dma.c
arch/x86_64/kernel/pci-nommu.c
arch/x86_64/kernel/suspend_asm.S
arch/x86_64/lib/bitops.c [new file with mode: 0644]
arch/x86_64/lib/bitstr.c
arch/x86_64/lib/memmove.c
arch/x86_64/mm/k8topology.c
arch/x86_64/pci/Makefile
arch/x86_64/pci/Makefile-BUS [new file with mode: 0644]
arch/x86_64/pci/k8-bus.c [new file with mode: 0644]
crypto/aes.c
crypto/arc4.c
crypto/blowfish.c
crypto/internal.h
crypto/scatterwalk.c
crypto/tea.c
crypto/wp512.c [new file with mode: 0644]
drivers/acpi/Makefile
drivers/acpi/blacklist.c
drivers/acpi/dispatcher/dsmethod.c
drivers/acpi/dispatcher/dsmthdat.c
drivers/acpi/dispatcher/dsutils.c
drivers/acpi/dispatcher/dswload.c
drivers/acpi/dispatcher/dswstate.c
drivers/acpi/events/evevent.c
drivers/acpi/events/evgpe.c
drivers/acpi/events/evgpeblk.c
drivers/acpi/events/evmisc.c
drivers/acpi/events/evregion.c
drivers/acpi/events/evrgnini.c
drivers/acpi/events/evxfevnt.c
drivers/acpi/events/evxfregn.c
drivers/acpi/executer/exconfig.c
drivers/acpi/executer/exfldio.c
drivers/acpi/executer/exmisc.c
drivers/acpi/executer/exmutex.c
drivers/acpi/executer/exoparg2.c
drivers/acpi/executer/exresolv.c
drivers/acpi/executer/exstore.c
drivers/acpi/hardware/hwgpe.c
drivers/acpi/hardware/hwregs.c
drivers/acpi/hardware/hwsleep.c
drivers/acpi/hardware/hwtimer.c
drivers/acpi/motherboard.c [new file with mode: 0644]
drivers/acpi/namespace/nsaccess.c
drivers/acpi/namespace/nseval.c
drivers/acpi/namespace/nsinit.c
drivers/acpi/namespace/nsparse.c
drivers/acpi/namespace/nsxfeval.c
drivers/acpi/namespace/nsxfname.c
drivers/acpi/numa.c
drivers/acpi/parser/psopcode.c
drivers/acpi/parser/psxface.c
drivers/acpi/resources/rsutils.c
drivers/acpi/resources/rsxface.c
drivers/acpi/sleep/Makefile
drivers/acpi/sleep/proc.c
drivers/acpi/sleep/sleep.h
drivers/acpi/sleep/wakeup.c [new file with mode: 0644]
drivers/acpi/tables/tbxfroot.c
drivers/acpi/utilities/utalloc.c
drivers/acpi/utilities/uteval.c
drivers/acpi/utilities/utglobal.c
drivers/acpi/utilities/utxface.c
drivers/atm/Makefile
drivers/atm/eni.c
drivers/atm/eni.h
drivers/atm/firestream.h
drivers/atm/he.h
drivers/atm/idt77252.h
drivers/atm/nicstar.c
drivers/atm/nicstar.h
drivers/atm/nicstarmac.c
drivers/atm/nicstarmac.h
drivers/block/DAC960.h
drivers/block/amiflop.c
drivers/block/cciss.h
drivers/block/cpqarray.h
drivers/block/nbd.c
drivers/block/sx8.c
drivers/block/ub.c [new file with mode: 0644]
drivers/cdrom/cdu31a.c
drivers/cdrom/mcd.c
drivers/char/agp/agp.h
drivers/char/agp/hp-agp.c
drivers/char/amiserial.c
drivers/char/drm/Makefile
drivers/char/drm/drm_core.h [new file with mode: 0644]
drivers/char/drm/drm_irq.h
drivers/char/drm/drm_memory.h
drivers/char/drm/drm_pciids.h
drivers/char/drm/drm_scatter.h
drivers/char/drm/ffb_context.c
drivers/char/drm/ffb_drv.h
drivers/char/drm/gamma_context.h
drivers/char/drm/gamma_drv.h
drivers/char/drm/i810_drv.c
drivers/char/drm/i810_drv.h
drivers/char/drm/i830_drv.h
drivers/char/drm/i915.h [new file with mode: 0644]
drivers/char/drm/i915_dma.c [new file with mode: 0644]
drivers/char/drm/i915_drm.h [new file with mode: 0644]
drivers/char/drm/i915_drv.c [new file with mode: 0644]
drivers/char/drm/i915_drv.h [new file with mode: 0644]
drivers/char/drm/i915_irq.c [new file with mode: 0644]
drivers/char/drm/i915_mem.c [new file with mode: 0644]
drivers/char/drm/sis.h
drivers/char/drm/sis_drv.c
drivers/char/drm/sis_drv.h
drivers/char/ds1620.c
drivers/char/dsp56k.c
drivers/char/ec3104_keyb.c
drivers/char/efirtc.c
drivers/char/epca.c
drivers/char/ftape/lowlevel/ftape-calibr.c
drivers/char/generic_serial.c
drivers/char/hpet.c
drivers/char/hvc_console.c
drivers/char/hvcs.c
drivers/char/hvsi.c [new file with mode: 0644]
drivers/char/ip2/ip2types.h
drivers/char/ipmi/Kconfig
drivers/char/ipmi/Makefile
drivers/char/ipmi/ipmi_poweroff.c [new file with mode: 0644]
drivers/char/ipmi/ipmi_si_sm.h
drivers/char/isicom.c
drivers/char/mmtimer.c [new file with mode: 0644]
drivers/char/moxa.c
drivers/char/nwflash.c
drivers/char/pcxx.c
drivers/char/rio/linux_compat.h
drivers/char/rio/rio_linux.c
drivers/char/riscom8.c
drivers/char/rocket_int.h
drivers/char/ser_a2232.c
drivers/char/serial167.c
drivers/char/serial_tx3912.c
drivers/char/snsc.c [new file with mode: 0644]
drivers/char/snsc.h [new file with mode: 0644]
drivers/char/specialix.c
drivers/char/sx.c
drivers/char/synclink.c
drivers/char/viocons.c
drivers/char/vme_scc.c
drivers/char/watchdog/ixp4xx_wdt.c
drivers/char/watchdog/mpc8xx_wdt.c [new file with mode: 0644]
drivers/char/watchdog/pcwd.c
drivers/char/watchdog/wdt285.c
drivers/char/watchdog/wdt977.c
drivers/cpufreq/Kconfig
drivers/cpufreq/Makefile
drivers/cpufreq/cpufreq_ondemand.c [new file with mode: 0644]
drivers/cpufreq/proc_intf.c
drivers/fc4/soc.h
drivers/fc4/socal.c
drivers/fc4/socal.h
drivers/i2c/Makefile
drivers/i2c/algos/Kconfig
drivers/i2c/algos/Makefile
drivers/i2c/algos/i2c-algo-ite.c
drivers/i2c/algos/i2c-algo-pca.c [new file with mode: 0644]
drivers/i2c/algos/i2c-algo-pca.h [new file with mode: 0644]
drivers/i2c/algos/i2c-algo-pcf.c
drivers/i2c/busses/i2c-hydra.c
drivers/i2c/busses/i2c-i810.c
drivers/i2c/busses/i2c-ite.c
drivers/i2c/busses/i2c-ixp2000.c [new file with mode: 0644]
drivers/i2c/busses/i2c-mpc.c [new file with mode: 0644]
drivers/i2c/busses/i2c-pca-isa.c [new file with mode: 0644]
drivers/i2c/busses/i2c-prosavage.c
drivers/i2c/busses/i2c-savage4.c
drivers/i2c/chips/adm1025.c
drivers/i2c/chips/ds1621.c
drivers/i2c/chips/isp1301_omap.c [new file with mode: 0644]
drivers/i2c/chips/pcf8591.c
drivers/i2c/chips/rtc8564.c
drivers/i2c/chips/smsc47m1.c [new file with mode: 0644]
drivers/i2c/i2c-sensor-detect.c [new file with mode: 0644]
drivers/i2c/i2c-sensor-vid.c [new file with mode: 0644]
drivers/ide/arm/Makefile
drivers/ide/arm/bast-ide.c [new file with mode: 0644]
drivers/ide/arm/icside.c
drivers/ide/ide-lib.c
drivers/ide/legacy/Makefile
drivers/ide/legacy/qd65xx.h
drivers/ide/pci/alim15x3.c
drivers/ide/pci/cmd640.c
drivers/ide/pci/cy82c693.c
drivers/ide/pci/hpt34x.c
drivers/ide/ppc/pmac.c
drivers/ieee1394/eth1394.h
drivers/ieee1394/ohci1394.h
drivers/input/gameport/cs461x.c
drivers/input/gameport/emu10k1-gp.c
drivers/input/gameport/fm801-gp.c
drivers/input/joystick/Kconfig
drivers/input/joystick/gamecon.c
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce-serio.c
drivers/input/joystick/iforce/iforce.h
drivers/input/joystick/magellan.c
drivers/input/joystick/spaceball.c
drivers/input/joystick/spaceorb.c
drivers/input/joystick/stinger.c
drivers/input/joystick/tmdc.c
drivers/input/joystick/twidjoy.c
drivers/input/joystick/warrior.c
drivers/input/keyboard/lkkbd.c
drivers/input/keyboard/newtonkbd.c
drivers/input/keyboard/sunkbd.c
drivers/input/keyboard/xtkbd.c
drivers/input/mouse/logips2pp.c
drivers/input/mouse/pc110pad.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse.h
drivers/input/mouse/sermouse.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/vsxxxaa.c
drivers/input/serio/Makefile
drivers/input/serio/ct82c710.c
drivers/input/serio/gscps2.c
drivers/input/serio/i8042-sparcio.h
drivers/input/serio/i8042.h
drivers/input/serio/maceps2.c
drivers/input/serio/parkbd.c
drivers/input/serio/pcips2.c
drivers/input/serio/q40kbd.c
drivers/input/serio/rpckbd.c
drivers/input/serio/serio.c
drivers/input/serio/serio_raw.c [new file with mode: 0644]
drivers/input/touchscreen/gunze.c
drivers/input/touchscreen/h3600_ts_input.c
drivers/isdn/hardware/avm/b1.c
drivers/isdn/hardware/avm/b1dma.c
drivers/isdn/hardware/avm/c4.c
drivers/isdn/hardware/avm/t1isa.c
drivers/isdn/hardware/eicon/capifunc.h
drivers/isdn/hardware/eicon/debug_if.h
drivers/isdn/hardware/eicon/debuglib.h
drivers/isdn/hardware/eicon/diva_didd.c
drivers/isdn/hardware/eicon/divasync.h
drivers/isdn/hardware/eicon/io.c
drivers/isdn/hardware/eicon/io.h
drivers/isdn/hardware/eicon/maintidi.h
drivers/isdn/hardware/eicon/pc.h
drivers/isdn/hardware/eicon/platform.h
drivers/isdn/hisax/avm_pci.c
drivers/isdn/hisax/bkm_a4t.c
drivers/isdn/hisax/bkm_a8.c
drivers/isdn/hisax/elsa.c
drivers/isdn/hisax/enternow_pci.c
drivers/isdn/hisax/gazel.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/niccy.c
drivers/isdn/hisax/nj_s.c
drivers/isdn/hisax/nj_u.c
drivers/isdn/hisax/sedlbauer.c
drivers/isdn/hisax/telespci.c
drivers/isdn/hisax/w6692.c
drivers/isdn/tpam/tpam_main.c
drivers/macintosh/adbhid.c
drivers/macintosh/ans-lcd.c
drivers/macintosh/macserial.c
drivers/macintosh/therm_windtunnel.c
drivers/macintosh/via-pmu.c
drivers/md/dm-log.c
drivers/md/dm-log.h
drivers/md/dm-raid1.c
drivers/md/dm-stripe.c
drivers/md/linear.c
drivers/md/raid0.c
drivers/md/raid10.c [new file with mode: 0644]
drivers/media/common/saa7146_i2c.c
drivers/media/dvb/bt8xx/bt878.c
drivers/media/dvb/frontends/alps_tdlb7.c
drivers/media/dvb/frontends/dst.c
drivers/media/dvb/frontends/sp887x.c
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/Makefile
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/video/adv7175.c
drivers/media/video/bttv-gpio.c
drivers/media/video/zoran_device.c
drivers/message/fusion/Makefile
drivers/message/i2o/debug.c [new file with mode: 0644]
drivers/message/i2o/device.c [new file with mode: 0644]
drivers/message/i2o/driver.c [new file with mode: 0644]
drivers/message/i2o/exec-osm.c [new file with mode: 0644]
drivers/message/i2o/i2o_block.h [new file with mode: 0644]
drivers/message/i2o/iop.c [new file with mode: 0644]
drivers/message/i2o/pci.c [new file with mode: 0644]
drivers/mmc/Kconfig [new file with mode: 0644]
drivers/mmc/Makefile [new file with mode: 0644]
drivers/mmc/mmc.c [new file with mode: 0644]
drivers/mmc/mmc.h [new file with mode: 0644]
drivers/mmc/mmc_block.c [new file with mode: 0644]
drivers/mmc/mmc_queue.c [new file with mode: 0644]
drivers/mmc/mmc_queue.h [new file with mode: 0644]
drivers/mmc/mmc_sysfs.c [new file with mode: 0644]
drivers/mmc/mmci.c [new file with mode: 0644]
drivers/mmc/mmci.h [new file with mode: 0644]
drivers/mmc/pxamci.c [new file with mode: 0644]
drivers/mmc/pxamci.h [new file with mode: 0644]
drivers/mtd/maps/ixp2000.c [new file with mode: 0644]
drivers/mtd/maps/ixp4xx.c
drivers/net/8139cp.c
drivers/net/8390.c
drivers/net/amd8111e.c
drivers/net/arcnet/arc-rimi.c
drivers/net/bonding/bond_alb.c
drivers/net/cs89x0.h
drivers/net/dl2k.h
drivers/net/gt64240eth.h [new file with mode: 0644]
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/mkiss.c
drivers/net/ibm_emac/ibm_emac.h
drivers/net/ibm_emac/ibm_emac_core.c
drivers/net/ibm_emac/ibm_emac_core.h
drivers/net/ibm_emac/ibm_emac_mal.c
drivers/net/ibmveth.h
drivers/net/ioc3-eth.c
drivers/net/mv643xx_eth.c [new file with mode: 0644]
drivers/net/mv643xx_eth.h [new file with mode: 0644]
drivers/net/myri_sbus.c
drivers/net/myri_sbus.h
drivers/net/sk98lin/skaddr.c
drivers/net/slip.c
drivers/net/smc91x.c
drivers/net/smc91x.h
drivers/net/sunbmac.c
drivers/net/sunbmac.h
drivers/net/sunhme.h
drivers/net/sunlance.c
drivers/net/sunqe.c
drivers/net/sunqe.h
drivers/net/tokenring/olympic.h
drivers/net/via-velocity.c
drivers/net/via-velocity.h
drivers/net/wan/cycx_x25.c
drivers/net/wan/lmc/lmc_debug.c
drivers/net/wan/pc300.h
drivers/net/wan/pc300_drv.c
drivers/net/wan/sdla_chdlc.c
drivers/net/wan/sdla_fr.c
drivers/net/wan/sdladrv.c
drivers/net/wan/sdlamain.c
drivers/net/wireless/airport.c
drivers/net/wireless/hermes.c
drivers/net/wireless/hermes_rid.h
drivers/net/wireless/ieee802_11.h
drivers/net/wireless/orinoco.h
drivers/net/wireless/orinoco_cs.c
drivers/net/wireless/ray_cs.h
drivers/net/wireless/wavelan.c
drivers/oprofile/buffer_sync.h
drivers/oprofile/cpu_buffer.h
drivers/oprofile/oprofile_stats.c
drivers/oprofile/timer_int.c
drivers/parisc/lasi.c
drivers/pci/Makefile
drivers/pci/hotplug/Kconfig
drivers/pci/hotplug/Makefile
drivers/pci/hotplug/acpiphp_ibm.c [new file with mode: 0644]
drivers/pci/remove.c
drivers/pci/setup-bus.c
drivers/pcmcia/au1000_generic.c
drivers/pcmcia/hd64465_ss.c
drivers/pcmcia/pd6729.c
drivers/pcmcia/pxa2xx_base.c
drivers/pcmcia/pxa2xx_lubbock.c
drivers/pcmcia/soc_common.c
drivers/pcmcia/yenta_socket.h
drivers/pnp/interface.c
drivers/pnp/pnpbios/proc.c
drivers/pnp/pnpbios/rsparser.c
drivers/pnp/system.c
drivers/s390/block/dcssblk.c
drivers/s390/char/con3215.c
drivers/s390/char/sclp_tty.c
drivers/s390/char/sclp_vt220.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/ccwgroup.c
drivers/s390/s390mach.h
drivers/s390/scsi/zfcp_fsf.h
drivers/sbus/char/aurora.c
drivers/sbus/char/bbc_envctrl.c
drivers/sbus/char/bbc_i2c.c
drivers/scsi/BusLogic.h
drivers/scsi/NCR5380.c
drivers/scsi/NCR5380.h
drivers/scsi/aha1542.h
drivers/scsi/aic7xxx/Kconfig.aic79xx
drivers/scsi/aic7xxx/Kconfig.aic7xxx
drivers/scsi/aic7xxx/aic79xx_pci.c
drivers/scsi/aic7xxx/aic7xxx_pci.c
drivers/scsi/aic7xxx/aicasm/Makefile
drivers/scsi/ibmvscsi/Makefile [new file with mode: 0644]
drivers/scsi/ibmvscsi/ibmvscsi.c [new file with mode: 0644]
drivers/scsi/ibmvscsi/ibmvscsi.h [new file with mode: 0644]
drivers/scsi/ibmvscsi/iseries_vscsi.c [new file with mode: 0644]
drivers/scsi/ibmvscsi/rpa_vscsi.c [new file with mode: 0644]
drivers/scsi/ibmvscsi/srp.h [new file with mode: 0644]
drivers/scsi/ibmvscsi/viosrp.h [new file with mode: 0644]
drivers/scsi/ipr.c
drivers/scsi/ipr.h
drivers/scsi/megaraid/Kconfig.megaraid [new file with mode: 0644]
drivers/scsi/megaraid/Makefile [new file with mode: 0644]
drivers/scsi/megaraid/mbox_defs.h [new file with mode: 0644]
drivers/scsi/megaraid/mega_common.h [new file with mode: 0644]
drivers/scsi/megaraid/megaraid_ioctl.h [new file with mode: 0644]
drivers/scsi/megaraid/megaraid_mbox.c [new file with mode: 0644]
drivers/scsi/megaraid/megaraid_mbox.h [new file with mode: 0644]
drivers/scsi/megaraid/megaraid_mm.c [new file with mode: 0644]
drivers/scsi/megaraid/megaraid_mm.h [new file with mode: 0644]
drivers/scsi/sata_nv.c
drivers/scsi/sata_sx4.c
drivers/scsi/sym53c8xx_2/sym_defs.h
drivers/scsi/sym53c8xx_2/sym_glue.c
drivers/scsi/sym53c8xx_2/sym_glue.h
drivers/scsi/sym53c8xx_2/sym_hipd.c
drivers/scsi/sym53c8xx_2/sym_hipd.h
drivers/scsi/sym53c8xx_2/sym_misc.c
drivers/scsi/sym53c8xx_2/sym_nvram.c
drivers/serial/68328serial.c
drivers/serial/8250.h
drivers/serial/icom.c [new file with mode: 0644]
drivers/serial/icom.h [new file with mode: 0644]
drivers/serial/mcfserial.c
drivers/serial/s3c2410.c
drivers/serial/serial_cs.c
drivers/serial/sn_console.c
drivers/usb/class/cdc-acm.h
drivers/usb/core/Kconfig
drivers/usb/core/otg_whitelist.h [new file with mode: 0644]
drivers/usb/gadget/Makefile
drivers/usb/gadget/lh7a40x_udc.c [new file with mode: 0644]
drivers/usb/gadget/lh7a40x_udc.h [new file with mode: 0644]
drivers/usb/gadget/net2280.h
drivers/usb/gadget/omap_udc.c [new file with mode: 0644]
drivers/usb/gadget/omap_udc.h [new file with mode: 0644]
drivers/usb/host/Kconfig
drivers/usb/host/hc_sl811.c
drivers/usb/media/sn9c102.h
drivers/usb/media/sn9c102_core.c
drivers/usb/media/sn9c102_pas106b.c
drivers/usb/media/sn9c102_pas202bcb.c [new file with mode: 0644]
drivers/usb/media/sn9c102_sensor.h
drivers/usb/media/sn9c102_tas5110c1b.c
drivers/usb/media/sn9c102_tas5130d1b.c
drivers/usb/misc/phidgetservo.c
drivers/usb/net/catc.c
drivers/usb/serial/io_fw_down.h
drivers/usb/serial/io_fw_down3.h
drivers/usb/serial/io_tables.h
drivers/usb/serial/io_usbvend.h
drivers/usb/storage/datafab.h
drivers/usb/storage/debug.c
drivers/usb/storage/debug.h
drivers/usb/storage/dpcm.c
drivers/usb/storage/dpcm.h
drivers/usb/storage/freecom.c
drivers/usb/storage/freecom.h
drivers/usb/storage/isd200.h
drivers/usb/storage/jumpshot.h
drivers/usb/storage/protocol.c
drivers/usb/storage/protocol.h
drivers/usb/storage/sddr09.h
drivers/usb/storage/sddr55.c
drivers/usb/storage/sddr55.h
drivers/usb/storage/transport.h
drivers/usb/usb-skeleton.c
drivers/video/amba-clcd.c [new file with mode: 0644]
drivers/video/amifb.c
drivers/video/asiliantfb.c
drivers/video/aty/aty128fb.c
drivers/video/bw2.c
drivers/video/cfbcopyarea.c
drivers/video/cfbfillrect.c
drivers/video/cfbimgblt.c
drivers/video/cg14.c
drivers/video/cg3.c
drivers/video/cg6.c
drivers/video/chipsfb.c
drivers/video/clps711xfb.c
drivers/video/controlfb.c
drivers/video/dnfb.c
drivers/video/epson1355fb.c
drivers/video/fbmon.c
drivers/video/ffb.c
drivers/video/fm2fb.c
drivers/video/g364fb.c
drivers/video/gbefb.c
drivers/video/hitfb.c
drivers/video/hpfb.c
drivers/video/i810/i810_dvt.c
drivers/video/i810/i810_main.c
drivers/video/igafb.c
drivers/video/leo.c
drivers/video/macfb.c
drivers/video/matrox/matroxfb_crtc2.h
drivers/video/matrox/matroxfb_misc.c
drivers/video/maxinefb.c
drivers/video/offb.c
drivers/video/p9100.c
drivers/video/platinumfb.c
drivers/video/pmag-ba-fb.c
drivers/video/pmagb-b-fb.c
drivers/video/pvr2fb.c
drivers/video/pxafb.c
drivers/video/riva/nv_driver.c
drivers/video/riva/riva_hw.h
drivers/video/riva/rivafb-i2c.c
drivers/video/sgivwfb.c
drivers/video/stifb.c
drivers/video/tcx.c
drivers/video/tx3912fb.c
drivers/video/valkyriefb.c
drivers/video/vgastate.c
drivers/w1/Kconfig
drivers/w1/Makefile
drivers/w1/ds_w1_bridge.c [new file with mode: 0644]
drivers/w1/dscore.c [new file with mode: 0644]
drivers/w1/dscore.h [new file with mode: 0644]
drivers/w1/matrox_w1.c
drivers/w1/w1.c
drivers/w1/w1.h
drivers/w1/w1_family.c
drivers/w1/w1_family.h
drivers/w1/w1_int.c
drivers/w1/w1_io.c
drivers/w1/w1_io.h
drivers/w1/w1_netlink.h
drivers/w1/w1_smem.c [new file with mode: 0644]
drivers/w1/w1_therm.c
drivers/zorro/Makefile
fs/adfs/adfs.h
fs/adfs/dir.c
fs/adfs/dir_f.c
fs/adfs/dir_fplus.h
fs/adfs/inode.c
fs/adfs/map.c
fs/adfs/super.c
fs/affs/namei.c
fs/afs/inode.c
fs/afs/main.c
fs/afs/vlclient.h
fs/afs/vnode.c
fs/afs/volume.h
fs/bfs/inode.c
fs/cifs/cifsencrypt.c
fs/cifs/netmisc.c
fs/cifs/ntlmssp.h
fs/coda/coda_linux.c
fs/coda/file.c
fs/coda/upcall.c
fs/efs/inode.c
fs/efs/super.c
fs/ext2/acl.h
fs/ext2/dir.c
fs/ext2/ext2.h
fs/ext2/xattr.h
fs/ext3/acl.h
fs/ext3/fsync.c
fs/ext3/xattr.h
fs/fat/cache.c
fs/fat/dir.c
fs/fat/misc.c
fs/freevxfs/vxfs_extern.h
fs/freevxfs/vxfs_inode.c
fs/freevxfs/vxfs_super.c
fs/hfs/bfind.c
fs/hfs/bitmap.c
fs/hfs/bnode.c
fs/hfs/brec.c
fs/hfs/btree.c
fs/hfs/btree.h
fs/hfs/extent.c
fs/hfs/hfs.h
fs/hfs/hfs_fs.h
fs/hfs/mdb.c
fs/hfs/part_tbl.c
fs/hfsplus/bfind.c
fs/hfsplus/bitmap.c
fs/hfsplus/btree.c
fs/hfsplus/extents.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/hfsplus_raw.h
fs/hfsplus/part_tbl.c
fs/hfsplus/super.c
fs/hostfs/Makefile
fs/hostfs/hostfs.h
fs/hppfs/Makefile
fs/hppfs/hppfs_kern.c
fs/jbd/recovery.c
fs/jfs/inode.c
fs/jfs/jfs_inode.c
fs/jfs/resize.c
fs/libfs.c
fs/lockd/clntproc.c
fs/lockd/svc.c
fs/lockd/svc4proc.c
fs/lockd/svcproc.c
fs/lockd/svcsubs.c
fs/minix/itree_common.c
fs/ncpfs/sock.c
fs/ncpfs/symlink.c
fs/nfs/Makefile
fs/nfs/callback.c [new file with mode: 0644]
fs/nfs/callback.h [new file with mode: 0644]
fs/nfs/callback_proc.c [new file with mode: 0644]
fs/nfs/callback_xdr.c [new file with mode: 0644]
fs/nfs/delegation.c [new file with mode: 0644]
fs/nfs/delegation.h [new file with mode: 0644]
fs/nfs/mount_clnt.c
fs/nfs/nfs3proc.c
fs/nfs/pagelist.c
fs/nfsd/Makefile
fs/nfsd/lockd.c
fs/nfsd/nfs3proc.c
fs/nfsd/nfs4acl.c [new file with mode: 0644]
fs/nfsd/nfssvc.c
fs/nls/nls_cp932.c
fs/ntfs/bitmap.c [new file with mode: 0644]
fs/ntfs/bitmap.h [new file with mode: 0644]
fs/ntfs/collate.h
fs/ntfs/index.c
fs/ntfs/index.h
fs/ntfs/lcnalloc.c [new file with mode: 0644]
fs/ntfs/lcnalloc.h [new file with mode: 0644]
fs/ntfs/quota.c
fs/openpromfs/inode.c
fs/partitions/acorn.c
fs/partitions/amiga.c
fs/partitions/atari.h
fs/partitions/efi.h
fs/partitions/ldm.c
fs/partitions/ldm.h
fs/partitions/mac.h
fs/partitions/osf.c
fs/partitions/sgi.c
fs/partitions/sun.c
fs/proc/task_nommu.c
fs/quota_v1.c
fs/reiserfs/xattr_acl.c
fs/romfs/inode.c
fs/sysv/balloc.c
fs/sysv/ialloc.c
fs/sysv/super.c
fs/sysv/sysv.h
fs/udf/balloc.c
fs/udf/directory.c
fs/udf/ecma_167.h
fs/udf/fsync.c
fs/udf/inode.c
fs/udf/osta_udf.h
fs/udf/partition.c
fs/udf/truncate.c
fs/udf/udfdecl.h
fs/udf/udfend.h
fs/udf/udftime.c
fs/ufs/dir.c
fs/ufs/inode.c
fs/ufs/super.c
fs/ufs/swab.h
fs/ufs/truncate.c
fs/ufs/util.h
fs/umsdos/inode.c
fs/vfat/namei.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_buf.h
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_globals.c
fs/xfs/linux-2.6/xfs_ioctl32.c [new file with mode: 0644]
fs/xfs/linux-2.6/xfs_ioctl32.h [new file with mode: 0644]
fs/xfs/linux-2.6/xfs_iops.h
fs/xfs/linux-2.6/xfs_linux.h
fs/xfs/linux-2.6/xfs_lrw.c
fs/xfs/linux-2.6/xfs_lrw.h
fs/xfs/linux-2.6/xfs_stats.c
fs/xfs/linux-2.6/xfs_sysctl.c
fs/xfs/linux-2.6/xfs_sysctl.h
fs/xfs/linux-2.6/xfs_vfs.c
fs/xfs/linux-2.6/xfs_vfs.h
fs/xfs/linux-2.6/xfs_vnode.h
fs/xfs/quota/xfs_dquot.c
fs/xfs/quota/xfs_dquot.h
fs/xfs/quota/xfs_qm.h
fs/xfs/quota/xfs_qm_stats.c
fs/xfs/quota/xfs_trans_dquot.c
fs/xfs/support/ktrace.c
fs/xfs/support/move.c
fs/xfs/xfs_alloc.c
fs/xfs/xfs_alloc_btree.c
fs/xfs/xfs_attr_leaf.h
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_dfrag.h
fs/xfs/xfs_dir2_trace.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_iomap.h
fs/xfs/xfs_log_priv.h
fs/xfs/xfs_quota.h
fs/xfs/xfs_sb.h
fs/xfs/xfs_types.h
include/acpi/acconfig.h
include/acpi/acdebug.h
include/acpi/acdisasm.h
include/acpi/acdispat.h
include/acpi/acevents.h
include/acpi/acexcep.h
include/acpi/acglobal.h
include/acpi/achware.h
include/acpi/acinterp.h
include/acpi/aclocal.h
include/acpi/acmacros.h
include/acpi/acnamesp.h
include/acpi/acobject.h
include/acpi/acparser.h
include/acpi/acpi_bus.h
include/acpi/acpixf.h
include/acpi/acstruct.h
include/acpi/actbl.h
include/acpi/actypes.h
include/acpi/platform/acenv.h
include/asm-alpha/a.out.h
include/asm-alpha/bug.h
include/asm-alpha/cache.h
include/asm-alpha/compiler.h
include/asm-alpha/core_apecs.h
include/asm-alpha/core_cia.h
include/asm-alpha/core_irongate.h
include/asm-alpha/core_marvel.h
include/asm-alpha/core_t2.h
include/asm-alpha/core_titan.h
include/asm-alpha/core_tsunami.h
include/asm-alpha/core_wildfire.h
include/asm-alpha/dma-mapping.h
include/asm-alpha/hardirq.h
include/asm-alpha/io_trivial.h [new file with mode: 0644]
include/asm-alpha/jensen.h
include/asm-alpha/machvec.h
include/asm-alpha/mmu_context.h
include/asm-alpha/pci.h
include/asm-alpha/ptrace.h
include/asm-alpha/socket.h
include/asm-alpha/sysinfo.h
include/asm-alpha/thread_info.h
include/asm-alpha/tlbflush.h
include/asm-alpha/vga.h
include/asm-arm/apm.h
include/asm-arm/arch-cl7500/uncompress.h
include/asm-arm/arch-clps711x/uncompress.h
include/asm-arm/arch-ebsa110/param.h
include/asm-arm/arch-ebsa285/uncompress.h
include/asm-arm/arch-epxa10db/uncompress.h
include/asm-arm/arch-h720x/boards.h [new file with mode: 0644]
include/asm-arm/arch-h720x/dma.h [new file with mode: 0644]
include/asm-arm/arch-h720x/h7201-regs.h [new file with mode: 0644]
include/asm-arm/arch-h720x/h7202-regs.h [new file with mode: 0644]
include/asm-arm/arch-h720x/hardware.h [new file with mode: 0644]
include/asm-arm/arch-h720x/io.h [new file with mode: 0644]
include/asm-arm/arch-h720x/irq.h [new file with mode: 0644]
include/asm-arm/arch-h720x/irqs.h [new file with mode: 0644]
include/asm-arm/arch-h720x/memory.h [new file with mode: 0644]
include/asm-arm/arch-h720x/param.h [new file with mode: 0644]
include/asm-arm/arch-h720x/serial.h [new file with mode: 0644]
include/asm-arm/arch-h720x/system.h [new file with mode: 0644]
include/asm-arm/arch-h720x/timex.h [new file with mode: 0644]
include/asm-arm/arch-h720x/uncompress.h [new file with mode: 0644]
include/asm-arm/arch-h720x/vmalloc.h [new file with mode: 0644]
include/asm-arm/arch-imx/dma.h [new file with mode: 0644]
include/asm-arm/arch-imx/hardware.h [new file with mode: 0644]
include/asm-arm/arch-imx/imx-regs.h [new file with mode: 0644]
include/asm-arm/arch-imx/io.h [new file with mode: 0644]
include/asm-arm/arch-imx/irq.h [new file with mode: 0644]
include/asm-arm/arch-imx/irqs.h [new file with mode: 0644]
include/asm-arm/arch-imx/memory.h [new file with mode: 0644]
include/asm-arm/arch-imx/mx1ads.h [new file with mode: 0644]
include/asm-arm/arch-imx/param.h [new file with mode: 0644]
include/asm-arm/arch-imx/serial.h [new file with mode: 0644]
include/asm-arm/arch-imx/system.h [new file with mode: 0644]
include/asm-arm/arch-imx/timex.h [new file with mode: 0644]
include/asm-arm/arch-imx/uncompress.h [new file with mode: 0644]
include/asm-arm/arch-imx/vmalloc.h [new file with mode: 0644]
include/asm-arm/arch-integrator/uncompress.h
include/asm-arm/arch-iop3xx/dma.h
include/asm-arm/arch-iop3xx/hardware.h
include/asm-arm/arch-iop3xx/iop321-irqs.h
include/asm-arm/arch-iop3xx/iop321.h
include/asm-arm/arch-iop3xx/iop331-irqs.h [new file with mode: 0644]
include/asm-arm/arch-iop3xx/iop331.h [new file with mode: 0644]
include/asm-arm/arch-iop3xx/iq31244.h [new file with mode: 0644]
include/asm-arm/arch-iop3xx/iq80321.h
include/asm-arm/arch-iop3xx/iq80331.h [new file with mode: 0644]
include/asm-arm/arch-iop3xx/irqs.h
include/asm-arm/arch-iop3xx/param.h
include/asm-arm/arch-iop3xx/serial.h
include/asm-arm/arch-iop3xx/system.h
include/asm-arm/arch-iop3xx/timex.h
include/asm-arm/arch-iop3xx/uncompress.h
include/asm-arm/arch-iop3xx/vmalloc.h
include/asm-arm/arch-ixp2000/dma.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/enp2611.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/gpio.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/hardware.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/io.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/irq.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/irqs.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/ixdp2x00.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/ixdp2x01.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/ixp2000-regs.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/memory.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/param.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/platform.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/serial.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/system.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/timex.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/uncompress.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/vmalloc.h [new file with mode: 0644]
include/asm-arm/arch-ixp4xx/io.h
include/asm-arm/arch-ixp4xx/uncompress.h
include/asm-arm/arch-l7200/param.h
include/asm-arm/arch-l7200/uncompress.h
include/asm-arm/arch-lh7a40x/uncompress.h
include/asm-arm/arch-omap/board-h2.h
include/asm-arm/arch-omap/board-h3.h
include/asm-arm/arch-omap/board-innovator.h
include/asm-arm/arch-omap/board-perseus2.h
include/asm-arm/arch-omap/board.h
include/asm-arm/arch-omap/fpga.h
include/asm-arm/arch-omap/mcbsp.h [new file with mode: 0644]
include/asm-arm/arch-omap/omap1510.h
include/asm-arm/arch-omap/omap1610.h
include/asm-arm/arch-omap/omap5912.h
include/asm-arm/arch-omap/omap730.h
include/asm-arm/arch-omap/tps65010.h [new file with mode: 0644]
include/asm-arm/arch-omap/usb.h [new file with mode: 0644]
include/asm-arm/arch-pxa/mmc.h [new file with mode: 0644]
include/asm-arm/arch-pxa/serial.h
include/asm-arm/arch-pxa/system.h
include/asm-arm/arch-pxa/uncompress.h
include/asm-arm/arch-rpc/io.h
include/asm-arm/arch-s3c2410/bast-cpld.h
include/asm-arm/arch-s3c2410/bast-irq.h
include/asm-arm/arch-s3c2410/dma.h
include/asm-arm/arch-s3c2410/hardware.h
include/asm-arm/arch-s3c2410/nand.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/param.h
include/asm-arm/arch-s3c2410/regs-clock.h
include/asm-arm/arch-s3c2410/regs-dsc.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-gpio.h
include/asm-arm/arch-s3c2410/regs-gpioj.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-iic.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-mem.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-nand.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-sdi.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-spi.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-timer.h
include/asm-arm/arch-s3c2410/regs-udc.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/uncompress.h
include/asm-arm/arch-s3c2410/usb-control.h [new file with mode: 0644]
include/asm-arm/arch-sa1100/uncompress.h
include/asm-arm/arch-shark/uncompress.h
include/asm-arm/bitops.h
include/asm-arm/bug.h
include/asm-arm/elf.h
include/asm-arm/hardirq.h
include/asm-arm/hardware.h
include/asm-arm/hardware/amba_clcd.h [new file with mode: 0644]
include/asm-arm/hardware/clock.h
include/asm-arm/io.h
include/asm-arm/mach/mmc.h [new file with mode: 0644]
include/asm-arm/mach/pci.h
include/asm-arm/mach/time.h
include/asm-arm/param.h
include/asm-arm/ptrace.h
include/asm-arm/semaphore.h
include/asm-arm/socket.h
include/asm-arm26/bug.h
include/asm-arm26/hardirq.h
include/asm-arm26/ptrace.h
include/asm-arm26/semaphore.h
include/asm-arm26/socket.h
include/asm-cris/arch-v10/ptrace.h
include/asm-cris/bug.h
include/asm-cris/hardirq.h
include/asm-cris/socket.h
include/asm-generic/bug.h [new file with mode: 0644]
include/asm-generic/ide_iops.h
include/asm-generic/iomap.h [new file with mode: 0644]
include/asm-generic/local.h
include/asm-generic/uaccess.h [new file with mode: 0644]
include/asm-h8300/bug.h
include/asm-h8300/ptrace.h
include/asm-h8300/socket.h
include/asm-i386/bug.h
include/asm-i386/hardirq.h
include/asm-i386/io.h
include/asm-i386/kdebug.h [new file with mode: 0644]
include/asm-i386/kprobes.h [new file with mode: 0644]
include/asm-i386/linkage.h
include/asm-i386/mach-bigsmp/mach_ipi.h
include/asm-i386/mach-default/do_timer.h
include/asm-i386/mach-default/mach_ipi.h
include/asm-i386/mach-numaq/mach_ipi.h
include/asm-i386/mach-summit/mach_ipi.h
include/asm-i386/mach-visws/do_timer.h
include/asm-i386/mtrr.h
include/asm-i386/ptrace.h
include/asm-i386/rwlock.h
include/asm-i386/semaphore.h
include/asm-i386/socket.h
include/asm-i386/topology.h
include/asm-ia64/bug.h
include/asm-ia64/compat.h
include/asm-ia64/elf.h
include/asm-ia64/hardirq.h
include/asm-ia64/hw_irq.h
include/asm-ia64/io.h
include/asm-ia64/mca.h
include/asm-ia64/mca_asm.h
include/asm-ia64/mmu_context.h
include/asm-ia64/mmzone.h
include/asm-ia64/numa.h
include/asm-ia64/ptrace.h
include/asm-ia64/sal.h
include/asm-ia64/semaphore.h
include/asm-ia64/siginfo.h
include/asm-ia64/sn/sn2/shubio.h
include/asm-ia64/sn/sn2/sn_hwperf.h [new file with mode: 0644]
include/asm-ia64/sn/xtalk/xtalk.h
include/asm-ia64/sn/xtalk/xwidget.h
include/asm-ia64/socket.h
include/asm-ia64/tlbflush.h
include/asm-m32r/a.out.h [new file with mode: 0644]
include/asm-m32r/addrspace.h [new file with mode: 0644]
include/asm-m32r/assembler.h [new file with mode: 0644]
include/asm-m32r/atomic.h [new file with mode: 0644]
include/asm-m32r/bitops.h [new file with mode: 0644]
include/asm-m32r/bug.h [new file with mode: 0644]
include/asm-m32r/bugs.h [new file with mode: 0644]
include/asm-m32r/byteorder.h [new file with mode: 0644]
include/asm-m32r/cache.h [new file with mode: 0644]
include/asm-m32r/cachectl.h [new file with mode: 0644]
include/asm-m32r/cacheflush.h [new file with mode: 0644]
include/asm-m32r/checksum.h [new file with mode: 0644]
include/asm-m32r/current.h [new file with mode: 0644]
include/asm-m32r/delay.h [new file with mode: 0644]
include/asm-m32r/div64.h [new file with mode: 0644]
include/asm-m32r/dma-mapping.h [new file with mode: 0644]
include/asm-m32r/dma.h [new file with mode: 0644]
include/asm-m32r/elf.h [new file with mode: 0644]
include/asm-m32r/errno.h [new file with mode: 0644]
include/asm-m32r/fcntl.h [new file with mode: 0644]
include/asm-m32r/flat.h [new file with mode: 0644]
include/asm-m32r/hardirq.h [new file with mode: 0644]
include/asm-m32r/hdreg.h [new file with mode: 0644]
include/asm-m32r/hw_irq.h [new file with mode: 0644]
include/asm-m32r/ide.h [new file with mode: 0644]
include/asm-m32r/io.h [new file with mode: 0644]
include/asm-m32r/ioctl.h [new file with mode: 0644]
include/asm-m32r/ioctls.h [new file with mode: 0644]
include/asm-m32r/ipc.h [new file with mode: 0644]
include/asm-m32r/ipcbuf.h [new file with mode: 0644]
include/asm-m32r/irq.h [new file with mode: 0644]
include/asm-m32r/kmap_types.h [new file with mode: 0644]
include/asm-m32r/linkage.h [new file with mode: 0644]
include/asm-m32r/local.h [new file with mode: 0644]
include/asm-m32r/m32102.h [new file with mode: 0644]
include/asm-m32r/m32102peri.h [new file with mode: 0644]
include/asm-m32r/m32700ut/m32700ut_lan.h [new file with mode: 0644]
include/asm-m32r/m32700ut/m32700ut_lcd.h [new file with mode: 0644]
include/asm-m32r/m32700ut/m32700ut_pld.h [new file with mode: 0644]
include/asm-m32r/m32r.h [new file with mode: 0644]
include/asm-m32r/m32r_mp_fpga.h [new file with mode: 0644]
include/asm-m32r/mappi2/mappi2_pld.h [new file with mode: 0644]
include/asm-m32r/mc146818rtc.h [new file with mode: 0644]
include/asm-m32r/mman.h [new file with mode: 0644]
include/asm-m32r/mmu.h [new file with mode: 0644]
include/asm-m32r/mmu_context.h [new file with mode: 0644]
include/asm-m32r/mmzone.h [new file with mode: 0644]
include/asm-m32r/module.h [new file with mode: 0644]
include/asm-m32r/msgbuf.h [new file with mode: 0644]
include/asm-m32r/namei.h [new file with mode: 0644]
include/asm-m32r/numnodes.h [new file with mode: 0644]
include/asm-m32r/opsput/opsput_lan.h [new file with mode: 0644]
include/asm-m32r/opsput/opsput_lcd.h [new file with mode: 0644]
include/asm-m32r/opsput/opsput_pld.h [new file with mode: 0644]
include/asm-m32r/page.h [new file with mode: 0644]
include/asm-m32r/param.h [new file with mode: 0644]
include/asm-m32r/pci.h [new file with mode: 0644]
include/asm-m32r/percpu.h [new file with mode: 0644]
include/asm-m32r/pgalloc.h [new file with mode: 0644]
include/asm-m32r/pgtable-2level.h [new file with mode: 0644]
include/asm-m32r/pgtable.h [new file with mode: 0644]
include/asm-m32r/poll.h [new file with mode: 0644]
include/asm-m32r/posix_types.h [new file with mode: 0644]
include/asm-m32r/processor.h [new file with mode: 0644]
include/asm-m32r/ptrace.h [new file with mode: 0644]
include/asm-m32r/resource.h [new file with mode: 0644]
include/asm-m32r/rtc.h [new file with mode: 0644]
include/asm-m32r/scatterlist.h [new file with mode: 0644]
include/asm-m32r/sections.h [new file with mode: 0644]
include/asm-m32r/segment.h [new file with mode: 0644]
include/asm-m32r/semaphore.h [new file with mode: 0644]
include/asm-m32r/sembuf.h [new file with mode: 0644]
include/asm-m32r/serial.h [new file with mode: 0644]
include/asm-m32r/setup.h [new file with mode: 0644]
include/asm-m32r/shmbuf.h [new file with mode: 0644]
include/asm-m32r/shmparam.h [new file with mode: 0644]
include/asm-m32r/sigcontext.h [new file with mode: 0644]
include/asm-m32r/siginfo.h [new file with mode: 0644]
include/asm-m32r/signal.h [new file with mode: 0644]
include/asm-m32r/smp.h [new file with mode: 0644]
include/asm-m32r/socket.h [new file with mode: 0644]
include/asm-m32r/sockios.h [new file with mode: 0644]
include/asm-m32r/spinlock.h [new file with mode: 0644]
include/asm-m32r/stat.h [new file with mode: 0644]
include/asm-m32r/statfs.h [new file with mode: 0644]
include/asm-m32r/string.h [new file with mode: 0644]
include/asm-m32r/syscall.h [new file with mode: 0644]
include/asm-m32r/system.h [new file with mode: 0644]
include/asm-m32r/termbits.h [new file with mode: 0644]
include/asm-m32r/termios.h [new file with mode: 0644]
include/asm-m32r/thread_info.h [new file with mode: 0644]
include/asm-m32r/timex.h [new file with mode: 0644]
include/asm-m32r/tlb.h [new file with mode: 0644]
include/asm-m32r/tlbflush.h [new file with mode: 0644]
include/asm-m32r/topology.h [new file with mode: 0644]
include/asm-m32r/types.h [new file with mode: 0644]
include/asm-m32r/uaccess.h [new file with mode: 0644]
include/asm-m32r/ucontext.h [new file with mode: 0644]
include/asm-m32r/unaligned.h [new file with mode: 0644]
include/asm-m32r/unistd.h [new file with mode: 0644]
include/asm-m32r/user.h [new file with mode: 0644]
include/asm-m32r/vga.h [new file with mode: 0644]
include/asm-m32r/xor.h [new file with mode: 0644]
include/asm-m68k/bug.h
include/asm-m68k/hardirq.h
include/asm-m68k/ptrace.h
include/asm-m68k/semaphore.h
include/asm-m68k/socket.h
include/asm-m68k/system.h
include/asm-m68knommu/bug.h
include/asm-m68knommu/hardirq.h
include/asm-m68knommu/ptrace.h
include/asm-m68knommu/semaphore.h
include/asm-mips/bug.h
include/asm-mips/dma-mapping.h
include/asm-mips/hardirq.h
include/asm-mips/siginfo.h
include/asm-mips/socket.h
include/asm-parisc/bug.h
include/asm-parisc/hardirq.h
include/asm-parisc/ptrace.h
include/asm-parisc/semaphore.h
include/asm-parisc/socket.h
include/asm-ppc/8253pit.h [new file with mode: 0644]
include/asm-ppc/bug.h
include/asm-ppc/checksum.h
include/asm-ppc/fsl_ocp.h
include/asm-ppc/hardirq.h
include/asm-ppc/mpc52xx.h
include/asm-ppc/open_pic.h
include/asm-ppc/residual.h
include/asm-ppc/semaphore.h
include/asm-ppc/socket.h
include/asm-ppc/thread_info.h
include/asm-ppc64/8253pit.h [new file with mode: 0644]
include/asm-ppc64/btext.h
include/asm-ppc64/bug.h
include/asm-ppc64/checksum.h
include/asm-ppc64/dma-mapping.h
include/asm-ppc64/hvcall.h
include/asm-ppc64/hvconsole.h
include/asm-ppc64/hvcserver.h
include/asm-ppc64/iSeries/iSeries_io.h
include/asm-ppc64/lmb.h
include/asm-ppc64/memory.h
include/asm-ppc64/pci-bridge.h
include/asm-ppc64/plpar_wrappers.h [new file with mode: 0644]
include/asm-ppc64/semaphore.h
include/asm-ppc64/socket.h
include/asm-ppc64/tlb.h
include/asm-s390/bug.h
include/asm-s390/dma-mapping.h
include/asm-s390/hardirq.h
include/asm-s390/idals.h
include/asm-s390/irq.h
include/asm-s390/lowcore.h
include/asm-s390/ptrace.h
include/asm-s390/socket.h
include/asm-s390/timer.h
include/asm-sh/bug.h
include/asm-sh/cacheflush.h
include/asm-sh/hardirq.h
include/asm-sh/ptrace.h
include/asm-sh/semaphore.h
include/asm-sh/socket.h
include/asm-sh64/cacheflush.h
include/asm-sh64/dma-mapping.h
include/asm-sh64/ptrace.h
include/asm-sh64/uaccess.h
include/asm-sparc/dma-mapping.h
include/asm-sparc/ptrace.h
include/asm-sparc/sigcontext.h
include/asm-sparc/socket.h
include/asm-sparc/vaddrs.h
include/asm-sparc64/delay.h
include/asm-sparc64/dma.h
include/asm-sparc64/ebus.h
include/asm-sparc64/elf.h
include/asm-sparc64/kdebug.h
include/asm-sparc64/kprobes.h [new file with mode: 0644]
include/asm-sparc64/parport.h
include/asm-sparc64/pbm.h
include/asm-sparc64/ptrace.h
include/asm-sparc64/sigcontext.h
include/asm-sparc64/socket.h
include/asm-sparc64/string.h
include/asm-sparc64/ttable.h
include/asm-sparc64/vga.h
include/asm-um/module-i386.h [new file with mode: 0644]
include/asm-um/ptrace-generic.h
include/asm-v850/bug.h
include/asm-v850/hardirq.h
include/asm-v850/ptrace.h
include/asm-v850/socket.h
include/asm-x86_64/apic.h
include/asm-x86_64/apicdef.h
include/asm-x86_64/atomic.h
include/asm-x86_64/bug.h
include/asm-x86_64/cpufeature.h
include/asm-x86_64/desc.h
include/asm-x86_64/dma-mapping.h
include/asm-x86_64/elf.h
include/asm-x86_64/hardirq.h
include/asm-x86_64/mtrr.h
include/asm-x86_64/pci.h
include/asm-x86_64/proto.h
include/asm-x86_64/socket.h
include/asm-x86_64/swiotlb.h [new file with mode: 0644]
include/asm-x86_64/system.h
include/linux/adfs_fs.h
include/linux/adfs_fs_i.h
include/linux/adfs_fs_sb.h
include/linux/affs_hardblocks.h
include/linux/amigaffs.h
include/linux/arcdevice.h
include/linux/atalk.h
include/linux/byteorder/big_endian.h
include/linux/byteorder/generic.h
include/linux/byteorder/little_endian.h
include/linux/coda.h
include/linux/cyclades.h
include/linux/dqblk_xfs.h
include/linux/efs_dir.h
include/linux/efs_fs.h
include/linux/efs_fs_i.h
include/linux/efs_fs_sb.h
include/linux/efs_vh.h
include/linux/err.h
include/linux/gen_stats.h [new file with mode: 0644]
include/linux/genhd.h
include/linux/hardirq.h [new file with mode: 0644]
include/linux/hdreg.h
include/linux/hiddev.h
include/linux/highuid.h
include/linux/hpet.h
include/linux/i2c-algo-pca.h [new file with mode: 0644]
include/linux/i2c-vid.h
include/linux/if_ether.h
include/linux/if_fddi.h
include/linux/if_tr.h
include/linux/if_vlan.h
include/linux/input.h
include/linux/ioctl32.h
include/linux/ip6_tunnel.h
include/linux/ipv6.h
include/linux/isicom.h
include/linux/kmod.h
include/linux/kprobes.h [new file with mode: 0644]
include/linux/kref.h
include/linux/linkage.h
include/linux/list.h
include/linux/lockd/bind.h
include/linux/lockd/lockd.h
include/linux/mempolicy.h
include/linux/mii.h
include/linux/mman.h
include/linux/mmc/card.h [new file with mode: 0644]
include/linux/mmc/host.h [new file with mode: 0644]
include/linux/mmc/mmc.h [new file with mode: 0644]
include/linux/mmc/protocol.h [new file with mode: 0644]
include/linux/mmtimer.h [new file with mode: 0644]
include/linux/msdos_fs.h
include/linux/mv643xx.h [new file with mode: 0644]
include/linux/ncp.h
include/linux/ncp_fs_i.h
include/linux/ncp_no.h
include/linux/netfilter_bridge/ebt_802_3.h
include/linux/netfilter_ipv4/ip_conntrack_core.h
include/linux/netfilter_ipv4/ip_conntrack_ftp.h
include/linux/netfilter_ipv4/ip_conntrack_irc.h
include/linux/netfilter_ipv4/ip_conntrack_protocol.h
include/linux/netfilter_ipv4/ip_conntrack_sctp.h [new file with mode: 0644]
include/linux/netfilter_ipv4/ip_conntrack_tcp.h
include/linux/netfilter_ipv4/ip_nat.h
include/linux/netfilter_ipv4/ip_nat_core.h
include/linux/netfilter_ipv4/ip_nat_helper.h
include/linux/netfilter_ipv4/ip_nat_protocol.h
include/linux/netfilter_ipv4/ipt_comment.h [new file with mode: 0644]
include/linux/netfilter_ipv4/ipt_sctp.h [new file with mode: 0644]
include/linux/netfilter_ipv6.h
include/linux/netfilter_ipv6/ip6t_physdev.h [new file with mode: 0644]
include/linux/nfs.h
include/linux/nfs4.h
include/linux/nfs4_acl.h [new file with mode: 0644]
include/linux/nfs_fs_i.h
include/linux/nfs_fs_sb.h
include/linux/nfs_page.h
include/linux/nfs_xdr.h
include/linux/nls.h
include/linux/node.h
include/linux/notifier.h
include/linux/percpu.h
include/linux/pfkeyv2.h
include/linux/pid.h
include/linux/profile.h
include/linux/raid/md.h
include/linux/raid/md_k.h
include/linux/raid/raid10.h [new file with mode: 0644]
include/linux/ramfs.h [new file with mode: 0644]
include/linux/rbtree.h
include/linux/romfs_fs.h
include/linux/stddef.h
include/linux/sunrpc/auth_gss.h
include/linux/sunrpc/gss_spkm3.h [new file with mode: 0644]
include/linux/sunrpc/sched.h
include/linux/sunrpc/svc.h
include/linux/sysv_fs.h
include/linux/tc_act/tc_gact.h [new file with mode: 0644]
include/linux/timex.h
include/linux/topology.h
include/linux/udf_fs_i.h
include/linux/ufs_fs.h
include/linux/ufs_fs_i.h
include/linux/umem.h
include/linux/usb_ch9.h
include/linux/usb_otg.h [new file with mode: 0644]
include/linux/workqueue.h
include/math-emu/op-common.h
include/media/id.h
include/media/tuner.h
include/net/dn_neigh.h
include/net/gen_stats.h [new file with mode: 0644]
include/net/if_inet6.h
include/net/inet_ecn.h
include/net/ip_fib.h
include/net/ipcomp.h
include/net/llc_pdu.h
include/net/neighbour.h
include/net/pkt_act.h
include/net/tc_act/tc_gact.h [new file with mode: 0644]
include/net/tcp_ecn.h
include/rxrpc/connection.h
include/rxrpc/packet.h
include/rxrpc/peer.h
include/rxrpc/rxrpc.h
include/rxrpc/transport.h
include/rxrpc/types.h
include/scsi/scsi_driver.h
include/sound/asequencer.h
include/sound/control.h
include/sound/driver.h
include/sound/es1688.h
include/sound/info.h
include/sound/memalloc.h
include/sound/pcm-indirect.h [new file with mode: 0644]
include/sound/pcm.h
include/sound/pcm_oss.h
include/sound/seq_kernel.h
include/sound/soundfont.h
include/sound/vx_core.h
include/video/epson1355.h [new file with mode: 0644]
include/video/tdfx.h
include/video/vga.h
kernel/audit.c
kernel/capability.c
kernel/exec_domain.c
kernel/kprobes.c [new file with mode: 0644]
kernel/power/Kconfig
kernel/power/console.c
kernel/power/disk.c
kernel/power/main.c
kernel/power/power.h
kernel/profile.c
kernel/ptrace.c
kernel/resource.c
kernel/softirq.c
kernel/spinlock.c [new file with mode: 0644]
lib/Kconfig.debug [new file with mode: 0644]
lib/iomap.c [new file with mode: 0644]
lib/kref.c
lib/zlib_inflate/Makefile
lib/zlib_inflate/infblock.c
lib/zlib_inflate/inflate.c
lib/zlib_inflate/inflate_sync.c [new file with mode: 0644]
lib/zlib_inflate/inftrees.h
mm/mempolicy.c
mm/thrash.c [new file with mode: 0644]
mm/tiny-shmem.c [new file with mode: 0644]
net/8021q/vlan.c
net/appletalk/Makefile
net/appletalk/atalk_proc.c
net/appletalk/sysctl_net_atalk.c
net/atm/common.h
net/atm/ipcommon.h
net/atm/lec.h
net/ax25/ax25_in.c
net/bluetooth/bnep/core.c
net/bridge/br_input.c
net/bridge/br_netfilter.c
net/bridge/netfilter/ebt_802_3.c
net/bridge/netfilter/ebt_among.c
net/bridge/netfilter/ebt_arp.c
net/bridge/netfilter/ebt_arpreply.c
net/bridge/netfilter/ebt_dnat.c
net/bridge/netfilter/ebt_ip.c
net/bridge/netfilter/ebt_log.c
net/bridge/netfilter/ebt_redirect.c
net/bridge/netfilter/ebt_snat.c
net/bridge/netfilter/ebt_stp.c
net/bridge/netfilter/ebt_vlan.c
net/core/dv.c
net/core/filter.c
net/core/gen_estimator.c [new file with mode: 0644]
net/core/gen_stats.c [new file with mode: 0644]
net/core/neighbour.c
net/core/utils.c
net/decnet/dn_neigh.c
net/ipv4/fib_lookup.h [new file with mode: 0644]
net/ipv4/fib_rules.c
net/ipv4/fib_semantics.c
net/ipv4/ipvs/ip_vs_core.c
net/ipv4/ipvs/ip_vs_proto.c
net/ipv4/ipvs/ip_vs_proto_ah.c
net/ipv4/ipvs/ip_vs_proto_esp.c
net/ipv4/ipvs/ip_vs_proto_icmp.c
net/ipv4/ipvs/ip_vs_proto_tcp.c
net/ipv4/ipvs/ip_vs_proto_udp.c
net/ipv4/netfilter/ip_conntrack_ftp.c
net/ipv4/netfilter/ip_conntrack_irc.c
net/ipv4/netfilter/ip_conntrack_proto_sctp.c [new file with mode: 0644]
net/ipv4/netfilter/ip_conntrack_tftp.c
net/ipv4/netfilter/ip_nat_ftp.c
net/ipv4/netfilter/ip_nat_helper.c
net/ipv4/netfilter/ip_nat_irc.c
net/ipv4/netfilter/ip_nat_proto_icmp.c
net/ipv4/netfilter/ip_nat_proto_tcp.c
net/ipv4/netfilter/ip_nat_proto_udp.c
net/ipv4/netfilter/ip_nat_proto_unknown.c
net/ipv4/netfilter/ip_nat_rule.c
net/ipv4/netfilter/ip_nat_tftp.c
net/ipv4/netfilter/ip_queue.c
net/ipv4/netfilter/ipchains_core.c
net/ipv4/netfilter/ipfwadm_core.c
net/ipv4/netfilter/ipt_ECN.c
net/ipv4/netfilter/ipt_NOTRACK.c
net/ipv4/netfilter/ipt_ah.c
net/ipv4/netfilter/ipt_comment.c [new file with mode: 0644]
net/ipv4/netfilter/ipt_conntrack.c
net/ipv4/netfilter/ipt_ecn.c
net/ipv4/netfilter/ipt_esp.c
net/ipv4/netfilter/ipt_mac.c
net/ipv4/netfilter/ipt_multiport.c
net/ipv4/netfilter/ipt_recent.c
net/ipv4/netfilter/ipt_sctp.c [new file with mode: 0644]
net/ipv4/netfilter/ipt_state.c
net/ipv4/netfilter/ipt_tcpmss.c
net/ipv4/netfilter/iptable_filter.c
net/ipv4/tcp_diag.c
net/ipv4/xfrm4_input.c
net/ipv4/xfrm4_output.c
net/ipv6/Kconfig
net/ipv6/datagram.c
net/ipv6/exthdrs_core.c
net/ipv6/ip6_fib.c
net/ipv6/netfilter/Kconfig
net/ipv6/netfilter/Makefile
net/ipv6/netfilter/ip6t_eui64.c
net/ipv6/netfilter/ip6t_mac.c
net/ipv6/netfilter/ip6t_physdev.c [new file with mode: 0644]
net/ipv6/netfilter/ip6table_filter.c
net/ipv6/xfrm6_input.c
net/ipv6/xfrm6_output.c
net/ipv6/xfrm6_tunnel.c
net/irda/irlan/irlan_common.c
net/irda/irlan/irlan_eth.c
net/irda/irqueue.c
net/llc/llc_input.c
net/llc/llc_output.c
net/rxrpc/main.c
net/rxrpc/peer.c
net/sched/act_api.c
net/sched/gact.c [new file with mode: 0644]
net/sched/sch_dsmark.c
net/sched/sch_netem.c
net/sched/sch_sfq.c
net/sched/sch_teql.c
net/sunrpc/auth_gss/gss_spkm3_mech.c [new file with mode: 0644]
net/sunrpc/auth_gss/gss_spkm3_seal.c [new file with mode: 0644]
net/sunrpc/auth_gss/gss_spkm3_token.c [new file with mode: 0644]
net/sunrpc/auth_gss/gss_spkm3_unseal.c [new file with mode: 0644]
net/sunrpc/sched.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svc.c
net/sunrpc/svcauth.c
net/sunrpc/svcauth_unix.c
scripts/Makefile.build
scripts/Makefile.clean
scripts/Makefile.host [new file with mode: 0644]
scripts/Makefile.lib
scripts/basic/Makefile
scripts/binoffset.c
scripts/genksyms/Makefile
scripts/genksyms/genksyms.c
scripts/kconfig/confdata.c
scripts/kconfig/gconf.c
scripts/kconfig/lkc.h
scripts/kconfig/menu.c
scripts/kconfig/zconf.tab.c_shipped
scripts/kconfig/zconf.y
scripts/lxdialog/Makefile
scripts/lxdialog/menubox.c
scripts/mksysmap [new file with mode: 0644]
scripts/mod/modpost.c
scripts/mod/modpost.h
scripts/mod/sumversion.c
scripts/namespace.pl [new file with mode: 0644]
scripts/package/Makefile
scripts/package/mkspec
scripts/patch-kernel
scripts/ver_linux
security/Kconfig
security/security.c
security/selinux/ss/avtab.c
security/selinux/ss/avtab.h
security/selinux/ss/policydb.h
sound/core/device.c
sound/core/hwdep.c
sound/core/info.c
sound/core/info_oss.c
sound/core/memory.c
sound/core/oss/mixer_oss.c
sound/core/oss/pcm_plugin.h
sound/core/pcm.c
sound/core/pcm_timer.c
sound/core/seq/instr/ainstr_fm.c
sound/core/seq/instr/ainstr_gf1.c
sound/core/seq/instr/ainstr_iw.c
sound/core/seq/instr/ainstr_simple.c
sound/core/seq/oss/seq_oss_ioctl.c
sound/core/seq/oss/seq_oss_midi.c
sound/core/seq/oss/seq_oss_readq.c
sound/core/seq/oss/seq_oss_readq.h
sound/core/seq/oss/seq_oss_rw.c
sound/core/seq/oss/seq_oss_synth.c
sound/core/seq/oss/seq_oss_timer.c
sound/core/seq/oss/seq_oss_writeq.c
sound/core/seq/seq_device.c
sound/core/seq/seq_fifo.c
sound/core/seq/seq_instr.c
sound/core/seq/seq_memory.c
sound/core/seq/seq_midi_emul.c
sound/core/seq/seq_midi_event.c
sound/core/seq/seq_ports.c
sound/core/seq/seq_prioq.c
sound/core/seq/seq_queue.c
sound/core/seq/seq_timer.c
sound/core/seq/seq_virmidi.c
sound/core/sgbuf.c
sound/drivers/mpu401/mpu401_uart.c
sound/drivers/opl3/opl3_midi.c
sound/drivers/opl3/opl3_synth.c
sound/drivers/opl4/Makefile
sound/drivers/opl4/opl4_lib.c
sound/drivers/opl4/opl4_local.h
sound/drivers/opl4/opl4_mixer.c
sound/drivers/opl4/opl4_proc.c
sound/drivers/opl4/opl4_synth.c
sound/drivers/vx/vx_core.c
sound/drivers/vx/vx_hwdep.c
sound/drivers/vx/vx_mixer.c
sound/drivers/vx/vx_pcm.c
sound/drivers/vx/vx_uer.c
sound/i2c/cs8427.c
sound/i2c/i2c.c
sound/i2c/l3/uda1341.c
sound/i2c/other/ak4117.c
sound/i2c/other/ak4xxx-adda.c
sound/i2c/tea6330t.c
sound/isa/ad1816a/ad1816a_lib.c
sound/isa/cs423x/cs4236_lib.c
sound/isa/es1688/es1688_lib.c
sound/isa/gus/Makefile
sound/isa/gus/gus_dram.c
sound/isa/gus/gus_instr.c
sound/isa/gus/gus_irq.c
sound/isa/gus/gus_main.c
sound/isa/gus/gus_mem.c
sound/isa/gus/gus_mem_proc.c
sound/isa/gus/gus_mixer.c
sound/isa/gus/gus_pcm.c
sound/isa/gus/gus_synth.c
sound/isa/gus/gus_timer.c
sound/isa/gus/gus_uart.c
sound/isa/sb/emu8000.c
sound/isa/sb/emu8000_callback.c
sound/isa/sb/emu8000_local.h
sound/isa/sb/emu8000_pcm.c
sound/isa/sb/emu8000_synth.c
sound/isa/sb/sb16_csp.c
sound/isa/sb/sb16_main.c
sound/isa/sb/sb8_main.c
sound/isa/sb/sb8_midi.c
sound/isa/sb/sb_common.c
sound/isa/sb/sb_mixer.c
sound/oss/ad1848.h
sound/oss/ad1889.h
sound/oss/ali5455.c
sound/oss/au1000.c
sound/oss/btaudio.c
sound/oss/cs4232.c
sound/oss/cs4232.h
sound/oss/cs46xx.c
sound/oss/dmasound/Kconfig
sound/oss/emu10k1/midi.c
sound/oss/forte.c
sound/oss/gus_card.c
sound/oss/harmony.c
sound/oss/ite8172.c
sound/oss/mad16.c
sound/oss/mpu401.h
sound/oss/msnd.h
sound/oss/msnd_pinnacle.c
sound/oss/nec_vrc5477.c
sound/oss/opl3sa.c
sound/oss/rme96xx.c
sound/oss/sb_common.c
sound/oss/sgalaxy.c
sound/oss/swarm_cs4297a.c
sound/oss/trix.c
sound/pci/Makefile
sound/pci/ac97/ac97_id.h
sound/pci/ac97/ac97_patch.h
sound/pci/ac97/ak4531_codec.c
sound/pci/atiixp_modem.c [new file with mode: 0644]
sound/pci/au88x0/au88x0_mixer.c
sound/pci/au88x0/au88x0_mpu401.c
sound/pci/au88x0/au88x0_xtalk.c
sound/pci/au88x0/au88x0_xtalk.h
sound/pci/cs46xx/cs46xx_lib.h
sound/pci/cs46xx/dsp_spos.c
sound/pci/emu10k1/emu10k1_callback.c
sound/pci/emu10k1/emu10k1_patch.c
sound/pci/emu10k1/emu10k1_synth.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/io.c
sound/pci/emu10k1/irq.c
sound/pci/emu10k1/memory.c
sound/pci/ice1712/ak4xxx.c
sound/pci/ice1712/ews.h
sound/pci/ice1712/pontis.c [new file with mode: 0644]
sound/pci/ice1712/pontis.h [new file with mode: 0644]
sound/pci/ice1712/vt1720_mobo.c [new file with mode: 0644]
sound/pci/ice1712/vt1720_mobo.h [new file with mode: 0644]
sound/pci/mixart/mixart.h
sound/pci/mixart/mixart_core.c
sound/pci/mixart/mixart_hwdep.c
sound/pci/mixart/mixart_mixer.c
sound/pci/trident/trident_memory.c
sound/pci/trident/trident_synth.c
sound/pci/vx222/vx222.h
sound/pci/vx222/vx222_ops.c
sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
sound/pcmcia/vx/vx_entry.c
sound/pcmcia/vx/vxp_mixer.c
sound/pcmcia/vx/vxp_ops.c
sound/ppc/Kconfig
sound/ppc/Makefile
sound/ppc/awacs.c
sound/ppc/beep.c [new file with mode: 0644]
sound/ppc/burgundy.c
sound/ppc/daca.c
sound/synth/emux/emux.c
sound/synth/emux/emux_effect.c
sound/synth/emux/emux_hwdep.c
sound/synth/emux/emux_nrpn.c
sound/synth/emux/emux_proc.c
sound/synth/emux/emux_seq.c
sound/synth/emux/emux_synth.c
sound/synth/emux/soundfont.c
sound/synth/util_mem.c
sound/usb/Kconfig
sound/usb/Makefile
sound/usb/usbmidi.c
sound/usb/usbmixer_maps.c
sound/usb/usx2y/Makefile [new file with mode: 0644]
sound/usb/usx2y/usX2Yhwdep.c [new file with mode: 0644]
sound/usb/usx2y/usX2Yhwdep.h [new file with mode: 0644]
sound/usb/usx2y/usbus428ctldefs.h [new file with mode: 0644]
sound/usb/usx2y/usbusx2y.c [new file with mode: 0644]
sound/usb/usx2y/usbusx2y.h [new file with mode: 0644]
sound/usb/usx2y/usbusx2yaudio.c [new file with mode: 0644]
sound/usb/usx2y/usx2y.h [new file with mode: 0644]
usr/Makefile

index 7b256c1..f25b395 100644 (file)
@@ -356,10 +356,10 @@ Generally, inline functions are preferable to macros resembling functions.
 
 Macros with multiple statements should be enclosed in a do - while block:
 
-#define macrofun(a,b,c)                        \
+#define macrofun(a, b, c)                      \
        do {                                    \
                if (a == 5)                     \
-                       do_this(b,c);           \
+                       do_this(b, c);          \
        } while (0)
 
 Things to avoid when using macros:
index bf212c0..9a23eab 100644 (file)
@@ -185,9 +185,7 @@ clean-files := $(DOCBOOKS) \
        $(patsubst %.sgml, %.9,    $(DOCBOOKS)) \
        $(C-procfs-example)
 
-ifneq ($(wildcard $(patsubst %.html,%,$(HTML))),)
-clean-rule := rm -rf $(wildcard $(patsubst %.html,%,$(HTML)))
-endif
+clean-dirs := $(patsubst %.sgml,%,$(DOCBOOKS))
 
 #man put files in man subdir - traverse down
 subdir- := man/
index f07e73a..0c28a96 100644 (file)
@@ -2,8 +2,8 @@
 <book id="USB-Gadget-API">
   <bookinfo>
     <title>USB Gadget API for Linux</title>
-    <date>02 June 2003</date>
-    <edition>02 June 2003</edition>
+    <date>20 August 2004</date>
+    <edition>20 August 2004</edition>
   
     <legalnotice>
        <para>
@@ -34,7 +34,7 @@
        </para>
     </legalnotice>
     <copyright>
-      <year>2003</year>
+      <year>2003-2004</year>
       <holder>David Brownell</holder>
     </copyright>
 
@@ -73,9 +73,13 @@ a number of important problems, including: </para>
        composite devices,
        and alternate interface settings.
        </para></listitem>
+    <listitem><para>USB "On-The-Go" (OTG) support, in conjunction
+       with updates to the Linux-USB host side.
+       </para></listitem>
     <listitem><para>Sharing data structures and API models with the
-       Linux-USB host side API.  This looks forward to USB "On-The-Go"
-       (OTG) and similar more-symmetric frameworks.
+       Linux-USB host side API.  This helps the OTG support, and
+       looks forward to more-symmetric frameworks (where the same
+       I/O model is used by both host and device side drivers).
        </para></listitem>
     <listitem><para>Minimalist, so it's easier to support new device
        controller hardware.  I/O processing doesn't imply large
@@ -153,6 +157,7 @@ with the lowest level (which directly handles hardware).
        the SA-11x0 or PXA-25x UDC (found within many PDAs),
        and a variety of other products.
        </para>
+
        </listitem></varlistentry>
 
     <varlistentry>
@@ -162,10 +167,14 @@ with the lowest level (which directly handles hardware).
        <para>The lower boundary of this driver implements hardware-neutral
        USB functions, using calls to the controller driver.
        Because such hardware varies widely in capabilities and restrictions,
-       the gadget driver is normally configured at compile time
+       and is used in embedded environments where space is at a premium,
+       the gadget driver is often configured at compile time
        to work with endpoints supported by one particular controller.
        Gadget drivers may be portable to several different controllers,
        using conditional compilation.
+       (Recent kernels substantially simplify the work involved in
+       supporting new hardware, by <emphasis>autoconfiguring</emphasis>
+       endpoints automatically for many bulk-oriented drivers.)
        Gadget driver responsibilities include:
        </para>
        <itemizedlist>
@@ -178,8 +187,9 @@ with the lowest level (which directly handles hardware).
                altsettings, including enabling and configuring endpoints
                </para></listitem>
            <listitem><para>handling life cycle events, such as managing
-               bindings
-               to hardware, and disconnection from the USB host.
+               bindings to hardware,
+               USB suspend/resume, remote wakeup,
+               and disconnection from the USB host.
                </para></listitem>
            <listitem><para>managing IN and OUT transfers on all currently
                enabled endpoints
@@ -244,15 +254,38 @@ with the lowest level (which directly handles hardware).
 
 </variablelist>
 
-<para>Over time, reusable utilities should evolve to help make some
-gadget driver tasks simpler.  An example of particular interest
+<para>OTG-capable systems will also need to include a standard Linux-USB
+host side stack,
+with <emphasis>usbcore</emphasis>,
+one or more <emphasis>Host Controller Drivers</emphasis> (HCDs),
+<emphasis>USB Device Drivers</emphasis> to support
+the OTG "Targeted Peripheral List",
+and so forth.
+There will also be an <emphasis>OTG Controller Driver</emphasis>,
+which is visible to gadget and device driver developers only indirectly.
+That helps the host and device side USB controllers implement the
+two new OTG protocols (HNP and SRP).
+Roles switch (host to peripheral, or vice versa) using HNP
+during USB suspend processing, and SRP can be viewed as a
+more battery-friendly kind of device wakeup protocol.
+</para>
+
+<para>Over time, reusable utilities are evolving to help make some
+gadget driver tasks simpler.
+For example, building configuration descriptors from vectors of
+descriptors for the configurations interfaces and endpoints is
+now automated, and many drivers now use autoconfiguration to
+choose hardware endpoints and initialize their descriptors.
+
+A potential example of particular interest
 is code implementing standard USB-IF protocols for
 HID, networking, storage, or audio classes.
 Some developers are interested in KDB or KGDB hooks, to let
 target hardware be remotely debugged.
 Most such USB protocol code doesn't need to be hardware-specific,
 any more than network protocols like X11, HTTP, or NFS are.
-Such interface drivers might be combined, to support composite devices.
+Such gadget-side interface drivers should eventually be combined,
+to implement composite devices.
 </para>
 
 </chapter>
@@ -284,7 +317,7 @@ data types and functions are described here.
 <para>However, docproc does not understand all the C constructs
 that are used, so some relevant information is likely omitted from
 what you are reading.  
-One example of such information is several per-request flags.
+One example of such information is endpoint autoconfiguration.
 You'll have to read the header file, and use example source
 code (such as that for "Gadget Zero"), to fully understand the API.
 </para>
@@ -292,7 +325,7 @@ code (such as that for "Gadget Zero"), to fully understand the API.
 <para>The part of the API implementing some basic
 driver capabilities is specific to the version of the
 Linux kernel that's in use.
-The 2.5 kernel includes a <emphasis>driver model</emphasis>
+The 2.6 kernel includes a <emphasis>driver model</emphasis>
 framework that has no analogue on earlier kernels;
 so those parts of the gadget API are not fully portable.
 (They are implemented on 2.4 kernels, but in a different way.)
@@ -308,17 +341,21 @@ There are significant hardware features, such as device-to-device DMA
 that would be added using hardware-specific APIs.
 </para>
 
-<para>This API expects drivers to use conditional compilation to handle
-endpoint capabilities of different hardware.
-Those tend to have arbitrary restrictions, relating to
+<para>This API allows drivers to use conditional compilation to handle
+endpoint capabilities of different hardware, but doesn't require that.
+Hardware tends to have arbitrary restrictions, relating to
 transfer types, addressing, packet sizes, buffering, and availability.
 As a rule, such differences only matter for "endpoint zero" logic
 that handles device configuration and management.
-The API only supports limited run-time
+The API supports limited run-time
 detection of capabilities, through naming conventions for endpoints.
-Although a gadget driver could scan the endpoints available to it and
-choose to map those capabilities onto driver functionality in some way,
-few drivers will want to reconfigure themselves at run-time.
+Many drivers will be able to at least partially autoconfigure
+themselves.
+In particular, driver init sections will often have endpoint
+autoconfiguration logic that scans the hardware's list of endpoints
+to find ones matching the driver requirements
+(relying on those conventions), to eliminate some of the most
+common reasons for conditional compilation.
 </para>
 
 <para>Like the Linux-USB host side API, this API exposes
@@ -355,10 +392,14 @@ and so on.
 At this point the device is logically in the USB ch9 initial state
 ("attached"), drawing no power and not usable
 (since it does not yet support enumeration).
+Any host should not see the device, since it's not
+activated the data line pullup used by the host to
+detect a device, even if VBUS power is available.
 </para></listitem>
 
 <listitem><para>Register a gadget driver that implements some higher level
-device function.  That will then bind() to a usb_gadget.
+device function.  That will then bind() to a usb_gadget, which
+activates the data line pullup sometime after detecting VBUS.
 </para></listitem>
 
 <listitem><para>The hardware driver can now start enumerating.
@@ -373,6 +414,8 @@ based both on what the bus interface hardware provides and on the
 functionality being implemented.
 That can involve alternate settings or configurations,
 unless the hardware prevents such operation.
+For OTG devices, each configuration descriptor includes
+an OTG descriptor.
 </para></listitem>
 
 <listitem><para>The gadget driver handles the last step of enumeration,
@@ -381,13 +424,18 @@ It enables all endpoints used in that configuration,
 with all interfaces in their default settings.
 That involves using a list of the hardware's endpoints, enabling each
 endpoint according to its descriptor.
+It may also involve using <function>usb_gadget_vbus_draw</function>
+to let more power be drawn from VBUS, as allowed by that configuration.
+For OTG devices, setting a configuration may also involve reporting
+HNP capabilities through a user interface.
 </para></listitem>
 
 <listitem><para>Do real work and perform data transfers, possibly involving
 changes to interface settings or switching to new configurations, until the
 device is disconnect()ed from the host.
 Queue any number of transfer requests to each endpoint.
-The drivers then go back to step 3 (above).
+It may be suspended and resumed several times before being disconnected.
+On disconnect, the drivers go back to step 3 (above).
 </para></listitem>
 
 <listitem><para>When the gadget driver module is being unloaded,
@@ -399,7 +447,9 @@ driver be unloaded.
 
 <para>Drivers will normally be arranged so that just loading the
 gadget driver module (or statically linking it into a Linux kernel)
-allows the peripheral device to be enumerated.
+allows the peripheral device to be enumerated, but some drivers
+will defer enumeration until some higher level component (like
+a user mode daemon) enables it.
 Note that at this lowest level there are no policies about how
 ep0 configuration logic is implemented,
 except that it should obey USB specifications.
@@ -410,6 +460,18 @@ or understanding that composite devices might happen to
 be built by integrating reusable components.
 </para>
 
+<para>Note that the lifecycle above can be slightly different
+for OTG devices.
+Other than providing an additional OTG descriptor in each
+configuration, only the HNP-related differences are particularly
+visible to driver code.
+They involve reporting requirements during the SET_CONFIGURATION
+request, and the option to invoke HNP during some suspend callbacks.
+Also, SRP changes the semantics of
+<function>usb_gadget_wakeup</function>
+slightly.
+</para>
+
 </sect1>
 
 <sect1 id="ch9"><title>USB 2.0 Chapter 9 Types and Constants</title>
@@ -418,9 +480,9 @@ be built by integrating reusable components.
 rely on common USB structures and constants
 defined in the
 <filename>&lt;linux/usb_ch9.h&gt;</filename>
-header file, which is standard in Linux 2.5 kernels.
+header file, which is standard in Linux 2.6 kernels.
 These are the same types and constants used by host
-side drivers.
+side drivers (and usbcore).
 </para>
 
 !Iinclude/linux/usb_ch9.h
@@ -451,26 +513,38 @@ USB peripheral controller drivers.
 
 <para>The core API is sufficient for writing a USB Gadget Driver,
 but some optional utilities are provided to simplify common tasks.
+These utilities include endpoint autoconfiguration.
 </para>
 
 !Edrivers/usb/gadget/usbstring.c
 !Edrivers/usb/gadget/config.c
+<!-- !Edrivers/usb/gadget/epautoconf.c -->
 </sect1>
 
 </chapter>
 
 <chapter id="controllers"><title>Peripheral Controller Drivers</title>
 
-<para>The first hardware supporting this API is the NetChip 2280
+<para>The first hardware supporting this API was the NetChip 2280
 controller, which supports USB 2.0 high speed and is based on PCI.
 This is the <filename>net2280</filename> driver module.
-The driver supports Linux kernel versions 2.4 and 2.5;
+The driver supports Linux kernel versions 2.4 and 2.6;
 contact NetChip Technologies for development boards and product
 information.
 </para> 
 
-<para>For users of Intel's PXA 2xx series processors,
-a <filename>pxa2xx_udc</filename> driver is available.
+<para>Other hardware working in the "gadget" framework includes:
+Intel's PXA 25x and IXP42x series processors
+(<filename>pxa2xx_udc</filename>),
+Toshiba TC86c001 "Goku-S" (<filename>goku_udc</filename>),
+Renesas SH7705/7727 (<filename>sh_udc</filename>),
+MediaQ 11xx (<filename>mq11xx_udc</filename>),
+Hynix HMS30C7202 (<filename>h7202_udc</filename>),
+National 9303/4 (<filename>n9604_udc</filename>),
+Texas Instruments OMAP (<filename>omap_udc</filename>),
+Sharp LH7A40x (<filename>lh7a40x_udc</filename>),
+and more.
+Most of those are full speed controllers.
 </para>
 
 <para>At this writing, there are people at work on drivers in
@@ -526,6 +600,15 @@ subset of CDC Ethernet.
 to avoid creating problems.)
 </para>
 
+<para>Support for Microsoft's <emphasis>RNDIS</emphasis>
+protocol has been contributed by Pengutronix and Auerswald GmbH.
+This is like CDC Ethernet, but it runs on more slightly USB hardware
+(but less than the CDC subset).
+However, its main claim to fame is being able to connect directly to
+recent versions of Windows, using drivers that Microsoft bundles
+and supports, making it much simpler to network with Windows.
+</para>
+
 <para>There is also support for user mode gadget drivers,
 using <emphasis>gadgetfs</emphasis>.
 This provides a <emphasis>User Mode API</emphasis> that presents
@@ -535,6 +618,10 @@ Familiar tools like GDB and pthreads can be used to
 develop and debug user mode drivers, so that once a robust
 controller driver is available many applications for it
 won't require new kernel mode software.
+Linux 2.6 <emphasis>Async I/O (AIO)</emphasis>
+support is available, so that user mode software
+can stream data with only slightly more overhead
+than a kernel driver.
 </para>
 
 <para>There's a USB Mass Storage class driver, which provides
@@ -548,6 +635,16 @@ storage class specification, using transparent SCSI commands
 to access the data from the backing store.
 </para>
 
+<para>There's a "serial line" driver, useful for TTY style
+operation over USB.
+The latest version of that driver supports CDC ACM style
+operation, like a USB modem, and so on most hardware it can
+interoperate easily with MS-Windows.
+One interesting use of that driver is in boot firmware (like a BIOS),
+which can sometimes use that model with very small systems without
+real serial lines.
+</para>
+
 <para>Support for other kinds of gadget is expected to
 be developed and contributed
 over time, as this driver framework evolves.
@@ -555,6 +652,96 @@ over time, as this driver framework evolves.
 
 </chapter>
 
+<chapter id="otg"><title>USB On-The-GO (OTG)</title>
+
+<para>USB OTG support on Linux 2.6 was initially developed
+by Texas Instruments for
+<ulink url="http://www.omap.com">OMAP</ulink> 16xx and 17xx
+series processors.
+Other OTG systems should work in similar ways, but the
+hardware level details could be very different.
+</para> 
+
+<para>Systems need specialized hardware support to implement OTG,
+notably including a special <emphasis>Mini-AB</emphasis> jack
+and associated transciever to support <emphasis>Dual-Role</emphasis>
+operation:
+they can act either as a host, using the standard
+Linux-USB host side driver stack,
+or as a peripheral, using this "gadget" framework.
+To do that, the system software relies on small additions
+to those programming interfaces,
+and on a new internal component (here called an "OTG Controller")
+affecting which driver stack connects to the OTG port.
+In each role, the system can re-use the existing pool of
+hardware-neutral drivers, layered on top of the controller
+driver interfaces (<emphasis>usb_bus</emphasis> or
+<emphasis>usb_gadget</emphasis>).
+Such drivers need at most minor changes, and most of the calls
+added to support OTG can also benefit non-OTG products.
+</para>
+
+<itemizedlist>
+    <listitem><para>Gadget drivers test the <emphasis>is_otg</emphasis>
+       flag, and use it to determine whether or not to include
+       an OTG descriptor in each of their configurations.
+       </para></listitem>
+    <listitem><para>Gadget drivers may need changes to support the
+       two new OTG protocols, exposed in new gadget attributes
+       such as <emphasis>b_hnp_enable</emphasis> flag.
+       HNP support should be reported through a user interface
+       (two LEDs could suffice), and is triggered in some cases
+       when the host suspends the peripheral.
+       SRP support can be user-initiated just like remote wakeup,
+       probably by pressing the same button.
+       </para></listitem>
+    <listitem><para>On the host side, USB device drivers need
+       to be taught to trigger HNP at appropriate moments, using
+       <function>usb_suspend_device()</function>.
+       That also conserves battery power, which is useful even
+       for non-OTG configurations.
+       </para></listitem>
+    <listitem><para>Also on the host side, a driver must support the
+       OTG "Targeted Peripheral List".  That's just a whitelist,
+       used to reject peripherals not supported with a given
+       Linux OTG host.
+       <emphasis>This whitelist is product-specific;
+       each product must modify <filename>otg_whitelist.h</filename>
+       to match its interoperability specification.
+       </emphasis>
+       </para>
+       <para>Non-OTG Linux hosts, like PCs and workstations,
+       normally have some solution for adding drivers, so that
+       peripherals that aren't recognized can eventually be supported.
+       That approach is unreasonable for consumer products that may
+       never have their firmware upgraded, and where it's usually
+       unrealistic to expect traditional PC/workstation/server kinds
+       of support model to work.
+       For example, it's often impractical to change device firmware
+       once the product has been distributed, so driver bugs can't
+       normally be fixed if they're found after shipment.
+       </para></listitem>
+</itemizedlist>
+
+<para>
+Additional changes are needed below those hardware-neutral
+<emphasis>usb_bus</emphasis> and <emphasis>usb_gadget</emphasis>
+driver interfaces; those aren't discussed here in any detail.
+Those affect the hardware-specific code for each USB Host or Peripheral
+controller, and how the HCD initializes (since OTG can be active only
+on a single port).
+They also involve what may be called an <emphasis>OTG Controller
+Driver</emphasis>, managing the OTG transceiver and the OTG state
+machine logic as well as much of the root hub behavior for the
+OTG port.
+The OTG controller driver needs to activate and deactivate USB
+controllers depending on the relevant device role.
+Some related changes were needed inside usbcore, so that it
+can identify OTG-capable devices and respond appropriately
+to HNP or SRP protocols.
+</para> 
+
+</chapter>
 
 </book>
 <!--
index 49a902f..8491969 100644 (file)
@@ -940,7 +940,6 @@ static int close_mouse(struct inode *inode, struct file *file)
         if(--mouse_users)
                 return 0;
         free_irq(OURMOUSE_IRQ, NULL);
-        MOD_DEC_USE_COUNT;
         return 0;
 }
   </programlisting>
index 52e4fd6..0f0c3a3 100644 (file)
 !Edrivers/usb/core/message.c
 !Edrivers/usb/core/file.c
 !Edrivers/usb/core/usb.c
+!Edrivers/usb/core/hub.c
     </chapter>
 
     <chapter><title>Host Controller APIs</title>
index 583eb0d..d6dcb27 100644 (file)
@@ -340,6 +340,8 @@ You can change this at module load time (for a module) with:
   modprobe ipmi_si.o type=<type1>,<type2>....
        ports=<port1>,<port2>... addrs=<addr1>,<addr2>...
        irqs=<irq1>,<irq2>... trydefaults=[0|1]
+       regspacings=<sp1>,<sp2>,... regsizes=<size1>,<size2>,...
+       regshifts=<shift1>,<shift2>,...
 
 Each of these except si_trydefaults is a list, the first item for the
 first interface, second item for the second interface, etc.
@@ -361,12 +363,35 @@ si_trydefaults sets whether the standard IPMI interface at 0xca2 and
 any interfaces specified by ACPE are tried.  By default, the driver
 tries it, set this value to zero to turn this off.
 
+The next three parameters have to do with register layout.  The
+registers used by the interfaces may not appear at successive
+locations and they may not be in 8-bit registers.  These parameters
+allow the layout of the data in the registers to be more precisely
+specified.
+
+The regspacings parameter give the number of bytes between successive
+register start addresses.  For instance, if the regspacing is set to 4
+and the start address is 0xca2, then the address for the second
+register would be 0xca6.  This defaults to 1.
+
+The regsizes parameter gives the size of a register, in bytes.  The
+data used by IPMI is 8-bits wide, but it may be inside a larger
+register.  This parameter allows the read and write type to specified.
+It may be 1, 2, 4, or 8.  The default is 1.
+
+Since the register size may be larger than 32 bits, the IPMI data may not
+be in the lower 8 bits.  The regshifts parameter give the amount to shift
+the data to get to the actual IPMI data.
+
 When compiled into the kernel, the addresses can be specified on the
 kernel command line as:
 
   ipmi_si.type=<type1>,<type2>...
        ipmi_si.ports=<port1>,<port2>... ipmi_si.addrs=<addr1>,<addr2>...
        ipmi_si.irqs=<irq1>,<irq2>... ipmi_si.trydefaults=[0|1]
+       ipmi_si.regspacings=<sp1>,<sp2>,...
+       ipmi_si.regsizes=<size1>,<size2>,...
+       ipmi_si.regshifts=<shift1>,<shift2>,...
 
 It works the same as the module parameters of the same names.
 
@@ -496,3 +521,8 @@ start a 120 timer if it is running to make sure the reboot occurs.
 Note that if you use the NMI preaction for the watchdog, you MUST
 NOT use nmi watchdog mode 1.  If you use the NMI watchdog, you
 must use mode 2.
+
+Once you open the watchdog timer, you must write a 'V' character to the
+device to close it, or the timer will not stop.  This is a new semantic
+for the driver, but makes it consistent with the rest of the watchdog
+drivers in Linux.
diff --git a/Documentation/ManagementStyle b/Documentation/ManagementStyle
new file mode 100644 (file)
index 0000000..cbbebfb
--- /dev/null
@@ -0,0 +1,276 @@
+
+                Linux kernel management style
+
+This is a short document describing the preferred (or made up, depending
+on who you ask) management style for the linux kernel.  It's meant to
+mirror the CodingStyle document to some degree, and mainly written to
+avoid answering (*) the same (or similar) questions over and over again. 
+
+Management style is very personal and much harder to quantify than
+simple coding style rules, so this document may or may not have anything
+to do with reality.  It started as a lark, but that doesn't mean that it
+might not actually be true. You'll have to decide for yourself.
+
+Btw, when talking about "kernel manager", it's all about the technical
+lead persons, not the people who do traditional management inside
+companies.  If you sign purchase orders or you have any clue about the
+budget of your group, you're almost certainly not a kernel manager. 
+These suggestions may or may not apply to you. 
+
+First off, I'd suggest buying "Seven Habits of Highly Successful
+People", and NOT read it.  Burn it, it's a great symbolic gesture. 
+
+(*) This document does so not so much by answering the question, but by
+making it painfully obvious to the questioner that we don't have a clue
+to what the answer is. 
+
+Anyway, here goes:
+
+
+               Chapter 1: Decisions
+
+Everybody thinks managers make decisions, and that decision-making is
+important.  The bigger and more painful the decision, the bigger the
+manager must be to make it.  That's very deep and obvious, but it's not
+actually true. 
+
+The name of the game is to _avoid_ having to make a decision.  In
+particular, if somebody tells you "choose (a) or (b), we really need you
+to decide on this", you're in trouble as a manager.  The people you
+manage had better know the details better than you, so if they come to
+you for a technical decision, you're screwed.  You're clearly not
+competent to make that decision for them. 
+
+(Corollary:if the people you manage don't know the details better than
+you, you're also screwed, although for a totally different reason. 
+Namely that you are in the wrong job, and that _they_ should be managing
+your brilliance instead). 
+
+So the name of the game is to _avoid_ decisions, at least the big and
+painful ones.  Making small and non-consequential decisions is fine, and
+makes you look like you know what you're doing, so what a kernel manager
+needs to do is to turn the big and painful ones into small things where
+nobody really cares. 
+
+It helps to realize that the key difference between a big decision and a
+small one is whether you can fix your decision afterwards.  Any decision
+can be made small by just always making sure that if you were wrong (and
+you _will_ be wrong), you can always undo the damage later by
+backtracking.  Suddenly, you get to be doubly managerial for making
+_two_ inconsequential decisions - the wrong one _and_ the right one. 
+
+And people will even see that as true leadership (*cough* bullshit
+*cough*).
+
+Thus the key to avoiding big decisions becomes to just avoiding to do
+things that can't be undone.  Don't get ushered into a corner from which
+you cannot escape.  A cornered rat may be dangerous - a cornered manager
+is just pitiful. 
+
+It turns out that since nobody would be stupid enough to ever really let
+a kernel manager have huge fiscal responsibility _anyway_, it's usually
+fairly easy to backtrack.  Since you're not going to be able to waste
+huge amounts of money that you might not be able to repay, the only
+thing you can backtrack on is a technical decision, and there
+back-tracking is very easy: just tell everybody that you were an
+incompetent nincompoop, say you're sorry, and undo all the worthless
+work you had people work on for the last year.  Suddenly the decision
+you made a year ago wasn't a big decision after all, since it could be
+easily undone. 
+
+It turns out that some people have trouble with this approach, for two
+reasons:
+ - admitting you were an idiot is harder than it looks.  We all like to
+   maintain appearances, and coming out in public to say that you were
+   wrong is sometimes very hard indeed. 
+ - having somebody tell you that what you worked on for the last year
+   wasn't worthwhile after all can be hard on the poor lowly engineers
+   too, and while the actual _work_ was easy enough to undo by just
+   deleting it, you may have irrevocably lost the trust of that
+   engineer.  And remember: "irrevocable" was what we tried to avoid in
+   the first place, and your decision ended up being a big one after
+   all. 
+
+Happily, both of these reasons can be mitigated effectively by just
+admitting up-front that you don't have a friggin' clue, and telling
+people ahead of the fact that your decision is purely preliminary, and
+might be the wrong thing.  You should always reserve the right to change
+your mind, and make people very _aware_ of that.  And it's much easier
+to admit that you are stupid when you haven't _yet_ done the really
+stupid thing.
+
+Then, when it really does turn out to be stupid, people just roll their
+eyes and say "Oops, he did it again".  
+
+This preemptive admission of incompetence might also make the people who
+actually do the work also think twice about whether it's worth doing or
+not.  After all, if _they_ aren't certain whether it's a good idea, you
+sure as hell shouldn't encourage them by promising them that what they
+work on will be included.  Make them at least think twice before they
+embark on a big endeavor. 
+
+Remember: they'd better know more about the details than you do, and
+they usually already think they have the answer to everything.  The best
+thing you can do as a manager is not to instill confidence, but rather a
+healthy dose of critical thinking on what they do. 
+
+Btw, another way to avoid a decision is to plaintively just whine "can't
+we just do both?" and look pitiful.  Trust me, it works.  If it's not
+clear which approach is better, they'll eventually figure it out.  The
+answer may end up being that both teams get so frustrated by the
+situation that they just give up. 
+
+That may sound like a failure, but it's usually a sign that there was
+something wrong with both projects, and the reason the people involved
+couldn't decide was that they were both wrong.  You end up coming up
+smelling like roses, and you avoided yet another decision that you could
+have screwed up on. 
+
+
+               Chapter 2: People
+
+Most people are idiots, and being a manager means you'll have to deal
+with it, and perhaps more importantly, that _they_ have to deal with
+_you_. 
+
+It turns out that while it's easy to undo technical mistakes, it's not
+as easy to undo personality disorders.  You just have to live with
+theirs - and yours. 
+
+However, in order to prepare yourself as a kernel manager, it's best to
+remember not to burn any bridges, bomb any innocent villagers, or
+alienate too many kernel developers. It turns out that alienating people
+is fairly easy, and un-alienating them is hard. Thus "alienating"
+immediately falls under the heading of "not reversible", and becomes a
+no-no according to Chapter 1.
+
+There's just a few simple rules here:
+ (1) don't call people d*ckheads (at least not in public)
+ (2) learn how to apologize when you forgot rule (1)
+
+The problem with #1 is that it's very easy to do, since you can say
+"you're a d*ckhead" in millions of different ways (*), sometimes without
+even realizing it, and almost always with a white-hot conviction that
+you are right. 
+
+And the more convinced you are that you are right (and let's face it,
+you can call just about _anybody_ a d*ckhead, and you often _will_ be
+right), the harder it ends up being to apologize afterwards. 
+
+To solve this problem, you really only have two options:
+ - get really good at apologies
+ - spread the "love" out so evenly that nobody really ends up feeling
+   like they get unfairly targeted.  Make it inventive enough, and they
+   might even be amused. 
+
+The option of being unfailingly polite really doesn't exist. Nobody will
+trust somebody who is so clearly hiding his true character.
+
+(*) Paul Simon sang "Fifty Ways to Lose Your Lover", because quite
+frankly, "A Million Ways to Tell a Developer He Is a D*ckhead" doesn't
+scan nearly as well.  But I'm sure he thought about it. 
+
+
+               Chapter 3: People II - the Good Kind
+
+While it turns out that most people are idiots, the corollary to that is
+sadly that you are one too, and that while we can all bask in the secure
+knowledge that we're better than the average person (let's face it,
+nobody ever believes that they're average or below-average), we should
+also admit that we're not the sharpest knife around, and there will be
+other people that are less of an idiot that you are. 
+
+Some people react badly to smart people.  Others take advantage of them. 
+
+Make sure that you, as a kernel maintainer, are in the second group. 
+Suck up to them, because they are the people who will make your job
+easier. In particular, they'll be able to make your decisions for you,
+which is what the game is all about.
+
+So when you find somebody smarter than you are, just coast along.  Your
+management responsibilities largely become ones of saying "Sounds like a
+good idea - go wild", or "That sounds good, but what about xxx?".  The
+second version in particular is a great way to either learn something
+new about "xxx" or seem _extra_ managerial by pointing out something the
+smarter person hadn't thought about.  In either case, you win.
+
+One thing to look out for is to realize that greatness in one area does
+not necessarily translate to other areas.  So you might prod people in
+specific directions, but let's face it, they might be good at what they
+do, and suck at everything else.  The good news is that people tend to
+naturally gravitate back to what they are good at, so it's not like you
+are doing something irreversible when you _do_ prod them in some
+direction, just don't push too hard.
+
+
+               Chapter 4: Placing blame
+
+Things will go wrong, and people want somebody to blame. Tag, you're it.
+
+It's not actually that hard to accept the blame, especially if people
+kind of realize that it wasn't _all_ your fault.  Which brings us to the
+best way of taking the blame: do it for another guy. You'll feel good
+for taking the fall, he'll feel good about not getting blamed, and the
+guy who lost his whole 36GB porn-collection because of your incompetence
+will grudgingly admit that you at least didn't try to weasel out of it.
+
+Then make the developer who really screwed up (if you can find him) know
+_in_private_ that he screwed up.  Not just so he can avoid it in the
+future, but so that he knows he owes you one.  And, perhaps even more
+importantly, he's also likely the person who can fix it.  Because, let's
+face it, it sure ain't you. 
+
+Taking the blame is also why you get to be manager in the first place. 
+It's part of what makes people trust you, and allow you the potential
+glory, because you're the one who gets to say "I screwed up".  And if
+you've followed the previous rules, you'll be pretty good at saying that
+by now. 
+
+
+               Chapter 5: Things to avoid
+
+There's one thing people hate even more than being called "d*ckhead",
+and that is being called a "d*ckhead" in a sanctimonious voice.  The
+first you can apologize for, the second one you won't really get the
+chance.  They likely will no longer be listening even if you otherwise
+do a good job. 
+
+We all think we're better than anybody else, which means that when
+somebody else puts on airs, it _really_ rubs us the wrong way.  You may
+be morally and intellectually superior to everybody around you, but
+don't try to make it too obvious unless you really _intend_ to irritate
+somebody (*). 
+
+Similarly, don't be too polite or subtle about things. Politeness easily
+ends up going overboard and hiding the problem, and as they say, "On the
+internet, nobody can hear you being subtle". Use a big blunt object to
+hammer the point in, because you can't really depend on people getting
+your point otherwise.
+
+Some humor can help pad both the bluntness and the moralizing.  Going
+overboard to the point of being ridiculous can drive a point home
+without making it painful to the recipient, who just thinks you're being
+silly.  It can thus help get through the personal mental block we all
+have about criticism. 
+
+(*) Hint: internet newsgroups that are not directly related to your work
+are great ways to take out your frustrations at other people. Write
+insulting posts with a sneer just to get into a good flame every once in
+a while, and you'll feel cleansed. Just don't crap too close to home.
+
+
+               Chapter 6: Why me?
+
+Since your main responsibility seems to be to take the blame for other
+peoples mistakes, and make it painfully obvious to everybody else that
+you're incompetent, the obvious question becomes one of why do it in the
+first place?
+
+First off, while you may or may not get screaming teenage girls (or
+boys, let's not be judgmental or sexist here) knocking on your dressing
+room door, you _will_ get an immense feeling of personal accomplishment
+for being "in charge".  Never mind the fact that you're really leading
+by trying to keep up with everybody else and running after them as fast
+as you can.  Everybody will still think you're the person in charge. 
+
+It's a great job if you can hack it.
diff --git a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt
new file mode 100644 (file)
index 0000000..12250b3
--- /dev/null
@@ -0,0 +1,387 @@
+Read the F-ing Papers!
+
+
+This document describes RCU-related publications, and is followed by
+the corresponding bibtex entries.
+
+The first thing resembling RCU was published in 1980, when Kung and Lehman
+[Kung80] recommended use of a garbage collector to defer destruction
+of nodes in a parallel binary search tree in order to simplify its
+implementation.  This works well in environments that have garbage
+collectors, but current production garbage collectors incur significant
+read-side overhead.
+
+In 1982, Manber and Ladner [Manber82,Manber84] recommended deferring
+destruction until all threads running at that time have terminated, again
+for a parallel binary search tree.  This approach works well in systems
+with short-lived threads, such as the K42 research operating system.
+However, Linux has long-lived tasks, so more is needed.
+
+In 1986, Hennessy, Osisek, and Seigh [Hennessy89] introduced passive
+serialization, which is an RCU-like mechanism that relies on the presence
+of "quiescent states" in the VM/XA hypervisor that are guaranteed not
+to be referencing the data structure.  However, this mechanism was not
+optimized for modern computer systems, which is not surprising given
+that these overheads were not so expensive in the mid-80s.  Nonetheless,
+passive serialization appears to be the first deferred-destruction
+mechanism to be used in production.  Furthermore, the relevant patent has
+lapsed, so this approach may be used in non-GPL software, if desired.
+(In contrast, use of RCU is permitted only in software licensed under
+GPL.  Sorry!!!)
+
+In 1990, Pugh [Pugh90] noted that explicitly tracking which threads
+were reading a given data structure permitted deferred free to operate
+in the presence of non-terminating threads.  However, this explicit
+tracking imposes significant read-side overhead, which is undesirable
+in read-mostly situations.  This algorithm does take pains to avoid
+write-side contention and parallelize the other write-side overheads by
+providing a fine-grained locking design, however, it would be interesting
+to see how much of the performance advantage reported in 1990 remains
+in 2004.
+
+At about this same time, Adams [Adams91] described ``chaotic relaxation'',
+where the normal barriers between successive iterations of convergent
+numerical algorithms are relaxed, so that iteration $n$ might use
+data from iteration $n-1$ or even $n-2$.  This introduces error,
+which typically slows convergence and thus increases the number of
+iterations required.  However, this increase is sometimes more than made
+up for by a reduction in the number of expensive barrier operations,
+which are otherwise required to synchronize the threads at the end
+of each iteration.  Unfortunately, chaotic relaxation requires highly
+structured data, such as the matrices used in scientific programs, and
+is thus inapplicable to most data structures in operating-system kernels.
+
+In 1993, Jacobson [Jacobson93] verbally described what is perhaps the
+simplest deferred-free technique: simply waiting a fixed amount of time
+before freeing blocks awaiting deferred free.  Jacobson did not describe
+any write-side changes he might have made in this work using SGI's Irix
+kernel.  Aju John published a similar technique in 1995 [AjuJohn95].
+This works well if there is a well-defined upper bound on the length of
+time that reading threads can hold references, as there might well be in
+hard real-time systems.  However, if this time is exceeded, perhaps due
+to preemption, excessive interrupts, or larger-than-anticipated load,
+memory corruption can ensue, with no reasonable means of diagnosis.
+Jacobson's technique is therefore inappropriate for use in production
+operating-system kernels, except when such kernels can provide hard
+real-time response guarantees for all operations.
+
+Also in 1995, Pu et al. [Pu95a] applied a technique similar to that of Pugh's
+read-side-tracking to permit replugging of algorithms within a commercial
+Unix operating system.  However, this replugging permitted only a single
+reader at a time.  The following year, this same group of researchers
+extended their technique to allow for multiple readers [Cowan96a].
+Their approach requires memory barriers (and thus pipeline stalls),
+but reduces memory latency, contention, and locking overheads.
+
+1995 also saw the first publication of DYNIX/ptx's RCU mechanism
+[Slingwine95], which was optimized for modern CPU architectures,
+and was successfully applied to a number of situations within the
+DYNIX/ptx kernel.  The corresponding conference paper appeared in 1998
+[McKenney98].
+
+In 1999, the Tornado and K42 groups described their "generations"
+mechanism, which quite similar to RCU [Gamsa99].  These operating systems
+made pervasive use of RCU in place of "existence locks", which greatly
+simplifies locking hierarchies.
+
+2001 saw the first RCU presentation involving Linux [McKenney01a]
+at OLS.  The resulting abundance of RCU patches was presented the
+following year [McKenney02a], and use of RCU in dcache was first
+described that same year [Linder02a].
+
+Also in 2002, Michael [Michael02b,Michael02a] presented techniques
+that defer the destruction of data structures to simplify non-blocking
+synchronization (wait-free synchronization, lock-free synchronization,
+and obstruction-free synchronization are all examples of non-blocking
+synchronization).  In particular, this technique eliminates locking,
+reduces contention, reduces memory latency for readers, and parallelizes
+pipeline stalls and memory latency for writers.  However, these
+techniques still impose significant read-side overhead in the form of
+memory barriers.  Researchers at Sun worked along similar lines in the
+same timeframe [HerlihyLM02,HerlihyLMS03].
+
+In 2003, the K42 group described how RCU could be used to create
+hot-pluggable implementations of operating-system functions.  Later that
+year saw a paper describing an RCU implementation of System V IPC
+[Arcangeli03], and an introduction to RCU in Linux Journal [McKenney03a].
+
+2004 has seen a Linux-Journal article on use of RCU in dcache
+[McKenney04a], a performance comparison of locking to RCU on several
+different CPUs [McKenney04b], a dissertation describing use of RCU in a
+number of operating-system kernels [PaulEdwardMcKenneyPhD], and a paper
+describing how to make RCU safe for soft-realtime applications [Sarma04c].
+
+
+Bibtex Entries
+
+@article{Kung80
+,author="H. T. Kung and Q. Lehman"
+,title="Concurrent Maintenance of Binary Search Trees"
+,Year="1980"
+,Month="September"
+,journal="ACM Transactions on Database Systems"
+,volume="5"
+,number="3"
+,pages="354-382"
+}
+
+@techreport{Manber82
+,author="Udi Manber and Richard E. Ladner"
+,title="Concurrency Control in a Dynamic Search Structure"
+,institution="Department of Computer Science, University of Washington"
+,address="Seattle, Washington"
+,year="1982"
+,number="82-01-01"
+,month="January"
+,pages="28"
+}
+
+@article{Manber84
+,author="Udi Manber and Richard E. Ladner"
+,title="Concurrency Control in a Dynamic Search Structure"
+,Year="1984"
+,Month="September"
+,journal="ACM Transactions on Database Systems"
+,volume="9"
+,number="3"
+,pages="439-455"
+}
+
+@techreport{Hennessy89
+,author="James P. Hennessy and Damian L. Osisek and Joseph W. {Seigh II}"
+,title="Passive Serialization in a Multitasking Environment"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1989"
+,number="US Patent 4,809,168 (lapsed)"
+,month="February"
+,pages="11"
+}
+
+@techreport{Pugh90
+,author="William Pugh"
+,title="Concurrent Maintenance of Skip Lists"
+,institution="Institute of Advanced Computer Science Studies, Department of Computer Science, University of Maryland"
+,address="College Park, Maryland"
+,year="1990"
+,number="CS-TR-2222.1"
+,month="June"
+}
+
+@Book{Adams91
+,Author="Gregory R. Adams"
+,title="Concurrent Programming, Principles, and Practices"
+,Publisher="Benjamin Cummins"
+,Year="1991"
+}
+
+@unpublished{Jacobson93
+,author="Van Jacobson"
+,title="Avoid Read-Side Locking Via Delayed Free"
+,year="1993"
+,month="September"
+,note="Verbal discussion"
+}
+
+@Conference{AjuJohn95
+,Author="Aju John"
+,Title="Dynamic vnodes -- Design and Implementation"
+,Booktitle="{USENIX Winter 1995}"
+,Publisher="USENIX Association"
+,Month="January"
+,Year="1995"
+,pages="11-23"
+,Address="New Orleans, LA"
+}
+
+@techreport{Slingwine95
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Apparatus and Method for Achieving Reduced Overhead Mutual
+Exclusion and Maintaining Coherency in a Multiprocessor System
+Utilizing Execution History and Thread Monitoring"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1995"
+,number="US Patent 5,442,758 (contributed under GPL)"
+,month="August"
+}
+
+@techreport{Slingwine97
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Method for maintaining data coherency using thread
+activity summaries in a multicomputer system"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1997"
+,number="US Patent 5,608,893 (contributed under GPL)"
+,month="March"
+}
+
+@techreport{Slingwine98
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Apparatus and method for achieving reduced overhead
+mutual exclusion and maintaining coherency in a multiprocessor
+system utilizing execution history and thread monitoring"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1998"
+,number="US Patent 5,727,209 (contributed under GPL)"
+,month="March"
+}
+
+@Conference{McKenney98
+,Author="Paul E. McKenney and John D. Slingwine"
+,Title="Read-Copy Update: Using Execution History to Solve Concurrency
+Problems"
+,Booktitle="{Parallel and Distributed Computing and Systems}"
+,Month="October"
+,Year="1998"
+,pages="509-518"
+,Address="Las Vegas, NV"
+}
+
+@Conference{Gamsa99
+,Author="Ben Gamsa and Orran Krieger and Jonathan Appavoo and Michael Stumm"
+,Title="Tornado: Maximizing Locality and Concurrency in a Shared Memory
+Multiprocessor Operating System"
+,Booktitle="{Proceedings of the 3\textsuperscript{rd} Symposium on
+Operating System Design and Implementation}"
+,Month="February"
+,Year="1999"
+,pages="87-100"
+,Address="New Orleans, LA"
+}
+
+@techreport{Slingwine01
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Apparatus and method for achieving reduced overhead
+mutual exclusion and maintaining coherency in a multiprocessor
+system utilizing execution history and thread monitoring"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="2001"
+,number="US Patent 5,219,690 (contributed under GPL)"
+,month="April"
+}
+
+@Conference{McKenney01a
+,Author="Paul E. McKenney and Jonathan Appavoo and Andi Kleen and
+Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
+,Title="Read-Copy Update"
+,Booktitle="{Ottawa Linux Symposium}"
+,Month="July"
+,Year="2001"
+,note="Available:
+\url{http://www.linuxsymposium.org/2001/abstracts/readcopy.php}
+\url{http://www.rdrop.com/users/paulmck/rclock/rclock_OLS.2001.05.01c.pdf}
+[Viewed June 23, 2004]"
+annotation="
+Described RCU, and presented some patches implementing and using it in
+the Linux kernel.
+"
+}
+
+@Conference{Linder02a
+,Author="Hanna Linder and Dipankar Sarma and Maneesh Soni"
+,Title="Scalability of the Directory Entry Cache"
+,Booktitle="{Ottawa Linux Symposium}"
+,Month="June"
+,Year="2002"
+,pages="289-300"
+}
+
+@Conference{McKenney02a
+,Author="Paul E. McKenney and Dipankar Sarma and
+Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
+,Title="Read-Copy Update"
+,Booktitle="{Ottawa Linux Symposium}"
+,Month="June"
+,Year="2002"
+,pages="338-367"
+,note="Available:
+\url{http://www.linux.org.uk/~ajh/ols2002_proceedings.pdf.gz}
+[Viewed June 23, 2004]"
+}
+
+@article{Appavoo03a
+,author="J. Appavoo and K. Hui and C. A. N. Soules and R. W. Wisniewski and
+D. M. {Da Silva} and O. Krieger and M. A. Auslander and D. J. Edelsohn and
+B. Gamsa and G. R. Ganger and P. McKenney and M. Ostrowski and
+B. Rosenburg and M. Stumm and J. Xenidis"
+,title="Enabling Autonomic Behavior in Systems Software With Hot Swapping"
+,Year="2003"
+,Month="January"
+,journal="IBM Systems Journal"
+,volume="42"
+,number="1"
+,pages="60-76"
+}
+
+@Conference{Arcangeli03
+,Author="Andrea Arcangeli and Mingming Cao and Paul E. McKenney and
+Dipankar Sarma"
+,Title="Using Read-Copy Update Techniques for {System V IPC} in the
+{Linux} 2.5 Kernel"
+,Booktitle="Proceedings of the 2003 USENIX Annual Technical Conference
+(FREENIX Track)"
+,Publisher="USENIX Association"
+,year="2003"
+,month="June"
+,pages="297-310"
+}
+
+@article{McKenney03a
+,author="Paul E. McKenney"
+,title="Using {RCU} in the {Linux} 2.5 Kernel"
+,Year="2003"
+,Month="October"
+,journal="Linux Journal"
+,volume="1"
+,number="114"
+,pages="18-26"
+}
+
+@article{McKenney04a
+,author="Paul E. McKenney and Dipankar Sarma and Maneesh Soni"
+,title="Scaling dcache with {RCU}"
+,Year="2004"
+,Month="January"
+,journal="Linux Journal"
+,volume="1"
+,number="118"
+,pages="38-46"
+}
+
+@Conference{McKenney04b
+,Author="Paul E. McKenney"
+,Title="{RCU} vs. Locking Performance on Different {CPUs}"
+,Booktitle="{linux.conf.au}"
+,Month="January"
+,Year="2004"
+,Address="Adelaide, Australia"
+,note="Available:
+\url{http://www.linux.org.au/conf/2004/abstracts.html#90}
+\url{http://www.rdrop.com/users/paulmck/rclock/lockperf.2004.01.17a.pdf}
+[Viewed June 23, 2004]"
+}
+
+@phdthesis{PaulEdwardMcKenneyPhD
+,author="Paul E. McKenney"
+,title="Exploiting Deferred Destruction:
+An Analysis of Read-Copy-Update Techniques
+in Operating System Kernels"
+,school="OGI School of Science and Engineering at
+Oregon Health and Sciences University"
+,year="2004"
+}
+
+@Conference{Sarma04c
+,Author="Dipankar Sarma and Paul E. McKenney"
+,Title="Making RCU Safe for Deep Sub-Millisecond Response Realtime Applications"
+,Booktitle="Proceedings of the 2004 USENIX Annual Technical Conference
+(FREENIX Track)"
+,Publisher="USENIX Association"
+,year="2004"
+,month="June"
+,pages="182-191"
+}
diff --git a/Documentation/RCU/UP.txt b/Documentation/RCU/UP.txt
new file mode 100644 (file)
index 0000000..551a803
--- /dev/null
@@ -0,0 +1,64 @@
+RCU on Uniprocessor Systems
+
+
+A common misconception is that, on UP systems, the call_rcu() primitive
+may immediately invoke its function, and that the synchronize_kernel
+primitive may return immediately.  The basis of this misconception
+is that since there is only one CPU, it should not be necessary to
+wait for anything else to get done, since there are no other CPUs for
+anything else to be happening on.  Although this approach will sort of
+work a surprising amount of the time, it is a very bad idea in general.
+This document presents two examples that demonstrate exactly how bad an
+idea this is.
+
+
+Example 1: softirq Suicide
+
+Suppose that an RCU-based algorithm scans a linked list containing
+elements A, B, and C in process context, and can delete elements from
+this same list in softirq context.  Suppose that the process-context scan
+is referencing element B when it is interrupted by softirq processing,
+which deletes element B, and then invokes call_rcu() to free element B
+after a grace period.
+
+Now, if call_rcu() were to directly invoke its arguments, then upon return
+from softirq, the list scan would find itself referencing a newly freed
+element B.  This situation can greatly decrease the life expectancy of
+your kernel.
+
+
+Example 2: Function-Call Fatality
+
+Of course, one could avert the suicide described in the preceding example
+by having call_rcu() directly invoke its arguments only if it was called
+from process context.  However, this can fail in a similar manner.
+
+Suppose that an RCU-based algorithm again scans a linked list containing
+elements A, B, and C in process contexts, but that it invokes a function
+on each element as it is scanned.  Suppose further that this function
+deletes element B from the list, then passes it to call_rcu() for deferred
+freeing.  This may be a bit unconventional, but it is perfectly legal
+RCU usage, since call_rcu() must wait for a grace period to elapse.
+Therefore, in this case, allowing call_rcu() to immediately invoke
+its arguments would cause it to fail to make the fundamental guarantee
+underlying RCU, namely that call_rcu() defers invoking its arguments until
+all RCU read-side critical sections currently executing have completed.
+
+Quick Quiz: why is it -not- legal to invoke synchronize_kernel() in
+this case?
+
+
+Summary
+
+Permitting call_rcu() to immediately invoke its arguments or permitting
+synchronize_kernel() to immediately return breaks RCU, even on a UP system.
+So do not do it!  Even on a UP system, the RCU infrastructure -must-
+respect grace periods.
+
+
+Answer to Quick Quiz
+
+The calling function is scanning an RCU-protected linked list, and
+is therefore within an RCU read-side critical section.  Therefore,
+the called function has been invoked within an RCU read-side critical
+section, and is not permitted to block.
diff --git a/Documentation/RCU/arrayRCU.txt b/Documentation/RCU/arrayRCU.txt
new file mode 100644 (file)
index 0000000..453ebe6
--- /dev/null
@@ -0,0 +1,141 @@
+Using RCU to Protect Read-Mostly Arrays
+
+
+Although RCU is more commonly used to protect linked lists, it can
+also be used to protect arrays.  Three situations are as follows:
+
+1.  Hash Tables
+
+2.  Static Arrays
+
+3.  Resizeable Arrays
+
+Each of these situations are discussed below.
+
+
+Situation 1: Hash Tables
+
+Hash tables are often implemented as an array, where each array entry
+has a linked-list hash chain.  Each hash chain can be protected by RCU
+as described in the listRCU.txt document.  This approach also applies
+to other array-of-list situations, such as radix trees.
+
+
+Situation 2: Static Arrays
+
+Static arrays, where the data (rather than a pointer to the data) is
+located in each array element, and where the array is never resized,
+have not been used with RCU.  Rik van Riel recommends using seqlock in
+this situation, which would also have minimal read-side overhead as long
+as updates are rare.
+
+Quick Quiz:  Why is it so important that updates be rare when
+            using seqlock?
+
+
+Situation 3: Resizeable Arrays
+
+Use of RCU for resizeable arrays is demonstrated by the grow_ary()
+function used by the System V IPC code.  The array is used to map from
+semaphore, message-queue, and shared-memory IDs to the data structure
+that represents the corresponding IPC construct.  The grow_ary()
+function does not acquire any locks; instead its caller must hold the
+ids->sem semaphore.
+
+The grow_ary() function, shown below, does some limit checks, allocates a
+new ipc_id_ary, copies the old to the new portion of the new, initializes
+the remainder of the new, updates the ids->entries pointer to point to
+the new array, and invokes ipc_rcu_putref() to free up the old array.
+Note that rcu_assign_pointer() is used to update the ids->entries pointer,
+which includes any memory barriers required on whatever architecture
+you are running on.
+
+       static int grow_ary(struct ipc_ids* ids, int newsize)
+       {
+               struct ipc_id_ary* new;
+               struct ipc_id_ary* old;
+               int i;
+               int size = ids->entries->size;
+
+               if(newsize > IPCMNI)
+                       newsize = IPCMNI;
+               if(newsize <= size)
+                       return newsize;
+
+               new = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*newsize +
+                                   sizeof(struct ipc_id_ary));
+               if(new == NULL)
+                       return size;
+               new->size = newsize;
+               memcpy(new->p, ids->entries->p,
+                      sizeof(struct kern_ipc_perm *)*size +
+                      sizeof(struct ipc_id_ary));
+               for(i=size;i<newsize;i++) {
+                       new->p[i] = NULL;
+               }
+               old = ids->entries;
+
+               /*
+                * Use rcu_assign_pointer() to make sure the memcpyed
+                * contents of the new array are visible before the new
+                * array becomes visible.
+                */
+               rcu_assign_pointer(ids->entries, new);
+
+               ipc_rcu_putref(old);
+               return newsize;
+       }
+
+The ipc_rcu_putref() function decrements the array's reference count
+and then, if the reference count has dropped to zero, uses call_rcu()
+to free the array after a grace period has elapsed.
+
+The array is traversed by the ipc_lock() function.  This function
+indexes into the array under the protection of rcu_read_lock(),
+using rcu_dereference() to pick up the pointer to the array so
+that it may later safely be dereferenced -- memory barriers are
+required on the Alpha CPU.  Since the size of the array is stored
+with the array itself, there can be no array-size mismatches, so
+a simple check suffices.  The pointer to the structure corresponding
+to the desired IPC object is placed in "out", with NULL indicating
+a non-existent entry.  After acquiring "out->lock", the "out->deleted"
+flag indicates whether the IPC object is in the process of being
+deleted, and, if not, the pointer is returned.
+
+       struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
+       {
+               struct kern_ipc_perm* out;
+               int lid = id % SEQ_MULTIPLIER;
+               struct ipc_id_ary* entries;
+
+               rcu_read_lock();
+               entries = rcu_dereference(ids->entries);
+               if(lid >= entries->size) {
+                       rcu_read_unlock();
+                       return NULL;
+               }
+               out = entries->p[lid];
+               if(out == NULL) {
+                       rcu_read_unlock();
+                       return NULL;
+               }
+               spin_lock(&out->lock);
+
+               /* ipc_rmid() may have already freed the ID while ipc_lock
+                * was spinning: here verify that the structure is still valid
+                */
+               if (out->deleted) {
+                       spin_unlock(&out->lock);
+                       rcu_read_unlock();
+                       return NULL;
+               }
+               return out;
+       }
+
+
+Answer to Quick Quiz:
+
+       The reason that it is important that updates be rare when
+       using seqlock is that frequent updates can livelock readers.
+       One way to avoid this problem is to assign a seqlock for
+       each array entry rather than to the entire array.
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
new file mode 100644 (file)
index 0000000..b3a568a
--- /dev/null
@@ -0,0 +1,157 @@
+Review Checklist for RCU Patches
+
+
+This document contains a checklist for producing and reviewing patches
+that make use of RCU.  Violating any of the rules listed below will
+result in the same sorts of problems that leaving out a locking primitive
+would cause.  This list is based on experiences reviewing such patches
+over a rather long period of time, but improvements are always welcome!
+
+0.     Is RCU being applied to a read-mostly situation?  If the data
+       structure is updated more than about 10% of the time, then
+       you should strongly consider some other approach, unless
+       detailed performance measurements show that RCU is nonetheless
+       the right tool for the job.
+
+       The other exception would be where performance is not an issue,
+       and RCU provides a simpler implementation.  An example of this
+       situation is the dynamic NMI code in the Linux 2.6 kernel,
+       at least on architectures where NMIs are rare.
+
+1.     Does the update code have proper mutual exclusion?
+
+       RCU does allow -readers- to run (almost) naked, but -writers- must
+       still use some sort of mutual exclusion, such as:
+
+       a.      locking,
+       b.      atomic operations, or
+       c.      restricting updates to a single task.
+
+       If you choose #b, be prepared to describe how you have handled
+       memory barriers on weakly ordered machines (pretty much all of
+       them -- even x86 allows reads to be reordered), and be prepared
+       to explain why this added complexity is worthwhile.  If you
+       choose #c, be prepared to explain how this single task does not
+       become a major bottleneck on big multiprocessor machines.
+
+2.     Do the RCU read-side critical sections make proper use of
+       rcu_read_lock() and friends?  These primitives are needed
+       to suppress preemption (or bottom halves, in the case of
+       rcu_read_lock_bh()) in the read-side critical sections,
+       and are also an excellent aid to readability.
+
+3.     Does the update code tolerate concurrent accesses?
+
+       The whole point of RCU is to permit readers to run without
+       any locks or atomic operations.  This means that readers will
+       be running while updates are in progress.  There are a number
+       of ways to handle this concurrency, depending on the situation:
+
+       a.      Make updates appear atomic to readers.  For example,
+               pointer updates to properly aligned fields will appear
+               atomic, as will individual atomic primitives.  Operations
+               performed under a lock and sequences of multiple atomic
+               primitives will -not- appear to be atomic.
+
+               This is almost always the best approach.
+
+       b.      Carefully order the updates and the reads so that
+               readers see valid data at all phases of the update.
+               This is often more difficult than it sounds, especially
+               given modern CPUs' tendency to reorder memory references.
+               One must usually liberally sprinkle memory barriers
+               (smp_wmb(), smp_rmb(), smp_mb()) through the code,
+               making it difficult to understand and to test.
+
+               It is usually better to group the changing data into
+               a separate structure, so that the change may be made
+               to appear atomic by updating a pointer to reference
+               a new structure containing updated values.
+
+4.     Weakly ordered CPUs pose special challenges.  Almost all CPUs
+       are weakly ordered -- even i386 CPUs allow reads to be reordered.
+       RCU code must take all of the following measures to prevent
+       memory-corruption problems:
+
+       a.      Readers must maintain proper ordering of their memory
+               accesses.  The rcu_dereference() primitive ensures that
+               the CPU picks up the pointer before it picks up the data
+               that the pointer points to.  This really is necessary
+               on Alpha CPUs.  If you don't believe me, see:
+
+                       http://www.openvms.compaq.com/wizard/wiz_2637.html
+
+               The rcu_dereference() primitive is also an excellent
+               documentation aid, letting the person reading the code
+               know exactly which pointers are protected by RCU.
+
+               The rcu_dereference() primitive is used by the various
+               "_rcu()" list-traversal primitives, such as the
+               list_for_each_entry_rcu().
+
+       b.      If the list macros are being used, the list_del_rcu(),
+               list_add_tail_rcu(), and list_del_rcu() primitives must
+               be used in order to prevent weakly ordered machines from
+               misordering structure initialization and pointer planting.
+               Similarly, if the hlist macros are being used, the
+               hlist_del_rcu() and hlist_add_head_rcu() primitives
+               are required.
+
+       c.      Updates must ensure that initialization of a given
+               structure happens before pointers to that structure are
+               publicized.  Use the rcu_assign_pointer() primitive
+               when publicizing a pointer to a structure that can
+               be traversed by an RCU read-side critical section.
+
+               [The rcu_assign_pointer() primitive is in process.]
+
+5.     If call_rcu(), or a related primitive such as call_rcu_bh(),
+       is used, the callback function must be written to be called
+       from softirq context.  In particular, it cannot block.
+
+6.     Since synchronize_kernel() blocks, it cannot be called from
+       any sort of irq context.
+
+7.     If the updater uses call_rcu(), then the corresponding readers
+       must use rcu_read_lock() and rcu_read_unlock().  If the updater
+       uses call_rcu_bh(), then the corresponding readers must use
+       rcu_read_lock_bh() and rcu_read_unlock_bh().  Mixing things up
+       will result in confusion and broken kernels.
+
+       One exception to this rule: rcu_read_lock() and rcu_read_unlock()
+       may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
+       in cases where local bottom halves are already known to be
+       disabled, for example, in irq or softirq context.  Commenting
+       such cases is a must, of course!  And the jury is still out on
+       whether the increased speed is worth it.
+
+8.     Although synchronize_kernel() is a bit slower than is call_rcu(),
+       it usually results in simpler code.  So, unless update performance
+       is important or the updaters cannot block, synchronize_kernel()
+       should be used in preference to call_rcu().
+
+9.     All RCU list-traversal primitives, which include
+       list_for_each_rcu(), list_for_each_entry_rcu(),
+       list_for_each_continue_rcu(), and list_for_each_safe_rcu(),
+       must be within an RCU read-side critical section.  RCU
+       read-side critical sections are delimited by rcu_read_lock()
+       and rcu_read_unlock(), or by similar primitives such as
+       rcu_read_lock_bh() and rcu_read_unlock_bh().
+
+       Use of the _rcu() list-traversal primitives outside of an
+       RCU read-side critical section causes no harm other than
+       a slight performance degradation on Alpha CPUs and some
+       confusion on the part of people trying to read the code.
+
+       Another way of thinking of this is "If you are holding the
+       lock that prevents the data structure from changing, why do
+       you also need RCU-based protection?"  That said, there may
+       well be situations where use of the _rcu() list-traversal
+       primitives while the update-side lock is held results in
+       simpler and more maintainable code.  The jury is still out
+       on this question.
+
+10.    Conversely, if you are in an RCU read-side critical section,
+       you -must- use the "_rcu()" variants of the list macros.
+       Failing to do so will break Alpha and confuse people reading
+       your code.
diff --git a/Documentation/RCU/listRCU.txt b/Documentation/RCU/listRCU.txt
new file mode 100644 (file)
index 0000000..46950af
--- /dev/null
@@ -0,0 +1,307 @@
+Using RCU to Protect Read-Mostly Linked Lists
+
+
+One of the best applications of RCU is to protect read-mostly linked lists
+("struct list_head" in list.h).  One big advantage of this approach
+is that all of the required memory barriers are included for you in
+the list macros.  This document describes several applications of RCU,
+with the best fits first.
+
+
+Example 1: Read-Side Action Taken Outside of Lock, No In-Place Updates
+
+The best applications are cases where, if reader-writer locking were
+used, the read-side lock would be dropped before taking any action
+based on the results of the search.  The most celebrated example is
+the routing table.  Because the routing table is tracking the state of
+equipment outside of the computer, it will at times contain stale data.
+Therefore, once the route has been computed, there is no need to hold
+the routing table static during transmission of the packet.  After all,
+you can hold the routing table static all you want, but that won't keep
+the external Internet from changing, and it is the state of the external
+Internet that really matters.  In addition, routing entries are typically
+added or deleted, rather than being modified in place.
+
+A straightforward example of this use of RCU may be found in the
+system-call auditing support.  For example, a reader-writer locked
+implementation of audit_filter_task() might be as follows:
+
+       static enum audit_state audit_filter_task(struct task_struct *tsk)
+       {
+               struct audit_entry *e;
+               enum audit_state   state;
+
+               read_lock(&auditsc_lock);
+               list_for_each_entry(e, &audit_tsklist, list) {
+                       if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+                               read_unlock(&auditsc_lock);
+                               return state;
+                       }
+               }
+               read_unlock(&auditsc_lock);
+               return AUDIT_BUILD_CONTEXT;
+       }
+
+Here the list is searched under the lock, but the lock is dropped before
+the corresponding value is returned.  By the time that this value is acted
+on, the list may well have been modified.  This makes sense, since if
+you are turning auditing off, it is OK to audit a few extra system calls.
+
+This means that RCU can be easily applied to the read side, as follows:
+
+       static enum audit_state audit_filter_task(struct task_struct *tsk)
+       {
+               struct audit_entry *e;
+               enum audit_state   state;
+
+               rcu_read_lock();
+               list_for_each_entry_rcu(e, &audit_tsklist, list) {
+                       if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+                               rcu_read_unlock();
+                               return state;
+                       }
+               }
+               rcu_read_unlock();
+               return AUDIT_BUILD_CONTEXT;
+       }
+
+The read_lock() and read_unlock() calls have become rcu_read_lock()
+and rcu_read_unlock(), respectively, and the list_for_each_entry() has
+become list_for_each_entry_rcu().  The _rcu() list-traversal primitives
+insert the read-side memory barriers that are required on DEC Alpha CPUs.
+
+The changes to the update side are also straightforward.  A reader-writer
+lock might be used as follows for deletion and insertion:
+
+       static inline int audit_del_rule(struct audit_rule *rule,
+                                        struct list_head *list)
+       {
+               struct audit_entry  *e;
+
+               write_lock(&auditsc_lock);
+               list_for_each_entry(e, list, list) {
+                       if (!audit_compare_rule(rule, &e->rule)) {
+                               list_del(&e->list);
+                               call_rcu(&e->rcu, audit_free_rule, e);
+                               return 0;
+                       }
+               }
+               write_unlock(&auditsc_lock);
+               return -EFAULT;         /* No matching rule */
+       }
+
+       static inline int audit_add_rule(struct audit_entry *entry,
+                                        struct list_head *list)
+       {
+               write_lock(&auditsc_lock);
+               if (entry->rule.flags & AUDIT_PREPEND) {
+                       entry->rule.flags &= ~AUDIT_PREPEND;
+                       list_add(&entry->list, list);
+               } else {
+                       list_add_tail(&entry->list, list);
+               }
+               write_unlock(&auditsc_lock);
+               return 0;
+       }
+
+Following are the RCU equivalents for these two functions:
+
+       static inline int audit_del_rule(struct audit_rule *rule,
+                                        struct list_head *list)
+       {
+               struct audit_entry  *e;
+
+               /* Do not use the _rcu iterator here, since this is the only
+                * deletion routine. */
+               list_for_each_entry(e, list, list) {
+                       if (!audit_compare_rule(rule, &e->rule)) {
+                               list_del_rcu(&e->list);
+                               call_rcu(&e->rcu, audit_free_rule, e);
+                               return 0;
+                       }
+               }
+               return -EFAULT;         /* No matching rule */
+       }
+
+       static inline int audit_add_rule(struct audit_entry *entry,
+                                        struct list_head *list)
+       {
+               if (entry->rule.flags & AUDIT_PREPEND) {
+                       entry->rule.flags &= ~AUDIT_PREPEND;
+                       list_add_rcu(&entry->list, list);
+               } else {
+                       list_add_tail_rcu(&entry->list, list);
+               }
+               return 0;
+       }
+
+Normally, the write_lock() and write_unlock() would be replaced by
+a spin_lock() and a spin_unlock(), but in this case, all callers hold
+audit_netlink_sem, so no additional locking is required.  The auditsc_lock
+can therefore be eliminated, since use of RCU eliminates the need for
+writers to exclude readers.
+
+The list_del(), list_add(), and list_add_tail() primitives have been
+replaced by list_del_rcu(), list_add_rcu(), and list_add_tail_rcu().
+The _rcu() list-manipulation primitives add memory barriers that are
+needed on weakly ordered CPUs (most of them!).
+
+So, when readers can tolerate stale data and when entries are either added
+or deleted, without in-place modification, it is very easy to use RCU!
+
+
+Example 2: Handling In-Place Updates
+
+The system-call auditing code does not update auditing rules in place.
+However, if it did, reader-writer-locked code to do so might look as
+follows (presumably, the field_count is only permitted to decrease,
+otherwise, the added fields would need to be filled in):
+
+       static inline int audit_upd_rule(struct audit_rule *rule,
+                                        struct list_head *list,
+                                        __u32 newaction,
+                                        __u32 newfield_count)
+       {
+               struct audit_entry  *e;
+               struct audit_newentry *ne;
+
+               write_lock(&auditsc_lock);
+               list_for_each_entry(e, list, list) {
+                       if (!audit_compare_rule(rule, &e->rule)) {
+                               e->rule.action = newaction;
+                               e->rule.file_count = newfield_count;
+                               write_unlock(&auditsc_lock);
+                               return 0;
+                       }
+               }
+               write_unlock(&auditsc_lock);
+               return -EFAULT;         /* No matching rule */
+       }
+
+The RCU version creates a copy, updates the copy, then replaces the old
+entry with the newly updated entry.  This sequence of actions, allowing
+concurrent reads while doing a copy to perform an update, is what gives
+RCU ("read-copy update") its name.  The RCU code is as follows:
+
+       static inline int audit_upd_rule(struct audit_rule *rule,
+                                        struct list_head *list,
+                                        __u32 newaction,
+                                        __u32 newfield_count)
+       {
+               struct audit_entry  *e;
+               struct audit_newentry *ne;
+
+               list_for_each_entry(e, list, list) {
+                       if (!audit_compare_rule(rule, &e->rule)) {
+                               ne = kmalloc(sizeof(*entry), GFP_ATOMIC);
+                               if (ne == NULL)
+                                       return -ENOMEM;
+                               audit_copy_rule(&ne->rule, &e->rule);
+                               ne->rule.action = newaction;
+                               ne->rule.file_count = newfield_count;
+                               list_add_rcu(ne, e);
+                               list_del(e);
+                               call_rcu(&e->rcu, audit_free_rule, e);
+                               return 0;
+                       }
+               }
+               return -EFAULT;         /* No matching rule */
+       }
+
+Again, this assumes that the caller holds audit_netlink_sem.  Normally,
+the reader-writer lock would become a spinlock in this sort of code.
+
+
+Example 3: Eliminating Stale Data
+
+The auditing examples above tolerate stale data, as do most algorithms
+that are tracking external state.  Because there is a delay from the
+time the external state changes before Linux becomes aware of the change,
+additional RCU-induced staleness is normally not a problem.
+
+However, there are many examples where stale data cannot be tolerated.
+One example in the Linux kernel is the System V IPC (see the ipc_lock()
+function in ipc/util.c).  This code checks a "deleted" flag under a
+per-entry spinlock, and, if the "deleted" flag is set, pretends that the
+entry does not exist.  For this to be helpful, the search function must
+return holding the per-entry spinlock, as ipc_lock() does in fact do.
+
+Quick Quiz:  Why does the search function need to return holding the
+per-entry lock for this deleted-flag technique to be helpful?
+
+If the system-call audit module were to ever need to reject stale data,
+one way to accomplish this would be to add a "deleted" flag and a "lock"
+spinlock to the audit_entry structure, and modify audit_filter_task()
+as follows:
+
+       static enum audit_state audit_filter_task(struct task_struct *tsk)
+       {
+               struct audit_entry *e;
+               enum audit_state   state;
+
+               rcu_read_lock();
+               list_for_each_entry_rcu(e, &audit_tsklist, list) {
+                       if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+                               spin_lock(&e->lock);
+                               if (e->deleted) {
+                                       spin_unlock(&e->lock);
+                                       rcu_read_unlock();
+                                       return AUDIT_BUILD_CONTEXT;
+                               }
+                               rcu_read_unlock();
+                               return state;
+                       }
+               }
+               rcu_read_unlock();
+               return AUDIT_BUILD_CONTEXT;
+       }
+
+Note that this example assumes that entries are only added and deleted.
+Additional mechanism is required to deal correctly with the
+update-in-place performed by audit_upd_rule().  For one thing,
+audit_upd_rule() would need additional memory barriers to ensure
+that the list_add_rcu() was really executed before the list_del_rcu().
+
+The audit_del_rule() function would need to set the "deleted"
+flag under the spinlock as follows:
+
+       static inline int audit_del_rule(struct audit_rule *rule,
+                                        struct list_head *list)
+       {
+               struct audit_entry  *e;
+
+               /* Do not use the _rcu iterator here, since this is the only
+                * deletion routine. */
+               list_for_each_entry(e, list, list) {
+                       if (!audit_compare_rule(rule, &e->rule)) {
+                               spin_lock(&e->lock);
+                               list_del_rcu(&e->list);
+                               e->deleted = 1;
+                               spin_unlock(&e->lock);
+                               call_rcu(&e->rcu, audit_free_rule, e);
+                               return 0;
+                       }
+               }
+               return -EFAULT;         /* No matching rule */
+       }
+
+
+Summary
+
+Read-mostly list-based data structures that can tolerate stale data are
+the most amenable to use of RCU.  The simplest case is where entries are
+either added or deleted from the data structure (or atomically modified
+in place), but non-atomic in-place modifications can be handled by making
+a copy, updating the copy, then replacing the original with the copy.
+If stale data cannot be tolerated, then a "deleted" flag may be used
+in conjunction with a per-entry spinlock in order to allow the search
+function to reject newly deleted data.
+
+
+Answer to Quick Quiz
+
+If the search function drops the per-entry lock before returning, then
+the caller will be processing stale data in any case.  If it is really
+OK to be processing stale data, then you don't need a "deleted" flag.
+If processing stale data really is a problem, then you need to hold the
+per-entry lock across all of the code that uses the value looked up.
diff --git a/Documentation/RCU/rcu.txt b/Documentation/RCU/rcu.txt
new file mode 100644 (file)
index 0000000..7e0c2ab
--- /dev/null
@@ -0,0 +1,67 @@
+RCU Concepts
+
+
+The basic idea behind RCU (read-copy update) is to split destructive
+operations into two parts, one that prevents anyone from seeing the data
+item being destroyed, and one that actually carries out the destruction.
+A "grace period" must elapse between the two parts, and this grace period
+must be long enough that any readers accessing the item being deleted have
+since dropped their references.  For example, an RCU-protected deletion
+from a linked list would first remove the item from the list, wait for
+a grace period to elapse, then free the element.  See the listRCU.txt
+file for more information on using RCU with linked lists.
+
+
+Frequently Asked Questions
+
+o      Why would anyone want to use RCU?
+
+       The advantage of RCU's two-part approach is that RCU readers need
+       not acquire any locks, perform any atomic instructions, write to
+       shared memory, or (on CPUs other than Alpha) execute any memory
+       barriers.  The fact that these operations are quite expensive
+       on modern CPUs is what gives RCU its performance advantages
+       in read-mostly situations.  The fact that RCU readers need not
+       acquire locks can also greatly simplify deadlock-avoidance code.
+
+o      How can the updater tell when a grace period has completed
+       if the RCU readers give no indication when they are done?
+
+       Just as with spinlocks, RCU readers are not permitted to
+       block, switch to user-mode execution, or enter the idle loop.
+       Therefore, as soon as a CPU is seen passing through any of these
+       three states, we know that that CPU has exited any previous RCU
+       read-side critical sections.  So, if we remove an item from a
+       linked list, and then wait until all CPUs have switched context,
+       executed in user mode, or executed in the idle loop, we can
+       safely free up that item.
+
+o      If I am running on a uniprocessor kernel, which can only do one
+       thing at a time, why should I wait for a grace period?
+
+       See the UP.txt file in this directory.
+
+o      How can I see where RCU is currently used in the Linux kernel?
+
+       Search for "rcu_read_lock", "call_rcu", and "synchronize_kernel".
+
+o      What guidelines should I follow when writing code that uses RCU?
+
+       See the checklist.txt file in this directory.
+
+o      Why the name "RCU"?
+
+       "RCU" stands for "read-copy update".  The file listRCU.txt has
+       more information on where this name came from, search for
+       "read-copy update" to find it.
+
+o      I hear that RCU is patented?  What is with that?
+
+       Yes, it is.  There are several known patents related to RCU,
+       search for the string "Patent" in RTFP.txt to find them.
+       Of these, one was allowed to lapse by the assignee, and the
+       others have been contributed to the Linux kernel under GPL.
+
+o      Where can I find more information on RCU?
+
+       See the RTFP.txt file in this directory.
diff --git a/Documentation/arm/IXP2000 b/Documentation/arm/IXP2000
new file mode 100644 (file)
index 0000000..48ba502
--- /dev/null
@@ -0,0 +1,69 @@
+
+-------------------------------------------------------------------------
+Release Notes for Linux on Intel's IXP2000 Network Processor
+
+Maintained by Deepak Saxena <dsaxena@plexity.net>
+-------------------------------------------------------------------------
+
+1. Overview
+
+Intel's IXP2000 family of NPUs (IXP2400, IXP2800, IXP2850) is designed
+for high-performance network applications such high-availability
+telecom systems. In addition to an XScale core, it contains up to 8
+"MicroEngines" that run special code, several high-end networking 
+interfaces (UTOPIA, SPI, etc), a PCI host bridge, one serial port,
+flash interface, and some other odds and ends. For more information, see:
+
+http://developer.intel.com/design/network/products/npfamily/ixp2xxx.htm
+
+2. Linux Support
+
+Linux currently supports the following features on the IXP2000 NPUS:
+
+- On-chip serial
+- PCI
+- Flash (MTD/JFFS2)
+- I2C through GPIO
+- Timers (watchdog, OS)
+
+That is about all we can support under Linux ATM b/c the core networking
+components of the chip are accessed via Intel's closed source SDK. 
+Please contact Intel directly on issues with using those. There is
+also a mailing list run by some folks at Princeton University that might
+be of helpful:  https://lists.cs.princeton.edu/mailman/listinfo/ixp2xxx
+
+WHATEVER YOU DO, DO NOT POST EMAIL TO THE LINUX-ARM OR LINUX-ARM-KERNEL
+MAILINNG LISTS REGARDING THE INTEL SDK.
+
+3. Supported Platforms
+
+- Intel IXDP2400 Reference Platform
+- Intel IXDP2800 Reference Platform
+- Intel IXDP2401 Reference Platform
+- Intel IXDP2801 Reference Platform
+- RadiSys ENP-2611
+
+4. Usage Notes
+
+- The IXP2000 platforms ususally have rather complex PCI bus topologies
+  with large memory space requirements. In addition, b/c of the way the
+  Intel SDK is designed, devices are enumerated in a vert specific
+  way. B/c of this this, we use "pci=firmware" option in the kernel
+  command line so that we do not re-enumerate the bus.
+
+- IXDP2x01 systems have variable clock tick rates that we cannot determine 
+  via HW registers. The "ixdp2x01_clk=XXX" cmd line options allows you
+  to pass the clock rate to the board port.
+
+5. Thanks
+
+The IXP2000 work has been funded by Intel Corp. and MontaVista Software, Inc.
+
+The following people have contributed patches/comments/etc:
+
+Naeem F. Afzal
+Lennert Buytenhek
+Jeffrey Daly
+
+-------------------------------------------------------------------------
+Last Update: 8/09/2004
diff --git a/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt b/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt
new file mode 100644 (file)
index 0000000..831b98c
--- /dev/null
@@ -0,0 +1,44 @@
+               Simtec Electronics EB2410ITX (BAST)
+               ===================================
+
+       http://www.simtec.co.uk/products/EB2410ITX/
+
+Introduction
+------------
+
+  The EB2410ITX is a S3C2410 based development board with a variety of
+  peripherals and expansion connectors. This board is also known by
+  the shortened name of Bast.
+
+
+Configuration
+-------------
+
+  To set the default configuration, use `make bast_defconfig` which
+  supports the commonly used features of this board
+
+
+Support
+-------
+
+  Official support information can be found on the Simtec Electronics
+  website, at the product page http://www.simtec.co.uk/products/EB2410ITX/
+  and http://www.simtec.co.uk/products/EB2410ITX/resources.html
+
+
+MTD
+---
+
+  The NAND and NOR onboard are currently supported in the linux-mtd cvs,
+  and are awaiting merge in the mainline. see the linux-mtd project at
+  http://www.linux-mtd.infradead.org/ for more information.
+
+
+IDE
+---
+
+  Both onboard IDE ports are supported, however there is no support for
+  changing speed of devices, PIO Mode 4 capable drives should be used.
+
+
+(c) 2004 Ben Dooks, Simtec Electronics
diff --git a/Documentation/arm/Samsung-S3C24XX/GPIO.txt b/Documentation/arm/Samsung-S3C24XX/GPIO.txt
new file mode 100644 (file)
index 0000000..0822764
--- /dev/null
@@ -0,0 +1,122 @@
+                       S3C2410 GPIO Control
+                       ====================
+
+Introduction
+------------
+
+  The s3c2410 kernel provides an interface to configure and
+  manipulate the state of the GPIO pins, and find out other
+  information about them.
+
+  There are a number of conditions attached to the configuration
+  of the s3c2410 GPIO system, please read the Samsung provided
+  data-sheet/users manual to find out the complete list.
+
+
+Headers
+-------
+
+  See include/asm-arm/arch-s3c2410/regs-gpio.h for the list
+  of GPIO pins, and the configuration values for them. This
+  is included by using #include <asm/arch/regs-gpio.h>
+
+  The GPIO management functions are defined in the hardware
+  header include/asm-arm/arch-s3c2410/hardware.h which can be
+  included by #include <asm/arch/hardware.h>
+
+  A useful ammount of documentation can be found in the hardware
+  header on how the GPIO functions (and others) work.
+
+  Whilst a number of these functions do make some checks on what
+  is passed to them, for speed of use, they may not always ensure
+  that the user supplied data to them is correct.
+
+
+PIN Numbers
+-----------
+
+  Each pin has an unique number associated with it in regs-gpio.h,
+  eg S3C2410_GPA0 or S3C2410_GPF1. These defines are used to tell
+  the GPIO functions which pin is to be used.
+
+
+Configuring a pin
+-----------------
+
+  The following function allows the configuration of a given pin to
+  be changed.
+
+    void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
+
+  Eg:
+
+     s3c2410_gpio_cfgpin(S3C2410_GPA0, S3C2410_GPA0_ADDR0);
+     s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
+
+   which would turn GPA0 into the lowest Address line A0, and set
+   GPE8 to be connected to the SDIO/MMC controller's SDDAT1 line.
+
+
+Reading the current configuration
+---------------------------------
+
+  The current configuration of a pin can be read by using:
+
+  s3c2410_gpio_getcfg(unsigned int pin);
+
+  The return value will be from the same set of values which can be
+  passed to s3c2410_gpio_cfgpin().
+
+
+Configuring a pull-up resistor
+------------------------------
+
+  A large proportion of the GPIO pins on the S3C2410 can have weak
+  pull-up resistors enabled. This can be configured by the following
+  function:
+
+    void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
+
+  Where the to value is zero to set the pull-up off, and 1 to enable
+  the specified pull-up. Any other values are currently undefined.
+
+
+Getting the state of a PIN
+--------------------------
+
+  The state of a pin can be read by using the function:
+
+    unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+  This will return either zero or non-zero. Do not count on this
+  function returning 1 if the pin is set.
+
+
+Setting the state of a PIN
+--------------------------
+
+  The value an pin is outputing can be modified by using the following:
+
+    void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
+
+  Which sets the given pin to the value. Use 0 to write 0, and 1 to
+  set the output to 1.
+
+
+Getting the IRQ number associated with a PIN
+--------------------------------------------
+
+  The following function can map the given pin number to an IRQ
+  number to pass to the IRQ system.
+
+   int s3c2410_gpio_getirq(unsigned int pin);
+
+  Note, not all pins have an IRQ.
+
+
+Authour
+-------
+
+
+Ben Dooks, 03 October 2004
+(c) 2004 Ben Dooks, Simtec Electronics
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
new file mode 100644 (file)
index 0000000..aa3f83a
--- /dev/null
@@ -0,0 +1,97 @@
+                       S3C24XX ARM Linux Overview
+                       ==========================
+
+
+
+Introduction
+------------
+
+  The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
+  by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 is
+  the only supported CPU in this range.
+
+
+Configuration
+-------------
+
+  A generic S3C2410 configuration is provided, and can be used as the
+  default by `make s3c2410_defconfig`. This configuration has support
+  for all the machines, and the commonly used features on them.
+
+  Certain machines may have their own default configurations as well,
+  please check the machine specific documentation.
+
+
+Machines
+--------
+
+  The currently supported machines are as follows:
+
+  Simtec Electronics EB2410ITX (BAST)
+
+    A general purpose development board, see EB2410ITX.txt for further
+    details
+
+  Samsung SMDK2410
+
+    Samsung's own development board, geared for PDA work.
+
+  Thorcom VR1000
+
+    Custom embedded board
+
+  HP IPAQ 1940
+
+    Handheld (IPAQ), available in several varieties
+
+
+NAND
+----
+
+  The current kernels do not have direct support for the NAND
+  controller, the latest linux-mtd CVS has support for this.
+  See http://www.linux-mtd.infradead.org/
+
+
+Serial
+------
+
+  The s3c2410 serial driver provides support for the internal
+  serial ports. These devices appear as /dev/ttySAC0 through 3.
+
+  To create device nodes for these, use the following commands
+
+    mknod ttySAC0 c 204 64
+    mknod ttySAC1 c 204 65
+    mknod ttySAC2 c 204 66
+
+
+GPIO
+----
+
+  The core contains support for manipulating the GPIO, see the
+  documentation in GPIO.txt in the same directory as this file.
+
+
+Clock Management
+----------------
+
+  The core provides the interface defined in the header file
+  include/asm-arm/hardware/clock.h, to allow control over the
+  various clock units
+
+
+Port Contributors
+-----------------
+
+  Ben Dooks
+  Vincent Sanders
+  Herbert Potzl
+  Arnaud Patard
+  Roc Wu
+
+
+Document Author
+---------------
+
+Ben Dooks, (c) 2004 Simtec Electronics
index 1df474c..62778c5 100644 (file)
@@ -227,6 +227,10 @@ TEA/XTEA algorithm contributors:
 Khazad algorithm contributors:
   Aaron Grothe
 
+Whirlpool algorithm contributors:
+  Aaron Grothe
+  Jean-Luc Cooke
+
 Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
 
 Please send any credits updates or corrections to:
index 70685dd..dd62c7b 100644 (file)
@@ -5,20 +5,21 @@ Definition
 ~~~~~~~~~~
 
 struct bus_type {
-        char                    * name;
-        rwlock_t                lock;
-        atomic_t                refcount;
+       char                    * name;
 
-        struct list_head        node;
-        struct list_head        devices;
-        struct list_head        drivers;
+       struct subsystem        subsys;
+       struct kset             drivers;
+       struct kset             devices;
 
-        struct driver_dir_entry dir;
-        struct driver_dir_entry device_dir;
-        struct driver_dir_entry driver_dir;
+       struct bus_attribute    * bus_attrs;
+       struct device_attribute * dev_attrs;
+       struct driver_attribute * drv_attrs;
 
-        int     (*match)        (struct device * dev, struct device_driver * drv);
-       struct device (*add)    (struct device * parent, char * bus_id);
+       int             (*match)(struct device * dev, struct device_driver * drv);
+       int             (*hotplug) (struct device *dev, char **envp, 
+                                   int num_envp, char *buffer, int buffer_size);
+       int             (*suspend)(struct device * dev, u32 state);
+       int             (*resume)(struct device * dev);
 };
 
 int bus_register(struct bus_type * bus);
@@ -47,7 +48,7 @@ Registration
 When a bus driver is initialized, it calls bus_register. This
 initializes the rest of the fields in the bus object and inserts it
 into a global list of bus types. Once the bus object is registered, 
-the fields in it (e.g. the rwlock_t) are usable by the bus driver. 
+the fields in it are usable by the bus driver. 
 
 
 Callbacks
@@ -71,40 +72,6 @@ When a driver is registered with the bus, the bus's list of devices is
 iterated over, and the match callback is called for each device that
 does not have a driver associated with it. 
 
-add(): Adding a child device
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The add callback is available to notify the bus about a child device
-at a particular location. 
-
-The parent parameter is the parent device of the child to be added. If
-parent == NULL, the bus should add the device as a child of a default
-parent device or as a child of the root. This policy decision is up to
-the bus driver.
-
-The format of the bus_id field should be consistent with the format of
-the bus_id field of the rest of the devices on the bus. This requires
-the caller to know the format.
-
-On return, the bus driver should return a pointer to the device that
-was created. If the device was not created, the bus driver should
-return an appropriate error code. Refer to include/linux/err.h for
-helper functions to encode errors. Some sample code:
-
-struct device * pci_bus_add(struct device * parent, char * bus_id)
-{
-       ...
-       /* the device already exists */
-       return ERR_PTR(-EEXIST);
-       ...
-}
-
-The caller can check the return value using IS_ERR():
-
-    struct device * newdev = pci_bus_type.add(parent,bus_id);
-    if (IS_ERR(newdev)) {
-       ...
-    }
 
 
 Device and Driver Lists
@@ -118,10 +85,11 @@ necessary.
 
 The LDM core provides helper functions for iterating over each list.
 
-int bus_for_each_dev(struct bus_type * bus, void * data, 
-                    int (*callback)(struct device * dev, void * data));
-int bus_for_each_drv(struct bus_type * bus, void * data,
-                    int (*callback)(struct device_driver * drv, void * data));
+int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,
+                    int (*fn)(struct device *, void *));
+
+int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, 
+                    void * data, int (*fn)(struct device_driver *, void *));
 
 These helpers iterate over the respective list, and call the callback
 for each device or driver in the list. All list accesses are
@@ -168,9 +136,9 @@ hierarchy:
 Exporting Attributes
 ~~~~~~~~~~~~~~~~~~~~
 struct bus_attribute {
-        struct attribute        attr;
-        ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t off);
-        ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off);
+       struct attribute        attr;
+       ssize_t (*show)(struct bus_type *, char * buf);
+       ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
 };
 
 Bus drivers can export attributes using the BUS_ATTR macro that works
index 1c465ed..f1c2cee 100644 (file)
@@ -90,7 +90,7 @@ prototypes:
        void (*destroy_inode)(struct inode *);
        void (*read_inode) (struct inode *);
        void (*dirty_inode) (struct inode *);
-       void (*write_inode) (struct inode *, int);
+       int (*write_inode) (struct inode *, int);
        void (*put_inode) (struct inode *);
        void (*drop_inode) (struct inode *);
        void (*delete_inode) (struct inode *);
@@ -276,21 +276,34 @@ foo_get_block(). It's an overkill, since block bitmaps can be protected by
 internal fs locking and real critical areas are much smaller than the areas
 filesystems protect now.
 
---------------------------- file_lock ------------------------------------
+----------------------- file_lock_operations ------------------------------
 prototypes:
-       void (*fl_notify)(struct file_lock *);  /* unblock callback */
        void (*fl_insert)(struct file_lock *);  /* lock insertion callback */
        void (*fl_remove)(struct file_lock *);  /* lock removal callback */
+       void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
+       void (*fl_release_private)(struct file_lock *);
+
 
 locking rules:
-               BKL     may block
-fl_notify:     yes     no
-fl_insert:     yes     no
-fl_remove:     yes     no
+                       BKL     may block
+fl_insert:             yes     no
+fl_remove:             yes     no
+fl_copy_lock:          yes     no
+fl_release_private:    yes     yes
+
+----------------------- lock_manager_operations ---------------------------
+prototypes:
+       int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
+       void (*fl_notify)(struct file_lock *);  /* unblock callback */
+
+locking rules:
+                       BKL     may block
+fl_compare_owner:      yes     no
+fl_notify:             yes     no
+
        Currently only NLM provides instances of this class. None of the
 them block. If you have out-of-tree instances - please, show up. Locking
 in that area will change.
-
 --------------------------- buffer_head -----------------------------------
 prototypes:
        void (*b_end_io)(struct buffer_head *bh, int uptodate);
index 02968c5..23a4d98 100644 (file)
@@ -17,6 +17,33 @@ Defaults are marked with (*).
 bsddf                  (*)     Makes `df' act like BSD.
 minixdf                                Makes `df' act like Minix.
 
+barrier=1                      This enables/disables barriers. barrier=0 disables it,
+                               barrier=1 enables it.
+
+orlov                  (*)     This enables the new Orlov block allocator. It's
+                               enabled by default.
+
+oldalloc                       This disables the Orlov block allocator and
+                               enables the old block allocator. Orlov should
+                               have better performance, we'd like to get some
+                               feedback  if it's the contrary for you.
+
+user_xattr             (*)     Enables POSIX Extended Attributes. It's enabled by
+                               default, however you need to confifure its support
+                               (CONFIG_EXT2_FS_XATTR). This is neccesary if you want
+                               to use POSIX Acces Control Lists support. You can visit
+                               http://acl.bestbits.at to know more about POSIX Extended
+                               attributes.
+
+nouser_xattr                   Disables POSIX Extended Attributes.
+
+acl                    (*)     Enables POSIX Access Control Lists support. This is
+                               enabled by default, however you need to configure
+                               its support (CONFIG_EXT2_FS_POSIX_ACL). If you want
+                               to know more about ACLs visit http://acl.bestbits.at
+
+noacl                          This option disables POSIX Access Control List support.
+
 check=none, nocheck    (*)     Don't do extra checking of bitmaps on mount
                                (check=normal and check=strict options removed)
 
@@ -336,9 +363,8 @@ and are copied into the filesystem.  If a transaction is incomplete at
 the time of the crash, then there is no guarantee of consistency for
 the blocks in that transaction so they are discarded (which means any
 filesystem changes they represent are also lost).
-
-The ext3 code is currently (Apr 2001) available for 2.2 kernels only,
-and not yet available for 2.4 kernels.
+Check Documentation/filesystems/ext3.txt if you want to read more about
+ext3 and journaling.
 
 References
 ==========
@@ -349,8 +375,6 @@ Design & Implementation     http://e2fsprogs.sourceforge.net/ext2intro.html
 Journaling (ext3)      ftp://ftp.uk.linux.org/pub/linux/sct/fs/jfs/
 Hashed Directories     http://kernelnewbies.org/~phillips/htree/
 Filesystem Resizing    http://ext2resize.sourceforge.net/
-Extended Attributes &
-Access Control Lists   http://acl.bestbits.at/
 Compression (*)                http://www.netspace.net.au/~reiter/e2compr/
 
 Implementations for:
index ff220af..9ab7f44 100644 (file)
@@ -22,6 +22,63 @@ journal=inum         When a journal already exists, this option is
                        the inode which will represent the ext3 file
                        system's journal file.
 
+noload                 Don't load the journal on mounting.
+
+data=journal           All data are committed into the journal prior
+                       to being written into the main file system.
+
+data=ordered   (*)     All data are forced directly out to the main file
+                       system prior to its metadata being committed to
+                       the journal.
+
+data=writeback         Data ordering is not preserved, data may be
+                       written into the main file system after its
+                       metadata has been committed to the journal.
+
+commit=nrsec   (*)     Ext3 can be told to sync all its data and metadata
+                       every 'nrsec' seconds. The default value is 5 seconds.
+                       This means that if you lose your power, you will lose,
+                       as much, the latest 5 seconds of work (your filesystem
+                       will not be damaged though, thanks to journaling). This
+                       default value (or any low value) will hurt performance,
+                       but it's good for data-safety. Setting it to 0 will
+                       have the same effect than leaving the default 5 sec.
+                       Setting it to very large values will improve
+                       performance.
+
+barrier=1              This enables/disables barriers. barrier=0 disables it,
+                       barrier=1 enables it.
+
+orlov          (*)     This enables the new Orlov block allocator. It's enabled
+                       by default.
+
+oldalloc               This disables the Orlov block allocator and enables the
+                       old block allocator. Orlov should have better performance,
+                       we'd like to get some feedback if it's the contrary for
+                       you.
+
+user_xattr     (*)     Enables POSIX Extended Attributes. It's enabled by
+                       default, however you need to confifure its support
+                       (CONFIG_EXT3_FS_XATTR). This is neccesary if you want
+                       to use POSIX Acces Control Lists support. You can visit
+                       http://acl.bestbits.at to know more about POSIX Extended
+                       attributes.
+
+nouser_xattr           Disables POSIX Extended Attributes.
+
+acl            (*)     Enables POSIX Access Control Lists support. This is
+                       enabled by default, however you need to configure
+                       its support (CONFIG_EXT3_FS_POSIX_ACL). If you want
+                       to know more about ACLs visit http://acl.bestbits.at
+
+noacl                  This option disables POSIX Access Control List support.
+
+reservation
+
+noreservation
+
+resize=
+
 bsddf          (*)     Make 'df' act like BSD.
 minixdf                        Make 'df' act like Minix.
 
@@ -30,8 +87,6 @@ nocheck
 
 debug                  Extra debugging information is sent to syslog.
 
-noload                 Don't load the journal on mounting.
-
 errors=remount-ro(*)   Remount the filesystem read-only on an error.
 errors=continue                Keep going on a filesystem error.
 errors=panic           Panic and halt the machine if an error occurs.
@@ -48,17 +103,6 @@ resuid=n            The user ID which may use the reserved blocks.
 
 sb=n                   Use alternate superblock at this location.
 
-data=journal           All data are committed into the journal prior 
-                       to being written into the main file system.
-               
-data=ordered   (*)     All data are forced directly out to the main file 
-                       system prior to its metadata being committed to 
-                       the journal.
-               
-data=writeback         Data ordering is not preserved, data may be 
-                       written into the main file system after its
-                       metadata has been committed to the journal.
-
 quota                  Quota options are currently silently ignored.
 noquota                        (see fs/ext3/super.c, line 594)
 grpquota
@@ -114,7 +158,7 @@ Compatibility
 -------------
 
 Ext2 partitions can be easily convert to ext3, with `tune2fs -j <dev>`.
- Ext3 is fully compatible with Ext2.  Ext3 partitions can easily be
+Ext3 is fully compatible with Ext2.  Ext3 partitions can easily be
 mounted as Ext2.
 
 External Tools
index 177edbe..417e309 100644 (file)
@@ -62,13 +62,21 @@ size:      The limit of allocated bytes for this tmpfs instance. The
            since the OOM handler will not be able to free that memory.
 nr_blocks: The same as size, but in blocks of PAGE_CACHE_SIZE.
 nr_inodes: The maximum number of inodes for this instance. The default
-           is half of the number of your physical RAM pages.
+           is half of the number of your physical RAM pages, or (on a
+           a machine with highmem) the number of lowmem RAM pages,
+           whichever is the lower.
 
 These parameters accept a suffix k, m or g for kilo, mega and giga and
 can be changed on remount.  The size parameter also accepts a suffix %
 to limit this tmpfs instance to that percentage of your physical RAM:
 the default, when neither size nor nr_blocks is specified, is size=50%
 
+If both nr_blocks (or size) and nr_inodes are set to 0, neither blocks
+nor inodes will be limited in that instance.  It is generally unwise to
+mount with such options, since it allows any user with write access to
+use up all the memory on the machine; but enhances the scalability of
+that instance in a system with many cpus making intensive use of it.
+
 
 To specify the initial root directory you can use the following mount
 options:
@@ -89,4 +97,4 @@ RAM/SWAP in 10240 inodes and it is only accessible by root.
 Author:
    Christoph Rohland <cr@sap.com>, 1.12.01
 Updated:
-   Hugh Dickins <hugh@veritas.com>, 01 April 2003
+   Hugh Dickins <hugh@veritas.com>, 01 September 2004
index 9557ea1..5be10c9 100644 (file)
@@ -176,7 +176,7 @@ filesystem. As of kernel 2.1.99, the following members are defined:
 
 struct super_operations {
        void (*read_inode) (struct inode *);
-       void (*write_inode) (struct inode *, int);
+       int (*write_inode) (struct inode *, int);
        void (*put_inode) (struct inode *);
        void (*drop_inode) (struct inode *);
        void (*delete_inode) (struct inode *);
index 9342540..c7d5d0c 100644 (file)
@@ -120,12 +120,18 @@ The following sysctls are available for the XFS filesystem:
 
   fs.xfs.stats_clear           (Min: 0  Default: 0  Max: 1)
        Setting this to "1" clears accumulated XFS statistics 
-       in /proc/fs/xfs/stat.  It then immediately reset to "0".
-       
-  fs.xfs.sync_interval         (Min: HZ  Default: 30*HZ  Max: 60*HZ)
-       The interval at which the xfssyncd thread for xfs filesystems
-       flushes metadata out to disk. This thread will flush log
-       activity out, and do some processing on unlinked inodes
+       in /proc/fs/xfs/stat.  It then immediately resets to "0".
+  
+  fs.xfs.xfssyncd_centisecs    (Min: 100  Default: 3000  Max: 720000)
+       The interval at which the xfssyncd thread flushes metadata
+       out to disk.  This thread will flush log activity out, and
+       do some processing on unlinked inodes.
+
+  fs.xfs.xfsbufd_centisecs     (Min: 50  Default: 100  Max: 3000)
+       The interval at which xfsbufd scans the dirty metadata buffers list.
+
+  fs.xfs.age_buffer_centisecs  (Min: 100  Default: 1500  Max: 720000)
+       The age at which xfsbufd flushes dirty metadata buffers to disk.
 
   fs.xfs.error_level           (Min: 0  Default: 3  Max: 11)
        A volume knob for error reporting when internal errors occur.
@@ -180,14 +186,3 @@ The following sysctls are available for the XFS filesystem:
        Setting this to "1" will cause the "noatime" flag set 
        by the chattr(1) command on a directory to be
        inherited by files in that directory.
-
-  vm.pagebuf.stats_clear       (Min: 0  Default: 0  Max: 1)
-       Setting this to "1" clears accumulated pagebuf statistics 
-       in /proc/fs/pagebuf/stat.  It then immediately reset to "0".
-       
-  vm.pagebuf.flush_age         (Min: 1*HZ  Default: 15*HZ  Max: 300*HZ)
-       The age at which dirty metadata buffers are flushed to disk
-
-  vm.pagebuf.flush_int         (Min: HZ/2  Default: HZ  Max: 30*HZ)
-       The interval at which the list of dirty metadata buffers is
-       scanned.
index 037c0be..09eab2f 100644 (file)
@@ -14,9 +14,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/timer.h>
-#include <asm/hardirq.h>
+#include <linux/firmware.h>
 
-#include "linux/firmware.h"
 
 MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
 MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
index d6608e0..1990130 100644 (file)
@@ -7,10 +7,10 @@
 HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/
 
 echo 1 > /sys/$DEVPATH/loading
-cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data
+cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data
 echo 0 > /sys/$DEVPATH/loading
 
 # To cancel the load in case of error:
 #
-#      echo -1 > /sysfs/$DEVPATH/loading
+#      echo -1 > /sys/$DEVPATH/loading
 #
index f651de4..3e74dae 100644 (file)
@@ -104,7 +104,7 @@ in[0-8]_input       Voltage input value.
                        in7_*   varies
                        in8_*   varies
 
-in0_ref                CPU core reference voltage.
+cpu[0-1]_vid   CPU core reference voltage.
                Unit: millivolt
                Read only.
                Not always correct.
diff --git a/Documentation/i2o/README b/Documentation/i2o/README
new file mode 100644 (file)
index 0000000..9aa6ddb
--- /dev/null
@@ -0,0 +1,63 @@
+
+       Linux I2O Support       (c) Copyright 1999 Red Hat Software
+                                       and others.
+
+       This program is free software; you can redistribute 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.
+
+AUTHORS (so far)
+
+Alan Cox, Building Number Three Ltd.
+       Core code, SCSI and Block OSMs
+
+Steve Ralston, LSI Logic Corp.
+       Debugging SCSI and Block OSM
+
+Deepak Saxena, Intel Corp.
+       Various core/block extensions
+       /proc interface, bug fixes
+       Ioctl interfaces for control
+       Debugging LAN OSM
+
+Philip Rumpf
+       Fixed assorted dumb SMP locking bugs
+
+Juha Sievanen, University of Helsinki Finland
+       LAN OSM code
+       /proc interface to LAN class
+       Bug fixes
+       Core code extensions
+
+Auvo Häkkinen, University of Helsinki Finland
+       LAN OSM code
+       /Proc interface to LAN class
+       Bug fixes
+       Core code extensions
+
+Taneli Vähäkangas, University of Helsinki Finland
+       Fixes to i2o_config
+
+CREDITS
+
+       This work was made possible by
+
+Red Hat Software
+       Funding for the Building #3 part of the project
+
+Symbios Logic (Now LSI)
+       Host adapters, hints, known to work platforms when I hit
+       compatibility problems
+
+BoxHill Corporation
+       Loan of initial FibreChannel disk array used for development work.
+
+European Comission
+       Funding the work done by the University of Helsinki
+
+SysKonnect
+        Loan of FDDI and Gigabit Ethernet cards
+
+ASUSTeK
+        Loan of I2O motherboard
diff --git a/Documentation/i2o/ioctl b/Documentation/i2o/ioctl
new file mode 100644 (file)
index 0000000..3e17497
--- /dev/null
@@ -0,0 +1,394 @@
+
+Linux I2O User Space Interface
+rev 0.3 - 04/20/99
+
+=============================================================================
+Originally written by Deepak Saxena(deepak@plexity.net)
+Currently maintained by Deepak Saxena(deepak@plexity.net)
+=============================================================================
+
+I. Introduction
+
+The Linux I2O subsystem provides a set of ioctl() commands that can be
+utilized by user space applications to communicate with IOPs and devices
+on individual IOPs. This document defines the specific ioctl() commands
+that are available to the user and provides examples of their uses.
+
+This document assumes the reader is familiar with or has access to the
+I2O specification as no I2O message parameters are outlined.  For information
+on the specification, see http://www.i2osig.org
+
+This document and the I2O user space interface are currently maintained
+by Deepak Saxena.  Please send all comments, errata, and bug fixes to
+deepak@csociety.purdue.edu
+
+II. IOP Access
+
+Access to the I2O subsystem is provided through the device file named
+/dev/i2o/ctl.  This file is a character file with major number 10 and minor
+number 166.  It can be created through the following command:
+
+   mknod /dev/i2o/ctl c 10 166
+
+III. Determining the IOP Count
+
+   SYNOPSIS
+
+   ioctl(fd, I2OGETIOPS,  int *count);
+
+   u8 count[MAX_I2O_CONTROLLERS];
+
+   DESCRIPTION
+
+   This function returns the system's active IOP table.  count should
+   point to a buffer containing MAX_I2O_CONTROLLERS entries.  Upon
+   returning, each entry will contain a non-zero value if the given
+   IOP unit is active, and NULL if it is inactive or non-existent.
+
+   RETURN VALUE.
+
+   Returns 0 if no errors occur, and -1 otherwise.  If an error occurs,
+   errno is set appropriately:
+
+     EFAULT   Invalid user space pointer was passed
+
+IV. Getting Hardware Resource Table
+
+   SYNOPSIS
+
+   ioctl(fd, I2OHRTGET, struct i2o_cmd_hrt *hrt);
+
+      struct i2o_cmd_hrtlct
+      {
+         u32   iop;      /* IOP unit number */
+         void  *resbuf;  /* Buffer for result */
+         u32   *reslen;  /* Buffer length in bytes */
+      };
+
+   DESCRIPTION
+
+   This function returns the Hardware Resource Table of the IOP specified
+   by hrt->iop in the buffer pointed to by hrt->resbuf. The actual size of
+   the data is written into *(hrt->reslen).
+
+   RETURNS
+
+   This function returns 0 if no errors occur. If an error occurs, -1
+   is returned and errno is set appropriately:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ENOBUFS     Buffer not large enough.  If this occurs, the required
+                  buffer length is written into *(hrt->reslen)
+
+V. Getting Logical Configuration Table
+
+   SYNOPSIS
+
+   ioctl(fd, I2OLCTGET, struct i2o_cmd_lct *lct);
+
+      struct i2o_cmd_hrtlct
+      {
+         u32   iop;      /* IOP unit number */
+         void  *resbuf;  /* Buffer for result */
+         u32   *reslen;  /* Buffer length in bytes */
+      };
+
+   DESCRIPTION
+
+   This function returns the Logical Configuration Table of the IOP specified
+   by lct->iop in the buffer pointed to by lct->resbuf. The actual size of
+   the data is written into *(lct->reslen).
+
+   RETURNS
+
+   This function returns 0 if no errors occur. If an error occurs, -1
+   is returned and errno is set appropriately:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ENOBUFS     Buffer not large enough.  If this occurs, the required
+                  buffer length is written into *(lct->reslen)
+
+VI. Settting Parameters
+
+   SYNOPSIS
+
+   ioctl(fd, I2OPARMSET, struct i2o_parm_setget *ops);
+
+      struct i2o_cmd_psetget
+      {
+         u32   iop;      /* IOP unit number */
+         u32   tid;      /* Target device TID */
+         void  *opbuf;   /* Operation List buffer */
+         u32   oplen;    /* Operation List buffer length in bytes */
+         void  *resbuf;  /* Result List buffer */
+         u32   *reslen;  /* Result List buffer length in bytes */
+      };
+
+   DESCRIPTION
+
+   This function posts a UtilParamsSet message to the device identified
+   by ops->iop and ops->tid.  The operation list for the message is
+   sent through the ops->opbuf buffer, and the result list is written
+   into the buffer pointed to by ops->resbuf.  The number of bytes
+   written is placed into *(ops->reslen).
+
+   RETURNS
+
+   The return value is the size in bytes of the data written into
+   ops->resbuf if no errors occur.  If an error occurs, -1 is returned
+   and errno is set appropriatly:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ENOBUFS     Buffer not large enough.  If this occurs, the required
+                  buffer length is written into *(ops->reslen)
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+   A return value of 0 does not mean that the value was actually
+   changed properly on the IOP.  The user should check the result
+   list to determine the specific status of the transaction.
+
+VII. Getting Parameters
+
+   SYNOPSIS
+
+   ioctl(fd, I2OPARMGET, struct i2o_parm_setget *ops);
+
+      struct i2o_parm_setget
+      {
+         u32   iop;      /* IOP unit number */
+         u32   tid;      /* Target device TID */
+         void  *opbuf;   /* Operation List buffer */
+         u32   oplen;    /* Operation List buffer length in bytes */
+         void  *resbuf;  /* Result List buffer */
+         u32   *reslen;  /* Result List buffer length in bytes */
+      };
+
+   DESCRIPTION
+
+   This function posts a UtilParamsGet message to the device identified
+   by ops->iop and ops->tid.  The operation list for the message is
+   sent through the ops->opbuf buffer, and the result list is written
+   into the buffer pointed to by ops->resbuf.  The actual size of data
+   written is placed into *(ops->reslen).
+
+   RETURNS
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ENOBUFS     Buffer not large enough.  If this occurs, the required
+                  buffer length is written into *(ops->reslen)
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+   A return value of 0 does not mean that the value was actually
+   properly retreived.  The user should check the result list
+   to determine the specific status of the transaction.
+
+VIII. Downloading Software
+
+   SYNOPSIS
+
+   ioctl(fd, I2OSWDL, struct i2o_sw_xfer *sw);
+
+      struct i2o_sw_xfer
+      {
+         u32   iop;       /* IOP unit number */
+         u8    flags;     /* DownloadFlags field */
+         u8    sw_type;   /* Software type */
+         u32   sw_id;     /* Software ID */
+         void  *buf;      /* Pointer to software buffer */
+         u32   *swlen;    /* Length of software buffer */
+         u32   *maxfrag;  /* Number of fragments */
+         u32   *curfrag;  /* Current fragment number */
+      };
+
+   DESCRIPTION
+
+   This function downloads a software fragment pointed by sw->buf
+   to the iop identified by sw->iop. The DownloadFlags, SwID, SwType
+   and SwSize fields of the ExecSwDownload message are filled in with
+   the values of sw->flags, sw->sw_id, sw->sw_type and *(sw->swlen).
+
+   The fragments _must_ be sent in order and be 8K in size. The last
+   fragment _may_ be shorter, however. The kernel will compute its
+   size based on information in the sw->swlen field.
+
+   Please note that SW transfers can take a long time.
+
+   RETURNS
+
+   This function returns 0 no errors occur. If an error occurs, -1
+   is returned and errno is set appropriatly:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+IX. Uploading Software
+
+   SYNOPSIS
+
+   ioctl(fd, I2OSWUL, struct i2o_sw_xfer *sw);
+
+      struct i2o_sw_xfer
+      {
+         u32   iop;      /* IOP unit number */
+         u8    flags;   /* UploadFlags */
+         u8    sw_type;  /* Software type */
+         u32   sw_id;    /* Software ID */
+         void  *buf;     /* Pointer to software buffer */
+         u32   *swlen;   /* Length of software buffer */
+         u32   *maxfrag; /* Number of fragments */
+         u32   *curfrag; /* Current fragment number */
+      };
+
+   DESCRIPTION
+
+   This function uploads a software fragment from the IOP identified
+   by sw->iop, sw->sw_type, sw->sw_id and optionally sw->swlen fields.
+   The UploadFlags, SwID, SwType and SwSize fields of the ExecSwUpload
+   message are filled in with the values of sw->flags, sw->sw_id,
+   sw->sw_type and *(sw->swlen).
+
+   The fragments _must_ be requested in order and be 8K in size. The
+   user is responsible for allocating memory pointed by sw->buf. The
+   last fragment _may_ be shorter.
+
+   Please note that SW transfers can take a long time.
+
+   RETURNS
+
+   This function returns 0 if no errors occur.  If an error occurs, -1
+   is returned and errno is set appropriatly:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+X. Removing Software
+
+   SYNOPSIS
+
+   ioctl(fd, I2OSWDEL, struct i2o_sw_xfer *sw);
+
+      struct i2o_sw_xfer
+      {
+         u32   iop;      /* IOP unit number */
+         u8    flags;   /* RemoveFlags */
+         u8    sw_type;  /* Software type */
+         u32   sw_id;    /* Software ID */
+         void  *buf;     /* Unused */
+         u32   *swlen;   /* Length of the software data */
+         u32   *maxfrag; /* Unused */
+         u32   *curfrag; /* Unused */
+      };
+
+   DESCRIPTION
+
+   This function removes software from the IOP identified by sw->iop.
+   The RemoveFlags, SwID, SwType and SwSize fields of the ExecSwRemove message
+   are filled in with the values of sw->flags, sw->sw_id, sw->sw_type and
+   *(sw->swlen). Give zero in *(sw->len) if the value is unknown. IOP uses
+   *(sw->swlen) value to verify correct identication of the module to remove.
+   The actual size of the module is written into *(sw->swlen).
+
+   RETURNS
+
+   This function returns 0 if no errors occur.  If an error occurs, -1
+   is returned and errno is set appropriatly:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+X. Validating Configuration
+
+   SYNOPSIS
+
+   ioctl(fd, I2OVALIDATE, int *iop);
+       u32 iop;
+
+   DESCRIPTION
+
+   This function posts an ExecConfigValidate message to the controller
+   identified by iop. This message indicates that the current
+   configuration is accepted. The iop changes the status of suspect drivers
+   to valid and may delete old drivers from its store.
+
+   RETURNS
+
+   This function returns 0 if no erro occur.  If an error occurs, -1 is
+   returned and errno is set appropriatly:
+
+      ETIMEDOUT   Timeout waiting for reply message
+      ENXIO       Invalid IOP number
+
+XI. Configuration Dialog
+
+   SYNOPSIS
+
+   ioctl(fd, I2OHTML, struct i2o_html *htquery);
+      struct i2o_html
+      {
+         u32   iop;      /* IOP unit number */
+         u32   tid;      /* Target device ID */
+         u32   page;     /* HTML page */
+         void  *resbuf;  /* Buffer for reply HTML page */
+         u32   *reslen;  /* Length in bytes of reply buffer */
+         void  *qbuf;    /* Pointer to HTTP query string */
+         u32   qlen;     /* Length in bytes of query string buffer */
+      };
+
+   DESCRIPTION
+
+   This function posts an UtilConfigDialog message to the device identified
+   by htquery->iop and htquery->tid.  The requested HTML page number is
+   provided by the htquery->page field, and the resultant data is stored
+   in the buffer pointed to by htquery->resbuf.  If there is an HTTP query
+   string that is to be sent to the device, it should be sent in the buffer
+   pointed to by htquery->qbuf.  If there is no query string, this field
+   should be set to NULL. The actual size of the reply received is written
+   into *(htquery->reslen).
+
+   RETURNS
+
+   This function returns 0 if no error occur. If an error occurs, -1
+   is returned and errno is set appropriatly:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ENOBUFS     Buffer not large enough.  If this occurs, the required
+                  buffer length is written into *(ops->reslen)
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+XII. Events
+
+    In the process of determining this.  Current idea is to have use
+    the select() interface to allow user apps to periodically poll
+    the /dev/i2o/ctl device for events.  When select() notifies the user
+    that an event is available, the user would call read() to retrieve
+    a list of all the events that are pending for the specific device.
+
+=============================================================================
+Revision History
+=============================================================================
+
+Rev 0.1 - 04/01/99
+- Initial revision
+
+Rev 0.2 - 04/06/99
+- Changed return values to match UNIX ioctl() standard.  Only return values
+  are 0 and -1.  All errors are reported through errno.
+- Added summary of proposed possible event interfaces
+
+Rev 0.3 - 04/20/99
+- Changed all ioctls() to use pointers to user data instead of actual data
+- Updated error values to match the code
index b8d92c0..88a011c 100644 (file)
@@ -335,6 +335,7 @@ controller (compatible with DirectPadPro):
  * Analog PSX Pad (red mode)
  * Analog PSX Pad (green mode)
  * PSX Rumble Pad
+ * PSX DDR Pad
 
 2.4 Sega
 ~~~~~~~~
@@ -452,14 +453,22 @@ uses the following kernel/module command line:
          5  | Multisystem 2-button joystick
          6  | N64 pad
          7  | Sony PSX controller
+         8  | Sony PSX DDR controller
 
-  The exact type of the PSX controller type is autoprobed, so you must have
-your controller plugged in before initializing.
+  The exact type of the PSX controller type is autoprobed when used so
+hot swapping should work (but is not recomended).
 
   Should you want to use more than one of parallel ports at once, you can use
 gamecon.map2 and gamecon.map3 as additional command line parameters for two
 more parallel ports.
 
+  There are two options specific to PSX driver portion.  gamecon.psx_delay sets
+the command delay when talking to the controllers. The default of 25 should
+work but you can try lowering it for better performace. If your pads don't
+respond try raising it untill they work. Setting the type to 8 allows the
+driver to be used with Dance Dance Revolution or similar games. Arrow keys are
+registered as key presses instead of X and Y axes.
+
 3.2 db9.c
 ~~~~~~~~~
   Apart from making an interface, there is nothing difficult on using the
index ec81776..1075e4d 100644 (file)
@@ -25,6 +25,7 @@ This document describes the Linux kernel Makefiles.
           --- 4.4 Using C++ for host programs
           --- 4.5 Controlling compiler options for host programs
           --- 4.6 When host programs are actually built
+          --- 4.7 Using hostprogs-$(CONFIG_FOO)
 
        === 5 Kbuild clean infrastructure
 
@@ -36,6 +37,8 @@ This document describes the Linux kernel Makefiles.
           --- 6.5 Building non-kbuild targets
           --- 6.6 Commands useful for building a boot image
           --- 6.7 Custom kbuild commands
+          --- 6.8 Preprocessing linker scripts
+          --- 6.9 $(CC) support functions
 
        === 7 Kbuild Variables
        === 8 Makefile language
@@ -387,7 +390,7 @@ compilation stage.
 Two steps are required in order to use a host executable.
 
 The first step is to tell kbuild that a host program exists. This is
-done utilising the variable host-prog.
+done utilising the variable hostprogs-y.
 
 The second step is to add an explicit dependency to the executable.
 This can be done in two ways. Either add the dependency in a rule, 
@@ -402,7 +405,7 @@ Both possibilities are described in the following.
        built on the build host.
 
        Example:
-               host-progs := bin2hex
+               hostprogs-y := bin2hex
 
        Kbuild assumes in the above example that bin2hex is made from a single
        c-source file named bin2hex.c located in the same directory as
@@ -418,7 +421,7 @@ Both possibilities are described in the following.
 
        Example:
                #scripts/lxdialog/Makefile
-               host-progs    := lxdialog  
+               hostprogs-y   := lxdialog  
                lxdialog-objs := checklist.o lxdialog.o
 
        Objects with extension .o are compiled from the corresponding .c
@@ -438,7 +441,7 @@ Both possibilities are described in the following.
 
        Example:
                #scripts/kconfig/Makefile
-               host-progs      := conf
+               hostprogs-y     := conf
                conf-objs       := conf.o libkconfig.so
                libkconfig-objs := expr.o type.o
   
@@ -457,7 +460,7 @@ Both possibilities are described in the following.
 
        Example:
                #scripts/kconfig/Makefile
-               host-progs    := qconf
+               hostprogs-y   := qconf
                qconf-cxxobjs := qconf.o
 
        In the example above the executable is composed of the C++ file
@@ -468,7 +471,7 @@ Both possibilities are described in the following.
 
        Example:
                #scripts/kconfig/Makefile
-               host-progs    := qconf
+               hostprogs-y   := qconf
                qconf-cxxobjs := qconf.o
                qconf-objs    := check.o
        
@@ -509,7 +512,7 @@ Both possibilities are described in the following.
 
        Example:
                #drivers/pci/Makefile
-               host-progs := gen-devlist
+               hostprogs-y := gen-devlist
                $(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist
                        ( cd $(obj); ./gen-devlist ) < $<
 
@@ -524,18 +527,32 @@ Both possibilities are described in the following.
 
        Example:
                #scripts/lxdialog/Makefile
-               host-progs    := lxdialog
-               always        := $(host-progs)
+               hostprogs-y   := lxdialog
+               always        := $(hostprogs-y)
 
        This will tell kbuild to build lxdialog even if not referenced in
        any rule.
 
+--- 4.7 Using hostprogs-$(CONFIG_FOO)
+
+       A typcal pattern in a Kbuild file lok like this:
+
+       Example:
+               #scripts/Makefile
+               hostprogs-$(CONFIG_KALLSYMS) += kallsyms
+
+       Kbuild knows about both 'y' for built-in and 'm' for module.
+       So if a config symbol evaluate to 'm', kbuild will still build
+       the binary. In other words Kbuild handle hostprogs-m exactly
+       like hostprogs-y. But only hostprogs-y is recommend used
+       when no CONFIG symbol are involved.
+
 === 5 Kbuild clean infrastructure
 
 "make clean" deletes most generated files in the src tree where the kernel
 is compiled. This includes generated files such as host programs.
-Kbuild knows targets listed in $(host-progs), $(always), $(extra-y) and
-$(targets). They are all deleted during "make clean".
+Kbuild knows targets listed in $(hostprogs-y), $(hostprogs-m), $(always),
+$(extra-y) and $(targets). They are all deleted during "make clean".
 Files matching the patterns "*.[oas]", "*.ko", plus some additional files
 generated by kbuild are deleted all over the kernel src tree when
 "make clean" is executed.
@@ -547,8 +564,17 @@ Additional files can be specified in kbuild makefiles by use of $(clean-files).
                clean-files := devlist.h classlist.h
 
 When executing "make clean", the two files "devlist.h classlist.h" will
-be deleted. Kbuild knows that files specified by $(clean-files) are
-located in the same directory as the makefile.
+be deleted. Kbuild will assume files to be in same relative directory as the
+Makefile except if an absolute path is specified (path starting with '/').
+
+To delete a directory hirachy use:
+       Example:
+               #scripts/package/Makefile
+               clean-dirs := $(objtree)/debian/
+
+This will delete the directory debian, including all subdirectories.
+Kbuild will assume the directories to be in the same relative path as the
+Makefile if no absolute path is specified (path does not start with '/').
 
 Usually kbuild descends down in subdirectories due to "obj-* := dir/",
 but in the architecture makefiles where the kbuild infrastructure
@@ -638,15 +664,6 @@ When kbuild executes the following steps are followed (roughly):
                #arch/i386/Makefile
                LDFLAGS_vmlinux := -e stext
 
-    LDFLAGS_BLOB       Options for $(LD) when linking the initramfs blob
-
-       The image used for initramfs is made during the build process.
-       LDFLAGS_BLOB is used to specify additional flags to be used when
-       creating the initramfs_data.o file.
-       Example:
-               #arch/i386/Makefile
-               LDFLAGS_BLOB := --format binary --oformat elf32-i386
-
     OBJCOPYFLAGS       objcopy flags
 
        When $(call if_changed,objcopy) is used to translate a .o file,
@@ -914,6 +931,90 @@ When kbuild executes the following steps are followed (roughly):
        will be displayed with "make KBUILD_VERBOSE=0".
        
 
+--- 6.8 Preprocessing linker scripts
+
+       When the vmlinux image is build the linker script:
+       arch/$(ARCH)/kernel/vmlinux.lds is used.
+       The script is a preprocessed variant of the file vmlinux.lds.S
+       located in the same directory.
+       kbuild knows .lds file and includes a rule *lds.S -> *lds.
+       
+       Example:
+               #arch/i386/kernel/Makefile
+               always := vmlinux.lds
+       
+               #Makefile
+               export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
+               
+       The assigment to $(always) is used to tell kbuild to build the
+       target: vmlinux.lds.
+       The assignment to $(CPPFLAGS_vmlinux.lds) tell kbuild to use the
+       specified options when building the target vmlinux.lds.
+       
+       When building the *.lds target kbuild used the variakles:
+       CPPFLAGS        : Set in top-level Makefile
+       EXTRA_CPPFLAGS  : May be set in the kbuild makefile
+       CPPFLAGS_$(@F)  : Target specific flags.
+                         Note that the full filename is used in this
+                         assignment.
+
+       The kbuild infrastructure for *lds file are used in several
+       architecture specific files.
+
+
+--- 6.9 $(CC) support functions
+
+       The kernel may be build with several different versions of
+       $(CC), each supporting a unique set of features and options.
+       kbuild provide basic support to check for valid options for $(CC).
+       $(CC) is useally the gcc compiler, but other alternatives are
+       available.
+
+    cc-option
+       cc-option is used to check if $(CC) support a given option, and not
+       supported to use an optional second option.
+
+       Example:
+               #arch/i386/Makefile
+               cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)
+
+       In the above example cflags-y will be assigned the option
+       -march=pentium-mmx if supported by $(CC), otherwise -march-i586.
+       The second argument to cc-option is optional, and if omitted
+       cflags-y will be assigned no value if first option is not supported.
+
+   cc-option-yn
+       cc-option-yn is used to check if gcc supports a given option
+       and return 'y' if supported, otherwise 'n'.
+
+       Example:
+               #arch/ppc/Makefile
+               biarch := $(call cc-option-yn, -m32)
+               aflags-$(biarch) += -a32
+               cflags-$(biarch) += -m32
+       
+       In the above example $(biarch) is set to y if $(CC) supports the -m32
+       option. When $(biarch) equals to y the expanded variables $(aflags-y)
+       and $(cflags-y) will be assigned the values -a32 and -m32.
+
+    cc-version
+       cc-version return a numerical version of the $(CC) compiler version.
+       The format is <major><minor> where both are two digits. So for example
+       gcc 3.41 would return 0341.
+       cc-version is useful when a specific $(CC) version is faulty in one
+       area, for example the -mregparm=3 were broken in some gcc version
+       even though the option was accepted by gcc.
+
+       Example:
+               #arch/i386/Makefile
+               GCC_VERSION := $(call cc-version)
+               cflags-y += $(shell \
+               if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;)
+
+       In the above example -mregparm=3 is only used for gcc version greater
+       than or equal to gcc 3.0.
+       
+
 === 7 Kbuild Variables
 
 The top Makefile exports the following variables:
diff --git a/Documentation/networking/gen_stats.txt b/Documentation/networking/gen_stats.txt
new file mode 100644 (file)
index 0000000..c3297f7
--- /dev/null
@@ -0,0 +1,117 @@
+Generic networking statistics for netlink users
+======================================================================
+
+Statistic counters are grouped into structs:
+
+Struct               TLV type              Description
+----------------------------------------------------------------------
+gnet_stats_basic     TCA_STATS_BASIC       Basic statistics
+gnet_stats_rate_est  TCA_STATS_RATE_EST    Rate estimator
+gnet_stats_queue     TCA_STATS_QUEUE       Queue statistics
+none                 TCA_STATS_APP         Application specific
+
+
+Collecting:
+-----------
+
+Declare the statistic structs you need:
+struct mystruct {
+       struct gnet_stats_basic bstats;
+       struct gnet_stats_queue qstats;
+       ...
+};
+
+Update statistics:
+mystruct->tstats.packet++;
+mystruct->qstats.backlog += skb->pkt_len;
+
+
+Export to userspace (Dump):
+---------------------------
+
+my_dumping_routine(struct sk_buff *skb, ...)
+{
+       struct gnet_dump dump;
+
+       if (gnet_stats_start_copy(skb, TCA_STATS2, &mystruct->lock, &dump) < 0)
+               goto rtattr_failure;
+
+       if (gnet_stats_copy_basic(&dump, &mystruct->bstats) < 0 ||
+           gnet_stats_copy_queue(&dump, &mystruct->qstats) < 0 ||
+               gnet_stats_copy_app(&dump, &xstats, sizeof(xstats)) < 0)
+               goto rtattr_failure;
+
+       if (gnet_stats_finish_copy(&dump) < 0)
+               goto rtattr_failure;
+       ...
+}
+
+TCA_STATS/TCA_XSTATS backward compatibility:
+--------------------------------------------
+
+Prior users of struct tc_stats and xstats can maintain backward
+compatibility by calling the compat wrappers to keep providing the
+existing TLV types.
+
+my_dumping_routine(struct sk_buff *skb, ...)
+{
+    if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
+               TCA_XSTATS, &mystruct->lock, &dump) < 0)
+               goto rtattr_failure;
+       ...
+}
+
+A struct tc_stats will be filled out during gnet_stats_copy_* calls
+and appended to the skb. TCA_XSTATS is provided if gnet_stats_copy_app
+was called.
+
+
+Locking:
+--------
+
+Locks are taken before writing and released once all statistics have
+been written. Locks are always released in case of an error. You
+are responsible for making sure that the lock is initialized.
+
+
+Rate Estimator:
+--------------
+
+0) Prepare an estimator attribute. Most likely this would be in user
+   space. The value of this TLV should contain a tc_estimator structure.
+   As usual, such a TLV nees to be 32 bit aligned and therefore the
+   length needs to be appropriately set etc. The estimator interval
+   and ewma log need to be converted to the appropriate values.
+   tc_estimator.c::tc_setup_estimator() is advisable to be used as the
+   conversion routine. It does a few clever things. It takes a time
+   interval in microsecs, a time constant also in microsecs and a struct
+   tc_estimator to  be populated. The returned tc_estimator can be
+   transported to the kernel.  Transfer such a structure in a TLV of type
+   TCA_RATE to your code in the kernel.
+
+In the kernel when setting up:
+1) make sure you have basic stats and rate stats setup first.
+2) make sure you have initialized stats lock that is used to setup such
+   stats.
+3) Now initialize a new estimator:
+
+   int ret = gen_new_estimator(my_basicstats,my_rate_est_stats,
+       mystats_lock, attr_with_tcestimator_struct);
+
+   if ret == 0
+       success
+   else
+       failed
+
+From now on, everytime you dump my_rate_est_stats it will contain
+uptodate info.
+
+Once you are done, call gen_kill_estimator(my_basicstats,
+my_rate_est_stats) Make sure that my_basicstats and my_rate_est_stats
+are still valid (i.e still exist) at the time of making this call.
+
+
+Authors:
+--------
+Thomas Graf <tgraf@suug.ch>
+Jamal Hadi Salim <hadi@cyberus.ca>
index 8c456ed..1509f3a 100644 (file)
@@ -43,8 +43,21 @@ dev->get_stats:
 
 dev->hard_start_xmit:
        Synchronization: dev->xmit_lock spinlock.
+       When the driver sets NETIF_F_LLTX in dev->features this will be
+       called without holding xmit_lock. In this case the driver 
+       has to lock by itself when needed. It is recommended to use a try lock
+       for this and return -1 when the spin lock fails. 
+       The locking there should also properly protect against 
+       set_multicast_list
        Context: BHs disabled
        Notes: netif_queue_stopped() is guaranteed false
+       Return codes: 
+       o NETDEV_TX_OK everything ok. 
+       o NETDEV_TX_BUSY Cannot transmit packet, try later 
+         Usually a bug, means queue start/stop flow control is broken in
+         the driver. Note: the driver must NOT put the skb in its DMA ring.
+       o NETDEV_TX_LOCKED Locking failed, please retry quickly.
+         Only valid when NETIF_F_LLTX is set.
 
 dev->tx_timeout:
        Synchronization: dev->xmit_lock spinlock.
index 111ad15..c0a62e1 100644 (file)
@@ -10,7 +10,7 @@ NOTE:Eight space tabs are the optimum editor setting for reading this file.
 
               Author(s) :  Ryan S. Arnold <rsa@us.ibm.com>
                       Date Created: March, 02, 2004
-                      Last Changed: July, 07, 2004
+                      Last Changed: August, 24, 2004
 
 ---------------------------------------------------------------------------
 Table of contents:
@@ -243,6 +243,25 @@ node.  If this is not done, the next user to connect to the console will
 continue using the previous user's logged in session which includes
 using the $TERM variable that the previous user supplied.
 
+Hotplug add and remove of vty-server adapters affects which /dev/hvcs* node
+is used to connect to each vty-server adapter.  In order to determine which
+vty-server adapter is associated with which /dev/hvcs* node a special sysfs
+attribute has been added to each vty-server sysfs entry.  This entry is
+called "index" and showing it reveals an integer that refers to the
+/dev/hvcs* entry to use to connect to that device.  For instance cating the
+index attribute of vty-server adapter 30000004 shows the following.
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat index
+       2
+
+This index of '2' means that in order to connect to vty-server adapter
+30000004 the user should interact with /dev/hvcs2.
+
+It should be noted that due to the system hotplug I/O capabilities of a
+system the /dev/hvcs* entry that interacts with a particular vty-server
+adapter is not guarenteed to remain the same across system reboots.  Look
+in the Q & A section for more on this issue.
+
 ---------------------------------------------------------------------------
 6. Disconnection
 
@@ -328,8 +347,8 @@ address that is created by firmware.  An example vty-server sysfs entry
 looks like the following:
 
        Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
-       .   current_vty   devspec  partner_clcs  vterm_state
-       ..  detach_state  name     partner_vtys
+       .   current_vty   devspec  name          partner_vtys
+       ..  detach_state  index    partner_clcs  vterm_state
 
 Each entry is provided, by default with a "name" attribute.  Reading the
 "name" attribute will reveal the device type as shown in the following
@@ -499,6 +518,20 @@ A: Yes, if you have dlpar and hotplug enabled for your system and it has
 been built into the kernel the hvcs drivers is configured to dynamically
 handle additions of new devices and removals of unused devices.
 
+---------------------------------------------------------------------------
+Q: For some reason /dev/hvcs* doesn't map to the same vty-server adapter
+after a reboot.  What happened?
+
+A: Assignment of vty-server adapters to /dev/hvcs* entries is always done
+in the order that the adapters are exposed.  Due to hotplug capabilities of
+this driver assignment of hotplug added vty-servers may be in a different
+order than how they would be exposed on module load.  Rebooting or
+reloading the module after dynamic addition may result in the /dev/hvcs*
+and vty-server coupling changing if a vty-server adapter was added in a
+slot inbetween two other vty-server adapters.  Refer to the section above
+on how to determine which vty-server goes with which /dev/hvcs* node.
+Hint; look at the sysfs "index" attribute for the vty-server.
+
 ---------------------------------------------------------------------------
 Q: Can I use /dev/hvcs* as a conduit to another partition and use a tty
 device on that partition as the other end of the pipe?
diff --git a/Documentation/sched-stats.txt b/Documentation/sched-stats.txt
new file mode 100644 (file)
index 0000000..6f72021
--- /dev/null
@@ -0,0 +1,153 @@
+Version 10 of schedstats includes support for sched_domains, which
+hit the mainline kernel in 2.6.7.  Some counters make more sense to be
+per-runqueue; other to be per-domain.  Note that domains (and their associated
+information) will only be pertinent and available on machines utilizing
+CONFIG_SMP.
+
+In version 10 of schedstat, there is at least one level of domain
+statistics for each cpu listed, and there may well be more than one
+domain.  Domains have no particular names in this implementation, but
+the highest numbered one typically arbitrates balancing across all the
+cpus on the machine, while domain0 is the most tightly focused domain,
+sometimes balancing only between pairs of cpus.  At this time, there
+are no architectures which need more than three domain levels. The first
+field in the domain stats is a bit map indicating which cpus are affected
+by that domain.
+
+These fields are counters, and only increment.  Programs which make use
+of these will need to start with a baseline observation and then calculate
+the change in the counters at each subsequent observation.  A perl script
+which does this for many of the fields is available at
+
+    http://eaglet.rain.com/rick/linux/schedstat/
+
+Note that any such script will necessarily be version-specific, as the main
+reason to change versions is changes in the output format.  For those wishing
+to write their own scripts, the fields are described here.
+
+CPU statistics
+--------------
+cpu<N> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
+
+NOTE: In the sched_yield() statistics, the active queue is considered empty
+    if it has only one process in it, since obviously the process calling
+    sched_yield() is that process.
+
+First four fields are sched_yield() statistics:
+     1) # of times both the active and the expired queue were empty
+     2) # of times just the active queue was empty
+     3) # of times just the expired queue was empty
+     4) # of times sched_yield() was called
+
+Next four are schedule() statistics:
+     5) # of times the active queue had at least one other process on it
+     6) # of times we switched to the expired queue and reused it
+     7) # of times schedule() was called
+     8) # of times schedule() left the processor idle
+
+Next four are active_load_balance() statistics:
+     9) # of times active_load_balance() was called
+    10) # of times active_load_balance() caused this cpu to gain a task
+    11) # of times active_load_balance() caused this cpu to lose a task
+    12) # of times active_load_balance() tried to move a task and failed
+
+Next three are try_to_wake_up() statistics:
+    13) # of times try_to_wake_up() was called
+    14) # of times try_to_wake_up() successfully moved the awakening task
+    15) # of times try_to_wake_up() attempted to move the awakening task
+
+Next two are wake_up_new_task() statistics:
+    16) # of times wake_up_new_task() was called
+    17) # of times wake_up_new_task() successfully moved the new task
+
+Next one is a sched_migrate_task() statistic:
+    18) # of times sched_migrate_task() was called
+
+Next one is a sched_balance_exec() statistic:
+    19) # of times sched_balance_exec() was called
+
+Next three are statistics describing scheduling latency:
+    20) sum of all time spent running by tasks on this processor (in ms)
+    21) sum of all time spent waiting to run by tasks on this processor (in ms)
+    22) # of tasks (not necessarily unique) given to the processor
+
+The last six are statistics dealing with pull_task():
+    23) # of times pull_task() moved a task to this cpu when newly idle
+    24) # of times pull_task() stole a task from this cpu when another cpu
+       was newly idle
+    25) # of times pull_task() moved a task to this cpu when idle
+    26) # of times pull_task() stole a task from this cpu when another cpu
+       was idle
+    27) # of times pull_task() moved a task to this cpu when busy
+    28) # of times pull_task() stole a task from this cpu when another cpu
+       was busy
+
+
+Domain statistics
+-----------------
+One of these is produced per domain for each cpu described. (Note that if
+CONFIG_SMP is not defined, *no* domains are utilized and these lines
+will not appear in the output.)
+
+domain<N> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+
+The first field is a bit mask indicating what cpus this domain operates over.
+
+The next fifteen are a variety of load_balance() statistics:
+
+     1) # of times in this domain load_balance() was called when the cpu
+       was idle
+     2) # of times in this domain load_balance() was called when the cpu
+       was busy
+     3) # of times in this domain load_balance() was called when the cpu
+       was just becoming idle
+     4) # of times in this domain load_balance() tried to move one or more
+       tasks and failed, when the cpu was idle
+     5) # of times in this domain load_balance() tried to move one or more
+       tasks and failed, when the cpu was busy
+     6) # of times in this domain load_balance() tried to move one or more
+       tasks and failed, when the cpu was just becoming idle
+     7) sum of imbalances discovered (if any) with each call to
+       load_balance() in this domain when the cpu was idle
+     8) sum of imbalances discovered (if any) with each call to
+       load_balance() in this domain when the cpu was busy
+     9) sum of imbalances discovered (if any) with each call to
+       load_balance() in this domain when the cpu was just becoming idle
+    10) # of times in this domain load_balance() was called but did not find
+       a busier queue while the cpu was idle
+    11) # of times in this domain load_balance() was called but did not find
+       a busier queue while the cpu was busy
+    12) # of times in this domain load_balance() was called but did not find
+       a busier queue while the cpu was just becoming idle
+    13) # of times in this domain a busier queue was found while the cpu was
+       idle but no busier group was found
+    14) # of times in this domain a busier queue was found while the cpu was
+       busy but no busier group was found
+    15) # of times in this domain a busier queue was found while the cpu was
+       just becoming idle but no busier group was found
+
+Next two are sched_balance_exec() statistics:
+    17) # of times in this domain sched_balance_exec() successfully pushed
+       a task to a new cpu
+    18) # of times in this domain sched_balance_exec() tried but failed to
+       push a task to a new cpu
+
+Next two are try_to_wake_up() statistics:
+    19) # of times in this domain try_to_wake_up() tried to move a task based
+       on affinity and cache warmth
+    20) # of times in this domain try_to_wake_up() tried to move a task based
+       on load balancing
+
+
+/proc/<pid>/schedstat
+----------------
+schedstats also adds a new /proc/<pid/schedstat file to include some of
+the same information on a per-process level.  There are three fields in
+this file correlating to fields 20, 21, and 22 in the CPU fields, but
+they only apply for that process.
+
+A program could be easily written to make use of these extra fields to
+report on how well a particular process or set of processes is faring
+under the scheduler's policies.  A simple version of such a program is
+available at
+    http://eaglet.rain.com/rick/linux/schedstat/v10/latency.c
index 03af4a4..431e398 100644 (file)
-### Version 2.00.3
-Wed Jan 29 09:13:44 EST 200 - Atul Mukker <atulm@lsil.com>
-i.     Change the handshake in ISR while acknowledging interrupts. Write the
-       valid interrupt pattern 0x10001234 as soon as it is read from the
-       outdoor register. In existing driver and on certain platform, invalid
-       command ids were being returned.
+Release Date   : Mon Sep 27 22:15:07 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version        : 2.20.4.0 (scsi module), 2.20.2.0 (cmm module)
+Older Version  : 2.20.3.1 (scsi module), 2.20.2.0 (cmm module)
 
-       Also, do not wait on status be become 0xFF, since FW can return this
-       status in certain circumstances.
+i.     Fix data corruption. Because of a typo in the driver, the IO packets
+       were wrongly shared by the ioctl path. This causes a whole IO command
+       to be replaced by an incoming ioctl command.
 
-       Initialize the numstatus field of mailbox to 0xFF so that we can wait
-       on this wait in next interrupt. Firmware does not change its value
-       unless there are some status to be posted
+Release Date   : Tue Aug 24 09:43:35 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version        : 2.20.3.1 (scsi module), 2.20.2.0 (cmm module)
+Older Version  : 2.20.3.0 (scsi module), 2.20.2.0 (cmm module)
 
-ii.    Specify the logical drive number while issuing the RESERVATION_STATUS
+i.     Function reordering so that inline functions are defined before they
+       are actually used. It is now mandatory for GCC 3.4.1 (current stable)
 
-iii.   Reduce the default mailbox busy wait time from 300us to 10us. This is
-       done to avaoid a possible deadlock in FW because of longer bust waits.
+       Declare some heavy-weight functions to be non-inlined,
+       megaraid_mbox_build_cmd, megaraid_mbox_runpendq,
+       megaraid_mbox_prepare_pthru, megaraid_mbox_prepare_epthru,
+       megaraid_busywait_mbox
 
-iv.    The max outstanding commands are reduced to 126 because that't the
-       safest value on all FW.
+               - Andrew Morton <akpm@osdl.org>, 08.19.2004
+               linux-scsi mailing list
 
-v.     Number of sectors per IO are reduced to 128 (64kb), becuase FW needs
-       resources in special circumstances like check consistency, rebuilds
-       etc.
+       "Something else to clean up after inclusion: every instance of an
+       inline function is actually rendered as a full function call, because
+       the function is always used before it is defined.  Atul, please
+       re-arrange the code to eliminate the need for most (all) of the
+       function prototypes at the top of each file, and define (not just
+       declare with a prototype) each inline function before its first use"
 
-vi.    max_commands is no longer a module parameter because of iv.
+               - Matt Domsch <Matt_Domsch@dell.com>, 07.27.2004
+               linux-scsi mailing list
 
-### Version: 2.00.2
-i.     Intermediate release with kernel specific code
 
+ii.    Display elapsed time (countdown) while waiting for FW to boot.
 
-### Version: 2.00.1i
-Wed Dec  4 14:34:51 EST 2002 - Atul Mukker <atulm@lsil.com>
-i.     Making the older IO based controllers to work with this driver
+iii.   Module compilation reorder in Makefile so that unresolved symbols do
+       not occur when driver is compiled non-modular.
 
+               Patrick J. LoPresti <patl@users.sourceforge.net>, 8.22.2004
+               linux-scsi mailing list
 
-### Version 2.00.1
-Fri Nov 15 10:59:44 EST 2002 - Atul Mukker <atulm@lsil.com>
-i.     Release host lock before issuing internal command to reset
-       reservations in megaraid_reset() and reacquire after internal command
-       is completed.
+
+Release Date   : Thu Aug 19 09:58:33 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version        : 2.20.3.0 (scsi module), 2.20.2.0 (cmm module)
+Older Version  : 2.20.2.0 (scsi module), 2.20.1.0 (cmm module)
+
+i.     When copying the mailbox packets, copy only first 14 bytes (for 32-bit
+       mailboxes) and only first 22 bytes (for 64-bit mailboxes). This is to
+       avoid getting the stale values for busy bit. We want to set the busy
+       bit just before issuing command to the FW.
+
+ii.    In the reset handling, if the reseted command is not owned by the
+       driver, do not (wrongly) print information for the "attached" driver
+       packet.
+
+iii.   Have extended wait when issuing command in synchronous mode. This is
+       required for the cases where the option ROM is disabled and there is
+       no BIOS to start the controller. The FW starts to boot after receiving
+       the first command from the driver. The current driver has 1 second
+       timeout for the synchronous commands, which is far less than what is
+       actually required. We now wait up to MBOX_RESET_TIME (180 seconds) for
+       FW boot process.
+
+iv.    In megaraid_mbox_product_info, clear the mailbox contents completely
+       before preparing the command for inquiry3. This is to ensure that the
+       FW does not get junk values in the command.
+
+v.     Do away with the redundant LSI_CONFIG_COMPAT redefinition for
+       CONFIG_COMPAT. Replace <asm/ioctl32.h> with <linux/ioctl32.h>
+
+               - James Bottomley <James.Bottomley@SteelEye.com>, 08.17.2004
+                linux-scsi mailing list
+
+vi.    Add support for 64-bit applications. Current drivers assume only
+       32-bit applications, even on 64-bit platforms. Use the "data" and
+       "buffer" fields of the mimd_t structure, instead of embedded 32-bit
+       addresses in application mailbox and passthru structures.
+
+vii.   Move the function declarations for the management module from
+       megaraid_mm.h to megaraid_mm.c
+
+               - Andrew Morton <akpm@osdl.org>, 08.19.2004
+               linux-scsi mailing list
+
+viii.  Change default values for MEGARAID_NEWGEN, MEGARAID_MM, and
+       MEGARAID_MAILBOX to 'n' in Kconfig.megaraid
+
+               - Andrew Morton <akpm@osdl.org>, 08.19.2004
+               linux-scsi mailing list
+
+ix.    replace udelay with msleep
+
+x.     Typos corrected in comments and whitespace adjustments, explicit
+       grouping of expressions.
+
+
+Release Date   : Fri Jul 23 15:22:07 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version        : 2.20.2.0 (scsi module), 2.20.1.0 (cmm module)
+Older Version  : 2.20.1.0 (scsi module), 2.20.0.0 (cmm module)
+
+i.     Add PCI ids for Acer ROMB 2E solution
+
+ii.    Add PCI ids for I4
+
+iii.   Typo corrected for subsys id for megaraid sata 300-4x
+
+iv.    Remove yield() while mailbox handshake in synchronous commands
+
+
+       "My other main gripe is things like this:
+
+       +       // wait for maximum 1 second for status to post
+       +       for (i = 0; i < 40000; i++) {
+       +               if (mbox->numstatus != 0xFF) break;
+       +               udelay(25); yield();
+       +       }
+
+       which litter the driver.  Use of yield() in drivers is deprecated."
+
+               - James Bottomley <James.Bottomley@SteelEye.com>, 07.14.2004
+                linux-scsi mailing list
+
+v.     Remove redundant __megaraid_busywait_mbox routine
+
+vi.    Fix bug in the managment module, which causes a system lockup when the
+       IO module is loaded and then unloaded, followed by executing any
+       management utility. The current version of management module does not
+       handle the adapter unregister properly.
+
+       Specifically, it still keeps a reference to the unregistered
+       controllers. To avoid this, the static array adapters has been
+       replaced by a dynamic list, which gets updated every time an adapter
+       is added or removed.
+
+       Also, during unregistration of the IO module, the resources are
+       now released in the exact reverse order of the allocation time
+       sequence.
+
+
+Release Date   : Fri Jun 25 18:58:43 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version        : 2.20.1.0
+Older Version  : megaraid 2.20.0.1
+
+i.     Stale list pointer in adapter causes kernel panic when module
+       megaraid_mbox is unloaded
+
+
+Release Date   : Thu Jun 24 20:37:11 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version        : 2.20.0.1
+Older Version  : megaraid 2.20.0.00
+
+i.     Modules are not 'y' by default, but depend on current definition of
+       SCSI & PCI.
+
+ii.    Redundant structure mraid_driver_t removed.
+
+iii.   Miscellaneous indentation and goto/label fixes.
+               - Christoph Hellwig <hch@infradead.org>, 06.24.2004 linux-scsi
+
+iv.    scsi_host_put(), do just before completing HBA shutdown.
+
+
+
+Release Date   : Mon Jun 21 19:53:54 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version        : 2.20.0.0
+Older Version  : megaraid 2.20.0.rc2 and 2.00.3
+
+i.     Independent module to interact with userland applications and
+       multiplex command to low level RAID module(s).
+
+       "Shared code in a third module, a "library module", is an acceptable
+       solution. modprobe automatically loads dependent modules, so users
+       running "modprobe driver1" or "modprobe driver2" would automatically
+       load the shared library module."
+
+               - Jeff Garzik <jgarzik@pobox.com> 02.25.2004 LKML
+
+       "As Jeff hinted, if your userspace<->driver API is consistent between
+       your new MPT-based RAID controllers and your existing megaraid driver,
+       then perhaps you need a single small helper module (lsiioctl or some
+       better name), loaded by both mptraid and megaraid automatically, which
+       handles registering the /dev/megaraid node dynamically. In this case,
+       both mptraid and megaraid would register with lsiioctl for each
+       adapter discovered, and lsiioctl would essentially be a switch,
+       redirecting userspace tool ioctls to the appropriate driver."
+
+               - Matt Domsch <Matt_Domsch@dell.com> 02.25.2004 LKML
+
+ii.    Remove C99 initializations from pci_device id.
+
+       "pci_id_table_g would be much more readable when not using C99
+       initializers.
+       PCI table doesn't change, there's lots of users that prefer the more
+       readable variant.  And it's really far less and much easier to grok
+       lines without C99 initializers."
+
+               - Christoph Hellwig <hch@infradead.org>, 05.28.2004 linux-scsi
+
+iii.   Many fixes as suggested by Christoph Hellwig <hch@infradead.org> on
+       linux-scsi, 05.28.2004
+
+iv.    We now support up to 32 parallel ioctl commands instead of current 1.
+       There is a conscious effort to let memory allocation not fail for ioctl
+       commands.
+
+v.     Do away with internal memory management. Use pci_pool_(create|alloc)
+       instead.
+
+vi.    Kill tasklet when unloading the driver.
+
+vii.   Do not use "host_lock', driver has fine-grain locks now to protect all
+       data structures.
+
+viii.  Optimize the build scatter-gather list routine. The callers already
+       know the data transfer address and length.
+
+ix.    Better implementation of error handling and recovery. Driver now
+       performs extended errors recovery for instances like scsi cable pull.
+
+x.     Disassociate the management commands with an overlaid scsi command.
+       Driver now treats the management packets as special packets and has a
+       dedicated callback routine.
diff --git a/Documentation/scsi/megaraid.txt b/Documentation/scsi/megaraid.txt
new file mode 100644 (file)
index 0000000..ff864c0
--- /dev/null
@@ -0,0 +1,70 @@
+                       Notes on Management Module
+                       ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Overview:
+--------
+
+Different classes of controllers from LSI Logic, accept and respond to the
+user applications in a similar way. They understand the same firmware control
+commands. Furthermore, the applications also can treat different classes of
+the controllers uniformly. Hence it is logical to have a single module that
+interefaces with the applications on one side and all the low level drivers
+on the other.
+
+The advantages, though obvious, are listed for completeness:
+
+       i.      Avoid duplicate code from the low level drivers.
+       ii.     Unburden the low level drivers from having to export the
+               character node device and related handling.
+       iii.    Implement any policy mechanisms in one place.
+       iv.     Applications have to interface with only module instead of
+               multiple low level drivers.
+
+Currently this module (called Common Management Module) is used only to issue
+ioctl commands. But this module is envisioned to handle all user space level
+interactions. So any 'proc', 'sysfs' implementations will be localized in this
+common module.
+
+Credits:
+-------
+
+"Shared code in a third module, a "library module", is an acceptable
+solution. modprobe automatically loads dependent modules, so users
+running "modprobe driver1" or "modprobe driver2" would automatically
+load the shared library module."
+
+               - Jeff Garzik (jgarzik@pobox.com), 02.25.2004 LKML
+
+"As Jeff hinted, if your userspace<->driver API is consistent between
+your new MPT-based RAID controllers and your existing megaraid driver,
+then perhaps you need a single small helper module (lsiioctl or some
+better name), loaded by both mptraid and megaraid automatically, which
+handles registering the /dev/megaraid node dynamically. In this case,
+both mptraid and megaraid would register with lsiioctl for each
+adapter discovered, and lsiioctl would essentially be a switch,
+redirecting userspace tool ioctls to the appropriate driver."
+
+               - Matt Domsch, (Matt_Domsch@dell.com), 02.25.2004 LKML
+
+Design:
+------
+
+The Common Management Module is implemented in megaraid_mm.[ch] files. This
+module acts as a registry for low level hba drivers. The low level drivers
+(currently only megaraid) register each controller with the common module.
+
+The applications interface with the common module via the character device
+node exported by the module.
+
+The lower level drivers now understand only a new improved ioctl packet called
+uioc_t. The management module converts the older ioctl packets from the older
+applications into uioc_t. After driver handles the uioc_t, the common module
+will convert that back into the old format before returning to applications.
+
+As new applications evolve and replace the old ones, the old packet format 
+will be retired.
+
+Common module dedicates one uioc_t packet to each controller registered. This
+can easily be more than one. But since megaraid is the only low level driver
+today, and it can handle only one ioctl, there is no reason to have more. But
+as new controller classes get added, this will be tuned appropriately.
index 32fdc15..1f3ae3e 100644 (file)
@@ -47,7 +47,6 @@
      </sect1>
      <sect1><title>Memory Management Helpers</title>
 !Esound/core/memory.c
-!Iinclude/sound/sndmagic.h
 !Esound/core/memalloc.c
      </sect1>
   </chapter>
index 9a193fc..3515917 100644 (file)
@@ -23,7 +23,6 @@ show up in /proc/sys/kernel:
 - dentry-state
 - domainname
 - hostname
-- htab-reclaim                [ PPC only ]
 - hotplug
 - java-appletviewer           [ binfmt_java, obsolete ]
 - java-interpreter            [ binfmt_java, obsolete ]
@@ -54,7 +53,6 @@ show up in /proc/sys/kernel:
 - tainted
 - threads-max
 - version
-- zero-paged                  [ PPC only ]
 
 ==============================================================
 
@@ -133,8 +131,8 @@ domainname and hostname, i.e.:
 # echo "darkstar" > /proc/sys/kernel/hostname
 # echo "mydomain" > /proc/sys/kernel/domainname
 has the same effect as
-# hostname "darkstar" > /proc/sys/kernel/hostname
-# domainname "mydomain" > /proc/sys/kernel/domainname
+# hostname "darkstar"
+# domainname "mydomain"
 
 Note, however, that the classic darkstar.frop.org has the
 hostname "darkstar" and DNS (Internet Domain Name Server)
@@ -145,14 +143,6 @@ see the hostname(1) man page.
 
 ==============================================================
 
-htab-reclaim: (PPC only)
-
-Setting this to a non-zero value, the PowerPC htab
-(see Documentation/powerpc/ppc_htab.txt) is pruned
-each time the system hits the idle loop.
-==============================================================
-
 hotplug:
 
 Path for the hotplug policy agent.
@@ -322,11 +312,3 @@ can be ORed together:
       Set by modutils >= 2.4.9 and module-init-tools.
   4 - Unsafe SMP processors: SMP with CPUs not designed for SMP.
 
-==============================================================
-
-zero-paged: (PPC only)
-
-When enabled (non-zero), Linux-PPC will pre-zero pages in
-the idle loop, possibly speeding up get_free_pages. Since
-this only affects what the idle loop is doing, you should
-enable this and see if anything changes.
diff --git a/Documentation/time_interpolators.txt b/Documentation/time_interpolators.txt
new file mode 100644 (file)
index 0000000..d9fefd5
--- /dev/null
@@ -0,0 +1,40 @@
+Time Interpolators
+------------------
+
+Time interpolators are a base of time calculation between timer ticks and
+allow an accurate determination of time down to the accuracy of the time
+source in nanoseconds.
+
+The architecture specific code typically provides gettimeofday and
+settimeofday under Linux. The time interpolator provides both if an arch
+defines CONFIG_TIME_INTERPOLATION. The arch still must set up timer tick
+operations and call the necessary functions to advance the clock.
+With the time interpolator a standardized interface exists for time
+interpolation between ticks which also allows the determination
+of time in a hardware independent way. The provided logic is highly scalable
+and has been tested in SMP situations of up to 512 CPUs.
+
+If CONFIG_TIME_INTERPOLATION is defined then the architecture specific code
+(or the device drivers - like HPET) must register time interpolators.
+These are typically defined in the following way:
+
+static struct time_interpolator my_interpolator;
+
+void time_init(void)
+{
+       ....
+       /* Initialization of the timer *.
+       my_interpolator.frequency = MY_FREQUENCY;
+       my_interpolator.source = TIME_SOURCE_MMIO32;
+       my_interpolator.address = &my_timer;
+       my_interpolator.shift = 32;             /* increase accuracy of scaling */
+       my_interpolator.drift = -1;             /* Unknown */
+       my_interpolator.jitter = 0;             /* A stable time source */
+       register_time_interpolator(&my_interpolator);
+       ....
+}
+
+For more details see include/linux/timex.h.
+
+Christoph Lameter <christoph@lameter.com>, September 8, 2004
+
diff --git a/Documentation/tty.txt b/Documentation/tty.txt
new file mode 100644 (file)
index 0000000..a496056
--- /dev/null
@@ -0,0 +1,194 @@
+
+                       The Lockronomicon
+
+Your guide to the ancient and twisted locking policies of the tty layer and
+the warped logic behind them. Beware all ye who read on.
+
+FIXME: still need to work out the full set of BKL assumptions and document
+them so they can eventually be killed off.
+
+
+Line Discipline
+---------------
+
+Line disciplines are registered with tty_register_ldisc() passing the
+discipline number and the ldisc structure. At the point of registration the 
+discipline must be ready to use and it is possible it will get used before
+the call returns success. If the call returns an error then it won't get
+called. Do not re-use ldisc numbers as they are part of the userspace ABI
+and writing over an existing ldisc will cause demons to eat your computer.
+After the return the ldisc data has been copied so you may free your own 
+copy of the structure. You must not re-register over the top of the line
+discipline even with the same data or your computer again will be eaten by
+demons.
+
+In order to remove a line discipline call tty_register_ldisc passing NULL.
+In ancient times this always worked. In modern times the function will
+return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
+code manages the module counts this should not usually be a concern.
+
+Heed this warning: the reference count field of the registered copies of the
+tty_ldisc structure in the ldisc table counts the number of lines using this
+discipline. The reference count of the tty_ldisc structure within a tty 
+counts the number of active users of the ldisc at this instant. In effect it
+counts the number of threads of execution within an ldisc method (plus those
+about to enter and exit although this detail matters not).
+
+Line Discipline Methods
+-----------------------
+
+TTY side interfaces:
+
+close()                -       This is called on a terminal when the line
+                       discipline is being unplugged. At the point of
+                       execution no further users will enter the
+                       ldisc code for this tty. Can sleep.
+
+open()         -       Called when the line discipline is attached to
+                       the terminal. No other call into the line
+                       discipline for this tty will occur until it
+                       completes successfully. Can sleep.
+
+write()                -       A process is writing data from user space
+                       through the line discipline. Multiple write calls
+                       are serialized by the tty layer for the ldisc. May
+                       sleep.
+
+flush_buffer() -       May be called at any point between open and close.
+
+chars_in_buffer() -    Report the number of bytes in the buffer.
+
+set_termios()  -       Called on termios structure changes. The caller
+                       passes the old termios data and the current data
+                       is in the tty. Called under the termios semaphore so
+                       allowed to sleep. Serialized against itself only.
+
+read()         -       Move data from the line discipline to the user.
+                       Multiple read calls may occur in parallel and the
+                       ldisc must deal with serialization issues. May 
+                       sleep.
+
+poll()         -       Check the status for the poll/select calls. Multiple
+                       poll calls may occur in parallel. May sleep.
+
+ioctl()                -       Called when an ioctl is handed to the tty layer
+                       that might be for the ldisc. Multiple ioctl calls
+                       may occur in parallel. May sleep. 
+
+Driver Side Interfaces:
+
+receive_buf()  -       Hand buffers of bytes from the driver to the ldisc
+                       for processing. Semantics currently rather
+                       mysterious 8(
+
+receive_room() -       Can be called by the driver layer at any time when
+                       the ldisc is opened. The ldisc must be able to
+                       handle the reported amount of data at that instant.
+                       Synchronization between active receive_buf and
+                       receive_room calls is down to the driver not the
+                       ldisc. Must not sleep.
+
+write_wakeup() -       May be called at any point between open and close.
+                       The TTY_DO_WRITE_WAKEUP flag indicates if a call
+                       is needed but always races versus calls. Thus the
+                       ldisc must be careful about setting order and to
+                       handle unexpected calls. Must not sleep.
+
+
+Locking
+
+Callers to the line discipline functions from the tty layer are required to
+take line discipline locks. The same is true of calls from the driver side
+but not yet enforced.
+
+Three calls are now provided
+
+       ldisc = tty_ldisc_ref(tty);
+
+takes a handle to the line discipline in the tty and returns it. If no ldisc
+is currently attached or the ldisc is being closed and re-opened at this
+point then NULL is returned. While this handle is held the ldisc will not
+change or go away.
+
+       tty_ldisc_deref(ldisc)
+
+Returns the ldisc reference and allows the ldisc to be closed. Returning the
+reference takes away your right to call the ldisc functions until you take
+a new reference.
+
+       ldisc = tty_ldisc_ref_wait(tty);
+
+Performs the same function as tty_ldisc_ref except that it will wait for an
+ldisc change to complete and then return a reference to the new ldisc. 
+
+While these functions are slightly slower than the old code they should have
+minimal impact as most receive logic uses the flip buffers and they only
+need to take a reference when they push bits up through the driver.
+
+A caution: The ldisc->open(), ldisc->close() and driver->set_ldisc 
+functions are called with the ldisc unavailable. Thus tty_ldisc_ref will
+fail in this situation if used within these functions. Ldisc and driver
+code calling its own functions must be careful in this case. 
+
+
+Driver Interface
+----------------
+
+open()         -       Called when a device is opened. May sleep
+
+close()                -       Called when a device is closed. At the point of
+                       return from this call the driver must make no 
+                       further ldisc calls of any kind. May sleep
+
+write()                -       Called to write bytes to the device. May not
+                       sleep. May occur in parallel in special cases. 
+                       Because this includes panic paths drivers generally
+                       shouldn't try and do clever locking here.
+
+put_char()     -       Stuff a single character onto the queue. The
+                       driver is guaranteed following up calls to
+                       flush_chars.
+
+flush_chars()  -       Ask the kernel to write put_char queue
+
+write_room()   -       Return the number of characters tht can be stuffed
+                       into the port buffers without overflow (or less).
+                       The ldisc is responsible for being intelligent
+                       about multi-threading of write_room/write calls
+
+ioctl()                -       Called when an ioctl may be for the driver
+
+set_termios()  -       Called on termios change, serialized against
+                       itself by a semaphore. May sleep.
+
+set_ldisc()    -       Notifier for discipline change. At the point this 
+                       is done the discipline is not yet usable. Can now
+                       sleep (I think)
+
+throttle()     -       Called by the ldisc to ask the driver to do flow
+                       control.  Serialization including with unthrottle
+                       is the job of the ldisc layer.
+
+unthrottle()   -       Called by the ldisc to ask the driver to stop flow
+                       control.
+
+stop()         -       Ldisc notifier to the driver to stop output. As with
+                       throttle the serializations with start() are down
+                       to the ldisc layer.
+
+start()                -       Ldisc notifier to the driver to start output.
+
+hangup()       -       Ask the tty driver to cause a hangup initiated
+                       from the host side. [Can sleep ??]
+
+break_ctl()    -       Send RS232 break. Can sleep. Can get called in
+                       parallel, driver must serialize (for now), and
+                       with write calls.
+
+wait_until_sent() -    Wait for characters to exit the hardware queue
+                       of the driver. Can sleep
+
+send_xchar()     -     Send XON/XOFF and if possible jump the queue with
+                       it in order to get fast flow control responses.
+                       Cannot sleep ??
+
index 65018c8..3999069 100644 (file)
@@ -14,10 +14,10 @@ Index
 4.  Module dependencies
 5.  Module loading
 6.  Module parameters
-7.  Device control through "sysfs"
+7.  Optional device control through "sysfs"
 8.  Supported devices
 9.  How to add support for new image sensors
-10. Note for V4L2 developers
+10. Notes for V4L2 application developers
 11. Contact information
 12. Credits
 
@@ -142,23 +142,21 @@ Description:    Debugging information level, from 0 to 3:
                 1 = critical errors
                 2 = significant informations
                 3 = more verbose messages
-                Level 3 is useful for testing only, when just one device
+                Level 3 is useful for testing only, when only one device
                 is used.
 Default:        2
 -------------------------------------------------------------------------------
 
 
-7. Device control through "sysfs"
-=================================
+7. Optional device control through "sysfs"
+==========================================
 It is possible to read and write both the SN9C10[12] and the image sensor
 registers by using the "sysfs" filesystem interface.
 
-Every time a supported device is recognized, read-only files named "redblue"
-and "green" are created in the /sys/class/video4linux/videoX directory. You can
-set the red, blue and green channel's gain by writing the desired value to
-them. The value may range from 0 to 15 for each channel; this means that
-"redblue" accepts 8-bit values, where the low 4 bits are reserved for red and
-the others for blue.
+Every time a supported device is recognized, a read-only file named "green" is
+created in the /sys/class/video4linux/videoX directory. You can set the green
+channel's gain by writing the desired value to it. The value may range from 0
+to 15.
 
 There are other four entries in the directory above for each registered camera:
 "reg", "val", "i2c_reg" and "i2c_val". The first two files control the
@@ -208,7 +206,7 @@ Vendor ID  Product ID
 0xc45      0x6029
 0xc45      0x602a
 0xc45      0x602c
-0xc45      0x8001
+0xc45      0x6030
 
 The list above does NOT imply that all those devices work with this driver: up
 until now only the ones that mount the following image sensors are supported.
@@ -217,6 +215,7 @@ Kernel messages will always tell you whether this is the case:
 Model       Manufacturer
 -----       ------------
 PAS106B     PixArt Imaging Inc.
+PAS202BCB   PixArt Imaging Inc.
 TAS5110C1B  Taiwan Advanced Sensor Corporation
 TAS5130D1B  Taiwan Advanced Sensor Corporation
 
@@ -239,23 +238,31 @@ have created for this purpose, which is present in "sn9c102_sensor.h"
 (documentation is included there). As an example, have a look at the code in
 "sn9c102_pas106b.c", which uses the mentioned interface.
 
-At the moment, not yet supported image sensors are: PAS202B (VGA),
-HV7131[D|E1] (VGA), MI03 (VGA), OV7620 (VGA).
+At the moment, not yet supported image sensors are: HV7131[D|E1] (VGA),
+MI03 (VGA), OV7620 (VGA).
 
 
-10. Note for V4L2 developers
-============================
+10. Notes for V4L2 application developers
+=========================================
 This driver follows the V4L2 API specifications. In particular, it enforces two
 rules:
 
-1) Exactly one I/O method, either "mmap" or "read", is associated with each
+- exactly one I/O method, either "mmap" or "read", is associated with each
 file descriptor. Once it is selected, the application must close and reopen the
-device to switch to the other I/O method.
+device to switch to the other I/O method;
 
-2) Previously mapped buffer memory must always be unmapped before calling any
-of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. In case,
-the same number of buffers as before will be allocated again to match the size
-of the new video frames, so you have to map them again before any I/O attempts.
+- previously mapped buffer memory must always be unmapped before calling any
+of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. The same
+number of buffers as before will be allocated again to match the size of the
+new video frames, so you have to map them again before any I/O attempts.
+
+Consistently with the hardware limits, this driver also supports image
+downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions.
+However the V4L2 API specifications don't correctly define how the scaling
+factor can be choosen arbitrarily by the "negotiation" of the "source" and
+"target" rectangles. To work around this flaw, we have added the convention
+that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
+scaling factor is restored to 1.
 
 
 11. Contact information
@@ -273,4 +280,6 @@ I would thank the following persons:
 
 - Stefano Mozzi, who donated 45 EU;
 - Luca Capello for the donation of a webcam;
-- Mizuno Takafumi for the donation of a webcam.
+- Mizuno Takafumi for the donation of a webcam;
+- Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB
+  image sensor.
index e0fd0b8..9db560e 100644 (file)
@@ -1,4 +1,4 @@
-The Linux kernel supports three overcommit handling modes
+The Linux kernel supports the following overcommit handling modes
 
 0      -       Heuristic overcommit handling. Obvious overcommits of
                address space are refused. Used for a typical system. It
@@ -7,10 +7,10 @@ The Linux kernel supports three overcommit handling modes
                allocate slighly more memory in this mode. This is the 
                default.
 
-1      -       No overcommit handling. Appropriate for some scientific
+1      -       Always overcommit. Appropriate for some scientific
                applications.
 
-2      -       (NEW) strict overcommit. The total address space commit
+2      -       Don't overcommit. The total address space commit
                for the system is not permitted to exceed swap + a
                configurable percentage (default is 50) of physical RAM.
                Depending on the percentage you use, in most situations
@@ -27,7 +27,7 @@ Gotchas
 
 The C language stack growth does an implicit mremap. If you want absolute
 guarantees and run close to the edge you MUST mmap your stack for the 
-largest size you think you will need. For typical stack usage is does
+largest size you think you will need. For typical stack usage this does
 not matter much but it's a corner case if you really really care
 
 In mode 2 the MAP_NORESERVE flag is ignored. 
index a586667..12187a3 100644 (file)
@@ -35,7 +35,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
-#include <linux/pcwd.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
 
 int fd;
 
index d78f8db..7f8570a 100644 (file)
@@ -136,17 +136,25 @@ PCI
 
 IOMMU
 
-  iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,soft]
+ iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
+         [,forcesac][,fullflush][,nomerge][,noaperture]
    size  set size of iommu (in bytes)
    noagp don't initialize the AGP driver and use full aperture.
    off   don't use the IOMMU
    leak  turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on)
    memaper[=order] allocate an own aperture over RAM with size 32MB^order.
    noforce don't force IOMMU usage. Default.
-   force  Force IOMMU
-   soft   Use software bounce buffering for non 32bit IO. Default on Intel
-          machines. 
-
-  swiotlb=pages
-
-  Prereserve that many 4K pages for the software IO bounce buffering.
+   force  Force IOMMU.
+   merge  Do SG merging. Implies force (experimental)
+   nomerge Don't do SG merging.
+   forcesac For SAC mode for masks <40bits  (experimental)
+   fullflush Flush IOMMU on each allocation (default)
+   nofullflush Don't use IOMMU fullflush
+   allowed  overwrite iommu off workarounds for specific chipsets.
+   soft         Use software bounce buffering (default for Intel machines)
+   noaperture Don't touch the aperture for AGP.
+
+  swiotlb=pages[,force]
+
+  pages  Prereserve that many 128K pages for the software IO bounce buffering.
+  force  Force all IO through the software TLB.
diff --git a/arch/alpha/Kconfig.debug b/arch/alpha/Kconfig.debug
new file mode 100644 (file)
index 0000000..36d0106
--- /dev/null
@@ -0,0 +1,59 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config EARLY_PRINTK
+       bool
+       depends on ALPHA_GENERIC || ALPHA_SRM
+       default y
+
+config DEBUG_RWLOCK
+       bool "Read-write spinlock debugging"
+       depends on DEBUG_KERNEL
+       help
+         If you say Y here then read-write lock processing will count how many
+         times it has tried to get the lock and issue an error message after
+         too many attempts.  If you suspect a rwlock problem or a kernel
+         hacker asks for this option then say Y.  Otherwise say N.
+
+config DEBUG_SEMAPHORE
+       bool "Semaphore debugging"
+       depends on DEBUG_KERNEL
+       help
+         If you say Y here then semaphore processing will issue lots of
+         verbose debugging messages.  If you suspect a semaphore problem or a
+         kernel hacker asks for this option then say Y.  Otherwise say N.
+
+config ALPHA_LEGACY_START_ADDRESS
+       bool "Legacy kernel start address"
+       depends on ALPHA_GENERIC
+       default n
+       ---help---
+         The 2.4 kernel changed the kernel start address from 0x310000
+         to 0x810000 to make room for the Wildfire's larger SRM console.
+         Recent consoles on Titan and Marvel machines also require the
+         extra room.
+
+         If you're using aboot 0.7 or later, the bootloader will examine the
+         ELF headers to determine where to transfer control. Unfortunately,
+         most older bootloaders -- APB or MILO -- hardcoded the kernel start
+         address rather than examining the ELF headers, and the result is a
+         hard lockup.
+
+         Say Y if you have a broken bootloader.  Say N if you do not, or if
+         you wish to run on Wildfire, Titan, or Marvel.
+
+config ALPHA_LEGACY_START_ADDRESS
+       bool
+       depends on !ALPHA_GENERIC && !ALPHA_TITAN && !ALPHA_MARVEL && !ALPHA_WILDFIRE
+       default y
+
+config MATHEMU
+       tristate "Kernel FP software completion" if DEBUG_KERNEL && !SMP
+       default y if !DEBUG_KERNEL || SMP
+       help
+         This option is required for IEEE compliant floating point arithmetic
+         on the Alpha. The only time you would ever not say Y is to say M in
+         order to debug the code. Say Y unless you know what you are doing.
+
+endmenu
index e309450..e1ae14c 100644 (file)
@@ -8,7 +8,7 @@
 # Copyright (C) 1994 by Linus Torvalds
 #
 
-host-progs     := tools/mkbb tools/objstrip
+hostprogs-y    := tools/mkbb tools/objstrip
 targets                := vmlinux.gz vmlinux \
                   vmlinux.nh tools/lxboot tools/bootlx tools/bootph \
                   tools/bootpzh bootloader bootpheader bootpzheader 
index 73202af..ab6fa54 100644 (file)
@@ -2,13 +2,13 @@
 # Makefile for the linux kernel.
 #
 
-extra-y                := head.o vmlinux.lds.s
+extra-y                := head.o vmlinux.lds
 EXTRA_AFLAGS   := $(CFLAGS)
 EXTRA_CFLAGS   := -Werror -Wno-sign-compare
 
 obj-y    := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
            irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \
-           alpha_ksyms.o systbls.o err_common.o
+           alpha_ksyms.o systbls.o err_common.o io.o
 
 obj-$(CONFIG_VGA_HOSE) += console.o
 obj-$(CONFIG_SMP)      += smp.o
index c901914..ad654af 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/tty.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/console.h>
@@ -67,36 +68,6 @@ EXPORT_SYMBOL(alpha_using_srm);
 #endif /* CONFIG_ALPHA_GENERIC */
 
 /* platform dependent support */
-EXPORT_SYMBOL(_inb);
-EXPORT_SYMBOL(_inw);
-EXPORT_SYMBOL(_inl);
-EXPORT_SYMBOL(_outb);
-EXPORT_SYMBOL(_outw);
-EXPORT_SYMBOL(_outl);
-EXPORT_SYMBOL(_readb);
-EXPORT_SYMBOL(_readw);
-EXPORT_SYMBOL(_readl);
-EXPORT_SYMBOL(_writeb);
-EXPORT_SYMBOL(_writew);
-EXPORT_SYMBOL(_writel);
-EXPORT_SYMBOL(___raw_readb); 
-EXPORT_SYMBOL(___raw_readw); 
-EXPORT_SYMBOL(___raw_readl); 
-EXPORT_SYMBOL(___raw_readq); 
-EXPORT_SYMBOL(___raw_writeb); 
-EXPORT_SYMBOL(___raw_writew); 
-EXPORT_SYMBOL(___raw_writel); 
-EXPORT_SYMBOL(___raw_writeq); 
-EXPORT_SYMBOL(_memcpy_fromio);
-EXPORT_SYMBOL(_memcpy_toio);
-EXPORT_SYMBOL(_memset_c_io);
-EXPORT_SYMBOL(scr_memcpyw);
-EXPORT_SYMBOL(insb);
-EXPORT_SYMBOL(insw);
-EXPORT_SYMBOL(insl);
-EXPORT_SYMBOL(outsb);
-EXPORT_SYMBOL(outsw);
-EXPORT_SYMBOL(outsl);
 EXPORT_SYMBOL(strcat);
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strcpy);
@@ -136,7 +107,9 @@ EXPORT_SYMBOL(pci_dac_dma_supported);
 EXPORT_SYMBOL(pci_dac_page_to_dma);
 EXPORT_SYMBOL(pci_dac_dma_to_page);
 EXPORT_SYMBOL(pci_dac_dma_to_offset);
+EXPORT_SYMBOL(alpha_gendev_to_pci);
 #endif
+EXPORT_SYMBOL(dma_set_mask);
 
 EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_elf_thread);
@@ -183,8 +156,8 @@ EXPORT_SYMBOL(__min_ipl);
 /*
  * The following are specially called from the uaccess assembly stubs.
  */
-EXPORT_SYMBOL_NOVERS(__copy_user);
-EXPORT_SYMBOL_NOVERS(__do_clear_user);
+EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(__do_clear_user);
 EXPORT_SYMBOL(__strncpy_from_user);
 EXPORT_SYMBOL(__strnlen_user);
 
@@ -243,17 +216,17 @@ EXPORT_SYMBOL(rtc_lock);
  */
 # undef memcpy
 # undef memset
-EXPORT_SYMBOL_NOVERS(__divl);
-EXPORT_SYMBOL_NOVERS(__divlu);
-EXPORT_SYMBOL_NOVERS(__divq);
-EXPORT_SYMBOL_NOVERS(__divqu);
-EXPORT_SYMBOL_NOVERS(__reml);
-EXPORT_SYMBOL_NOVERS(__remlu);
-EXPORT_SYMBOL_NOVERS(__remq);
-EXPORT_SYMBOL_NOVERS(__remqu);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memchr);
+EXPORT_SYMBOL(__divl);
+EXPORT_SYMBOL(__divlu);
+EXPORT_SYMBOL(__divq);
+EXPORT_SYMBOL(__divqu);
+EXPORT_SYMBOL(__reml);
+EXPORT_SYMBOL(__remlu);
+EXPORT_SYMBOL(__remq);
+EXPORT_SYMBOL(__remqu);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memchr);
 
 EXPORT_SYMBOL(get_wchan);
 
diff --git a/arch/alpha/kernel/io.c b/arch/alpha/kernel/io.c
new file mode 100644 (file)
index 0000000..19c5875
--- /dev/null
@@ -0,0 +1,630 @@
+/*
+ * Alpha IO and memory functions.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+/* Out-of-line versions of the i/o routines that redirect into the 
+   platform-specific version.  Note that "platform-specific" may mean
+   "generic", which bumps through the machine vector.  */
+
+unsigned int
+ioread8(void __iomem *addr)
+{
+       unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
+       mb();
+       return ret;
+}
+
+unsigned int ioread16(void __iomem *addr)
+{
+       unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
+       mb();
+       return ret;
+}
+
+unsigned int ioread32(void __iomem *addr)
+{
+       unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
+       mb();
+       return ret;
+}
+
+void iowrite8(u8 b, void __iomem *addr)
+{
+       IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr);
+       mb();
+}
+
+void iowrite16(u16 b, void __iomem *addr)
+{
+       IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr);
+       mb();
+}
+
+void iowrite32(u32 b, void __iomem *addr)
+{
+       IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr);
+       mb();
+}
+
+EXPORT_SYMBOL(ioread8);
+EXPORT_SYMBOL(ioread16);
+EXPORT_SYMBOL(ioread32);
+EXPORT_SYMBOL(iowrite8);
+EXPORT_SYMBOL(iowrite16);
+EXPORT_SYMBOL(iowrite32);
+
+u8 inb(unsigned long port)
+{
+       return ioread8(ioport_map(port, 1));
+}
+
+u16 inw(unsigned long port)
+{
+       return ioread16(ioport_map(port, 2));
+}
+
+u32 inl(unsigned long port)
+{
+       return ioread32(ioport_map(port, 4));
+}
+
+void outb(u8 b, unsigned long port)
+{
+       iowrite8(b, ioport_map(port, 1));
+}
+
+void outw(u16 b, unsigned long port)
+{
+       iowrite16(b, ioport_map(port, 2));
+}
+
+void outl(u32 b, unsigned long port)
+{
+       iowrite32(b, ioport_map(port, 4));
+}
+
+EXPORT_SYMBOL(inb);
+EXPORT_SYMBOL(inw);
+EXPORT_SYMBOL(inl);
+EXPORT_SYMBOL(outb);
+EXPORT_SYMBOL(outw);
+EXPORT_SYMBOL(outl);
+
+u8 __raw_readb(const volatile void __iomem *addr)
+{
+       return IO_CONCAT(__IO_PREFIX,readb)(addr);
+}
+
+u16 __raw_readw(const volatile void __iomem *addr)
+{
+       return IO_CONCAT(__IO_PREFIX,readw)(addr);
+}
+
+u32 __raw_readl(const volatile void __iomem *addr)
+{
+       return IO_CONCAT(__IO_PREFIX,readl)(addr);
+}
+
+u64 __raw_readq(const volatile void __iomem *addr)
+{
+       return IO_CONCAT(__IO_PREFIX,readq)(addr);
+}
+
+void __raw_writeb(u8 b, volatile void __iomem *addr)
+{
+       IO_CONCAT(__IO_PREFIX,writeb)(b, addr);
+}
+
+void __raw_writew(u16 b, volatile void __iomem *addr)
+{
+       IO_CONCAT(__IO_PREFIX,writew)(b, addr);
+}
+
+void __raw_writel(u32 b, volatile void __iomem *addr)
+{
+       IO_CONCAT(__IO_PREFIX,writel)(b, addr);
+}
+
+void __raw_writeq(u64 b, volatile void __iomem *addr)
+{
+       IO_CONCAT(__IO_PREFIX,writeq)(b, addr);
+}
+
+EXPORT_SYMBOL(__raw_readb); 
+EXPORT_SYMBOL(__raw_readw); 
+EXPORT_SYMBOL(__raw_readl); 
+EXPORT_SYMBOL(__raw_readq); 
+EXPORT_SYMBOL(__raw_writeb); 
+EXPORT_SYMBOL(__raw_writew); 
+EXPORT_SYMBOL(__raw_writel); 
+EXPORT_SYMBOL(__raw_writeq); 
+
+u8 readb(const volatile void __iomem *addr)
+{
+       u8 ret = __raw_readb(addr);
+       mb();
+       return ret;
+}
+
+u16 readw(const volatile void __iomem *addr)
+{
+       u16 ret = __raw_readw(addr);
+       mb();
+       return ret;
+}
+
+u32 readl(const volatile void __iomem *addr)
+{
+       u32 ret = __raw_readl(addr);
+       mb();
+       return ret;
+}
+
+u64 readq(const volatile void __iomem *addr)
+{
+       u64 ret = __raw_readq(addr);
+       mb();
+       return ret;
+}
+
+void writeb(u8 b, volatile void __iomem *addr)
+{
+       __raw_writeb(b, addr);
+       mb();
+}
+
+void writew(u16 b, volatile void __iomem *addr)
+{
+       __raw_writew(b, addr);
+       mb();
+}
+
+void writel(u32 b, volatile void __iomem *addr)
+{
+       __raw_writel(b, addr);
+       mb();
+}
+
+void writeq(u64 b, volatile void __iomem *addr)
+{
+       __raw_writeq(b, addr);
+       mb();
+}
+
+EXPORT_SYMBOL(readb);
+EXPORT_SYMBOL(readw);
+EXPORT_SYMBOL(readl);
+EXPORT_SYMBOL(readq);
+EXPORT_SYMBOL(writeb);
+EXPORT_SYMBOL(writew);
+EXPORT_SYMBOL(writel);
+EXPORT_SYMBOL(writeq);
+
+
+/*
+ * Read COUNT 8-bit bytes from port PORT into memory starting at SRC.
+ */
+void ioread8_rep(void __iomem *port, void *dst, unsigned long count)
+{
+       while ((unsigned long)dst & 0x3) {
+               if (!count)
+                       return;
+               count--;
+               *(unsigned char *)dst = ioread8(port);
+               dst += 1;
+       }
+
+       while (count >= 4) {
+               unsigned int w;
+               count -= 4;
+               w = ioread8(port);
+               w |= ioread8(port) << 8;
+               w |= ioread8(port) << 16;
+               w |= ioread8(port) << 24;
+               *(unsigned int *)dst = w;
+               dst += 4;
+       }
+
+       while (count) {
+               --count;
+               *(unsigned char *)dst = ioread8(port);
+               dst += 1;
+       }
+}
+
+void insb(unsigned long port, void *dst, unsigned long count)
+{
+       ioread8_rep(ioport_map(port, 1), dst, count);
+}
+
+EXPORT_SYMBOL(ioread8_rep);
+EXPORT_SYMBOL(insb);
+
+/*
+ * Read COUNT 16-bit words from port PORT into memory starting at
+ * SRC.  SRC must be at least short aligned.  This is used by the
+ * IDE driver to read disk sectors.  Performance is important, but
+ * the interfaces seems to be slow: just using the inlined version
+ * of the inw() breaks things.
+ */
+void ioread16_rep(void __iomem *port, void *dst, unsigned long count)
+{
+       if (unlikely((unsigned long)dst & 0x3)) {
+               if (!count)
+                       return;
+               BUG_ON((unsigned long)dst & 0x1);
+               count--;
+               *(unsigned short *)dst = ioread16(port);
+               dst += 2;
+       }
+
+       while (count >= 2) {
+               unsigned int w;
+               count -= 2;
+               w = ioread16(port);
+               w |= ioread16(port) << 16;
+               *(unsigned int *)dst = w;
+               dst += 4;
+       }
+
+       if (count) {
+               *(unsigned short*)dst = ioread16(port);
+       }
+}
+
+void insw(unsigned long port, void *dst, unsigned long count)
+{
+       ioread16_rep(ioport_map(port, 2), dst, count);
+}
+
+EXPORT_SYMBOL(ioread16_rep);
+EXPORT_SYMBOL(insw);
+
+
+/*
+ * Read COUNT 32-bit words from port PORT into memory starting at
+ * SRC. Now works with any alignment in SRC. Performance is important,
+ * but the interfaces seems to be slow: just using the inlined version
+ * of the inl() breaks things.
+ */
+void ioread32_rep(void __iomem *port, void *dst, unsigned long count)
+{
+       if (unlikely((unsigned long)dst & 0x3)) {
+               while (count--) {
+                       struct S { int x __attribute__((packed)); };
+                       ((struct S *)dst)->x = ioread32(port);
+                       dst += 4;
+               }
+       } else {
+               /* Buffer 32-bit aligned.  */
+               while (count--) {
+                       *(unsigned int *)dst = ioread32(port);
+                       dst += 4;
+               }
+       }
+}
+
+void insl(unsigned long port, void *dst, unsigned long count)
+{
+       ioread32_rep(ioport_map(port, 4), dst, count);
+}
+
+EXPORT_SYMBOL(ioread32_rep);
+EXPORT_SYMBOL(insl);
+
+
+/*
+ * Like insb but in the opposite direction.
+ * Don't worry as much about doing aligned memory transfers:
+ * doing byte reads the "slow" way isn't nearly as slow as
+ * doing byte writes the slow way (no r-m-w cycle).
+ */
+void iowrite8_rep(void __iomem *port, const void *xsrc, unsigned long count)
+{
+       const unsigned char *src = xsrc;
+       while (count--)
+               iowrite8(*src++, port);
+}
+
+void outsb(unsigned long port, const void *src, unsigned long count)
+{
+       iowrite8_rep(ioport_map(port, 1), src, count);
+}
+
+EXPORT_SYMBOL(iowrite8_rep);
+EXPORT_SYMBOL(outsb);
+
+
+/*
+ * Like insw but in the opposite direction.  This is used by the IDE
+ * driver to write disk sectors.  Performance is important, but the
+ * interfaces seems to be slow: just using the inlined version of the
+ * outw() breaks things.
+ */
+void iowrite16_rep(void __iomem *port, const void *src, unsigned long count)
+{
+       if (unlikely((unsigned long)src & 0x3)) {
+               if (!count)
+                       return;
+               BUG_ON((unsigned long)src & 0x1);
+               iowrite16(*(unsigned short *)src, port);
+               src += 2;
+               --count;
+       }
+
+       while (count >= 2) {
+               unsigned int w;
+               count -= 2;
+               w = *(unsigned int *)src;
+               src += 4;
+               iowrite16(w >>  0, port);
+               iowrite16(w >> 16, port);
+       }
+
+       if (count) {
+               iowrite16(*(unsigned short *)src, port);
+       }
+}
+
+void outsw(unsigned long port, const void *src, unsigned long count)
+{
+       iowrite16_rep(ioport_map(port, 2), src, count);
+}
+
+EXPORT_SYMBOL(iowrite16_rep);
+EXPORT_SYMBOL(outsw);
+
+
+/*
+ * Like insl but in the opposite direction.  This is used by the IDE
+ * driver to write disk sectors.  Works with any alignment in SRC.
+ * Performance is important, but the interfaces seems to be slow:
+ * just using the inlined version of the outl() breaks things.
+ */
+void iowrite32_rep(void __iomem *port, const void *src, unsigned long count)
+{
+       if (unlikely((unsigned long)src & 0x3)) {
+               while (count--) {
+                       struct S { int x __attribute__((packed)); };
+                       iowrite32(((struct S *)src)->x, port);
+                       src += 4;
+               }
+       } else {
+               /* Buffer 32-bit aligned.  */
+               while (count--) {
+                       iowrite32(*(unsigned int *)src, port);
+                       src += 4;
+               }
+       }
+}
+
+void outsl(unsigned long port, const void *src, unsigned long count)
+{
+       iowrite32_rep(ioport_map(port, 4), src, count);
+}
+
+EXPORT_SYMBOL(iowrite32_rep);
+EXPORT_SYMBOL(outsl);
+
+
+/*
+ * Copy data from IO memory space to "real" memory space.
+ * This needs to be optimized.
+ */
+void memcpy_fromio(void *to, const volatile void __iomem *from, long count)
+{
+       /* Optimize co-aligned transfers.  Everything else gets handled
+          a byte at a time. */
+
+       if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
+               count -= 8;
+               do {
+                       *(u64 *)to = __raw_readq(from);
+                       count -= 8;
+                       to += 8;
+                       from += 8;
+               } while (count >= 0);
+               count += 8;
+       }
+
+       if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
+               count -= 4;
+               do {
+                       *(u32 *)to = __raw_readl(from);
+                       count -= 4;
+                       to += 4;
+                       from += 4;
+               } while (count >= 0);
+               count += 4;
+       }
+
+       if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
+               count -= 2;
+               do {
+                       *(u16 *)to = __raw_readw(from);
+                       count -= 2;
+                       to += 2;
+                       from += 2;
+               } while (count >= 0);
+               count += 2;
+       }
+
+       while (count > 0) {
+               *(u8 *) to = __raw_readb(from);
+               count--;
+               to++;
+               from++;
+       }
+       mb();
+}
+
+EXPORT_SYMBOL(memcpy_fromio);
+
+
+/*
+ * Copy data from "real" memory space to IO memory space.
+ * This needs to be optimized.
+ */
+void memcpy_toio(volatile void __iomem *to, const void *from, long count)
+{
+       /* Optimize co-aligned transfers.  Everything else gets handled
+          a byte at a time. */
+       /* FIXME -- align FROM.  */
+
+       if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
+               count -= 8;
+               do {
+                       __raw_writeq(*(const u64 *)from, to);
+                       count -= 8;
+                       to += 8;
+                       from += 8;
+               } while (count >= 0);
+               count += 8;
+       }
+
+       if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
+               count -= 4;
+               do {
+                       __raw_writel(*(const u32 *)from, to);
+                       count -= 4;
+                       to += 4;
+                       from += 4;
+               } while (count >= 0);
+               count += 4;
+       }
+
+       if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
+               count -= 2;
+               do {
+                       __raw_writew(*(const u16 *)from, to);
+                       count -= 2;
+                       to += 2;
+                       from += 2;
+               } while (count >= 0);
+               count += 2;
+       }
+
+       while (count > 0) {
+               __raw_writeb(*(const u8 *) from, to);
+               count--;
+               to++;
+               from++;
+       }
+       mb();
+}
+
+EXPORT_SYMBOL(memcpy_toio);
+
+
+/*
+ * "memset" on IO memory space.
+ */
+void _memset_c_io(volatile void __iomem *to, unsigned long c, long count)
+{
+       /* Handle any initial odd byte */
+       if (count > 0 && ((u64)to & 1)) {
+               __raw_writeb(c, to);
+               to++;
+               count--;
+       }
+
+       /* Handle any initial odd halfword */
+       if (count >= 2 && ((u64)to & 2)) {
+               __raw_writew(c, to);
+               to += 2;
+               count -= 2;
+       }
+
+       /* Handle any initial odd word */
+       if (count >= 4 && ((u64)to & 4)) {
+               __raw_writel(c, to);
+               to += 4;
+               count -= 4;
+       }
+
+       /* Handle all full-sized quadwords: we're aligned
+          (or have a small count) */
+       count -= 8;
+       if (count >= 0) {
+               do {
+                       __raw_writeq(c, to);
+                       to += 8;
+                       count -= 8;
+               } while (count >= 0);
+       }
+       count += 8;
+
+       /* The tail is word-aligned if we still have count >= 4 */
+       if (count >= 4) {
+               __raw_writel(c, to);
+               to += 4;
+               count -= 4;
+       }
+
+       /* The tail is half-word aligned if we have count >= 2 */
+       if (count >= 2) {
+               __raw_writew(c, to);
+               to += 2;
+               count -= 2;
+       }
+
+       /* And finally, one last byte.. */
+       if (count) {
+               __raw_writeb(c, to);
+       }
+       mb();
+}
+
+EXPORT_SYMBOL(_memset_c_io);
+
+/* A version of memcpy used by the vga console routines to move data around
+   arbitrarily between screen and main memory.  */
+
+void
+scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
+{
+       const u16 __iomem *ios = (const u16 __iomem *) s;
+       u16 __iomem *iod = (u16 __iomem *) d;
+       int s_isio = __is_ioaddr(s);
+       int d_isio = __is_ioaddr(d);
+
+       if (s_isio) {
+               if (d_isio) {
+                       /* FIXME: Should handle unaligned ops and
+                          operation widening.  */
+
+                       count /= 2;
+                       while (count--) {
+                               u16 tmp = __raw_readw(ios++);
+                               __raw_writew(tmp, iod++);
+                       }
+               }
+               else
+                       memcpy_fromio(d, ios, count);
+       } else {
+               if (d_isio)
+                       memcpy_toio(iod, s, count);
+               else
+                       memcpy(d, s, count);
+       }
+}
+
+EXPORT_SYMBOL(scr_memcpyw);
+
+void __iomem *ioport_map(unsigned long port, unsigned int size)
+{
+       return IO_CONCAT(__IO_PREFIX,ioportmap) (port);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+}
+
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
index d626a8b..f201d8f 100644 (file)
@@ -40,32 +40,3 @@ extern struct hw_interrupt_type i8259a_irq_type;
 extern void init_i8259a_irqs(void);
 
 extern void handle_irq(int irq, struct pt_regs * regs);
-
-extern unsigned long prof_cpu_mask;
-
-static inline void
-alpha_do_profile(unsigned long pc)
-{
-       extern char _stext;
-
-       if (!prof_buffer)
-               return;
-
-       /*
-        * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-        * (default is all CPUs.)
-        */
-       if (!((1<<smp_processor_id()) & prof_cpu_mask))
-               return;
-
-       pc -= (unsigned long) &_stext;
-       pc >>= prof_shift;
-       /*
-        * Don't ignore out-of-bounds PC values silently,
-        * put them into the last histogram slot, so if
-        * present, they will show up as a sharp peak.
-        */
-       if (pc > prof_len - 1)
-               pc = prof_len - 1;
-       atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
index b8a7e3f..582a351 100644 (file)
@@ -7,8 +7,10 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/dma-mapping.h>
 
 #include "proto.h"
 
@@ -101,41 +103,112 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
        else
                return -ENODEV;
 }
-/* stubs for the routines in pci_iommu.c */
+
+/* Stubs for the routines in pci_iommu.c: */
+
 void *
 pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
 {
        return NULL;
 }
+
 void
 pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr,
                    dma_addr_t dma_addr)
 {
 }
+
 dma_addr_t
 pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size,
               int direction)
 {
        return (dma_addr_t) 0;
 }
+
 void
 pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
                 int direction)
 {
 }
+
 int
 pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
           int direction)
 {
        return 0;
 }
+
 void
 pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
             int direction)
 {
 }
+
 int
 pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
 {
        return 0;
 }
+
+/* Generic DMA mapping functions: */
+
+void *
+dma_alloc_coherent(struct device *dev, size_t size,
+                  dma_addr_t *dma_handle, int gfp)
+{
+       void *ret;
+
+       if (!dev || *dev->dma_mask >= 0xffffffffUL)
+               gfp &= ~GFP_DMA;
+       ret = (void *)__get_free_pages(gfp, get_order(size));
+       if (ret) {
+               memset(ret, 0, size);
+               *dma_handle = virt_to_bus(ret);
+       }
+       return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+          enum dma_data_direction direction)
+{
+       int i;
+
+       for (i = 0; i < nents; i++ ) {
+               void *va;
+
+               BUG_ON(!sg[i].page);
+               va = page_address(sg[i].page) + sg[i].offset;
+               sg_dma_address(sg + i) = (dma_addr_t)virt_to_bus(va);
+               sg_dma_len(sg + i) = sg[i].length;
+       }
+
+       return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+int
+dma_set_mask(struct device *dev, u64 mask)
+{
+       if (!dev->dma_mask || !dma_supported(dev, mask))
+               return -EIO;
+
+       *dev->dma_mask = mask;
+
+       return 0;
+}
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+}
+
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
index 1e3abbb..b4c64d4 100644 (file)
@@ -67,6 +67,7 @@ quirk_isa_bridge(struct pci_dev *dev)
 {
        dev->class = PCI_CLASS_BRIDGE_ISA << 8;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge);
 
 static void __init
 quirk_cypress(struct pci_dev *dev)
@@ -100,6 +101,7 @@ quirk_cypress(struct pci_dev *dev)
                }
        }
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, quirk_cypress);
 
 /* Called for each device after PCI setup is done. */
 static void __init
@@ -112,17 +114,10 @@ pcibios_fixup_final(struct pci_dev *dev)
                isa_bridge = dev;
        }
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final);
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-       { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378,
-         quirk_isa_bridge },
-       { PCI_FIXUP_HEADER, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693,
-         quirk_cypress },
-       { PCI_FIXUP_FINAL,  PCI_ANY_ID, PCI_ANY_ID,
-         pcibios_fixup_final },
-       { 0 }
-};
-
+/* Just declaring that the power-of-ten prefixes are actually the
+   power-of-two ones doesn't make it true :) */
 #define KB                     1024
 #define MB                     (1024*KB)
 #define GB                     (1024*MB)
@@ -536,3 +531,37 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
 
        return -EOPNOTSUPP;
 }
+
+/* Create an __iomem token from a PCI BAR.  Copied from lib/iomap.c with
+   no changes, since we don't want the other things in that object file.  */
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (!len || !start)
+               return NULL;
+       if (maxlen && len > maxlen)
+               len = maxlen;
+       if (flags & IORESOURCE_IO)
+               return ioport_map(start, len);
+       if (flags & IORESOURCE_MEM) {
+               /* Not checking IORESOURCE_CACHEABLE because alpha does
+                  not distinguish between ioremap and ioremap_nocache.  */
+               return ioremap(start, len);
+       }
+       return NULL;
+}
+
+/* Destroy that token.  Not copied from lib/iomap.c.  */
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+       if (__is_mmio(addr))
+               iounmap(addr);
+}
+
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
index b47c356..7cb23f1 100644 (file)
@@ -930,3 +930,42 @@ pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
 {
        return (dma_addr & ~PAGE_MASK);
 }
+
+
+/* Helper for generic DMA-mapping functions. */
+
+struct pci_dev *
+alpha_gendev_to_pci(struct device *dev)
+{
+       if (dev && dev->bus == &pci_bus_type)
+               return to_pci_dev(dev);
+
+       /* Assume that non-PCI devices asking for DMA are either ISA or EISA,
+          BUG() otherwise. */
+       BUG_ON(!isa_bridge);
+
+       /* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA
+          bridge is bus master then). */
+       if (!dev || !dev->dma_mask || !*dev->dma_mask)
+               return isa_bridge;
+
+       /* For EISA bus masters, return isa_bridge (it might have smaller
+          dma_mask due to wiring limitations). */
+       if (*dev->dma_mask >= isa_bridge->dma_mask)
+               return isa_bridge;
+
+       /* This assumes ISA bus master with dma_mask 0xffffff. */
+       return NULL;
+}
+
+int
+dma_set_mask(struct device *dev, u64 mask)
+{
+       if (!dev->dma_mask ||
+           !pci_dma_supported(alpha_gendev_to_pci(dev), mask))
+               return -EIO;
+
+       *dev->dma_mask = mask;
+
+       return 0;
+}
index 1a9b4c6..49c8c97 100644 (file)
@@ -91,15 +91,15 @@ srmcons_receive_chars(unsigned long data)
 
 /* called with callback_lock held */
 static int
-srmcons_do_write(struct tty_struct *tty, const unsigned char *buf, int count)
+srmcons_do_write(struct tty_struct *tty, const char *buf, int count)
 {
-       unsigned char *str_cr = "\r";
+       static char str_cr[1] = "\r";
        long c, remaining = count;
        srmcons_result result;
-       unsigned char *cur;
+       char *cur;
        int need_cr;
 
-       for (cur = (unsigned char *)buf; remaining > 0; ) {
+       for (cur = (char *)buf; remaining > 0; ) {
                need_cr = 0;
                /* 
                 * Break it up into reasonable size chunks to allow a chance
@@ -138,7 +138,7 @@ srmcons_write(struct tty_struct *tty, int from_user,
        unsigned long flags;
 
        if (from_user) {
-               unsigned char tmp[512];
+               char tmp[512];
                int ret = 0;
                size_t c;
 
@@ -146,7 +146,7 @@ srmcons_write(struct tty_struct *tty, int from_user,
                        if (c > sizeof(tmp))
                                c = sizeof(tmp);
                        
-                       c -= copy_from_user(tmp, buf, c);
+                       c -= copy_from_user(tmp, (const char __user *) buf, c);
 
                        if (!c) { 
                                printk("%s: EFAULT (count %d)\n",
@@ -167,7 +167,7 @@ srmcons_write(struct tty_struct *tty, int from_user,
        }
 
        spin_lock_irqsave(&srmcons_callback_lock, flags);
-       srmcons_do_write(tty, buf, count);
+       srmcons_do_write(tty, (const char *) buf, count);
        spin_unlock_irqrestore(&srmcons_callback_lock, flags);
 
        return count;
index bf2cfa1..6852eee 100644 (file)
@@ -274,7 +274,6 @@ struct alpha_machine_vector alcor_mv __initmv = {
        DO_EV5_MMU,
        DO_DEFAULT_RTC,
        DO_CIA_IO,
-       DO_CIA_BUS,
        .machine_check          = cia_machine_check,
        .max_isa_dma_address    = ALPHA_ALCOR_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = EISA_DEFAULT_IO_BASE,
@@ -292,7 +291,7 @@ struct alpha_machine_vector alcor_mv __initmv = {
        .pci_swizzle            = common_swizzle,
 
        .sys = { .cia = {
-           .gru_int_req_bits   = ALCOR_GRU_INT_REQ_BITS
+               .gru_int_req_bits = ALCOR_GRU_INT_REQ_BITS
        }}
 };
 ALIAS_MV(alcor)
@@ -302,7 +301,6 @@ struct alpha_machine_vector xlt_mv __initmv = {
        DO_EV5_MMU,
        DO_DEFAULT_RTC,
        DO_CIA_IO,
-       DO_CIA_BUS,
        .machine_check          = cia_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = EISA_DEFAULT_IO_BASE,
@@ -320,7 +318,7 @@ struct alpha_machine_vector xlt_mv __initmv = {
        .pci_swizzle            = common_swizzle,
 
        .sys = { .cia = {
-           .gru_int_req_bits   = XLT_GRU_INT_REQ_BITS
+               .gru_int_req_bits = XLT_GRU_INT_REQ_BITS
        }}
 };
 
index 568feb8..c3f9dbc 100644 (file)
@@ -327,7 +327,6 @@ struct alpha_machine_vector cabriolet_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_APECS_IO,
-       DO_APECS_BUS,
        .machine_check          = apecs_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
@@ -354,7 +353,6 @@ struct alpha_machine_vector eb164_mv __initmv = {
        DO_EV5_MMU,
        DO_DEFAULT_RTC,
        DO_CIA_IO,
-       DO_CIA_BUS,
        .machine_check          = cia_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
@@ -380,7 +378,6 @@ struct alpha_machine_vector eb66p_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_LCA_IO,
-       DO_LCA_BUS,
        .machine_check          = lca_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
@@ -405,7 +402,6 @@ struct alpha_machine_vector lx164_mv __initmv = {
        DO_EV5_MMU,
        DO_DEFAULT_RTC,
        DO_PYXIS_IO,
-       DO_CIA_BUS,
        .machine_check          = cia_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
@@ -432,7 +428,6 @@ struct alpha_machine_vector pc164_mv __initmv = {
        DO_EV5_MMU,
        DO_DEFAULT_RTC,
        DO_CIA_IO,
-       DO_CIA_BUS,
        .machine_check          = cia_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
index 035af0b..32d9c35 100644 (file)
@@ -212,7 +212,6 @@ struct alpha_machine_vector eb64p_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_APECS_IO,
-       DO_APECS_BUS,
        .machine_check          = apecs_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
@@ -238,7 +237,6 @@ struct alpha_machine_vector eb66_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_LCA_IO,
-       DO_LCA_BUS,
        .machine_check          = lca_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
index ed6ce2f..fcabb7c 100644 (file)
@@ -249,8 +249,6 @@ jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs)
        printk(KERN_CRIT "Machine check\n");
 }
 
-#define jensen_pci_tbi ((void*)0)
-
 
 /*
  * The System Vector
@@ -260,7 +258,6 @@ struct alpha_machine_vector jensen_mv __initmv = {
        .vector_name            = "Jensen",
        DO_EV4_MMU,
        IO_LITE(JENSEN,jensen),
-       BUS(jensen),
        .machine_check          = jensen_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .rtc_port               = 0x170,
index 561122b..52873d5 100644 (file)
@@ -471,7 +471,6 @@ struct alpha_machine_vector marvel_ev7_mv __initmv = {
        DO_EV7_MMU,
        DO_DEFAULT_RTC,
        DO_MARVEL_IO,
-       DO_MARVEL_BUS,
        .machine_check          = marvel_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
index a8cd711..61ac56f 100644 (file)
@@ -269,7 +269,6 @@ struct alpha_machine_vector miata_mv __initmv = {
        DO_EV5_MMU,
        DO_DEFAULT_RTC,
        DO_PYXIS_IO,
-       DO_CIA_BUS,
        .machine_check          = cia_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
index 57ed49d..a55c109 100644 (file)
@@ -221,7 +221,6 @@ struct alpha_machine_vector mikasa_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_APECS_IO,
-       DO_APECS_BUS,
        .machine_check          = mikasa_apecs_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
@@ -246,7 +245,6 @@ struct alpha_machine_vector mikasa_primo_mv __initmv = {
        DO_EV5_MMU,
        DO_DEFAULT_RTC,
        DO_CIA_IO,
-       DO_CIA_BUS,
        .machine_check          = cia_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
index fcf04ed..dd3bded 100644 (file)
@@ -250,7 +250,6 @@ struct alpha_machine_vector nautilus_mv __initmv = {
        DO_EV6_MMU,
        DO_DEFAULT_RTC,
        DO_IRONGATE_IO,
-       DO_IRONGATE_BUS,
        .machine_check          = nautilus_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
index e974cdb..02363fa 100644 (file)
@@ -303,7 +303,6 @@ struct alpha_machine_vector noritake_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_APECS_IO,
-       DO_APECS_BUS,
        .machine_check          = noritake_apecs_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = EISA_DEFAULT_IO_BASE,
@@ -328,7 +327,6 @@ struct alpha_machine_vector noritake_primo_mv __initmv = {
        DO_EV5_MMU,
        DO_DEFAULT_RTC,
        DO_CIA_IO,
-       DO_CIA_BUS,
        .machine_check          = cia_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = EISA_DEFAULT_IO_BASE,
index 0724393..38d32bc 100644 (file)
@@ -250,7 +250,6 @@ struct alpha_machine_vector rawhide_mv __initmv = {
        DO_EV5_MMU,
        DO_DEFAULT_RTC,
        DO_MCPCIA_IO,
-       DO_MCPCIA_BUS,
        .machine_check          = mcpcia_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
index 3dcbd27..dfe16bc 100644 (file)
@@ -201,7 +201,6 @@ struct alpha_machine_vector rx164_mv __initmv = {
        DO_EV5_MMU,
        DO_DEFAULT_RTC,
        DO_POLARIS_IO,
-       DO_POLARIS_BUS,
        .machine_check          = polaris_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
index e129e0e..17423dd 100644 (file)
@@ -566,7 +566,6 @@ struct alpha_machine_vector sable_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_T2_IO,
-       DO_T2_BUS,
        .machine_check          = t2_machine_check,
        .max_isa_dma_address    = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = EISA_DEFAULT_IO_BASE,
@@ -599,7 +598,6 @@ struct alpha_machine_vector sable_gamma_mv __initmv = {
        DO_EV5_MMU,
        DO_DEFAULT_RTC,
        DO_T2_IO,
-       DO_T2_BUS,
        .machine_check          = t2_machine_check,
        .max_isa_dma_address    = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = EISA_DEFAULT_IO_BASE,
@@ -631,7 +629,6 @@ struct alpha_machine_vector lynx_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_T2_IO,
-       DO_T2_BUS,
        .machine_check          = t2_machine_check,
        .max_isa_dma_address    = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = EISA_DEFAULT_IO_BASE,
index 177e127..47df48a 100644 (file)
@@ -288,7 +288,6 @@ struct alpha_machine_vector alphabook1_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_LCA_IO,
-       DO_LCA_BUS,
        .machine_check          = lca_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
@@ -319,7 +318,6 @@ struct alpha_machine_vector avanti_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_APECS_IO,
-       DO_APECS_BUS,
        .machine_check          = apecs_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
@@ -349,7 +347,6 @@ struct alpha_machine_vector noname_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_LCA_IO,
-       DO_LCA_BUS,
        .machine_check          = lca_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
@@ -388,7 +385,6 @@ struct alpha_machine_vector p2k_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_LCA_IO,
-       DO_LCA_BUS,
        .machine_check          = lca_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
@@ -418,7 +414,6 @@ struct alpha_machine_vector xl_mv __initmv = {
        DO_EV4_MMU,
        DO_DEFAULT_RTC,
        DO_APECS_IO,
-       BUS(apecs),
        .machine_check          = apecs_machine_check,
        .max_isa_dma_address    = ALPHA_XL_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
index 1114bf7..4466af6 100644 (file)
@@ -66,7 +66,7 @@ titan_update_irq_hw(unsigned long mask)
        register int bcpu = boot_cpuid;
 
 #ifdef CONFIG_SMP
-       register unsigned long cpm = cpu_present_mask;
+       cpumask_t cpm = cpu_present_mask;
        volatile unsigned long *dim0, *dim1, *dim2, *dim3;
        unsigned long mask0, mask1, mask2, mask3, dummy;
 
@@ -85,10 +85,10 @@ titan_update_irq_hw(unsigned long mask)
        dim1 = &cchip->dim1.csr;
        dim2 = &cchip->dim2.csr;
        dim3 = &cchip->dim3.csr;
-       if ((cpm & 1) == 0) dim0 = &dummy;
-       if ((cpm & 2) == 0) dim1 = &dummy;
-       if ((cpm & 4) == 0) dim2 = &dummy;
-       if ((cpm & 8) == 0) dim3 = &dummy;
+       if (!cpu_isset(0, cpm)) dim0 = &dummy;
+       if (!cpu_isset(1, cpm)) dim1 = &dummy;
+       if (!cpu_isset(2, cpm)) dim2 = &dummy;
+       if (!cpu_isset(3, cpm)) dim3 = &dummy;
 
        *dim0 = mask0;
        *dim1 = mask1;
@@ -145,12 +145,12 @@ titan_end_irq(unsigned int irq)
 }
 
 static void
-titan_cpu_set_irq_affinity(unsigned int irq, unsigned long affinity)
+titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
 {
        int cpu;
 
        for (cpu = 0; cpu < 4; cpu++) {
-               if (affinity & (1UL << cpu))
+               if (cpu_isset(cpu, affinity))
                        titan_cpu_irq_affinity[cpu] |= 1UL << irq;
                else
                        titan_cpu_irq_affinity[cpu] &= ~(1UL << irq);
@@ -159,7 +159,7 @@ titan_cpu_set_irq_affinity(unsigned int irq, unsigned long affinity)
 }
 
 static void
-titan_set_irq_affinity(unsigned int irq, unsigned long affinity)
+titan_set_irq_affinity(unsigned int irq, cpumask_t affinity)
 { 
        spin_lock(&titan_irq_lock);
        titan_cpu_set_irq_affinity(irq - 16, affinity);
@@ -369,7 +369,6 @@ struct alpha_machine_vector titan_mv __initmv = {
        DO_EV6_MMU,
        DO_DEFAULT_RTC,
        DO_TITAN_IO,
-       DO_TITAN_BUS,
        .machine_check          = titan_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
@@ -397,7 +396,6 @@ struct alpha_machine_vector privateer_mv __initmv = {
        DO_EV6_MMU,
        DO_DEFAULT_RTC,
        DO_TITAN_IO,
-       DO_TITAN_BUS,
        .machine_check          = privateer_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
index 35b0f4c..959e8d7 100644 (file)
@@ -337,7 +337,6 @@ struct alpha_machine_vector wildfire_mv __initmv = {
        DO_EV6_MMU,
        DO_DEFAULT_RTC,
        DO_WILDFIRE_IO,
-       DO_WILDFIRE_BUS,
        .machine_check          = wildfire_machine_check,
        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
        .min_io_address         = DEFAULT_IO_BASE,
index d159b8f..0922e07 100644 (file)
@@ -18,6 +18,7 @@ SECTIONS
   .text : { 
        *(.text) 
        SCHED_TEXT
+       LOCK_TEXT
        *(.fixup)
        *(.gnu.warning)
   } :kernel
@@ -45,11 +46,6 @@ SECTIONS
   .init.setup : { *(.init.setup) }
   __setup_end = .;
 
-  . = ALIGN(8);
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
-
   . = ALIGN(8);
   __initcall_start = .;
   .initcall.init : {
index a623099..21cf624 100644 (file)
@@ -17,7 +17,6 @@ lib-y =       __divqu.o __remqu.o __divlu.o __remlu.o \
        $(ev6-y)memset.o \
        $(ev6-y)memcpy.o \
        memmove.o \
-       io.o \
        checksum.o \
        csum_partial_copy.o \
        $(ev67-y)strlen.o \
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
new file mode 100644 (file)
index 0000000..266f46c
--- /dev/null
@@ -0,0 +1,115 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+# RMK wants arm kernels compiled with frame pointers so hardwire this to y.
+# If you know what you are doing and are willing to live without stack
+# traces, you can get a slightly smaller kernel by setting this option to
+# n, but then RMK will have to kill you ;).
+config FRAME_POINTER
+       bool
+       default y
+       help
+         If you say N here, the resulting kernel will be slightly smaller and
+         faster. However, when a problem occurs with the kernel, the
+         information that is reported is severely limited. Most people
+         should say Y here.
+
+config DEBUG_USER
+       bool "Verbose user fault messages"
+       help
+         When a user program crashes due to an exception, the kernel can
+         print a brief message explaining what the problem was. This is
+         sometimes helpful for debugging but serves no purpose on a
+         production system. Most people should say N here.
+
+         In addition, you need to pass user_debug=N on the kernel command
+         line to enable this feature.  N consists of the sum of:
+
+             1 - undefined instruction events
+             2 - system calls
+             4 - invalid data aborts
+             8 - SIGSEGV faults
+            16 - SIGBUS faults
+
+config DEBUG_WAITQ
+       bool "Wait queue debugging"
+       depends on DEBUG_KERNEL
+
+config DEBUG_ERRORS
+       bool "Verbose kernel error messages"
+       depends on DEBUG_KERNEL
+       help
+         This option controls verbose debugging information which can be
+         printed when the kernel detects an internal error. This debugging
+         information is useful to kernel hackers when tracking down problems,
+         but mostly meaningless to other people. It's safe to say Y unless
+         you are concerned with the code size or don't want to see these
+         messages.
+
+config DEBUG_INFO
+       bool "Include GDB debugging information in kernel binary"
+       help
+         Say Y here to include source-level debugging information in the
+         `vmlinux' binary image. This is handy if you want to use gdb or
+         addr2line to debug the kernel. It has no impact on the in-memory
+         footprint of the running kernel but it can increase the amount of
+         time and disk space needed for compilation of the kernel. If in
+         doubt say N.
+
+# These options are only for real kernel hackers who want to get their hands dirty.
+config DEBUG_LL
+       bool "Kernel low-level debugging functions"
+       depends on DEBUG_KERNEL
+       help
+         Say Y here to include definitions of printascii, printchar, printhex
+         in the kernel.  This is helpful if you are debugging code that
+         executes before the console is initialized.
+
+config DEBUG_ICEDCC
+       bool "Kernel low-level debugging via EmbeddedICE DCC channel"
+       depends on DEBUG_LL
+       help
+         Say Y here if you want the debug print routines to direct their
+         output to the EmbeddedICE macrocell's DCC channel using
+         co-processor 14. This is known to work on the ARM9 style ICE
+         channel.
+
+         It does include a timeout to ensure that the system does not
+         totally freeze when there is nothing connected to read.
+
+config DEBUG_DC21285_PORT
+       bool "Kernel low-level debugging messages via footbridge serial port"
+       depends on DEBUG_LL && FOOTBRIDGE
+       help
+         Say Y here if you want the debug print routines to direct their
+         output to the serial port in the DC21285 (Footbridge). Saying N
+         will cause the debug messages to appear on the first 16550
+         serial port.
+
+config DEBUG_CLPS711X_UART2
+       bool "Kernel low-level debugging messages via UART2"
+       depends on DEBUG_LL && ARCH_CLPS711X
+       help
+         Say Y here if you want the debug print routines to direct their
+         output to the second serial port on these devices.  Saying N will
+         cause the debug messages to appear on the first serial port.
+
+config DEBUG_S3C2410_PORT
+       depends on DEBUG_LL && ARCH_S3C2410
+       bool "Kernel low-level debugging messages via S3C2410 UART"
+       help
+         Say Y here if you want debug print routines to go to one of the
+         S3C2410 internal UARTs. The chosen UART must have been configured
+         before it is used.
+
+config DEBUG_S3C2410_UART
+       depends on DEBUG_LL && ARCH_S3C2410
+       int "S3C2410 UART to use for low-level debug"
+       default "0"
+       help
+         Choice for UART for kernel low-level using S3C2410 UARTS,
+         should be between zero and two. The port must have been
+         initalised by the boot-loader before use.
+
+endmenu
diff --git a/arch/arm/boot/compressed/big-endian.S b/arch/arm/boot/compressed/big-endian.S
new file mode 100644 (file)
index 0000000..25ab26f
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ *  linux/arch/arm/boot/compressed/big-endian.S
+ *
+ *  Switch CPU into big endian mode.
+ *  Author: Nicolas Pitre
+ */
+
+       .section ".start", #alloc, #execinstr
+
+       mrc     p15, 0, r0, c1, c0, 0   @ read control reg
+       orr     r0, r0, #(1 << 7)       @ enable big endian mode
+       mcr     p15, 0, r0, c1, c0, 0   @ write control reg
+
index ebcac6c..23434b5 100644 (file)
@@ -23,17 +23,17 @@ unsigned int __machine_arch_type;
 #include <asm/arch/uncompress.h>
 
 #ifdef STANDALONE_DEBUG
-#define puts printf
+#define putstr printf
 #endif
 
 #ifdef CONFIG_DEBUG_ICEDCC
-#define puts icedcc_puts
+#define putstr icedcc_putstr
 #define putc icedcc_putc
 
 extern void idedcc_putc(int ch);
 
 static void
-icedcc_puts(const char *ptr)
+icedcc_putstr(const char *ptr)
 {
        for (; *ptr != '\0'; ptr++) {
                icedcc_putc(*ptr);
@@ -191,7 +191,7 @@ static void error(char *m);
 static void gzip_mark(void **);
 static void gzip_release(void **);
 
-static void puts(const char *);
+static void putstr(const char *);
 
 extern int end;
 static ulg free_mem_ptr;
@@ -280,14 +280,14 @@ void flush_window(void)
        bytes_out += (ulg)outcnt;
        output_ptr += (ulg)outcnt;
        outcnt = 0;
-       puts(".");
+       putstr(".");
 }
 
 static void error(char *x)
 {
-       puts("\n\n");
-       puts(x);
-       puts("\n\n -- System halted");
+       putstr("\n\n");
+       putstr(x);
+       putstr("\n\n -- System halted");
 
        while(1);       /* Halt */
 }
@@ -306,9 +306,9 @@ decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
        arch_decomp_setup();
 
        makecrc();
-       puts("Uncompressing Linux...");
+       putstr("Uncompressing Linux...");
        gunzip();
-       puts(" done, booting the kernel.\n");
+       putstr(" done, booting the kernel.\n");
        return output_ptr;
 }
 #else
@@ -320,9 +320,9 @@ int main()
        output_data = output_buffer;
 
        makecrc();
-       puts("Uncompressing Linux...");
+       putstr("Uncompressing Linux...");
        gunzip();
-       puts("done.\n");
+       putstr("done.\n");
        return 0;
 }
 #endif
index 2b1f60f..68f4047 100644 (file)
@@ -176,7 +176,6 @@ CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_FWMARK=y
 CONFIG_IP_ROUTE_NAT=y
 # CONFIG_IP_ROUTE_MULTIPATH is not set
-# CONFIG_IP_ROUTE_TOS is not set
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig
new file mode 100644 (file)
index 0000000..2f09ba9
--- /dev/null
@@ -0,0 +1,795 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# 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_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP2400/2800 Implementation Options
+#
+
+#
+# IXP2400/2800 Platforms
+#
+CONFIG_ARCH_ENP2611=y
+# CONFIG_ARCH_IXDP2400 is not set
+# CONFIG_ARCH_IXDP2800 is not set
+# CONFIG_ARCH_IXDP2401 is not set
+# CONFIG_ARCH_IXDP2801 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL 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=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_IXP2000=y
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PCI 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_BLKMTD 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
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# 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_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_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM 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=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=y
+# CONFIG_EEPRO100_PIO 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_8139CP 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
+# CONFIG_VIA_VELOCITY 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_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO 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=y
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 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
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP2000_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF 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_ISA is not set
+# CONFIG_I2C_IXP2000 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY 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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# 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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_BDI2000_XSCALE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/ep80219_defconfig b/arch/arm/configs/ep80219_defconfig
new file mode 100644 (file)
index 0000000..fc4dbc2
--- /dev/null
@@ -0,0 +1,849 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# 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_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+CONFIG_ARCH_IOP3XX=y
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
+
+#
+# IOP3xx Implementation Options
+#
+
+#
+# IOP3xx Platform Types
+#
+# CONFIG_ARCH_IQ80321 is not set
+CONFIG_ARCH_IQ31244=y
+# CONFIG_ARCH_IQ80331 is not set
+CONFIG_ARCH_EP80219=y
+CONFIG_ARCH_IOP321=y
+# CONFIG_ARCH_IOP331 is not set
+
+#
+# IOP3xx Chipset Features
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200 mem=128M@0xa0000000"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL 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=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 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_BLKMTD 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
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# 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_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_SIZE=8192
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_LINEAR is not set
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+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 is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM 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=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=y
+CONFIG_E100_NAPI=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP 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
+# CONFIG_VIA_VELOCITY 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_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO 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_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
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+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
+
+#
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# 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_DPT_I2O is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 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
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 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
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF 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_IOP3XX=y
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR 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_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_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# 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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/h7201_defconfig b/arch/arm/configs/h7201_defconfig
new file mode 100644 (file)
index 0000000..e18dad4
--- /dev/null
@@ -0,0 +1,511 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc1
+# Thu Sep  2 11:04:11 2004
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# 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_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+CONFIG_ARCH_H720X=y
+
+#
+# h720x Implementations
+#
+CONFIG_ARCH_H7201=y
+# CONFIG_ARCH_H7202 is not set
+CONFIG_CPU_H7201=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM720T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_LV4T=y
+CONFIG_CPU_CACHE_V4=y
+CONFIG_CPU_COPY_V4WT=y
+CONFIG_CPU_TLB_V4WT=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+
+#
+# General setup
+#
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE=""
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=0
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL 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 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=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_H720X 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_BLKMTD 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
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 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
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/h7202_defconfig b/arch/arm/configs/h7202_defconfig
new file mode 100644 (file)
index 0000000..ba3f639
--- /dev/null
@@ -0,0 +1,652 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc1
+# Thu Sep 30 10:30:42 2004
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# 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_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+CONFIG_ARCH_H720X=y
+
+#
+# h720x Implementations
+#
+# CONFIG_ARCH_H7201 is not set
+CONFIG_ARCH_H7202=y
+# CONFIG_ARCH_FU7202 is not set
+CONFIG_CPU_H7202=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM720T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_LV4T=y
+CONFIG_CPU_CACHE_V4=y
+CONFIG_CPU_COPY_V4WT=y
+CONFIG_CPU_TLB_V4WT=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+
+#
+# General setup
+#
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,19200"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# 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_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL 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=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+CONFIG_MTD_H720X=y
+
+#
+# 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_BLKMTD 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
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+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 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_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_SMC91X is not set
+# CONFIG_CS89x0 is not set
+CONFIG_CIRRUS=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
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_H7202=y
+
+#
+# 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_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# 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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_SA1100 is not set
+CONFIG_USB_GADGET_H7202=y
+CONFIG_USB_H7202=m
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ETH is not set
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_G_MULTISER=m
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/iq31244_defconfig b/arch/arm/configs/iq31244_defconfig
new file mode 100644 (file)
index 0000000..64ebb89
--- /dev/null
@@ -0,0 +1,818 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# 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_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+CONFIG_ARCH_IOP3XX=y
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
+
+#
+# IOP3xx Implementation Options
+#
+
+#
+# IOP3xx Platform Types
+#
+# CONFIG_ARCH_IQ80321 is not set
+CONFIG_ARCH_IQ31244=y
+# CONFIG_ARCH_IQ80331 is not set
+# CONFIG_ARCH_EP80219 is not set
+CONFIG_ARCH_IOP321=y
+# CONFIG_ARCH_IOP331 is not set
+
+#
+# IOP3xx Chipset Features
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200 mem=256M@0xa0000000"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL 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=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 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_BLKMTD 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
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# 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_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_SIZE=8192
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_LINEAR is not set
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+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 is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO 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_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
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+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
+
+#
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# 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_DPT_I2O is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 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
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 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
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF 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_IOP3XX=y
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR 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_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_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# 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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
index c9afe24..f19320b 100644 (file)
@@ -10,27 +10,39 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 
 #
 # Loadable module support
 #
 CONFIG_MODULES=y
-# CONFIG_MODULE_UNLOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_KMOD=y
@@ -38,64 +50,42 @@ CONFIG_KMOD=y
 #
 # System Type
 #
-# CONFIG_ARCH_ADIFCC is not set
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_CAMELOT is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 CONFIG_ARCH_IOP3XX=y
+# CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
 
 #
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
+# IOP3xx Implementation Options
 #
 
 #
-# IOP3xx Implementation Options
+# IOP3xx Platform Types
 #
-# CONFIG_ARCH_IQ80310 is not set
 CONFIG_ARCH_IQ80321=y
-# CONFIG_ARCH_IOP310 is not set
+# CONFIG_ARCH_IQ31244 is not set
+# CONFIG_ARCH_IQ80331 is not set
+# CONFIG_ARCH_EP80219 is not set
 CONFIG_ARCH_IOP321=y
+# CONFIG_ARCH_IOP331 is not set
 
 #
 # IOP3xx Chipset Features
 #
-# CONFIG_IOP3XX_AAU is not set
-# CONFIG_IOP3XX_DMA is not set
-# CONFIG_IOP3XX_MU is not set
-# CONFIG_IOP3XX_PMON is not set
-
-#
-# ADIFCC Implementation Options
-#
-
-#
-# ADI Board Types
-#
-
-#
-# Intel PXA250/210 Implementations
-#
-
-#
-# SA11x0 Implementations
-#
 
 #
 # Processor Type
@@ -103,6 +93,9 @@ CONFIG_ARCH_IOP321=y
 CONFIG_CPU_32=y
 CONFIG_CPU_XSCALE=y
 CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -119,12 +112,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 # CONFIG_PCI_LEGACY_PROC is not set
 CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
 
 #
 # At least one math emulation must be selected
@@ -132,11 +119,16 @@ CONFIG_PCI_NAMES=y
 CONFIG_FPE_NWFPE=y
 # CONFIG_FPE_NWFPE_XP is not set
 # CONFIG_FPE_FASTFPE is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+# CONFIG_VFP is not set
 CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
 # CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_PM is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_ARTHUR is not set
@@ -156,6 +148,8 @@ CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
 # CONFIG_MTD_AFS_PARTS is not set
 
@@ -175,13 +169,23 @@ 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=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # 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
@@ -196,6 +200,7 @@ CONFIG_MTD_CFI_INTELEXT=y
 #
 # 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_BLKMTD is not set
 
@@ -214,7 +219,6 @@ CONFIG_MTD_CFI_INTELEXT=y
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 
 #
 # Block devices
@@ -226,6 +230,7 @@ CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_BLK_DEV_UMEM 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_SIZE=8192
 # CONFIG_BLK_DEV_INITRD is not set
@@ -243,14 +248,13 @@ CONFIG_NET=y
 #
 # Networking options
 #
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
 # CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
@@ -258,40 +262,26 @@ CONFIG_IP_PNP_BOOTP=y
 # 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_ARPD is not set
-# CONFIG_INET_ECN 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
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
+# CONFIG_NETFILTER is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
 # CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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_NET_DIVERT is not set
@@ -303,57 +293,32 @@ CONFIG_IPV6_SCTP__=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 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
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_SMC91X is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# 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_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO 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_8139CP 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
+# CONFIG_NET_ETHERNET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -373,96 +338,33 @@ CONFIG_E1000_NAPI=y
 # Ethernet (10000 Mbit)
 #
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+# CONFIG_S2IO is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Token Ring devices
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
 
 #
-# Token Ring devices (depends on LLC=y)
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
+# CONFIG_NET_RADIO is not set
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDE_TCQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_BLK_DEV_ADMA=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
@@ -470,7 +372,11 @@ CONFIG_IDEDMA_AUTO=y
 # CONFIG_SCSI is not set
 
 #
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
 #
 # CONFIG_IEEE1394 is not set
 
@@ -482,16 +388,24 @@ CONFIG_IDEDMA_AUTO=y
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
 
 #
 # Input device support
 #
-# CONFIG_INPUT is not set
+CONFIG_INPUT=y
 
 #
 # Userland interfaces
 #
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
@@ -499,14 +413,23 @@ CONFIG_IDEDMA_AUTO=y
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 # CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 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
 
 #
 # Character devices
 #
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -514,40 +437,17 @@ CONFIG_SOUND_GAMEPORT=y
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_DZ is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# L3 serial bus support
-#
-# CONFIG_L3 is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -569,54 +469,44 @@ CONFIG_UNIX98_PTY_COUNT=256
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-CONFIG_VIDEO_DEV=y
 
 #
-# Video For Linux
-#
-# CONFIG_VIDEO_PROC_FS is not set
-
-#
-# Video Adapters
+# I2C support
 #
-# CONFIG_VIDEO_PMS is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_HEXIUM_ORION is not set
-# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_I2C is not set
 
 #
-# Radio Adapters
+# Multimedia devices
 #
-# CONFIG_RADIO_GEMTEK_PCI is not set
-# CONFIG_RADIO_MAXIRADIO is not set
-# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_VIDEO_DEV is not set
 
 #
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
-# CONFIG_VIDEO_BTCX is not set
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD 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_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_XFS_FS is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
@@ -632,17 +522,19 @@ CONFIG_EXT2_FS=y
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# 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_SYSFS=y
 # CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
 #
@@ -651,6 +543,7 @@ CONFIG_RAMFS=y
 # 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
@@ -658,6 +551,10 @@ CONFIG_RAMFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 # CONFIG_JFFS2_FS_NAND 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
@@ -669,19 +566,23 @@ CONFIG_JFFS2_FS_DEBUG=0
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
 # CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
+# CONFIG_RPCSEC_GSS_KRB5 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_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -699,46 +600,51 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
-# Graphics support
+# Native Language Support
 #
-# CONFIG_FB is not set
+# CONFIG_NLS is not set
 
 #
-# Sound
+# Profiling support
 #
-# CONFIG_SOUND is not set
+# CONFIG_PROFILING is not set
 
 #
-# Misc devices
+# Graphics support
+#
+# CONFIG_FB is not set
+
 #
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
 
 #
-# Multimedia Capabilities Port drivers
+# Sound
 #
-# CONFIG_MCP is not set
+# CONFIG_SOUND is not set
 
 #
-# Console Switches
+# Misc devices
 #
-# CONFIG_SWITCHES is not set
 
 #
 # USB support
 #
 # CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
 
 #
-# Bluetooth support
+# USB Gadget Support
 #
-# CONFIG_BT is not set
+# CONFIG_USB_GADGET is not set
 
 #
 # Kernel hacking
@@ -746,14 +652,7 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_FRAME_POINTER=y
 # CONFIG_DEBUG_USER is not set
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_KERNEL is not set
 
 #
 # Security options
@@ -768,6 +667,8 @@ CONFIG_DEBUG_LL=y
 #
 # Library routines
 #
-# CONFIG_CRC32 is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/iq80331_defconfig b/arch/arm/configs/iq80331_defconfig
new file mode 100644 (file)
index 0000000..9adbf9b
--- /dev/null
@@ -0,0 +1,753 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# 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_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+CONFIG_ARCH_IOP3XX=y
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
+
+#
+# IOP3xx Implementation Options
+#
+
+#
+# IOP3xx Platform Types
+#
+# CONFIG_ARCH_IQ80321 is not set
+# CONFIG_ARCH_IQ31244 is not set
+CONFIG_ARCH_IQ80331=y
+# CONFIG_ARCH_EP80219 is not set
+CONFIG_ARCH_IOP331=y
+
+#
+# IOP3xx Chipset Features
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200 mem=128M@0x00000000"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL 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 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=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 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_BLKMTD 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
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# 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_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_SIZE=8192
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+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 is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO 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_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
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+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
+
+#
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# 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_DPT_I2O is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 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
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 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
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR 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_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_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+# CONFIG_JFFS2_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_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# 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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
new file mode 100644 (file)
index 0000000..2f028ed
--- /dev/null
@@ -0,0 +1,796 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# 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_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP2400/2800 Implementation Options
+#
+
+#
+# IXP2400/2800 Platforms
+#
+# CONFIG_ARCH_ENP2611 is not set
+CONFIG_ARCH_IXDP2400=y
+# CONFIG_ARCH_IXDP2800 is not set
+CONFIG_ARCH_IXDP2X00=y
+# CONFIG_ARCH_IXDP2401 is not set
+# CONFIG_ARCH_IXDP2801 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL 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=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_IXP2000=y
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PCI 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_BLKMTD 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
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# 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_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_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM 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=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=y
+# CONFIG_EEPRO100_PIO 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_8139CP 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
+# CONFIG_VIA_VELOCITY 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_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO 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=y
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 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
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP2000_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF 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_ISA is not set
+# CONFIG_I2C_IXP2000 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY 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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# 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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_BDI2000_XSCALE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig
new file mode 100644 (file)
index 0000000..7af19ae
--- /dev/null
@@ -0,0 +1,797 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# 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_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP2400/2800 Implementation Options
+#
+
+#
+# IXP2400/2800 Platforms
+#
+# CONFIG_ARCH_ENP2611 is not set
+# CONFIG_ARCH_IXDP2400 is not set
+# CONFIG_ARCH_IXDP2800 is not set
+CONFIG_ARCH_IXDP2401=y
+# CONFIG_ARCH_IXDP2801 is not set
+CONFIG_ARCH_IXDP2X01=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL 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=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_IXP2000=y
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PCI 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_BLKMTD 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
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# 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_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_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM 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=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_CS89x0=y
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO 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_8139CP 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
+# CONFIG_VIA_VELOCITY 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_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO 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=y
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 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
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP2000_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF 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_ISA is not set
+# CONFIG_I2C_IXP2000 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY 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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# 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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_BDI2000_XSCALE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
new file mode 100644 (file)
index 0000000..ea4b05a
--- /dev/null
@@ -0,0 +1,796 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# 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_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP2400/2800 Implementation Options
+#
+
+#
+# IXP2400/2800 Platforms
+#
+# CONFIG_ARCH_ENP2611 is not set
+# CONFIG_ARCH_IXDP2400 is not set
+CONFIG_ARCH_IXDP2800=y
+CONFIG_ARCH_IXDP2X00=y
+# CONFIG_ARCH_IXDP2401 is not set
+# CONFIG_ARCH_IXDP2801 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL 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=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_IXP2000=y
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PCI 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_BLKMTD 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
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# 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_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_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM 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=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=y
+# CONFIG_EEPRO100_PIO 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_8139CP 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
+# CONFIG_VIA_VELOCITY 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_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO 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=y
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 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
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP2000_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF 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_ISA is not set
+# CONFIG_I2C_IXP2000 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY 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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# 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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_BDI2000_XSCALE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig
new file mode 100644 (file)
index 0000000..f0b0b1c
--- /dev/null
@@ -0,0 +1,797 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# 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_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP2400/2800 Implementation Options
+#
+
+#
+# IXP2400/2800 Platforms
+#
+# CONFIG_ARCH_ENP2611 is not set
+# CONFIG_ARCH_IXDP2400 is not set
+# CONFIG_ARCH_IXDP2800 is not set
+# CONFIG_ARCH_IXDP2401 is not set
+CONFIG_ARCH_IXDP2801=y
+CONFIG_ARCH_IXDP2X01=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware ixdp2x01_clock=50000000"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL 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=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_IXP2000=y
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PCI 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_BLKMTD 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
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# 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_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_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM 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=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_CS89x0=y
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO 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_8139CP 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
+# CONFIG_VIA_VELOCITY 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_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO 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=y
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 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
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP2000_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF 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_ISA is not set
+# CONFIG_I2C_IXP2000 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY 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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# 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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_BDI2000_XSCALE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
index 1933c70..7b821f8 100644 (file)
@@ -308,7 +308,6 @@ CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_FWMARK=y
 CONFIG_IP_ROUTE_NAT=y
 CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
diff --git a/arch/arm/configs/mx1ads_defconfig b/arch/arm/configs/mx1ads_defconfig
new file mode 100644 (file)
index 0000000..89da10c
--- /dev/null
@@ -0,0 +1,652 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_IOSCHED_NOOP is not set
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# 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_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 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
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_IMX=y
+
+#
+# IMX Implementations
+#
+CONFIG_ARCH_MX1ADS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# General setup
+#
+CONFIG_ISA=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_CPU_FREQ is not set
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+CONFIG_FPE_FASTFPE=y
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+CONFIG_PREEMPT=y
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttySMX0,57600n8 ip=bootp root=/dev/nfs"
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+# 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_MX1ADS=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD 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
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD 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_RAM is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL 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 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# 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_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# 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_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=m
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+
+#
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_DES 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_ARC4 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
index d9e4587..9919e7f 100644 (file)
@@ -77,6 +77,12 @@ CONFIG_ARCH_H1940=y
 CONFIG_ARCH_SMDK2410=y
 CONFIG_MACH_VR1000=y
 
+#
+# S3C2410 Setup
+#
+CONFIG_S3C2410_DMA=y
+# CONFIG_S3C2410_DMA_DEBUG is not set
+
 #
 # Processor Type
 #
@@ -601,6 +607,8 @@ CONFIG_ROMFS_FS=y
 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
 
 #
index a64f78d..70aade0 100644 (file)
 /*
  * Maximum number of events stored
  */
-#define APM_MAX_EVENTS         20
+#define APM_MAX_EVENTS         16
+
+struct apm_queue {
+       unsigned int            event_head;
+       unsigned int            event_tail;
+       apm_event_t             events[APM_MAX_EVENTS];
+};
 
 /*
  * The per-file APM data
 struct apm_user {
        struct list_head        list;
 
-       int                     suser: 1;
-       int                     writer: 1;
-       int                     reader: 1;
-       int                     suspend_wait: 1;
-       int                     suspend_result;
-
-       int                     suspends_pending;
-       int                     standbys_pending;
-       unsigned int            suspends_read;
-       unsigned int            standbys_read;
+       unsigned int            suser: 1;
+       unsigned int            writer: 1;
+       unsigned int            reader: 1;
 
-       int                     event_head;
-       int                     event_tail;
-       apm_event_t             events[APM_MAX_EVENTS];
+       int                     suspend_result;
+       unsigned int            suspend_state;
+#define SUSPEND_NONE   0               /* no suspend pending */
+#define SUSPEND_PENDING        1               /* suspend pending read */
+#define SUSPEND_READ   2               /* suspend read, pending ack */
+#define SUSPEND_ACKED  3               /* suspend acked */
+#define SUSPEND_DONE   4               /* suspend completed */
+
+       struct apm_queue        queue;
 };
 
 /*
  * Local variables
  */
 static int suspends_pending;
-static int standbys_pending;
 static int apm_disabled;
 
 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
@@ -83,14 +87,19 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 /*
  * This is a list of everyone who has opened /dev/apm_bios
  */
-static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED;
+static DECLARE_RWSEM(user_list_lock);
 static LIST_HEAD(apm_user_list);
 
 /*
- * The kapmd info.
+ * kapmd info.  kapmd provides us a process context to handle
+ * "APM" events within - specifically necessary if we're going
+ * to be suspending the system.
  */
-static struct task_struct *kapmd;
+static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
 static DECLARE_COMPLETION(kapmd_exit);
+static spinlock_t kapmd_queue_lock = SPIN_LOCK_UNLOCKED;
+static struct apm_queue kapmd_queue;
+
 
 static const char driver_version[] = "1.13";   /* no spaces */
 
@@ -102,19 +111,6 @@ static const char driver_version[] = "1.13";       /* no spaces */
  */
 static void __apm_get_power_status(struct apm_power_info *info)
 {
-#if 0 && defined(CONFIG_SA1100_H3600) && defined(CONFIG_TOUCHSCREEN_H3600)
-       extern int h3600_apm_get_power_status(u_char *, u_char *, u_char *,
-                                             u_char *, u_short *);
-
-       if (machine_is_h3600()) {
-               int dx;
-               h3600_apm_get_power_status(&info->ac_line_status,
-                               &info->battery_status, &info->battery_flag,
-                               &info->battery_life, &dx);
-               info->time = dx & 0x7fff;
-               info->units = dx & 0x8000 ? 0 : 1;
-       }
-#endif
 }
 
 /*
@@ -123,65 +119,71 @@ static void __apm_get_power_status(struct apm_power_info *info)
 void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
 EXPORT_SYMBOL(apm_get_power_status);
 
-static int queue_empty(struct apm_user *as)
+
+/*
+ * APM event queue management.
+ */
+static inline int queue_empty(struct apm_queue *q)
 {
-       return as->event_head == as->event_tail;
+       return q->event_head == q->event_tail;
 }
 
-static apm_event_t get_queued_event(struct apm_user *as)
+static inline apm_event_t queue_get_event(struct apm_queue *q)
 {
-       as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
-       return as->events[as->event_tail];
+       q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+       return q->events[q->event_tail];
 }
 
-static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+static void queue_add_event(struct apm_queue *q, apm_event_t event)
 {
-       as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
-       if (as->event_head == as->event_tail) {
+       q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
+       if (q->event_head == q->event_tail) {
                static int notified;
 
                if (notified++ == 0)
                    printk(KERN_ERR "apm: an event queue overflowed\n");
-               as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+               q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
        }
-       as->events[as->event_head] = event;
-
-       if (!as->suser || !as->writer)
-               return;
-
-       switch (event) {
-       case APM_SYS_SUSPEND:
-       case APM_USER_SUSPEND:
-               as->suspends_pending++;
-               suspends_pending++;
-               break;
+       q->events[q->event_head] = event;
+}
 
-       case APM_SYS_STANDBY:
-       case APM_USER_STANDBY:
-               as->standbys_pending++;
-               standbys_pending++;
-               break;
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+       if (as->suser && as->writer) {
+               switch (event) {
+               case APM_SYS_SUSPEND:
+               case APM_USER_SUSPEND:
+                       /*
+                        * If this user already has a suspend pending,
+                        * don't queue another one.
+                        */
+                       if (as->suspend_state != SUSPEND_NONE)
+                               return;
+
+                       as->suspend_state = SUSPEND_PENDING;
+                       suspends_pending++;
+                       break;
+               }
        }
+       queue_add_event(&as->queue, event);
 }
 
 static void queue_event(apm_event_t event, struct apm_user *sender)
 {
-       struct list_head *l;
-
-       spin_lock(&user_list_lock);
-       list_for_each(l, &apm_user_list) {
-               struct apm_user *as = list_entry(l, struct apm_user, list);
+       struct apm_user *as;
 
+       down_read(&user_list_lock);
+       list_for_each_entry(as, &apm_user_list, list) {
                if (as != sender && as->reader)
                        queue_event_one_user(as, event);
        }
-       spin_unlock(&user_list_lock);
+       up_read(&user_list_lock);
        wake_up_interruptible(&apm_waitqueue);
 }
 
-static int apm_suspend(void)
+static void apm_suspend(void)
 {
-       struct list_head *l;
+       struct apm_user *as;
        int err = pm_suspend(PM_SUSPEND_MEM);
 
        /*
@@ -193,52 +195,39 @@ static int apm_suspend(void)
        /*
         * Finally, wake up anyone who is sleeping on the suspend.
         */
-       spin_lock(&user_list_lock);
-       list_for_each(l, &apm_user_list) {
-               struct apm_user *as = list_entry(l, struct apm_user, list);
-
+       down_read(&user_list_lock);
+       list_for_each_entry(as, &apm_user_list, list) {
                as->suspend_result = err;
-               as->suspend_wait = 0;
+               as->suspend_state = SUSPEND_DONE;
        }
-       spin_unlock(&user_list_lock);
+       up_read(&user_list_lock);
 
-       wake_up_interruptible(&apm_suspend_waitqueue);
-       return err;
+       wake_up(&apm_suspend_waitqueue);
 }
 
 static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
 {
        struct apm_user *as = fp->private_data;
        apm_event_t event;
-       int i = count, ret = 0, nonblock = fp->f_flags & O_NONBLOCK;
+       int i = count, ret = 0;
 
        if (count < sizeof(apm_event_t))
                return -EINVAL;
 
-       if (queue_empty(as) && nonblock)
+       if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
                return -EAGAIN;
 
-       wait_event_interruptible(apm_waitqueue, !queue_empty(as));
+       wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
 
-       while ((i >= sizeof(event)) && !queue_empty(as)) {
-               event = get_queued_event(as);
-               printk("  apm_read: event=%d\n", event);
+       while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
+               event = queue_get_event(&as->queue);
 
                ret = -EFAULT;
                if (copy_to_user(buf, &event, sizeof(event)))
                        break;
 
-               switch (event) {
-               case APM_SYS_SUSPEND:
-               case APM_USER_SUSPEND:
-                       as->suspends_read++;
-                       break;
-
-               case APM_SYS_STANDBY:
-               case APM_USER_STANDBY:
-                       as->standbys_read++;
-                       break;
-               }
+               if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
+                       as->suspend_state = SUSPEND_READ;
 
                buf += sizeof(event);
                i -= sizeof(event);
@@ -252,10 +241,10 @@ static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t
 
 static unsigned int apm_poll(struct file *fp, poll_table * wait)
 {
-       struct apm_user * as = fp->private_data;
+       struct apm_user *as = fp->private_data;
 
        poll_wait(fp, &apm_waitqueue, wait);
-       return queue_empty(as) ? 0 : POLLIN | POLLRDNORM;
+       return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
 }
 
 /*
@@ -272,43 +261,65 @@ static int
 apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
 {
        struct apm_user *as = filp->private_data;
+       unsigned long flags;
        int err = -EINVAL;
 
        if (!as->suser || !as->writer)
                return -EPERM;
 
        switch (cmd) {
-       case APM_IOC_STANDBY:
-               break;
-
        case APM_IOC_SUSPEND:
-               /*
-                * If we read a suspend command from /dev/apm_bios,
-                * then the corresponding APM_IOC_SUSPEND ioctl is
-                * interpreted as an acknowledge.
-                */
-               if (as->suspends_read > 0) {
-                       as->suspends_read--;
-                       as->suspends_pending--;
+               as->suspend_result = -EINTR;
+
+               if (as->suspend_state == SUSPEND_READ) {
+                       /*
+                        * If we read a suspend command from /dev/apm_bios,
+                        * then the corresponding APM_IOC_SUSPEND ioctl is
+                        * interpreted as an acknowledge.
+                        */
+                       as->suspend_state = SUSPEND_ACKED;
                        suspends_pending--;
                } else {
+                       /*
+                        * Otherwise it is a request to suspend the system.
+                        * Queue an event for all readers, and expect an
+                        * acknowledge from all writers who haven't already
+                        * acknowledged.
+                        */
                        queue_event(APM_USER_SUSPEND, as);
                }
 
                /*
-                * If there are outstanding suspend requests for other
-                * people on /dev/apm_bios, we must sleep for them.
-                * Last one to bed turns the lights out.
+                * If there are no further acknowledges required, suspend
+                * the system.
                 */
-               if (suspends_pending > 0) {
-                       as->suspend_wait = 1;
-                       err = wait_event_interruptible(apm_suspend_waitqueue,
-                                                as->suspend_wait == 0);
-                       if (err == 0)
-                               err = as->suspend_result;
-               } else {                        
-                       err = apm_suspend();
-               }
+               if (suspends_pending == 0)
+                       apm_suspend();
+
+               /*
+                * Wait for the suspend/resume to complete.  If there are
+                * pending acknowledges, we wait here for them.
+                *
+                * Note that we need to ensure that the PM subsystem does
+                * not kick us out of the wait when it suspends the threads.
+                */
+               flags = current->flags;
+               current->flags |= PF_NOFREEZE;
+
+               /*
+                * Note: do not allow a thread which is acking the suspend
+                * to escape until the resume is complete.
+                */
+               if (as->suspend_state == SUSPEND_ACKED)
+                       wait_event(apm_suspend_waitqueue,
+                                        as->suspend_state == SUSPEND_DONE);
+               else
+                       wait_event_interruptible(apm_suspend_waitqueue,
+                                        as->suspend_state == SUSPEND_DONE);
+
+               current->flags = flags;
+               err = as->suspend_result;
+               as->suspend_state = SUSPEND_NONE;
                break;
        }
 
@@ -320,24 +331,19 @@ static int apm_release(struct inode * inode, struct file * filp)
        struct apm_user *as = filp->private_data;
        filp->private_data = NULL;
 
-       spin_lock(&user_list_lock);
+       down_write(&user_list_lock);
        list_del(&as->list);
-       spin_unlock(&user_list_lock);
+       up_write(&user_list_lock);
 
        /*
         * We are now unhooked from the chain.  As far as new
         * events are concerned, we no longer exist.  However, we
-        * need to balance standbys_pending and suspends_pending,
-        * which means the possibility of sleeping.
+        * need to balance suspends_pending, which means the
+        * possibility of sleeping.
         */
-       if (as->standbys_pending > 0) {
-               standbys_pending -= as->standbys_pending;
-//             if (standbys_pending <= 0)
-//                     standby();
-       }
-       if (as->suspends_pending > 0) {
-               suspends_pending -= as->suspends_pending;
-               if (suspends_pending <= 0)
+       if (as->suspend_state != SUSPEND_NONE) {
+               suspends_pending -= 1;
+               if (suspends_pending == 0)
                        apm_suspend();
        }
 
@@ -364,9 +370,9 @@ static int apm_open(struct inode * inode, struct file * filp)
                as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
                as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
 
-               spin_lock(&user_list_lock);
+               down_write(&user_list_lock);
                list_add(&as->list, &apm_user_list);
-               spin_unlock(&user_list_lock);
+               up_write(&user_list_lock);
 
                filp->private_data = as;
        }
@@ -438,7 +444,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
        info.ac_line_status = 0xff;
        info.battery_status = 0xff;
        info.battery_flag   = 0xff;
-       info.battery_life   = 255;
+       info.battery_life   = -1;
        info.time           = -1;
        info.units          = -1;
 
@@ -461,34 +467,53 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
 }
 #endif
 
-#if 0
-static int kapmd(void *startup)
+static int kapmd(void *arg)
 {
-       struct task_struct *tsk = current;
+       daemonize("kapmd");
+       current->flags |= PF_NOFREEZE;
 
-       daemonize();
-       strcpy(tsk->comm, "kapmd");
-       kapmd = tsk;
+       do {
+               apm_event_t event;
 
-       spin_lock_irq(&tsk->sigmask_lock);
-       siginitsetinv(&tsk->blocked, sigmask(SIGQUIT));
-       recalc_sigpending(tsk);
-       spin_unlock_irq(&tsk->sigmask_lock);
+               wait_event_interruptible(kapmd_wait,
+                               !queue_empty(&kapmd_queue) || !pm_active);
 
-       complete((struct completion *)startup);
+               if (!pm_active)
+                       break;
 
-       do {
-               set_task_state(tsk, TASK_INTERRUPTIBLE);
-               schedule();
-       } while (!signal_pending(tsk));
+               spin_lock_irq(&kapmd_queue_lock);
+               event = 0;
+               if (!queue_empty(&kapmd_queue))
+                       event = queue_get_event(&kapmd_queue);
+               spin_unlock_irq(&kapmd_queue_lock);
+
+               switch (event) {
+               case 0:
+                       break;
+
+               case APM_LOW_BATTERY:
+               case APM_POWER_STATUS_CHANGE:
+                       queue_event(event, NULL);
+                       break;
+
+               case APM_USER_SUSPEND:
+               case APM_SYS_SUSPEND:
+                       queue_event(event, NULL);
+                       if (suspends_pending == 0)
+                               apm_suspend();
+                       break;
+
+               case APM_CRITICAL_SUSPEND:
+                       apm_suspend();
+                       break;
+               }
+       } while (1);
 
        complete_and_exit(&kapmd_exit, 0);
 }
-#endif
 
 static int __init apm_init(void)
 {
-//     struct completion startup = COMPLETION_INITIALIZER(startup);
        int ret;
 
        if (apm_disabled) {
@@ -501,22 +526,24 @@ static int __init apm_init(void)
                return -EINVAL;
        }
 
-//     ret = kernel_thread(kapmd, &startup, CLONE_FS | CLONE_FILES);
-//     if (ret)
-//             return ret;
-//     wait_for_completion(&startup);
-
        pm_active = 1;
 
+       ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
+       if (ret < 0) {
+               pm_active = 0;
+               return ret;
+       }
+
 #ifdef CONFIG_PROC_FS
        create_proc_info_entry("apm", 0, NULL, apm_get_info);
 #endif
 
        ret = misc_register(&apm_device);
        if (ret != 0) {
-               pm_active = 0;
                remove_proc_entry("apm", NULL);
-               send_sig(SIGQUIT, kapmd, 1);
+
+               pm_active = 0;
+               wake_up(&kapmd_wait);
                wait_for_completion(&kapmd_exit);
        }
 
@@ -527,9 +554,10 @@ static void __exit apm_exit(void)
 {
        misc_deregister(&apm_device);
        remove_proc_entry("apm", NULL);
+
        pm_active = 0;
-//     send_sig(SIGQUIT, kapmd, 1);
-//     wait_for_completion(&kapmd_exit);
+       wake_up(&kapmd_wait);
+       wait_for_completion(&kapmd_exit);
 }
 
 module_init(apm_init);
@@ -556,3 +584,27 @@ static int __init apm_setup(char *str)
 
 __setup("apm=", apm_setup);
 #endif
+
+/**
+ * apm_queue_event - queue an APM event for kapmd
+ * @event: APM event
+ *
+ * Queue an APM event for kapmd to process and ultimately take the
+ * appropriate action.  Only a subset of events are handled:
+ *   %APM_LOW_BATTERY
+ *   %APM_POWER_STATUS_CHANGE
+ *   %APM_USER_SUSPEND
+ *   %APM_SYS_SUSPEND
+ *   %APM_CRITICAL_SUSPEND
+ */
+void apm_queue_event(apm_event_t event)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&kapmd_queue_lock, flags);
+       queue_add_event(&kapmd_queue, event);
+       spin_unlock_irqrestore(&kapmd_queue_lock, flags);
+
+       wake_up_interruptible(&kapmd_wait);
+}
+EXPORT_SYMBOL(apm_queue_event);
index 3da0b80..d868099 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/kernel/calls.S
  *
- *  Copyright (C) 1995-2003 Russell King
+ *  Copyright (C) 1995-2004 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
@@ -288,6 +288,13 @@ __syscall_start:
                .long   sys_pciconfig_iobase
                .long   sys_pciconfig_read
                .long   sys_pciconfig_write
+               .long   sys_mq_open
+/* 275 */      .long   sys_mq_unlink
+               .long   sys_mq_timedsend
+               .long   sys_mq_timedreceive
+               .long   sys_mq_notify
+               .long   sys_mq_getsetattr
+/* 280 */      .long   sys_waitid
 __syscall_end:
 
                .rept   NR_syscalls - (__syscall_end - __syscall_start) / 4
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
new file mode 100644 (file)
index 0000000..8f74e24
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ *  linux/arch/arm/kernel/iwmmxt.S
+ *
+ *  XScale iWMMXt (Concan) context switching and handling
+ *
+ *  Initial code:
+ *  Copyright (c) 2003, Intel Corporation
+ *
+ *  Full lazy switching support, optimizations and more, by Nicolas Pitre
+*   Copyright (c) 2003-2004, 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.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/thread_info.h>
+#include <asm/constants.h>
+
+#define MMX_WR0                        (0x00)
+#define MMX_WR1                        (0x08)
+#define MMX_WR2                        (0x10)
+#define MMX_WR3                        (0x18)
+#define MMX_WR4                        (0x20)
+#define MMX_WR5                        (0x28)
+#define MMX_WR6                        (0x30)
+#define MMX_WR7                        (0x38)
+#define MMX_WR8                        (0x40)
+#define MMX_WR9                        (0x48)
+#define MMX_WR10               (0x50)
+#define MMX_WR11               (0x58)
+#define MMX_WR12               (0x60)
+#define MMX_WR13               (0x68)
+#define MMX_WR14               (0x70)
+#define MMX_WR15               (0x78)
+#define MMX_WCSSF              (0x80)
+#define MMX_WCASF              (0x84)
+#define MMX_WCGR0              (0x88)
+#define MMX_WCGR1              (0x8C)
+#define MMX_WCGR2              (0x90)
+#define MMX_WCGR3              (0x94)
+
+#define MMX_SIZE               (0x98)
+
+       .text
+
+/*
+ * Lazy switching of Concan coprocessor context
+ *
+ * r10 = struct thread_info pointer
+ * r9  = ret_from_exception
+ * lr  = undefined instr exit
+ *
+ * called from prefetch exception handler with interrupts disabled
+ */
+
+ENTRY(iwmmxt_task_enable)
+
+       mrc     p15, 0, r2, c15, c1, 0
+       tst     r2, #0x3                        @ CP0 and CP1 accessible?
+       movne   pc, lr                          @ if so no business here
+       orr     r2, r2, #0x3                    @ enable access to CP0 and CP1
+       mcr     p15, 0, r2, c15, c1, 0
+
+       ldr     r3, =concan_owner
+       add     r0, r10, #TI_IWMMXT_STATE       @ get task Concan save area
+       ldr     r2, [sp, #60]                   @ current task pc value
+       ldr     r1, [r3]                        @ get current Concan owner
+       str     r0, [r3]                        @ this task now owns Concan regs
+       sub     r2, r2, #4                      @ adjust pc back
+       str     r2, [sp, #60]
+
+       mrc     p15, 0, r2, c2, c0, 0
+       mov     r2, r2                          @ cpwait
+
+       teq     r1, #0                          @ test for last ownership
+       mov     lr, r9                          @ normal exit from exception
+       beq     concan_load                     @ no owner, skip save
+
+concan_save:
+
+       tmrc    r2, wCon
+
+       @ CUP? wCx
+       tst     r2, #0x1
+       beq     1f
+
+concan_dump:
+
+       wstrw   wCSSF, [r1, #MMX_WCSSF]
+       wstrw   wCASF, [r1, #MMX_WCASF]
+       wstrw   wCGR0, [r1, #MMX_WCGR0]
+       wstrw   wCGR1, [r1, #MMX_WCGR1]
+       wstrw   wCGR2, [r1, #MMX_WCGR2]
+       wstrw   wCGR3, [r1, #MMX_WCGR3]
+
+1:     @ MUP? wRn
+       tst     r2, #0x2
+       beq     2f
+
+       wstrd   wR0,  [r1, #MMX_WR0]
+       wstrd   wR1,  [r1, #MMX_WR1]
+       wstrd   wR2,  [r1, #MMX_WR2]
+       wstrd   wR3,  [r1, #MMX_WR3]
+       wstrd   wR4,  [r1, #MMX_WR4]
+       wstrd   wR5,  [r1, #MMX_WR5]
+       wstrd   wR6,  [r1, #MMX_WR6]
+       wstrd   wR7,  [r1, #MMX_WR7]
+       wstrd   wR8,  [r1, #MMX_WR8]
+       wstrd   wR9,  [r1, #MMX_WR9]
+       wstrd   wR10, [r1, #MMX_WR10]
+       wstrd   wR11, [r1, #MMX_WR11]
+       wstrd   wR12, [r1, #MMX_WR12]
+       wstrd   wR13, [r1, #MMX_WR13]
+       wstrd   wR14, [r1, #MMX_WR14]
+       wstrd   wR15, [r1, #MMX_WR15]
+
+2:     teq     r0, #0                          @ anything to load?
+       moveq   pc, lr
+
+concan_load:
+
+       @ Load wRn
+       wldrd   wR0,  [r0, #MMX_WR0]
+       wldrd   wR1,  [r0, #MMX_WR1]
+       wldrd   wR2,  [r0, #MMX_WR2]
+       wldrd   wR3,  [r0, #MMX_WR3]
+       wldrd   wR4,  [r0, #MMX_WR4]
+       wldrd   wR5,  [r0, #MMX_WR5]
+       wldrd   wR6,  [r0, #MMX_WR6]
+       wldrd   wR7,  [r0, #MMX_WR7]
+       wldrd   wR8,  [r0, #MMX_WR8]
+       wldrd   wR9,  [r0, #MMX_WR9]
+       wldrd   wR10, [r0, #MMX_WR10]
+       wldrd   wR11, [r0, #MMX_WR11]
+       wldrd   wR12, [r0, #MMX_WR12]
+       wldrd   wR13, [r0, #MMX_WR13]
+       wldrd   wR14, [r0, #MMX_WR14]
+       wldrd   wR15, [r0, #MMX_WR15]
+
+       @ Load wCx
+       wldrw   wCSSF, [r0, #MMX_WCSSF]
+       wldrw   wCASF, [r0, #MMX_WCASF]
+       wldrw   wCGR0, [r0, #MMX_WCGR0]
+       wldrw   wCGR1, [r0, #MMX_WCGR1]
+       wldrw   wCGR2, [r0, #MMX_WCGR2]
+       wldrw   wCGR3, [r0, #MMX_WCGR3]
+
+       @ clear CUP/MUP (only if r1 != 0)
+       teq     r1, #0
+       mov     r2, #0
+       moveq   pc, lr
+       tmcr    wCon, r2
+       mov     pc, lr
+
+/*
+ * Back up Concan regs to save area and disable access to them
+ * (mainly for gdb or sleep mode usage)
+ *
+ * r0 = struct thread_info pointer of target task or NULL for any
+ */
+
+ENTRY(iwmmxt_task_disable)
+
+       stmfd   sp!, {r4, lr}
+
+       mrs     ip, cpsr
+       orr     r2, ip, #PSR_I_BIT              @ disable interrupts
+       msr     cpsr_c, r2
+
+       ldr     r3, =concan_owner
+       add     r2, r0, #TI_IWMMXT_STATE        @ get task Concan save area
+       ldr     r1, [r3]                        @ get current Concan owner
+       teq     r1, #0                          @ any current owner?
+       beq     1f                              @ no: quit
+       teq     r0, #0                          @ any owner?
+       teqne   r1, r2                          @ or specified one?
+       bne     1f                              @ no: quit
+
+       mrc     p15, 0, r4, c15, c1, 0
+       orr     r4, r4, #0x3                    @ enable access to CP0 and CP1
+       mcr     p15, 0, r4, c15, c1, 0
+       mov     r0, #0                          @ nothing to load
+       str     r0, [r3]                        @ no more current owner
+       mrc     p15, 0, r2, c2, c0, 0
+       mov     r2, r2                          @ cpwait
+       bl      concan_save
+
+       bic     r4, r4, #0x3                    @ disable access to CP0 and CP1
+       mcr     p15, 0, r4, c15, c1, 0
+       mrc     p15, 0, r2, c2, c0, 0
+       mov     r2, r2                          @ cpwait
+
+1:     msr     cpsr_c, ip                      @ restore interrupt mode
+       ldmfd   sp!, {r4, pc}
+
+/*
+ * Copy Concan state to given memory address
+ *
+ * r0 = struct thread_info pointer of target task
+ * r1 = memory address where to store Concan state
+ *
+ * this is called mainly in the creation of signal stack frames
+ */
+
+ENTRY(iwmmxt_task_copy)
+
+       mrs     ip, cpsr
+       orr     r2, ip, #PSR_I_BIT              @ disable interrupts
+       msr     cpsr_c, r2
+
+       ldr     r3, =concan_owner
+       add     r2, r0, #TI_IWMMXT_STATE        @ get task Concan save area
+       ldr     r3, [r3]                        @ get current Concan owner
+       teq     r2, r3                          @ does this task own it...
+       beq     1f
+
+       @ current Concan values are in the task save area
+       msr     cpsr_c, ip                      @ restore interrupt mode
+       mov     r0, r1
+       mov     r1, r2
+       mov     r2, #MMX_SIZE
+       b       memcpy
+
+1:     @ this task owns Concan regs -- grab a copy from there
+       mov     r0, #0                          @ nothing to load
+       mov     r2, #3                          @ save all regs
+       mov     r3, lr                          @ preserve return address
+       bl      concan_dump
+       msr     cpsr_c, ip                      @ restore interrupt mode
+       mov     pc, r3
+
+/*
+ * Restore Concan state from given memory address
+ *
+ * r0 = struct thread_info pointer of target task
+ * r1 = memory address where to get Concan state from
+ *
+ * this is used to restore Concan state when unwinding a signal stack frame
+ */
+
+ENTRY(iwmmxt_task_restore)
+
+       mrs     ip, cpsr
+       orr     r2, ip, #PSR_I_BIT              @ disable interrupts
+       msr     cpsr_c, r2
+
+       ldr     r3, =concan_owner
+       add     r2, r0, #TI_IWMMXT_STATE        @ get task Concan save area
+       ldr     r3, [r3]                        @ get current Concan owner
+       bic     r2, r2, #0x7                    @ 64-bit alignment
+       teq     r2, r3                          @ does this task own it...
+       beq     1f
+
+       @ this task doesn't own Concan regs -- use its save area
+       msr     cpsr_c, ip                      @ restore interrupt mode
+       mov     r0, r2
+       mov     r2, #MMX_SIZE
+       b       memcpy
+
+1:     @ this task owns Concan regs -- load them directly
+       mov     r0, r1
+       mov     r1, #0                          @ don't clear CUP/MUP
+       mov     r3, lr                          @ preserve return address
+       bl      concan_load
+       msr     cpsr_c, ip                      @ restore interrupt mode
+       mov     pc, r3
+
+/*
+ * Concan handling on task switch
+ *
+ * r0 = previous task_struct pointer (must be preserved)
+ * r1 = previous thread_info pointer
+ * r2 = next thread_info.cpu_domain pointer (must be preserved)
+ *
+ * Called only from __switch_to with task preemption disabled.
+ * No need to care about preserving r4 and above.
+ */
+ENTRY(iwmmxt_task_switch)
+
+       mrc     p15, 0, r4, c15, c1, 0
+       tst     r4, #0x3                        @ CP0 and CP1 accessible?
+       bne     1f                              @ yes: block them for next task
+
+       ldr     r5, =concan_owner
+       add     r6, r2, #(TI_IWMMXT_STATE - TI_CPU_DOMAIN) @ get next task Concan save area
+       ldr     r5, [r5]                        @ get current Concan owner
+       teq     r5, r6                          @ next task owns it?
+       movne   pc, lr                          @ no: leave Concan disabled
+
+1:     eor     r4, r4, #3                      @ flip Concan access
+       mcr     p15, 0, r4, c15, c1, 0
+
+       mrc     p15, 0, r4, c2, c0, 0
+       sub     pc, lr, r4, lsr #32             @ cpwait and return
+
+/*
+ * Remove Concan ownership of given task
+ *
+ * r0 = struct thread_info pointer
+ */
+ENTRY(iwmmxt_task_release)
+
+       mrs     r2, cpsr
+       orr     ip, r2, #PSR_I_BIT              @ disable interrupts
+       msr     cpsr_c, ip
+       ldr     r3, =concan_owner
+       add     r0, r0, #TI_IWMMXT_STATE        @ get task Concan save area
+       ldr     r1, [r3]                        @ get current Concan owner
+       eors    r0, r0, r1                      @ if equal...
+       streq   r0, [r3]                        @ then clear ownership
+       msr     cpsr_c, r2                      @ restore interrupts
+       mov     pc, lr
+
+       .data
+concan_owner:
+       .word   0
+
index a5db0dd..1131500 100644 (file)
@@ -38,9 +38,6 @@ SECTIONS
                __early_begin = .;
                        *(__early_param)
                __early_end = .;
-               __start___param = .;
-                       *(__param)
-               __stop___param = .;
                __initcall_start = .;
                        *(.initcall1.init)
                        *(.initcall2.init)
@@ -74,6 +71,7 @@ SECTIONS
                _text = .;              /* Text and read-only data      */
                        *(.text)
                        SCHED_TEXT
+                       LOCK_TEXT
                        *(.fixup)
                        *(.gnu.warning)
                        *(.rodata)
index cf39204..9478e01 100644 (file)
 
        .global __get_user_1
 __get_user_1:
-       bic     r1, sp, #0x1f00
-       bic     r1, r1, #0x00ff
-       ldr     r1, [r1, #TI_ADDR_LIMIT]
-       sub     r1, r1, #1
-       cmp     r0, r1
-1:     ldrlsbt r1, [r0]
-       movls   r0, #0
-       movls   pc, lr
-       b       __get_user_bad
+1:     ldrbt   r1, [r0]
+       mov     r0, #0
+       mov     pc, lr
 
        .global __get_user_2
 __get_user_2:
-       bic     r2, sp, #0x1f00
-       bic     r2, r2, #0x00ff
-       ldr     r2, [r2, #TI_ADDR_LIMIT]
-       sub     r2, r2, #2
-       cmp     r0, r2
-2:     ldrlsbt r1, [r0], #1
-3:     ldrlsbt r2, [r0]
+2:     ldrbt   r1, [r0], #1
+3:     ldrbt   r2, [r0]
 #ifndef __ARMEB__
-       orrls   r1, r1, r2, lsl #8
+       orr     r1, r1, r2, lsl #8
 #else
-       orrls   r1, r2, r1, lsl #8
+       orr     r1, r2, r1, lsl #8
 #endif
-       movls   r0, #0
-       movls   pc, lr
-       b       __get_user_bad
+       mov     r0, #0
+       mov     pc, lr
 
        .global __get_user_4
 __get_user_4:
-       bic     r1, sp, #0x1f00
-       bic     r1, r1, #0x00ff
-       ldr     r1, [r1, #TI_ADDR_LIMIT]
-       sub     r1, r1, #4
-       cmp     r0, r1
-4:     ldrlst  r1, [r0]
-       movls   r0, #0
-       movls   pc, lr
-       b       __get_user_bad
+4:     ldrt    r1, [r0]
+       mov     r0, #0
+       mov     pc, lr
 
        .global __get_user_8
 __get_user_8:
-       bic     r2, sp, #0x1f00
-       bic     r2, r2, #0x00ff
-       ldr     r2, [r2, #TI_ADDR_LIMIT]
-       sub     r2, r2, #8
-       cmp     r0, r2
-5:     ldrlst  r1, [r0], #4
-6:     ldrlst  r2, [r0]
-       movls   r0, #0
-       movls   pc, lr
-
-       /* fall through */
+5:     ldrt    r1, [r0], #4
+6:     ldrt    r2, [r0]
+       mov     r0, #0
+       mov     pc, lr
 
 __get_user_bad_8:
        mov     r2, #0
index 293de2d..b978885 100644 (file)
 
        .global __put_user_1
 __put_user_1:
-       bic     ip, sp, #0x1f00
-       bic     ip, ip, #0x00ff
-       ldr     ip, [ip, #TI_ADDR_LIMIT]
-       sub     ip, ip, #1
-       cmp     r0, ip
-1:     strlsbt r1, [r0]
-       movls   r0, #0
-       movls   pc, lr
-       b       __put_user_bad
+1:     strbt   r1, [r0]
+       mov     r0, #0
+       mov     pc, lr
 
        .global __put_user_2
 __put_user_2:
-       bic     ip, sp, #0x1f00
-       bic     ip, ip, #0x00ff
-       ldr     ip, [ip, #TI_ADDR_LIMIT]
-       sub     ip, ip, #2
-       cmp     r0, ip
-       movls   ip, r1, lsr #8
+       mov     ip, r1, lsr #8
 #ifndef __ARMEB__
-2:     strlsbt r1, [r0], #1
-3:     strlsbt ip, [r0]
+2:     strbt   r1, [r0], #1
+3:     strbt   ip, [r0]
 #else
-2:     strlsbt ip, [r0], #1
-3:     strlsbt r1, [r0]
+2:     strbt   ip, [r0], #1
+3:     strbt   r1, [r0]
 #endif
-       movls   r0, #0
-       movls   pc, lr
-       b       __put_user_bad
+       mov     r0, #0
+       mov     pc, lr
 
        .global __put_user_4
 __put_user_4:
-       bic     ip, sp, #0x1f00
-       bic     ip, ip, #0x00ff
-       ldr     ip, [ip, #TI_ADDR_LIMIT]
-       sub     ip, ip, #4
-       cmp     r0, ip
-4:     strlst  r1, [r0]
-       movls   r0, #0
-       movls   pc, lr
-       b       __put_user_bad
+4:     strt    r1, [r0]
+       mov     r0, #0
+       mov     pc, lr
 
        .global __put_user_8
 __put_user_8:
-       bic     ip, sp, #0x1f00
-       bic     ip, ip, #0x00ff
-       ldr     ip, [ip, #TI_ADDR_LIMIT]
-       sub     ip, ip, #8
-       cmp     r0, ip
-5:     strlst  r1, [r0], #4
-6:     strlst  r2, [r0]
-       movls   r0, #0
-       movls   pc, lr
-
-       /* fall through */
+5:     strt    r1, [r0], #4
+6:     strt    r2, [r0]
+       mov     r0, #0
+       mov     pc, lr
 
 __put_user_bad:
        mov     r0, #-EFAULT
diff --git a/arch/arm/mach-h720x/Kconfig b/arch/arm/mach-h720x/Kconfig
new file mode 100644 (file)
index 0000000..44a303d
--- /dev/null
@@ -0,0 +1,27 @@
+menu "h720x Implementations"
+
+config ARCH_H7201
+       bool "gms30c7201"
+       depends on ARCH_H720X
+       select CPU_H7201
+       help
+         Say Y here if you are using the Hynix GMS30C7201 Reference Board
+
+config ARCH_H7202
+       bool "hms30c7202"
+       select CPU_H7202
+       depends on ARCH_H720X
+       help
+         Say Y here if you are using the Hynix HMS30C7202 Reference Board
+
+endmenu
+
+config CPU_H7201
+       bool
+       help
+         Select code specific to h7201 variants
+
+config CPU_H7202
+       bool
+       help
+         Select code specific to h7202 variants
diff --git a/arch/arm/mach-h720x/Makefile b/arch/arm/mach-h720x/Makefile
new file mode 100644 (file)
index 0000000..e4cf728
--- /dev/null
@@ -0,0 +1,16 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y := common.o
+obj-m :=
+obj-n :=
+obj-  :=
+
+# Specific board support
+
+obj-$(CONFIG_ARCH_H7201)               += h7201-eval.o
+obj-$(CONFIG_ARCH_H7202)               += h7202-eval.o
+obj-$(CONFIG_CPU_H7201)                += cpu-h7201.o
+obj-$(CONFIG_CPU_H7202)                += cpu-h7202.o
diff --git a/arch/arm/mach-h720x/common.c b/arch/arm/mach-h720x/common.c
new file mode 100644 (file)
index 0000000..96aa3af
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * linux/arch/arm/mach-h720x/common.c
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * common stuff for Hynix h720x processors
+ *
+ * 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/sched.h>
+#include <linux/slab.h>
+#include <linux/mman.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/arch/irqs.h>
+
+#include <asm/mach/dma.h>
+
+#if 0
+#define IRQDBG(args...) printk(args)
+#else
+#define IRQDBG(args...) do {} while(0)
+#endif
+
+void __init arch_dma_init(dma_t *dma)
+{
+}
+
+/*
+ * Return usecs since last timer reload
+ * (timercount * (usecs perjiffie)) / (ticks per jiffie)
+ */
+unsigned long h720x_gettimeoffset(void)
+{
+       return (CPU_REG (TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH;
+}
+
+/*
+ * mask Global irq's
+ */
+static void mask_global_irq (unsigned int irq )
+{
+       CPU_REG (IRQC_VIRT, IRQC_IER) &= ~(1 << irq);
+}
+
+/*
+ * unmask Global irq's
+ */
+static void unmask_global_irq (unsigned int irq )
+{
+       CPU_REG (IRQC_VIRT, IRQC_IER) |= (1 << irq);
+}
+
+
+/*
+ * ack GPIO irq's
+ * Ack only for edge triggered int's valid
+ */
+static void inline ack_gpio_irq(u32 irq)
+{
+       u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(irq));
+       u32 bit = IRQ_TO_BIT(irq);
+       if ( (CPU_REG (reg_base, GPIO_EDGE) & bit))
+               CPU_REG (reg_base, GPIO_CLR) = bit;
+}
+
+/*
+ * mask GPIO irq's
+ */
+static void inline mask_gpio_irq(u32 irq)
+{
+       u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(irq));
+       u32 bit = IRQ_TO_BIT(irq);
+       CPU_REG (reg_base, GPIO_MASK) &= ~bit;
+}
+
+/*
+ * unmask GPIO irq's
+ */
+static void inline unmask_gpio_irq(u32 irq)
+{
+       u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(irq));
+       u32 bit = IRQ_TO_BIT(irq);
+       CPU_REG (reg_base, GPIO_MASK) |= bit;
+}
+
+static void
+h720x_gpio_handler(unsigned int mask, unsigned int irq,
+                 struct irqdesc *desc, struct pt_regs *regs)
+{
+       IRQDBG("%s irq: %d\n",__FUNCTION__,irq);
+       desc = irq_desc + irq;
+       while (mask) {
+               if (mask & 1) {
+                       IRQDBG("handling irq %d\n", irq);
+                       desc->handle(irq, desc, regs);
+               }
+               irq++;
+               desc++;
+               mask >>= 1;
+       }
+}
+
+static void
+h720x_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned int mask, irq;
+
+       mask = CPU_REG(GPIO_A_VIRT,GPIO_STAT);
+       irq = IRQ_CHAINED_GPIOA(0);
+       IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
+       h720x_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+h720x_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned int mask, irq;
+       mask = CPU_REG(GPIO_B_VIRT,GPIO_STAT);
+       irq = IRQ_CHAINED_GPIOB(0);
+       IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
+       h720x_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+h720x_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned int mask, irq;
+
+       mask = CPU_REG(GPIO_C_VIRT,GPIO_STAT);
+       irq = IRQ_CHAINED_GPIOC(0);
+       IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
+       h720x_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+h720x_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned int mask, irq;
+
+       mask = CPU_REG(GPIO_D_VIRT,GPIO_STAT);
+       irq = IRQ_CHAINED_GPIOD(0);
+       IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
+       h720x_gpio_handler(mask, irq, desc, regs);
+}
+
+#ifdef CONFIG_CPU_H7202
+static void
+h720x_gpioe_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned int mask, irq;
+
+       mask = CPU_REG(GPIO_E_VIRT,GPIO_STAT);
+       irq = IRQ_CHAINED_GPIOE(0);
+       IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
+       h720x_gpio_handler(mask, irq, desc, regs);
+}
+#endif
+
+static struct irqchip h720x_global_chip = {
+       .ack = mask_global_irq,
+       .mask = mask_global_irq,
+       .unmask = unmask_global_irq,
+};
+
+static struct irqchip h720x_gpio_chip = {
+       .ack = ack_gpio_irq,
+       .mask = mask_gpio_irq,
+       .unmask = unmask_gpio_irq,
+};
+
+/*
+ * Initialize IRQ's, mask all, enable multiplexed irq's
+ */
+void __init h720x_init_irq (void)
+{
+       int     irq;
+
+       /* Mask global irq's */
+       CPU_REG (IRQC_VIRT, IRQC_IER) = 0x0;
+
+       /* Mask all multiplexed irq's */
+       CPU_REG (GPIO_A_VIRT, GPIO_MASK) = 0x0;
+       CPU_REG (GPIO_B_VIRT, GPIO_MASK) = 0x0;
+       CPU_REG (GPIO_C_VIRT, GPIO_MASK) = 0x0;
+       CPU_REG (GPIO_D_VIRT, GPIO_MASK) = 0x0;
+
+       /* Initialize global IRQ's, fast path */
+       for (irq = 0; irq < NR_GLBL_IRQS; irq++) {
+               set_irq_chip(irq, &h720x_global_chip);
+               set_irq_handler(irq, do_level_IRQ);
+               set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+       }
+
+       /* Initialize multiplexed IRQ's, slow path */
+       for (irq = IRQ_CHAINED_GPIOA(0) ; irq <= IRQ_CHAINED_GPIOD(31); irq++) {
+               set_irq_chip(irq, &h720x_gpio_chip);
+               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_flags(irq, IRQF_VALID );
+       }
+       set_irq_chained_handler(IRQ_GPIOA, h720x_gpioa_demux_handler);
+       set_irq_chained_handler(IRQ_GPIOB, h720x_gpiob_demux_handler);
+       set_irq_chained_handler(IRQ_GPIOC, h720x_gpioc_demux_handler);
+       set_irq_chained_handler(IRQ_GPIOD, h720x_gpiod_demux_handler);
+
+#ifdef CONFIG_CPU_H7202
+       for (irq = IRQ_CHAINED_GPIOE(0) ; irq <= IRQ_CHAINED_GPIOE(31); irq++) {
+               set_irq_chip(irq, &h720x_gpio_chip);
+               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_flags(irq, IRQF_VALID );
+       }
+       set_irq_chained_handler(IRQ_GPIOE, h720x_gpioe_demux_handler);
+#endif
+
+       /* Enable multiplexed irq's */
+       CPU_REG (IRQC_VIRT, IRQC_IER) = IRQ_ENA_MUX;
+}
+
+static struct map_desc h720x_io_desc[] __initdata = {
+       { IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE },
+};
+
+/* Initialize io tables */
+void __init h720x_map_io(void)
+{
+       iotable_init(h720x_io_desc,ARRAY_SIZE(h720x_io_desc));
+}
diff --git a/arch/arm/mach-h720x/cpu-h7201.c b/arch/arm/mach-h720x/cpu-h7201.c
new file mode 100644 (file)
index 0000000..30f4d61
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/arm/mach-h720x/cpu-h7201.c
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * processor specific stuff for the Hynix h7201
+ *
+ * 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>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/irqs.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+extern unsigned long h720x_gettimeoffset(void);
+extern void __init h720x_init_irq (void);
+
+/*
+ * Timer interrupt handler
+ */
+static irqreturn_t
+h7201_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       CPU_REG (TIMER_VIRT, TIMER_TOPSTAT);
+       timer_tick(regs);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction h7201_timer_irq = {
+       .name           = "h7201 Timer Tick",
+       .flags          = SA_INTERRUPT,
+       .handler        = h7201_timer_interrupt
+};
+
+/*
+ * Setup TIMER0 as system timer
+ */
+void __init h7201_init_time(void)
+{
+       gettimeoffset = h720x_gettimeoffset;
+
+       CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
+       CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
+       CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
+       CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) = ENABLE_TM0_INTR | TIMER_ENABLE_BIT;
+
+       setup_irq(IRQ_TIMER0, &h7201_timer_irq);
+}
diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c
new file mode 100644 (file)
index 0000000..ee7abcd
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * linux/arch/arm/mach-h720x/cpu-h7202.c
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * processor specific stuff for the Hynix h7201
+ *
+ * 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>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/irqs.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <linux/device.h>
+
+static struct resource h7202ps2_resources[] = {
+       [0] = {
+               .start  = 0x8002c000,
+               .end    = 0x8002c040,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_PS2,
+               .end    = IRQ_PS2,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device h7202ps2_device = {
+       .name           = "h7202ps2",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(h7202ps2_resources),
+       .resource       = h7202ps2_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+       &h7202ps2_device,
+};
+
+extern unsigned long h720x_gettimeoffset(void);
+extern void __init h720x_init_irq (void);
+
+/* Although we have two interrupt lines for the timers, we only have one
+ * status register which clears all pending timer interrupts on reading. So
+ * we have to handle all timer interrupts in one place.
+ */
+static void
+h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned int mask, irq;
+
+       mask = CPU_REG (TIMER_VIRT, TIMER_TOPSTAT);
+
+       if ( mask & TSTAT_T0INT ) {
+               timer_tick(regs);
+               if( mask == TSTAT_T0INT )
+                       return;
+       }
+
+       mask >>= 1;
+       irq = IRQ_TIMER1;
+       desc = irq_desc + irq;
+       while (mask) {
+               if (mask & 1)
+                       desc->handle(irq, desc, regs);
+               irq++;
+               desc++;
+               mask >>= 1;
+       }
+}
+
+/*
+ * Timer interrupt handler
+ */
+static irqreturn_t
+h7202_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       h7202_timerx_demux_handler(0, NULL, regs);
+       return IRQ_HANDLED;
+}
+
+/*
+ * mask multiplexed timer irq's
+ */
+static void inline mask_timerx_irq (u32 irq)
+{
+       unsigned int bit;
+       bit = 2 << ((irq == IRQ_TIMER64B) ? 4 : (irq - IRQ_TIMER1));
+       CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) &= ~bit;
+}
+
+/*
+ * unmask multiplexed timer irq's
+ */
+static void inline unmask_timerx_irq (u32 irq)
+{
+       unsigned int bit;
+       bit = 2 << ((irq == IRQ_TIMER64B) ? 4 : (irq - IRQ_TIMER1));
+       CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) |= bit;
+}
+
+static struct irqchip h7202_timerx_chip = {
+       .ack = mask_timerx_irq,
+       .mask = mask_timerx_irq,
+       .unmask = unmask_timerx_irq,
+};
+
+static struct irqaction h7202_timer_irq = {
+       .name           = "h7202 Timer Tick",
+       .flags          = SA_INTERRUPT,
+       .handler        = h7202_timer_interrupt
+};
+
+/*
+ * Setup TIMER0 as system timer
+ */
+void __init h7202_init_time(void)
+{
+       gettimeoffset = h720x_gettimeoffset;
+
+       CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
+       CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
+       CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
+       CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) = ENABLE_TM0_INTR | TIMER_ENABLE_BIT;
+
+       setup_irq(IRQ_TIMER0, &h7202_timer_irq);
+}
+
+void __init h7202_init_irq (void)
+{
+       int     irq;
+
+       CPU_REG (GPIO_E_VIRT, GPIO_MASK) = 0x0;
+
+       for (irq = IRQ_TIMER1;
+                         irq < IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS); irq++) {
+               mask_timerx_irq(irq);
+               set_irq_chip(irq, &h7202_timerx_chip);
+               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_flags(irq, IRQF_VALID );
+       }
+       set_irq_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler);
+
+       h720x_init_irq();
+}
+
+void __init init_hw_h7202(void)
+{
+       /* Enable clocks */
+       CPU_REG (PMU_BASE, PMU_PLL_CTRL) |= PLL_2_EN | PLL_1_EN | PLL_3_MUTE;
+
+       (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+}
diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c
new file mode 100644 (file)
index 0000000..d2208c1
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * linux/arch/arm/mach-h720x/h7201-eval.c
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * Architecture specific stuff for Hynix GMS30C7201 development board
+ *
+ * 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/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/device.h>
+
+#include <asm/setup.h>
+#include <asm/types.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware.h>
+
+extern void h720x_init_irq (void);
+extern void h7201_init_time(void);
+extern void __init h720x_map_io(void);
+
+MACHINE_START(H7201, "Hynix GMS30C7201")
+       MAINTAINER("Robert Schwebel, Pengutronix")
+       BOOT_MEM(0x40000000, 0x80000000, 0xf0000000)
+       BOOT_PARAMS(0xc0001000)
+       MAPIO(h720x_map_io)
+       INITIRQ(h720x_init_irq)
+       INITTIME(h7201_init_time)
+MACHINE_END
diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
new file mode 100644 (file)
index 0000000..9398731
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * linux/arch/arm/mach-h720x/h7202-eval.c
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *              2004 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * Architecture specific stuff for Hynix HMS30C7202 development board
+ *
+ * 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/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/device.h>
+
+#include <asm/setup.h>
+#include <asm/types.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware.h>
+
+extern void __init init_hw_h7202(void);
+extern void __init h7202_init_irq (void);
+extern void __init h7202_init_time(void);
+extern void __init h720x_map_io(void);
+
+static struct resource cirrus_resources[] = {
+       [0] = {
+               .start  = ETH0_PHYS + 0x300,
+               .end    = ETH0_PHYS + 0x300 + 0x10,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_CHAINED_GPIOB(8),
+               .end    = IRQ_CHAINED_GPIOB(8),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device cirrus_device = {
+       .name           = "cirrus-cs89x0",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(cirrus_resources),
+       .resource       = cirrus_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+       &cirrus_device,
+};
+
+/*
+ * Hardware init. This is called early in initcalls
+ * Place pin inits here. So you avoid adding ugly
+ * #ifdef stuff to common drivers.
+ * Use this only, if your bootloader is not able
+ * to initialize the pins proper.
+ */
+static void __init init_eval_h7202(void)
+{
+       init_hw_h7202();
+       (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+
+       /* Enable interrupt on portb bit 8 (ethernet) */
+       CPU_REG (GPIO_B_VIRT, GPIO_POL) &= ~(1 << 8);
+       CPU_REG (GPIO_B_VIRT, GPIO_EN) |= (1 << 8);
+}
+
+MACHINE_START(H7202, "Hynix HMS30C7202")
+       MAINTAINER("Robert Schwebel, Pengutronix")
+       BOOT_MEM(0x40000000, 0x80000000, 0xf0000000)
+       BOOT_PARAMS(0x40000100)
+       MAPIO(h720x_map_io)
+       INITIRQ(h7202_init_irq)
+       INITTIME(h7202_init_time)
+       INIT_MACHINE(init_eval_h7202)
+MACHINE_END
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
new file mode 100644 (file)
index 0000000..ec85813
--- /dev/null
@@ -0,0 +1,10 @@
+menu "IMX Implementations"
+       depends on ARCH_IMX
+
+config ARCH_MX1ADS
+       bool "mx1ads"
+       depends on ARCH_IMX
+       help
+         Say Y here if you are using the Motorola MX1ADS board
+
+endmenu
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
new file mode 100644 (file)
index 0000000..0b27d79
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+# Object file lists.
+
+obj-y                  += irq.o time.o dma.o generic.o
+
+# Specific board support
+obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o
+
+# Support for blinky lights
+led-y := leds.o
+
+obj-$(CONFIG_LEDS)     +=  $(led-y)
+led-$(CONFIG_ARCH_MX1ADS) += leds-mx1ads.o
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
new file mode 100644 (file)
index 0000000..7387ccb
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ *  linux/arch/arm/mach-imx/dma.c
+ *
+ *  imx DMA registration and IRQ dispatching
+ *
+ *  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.
+ *
+ *  03/03/2004 Sascha Hauer <sascha@saschahauer.de>
+ *             initial version heavily inspired by
+ *             linux/arch/arm/mach-pxa/dma.c
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/dma.h>
+
+static struct dma_channel {
+       char *name;
+       void (*irq_handler) (int, void *, struct pt_regs *);
+       void (*err_handler) (int, void *, struct pt_regs *);
+       void *data;
+} dma_channels[11];
+
+/* set err_handler to NULL to have the standard info-only error handler */
+int
+imx_request_dma(char *name, imx_dma_prio prio,
+               void (*irq_handler) (int, void *, struct pt_regs *),
+               void (*err_handler) (int, void *, struct pt_regs *), void *data)
+{
+       unsigned long flags;
+       int i, found = 0;
+
+       /* basic sanity checks */
+       if (!name || !irq_handler)
+               return -EINVAL;
+
+       local_irq_save(flags);
+
+       /* try grabbing a DMA channel with the requested priority */
+       for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
+               if (!dma_channels[i].name) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found) {
+               /* requested prio group is full, try hier priorities */
+               for (i = prio - 1; i >= 0; i--) {
+                       if (!dma_channels[i].name) {
+                               found = 1;
+                               break;
+                       }
+               }
+       }
+
+       if (found) {
+               DIMR &= ~(1 << i);
+               dma_channels[i].name = name;
+               dma_channels[i].irq_handler = irq_handler;
+               dma_channels[i].err_handler = err_handler;
+               dma_channels[i].data = data;
+       } else {
+               printk(KERN_WARNING "No more available DMA channels for %s\n",
+                      name);
+               i = -ENODEV;
+       }
+
+       local_irq_restore(flags);
+       return i;
+}
+
+void
+imx_free_dma(int dma_ch)
+{
+       unsigned long flags;
+
+       if (!dma_channels[dma_ch].name) {
+               printk(KERN_CRIT
+                      "%s: trying to free channel %d which is already freed\n",
+                      __FUNCTION__, dma_ch);
+               return;
+       }
+
+       local_irq_save(flags);
+       DIMR &= ~(1 << dma_ch);
+       dma_channels[dma_ch].name = NULL;
+       local_irq_restore(flags);
+}
+
+static irqreturn_t
+dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       int i;
+       struct dma_channel *channel;
+       unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
+
+       for (i = 0; i < 11; i++) {
+               channel = &dma_channels[i];
+
+               if ( (err_mask & 1<<i) && channel->name && channel->err_handler) {
+                       channel->err_handler(i, channel->data, regs);
+                       continue;
+               }
+
+               if (DBTOSR & (1 << i)) {
+                       printk(KERN_WARNING
+                              "Burst timeout on channel %d (%s)\n",
+                              i, channel->name);
+                       DBTOSR |= (1 << i);
+               }
+               if (DRTOSR & (1 << i)) {
+                       printk(KERN_WARNING
+                              "Request timeout on channel %d (%s)\n",
+                              i, channel->name);
+                       DRTOSR |= (1 << i);
+               }
+               if (DSESR & (1 << i)) {
+                       printk(KERN_WARNING
+                              "Transfer timeout on channel %d (%s)\n",
+                              i, channel->name);
+                       DSESR |= (1 << i);
+               }
+               if (DBOSR & (1 << i)) {
+                       printk(KERN_WARNING
+                              "Buffer overflow timeout on channel %d (%s)\n",
+                              i, channel->name);
+                       DBOSR |= (1 << i);
+               }
+               DISR |= (1 << i);
+       }
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t
+dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       int i, disr = DISR;
+
+       for (i = 0; i < 11; i++) {
+               if (disr & (1 << i)) {
+                       struct dma_channel *channel = &dma_channels[i];
+                       if (channel->name && channel->irq_handler) {
+                               channel->irq_handler(i, channel->data, regs);
+                       } else {
+                               /*
+                                * IRQ for an unregistered DMA channel:
+                                * let's clear the interrupts and disable it.
+                                */
+                               printk(KERN_WARNING
+                                      "spurious IRQ for DMA channel %d\n", i);
+                               DISR |= (1 << i);
+                       }
+               }
+       }
+       return IRQ_HANDLED;
+}
+
+static int __init
+imx_dma_init(void)
+{
+       int ret;
+
+       /* reset DMA module */
+       DCR = DCR_DRST;
+
+       ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL);
+       if (ret) {
+               printk(KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
+               return ret;
+       }
+
+       ret = request_irq(DMA_ERR, dma_err_handler, 0, "DMA", NULL);
+       if (ret) {
+               printk(KERN_CRIT "Wow!  Can't register ERRIRQ for DMA\n");
+               free_irq(DMA_INT, NULL);
+       }
+
+       /* enable DMA module */
+       DCR = DCR_DEN;
+
+       /* clear all interrupts */
+       DISR = 0x3ff;
+
+       /* enable interrupts */
+       DIMR = 0;
+
+       return ret;
+}
+
+arch_initcall(imx_dma_init);
+
+EXPORT_SYMBOL(imx_request_dma);
+EXPORT_SYMBOL(imx_free_dma);
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
new file mode 100644 (file)
index 0000000..4954653
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ *  arch/arm/mach-imx/generic.c
+ *
+ *  author: Sascha Hauer
+ *  Created: april 20th, 2004
+ *  Copyright: Synertronixx GmbH
+ *
+ *  Common code for i.MX machines
+ *
+ * This program is free software; you can redistribute 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/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/map.h>
+
+void imx_gpio_mode(int gpio_mode)
+{
+       unsigned int pin = gpio_mode & GPIO_PIN_MASK;
+       unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> 5;
+       unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> 10;
+       unsigned int tmp;
+
+       /* Pullup enable */
+       if(gpio_mode & GPIO_PUEN)
+               PUEN(port) |= (1<<pin);
+       else
+               PUEN(port) &= ~(1<<pin);
+
+       /* Data direction */
+       if(gpio_mode & GPIO_OUT)
+               DDIR(port) |= 1<<pin;
+       else
+               DDIR(port) &= ~(1<<pin);
+
+       /* Primary / alternate function */
+       if(gpio_mode & GPIO_AF)
+               GPR(port) |= (1<<pin);
+       else
+               GPR(port) &= ~(1<<pin);
+
+       /* use as gpio? */
+       if( ocr == 3 )
+               GIUS(port) |= (1<<pin);
+       else
+               GIUS(port) &= ~(1<<pin);
+
+       /* Output / input configuration */
+       /* FIXME: I'm not very sure about OCR and ICONF, someone
+        * should have a look over it
+        */
+       if(pin<16) {
+               tmp = OCR1(port);
+               tmp &= ~( 3<<(pin*2));
+               tmp |= (ocr << (pin*2));
+               OCR1(port) = tmp;
+
+               if( gpio_mode & GPIO_AOUT )
+                       ICONFA1(port) &= ~( 3<<(pin*2));
+               if( gpio_mode & GPIO_BOUT )
+                       ICONFB1(port) &= ~( 3<<(pin*2));
+       } else {
+               tmp = OCR2(port);
+               tmp &= ~( 3<<((pin-16)*2));
+               tmp |= (ocr << ((pin-16)*2));
+               OCR2(port) = tmp;
+
+               if( gpio_mode & GPIO_AOUT )
+                       ICONFA2(port) &= ~( 3<<((pin-16)*2));
+               if( gpio_mode & GPIO_BOUT )
+                       ICONFB2(port) &= ~( 3<<((pin-16)*2));
+       }
+}
+
+EXPORT_SYMBOL(imx_gpio_mode);
+
+/*
+ *  get the system pll clock in Hz
+ *
+ *                  mfi + mfn / (mfd +1)
+ *  f = 2 * f_ref * --------------------
+ *                        pd + 1
+ */
+static unsigned int imx_decode_pll(unsigned int pll)
+{
+       u32 mfi = (pll >> 10) & 0xf;
+       u32 mfn = pll & 0x3f;
+       u32 mfd = (pll >> 16) & 0x3f;
+       u32 pd =  (pll >> 26) & 0xf;
+       u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
+
+       mfi = mfi <= 5 ? 5 : mfi;
+
+       return (2 * (f_ref>>10) * ( (mfi<<10) + (mfn<<10) / (mfd+1) )) / (pd+1);
+}
+
+unsigned int imx_get_system_clk(void)
+{
+       return imx_decode_pll(SPCTL0);
+}
+EXPORT_SYMBOL(imx_get_system_clk);
+
+unsigned int imx_get_mcu_clk(void)
+{
+       return imx_decode_pll(MPCTL0);
+}
+EXPORT_SYMBOL(imx_get_mcu_clk);
+
+/*
+ *  get peripheral clock 1 ( UART[12], Timer[12], PWM )
+ */
+unsigned int imx_get_perclk1(void)
+{
+       return imx_get_system_clk() / (((PCDR) & 0xf)+1);
+}
+EXPORT_SYMBOL(imx_get_perclk1);
+
+/*
+ *  get peripheral clock 2 ( LCD, SD, SPI[12] )
+ */
+unsigned int imx_get_perclk2(void)
+{
+       return imx_get_system_clk() / (((PCDR>>4) & 0xf)+1);
+}
+EXPORT_SYMBOL(imx_get_perclk2);
+
+/*
+ *  get peripheral clock 3 ( SSI )
+ */
+unsigned int imx_get_perclk3(void)
+{
+       return imx_get_system_clk() / (((PCDR>>16) & 0x7f)+1);
+}
+EXPORT_SYMBOL(imx_get_perclk3);
+
+/*
+ *  get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
+ */
+unsigned int imx_get_hclk(void)
+{
+       return imx_get_system_clk() / (((CSCR>>10) & 0xf)+1);
+}
+EXPORT_SYMBOL(imx_get_hclk);
+
+static struct resource imx_mmc_resources[] = {
+       [0] = {
+               .start  = 0x00214000,
+               .end    = 0x002140FF,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = (SDHC_INT),
+               .end    = (SDHC_INT),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device imx_mmc_device = {
+       .name           = "imx-mmc",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(imx_mmc_resources),
+       .resource       = imx_mmc_resources,
+};
+
+static struct resource imx_uart1_resources[] = {
+       [0] = {
+               .start  = 0x00206000,
+               .end    = 0x002060FF,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = (UART1_MINT_RX),
+               .end    = (UART1_MINT_RX),
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               .start  = (UART1_MINT_TX),
+               .end    = (UART1_MINT_TX),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device imx_uart1_device = {
+       .name           = "imx-uart",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(imx_uart1_resources),
+       .resource       = imx_uart1_resources,
+};
+
+static struct resource imx_uart2_resources[] = {
+       [0] = {
+               .start  = 0x00207000,
+               .end    = 0x002070FF,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = (UART2_MINT_RX),
+               .end    = (UART2_MINT_RX),
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               .start  = (UART2_MINT_TX),
+               .end    = (UART2_MINT_TX),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device imx_uart2_device = {
+       .name           = "imx-uart",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(imx_uart2_resources),
+       .resource       = imx_uart2_resources,
+};
+
+static struct resource imxfb_resources[] = {
+       [0] = {
+               .start  = 0x00205000,
+               .end    = 0x002050FF,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = LCDC_INT,
+               .end    = LCDC_INT,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device imxfb_device = {
+       .name           = "imx-fb",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(imxfb_resources),
+       .resource       = imxfb_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+       &imx_mmc_device,
+       &imxfb_device,
+       &imx_uart1_device,
+       &imx_uart2_device,
+};
+
+static struct map_desc imx_io_desc[] __initdata = {
+       /* virtual     physical    length      type */
+       {IMX_IO_BASE, IMX_IO_PHYS, IMX_IO_SIZE, MT_DEVICE},
+};
+
+void __init
+imx_map_io(void)
+{
+       iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
+}
+
+static int __init imx_init(void)
+{
+       return platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+subsys_initcall(imx_init);
diff --git a/arch/arm/mach-imx/generic.h b/arch/arm/mach-imx/generic.h
new file mode 100644 (file)
index 0000000..31e1911
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ *  linux/arch/arm/mach-imx/generic.h
+ *
+ * Author:     Sascha Hauer <sascha@saschahauer.de>
+ * Copyright:  Synertronixx GmbH
+ *
+ * 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.
+ */
+
+extern void __init imx_map_io(void);
+extern void __init imx_init_irq(void);
+extern void __init imx_init_time(void);
diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c
new file mode 100644 (file)
index 0000000..0c27134
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ *  linux/arch/arm/mach-imx/irq.c
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.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
+ *
+ *  03/03/2004   Sascha Hauer <sascha@saschahauer.de>
+ *               Copied from the motorola bsp package and added gpio demux
+ *               interrupt handler
+ */
+
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+/*
+ *
+ * We simply use the ENABLE DISABLE registers inside of the IMX
+ * to turn on/off specific interrupts.  FIXME- We should
+ * also add support for the accelerated interrupt controller
+ * by putting offets to irq jump code in the appropriate
+ * places.
+ *
+ */
+
+#define INTENNUM_OFF              0x8
+#define INTDISNUM_OFF             0xC
+
+#define VA_AITC_BASE              IO_ADDRESS(IMX_AITC_BASE)
+#define IMX_AITC_INTDISNUM       (VA_AITC_BASE + INTDISNUM_OFF)
+#define IMX_AITC_INTENNUM        (VA_AITC_BASE + INTENNUM_OFF)
+
+#if 0
+#define DEBUG_IRQ(fmt...)      printk(fmt)
+#else
+#define DEBUG_IRQ(fmt...)      do { } while (0)
+#endif
+
+static void
+imx_mask_irq(unsigned int irq)
+{
+       __raw_writel(irq, IMX_AITC_INTDISNUM);
+}
+
+static void
+imx_unmask_irq(unsigned int irq)
+{
+       __raw_writel(irq, IMX_AITC_INTENNUM);
+}
+
+static int
+imx_gpio_irq_type(unsigned int _irq, unsigned int type)
+{
+       unsigned int irq_type = 0, irq, reg, bit;
+
+       irq = _irq - IRQ_GPIOA(0);
+       reg = irq >> 5;
+       bit = 1 << (irq % 32);
+
+       if (type == IRQT_PROBE) {
+               /* Don't mess with enabled GPIOs using preconfigured edges or
+                  GPIOs set to alternate function during probe */
+               /* TODO: support probe */
+//              if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx]) &
+//                  GPIO_bit(gpio))
+//                      return 0;
+//              if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
+//                      return 0;
+//              type = __IRQT_RISEDGE | __IRQT_FALEDGE;
+       }
+
+       GIUS(reg) |= bit;
+       DDIR(reg) &= ~(bit);
+
+       DEBUG_IRQ("setting type of irq %d to ", _irq);
+
+       if (type & __IRQT_RISEDGE) {
+               DEBUG_IRQ("rising edges\n");
+               irq_type = 0x0;
+       }
+       if (type & __IRQT_FALEDGE) {
+               DEBUG_IRQ("falling edges\n");
+               irq_type = 0x1;
+       }
+       if (type & __IRQT_LOWLVL) {
+               DEBUG_IRQ("low level\n");
+               irq_type = 0x3;
+       }
+       if (type & __IRQT_HIGHLVL) {
+               DEBUG_IRQ("high level\n");
+               irq_type = 0x2;
+       }
+
+       if (irq % 32 < 16) {
+               ICR1(reg) = (ICR1(reg) & ~(0x3 << ((irq % 16) * 2))) |
+                   (irq_type << ((irq % 16) * 2));
+       } else {
+               ICR2(reg) = (ICR2(reg) & ~(0x3 << ((irq % 16) * 2))) |
+                   (irq_type << ((irq % 16) * 2));
+       }
+
+       return 0;
+
+}
+
+static void
+imx_gpio_ack_irq(unsigned int irq)
+{
+       DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
+       ISR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32);
+}
+
+static void
+imx_gpio_mask_irq(unsigned int irq)
+{
+       DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
+       IMR(IRQ_TO_REG(irq)) &= ~( 1 << ((irq - IRQ_GPIOA(0)) % 32));
+}
+
+static void
+imx_gpio_unmask_irq(unsigned int irq)
+{
+       DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
+       IMR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32);
+}
+
+static void
+imx_gpio_handler(unsigned int mask, unsigned int irq,
+                 struct irqdesc *desc, struct pt_regs *regs)
+{
+       desc = irq_desc + irq;
+       while (mask) {
+               if (mask & 1) {
+                       DEBUG_IRQ("handling irq %d\n", irq);
+                       desc->handle(irq, desc, regs);
+               }
+               irq++;
+               desc++;
+               mask >>= 1;
+       }
+}
+
+static void
+imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned int mask, irq;
+
+       mask = ISR(0);
+       irq = IRQ_GPIOA(0);
+       imx_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned int mask, irq;
+
+       mask = ISR(1);
+       irq = IRQ_GPIOB(0);
+       imx_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned int mask, irq;
+
+       mask = ISR(2);
+       irq = IRQ_GPIOC(0);
+       imx_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+imx_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned int mask, irq;
+
+       mask = ISR(3);
+       irq = IRQ_GPIOD(0);
+       imx_gpio_handler(mask, irq, desc, regs);
+}
+
+static struct irqchip imx_internal_chip = {
+       .ack = imx_mask_irq,
+       .mask = imx_mask_irq,
+       .unmask = imx_unmask_irq,
+};
+
+static struct irqchip imx_gpio_chip = {
+       .ack = imx_gpio_ack_irq,
+       .mask = imx_gpio_mask_irq,
+       .unmask = imx_gpio_unmask_irq,
+       .type = imx_gpio_irq_type,
+};
+
+void __init
+imx_init_irq(void)
+{
+       unsigned int irq;
+
+       DEBUG_IRQ("Initializing imx interrupts\n");
+
+       /* Mask all interrupts initially */
+       IMR(0) = 0;
+       IMR(1) = 0;
+       IMR(2) = 0;
+       IMR(3) = 0;
+
+       for (irq = 0; irq < IMX_IRQS; irq++) {
+               set_irq_chip(irq, &imx_internal_chip);
+               set_irq_handler(irq, do_level_IRQ);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+
+       for (irq = IRQ_GPIOA(0); irq < IRQ_GPIOD(32); irq++) {
+               set_irq_chip(irq, &imx_gpio_chip);
+               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+
+       set_irq_chained_handler(GPIO_INT_PORTA, imx_gpioa_demux_handler);
+       set_irq_chained_handler(GPIO_INT_PORTB, imx_gpiob_demux_handler);
+       set_irq_chained_handler(GPIO_INT_PORTC, imx_gpioc_demux_handler);
+       set_irq_chained_handler(GPIO_INT_PORTD, imx_gpiod_demux_handler);
+
+       /* Disable all interrupts initially. */
+       /* In IMX this is done in the bootloader. */
+}
diff --git a/arch/arm/mach-imx/leds-mx1ads.c b/arch/arm/mach-imx/leds-mx1ads.c
new file mode 100644 (file)
index 0000000..e6399b0
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * linux/arch/arm/mach-imx/leds-mx1ads.c
+ *
+ * Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
+ *
+ * Original (leds-footbridge.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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/hardware.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+#include "leds.h"
+
+/*
+ * The MX1ADS Board has only one usable LED,
+ * so select only the timer led or the
+ * cpu usage led
+ */
+void
+mx1ads_leds_event(led_event_t ledevt)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       switch (ledevt) {
+#ifdef CONFIG_LEDS_CPU
+       case led_idle_start:
+               DR(0) &= ~(1<<2);
+               break;
+
+       case led_idle_end:
+               DR(0) |= 1<<2;
+               break;
+#endif
+
+#ifdef CONFIG_LEDS_TIMER
+       case led_timer:
+               DR(0) ^= 1<<2;
+#endif
+       default:
+               break;
+       }
+       local_irq_restore(flags);
+}
diff --git a/arch/arm/mach-imx/leds.c b/arch/arm/mach-imx/leds.c
new file mode 100644 (file)
index 0000000..471c1db
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/arm/mach-imx/leds.h
+ *
+ * Copyright (C) 2004 Sascha Hauer <sascha@saschahauer.de>
+ *
+ *
+ * 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/init.h>
+
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+
+#include "leds.h"
+
+static int __init
+leds_init(void)
+{
+       if (machine_is_mx1ads()) {
+               leds_event = mx1ads_leds_event;
+       }
+
+       return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-imx/leds.h b/arch/arm/mach-imx/leds.h
new file mode 100644 (file)
index 0000000..83fa21e
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * include/asm-arm/arch-imx/leds.h
+ *
+ * Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
+ *
+ * blinky lights for IMX-based systems
+ *
+ */
+extern void mx1ads_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
new file mode 100644 (file)
index 0000000..bd92b90
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/mach-imx/mx1ads.c
+ *
+ * Initially based on:
+ *     linux-2.6.7-imx/arch/arm/mach-imx/scb9328.c
+ *     Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
+ *
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <linux/interrupt.h>
+#include "generic.h"
+#include <asm/serial.h>
+
+static struct resource mx1ads_resources[] = {
+       [0] = {
+               .start  = IMX_CS4_VIRT,
+               .end    = IMX_CS4_VIRT + 16,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 13,
+               .end    = 13,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device mx1ads_device = {
+       .name           = "mx1ads",
+       .num_resources  = ARRAY_SIZE(mx1ads_resources),
+       .resource       = mx1ads_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+       &mx1ads_device,
+};
+
+static void __init
+mx1ads_init(void)
+{
+#ifdef CONFIG_LEDS
+       imx_gpio_mode(GPIO_PORTA | GPIO_OUT | GPIO_GPIO | 2);
+#endif
+       platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static struct map_desc mx1ads_io_desc[] __initdata = {
+       /* virtual     physical    length      type */
+       {IMX_CS0_VIRT, IMX_CS0_PHYS, IMX_CS0_SIZE, MT_DEVICE},
+       {IMX_CS1_VIRT, IMX_CS1_PHYS, IMX_CS1_SIZE, MT_DEVICE},
+       {IMX_CS2_VIRT, IMX_CS2_PHYS, IMX_CS2_SIZE, MT_DEVICE},
+       {IMX_CS3_VIRT, IMX_CS3_PHYS, IMX_CS3_SIZE, MT_DEVICE},
+       {IMX_CS4_VIRT, IMX_CS4_PHYS, IMX_CS4_SIZE, MT_DEVICE},
+       {IMX_CS5_VIRT, IMX_CS5_PHYS, IMX_CS5_SIZE, MT_DEVICE},
+};
+
+static void __init
+mx1ads_map_io(void)
+{
+       imx_map_io();
+       iotable_init(mx1ads_io_desc, ARRAY_SIZE(mx1ads_io_desc));
+}
+
+MACHINE_START(MX1ADS, "Motorola MX1ADS")
+       MAINTAINER("Sascha Hauer, Pengutronix")
+       BOOT_MEM(0x08000000, 0x00200000, 0xe0200000)
+       BOOT_PARAMS(0x08000100)
+       MAPIO(mx1ads_map_io)
+       INITIRQ(imx_init_irq)
+       INITTIME(imx_init_time)
+       INIT_MACHINE(mx1ads_init)
+MACHINE_END
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
new file mode 100644 (file)
index 0000000..ac7cab9
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  linux/arch/arm/mach-imx/time.c
+ *
+ *  Copyright (C) 2000-2001 Deep Blue Solutions
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.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/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/time.h>
+
+/* Use timer 1 as system timer */
+#define TIMER_BASE IMX_TIM1_BASE
+
+/*
+ * Returns number of us since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long
+imx_gettimeoffset(void)
+{
+       unsigned long ticks;
+
+       /*
+        * 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.
+        */
+       ticks = IMX_TCN(TIMER_BASE);
+
+       /*
+        * Interrupt pending?  If so, we've reloaded once already.
+        */
+       if (IMX_TSTAT(TIMER_BASE) & TSTAT_COMP)
+               ticks += LATCH;
+
+       /*
+        * Convert the ticks to usecs
+        */
+       return (1000000 / CLK32) * ticks;
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       /* clear the interrupt */
+       if (IMX_TSTAT(TIMER_BASE))
+               IMX_TSTAT(TIMER_BASE) = 0;
+
+       timer_tick(regs);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction imx_timer_irq = {
+       .name           = "i.MX Timer Tick",
+       .flags          = SA_INTERRUPT,
+       .handler        = imx_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+void __init
+imx_init_time(void)
+{
+       /*
+        * Initialise to a known state (all timers off, and timing reset)
+        */
+       IMX_TCTL(TIMER_BASE) = 0;
+       IMX_TPRER(TIMER_BASE) = 0;
+       IMX_TCMP(TIMER_BASE) = LATCH - 1;
+       IMX_TCTL(TIMER_BASE) = TCTL_CLK_32 | TCTL_IRQEN | TCTL_TEN;
+
+       /*
+        * Make irqs happen for the system timer
+        */
+       setup_irq(TIM1_INT, &imx_timer_irq);
+       gettimeoffset = imx_gettimeoffset;
+}
index 6a388e2..019b1bf 100644 (file)
@@ -2,53 +2,48 @@ if ARCH_IOP3XX
 
 menu "IOP3xx Implementation Options"
 
-choice
-       prompt "IOP3xx System Type"
-       default ARCH_IQ80310
-
-config ARCH_IQ80310
-       bool "IQ80310"
-       help
-         Say Y here if you want to run your kernel on the Intel IQ80310
-         evaluation kit for the IOP310 chipset.
+comment "IOP3xx Platform Types"
 
 config ARCH_IQ80321
-       bool "IQ80321"
+       bool "Enable support for IQ80321"
+       select ARCH_IOP321
        help
          Say Y here if you want to run your kernel on the Intel IQ80321
          evaluation kit for the IOP321 chipset.
-endchoice
 
-# Which IOP variant are we running?
-config ARCH_IOP310
-       bool
-       default ARCH_IQ80310
+config ARCH_IQ31244
+       bool "Enable support for IQ31244"
+       select ARCH_IOP321
        help
-         The IQ80310 uses the IOP310 variant.
+         Say Y here if you want to run your kernel on the Intel IQ31244
+         evaluation kit for the IOP321 chipset.
+
+config ARCH_IQ80331
+       bool "Enable support for IQ80331"
+       select ARCH_IOP331
+       help
+         Say Y here if you want to run your kernel on the Intel IQ80331
+         evaluation kit for the IOP331 chipset.
+
+config ARCH_EP80219
+    bool "Enable support for EP80219"
+    select ARCH_IOP321
+    select ARCH_IQ31244
 
+# Which IOP variant are we running?
 config ARCH_IOP321
        bool
-       default ARCH_IQ80321
        help
          The IQ80321 uses the IOP321 variant.
+         The IQ31244 and EP80219 uses the IOP321 variant.
 
-comment "IOP3xx Chipset Features"
-
-config IOP3XX_AAU
-       bool "Support Intel IOP3xx Application Accelerator Unit (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-
-config IOP3XX_DMA
-       bool "Support Intel IOP3xx DMA (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-
-config IOP3XX_MU
-       bool "Support Intel IOP3xx Messaging Unit (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+config ARCH_IOP331
+       bool
+       default ARCH_IQ80331
+       help
+         The IQ80331 uses the IOP331 variant.
 
-config IOP3XX_PMON
-       bool "Support Intel IOP3xx Performance Monitor (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+comment "IOP3xx Chipset Features"
 
 endmenu
 
index a6d1cf9..dcbffb6 100644 (file)
@@ -4,27 +4,18 @@
 
 # Object file lists.
 
-obj-y                  := arch.o
+obj-y                  := common.o
 
 obj-m                  :=
 obj-n                  :=
 obj-                   :=
 
-obj-$(CONFIG_ARCH_IOP310)  += xs80200-irq.o iop310-irq.o iop310-pci.o mm.o
+obj-$(CONFIG_ARCH_IOP321)  += iop321-setup.o iop321-irq.o iop321-pci.o iop321-mm.o iop321-time.o
 
-obj-$(CONFIG_ARCH_IQ80310) += iq80310-pci.o iq80310-irq.o
+obj-$(CONFIG_ARCH_IOP331)  += iop331-setup.o iop331-irq.o iop331-pci.o iop331-time.o
 
-obj-$(CONFIG_ARCH_IOP321)  += iop321-irq.o iop321-pci.o mm-321.o iop321-time.o
+obj-$(CONFIG_ARCH_IQ80321) += iq80321-mm.o iq80321-pci.o
 
-obj-$(CONFIG_ARCH_IQ80321) += iq80321-pci.o
+obj-$(CONFIG_ARCH_IQ31244) += iq31244-mm.o iq31244-pci.o
 
-ifeq ($(CONFIG_ARCH_IQ80310),y)
-   ifneq ($(CONFIG_XSCALE_PMU_TIMER),y)
-      obj-y                    += iq80310-time.o
-   endif
-endif
-
-obj-$(CONFIG_IOP3XX_AAU) += aau.o
-obj-$(CONFIG_IOP3XX_DMA) += dma.o
-obj-$(CONFIG_IOP3XX_MU) += message.o
-obj-$(CONFIG_IOP3XX_PMON) += pmon.o
+obj-$(CONFIG_ARCH_IQ80331) += iq80331-mm.o iq80331-pci.o
diff --git a/arch/arm/mach-iop3xx/common.c b/arch/arm/mach-iop3xx/common.c
new file mode 100644 (file)
index 0000000..c0bbe5a
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/mach-iop3xx/common.c
+ *
+ * Common routines shared across all IOP3xx implementations
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright 2003 (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.
+ */
+
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <asm/hardware.h>
+
+/*
+ * Shared variables
+ */
+unsigned long iop3xx_pcibios_min_io = 0;
+unsigned long iop3xx_pcibios_min_mem = 0;
+
+#ifdef CONFIG_ARCH_EP80219
+#include <linux/kernel.h>
+/*
+ * Default power-off for EP80219
+ */
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+static inline void ep80219_send_to_pic(__u8 c) {
+}
+
+void ep80219_power_off(void)
+{
+       /*
+     * This function will send a SHUTDOWN_COMPLETE message to the PIC controller
+     * over I2C.  We are not using the i2c subsystem since we are going to power
+     * off and it may be removed
+     */
+
+       /* Send the Address byte w/ the start condition */
+       *IOP321_IDBR1 = 0x60;
+       *IOP321_ICR1 = 0xE9;
+    mdelay(1);
+
+       /* Send the START_MSG byte w/ no start or stop condition */
+       *IOP321_IDBR1 = 0x0F;
+       *IOP321_ICR1 = 0xE8;
+    mdelay(1);
+
+       /* Send the SHUTDOWN_COMPLETE Message ID byte w/ no start or stop condition */
+       *IOP321_IDBR1 = 0x03;
+       *IOP321_ICR1 = 0xE8;
+    mdelay(1);
+
+       /* Send an ignored byte w/ stop condition */
+       *IOP321_IDBR1 = 0x00;
+       *IOP321_ICR1 = 0xEA;
+
+       while (1) ;
+}
+
+#include <linux/init.h>
+#include <linux/pm.h>
+
+static int __init ep80219_init(void)
+{
+       pm_power_off = ep80219_power_off;
+       return 0;
+}
+arch_initcall(ep80219_init);
+#endif
index 472faf5..d42aae6 100644 (file)
@@ -81,7 +81,8 @@ void __init iop321_init_irq(void)
 
        intctl_write(0);                // disable all interrupts
        intstr_write(0);                // treat all as IRQ
-       if(machine_is_iq80321())        // all interrupts are inputs to chip
+       if(machine_is_iq80321() ||
+          machine_is_iq31244())        // all interrupts are inputs to chip
                *IOP321_PCIIRSR = 0x0f;
 
        for(i = IOP321_IRQ_OFS; i < NR_IOP321_IRQS; i++)
diff --git a/arch/arm/mach-iop3xx/iop321-mm.c b/arch/arm/mach-iop3xx/iop321-mm.c
new file mode 100644 (file)
index 0000000..818a548
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/arm/mach-iop3xx/mm.c
+ *
+ * Low level memory initialization for IOP321 based systems
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * This program is free software; you can redistribute  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/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * Standard IO mapping for all IOP321 based systems
+ */
+static struct map_desc iop321_std_desc[] __initdata = {
+ /* virtual     physical      length      type */
+
+ /* mem mapped registers */
+ { IOP321_VIRT_MEM_BASE,  IOP321_PHY_MEM_BASE,   0x00002000,  MT_DEVICE },
+
+ /* PCI IO space */
+ { 0xfe000000,  0x90000000,   0x00020000,  MT_DEVICE }
+};
+
+void __init iop321_map_io(void)
+{
+       iotable_init(iop321_std_desc, ARRAY_SIZE(iop321_std_desc));
+}
index 3ae69a1..8fdfc3a 100644 (file)
@@ -44,7 +44,7 @@ static u32 iop321_cfg_address(struct pci_bus *bus, int devfn, int where)
        u32 addr;
 
        if (sys->busnr == bus->number)
-               addr = 1 << (PCI_SLOT(devfn) + 16);
+               addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
        else
                addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
 
@@ -158,6 +158,8 @@ iop321_write_config(struct pci_bus *bus, unsigned int devfn, int where,
                        : "r" (value), "r" (addr),
                          "r" (IOP321_OCCAR), "r" (IOP321_OCCDR));
        }
+
+       return PCIBIOS_SUCCESSFUL;
 }
 
 static struct pci_ops iop321_ops = {
@@ -193,53 +195,16 @@ struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *sys)
        return pci_scan_bus(sys->busnr, &iop321_ops, sys);
 }
 
-/*
- * Setup the system data for controller 'nr'.   Return 0 if none found,
- * 1 if found, or negative error.
- */
-int iop321_setup(int nr, struct pci_sys_data *sys)
-{
-       struct resource *res;
-
-       if (nr >= 1)
-               return 0;
-
-       res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-       if (!res)
-               panic("PCI: unable to alloc resources");
-
-       memset(res, 0, sizeof(struct resource) * 2);
-
-       switch (nr) {
-       case 0:
-               res[0].start = IOP321_PCI_IO_BASE + 0x6e000000;
-               res[0].end   = IOP321_PCI_IO_BASE + IOP321_PCI_IO_SIZE-1 + 0x6e000000;
-               res[0].name  = "PCI IO Primary";
-               res[0].flags = IORESOURCE_IO;
-
-               res[1].start = IOP321_PCI_MEM_BASE;
-               res[1].end   = IOP321_PCI_MEM_BASE + IOP321_PCI_MEM_SIZE;
-               res[1].name  = "PCI Memory Primary";
-               res[1].flags = IORESOURCE_MEM;
-               break;
-       }
-
-       request_resource(&ioport_resource, &res[0]);
-       request_resource(&iomem_resource, &res[1]);
-
-       sys->resource[0] = &res[0];
-       sys->resource[1] = &res[1];
-       sys->resource[2] = NULL;
-       sys->io_offset   = 0x6e000000;
-
-       return 1;
-}
-
-
-
-
 void iop321_init(void)
 {
+#if CONFIG_ARCH_EP80219
+    *IOP321_ATUCR = 0x2;
+    *IOP321_OIOWTVR = 0x90000000;
+    *IOP321_IABAR0  = 0x00000004;
+    *IOP321_IABAR2  = 0xa000000c;
+    *IOP321_IALR2   = 0xe0000000;
+#endif
+
        DBG("PCI:  Intel 80321 PCI init code.\n");
        DBG("\tATU: IOP321_ATUCMD=0x%04x\n", *IOP321_ATUCMD);
        DBG("\tATU: IOP321_OMWTVR0=0x%04x, IOP321_OIOWTVR=0x%04x\n",
@@ -251,7 +216,12 @@ void iop321_init(void)
        DBG("\tATU: IOP321_IABAR2=0x%08x IOP321_IALR2=0x%08x IOP321_IATVR2=%08x\n", *IOP321_IABAR2, *IOP321_IALR2, *IOP321_IATVR2);
        DBG("\tATU: IOP321_IABAR3=0x%08x IOP321_IALR3=0x%08x IOP321_IATVR3=%08x\n", *IOP321_IABAR3, *IOP321_IALR3, *IOP321_IATVR3);
 
+#if 0
+       hook_fault_code(4, iop321_pci_abort, SIGBUS, "external abort on linefetch");
+       hook_fault_code(6, iop321_pci_abort, SIGBUS, "external abort on linefetch");
+       hook_fault_code(8, iop321_pci_abort, SIGBUS, "external abort on non-linefetch");
+       hook_fault_code(10, iop321_pci_abort, SIGBUS, "external abort on non-linefetch");
+#endif
        hook_fault_code(16+6, iop321_pci_abort, SIGBUS, "imprecise external abort");
-
 }
 
diff --git a/arch/arm/mach-iop3xx/iop321-setup.c b/arch/arm/mach-iop3xx/iop321-setup.c
new file mode 100644 (file)
index 0000000..e92f77f
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * linux/arch/arm/mach-iop3xx/iop321-setup.c
+ *
+ * Author: Nicolas Pitre <nico@cam.org>
+ * Copyright (C) 2001 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.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#ifdef CONFIG_ARCH_IQ80321
+extern void iq80321_map_io(void);
+extern void iop321_init_irq(void);
+extern void iop321_init_time(void);
+#endif
+
+#ifdef CONFIG_ARCH_IQ31244
+extern void iq31244_map_io(void);
+extern void iop321_init_irq(void);
+extern void iop321_init_time(void);
+#endif
+
+static void __init
+fixup_iop321(struct machine_desc *desc, struct tag *tags,
+             char **cmdline, struct meminfo *mi)
+{
+}
+
+#if defined(CONFIG_ARCH_IQ80321)
+MACHINE_START(IQ80321, "Intel IQ80321")
+       MAINTAINER("Intel Corporation")
+       BOOT_MEM(PHYS_OFFSET, IQ80321_UART, 0xfe800000)
+       FIXUP(fixup_iop321)
+       MAPIO(iq80321_map_io)
+       INITIRQ(iop321_init_irq)
+       INITTIME(iop321_init_time)
+    BOOT_PARAMS(0xa0000100)
+MACHINE_END
+#elif defined(CONFIG_ARCH_IQ31244)
+    MACHINE_START(IQ31244, "Intel IQ31244")
+    MAINTAINER("Intel Corp.")
+    BOOT_MEM(PHYS_OFFSET, IQ31244_UART, IQ31244_UART)
+    MAPIO(iq31244_map_io)
+    INITIRQ(iop321_init_irq)
+       INITTIME(iop321_init_time)
+    BOOT_PARAMS(0xa0000100)
+MACHINE_END
+#else
+#error No machine descriptor defined for this IOP3XX implementation
+#endif
diff --git a/arch/arm/mach-iop3xx/iop331-irq.c b/arch/arm/mach-iop3xx/iop331-irq.c
new file mode 100644 (file)
index 0000000..f4d4321
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * linux/arch/arm/mach-iop3xx/iop331-irq.c
+ *
+ * Generic IOP331 IRQ handling functionality
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+
+#include <asm/mach-types.h>
+
+static u32 iop331_mask0 = 0;
+static u32 iop331_mask1 = 0;
+
+static inline void intctl_write0(u32 val)
+{
+    // INTCTL0
+       asm volatile("mcr p6,0,%0,c0,c0,0"::"r" (val));
+}
+
+static inline void intctl_write1(u32 val)
+{
+    // INTCTL1
+    asm volatile("mcr p6,0,%0,c1,c0,0"::"r" (val));
+}
+
+static inline void intstr_write0(u32 val)
+{
+    // INTSTR0
+       asm volatile("mcr p6,0,%0,c2,c0,0"::"r" (val));
+}
+
+static inline void intstr_write1(u32 val)
+{
+    // INTSTR1
+       asm volatile("mcr p6,0,%0,c3,c0,0"::"r" (val));
+}
+
+static void
+iop331_irq_mask1 (unsigned int irq)
+{
+        iop331_mask0 &= ~(1 << (irq - IOP331_IRQ_OFS));
+        intctl_write0(iop331_mask0);
+}
+
+static void
+iop331_irq_mask2 (unsigned int irq)
+{
+        iop331_mask1 &= ~(1 << (irq - IOP331_IRQ_OFS - 32));
+        intctl_write1(iop331_mask1);
+}
+
+static void
+iop331_irq_unmask1(unsigned int irq)
+{
+        iop331_mask0 |= (1 << (irq - IOP331_IRQ_OFS));
+        intctl_write0(iop331_mask0);
+}
+
+static void
+iop331_irq_unmask2(unsigned int irq)
+{
+        iop331_mask1 |= (1 << (irq - IOP331_IRQ_OFS - 32));
+        intctl_write1(iop331_mask1);
+}
+
+struct irqchip iop331_irqchip1 = {
+       .ack    = iop331_irq_mask1,
+       .mask   = iop331_irq_mask1,
+       .unmask = iop331_irq_unmask1,
+};
+
+struct irqchip iop331_irqchip2 = {
+       .ack    = iop331_irq_mask2,
+       .mask   = iop331_irq_mask2,
+       .unmask = iop331_irq_unmask2,
+};
+
+void __init iop331_init_irq(void)
+{
+       unsigned int i, tmp;
+
+       /* Enable access to coprocessor 6 for dealing with IRQs.
+        * From RMK:
+        * Basically, the Intel documentation here is poor.  It appears that
+        * you need to set the bit to be able to access the coprocessor from
+        * SVC mode.  Whether that allows access from user space or not is
+        * unclear.
+        */
+       asm volatile (
+               "mrc p15, 0, %0, c15, c1, 0\n\t"
+               "orr %0, %0, %1\n\t"
+               "mcr p15, 0, %0, c15, c1, 0\n\t"
+               /* The action is delayed, so we have to do this: */
+               "mrc p15, 0, %0, c15, c1, 0\n\t"
+               "mov %0, %0\n\t"
+               "sub pc, pc, #4"
+               : "=r" (tmp) : "i" (1 << 6) );
+
+       intctl_write0(0);               // disable all interrupts
+       intctl_write1(0);
+       intstr_write0(0);               // treat all as IRQ
+       intstr_write1(0);
+       if(machine_is_iq80331())        // all interrupts are inputs to chip
+               *IOP331_PCIIRSR = 0x0f;
+
+       for(i = IOP331_IRQ_OFS; i < NR_IOP331_IRQS; i++)
+       {
+               set_irq_chip(i, (i < 32) ? &iop331_irqchip1 : &iop331_irqchip2);
+               set_irq_handler(i, do_level_IRQ);
+               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+       }
+}
+
diff --git a/arch/arm/mach-iop3xx/iop331-mm.c b/arch/arm/mach-iop3xx/iop331-mm.c
new file mode 100644 (file)
index 0000000..8a43d4d
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/arm/mach-iop3xx/mm.c
+ *
+ * Low level memory initialization for IOP331 based systems
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * This program is free software; you can redistribute  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/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * Standard IO mapping for all IOP331 based systems
+ */
+static struct map_desc iop331_std_desc[] __initdata = {
+ /* virtual     physical      length      type */
+
+ /* mem mapped registers */
+ { IOP331_VIRT_MEM_BASE,  IOP331_PHYS_MEM_BASE,   0x00002000,  MT_DEVICE },
+
+ /* PCI IO space */
+ { 0xfe000000,  0x90000000,   0x00020000,  MT_DEVICE }
+};
+
+void __init iop331_map_io(void)
+{
+       iotable_init(iop331_std_desc, ARRAY_SIZE(iop331_std_desc));
+}
diff --git a/arch/arm/mach-iop3xx/iop331-pci.c b/arch/arm/mach-iop3xx/iop331-pci.c
new file mode 100644 (file)
index 0000000..f6118dd
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * arch/arm/mach-iop3xx/iop331-pci.c
+ *
+ * PCI support for the Intel IOP331 chipset
+ *
+ * Author: Dave Jiang (dave.jiang@intel.com)
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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/pci.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach/pci.h>
+
+#include <asm/arch/iop331.h>
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define  DBG(x...) printk(x)
+#else
+#define  DBG(x...) do { } while (0)
+#endif
+
+/*
+ * This routine builds either a type0 or type1 configuration command.  If the
+ * bus is on the 80331 then a type0 made, else a type1 is created.
+ */
+static u32 iop331_cfg_address(struct pci_bus *bus, int devfn, int where)
+{
+       struct pci_sys_data *sys = bus->sysdata;
+       u32 addr;
+
+       if (sys->busnr == bus->number)
+               addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
+       else
+               addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
+
+       addr |= PCI_FUNC(devfn) << 8 | (where & ~3);
+
+       return addr;
+}
+
+/*
+ * 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
+ * the discovery stage.
+ */
+static int iop331_pci_status(void)
+{
+       unsigned int status;
+       int ret = 0;
+
+       /*
+        * Check the status registers.
+        */
+       status = *IOP331_ATUSR;
+       if (status & 0xf900)
+       {
+               DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status);
+               *IOP331_ATUSR = status & 0xf900;
+               ret = 1;
+       }
+       status = *IOP331_ATUISR;
+       if (status & 0x679f)
+       {
+               DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status);
+               *IOP331_ATUISR = status & 0x679f;
+               ret = 1;
+       }
+       return ret;
+}
+
+/*
+ * Simply write the address register and read the configuration
+ * data.  Note that the 4 nop's ensure that we are able to handle
+ * a delayed abort (in theory.)
+ */
+static inline u32 iop331_read(unsigned long addr)
+{
+       u32 val;
+
+       __asm__ __volatile__(
+               "str    %1, [%2]\n\t"
+               "ldr    %0, [%3]\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               : "=r" (val)
+               : "r" (addr), "r" (IOP331_OCCAR), "r" (IOP331_OCCDR));
+
+       return val;
+}
+
+/*
+ * The read routines must check the error status of the last configuration
+ * cycle.  If there was an error, the routine returns all hex f's.
+ */
+static int
+iop331_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+               int size, u32 *value)
+{
+       unsigned long addr = iop331_cfg_address(bus, devfn, where);
+       u32 val = iop331_read(addr) >> ((where & 3) * 8);
+
+       if( iop331_pci_status() )
+               val = 0xffffffff;
+
+       *value = val;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop331_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+               int size, u32 value)
+{
+       unsigned long addr = iop331_cfg_address(bus, devfn, where);
+       u32 val;
+
+       if (size != 4) {
+               val = iop331_read(addr);
+               if (!iop331_pci_status() == 0)
+                       return PCIBIOS_SUCCESSFUL;
+
+               where = (where & 3) * 8;
+
+               if (size == 1)
+                       val &= ~(0xff << where);
+               else
+                       val &= ~(0xffff << where);
+
+               *IOP331_OCCDR = val | value << where;
+       } else {
+               asm volatile(
+                       "str    %1, [%2]\n\t"
+                       "str    %0, [%3]\n\t"
+                       "nop\n\t"
+                       "nop\n\t"
+                       "nop\n\t"
+                       "nop\n\t"
+                       :
+                       : "r" (value), "r" (addr),
+                         "r" (IOP331_OCCAR), "r" (IOP331_OCCDR));
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops iop331_ops = {
+       .read   = iop331_read_config,
+       .write  = iop331_write_config,
+};
+
+/*
+ * When a PCI device does not exist during config cycles, the XScale gets a
+ * bus error instead of returning 0xffffffff. This handler simply returns.
+ */
+int
+iop331_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+       DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
+               addr, fsr, regs->ARM_pc, regs->ARM_lr);
+
+       /*
+        * If it was an imprecise abort, then we need to correct the
+        * return address to be _after_ the instruction.
+        */
+       if (fsr & (1 << 10))
+               regs->ARM_pc += 4;
+
+       return 0;
+}
+
+/*
+ * Scan an IOP331 PCI bus.  sys->bus defines which bus we scan.
+ */
+struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *sys)
+{
+       return pci_scan_bus(sys->busnr, &iop331_ops, sys);
+}
+
+void iop331_init(void)
+{
+       DBG("PCI:  Intel 80331 PCI init code.\n");
+       DBG("\tATU: IOP331_ATUCMD=0x%04x\n", *IOP331_ATUCMD);
+       DBG("\tATU: IOP331_OMWTVR0=0x%04x, IOP331_OIOWTVR=0x%04x\n",
+                       *IOP331_OMWTVR0,
+                       *IOP331_OIOWTVR);
+       DBG("\tATU: IOP331_ATUCR=0x%08x\n", *IOP331_ATUCR);
+       DBG("\tATU: IOP331_IABAR0=0x%08x IOP331_IALR0=0x%08x IOP331_IATVR0=%08x\n", *IOP331_IABAR0, *IOP331_IALR0, *IOP331_IATVR0);
+       DBG("\tATU: IOP331_ERBAR=0x%08x IOP331_ERLR=0x%08x IOP331_ERTVR=%08x\n", *IOP331_ERBAR, *IOP331_ERLR, *IOP331_ERTVR);
+       DBG("\tATU: IOP331_IABAR2=0x%08x IOP331_IALR2=0x%08x IOP331_IATVR2=%08x\n", *IOP331_IABAR2, *IOP331_IALR2, *IOP331_IATVR2);
+       DBG("\tATU: IOP331_IABAR3=0x%08x IOP331_IALR3=0x%08x IOP331_IATVR3=%08x\n", *IOP331_IABAR3, *IOP331_IALR3, *IOP331_IATVR3);
+
+       /* redboot changed, reset IABAR0 to something sane */
+       /* fixes master aborts in plugged in cards */
+       /* will clean up later and work nicely with redboot */
+       *IOP331_IABAR0 = 0x00000004;
+       hook_fault_code(16+6, iop331_pci_abort, SIGBUS, "imprecise external abort");
+}
+
diff --git a/arch/arm/mach-iop3xx/iop331-setup.c b/arch/arm/mach-iop3xx/iop331-setup.c
new file mode 100644 (file)
index 0000000..681e1ce
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/arm/mach-iop3xx/iop331-setup.c
+ *
+ * Author: Dave Jiang (dave.jiang@intel.com)
+ * Copyright (C) 2004 Intel 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/mm.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#define IOP331_UART_XTAL 33334000
+
+/*
+ * Standard IO mapping for all IOP331 based systems
+ */
+static struct map_desc iop331_std_desc[] __initdata = {
+ /* virtual     physical      length      type */
+
+ /* mem mapped registers */
+ { IOP331_VIRT_MEM_BASE,  IOP331_PHYS_MEM_BASE,   0x00002000,  MT_DEVICE },
+
+ /* PCI IO space */
+ { 0xfe000000,  0x90000000,   0x00020000,  MT_DEVICE }
+};
+
+static struct uart_port iop331_serial_ports[] = {
+       {
+               .membase        = (char*)(IQ80331_UART0_VIRT),
+               .mapbase        = (IQ80331_UART0_PHYS),
+               .irq            = IRQ_IOP331_UART0,
+               .flags          = UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IOP331_UART_XTAL,
+               .line           = 0,
+               .type           = PORT_XSCALE,
+               .fifosize       = 32
+       } , {
+               .membase        = (char*)(IQ80331_UART1_VIRT),
+               .mapbase        = (IQ80331_UART1_PHYS),
+               .irq            = IRQ_IOP331_UART1,
+               .flags          = UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IOP331_UART_XTAL,
+               .line           = 1,
+               .type           = PORT_XSCALE,
+               .fifosize       = 32
+       }
+};
+
+void __init iop331_map_io(void)
+{
+       iotable_init(iop331_std_desc, ARRAY_SIZE(iop331_std_desc));
+       early_serial_setup(&iop331_serial_ports[0]);
+       early_serial_setup(&iop331_serial_ports[1]);
+}
+
+#ifdef CONFIG_ARCH_IQ80331
+extern void iop331_init_irq(void);
+extern void iop331_init_time(void);
+extern void iq80331_map_io(void);
+#endif
+
+#if defined(CONFIG_ARCH_IQ80331)
+MACHINE_START(IQ80331, "Intel IQ80331")
+    MAINTAINER("Intel Corp.")
+    BOOT_MEM(PHYS_OFFSET, 0xfefff000, 0xfffff000) // virtual, physical
+    //BOOT_MEM(PHYS_OFFSET, IQ80331_UART0_VIRT, IQ80331_UART0_PHYS)
+    MAPIO(iq80331_map_io)
+    INITIRQ(iop331_init_irq)
+    INITTIME(iop331_init_time)
+    BOOT_PARAMS(0x0100)
+MACHINE_END
+#else
+#error No machine descriptor defined for this IOP3XX implementation
+#endif
+
+
diff --git a/arch/arm/mach-iop3xx/iop331-time.c b/arch/arm/mach-iop3xx/iop331-time.c
new file mode 100644 (file)
index 0000000..c90a0c9
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * arch/arm/mach-iop3xx/iop331-time.c
+ *
+ * Timer code for IOP331 based systems
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ *
+ * Copyright 2003 Intel Corp.
+ *
+ *  This program is free software; you can redistribute  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/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/timex.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/mach-types.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+#undef IOP331_TIME_SYNC
+
+static unsigned long iop331_latch;
+
+static inline unsigned long get_elapsed(void)
+{
+       return iop331_latch - *IOP331_TU_TCR0;
+}
+
+static unsigned long iop331_gettimeoffset(void)
+{
+       unsigned long elapsed, usec;
+       u32 tisr1, tisr2;
+
+       /*
+        * If an interrupt was pending before we read the timer,
+        * we've already wrapped.  Factor this into the time.
+        * If an interrupt was pending after we read the timer,
+        * it may have wrapped between checking the interrupt
+        * status and reading the timer.  Re-read the timer to
+        * be sure its value is after the wrap.
+        */
+
+       asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1));
+       elapsed = get_elapsed();
+       asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
+
+       if(tisr1 & 1)
+               elapsed += iop331_latch;
+       else if (tisr2 & 1)
+               elapsed = iop331_latch + get_elapsed();
+
+       /*
+        * Now convert them to usec.
+        */
+       usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / iop331_latch;
+
+       return usec;
+}
+
+static irqreturn_t
+iop331_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       u32 tisr;
+#ifdef IOP331_TIME_SYNC
+       u32 passed;
+#define TM_THRESH (iop331_latch*2)
+#endif
+
+       asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
+
+       tisr |= 1;
+
+       asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
+
+#ifdef IOP331_TIME_SYNC
+       passed = 0xffffffff - *IOP331_TU_TCR1;
+
+       do
+       {
+               do_timer(regs);
+               if(passed < TM_THRESH)
+                       break;
+               if(passed > iop331_latch)
+                       passed -= iop331_latch;
+               else
+                       passed = 0;
+       } while(1);
+
+       asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
+#else
+       do_timer(regs);
+#endif
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction iop331_timer_irq = {
+       .name           = "IOP331 Timer Tick",
+       .handler        = iop331_timer_interrupt,
+       .flags          = SA_INTERRUPT
+};
+
+extern int setup_arm_irq(int, struct irqaction*);
+
+void __init iop331_init_time(void)
+{
+       u32 timer_ctl;
+
+       iop331_latch = (CLOCK_TICK_RATE + HZ / 2) / HZ;
+       gettimeoffset = iop331_gettimeoffset;
+       setup_irq(IRQ_IOP331_TIMER0, &iop331_timer_irq);
+
+       timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED | IOP331_TMR_RELOAD |
+                       IOP331_TMR_RATIO_1_1;
+
+       asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (iop331_latch));
+
+       asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
+
+#ifdef IOP331_TIME_SYNC
+        /* Setup second timer */
+        /* setup counter */
+        timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED |
+                        IOP331_TMR_RATIO_1_1;
+        asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
+        /* setup control */
+        asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (timer_ctl));
+#endif
+}
+
+
diff --git a/arch/arm/mach-iop3xx/iq31244-mm.c b/arch/arm/mach-iop3xx/iq31244-mm.c
new file mode 100644 (file)
index 0000000..b01042f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * linux/arch/arm/mach-iop3xx/mm.c
+ *
+ * Low level memory initialization for iq80321 platform
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * This program is free software; you can redistribute  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/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * IQ80321 specific IO mappings
+ *
+ * We use RedBoot's setup for the onboard devices.
+ */
+static struct map_desc iq31244_io_desc[] __initdata = {
+ /* virtual     physical      length        type */
+
+ /* on-board devices */
+ { IQ31244_UART, IQ31244_UART,   0x00100000,   MT_DEVICE }
+};
+
+void __init iq31244_map_io(void)
+{
+       iop321_map_io();
+
+       iotable_init(iq31244_io_desc, ARRAY_SIZE(iq31244_io_desc));
+}
diff --git a/arch/arm/mach-iop3xx/iq31244-pci.c b/arch/arm/mach-iop3xx/iq31244-pci.c
new file mode 100644 (file)
index 0000000..5eac93e
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * arch/arm/mach-iop3xx/iq80321-pci.c
+ *
+ * PCI support for the Intel IQ80321 reference board
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * 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/pci.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/*
+ * The following macro is used to lookup irqs in a standard table
+ * format for those systems that do not already have PCI
+ * interrupts properly routed.  We assume 1 <= pin <= 4
+ */
+#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)      \
+({ int _ctl_ = -1;                             \
+   unsigned int _idsel = idsel - minid;                \
+   if (_idsel <= maxid)                                \
+      _ctl_ = pci_irq_table[_idsel][pin-1];    \
+   _ctl_; })
+
+#define INTA   IRQ_IQ31244_INTA
+#define INTB   IRQ_IQ31244_INTB
+#define INTC   IRQ_IQ31244_INTC
+#define INTD   IRQ_IQ31244_INTD
+
+#define INTE   IRQ_IQ31244_I82546
+
+static inline int __init
+iq31244_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+{
+       static int pci_irq_table[][4] = {
+               /*
+                * PCI IDSEL/INTPIN->INTLINE
+                * A       B       C       D
+                */
+#ifdef CONFIG_ARCH_EP80219
+               {INTB, INTB, INTB, INTB}, /* CFlash */
+               {INTE, INTE, INTE, INTE}, /* 82551 Pro 100 */
+               {INTD, INTD, INTD, INTD}, /* PCI-X Slot */
+               {INTC, INTC, INTC, INTC}, /* SATA   */
+#else
+               {INTB, INTB, INTB, INTB}, /* CFlash */
+               {INTC, INTC, INTC, INTC}, /* SATA   */
+               {INTD, INTD, INTD, INTD}, /* PCI-X Slot */
+               {INTE, INTE, INTE, INTE}, /* 82546 GigE */
+#endif // CONFIG_ARCH_EP80219
+       };
+
+       BUG_ON(pin < 1 || pin > 4);
+
+       return PCI_IRQ_TABLE_LOOKUP(0, 7);
+}
+
+static int iq31244_setup(int nr, struct pci_sys_data *sys)
+{
+       struct resource *res;
+
+       if(nr != 0)
+               return 0;
+
+       res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+       if (!res)
+               panic("PCI: unable to alloc resources");
+
+       memset(res, 0, sizeof(struct resource) * 2);
+
+       res[0].start = IQ31244_PCI_IO_BASE + 0x6e000000;
+       res[0].end   = IQ31244_PCI_IO_BASE + IQ31244_PCI_IO_SIZE - 1 + IQ31244_PCI_IO_OFFSET;
+       res[0].name  = "IQ31244 PCI I/O Space";
+       res[0].flags = IORESOURCE_IO;
+
+       res[1].start = IQ31244_PCI_MEM_BASE;
+       res[1].end   = IQ31244_PCI_MEM_BASE + IQ31244_PCI_MEM_SIZE;
+       res[1].name  = "IQ31244 PCI Memory Space";
+       res[1].flags = IORESOURCE_MEM;
+
+       request_resource(&ioport_resource, &res[0]);
+       request_resource(&iomem_resource, &res[1]);
+
+       sys->resource[0] = &res[0];
+       sys->resource[1] = &res[1];
+       sys->resource[2] = NULL;
+       sys->io_offset   = IQ31244_PCI_IO_OFFSET;
+       sys->mem_offset = IQ80321_PCI_MEM_BASE -
+               (*IOP321_IABAR1 & PCI_BASE_ADDRESS_MEM_MASK);
+
+       iop3xx_pcibios_min_io = IQ31244_PCI_IO_BASE;
+       iop3xx_pcibios_min_mem = IQ31244_PCI_MEM_BASE;
+
+       return 1;
+}
+
+static void iq31244_preinit(void)
+{
+       iop321_init();
+       /* setting up the second translation window */
+       *IOP321_OMWTVR1 = IQ31244_PCI_MEM_BASE + 0x04000000;
+       *IOP321_OUMWTVR1 = 0x0;
+}
+
+static struct hw_pci iq31244_pci __initdata = {
+       .swizzle        = pci_std_swizzle,
+       .nr_controllers = 1,
+       .setup          = iq31244_setup,
+       .scan           = iop321_scan_bus,
+       .preinit        = iq31244_preinit,
+       .map_irq        = iq31244_map_irq
+};
+
+static int __init iq31244_pci_init(void)
+{
+       if (machine_is_iq31244())
+               pci_common_init(&iq31244_pci);
+       return 0;
+}
+
+subsys_initcall(iq31244_pci_init);
+
+
+
+
diff --git a/arch/arm/mach-iop3xx/iq80321-mm.c b/arch/arm/mach-iop3xx/iq80321-mm.c
new file mode 100644 (file)
index 0000000..1580c7e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * linux/arch/arm/mach-iop3xx/mm.c
+ *
+ * Low level memory initialization for iq80321 platform
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * This program is free software; you can redistribute  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/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * IQ80321 specific IO mappings
+ *
+ * We use RedBoot's setup for the onboard devices.
+ */
+static struct map_desc iq80321_io_desc[] __initdata = {
+ /* virtual     physical      length        type */
+
+ /* on-board devices */
+ { IQ80321_UART, IQ80321_UART,   0x00100000,   MT_DEVICE }
+};
+
+void __init iq80321_map_io(void)
+{
+       iop321_map_io();
+
+       iotable_init(iq80321_io_desc, ARRAY_SIZE(iq80321_io_desc));
+}
index 7dce5df..5d96248 100644 (file)
 
 #define INTE   IRQ_IQ80321_I82544
 
-typedef u8 irq_table[4];
-
-static irq_table pci_irq_table[] = {
-       /*
-        * PCI IDSEL/INTPIN->INTLINE
-        * A       B       C       D
-        */
-       {INTE, INTE, INTE, INTE}, /* Gig-E */
-       {INTD, INTC, INTD, INTA}, /* Unused */
-       {INTC, INTD, INTA, INTB}, /* PCI-X Slot */
-};
-
 static inline int __init
 iq80321_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
 {
+       static int pci_irq_table[][4] = {
+               /*
+                * PCI IDSEL/INTPIN->INTLINE
+                * A       B       C       D
+                */
+               {INTE, INTE, INTE, INTE}, /* Gig-E */
+               {-1, -1, -1, -1},         /* Unused */
+               {INTC, INTD, INTA, INTB}, /* PCI-X Slot */
+               {-1, -1, -1, -1},
+       };
+
        BUG_ON(pin < 1 || pin > 4);
 
-       return PCI_IRQ_TABLE_LOOKUP(2, 3);
+//     return PCI_IRQ_TABLE_LOOKUP(4, 7);
+       return pci_irq_table[idsel%4][pin-1];
 }
 
 static int iq80321_setup(int nr, struct pci_sys_data *sys)
 {
-       switch (nr) {
-       case 0:
-               sys->map_irq = iq80321_map_irq;
-               break;
-       default:
+       struct resource *res;
+
+       if(nr != 0)
                return 0;
-       }
 
-       return iop321_setup(nr, sys);
+       res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+       if (!res)
+               panic("PCI: unable to alloc resources");
+
+       memset(res, 0, sizeof(struct resource) * 2);
+
+       res[0].start = IQ80321_PCI_IO_BASE + IQ80321_PCI_IO_OFFSET;
+       res[0].end   = IQ80321_PCI_IO_BASE + IQ80321_PCI_IO_SIZE - 1 + IQ80321_PCI_IO_OFFSET;
+       res[0].name  = "IQ80321 PCI I/O Space";
+       res[0].flags = IORESOURCE_IO;
+
+       res[1].start = IQ80321_PCI_MEM_BASE;
+       res[1].end   = IQ80321_PCI_MEM_BASE + IQ80321_PCI_MEM_SIZE;
+       res[1].name  = "IQ80321 PCI Memory Space";
+       res[1].flags = IORESOURCE_MEM;
+
+       request_resource(&ioport_resource, &res[0]);
+       request_resource(&iomem_resource, &res[1]);
+
+       /*
+        * Since the IQ80321 is a slave card on a PCI backplane,
+        * it uses BAR1 to reserve a portion of PCI memory space for
+        * use with the private devices on the secondary bus
+        * (GigE and PCI-X slot). We read BAR1 and configure
+        * our outbound translation windows to target that
+        * address range and assign all devices in that
+        * address range. W/O this, certain BIOSes will fail
+        * to boot as the IQ80321 claims addresses that are
+        * in use by other devices.
+        *
+        * Note that the same cannot be done  with I/O space,
+        * so hopefully the host will stick to the lower 64K for
+        * PCI I/O and leave us alone.
+        */
+       sys->mem_offset = IQ80321_PCI_MEM_BASE -
+               (*IOP321_IABAR1 & PCI_BASE_ADDRESS_MEM_MASK);
+
+       sys->resource[0] = &res[0];
+       sys->resource[1] = &res[1];
+       sys->resource[2] = NULL;
+       sys->io_offset   = IQ80321_PCI_IO_OFFSET;
+
+       iop3xx_pcibios_min_io = IQ80321_PCI_IO_BASE;
+       iop3xx_pcibios_min_mem = IQ80321_PCI_MEM_BASE;
+
+       return 1;
 }
 
 static void iq80321_preinit(void)
@@ -82,6 +124,7 @@ static struct hw_pci iq80321_pci __initdata = {
        .setup          = iq80321_setup,
        .scan           = iop321_scan_bus,
        .preinit        = iq80321_preinit,
+       .map_irq        = iq80321_map_irq
 };
 
 static int __init iq80321_pci_init(void)
diff --git a/arch/arm/mach-iop3xx/iq80331-mm.c b/arch/arm/mach-iop3xx/iq80331-mm.c
new file mode 100644 (file)
index 0000000..ee8c333
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/arm/mach-iop3xx/mm.c
+ *
+ * Low level memory initialization for iq80331 platform
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * This program is free software; you can redistribute  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/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * IQ80331 specific IO mappings
+ *
+ * We use RedBoot's setup for the onboard devices.
+ */
+
+void __init iq80331_map_io(void)
+{
+       iop331_map_io();
+}
diff --git a/arch/arm/mach-iop3xx/iq80331-pci.c b/arch/arm/mach-iop3xx/iq80331-pci.c
new file mode 100644 (file)
index 0000000..1eff557
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * arch/arm/mach-iop3xx/iq80331-pci.c
+ *
+ * PCI support for the Intel IQ80331 reference board
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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/pci.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/*
+ * The following macro is used to lookup irqs in a standard table
+ * format for those systems that do not already have PCI
+ * interrupts properly routed.  We assume 1 <= pin <= 4
+ */
+#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)      \
+({ int _ctl_ = -1;                             \
+   unsigned int _idsel = idsel - minid;                \
+   if (_idsel <= maxid)                                \
+      _ctl_ = pci_irq_table[_idsel][pin-1];    \
+   _ctl_; })
+
+#define INTA   IRQ_IQ80331_INTA
+#define INTB   IRQ_IQ80331_INTB
+#define INTC   IRQ_IQ80331_INTC
+#define INTD   IRQ_IQ80331_INTD
+
+//#define INTE IRQ_IQ80331_I82544
+
+static inline int __init
+iq80331_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+{
+       static int pci_irq_table[][4] = {
+               /*
+                * PCI IDSEL/INTPIN->INTLINE
+                * A       B       C       D
+                */
+               {INTB, INTC, INTD, INTA}, /* PCI-X Slot */
+               {INTC, INTC, INTC, INTC}, /* GigE  */
+       };
+
+       BUG_ON(pin < 1 || pin > 4);
+
+       return PCI_IRQ_TABLE_LOOKUP(1, 7);
+}
+
+static int iq80331_setup(int nr, struct pci_sys_data *sys)
+{
+       struct resource *res;
+
+       if(nr != 0)
+               return 0;
+
+       res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+       if (!res)
+               panic("PCI: unable to alloc resources");
+
+       memset(res, 0, sizeof(struct resource) * 2);
+
+       res[0].start = IQ80331_PCI_IO_BASE + 0x6e000000;
+       res[0].end   = IQ80331_PCI_IO_BASE + IQ80331_PCI_IO_SIZE - 1 + IQ80331_PCI_IO_OFFSET;
+       res[0].name  = "IQ80331 PCI I/O Space";
+       res[0].flags = IORESOURCE_IO;
+
+       res[1].start = IQ80331_PCI_MEM_BASE;
+       res[1].end   = IQ80331_PCI_MEM_BASE + IQ80331_PCI_MEM_SIZE;
+       res[1].name  = "IQ80331 PCI Memory Space";
+       res[1].flags = IORESOURCE_MEM;
+
+       request_resource(&ioport_resource, &res[0]);
+       request_resource(&iomem_resource, &res[1]);
+
+       /*
+        * Since the IQ80331 is a slave card on a PCI backplane,
+        * it uses BAR1 to reserve a portion of PCI memory space for
+        * use with the private devices on the secondary bus
+        * (GigE and PCI-X slot). We read BAR1 and configure
+        * our outbound translation windows to target that
+        * address range and assign all devices in that
+        * address range. W/O this, certain BIOSes will fail
+        * to boot as the IQ80331 claims addresses that are
+        * in use by other devices.
+        *
+        * Note that the same cannot be done  with I/O space,
+        * so hopefully the host will stick to the lower 64K for
+        * PCI I/O and leave us alone.
+        */
+       sys->mem_offset = IQ80331_PCI_MEM_BASE -
+               (*IOP331_IABAR1 & PCI_BASE_ADDRESS_MEM_MASK);
+
+       sys->resource[0] = &res[0];
+       sys->resource[1] = &res[1];
+       sys->resource[2] = NULL;
+       sys->io_offset   = IQ80331_PCI_IO_OFFSET;
+
+       iop3xx_pcibios_min_io = IQ80331_PCI_IO_BASE;
+       iop3xx_pcibios_min_mem = IQ80331_PCI_MEM_BASE;
+
+       return 1;
+}
+
+static void iq80331_preinit(void)
+{
+       iop331_init();
+}
+
+static struct hw_pci iq80331_pci __initdata = {
+       .swizzle        = pci_std_swizzle,
+       .nr_controllers = 1,
+       .setup          = iq80331_setup,
+       .scan           = iop331_scan_bus,
+       .preinit        = iq80331_preinit,
+       .map_irq        = iq80331_map_irq
+};
+
+static int __init iq80331_pci_init(void)
+{
+       if (machine_is_iq80331())
+               pci_common_init(&iq80331_pci);
+       return 0;
+}
+
+subsys_initcall(iq80331_pci_init);
+
+
+
+
diff --git a/arch/arm/mach-ixp2000/Kconfig b/arch/arm/mach-ixp2000/Kconfig
new file mode 100644 (file)
index 0000000..a22d220
--- /dev/null
@@ -0,0 +1,59 @@
+
+if ARCH_IXP2000
+
+config ARCH_SUPPORTS_BIG_ENDIAN
+       bool
+       default y
+
+menu "Intel IXP2400/2800 Implementation Options"
+
+comment "IXP2400/2800 Platforms"
+
+config ARCH_ENP2611
+       bool "Support Radisys ENP-2611"
+       help
+         Say 'Y' here if you want your kernel to support the Radisys
+         ENP2611 PCI network processing card. For more information on
+         this card, see Documentation/arm/ENP2611.
+
+config ARCH_IXDP2400
+       bool "Support Intel IXDP2400"
+       help
+         Say 'Y' here if you want your kernel to support the Intel
+         IXDP2400 reference platform. For more information on
+         this platform, see Documentation/arm/IXP2000.
+
+config ARCH_IXDP2800
+       bool "Support Intel IXDP2800"
+       help
+         Say 'Y' here if you want your kernel to support the Intel
+         IXDP2800 reference platform. For more information on
+         this platform, see Documentation/arm/IXP2000.
+
+config ARCH_IXDP2X00
+       bool
+       depends on ARCH_IXDP2400 || ARCH_IXDP2800
+       default y       
+
+config ARCH_IXDP2401
+       bool "Support Intel IXDP2401"
+       help
+         Say 'Y' here if you want your kernel to support the Intel
+         IXDP2401 reference platform. For more information on
+         this platform, see Documentation/arm/IXP2000.
+
+config ARCH_IXDP2801
+       bool "Support Intel IXDP2801"
+       help
+         Say 'Y' here if you want your kernel to support the Intel
+         IXDP2801 reference platform. For more information on
+         this platform, see Documentation/arm/IXP2000.
+
+config ARCH_IXDP2X01
+       bool
+       depends on ARCH_IXDP2401 || ARCH_IXDP2801
+       default y       
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-ixp2000/Makefile b/arch/arm/mach-ixp2000/Makefile
new file mode 100644 (file)
index 0000000..1e6139d
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Makefile for the linux kernel.
+#
+obj-y                  := core.o pci.o
+obj-m                  :=
+obj-n                  :=
+obj-                   :=
+
+obj-$(CONFIG_ARCH_ENP2611)     += enp2611.o
+obj-$(CONFIG_ARCH_IXDP2400)    += ixdp2400.o
+obj-$(CONFIG_ARCH_IXDP2800)    += ixdp2800.o
+obj-$(CONFIG_ARCH_IXDP2X00)    += ixdp2x00.o
+obj-$(CONFIG_ARCH_IXDP2X01)    += ixdp2x01.o
+
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
new file mode 100644 (file)
index 0000000..2d66337
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ * arch/arm/mach-ixp2000/common.c
+ *
+ * Common routines used by all IXP2400/2800 based platforms.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (C) MontaVista Software, Inc. 
+ *
+ * Based on work Copyright (C) 2002-2003 Intel Corporation
+ * 
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/serial_core.h>
+#include <linux/mm.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+
+static spinlock_t ixp2000_slowport_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long ixp2000_slowport_irq_flags;
+
+/*************************************************************************
+ * Slowport access routines
+ *************************************************************************/
+void ixp2000_acquire_slowport(struct slowport_cfg *new_cfg, struct slowport_cfg *old_cfg)
+{
+
+       spin_lock_irqsave(&ixp2000_slowport_lock, ixp2000_slowport_irq_flags);
+
+       old_cfg->CCR = *IXP2000_SLOWPORT_CCR;
+       old_cfg->WTC = *IXP2000_SLOWPORT_WTC2;
+       old_cfg->RTC = *IXP2000_SLOWPORT_RTC2;
+       old_cfg->PCR = *IXP2000_SLOWPORT_PCR;
+       old_cfg->ADC = *IXP2000_SLOWPORT_ADC;
+
+       ixp2000_reg_write(IXP2000_SLOWPORT_CCR, new_cfg->CCR);
+       ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, new_cfg->WTC);
+       ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, new_cfg->RTC);
+       ixp2000_reg_write(IXP2000_SLOWPORT_PCR, new_cfg->PCR);
+       ixp2000_reg_write(IXP2000_SLOWPORT_ADC, new_cfg->ADC);
+}
+
+void ixp2000_release_slowport(struct slowport_cfg *old_cfg)
+{
+       ixp2000_reg_write(IXP2000_SLOWPORT_CCR, old_cfg->CCR);
+       ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, old_cfg->WTC);
+       ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, old_cfg->RTC);
+       ixp2000_reg_write(IXP2000_SLOWPORT_PCR, old_cfg->PCR);
+       ixp2000_reg_write(IXP2000_SLOWPORT_ADC, old_cfg->ADC);
+
+       spin_unlock_irqrestore(&ixp2000_slowport_lock, 
+                                       ixp2000_slowport_irq_flags);
+}
+
+/*************************************************************************
+ * Chip specific mappings shared by all IXP2000 systems
+ *************************************************************************/
+static struct map_desc ixp2000_small_io_desc[] __initdata = {
+       {
+               .virtual        = IXP2000_GLOBAL_REG_VIRT_BASE,
+               .physical       = IXP2000_GLOBAL_REG_PHYS_BASE,
+               .length         = IXP2000_GLOBAL_REG_SIZE,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        = IXP2000_GPIO_VIRT_BASE,
+               .physical       = IXP2000_GPIO_PHYS_BASE,
+               .length         = IXP2000_GPIO_SIZE,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        = IXP2000_TIMER_VIRT_BASE,
+               .physical       = IXP2000_TIMER_PHYS_BASE,
+               .length         = IXP2000_TIMER_SIZE,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        = IXP2000_UART_VIRT_BASE,
+               .physical       = IXP2000_UART_PHYS_BASE,
+               .length         = IXP2000_UART_SIZE,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        = IXP2000_SLOWPORT_CSR_VIRT_BASE,
+               .physical       = IXP2000_SLOWPORT_CSR_PHYS_BASE,
+               .length         = IXP2000_SLOWPORT_CSR_SIZE,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        = IXP2000_INTCTL_VIRT_BASE,
+               .physical       = IXP2000_INTCTL_PHYS_BASE,
+               .length         = IXP2000_INTCTL_SIZE,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        = IXP2000_PCI_CREG_VIRT_BASE,
+               .physical       = IXP2000_PCI_CREG_PHYS_BASE,
+               .length         = IXP2000_PCI_CREG_SIZE,
+               .type           = MT_DEVICE
+       }
+};
+
+static struct map_desc ixp2000_large_io_desc[] __initdata = {
+       {
+               .virtual        = IXP2000_PCI_CSR_VIRT_BASE,
+               .physical       = IXP2000_PCI_CSR_PHYS_BASE,
+               .length         = IXP2000_PCI_CSR_SIZE,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        = IXP2000_PCI_IO_VIRT_BASE,
+               .physical       = IXP2000_PCI_IO_PHYS_BASE,
+               .length         = IXP2000_PCI_IO_SIZE,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        = IXP2000_PCI_CFG0_VIRT_BASE,
+               .physical       = IXP2000_PCI_CFG0_PHYS_BASE,
+               .length         = IXP2000_PCI_CFG0_SIZE,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        = IXP2000_PCI_CFG1_VIRT_BASE,
+               .physical       = IXP2000_PCI_CFG1_PHYS_BASE,
+               .length         = IXP2000_PCI_CFG1_SIZE,
+               .type           = MT_DEVICE
+       }
+};
+
+static struct uart_port ixp2000_serial_port = {
+       .membase        = (char *)(IXP2000_UART_VIRT_BASE + 3),
+       .mapbase        = IXP2000_UART_PHYS_BASE + 3,
+       .irq            = IRQ_IXP2000_UART,
+       .flags          = UPF_SKIP_TEST,
+       .iotype         = UPIO_MEM,
+       .regshift       = 2,
+       .uartclk        = 50000000,
+       .line           = 0,
+       .type           = PORT_XSCALE,
+       .fifosize       = 16
+};
+
+void __init ixp2000_map_io(void)
+{
+       iotable_init(ixp2000_small_io_desc, ARRAY_SIZE(ixp2000_small_io_desc));
+       iotable_init(ixp2000_large_io_desc, ARRAY_SIZE(ixp2000_large_io_desc));
+       early_serial_setup(&ixp2000_serial_port);
+}
+
+/*************************************************************************
+ * Timer-tick functions for IXP2000
+ *************************************************************************/
+static unsigned ticks_per_jiffy;
+static unsigned ticks_per_usec;
+
+static unsigned long ixp2000_gettimeoffset (void)
+{
+       unsigned long elapsed;
+
+       /* Get ticks since last perfect jiffy */
+       elapsed = ticks_per_jiffy - *IXP2000_T1_CSR;
+
+       return elapsed / ticks_per_usec;
+}
+
+static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       /* clear timer 1 */
+       ixp2000_reg_write(IXP2000_T1_CLR, 1);
+       
+       timer_tick(regs);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction ixp2000_timer_irq = {
+       .name           = "IXP2000 Timer Tick",
+       .flags          = SA_INTERRUPT,
+       .handler        = ixp2000_timer_interrupt
+};
+
+void __init ixp2000_init_time(unsigned long tick_rate)
+{
+       gettimeoffset = ixp2000_gettimeoffset;
+
+       ixp2000_reg_write(IXP2000_T1_CLR, 0);
+       ixp2000_reg_write(IXP2000_T2_CLR, 0);
+
+       ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
+       ticks_per_usec = tick_rate / 1000000;
+
+       ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy);
+       ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
+
+       /* register for interrupt */
+       setup_irq(IRQ_IXP2000_TIMER1, &ixp2000_timer_irq);
+}
+
+/*************************************************************************
+ * GPIO helpers
+ *************************************************************************/
+static unsigned long GPIO_IRQ_rising_edge;
+static unsigned long GPIO_IRQ_falling_edge;
+static unsigned long GPIO_IRQ_level_low;
+static unsigned long GPIO_IRQ_level_high;
+
+void gpio_line_config(int line, int style)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       if(style == GPIO_OUT) {
+               /* if it's an output, it ain't an interrupt anymore */
+               ixp2000_reg_write(IXP2000_GPIO_PDSR, (1 << line));
+               GPIO_IRQ_falling_edge &= ~(1 << line);
+               GPIO_IRQ_rising_edge &= ~(1 << line);
+               GPIO_IRQ_level_low &= ~(1 << line);
+               GPIO_IRQ_level_high &= ~(1 << line);
+               ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);
+               ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);
+               ixp2000_reg_write(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
+               ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);
+               irq_desc[line+IRQ_IXP2000_GPIO0].valid = 0;
+       } else if(style == GPIO_IN) {
+               ixp2000_reg_write(IXP2000_GPIO_PDCR, (1 << line));
+       }
+               
+       local_irq_restore(flags);
+}      
+
+
+/*************************************************************************
+ * IRQ handling IXP2000
+ *************************************************************************/
+static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{                               
+       int i;
+       unsigned long status = *IXP2000_GPIO_INST;
+                  
+       for (i = 0; i <= 7; i++) {
+               if (status & (1<<i)) {
+                       desc = irq_desc + i + IRQ_IXP2000_GPIO0;
+                       desc->handle(i + IRQ_IXP2000_GPIO0, desc, regs);
+               }
+       }
+}
+
+static void ixp2000_GPIO_irq_mask_ack(unsigned int irq)
+{
+       ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+       ixp2000_reg_write(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
+}
+
+static void ixp2000_GPIO_irq_mask(unsigned int irq)
+{
+       ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+}
+
+static void ixp2000_GPIO_irq_unmask(unsigned int irq)
+{
+       ixp2000_reg_write(IXP2000_GPIO_INSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+}
+
+static struct irqchip ixp2000_GPIO_irq_chip = {
+       .ack    = ixp2000_GPIO_irq_mask_ack,
+       .mask   = ixp2000_GPIO_irq_mask,
+       .unmask = ixp2000_GPIO_irq_unmask
+};
+
+static void ixp2000_pci_irq_mask(unsigned int irq)
+{
+       unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
+       if (irq == IRQ_IXP2000_PCIA)
+               ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26)));
+       else if (irq == IRQ_IXP2000_PCIB)
+               ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27)));
+}
+
+static void ixp2000_pci_irq_unmask(unsigned int irq)
+{
+       unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
+       if (irq == IRQ_IXP2000_PCIA)
+               ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 26)));
+       else if (irq == IRQ_IXP2000_PCIB)
+               ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27)));
+}
+
+static struct irqchip ixp2000_pci_irq_chip = {
+       .ack    = ixp2000_pci_irq_mask,
+       .mask   = ixp2000_pci_irq_mask,
+       .unmask = ixp2000_pci_irq_unmask
+};
+
+/*
+ * Error interrupts. These are used extensively by the microengine drivers
+ */
+static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc,  struct pt_regs *regs)
+{
+       int i;
+       unsigned long status = *IXP2000_IRQ_ERR_STATUS;
+
+
+       for (i = 0; i <= 12; i++) {
+               if (status & (1 << i)) {
+                       desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i;
+                       desc->handle(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs);
+               }
+       }
+}
+
+static void ixp2000_err_irq_mask(unsigned int irq)
+{
+       ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_CLR,
+                       (1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
+}
+
+static void ixp2000_err_irq_unmask(unsigned int irq)
+{
+       ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_SET,
+                       (1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
+}
+
+static struct irqchip ixp2000_err_irq_chip = {
+       .ack    = ixp2000_err_irq_mask,
+       .mask   = ixp2000_err_irq_mask,
+       .unmask = ixp2000_err_irq_unmask
+};
+
+static void ixp2000_irq_mask(unsigned int irq)
+{
+       ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, (1 << irq));
+}
+
+static void ixp2000_irq_unmask(unsigned int irq)
+{
+       ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET,  (1 << irq));
+}
+
+static struct irqchip ixp2000_irq_chip = {
+       .ack    = ixp2000_irq_mask,
+       .mask   = ixp2000_irq_mask,
+       .unmask = ixp2000_irq_unmask
+};
+
+void __init ixp2000_init_irq(void)
+{
+       int irq;
+
+       /*
+        * Mask all sources
+        */
+       ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, 0xffffffff);
+       ixp2000_reg_write(IXP2000_FIQ_ENABLE_CLR, 0xffffffff);
+
+       /* clear all GPIO edge/level detects */
+       ixp2000_reg_write(IXP2000_GPIO_REDR, 0);
+       ixp2000_reg_write(IXP2000_GPIO_FEDR, 0);
+       ixp2000_reg_write(IXP2000_GPIO_LSHR, 0);
+       ixp2000_reg_write(IXP2000_GPIO_LSLR, 0);
+       ixp2000_reg_write(IXP2000_GPIO_INCR, -1);
+
+       /* clear PCI interrupt sources */
+       ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, 0);
+
+       /*
+        * Certain bits in the IRQ status register of the 
+        * IXP2000 are reserved. Instead of trying to map
+        * things non 1:1 from bit position to IRQ number,
+        * we mark the reserved IRQs as invalid. This makes
+        * our mask/unmask code much simpler.
+        */
+       for (irq = IRQ_IXP2000_SWI; irq <= IRQ_IXP2000_THDB3; irq++) {
+               if((1 << irq) & IXP2000_VALID_IRQ_MASK) {
+                       set_irq_chip(irq, &ixp2000_irq_chip);
+                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_flags(irq, IRQF_VALID);
+               } else set_irq_flags(irq, 0);
+       }
+       
+       /*
+        * GPIO IRQs are invalid until someone sets the interrupt mode
+        * by calling gpio_line_set();
+        */
+       for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) {
+               set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
+               set_irq_handler(irq, do_level_IRQ);
+               set_irq_flags(irq, 0);
+       }
+       set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);
+
+       /*
+        * Enable PCI irq
+        */
+       *(IXP2000_IRQ_ENABLE_SET) = (1 << IRQ_IXP2000_PCI);
+       for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) {
+               set_irq_chip(irq, &ixp2000_pci_irq_chip);
+               set_irq_handler(irq, do_level_IRQ);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+
+       for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) {
+               set_irq_chip(irq, &ixp2000_err_irq_chip);
+               set_irq_handler(irq, do_level_IRQ);
+               set_irq_flags(irq, IRQF_VALID);
+       }       
+       set_irq_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler);
+}
+
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
new file mode 100644 (file)
index 0000000..a6e30d0
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * arch/arm/mach-ixp2000/enp2611.c
+ *
+ * Radisys ENP-2611 support.
+ *
+ * Created 2004 by Lennert Buytenhek from the ixdp2x01 code.  The
+ * original version carries the following notices:
+ *
+ * Original Author: Andrzej Mialwoski <andrzej.mialwoski@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002-2003 Intel Corp.
+ * Copyright (C) 2003-2004 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+/*************************************************************************
+ * ENP-2611 timer tick configuration
+ *************************************************************************/
+static void __init enp2611_init_time(void)
+{
+       ixp2000_init_time(50 * 1000 * 1000);
+}
+
+
+/*************************************************************************
+ * ENP-2611 PCI
+ *************************************************************************/
+static int enp2611_pci_setup(int nr, struct pci_sys_data *sys)
+{
+       sys->mem_offset = 0xe0000000;
+       ixp2000_pci_setup(nr, sys);
+       return 1;
+}
+
+static void __init enp2611_pci_preinit(void)
+{
+       ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
+       ixp2000_pci_preinit();
+}
+
+static inline int enp2611_pci_valid_device(struct pci_bus *bus,
+                                               unsigned int devfn)
+{
+       /* The 82559 ethernet controller appears at both PCI:1:0:0 and
+        * PCI:1:2:0, so let's pretend the second one isn't there.
+        */
+       if (bus->number == 0x01 && devfn == 0x10)
+               return 0;
+
+       return 1;
+}
+
+static int enp2611_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+                                       int where, int size, u32 *value)
+{
+       if (enp2611_pci_valid_device(bus, devfn))
+               return ixp2000_pci_read_config(bus, devfn, where, size, value);
+
+       return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static int enp2611_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+                                       int where, int size, u32 value)
+{
+       if (enp2611_pci_valid_device(bus, devfn))
+               return ixp2000_pci_write_config(bus, devfn, where, size, value);
+
+       return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static struct pci_ops enp2611_pci_ops = {
+       .read   = enp2611_pci_read_config,
+       .write  = enp2611_pci_write_config
+};
+
+static struct pci_bus * __init enp2611_pci_scan_bus(int nr,
+                                               struct pci_sys_data *sys)
+{
+       return pci_scan_bus(sys->busnr, &enp2611_pci_ops, sys);
+}
+
+static int __init enp2611_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int irq;
+
+       if (dev->bus->number == 0x00 && PCI_SLOT(dev->devfn) == 0x01) {
+               /* 21555 non-transparent bridge.  */
+               irq = IRQ_IXP2000_PCIB;
+       } else if (dev->bus->number == 0x01 && PCI_SLOT(dev->devfn) == 0x00) {
+               /* 82559 ethernet.  */
+               irq = IRQ_IXP2000_PCIA;
+       } else {
+               printk(KERN_INFO "enp2611_pci_map_irq for unknown device\n");
+               irq = IRQ_IXP2000_PCI;
+       }
+
+       printk(KERN_INFO "Assigned IRQ %d to PCI:%d:%d:%d\n", irq,
+               dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+
+       return irq;
+}
+
+struct hw_pci enp2611_pci __initdata = {
+       .nr_controllers = 1,
+       .setup          = enp2611_pci_setup,
+       .preinit        = enp2611_pci_preinit,
+       .scan           = enp2611_pci_scan_bus,
+       .map_irq        = enp2611_pci_map_irq,
+};
+
+int __init enp2611_pci_init(void)
+{
+       pci_common_init(&enp2611_pci);
+       return 0;
+}
+
+subsys_initcall(enp2611_pci_init);
+
+
+/*************************************************************************
+ * ENP-2611 Machine Intialization
+ *************************************************************************/
+static struct flash_platform_data enp2611_flash_platform_data = {
+       .map_name       = "cfi_probe",
+       .width          = 1,
+};
+
+static struct ixp2000_flash_data enp2611_flash_data = {
+       .platform_data  = &enp2611_flash_platform_data,
+       .nr_banks       = 1
+};
+
+static struct resource enp2611_flash_resource = {
+       .start          = 0xc4000000,
+       .end            = 0xc4000000 + 0x00ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device enp2611_flash = {
+       .name           = "IXP2000-Flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &enp2611_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &enp2611_flash_resource,
+};
+
+static struct platform_device *enp2611_devices[] __initdata = {
+       &enp2611_flash
+};
+
+static void __init enp2611_init_machine(void)
+{
+       platform_add_devices(enp2611_devices, ARRAY_SIZE(enp2611_devices));
+}
+
+
+#ifdef CONFIG_ARCH_ENP2611
+MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
+       MAINTAINER("Lennert Buytenhek <buytenh@wantstofly.org>")
+       BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+       BOOT_PARAMS(0x00000100)
+       MAPIO(ixp2000_map_io)
+       INITIRQ(ixp2000_init_irq)
+       INITTIME(enp2611_init_time)
+       INIT_MACHINE(enp2611_init_machine)
+MACHINE_END
+#endif
+
+
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
new file mode 100644 (file)
index 0000000..39ef558
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2400.c
+ *
+ * IXDP2400 platform support
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * IXDP2400 timer tick
+ *************************************************************************/
+static void __init ixdp2400_init_time(void)
+{
+       int numerator, denominator;
+       int denom_array[] = {2, 4, 8, 16, 1, 2, 4, 8};
+
+       numerator = (*(IXDP2400_CPLD_SYS_CLK_M) & 0xFF) *2;
+       denominator = denom_array[(*(IXDP2400_CPLD_SYS_CLK_N) & 0x7)];
+
+       ixp2000_init_time(((3125000 * numerator) / (denominator)) / 2);
+}
+
+/*************************************************************************
+ * IXDP2400 PCI
+ *************************************************************************/
+void __init ixdp2400_pci_preinit(void)
+{
+       ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
+       ixp2000_pci_preinit();
+}
+
+int ixdp2400_pci_setup(int nr, struct pci_sys_data *sys)
+{
+       sys->mem_offset = 0xe0000000;
+
+       ixp2000_pci_setup(nr, sys);
+
+       return 1;
+}
+
+static int __init ixdp2400_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (ixdp2x00_master_npu()) {
+
+               /*
+                * Root bus devices.  Slave NPU is only one with interrupt.
+                * Everything else, we just return -1 b/c nothing else
+                * on the root bus has interrupts.
+                */
+               if(!dev->bus->self) {
+                       if(dev->devfn == IXDP2X00_SLAVE_NPU_DEVFN )
+                               return IRQ_IXDP2400_INGRESS_NPU;
+
+                       return -1;
+               }
+
+               /*
+                * Bridge behind the PMC slot.
+                * NOTE: Only INTA from the PMC slot is routed. VERY BAD.
+                */
+               if(dev->bus->self->devfn == IXDP2X00_PMC_DEVFN &&
+                       dev->bus->parent->self->devfn == IXDP2X00_P2P_DEVFN &&
+                       !dev->bus->parent->self->bus->parent)
+                                 return IRQ_IXDP2400_PMC;
+
+               /*
+                * Device behind the first bridge
+                */
+               if(dev->bus->self->devfn == IXDP2X00_P2P_DEVFN) {
+                       switch(dev->devfn) {
+                               case IXDP2400_MASTER_ENET_DEVFN:        
+                                       return IRQ_IXDP2400_ENET;       
+                       
+                               case IXDP2400_MEDIA_DEVFN:
+                                       return IRQ_IXDP2400_MEDIA_PCI;
+
+                               case IXDP2400_SWITCH_FABRIC_DEVFN:
+                                       return IRQ_IXDP2400_SF_PCI;
+
+                               case IXDP2X00_PMC_DEVFN:
+                                       return IRQ_IXDP2400_PMC;
+                       }
+               }
+
+               return -1;
+       } else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
+}
+
+
+static void ixdp2400_pci_postinit(void)
+{
+       struct pci_dev *dev;
+
+       if (ixdp2x00_master_npu()) {
+               dev = pci_find_slot(1, IXDP2400_SLAVE_ENET_DEVFN);
+               pci_remove_bus_device(dev);
+       } else {
+               dev = pci_find_slot(1, IXDP2400_MASTER_ENET_DEVFN);
+               pci_remove_bus_device(dev);
+
+               ixdp2x00_slave_pci_postinit();
+       }
+}
+
+static struct hw_pci ixdp2400_pci __initdata = {
+       .nr_controllers = 1,
+       .setup          = ixdp2400_pci_setup,
+       .preinit        = ixdp2400_pci_preinit,
+       .postinit       = ixdp2400_pci_postinit,
+       .scan           = ixp2000_pci_scan_bus,
+       .map_irq        = ixdp2400_pci_map_irq,
+};
+
+int __init ixdp2400_pci_init(void)
+{
+       if (machine_is_ixdp2400())
+               pci_common_init(&ixdp2400_pci);
+
+       return 0;
+}
+
+subsys_initcall(ixdp2400_pci_init);
+
+void ixdp2400_init_irq(void)
+{
+       ixdp2x00_init_irq(IXDP2400_CPLD_INT_STAT, IXDP2400_CPLD_INT_MASK, IXDP2400_NR_IRQS);
+}
+
+MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
+       MAINTAINER("MontaVista Software, Inc.")
+       BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+       BOOT_PARAMS(0x00000100)
+       MAPIO(ixdp2x00_map_io)
+       INITIRQ(ixdp2400_init_irq)
+       INITTIME(ixdp2400_init_time)
+       INIT_MACHINE(ixdp2x00_init_machine)
+MACHINE_END
+
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
new file mode 100644 (file)
index 0000000..285eaf0
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2800.c
+ *
+ * IXDP2800 platform support
+ *
+ * Original Author: Jeffrey Daly <jeffrey.daly@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/arch.h>
+
+
+void ixdp2400_init_irq(void)
+{
+       ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2400_NR_IRQS);
+}
+
+/*************************************************************************
+ * IXDP2800 timer tick
+ *************************************************************************/
+
+static void __init ixdp2800_init_time(void)
+{
+       ixp2000_init_time(50000000);
+}
+
+/*************************************************************************
+ * IXDP2800 PCI
+ *************************************************************************/
+void __init ixdp2800_pci_preinit(void)
+{
+       printk("ixdp2x00_pci_preinit called\n");
+
+       *IXP2000_PCI_ADDR_EXT =  0x0000e000;
+
+       *IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff;
+       *IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff;
+
+       ixp2000_pci_preinit();
+}
+
+int ixdp2800_pci_setup(int nr, struct pci_sys_data *sys)
+{
+       sys->mem_offset = 0x00000000;
+
+       ixp2000_pci_setup(nr, sys);
+
+       return 1;
+}
+
+static int __init ixdp2800_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (ixdp2x00_master_npu()) {
+
+               /*
+                * Root bus devices.  Slave NPU is only one with interrupt.
+                * Everything else, we just return -1 which is invalid.
+                */
+               if(!dev->bus->self) {
+                       if(dev->devfn == IXDP2X00_SLAVE_NPU_DEVFN )
+                               return IRQ_IXDP2800_INGRESS_NPU;
+
+                       return -1;
+               }
+
+               /*
+                * Bridge behind the PMC slot.
+                */
+               if(dev->bus->self->devfn == IXDP2X00_PMC_DEVFN &&
+                       dev->bus->parent->self->devfn == IXDP2X00_P2P_DEVFN &&
+                       !dev->bus->parent->self->bus->parent)
+                                 return IRQ_IXDP2800_PMC;
+
+               /*
+                * Device behind the first bridge
+                */
+               if(dev->bus->self->devfn == IXDP2X00_P2P_DEVFN) {
+                       switch(PCI_SLOT(dev->devfn)) {
+                               case IXDP2X00_PMC_DEVFN:
+                                       return IRQ_IXDP2800_PMC;        
+                       
+                               case IXDP2800_MASTER_ENET_DEVFN:
+                                       return IRQ_IXDP2800_EGRESS_ENET;
+
+                               case IXDP2800_SWITCH_FABRIC_DEVFN:
+                                       return IRQ_IXDP2800_FABRIC;
+                       }
+               }
+
+               return -1;
+       } else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
+}
+
+static void ixdp2800_pci_postinit(void)
+{
+       struct pci_dev *dev;
+
+       if (ixdp2x00_master_npu()) {
+               dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
+               pci_remove_bus_device(dev);
+       } else {
+               dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN);
+               pci_remove_bus_device(dev);
+
+               ixdp2x00_slave_pci_postinit();
+       }
+}
+
+struct hw_pci ixdp2800_pci __initdata = {
+       .nr_controllers = 1,
+       .setup          = ixdp2800_pci_setup,
+       .preinit        = ixdp2800_pci_preinit,
+       .postinit       = ixdp2800_pci_postinit,
+       .scan           = ixp2000_pci_scan_bus,
+       .map_irq        = ixdp2800_pci_map_irq,
+};
+
+int __init ixdp2800_pci_init(void)
+{
+       if (machine_is_ixdp2800())
+               pci_common_init(&ixdp2800_pci);
+
+       return 0;
+}
+
+subsys_initcall(ixdp2800_pci_init);
+
+void ixdp2800_init_irq(void)
+{
+       ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2800_NR_IRQS);
+}
+
+MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
+       MAINTAINER("MontaVista Software, Inc.")
+       BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+       BOOT_PARAMS(0x00000100)
+       MAPIO(ixdp2x00_map_io)
+       INITIRQ(ixdp2800_init_irq)
+       INITTIME(ixdp2800_init_time)
+       INIT_MACHINE(ixdp2x00_init_machine)
+MACHINE_END
+
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
new file mode 100644 (file)
index 0000000..cda60b7
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2x00.c
+ *
+ * Code common to IXDP2400 and IXDP2800 platforms.
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * IXDP2x00 IRQ Initialization
+ *************************************************************************/
+static volatile unsigned long *board_irq_mask;
+static volatile unsigned long *board_irq_stat;
+static unsigned long board_irq_count;
+
+#ifdef CONFIG_ARCH_IXDP2400
+/*
+ * Slowport configuration for accessing CPLD registers on IXDP2x00
+ */
+static struct slowport_cfg slowport_cpld_cfg = {
+       .CCR =  SLOWPORT_CCR_DIV_2,
+       .WTC = 0x00000070,
+       .RTC = 0x00000070,
+       .PCR = SLOWPORT_MODE_FLASH,
+       .ADC = SLOWPORT_ADDR_WIDTH_24 | SLOWPORT_DATA_WIDTH_8
+};
+#endif
+
+static void ixdp2x00_irq_mask(unsigned int irq)
+{
+       unsigned long dummy;
+       static struct slowport_cfg old_cfg;
+
+       /*
+        * This is ugly in common code but really don't know
+        * of a better way to handle it. :(
+        */
+#ifdef CONFIG_ARCH_IXDP2400
+       if (machine_is_ixdp2400())
+               ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
+#endif
+
+       dummy = *board_irq_mask;
+       dummy |=  IXP2000_BOARD_IRQ_MASK(irq);
+       ixp2000_reg_write(board_irq_mask, dummy);
+
+#ifdef CONFIG_ARCH_IXDP2400
+       if (machine_is_ixdp2400())
+               ixp2000_release_slowport(&old_cfg);
+#endif
+}
+
+static void ixdp2x00_irq_unmask(unsigned int irq)
+{
+       unsigned long dummy;
+       static struct slowport_cfg old_cfg;
+
+#ifdef CONFGI_ARCH_IXDP2400
+       if (machine_is_ixdp2400())
+               ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
+#endif
+
+       dummy = *board_irq_mask;
+       dummy &=  ~IXP2000_BOARD_IRQ_MASK(irq);
+       ixp2000_reg_write(board_irq_mask, dummy);
+
+       if (machine_is_ixdp2400()) 
+               ixp2000_release_slowport(&old_cfg);
+}
+
+static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+        volatile u32 ex_interrupt = 0;
+       static struct slowport_cfg old_cfg;
+       int i;
+
+       desc->chip->mask(irq);
+
+#ifdef CONFIG_ARCH_IXDP2400
+       if (machine_is_ixdp2400())
+               ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
+#endif
+        ex_interrupt = *board_irq_stat & 0xff;
+       if (machine_is_ixdp2400())
+               ixp2000_release_slowport(&old_cfg);
+
+       if(!ex_interrupt) {
+               printk(KERN_ERR "Spurious IXDP2x00 CPLD interrupt!\n");
+               return;
+       }
+
+       for(i = 0; i < board_irq_count; i++) {
+               if(ex_interrupt & (1 << i))  {
+                       struct irqdesc *cpld_desc;
+                       int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
+                       cpld_desc = irq_desc + cpld_irq;
+                       cpld_desc->handle(cpld_irq, cpld_desc, regs);
+               }
+       }
+
+       desc->chip->unmask(irq);
+}
+
+static struct irqchip ixdp2x00_cpld_irq_chip = {
+       .ack    = ixdp2x00_irq_mask,
+       .mask   = ixdp2x00_irq_mask,
+       .unmask = ixdp2x00_irq_unmask
+};
+
+void ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_irqs)
+{
+       unsigned int irq;
+
+       ixp2000_init_irq();
+       
+       if (!ixdp2x00_master_npu())
+               return;
+
+       board_irq_stat = stat_reg;
+       board_irq_mask = mask_reg;
+       board_irq_count = nr_irqs;
+
+       *board_irq_mask = 0xffffffff;
+
+       for(irq = IXP2000_BOARD_IRQ(0); irq < IXP2000_BOARD_IRQ(board_irq_count); irq++) {
+               set_irq_chip(irq, &ixdp2x00_cpld_irq_chip);
+               set_irq_handler(irq, do_level_IRQ);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+
+       /* Hook into PCI interrupt */
+       set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x00_irq_handler);
+}
+
+/*************************************************************************
+ * IXDP2x00 memory map
+ *************************************************************************/
+static struct map_desc ixdp2x00_io_desc __initdata = {
+       .virtual        = IXDP2X00_VIRT_CPLD_BASE, 
+       .physical       = IXDP2X00_PHYS_CPLD_BASE,
+       .length         = IXDP2X00_CPLD_SIZE,
+       .type           = MT_DEVICE
+};
+
+void __init ixdp2x00_map_io(void)
+{
+       ixp2000_map_io();       
+
+       iotable_init(&ixdp2x00_io_desc, 1);
+}
+
+/*************************************************************************
+ * IXDP2x00-common PCI init
+ *
+ * The IXDP2[48]00 has a horrid PCI bus layout. Basically the board 
+ * contains two NPUs (ingress and egress) connected over PCI,  both running 
+ * instances  of the kernel. So far so good. Peers on the PCI bus running 
+ * Linux is a common design in telecom systems. The problem is that instead 
+ * of all the devices being controlled by a single host, different
+ * devices are controlles by different NPUs on the same bus, leading to
+ * multiple hosts on the bus.i The exact bus layout looks like:
+ *
+ *                   Bus 0
+ *    Master NPU <-------------------+-------------------> Slave NPU
+ *                                   |
+ *                                   |
+ *                                  P2P 
+ *                                   |
+ *
+ *                  Bus 1            |
+ *               <--+------+---------+---------+------+-->
+ *                  |      |         |         |      |
+ *                  |      |         |         |      |
+ *             ... Dev    PMC       Media     Eth0   Eth1 ...
+ *
+ * The master controlls all but Eth1, which is controlled by the
+ * slave. What this measn is that the both the master and the slave
+ * have to scan the bus, but only one of them can enumerate the bus.
+ * In addition, after the bus is scaned, each kernel must remove
+ * the device(s) it does not control from the PCI dev list otherwise
+ * a driver on each NPU will try to manage it and we will have horrible
+ * conflicts. Oh..and the slave NPU needs to see the master NPU
+ * for Intel's drivers to work properly. Closed source drivers...
+ *
+ * The way we deal with this is fairly simple but ugly:
+ *
+ * 1) Let master scan and enumerate the bus completely.
+ * 2) Master deletes Eth1 from device list.
+ * 3) Slave scans bus and then deletes all but Eth1 (Eth0 on slave)
+ *    from device list.
+ * 4) Find HW designers and LART them.
+ *
+ * The boards also do not do normal PCI IRQ routing, or any sort of 
+ * sensical  swizzling, so we just need to check where on the  bus a
+ * device sits and figure out to which CPLD pin the interrupt is routed.
+ * See ixdp2[48]00.c files.
+ *
+ *************************************************************************/
+void ixdp2x00_slave_pci_postinit(void)
+{
+       struct pci_dev *dev;
+
+       /*
+        * Remove PMC device is there is one
+        */
+       if((dev = pci_find_slot(1, IXDP2X00_PMC_DEVFN)))
+               pci_remove_bus_device(dev);
+
+       dev = pci_find_slot(0, IXDP2X00_21555_DEVFN);
+       pci_remove_bus_device(dev);
+}
+
+/**************************************************************************
+ * IXDP2x00 Machine Setup
+ *************************************************************************/
+static struct flash_platform_data ixdp2x00_platform_data = {
+       .map_name       = "cfi_probe",
+       .width          = 1,
+};
+
+static struct ixp2000_flash_data ixdp2x00_flash_data = {
+       .platform_data  = &ixdp2x00_platform_data,
+       .nr_banks       = 1
+};
+
+static struct resource ixdp2x00_flash_resource = {
+       .start          = 0xc4000000,
+       .end            = 0xc4000000 + 0x00ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp2x00_flash = {
+       .name           = "IXP2000-Flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &ixdp2x00_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &ixdp2x00_flash_resource,
+};
+
+static struct ixp2000_i2c_pins ixdp2x00_i2c_gpio_pins = {
+       .sda_pin        = IXDP2X00_GPIO_SDA,
+       .scl_pin        = IXDP2X00_GPIO_SCL,
+};
+
+static struct platform_device ixdp2x00_i2c_controller = {
+       .name           = "IXP2000-I2C",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &ixdp2x00_i2c_gpio_pins,
+       },
+       .num_resources  = 0
+};
+
+static struct platform_device *ixdp2x00_devices[] __initdata = {
+       &ixdp2x00_flash,
+       &ixdp2x00_i2c_controller
+};
+
+void __init ixdp2x00_init_machine(void)
+{
+       gpio_line_set(IXDP2X00_GPIO_I2C_ENABLE, 1);
+       gpio_line_config(IXDP2X00_GPIO_I2C_ENABLE, GPIO_OUT);
+
+       platform_add_devices(ixdp2x00_devices, ARRAY_SIZE(ixdp2x00_devices));
+}
+
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
new file mode 100644 (file)
index 0000000..176114a
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2x01.c
+ *
+ * Code common to Intel IXDP2401 and IXDP2801 platforms
+ *
+ * Original Author: Andrzej Mialwoski <andrzej.mialwoski@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002-2003 Intel Corp.
+ * Copyright (C) 2003-2004 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+/*************************************************************************
+ * IXDP2x01 IRQ Handling
+ *************************************************************************/
+static void ixdp2x01_irq_mask(unsigned int irq)
+{
+       *IXDP2X01_INT_MASK_SET_REG = IXP2000_BOARD_IRQ_MASK(irq);
+}
+
+static void ixdp2x01_irq_unmask(unsigned int irq)
+{
+       *IXDP2X01_INT_MASK_CLR_REG = IXP2000_BOARD_IRQ_MASK(irq);
+}
+
+static u32 valid_irq_mask;
+
+static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+       u32 ex_interrupt;
+       int i;
+
+       desc->chip->mask(irq);
+
+       ex_interrupt = *IXDP2X01_INT_STAT_REG & valid_irq_mask;
+
+       if (!ex_interrupt) {
+               printk(KERN_ERR "Spurious IXDP2X01 CPLD interrupt!\n");
+               return;
+       }
+
+       for (i = 0; i < IXP2000_BOARD_IRQS; i++) {
+               if (ex_interrupt & (1 << i)) {
+                       struct irqdesc *cpld_desc;
+                       int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
+                       cpld_desc = irq_desc + cpld_irq;
+                       cpld_desc->handle(cpld_irq, cpld_desc, regs);
+               }
+       }
+
+       desc->chip->unmask(irq);
+}
+
+static struct irqchip ixdp2x01_irq_chip = {
+       .mask   = ixdp2x01_irq_mask,
+       .ack    = ixdp2x01_irq_mask,
+       .unmask = ixdp2x01_irq_unmask
+};
+
+/*
+ * We only do anything if we are the master NPU on the board.
+ * The slave NPU only has the ethernet chip going directly to
+ * the PCIB interrupt input.
+ */
+void __init ixdp2x01_init_irq(void)
+{
+       int irq = 0;
+
+       /* initialize chip specific interrupts */
+       ixp2000_init_irq();
+
+       if (machine_is_ixdp2401())
+               valid_irq_mask = IXDP2401_VALID_IRQ_MASK;
+       else
+               valid_irq_mask = IXDP2801_VALID_IRQ_MASK;
+
+       /* Mask all interrupts from CPLD, disable simulation */
+       *IXDP2X01_INT_MASK_SET_REG = 0xffffffff;
+       *IXDP2X01_INT_SIM_REG = 0;
+
+       for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) {
+               if (irq & valid_irq_mask) {
+                       set_irq_chip(irq, &ixdp2x01_irq_chip);
+                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_flags(irq, IRQF_VALID);
+               } else {
+                       set_irq_flags(irq, 0);
+               }
+       }
+
+       /* Hook into PCI interrupts */
+       set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x01_irq_handler);
+}
+
+
+/*************************************************************************
+ * IXDP2x01 memory map and serial ports
+ *************************************************************************/
+static struct map_desc ixdp2x01_io_desc __initdata = {
+       .virtual        = IXDP2X01_VIRT_CPLD_BASE, 
+       .physical       = IXDP2X01_PHYS_CPLD_BASE,
+       .length         = IXDP2X01_CPLD_REGION_SIZE,
+       .type           = MT_DEVICE
+};
+
+static struct uart_port ixdp2x01_serial_ports[2] = {
+       {
+               .membase        = (char *)(IXDP2X01_UART1_VIRT_BASE),
+               .mapbase        = (unsigned long)IXDP2X01_UART1_PHYS_BASE,
+               .irq            = IRQ_IXDP2X01_UART1,
+               .flags          = UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM32,
+               .regshift       = 2,
+               .uartclk        = IXDP2X01_UART_CLK,
+               .line           = 1,
+               .type           = PORT_16550A,
+               .fifosize       = 16
+       }, {
+               .membase        = (char *)(IXDP2X01_UART2_VIRT_BASE),
+               .mapbase        = (unsigned long)IXDP2X01_UART2_PHYS_BASE,
+               .irq            = IRQ_IXDP2X01_UART2,
+               .flags          = UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM32,
+               .regshift       = 2,
+               .uartclk        = IXDP2X01_UART_CLK,
+               .line           = 2,
+               .type           = PORT_16550A,
+               .fifosize       = 16
+       }, 
+};
+
+static void __init ixdp2x01_map_io(void)
+{
+       ixp2000_map_io();       
+
+       iotable_init(&ixdp2x01_io_desc, 1);
+
+       early_serial_setup(&ixdp2x01_serial_ports[0]);
+       early_serial_setup(&ixdp2x01_serial_ports[1]);
+}
+
+
+/*************************************************************************
+ * IXDP2x01 timer tick configuration
+ *************************************************************************/
+static unsigned int ixdp2x01_clock;
+
+static int __init ixdp2x01_clock_setup(char *str)
+{
+       ixdp2x01_clock = simple_strtoul(str, NULL, 10);
+
+       return 1;
+}
+
+__setup("ixdp2x01_clock=", ixdp2x01_clock_setup);
+
+static void __init ixdp2x01_init_time(void)
+{
+       if (!ixdp2x01_clock)
+               ixdp2x01_clock = 50000000;
+
+       ixp2000_init_time(ixdp2x01_clock);
+}
+
+/*************************************************************************
+ * IXDP2x01 PCI
+ *************************************************************************/
+void __init ixdp2x01_pci_preinit(void)
+{
+       ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00000000);
+       ixp2000_pci_preinit();
+}
+
+#define DEVPIN(dev, pin) ((pin) | ((dev) << 3))
+
+static int __init ixdp2x01_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       u8 bus = dev->bus->number;
+       u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin);
+       struct pci_bus *tmp_bus = dev->bus;
+
+       /* Primary bus, no interrupts here */
+       if (bus == 0) {
+               return -1;
+       }
+
+       /* Lookup first leaf in bus tree */
+       while ((tmp_bus->parent != NULL) && (tmp_bus->parent->parent != NULL)) {
+               tmp_bus = tmp_bus->parent;
+       }
+
+       /* Select between known bridges */
+       switch (tmp_bus->self->devfn | (tmp_bus->self->bus->number << 8)) {
+       /* Device is located after first MB bridge */
+       case 0x0008:
+               if (tmp_bus == dev->bus) {
+                       /* Device is located directy after first MB bridge */
+                       switch (devpin) {
+                       case DEVPIN(1, 1):      /* Onboard 82546 ch 0 */
+                               if (machine_is_ixdp2401())
+                                       return IRQ_IXDP2401_INTA_82546;
+                               return -1;
+                       case DEVPIN(1, 2):      /* Onboard 82546 ch 1 */
+                               if (machine_is_ixdp2401())
+                                       return IRQ_IXDP2401_INTB_82546;
+                               return -1;
+                       case DEVPIN(0, 1):      /* PMC INTA# */
+                               return IRQ_IXDP2X01_SPCI_PMC_INTA;
+                       case DEVPIN(0, 2):      /* PMC INTB# */
+                               return IRQ_IXDP2X01_SPCI_PMC_INTB;
+                       case DEVPIN(0, 3):      /* PMC INTC# */
+                               return IRQ_IXDP2X01_SPCI_PMC_INTC;
+                       case DEVPIN(0, 4):      /* PMC INTD# */
+                               return IRQ_IXDP2X01_SPCI_PMC_INTD;
+                       }
+               }
+               break;
+       case 0x0010:
+               if (tmp_bus == dev->bus) {
+                       /* Device is located directy after second MB bridge */
+                       /* Secondary bus of second bridge */
+                       switch (devpin) {
+                       case DEVPIN(0, 1):      /* DB#0 */
+                               return IRQ_IXDP2X01_SPCI_DB_0;
+                       case DEVPIN(1, 1):      /* DB#1 */
+                               return IRQ_IXDP2X01_SPCI_DB_1;
+                       }
+               } else {
+                       /* Device is located indirectly after second MB bridge */
+                       /* Not supported now */
+               }
+               break;
+       }
+
+       return -1;
+}
+
+
+static int ixdp2x01_pci_setup(int nr, struct pci_sys_data *sys)
+{
+       sys->mem_offset = 0xe0000000;
+
+       if (machine_is_ixdp2801())
+               sys->mem_offset -= ((*IXP2000_PCI_ADDR_EXT & 0xE000) << 16);
+
+       return ixp2000_pci_setup(nr, sys);
+}
+
+struct hw_pci ixdp2x01_pci __initdata = {
+       .nr_controllers = 1,
+       .setup          = ixdp2x01_pci_setup,
+       .preinit        = ixdp2x01_pci_preinit,
+       .scan           = ixp2000_pci_scan_bus,
+       .map_irq        = ixdp2x01_pci_map_irq,
+};
+
+int __init ixdp2x01_pci_init(void)
+{
+
+       pci_common_init(&ixdp2x01_pci);
+       return 0;
+}
+
+subsys_initcall(ixdp2x01_pci_init);
+
+/*************************************************************************
+ * IXDP2x01 Machine Intialization
+ *************************************************************************/
+static struct flash_platform_data ixdp2x01_flash_platform_data = {
+       .map_name       = "cfi_probe",
+       .width          = 1,
+};
+
+static unsigned long ixdp2x01_flash_bank_setup(unsigned long ofs)
+{
+       *IXDP2X01_CPLD_FLASH_REG = 
+               ((ofs >> IXDP2X01_FLASH_WINDOW_BITS) | IXDP2X01_CPLD_FLASH_INTERN);
+       return (ofs & IXDP2X01_FLASH_WINDOW_MASK);
+}
+
+static struct ixp2000_flash_data ixdp2x01_flash_data = {
+       .platform_data  = &ixdp2x01_flash_platform_data,
+       .bank_setup     = ixdp2x01_flash_bank_setup
+};
+
+static struct resource ixdp2x01_flash_resource = {
+       .start          = 0xc4000000,
+       .end            = 0xc4000000 + 0x01ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp2x01_flash = {
+       .name           = "IXP2000-Flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &ixdp2x01_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &ixdp2x01_flash_resource,
+};
+
+static struct platform_device *ixdp2x01_devices[] __initdata = {
+       &ixdp2x01_flash
+};
+
+static void __init ixdp2x01_init_machine(void)
+{
+       *IXDP2X01_CPLD_FLASH_REG = 
+               (IXDP2X01_CPLD_FLASH_BANK_MASK | IXDP2X01_CPLD_FLASH_INTERN);
+       
+       ixdp2x01_flash_data.nr_banks =
+               ((*IXDP2X01_CPLD_FLASH_REG & IXDP2X01_CPLD_FLASH_BANK_MASK) + 1);
+
+       platform_add_devices(ixdp2x01_devices, ARRAY_SIZE(ixdp2x01_devices));
+}
+
+
+#ifdef CONFIG_ARCH_IXDP2401
+MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
+       MAINTAINER("MontaVista Software, Inc.")
+       BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+       BOOT_PARAMS(0x00000100)
+       MAPIO(ixdp2x01_map_io)
+       INITIRQ(ixdp2x01_init_irq)
+       INITTIME(ixdp2x01_init_time)
+       INIT_MACHINE(ixdp2x01_init_machine)
+MACHINE_END
+#endif
+
+#ifdef CONFIG_ARCH_IXDP2801
+MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
+       MAINTAINER("MontaVista Software, Inc.")
+       BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+       BOOT_PARAMS(0x00000100)
+       MAPIO(ixdp2x01_map_io)
+       INITIRQ(ixdp2x01_init_irq)
+       INITTIME(ixdp2x01_init_time)
+       INIT_MACHINE(ixdp2x01_init_machine)
+MACHINE_END
+#endif
+
+
diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
new file mode 100644 (file)
index 0000000..d08cebe
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * arch/arm/mach-ixp2000/pci.c
+ *
+ * PCI routines for IXDP2400/IXDP2800 boards
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintained by: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+static int pci_master_aborts = 0;
+
+static int clear_master_aborts(void);
+
+static u32 *
+ixp2000_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
+{
+       u32 *paddress;
+
+       if (PCI_SLOT(devfn) > 7)
+               return 0;
+
+       /* Must be dword aligned */
+       where &= ~3;
+
+       /*
+        * For top bus, generate type 0, else type 1
+        */
+       if (!bus_nr) {
+               /* only bits[23:16] are used for IDSEL */
+               paddress = (u32 *) (IXP2000_PCI_CFG0_VIRT_BASE
+                                   | (1 << (PCI_SLOT(devfn) + 16))
+                                   | (PCI_FUNC(devfn) << 8) | where);
+       } else {
+               paddress = (u32 *) (IXP2000_PCI_CFG1_VIRT_BASE 
+                                   | (bus_nr << 16)
+                                   | (PCI_SLOT(devfn) << 11)
+                                   | (PCI_FUNC(devfn) << 8) | where);
+       }
+
+       return paddress;
+}
+
+/*
+ * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes.
+ * 0 and 3 are not valid indexes...
+ */
+static u32 bytemask[] = {
+       /*0*/   0,
+       /*1*/   0xff,
+       /*2*/   0xffff,
+       /*3*/   0,
+       /*4*/   0xffffffff,
+};
+
+
+int ixp2000_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+                               int size, u32 *value)
+{
+       u32 n;
+       u32 *addr;
+
+       n = where % 4;
+
+       addr = ixp2000_pci_config_addr(bus->number, devfn, where);
+       if (!addr)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       pci_master_aborts = 0;
+       *value = (*addr >> (8*n)) & bytemask[size];
+       if (pci_master_aborts) {
+               pci_master_aborts = 0;
+               *value = 0xffffffff;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * We don't do error checks by callling clear_master_aborts() b/c the
+ * assumption is that the caller did a read first to make sure a device
+ * exists.
+ */
+int ixp2000_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+                               int size, u32 value)
+{
+       u32 mask;
+       u32 *addr;
+       u32 temp;
+
+       mask = ~(bytemask[size] << ((where % 0x4) * 8));
+       addr = ixp2000_pci_config_addr(bus->number, devfn, where);
+       if (!addr)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       temp = (u32) (value) << ((where % 0x4) * 8);
+       *addr = (*addr & mask) | temp;
+
+       clear_master_aborts();
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+
+static struct pci_ops ixp2000_pci_ops = {
+       .read   = ixp2000_pci_read_config,
+       .write  = ixp2000_pci_write_config
+};
+
+struct pci_bus *ixp2000_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
+{
+       return pci_scan_bus(sysdata->busnr, &ixp2000_pci_ops, sysdata);
+}
+
+
+int ixp2000_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+
+       volatile u32 temp;
+
+       pci_master_aborts = 1;
+
+       cli();
+       temp = *(IXP2000_PCI_CONTROL);
+       if (temp & ((1 << 8) | (1 << 5))) {
+               *(IXP2000_PCI_CONTROL) = temp;
+       }
+
+       temp = *(IXP2000_PCI_CMDSTAT);
+       if (temp & (1 << 29)) {
+               while (temp & (1 << 29)) {      
+                       *(IXP2000_PCI_CMDSTAT) = temp;
+                       temp = *(IXP2000_PCI_CMDSTAT);
+               }
+       }
+       sti();
+
+       /*
+        * If it was an imprecise abort, then we need to correct the
+        * return address to be _after_ the instruction.
+        */
+       if (fsr & (1 << 10))
+               regs->ARM_pc += 4;
+
+       return 0;
+}
+
+int
+clear_master_aborts(void)
+{
+       volatile u32 temp;
+
+       cli();
+       temp = *(IXP2000_PCI_CONTROL);
+       if (temp & ((1 << 8) | (1 << 5))) {     
+               *(IXP2000_PCI_CONTROL) = temp;
+       }
+
+       temp = *(IXP2000_PCI_CMDSTAT);
+       if (temp & (1 << 29)) {
+               while (temp & (1 << 29)) {
+                       *(IXP2000_PCI_CMDSTAT) = temp;
+                       temp = *(IXP2000_PCI_CMDSTAT);
+               }
+       }
+       sti();
+
+       return 0;
+}
+
+void __init
+ixp2000_pci_preinit(void)
+{
+       hook_fault_code(16+6, ixp2000_pci_abort_handler, SIGBUS,
+                               "PCI config cycle to non-existent device");
+}
+
+
+/*
+ * IXP2000 systems often have large resource requirements, so we just
+ * use our own resource space.
+ */
+static struct resource ixp2000_pci_mem_space = {
+       .start  = 0x00000000,
+       .end    = 0xffffffff,
+       .flags  = IORESOURCE_MEM,
+       .name   = "PCI Mem Space"
+};
+
+static struct resource ixp2000_pci_io_space = {
+       .start  = 0x00000000,
+       .end    = 0xffffffff,
+       .flags  = IORESOURCE_IO,
+       .name   = "PCI I/O Space"
+};
+
+int ixp2000_pci_setup(int nr, struct pci_sys_data *sys)
+{
+       if (nr >= 1)
+               return 0;
+
+       sys->resource[0] = &ixp2000_pci_io_space;
+       sys->resource[1] = &ixp2000_pci_mem_space;
+       sys->resource[2] = NULL;
+
+       return 1;
+}
+
index a4edbe0..24ffa32 100644 (file)
@@ -207,7 +207,7 @@ void __init ixp4xx_init_irq(void)
 
 static unsigned volatile last_jiffy_time;
 
-#define CLOCK_TICKS_PER_USEC   (CLOCK_TICK_RATE / USEC_PER_SEC)
+#define CLOCK_TICKS_PER_USEC   ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
 
 /* IRQs are disabled before entering here from do_gettimeofday() */
 static unsigned long ixp4xx_gettimeoffset(void)
index 61ada24..f4943ca 100644 (file)
 #include <asm/mach/time.h>
 
 #if HZ < 100
-# define TIMER_CONTROL TIMER_CONTROL1
-# define TIMER_LOAD    TIMER_LOAD1
+# define TIMER_CONTROL TIMER_CONTROL2
+# define TIMER_LOAD    TIMER_LOAD2
 # define TIMER_CONSTANT        (508469/HZ)
 # define TIMER_MODE    (TIMER_C_ENABLE | TIMER_C_PERIODIC | TIMER_C_508KHZ)
-# define TIMER_EOI     TIMER_EOI1
-# define TIMER_IRQ     IRQ_T1UI
+# define TIMER_EOI     TIMER_EOI2
+# define TIMER_IRQ     IRQ_T2UI
 #else
 # define TIMER_CONTROL TIMER_CONTROL3
 # define TIMER_LOAD    TIMER_LOAD3
diff --git a/arch/arm/mach-omap/board-h2.c b/arch/arm/mach-omap/board-h2.c
new file mode 100644 (file)
index 0000000..1441089
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * linux/arch/arm/mach-omap/board-h2.c
+ *
+ * Board specific inits for OMAP-1610 H2
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ *
+ * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
+ * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.com>
+ *
+ * H2 specific changes and cleanup
+ * Copyright (C) 2004 Nokia Corporation by Imre Deak <imre.deak@nokia.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/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/clocks.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/usb.h>
+
+#include "common.h"
+
+extern void __init omap_init_time(void);
+
+static struct map_desc h2_io_desc[] __initdata = {
+{ OMAP1610_ETHR_BASE, OMAP1610_ETHR_START, OMAP1610_ETHR_SIZE,MT_DEVICE },
+{ OMAP1610_NOR_FLASH_BASE, OMAP1610_NOR_FLASH_START, OMAP1610_NOR_FLASH_SIZE,
+       MT_DEVICE },
+};
+
+static struct resource h2_smc91x_resources[] = {
+       [0] = {
+               .start  = OMAP1610_ETHR_START,          /* Physical */
+               .end    = OMAP1610_ETHR_START + SZ_4K,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 0,                            /* Really GPIO 0 */
+               .end    = 0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device h2_smc91x_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(h2_smc91x_resources),
+       .resource       = h2_smc91x_resources,
+};
+
+static struct platform_device *h2_devices[] __initdata = {
+       &h2_smc91x_device,
+};
+
+void h2_init_irq(void)
+{
+       omap_init_irq();
+}
+
+static struct omap_usb_config h2_usb_config __initdata = {
+       /* usb1 has a Mini-AB port and external isp1301 transceiver */
+       .otg            = 2,
+
+#ifdef CONFIG_USB_GADGET_OMAP
+       .hmc_mode       = 19,   // 0:host(off) 1:dev|otg 2:disabled
+       // .hmc_mode    = 21,   // 0:host(off) 1:dev(loopback) 2:host(loopback)
+#elif  defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+       /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
+       .hmc_mode       = 20,   // 1:dev|otg(off) 1:host 2:disabled
+#endif
+
+       .pins[1]        = 3,
+};
+
+static struct omap_board_config_kernel h2_config[] = {
+       { OMAP_TAG_USB,           &h2_usb_config },
+};
+
+static void __init h2_init(void)
+{
+       platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
+       omap_board_config = h2_config;
+       omap_board_config_size = ARRAY_SIZE(h2_config);
+}
+
+static void __init h2_map_io(void)
+{
+       omap_map_io();
+       iotable_init(h2_io_desc, ARRAY_SIZE(h2_io_desc));
+}
+
+MACHINE_START(OMAP_H2, "TI-H2")
+       MAINTAINER("Imre Deak <imre.deak@nokia.com>")
+       BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
+       BOOT_PARAMS(0x10000100)
+       MAPIO(h2_map_io)
+       INITIRQ(h2_init_irq)
+       INIT_MACHINE(h2_init)
+       INITTIME(omap_init_time)
+MACHINE_END
diff --git a/arch/arm/mach-omap/board-h3.c b/arch/arm/mach-omap/board-h3.c
new file mode 100644 (file)
index 0000000..d573b0c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * linux/arch/arm/mach-omap/board-h3.c
+ *
+ * This file contains OMAP1710 H3 specific code.
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ *         Greg Lonnon (glonnon@ridgerun.com) or info@ridgerun.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/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/hardware.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/gpio.h>
+#include <asm/mach-types.h>
+#include "common.h"
+
+extern void __init omap_init_time(void);
+
+void h3_init_irq(void)
+{
+       omap_init_irq();
+}
+
+static struct resource smc91x_resources[] = {
+       [0] = {
+               .start  = OMAP1710_ETHR_START,          /* Physical */
+               .end    = OMAP1710_ETHR_START + OMAP1710_ETHR_SIZE,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 0,
+               .end    = 0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device smc91x_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smc91x_resources),
+       .resource       = smc91x_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+        &smc91x_device,
+};
+
+static void __init h3_init(void)
+{
+       (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static struct map_desc h3_io_desc[] __initdata = {
+{ OMAP1710_ETHR_BASE,  OMAP1710_ETHR_START,  OMAP1710_ETHR_SIZE,  MT_DEVICE },
+{ OMAP_NOR_FLASH_BASE, OMAP_NOR_FLASH_START, OMAP_NOR_FLASH_SIZE, MT_DEVICE },
+};
+
+static void __init h3_map_io(void)
+{
+       omap_map_io();
+       iotable_init(h3_io_desc, ARRAY_SIZE(h3_io_desc));
+}
+
+MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
+       MAINTAINER("Texas Instruments, Inc.")
+       BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
+       BOOT_PARAMS(0x10000100)
+       MAPIO(h3_map_io)
+       INITIRQ(h3_init_irq)
+       INIT_MACHINE(h3_init)
+       INITTIME(omap_init_time)
+MACHINE_END
index bda7c6f..b507856 100644 (file)
@@ -36,6 +36,8 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/board.h>
 
+extern void start_mputimer1(unsigned long load_val);
+
 /* Input clock in MHz */
 static unsigned int source_clock = 12;
 
@@ -239,7 +241,7 @@ int ck_auto_unclock = 1;
 int ck_debug = 0;
 
 #define CK_MAX_PLL_FREQ                OMAP_CK_MAX_RATE
-static __u8 ck_valid_table[CK_MAX_PLL_FREQ / 8 + 1];
+static __u32 ck_valid_table[CK_MAX_PLL_FREQ / 32 + 1];
 static __u8 ck_lookup_table[CK_MAX_PLL_FREQ];
 
 int
@@ -615,11 +617,11 @@ __ck_make_lookup_table(void)
 int __init
 init_ck(void)
 {
-       const struct omap_clock_info *info;
+       const struct omap_clock_config *info;
        int crystal_type = 0; /* Default 12 MHz */
 
        __ck_make_lookup_table();
-       info = omap_get_per_info(OMAP_TAG_CLOCK, struct omap_clock_info);
+       info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
        if (info != NULL) {
                if (!cpu_is_omap1510())
                        crystal_type = info->system_clock_type;
@@ -645,7 +647,8 @@ init_ck(void)
 #elif defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
        omap_writew(0x250E, ARM_CKCTL);
        omap_writew(0x2710, DPLL_CTL);
-#elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912))
+#elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
+                                         || defined(CONFIG_ARCH_OMAP1710))
        omap_writew(0x150f, ARM_CKCTL);
        if (crystal_type == 2) {
                source_clock = 13;      /* MHz */
index 43aaa1c..17d82a7 100644 (file)
@@ -104,7 +104,7 @@ static struct map_desc omap1510_io_desc[] __initdata = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_OMAP1610
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
 static struct map_desc omap1610_io_desc[] __initdata = {
  { OMAP1610_DSP_BASE,    OMAP1610_DSP_START,    OMAP1610_DSP_SIZE,    MT_DEVICE },
  { OMAP1610_DSPREG_BASE, OMAP1610_DSPREG_START, OMAP1610_DSPREG_SIZE, MT_DEVICE },
@@ -147,8 +147,8 @@ static void __init _omap_map_io(void)
                iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
        }
 #endif
-#ifdef CONFIG_ARCH_OMAP1610
-       if (cpu_is_omap1610()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+       if (cpu_is_omap1610() || cpu_is_omap1710()) {
                iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
        }
 #endif
@@ -181,13 +181,18 @@ void omap_map_io(void)
 extern int omap_bootloader_tag_len;
 extern u8 omap_bootloader_tag[];
 
-const void *__omap_get_per_info(u16 tag, size_t len)
+struct omap_board_config_kernel *omap_board_config;
+int omap_board_config_size = 0;
+
+const void *__omap_get_config(u16 tag, size_t len)
 {
-       struct omap_board_info_entry *info = NULL;
+       struct omap_board_config_entry *info = NULL;
+       struct omap_board_config_kernel *kinfo = NULL;
+       int i;
 
 #ifdef CONFIG_OMAP_BOOT_TAG
        if (omap_bootloader_tag_len > 4)
-               info = (struct omap_board_info_entry *) omap_bootloader_tag;
+               info = (struct omap_board_config_entry *) omap_bootloader_tag;
        while (info != NULL) {
                u8 *next;
 
@@ -198,26 +203,38 @@ const void *__omap_get_per_info(u16 tag, size_t len)
                if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
                        info = NULL;
                else
-                       info = (struct omap_board_info_entry *) next;
+                       info = (struct omap_board_config_entry *) next;
+       }
+       if (info != NULL) {
+               /* Check the length as a lame attempt to check for
+                * binary inconsistancy. */
+               if (info->len != len) {
+                       printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
+                              tag, len, info->len);
+                       return NULL;
+               }
+               return info->data;
        }
 #endif
-       if (info == NULL)
-               return NULL;
-       if (info->len != len) {
-               printk(KERN_ERR "OMAP per_info: Length mismatch with tag %x (want %d, got %d)\n",
-                      tag, len, info->len);
-               return NULL;
+       /* Try to find the config from the board-specific structures
+        * in the kernel. */
+       for (i = 0; i < omap_board_config_size; i++) {
+               if (omap_board_config[i].tag == tag) {
+                       kinfo = &omap_board_config[i];
+                       break;
+               }
        }
-
-       return info->data;
+       if (kinfo == NULL)
+               return NULL;
+       return kinfo->data;
 }
-EXPORT_SYMBOL(__omap_get_per_info);
+EXPORT_SYMBOL(__omap_get_config);
 
 static int __init omap_add_serial_console(void)
 {
-       const struct omap_uart_info *info;
+       const struct omap_uart_config *info;
 
-       info = omap_get_per_info(OMAP_TAG_UART, struct omap_uart_info);
+       info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
        if (info != NULL && info->console_uart) {
                static char speed[11], *opt = NULL;
 
index d9246b1..f0ce5c1 100644 (file)
 #include <asm/arch/fpga.h>
 #include <asm/arch/gpio.h>
 
-unsigned char fpga_read(int reg)
-{
-       return __raw_readb(reg);
-}
-
-void fpga_write(unsigned char val, int reg)
-{
-       __raw_writeb(val, reg);
-}
-
 static void fpga_mask_irq(unsigned int irq)
 {
-       irq -= IH_FPGA_BASE;
+       irq -= OMAP1510_IH_FPGA_BASE;
 
        if (irq < 8)
                __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO)
@@ -76,7 +66,7 @@ static void fpga_ack_irq(unsigned int irq)
 
 static void fpga_unmask_irq(unsigned int irq)
 {
-       irq -= IH_FPGA_BASE;
+       irq -= OMAP1510_IH_FPGA_BASE;
 
        if (irq < 8)
                __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO) | (1 << irq)),
@@ -114,8 +104,8 @@ void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc,
                        break;
                }
 
-               for (fpga_irq = IH_FPGA_BASE;
-                       (fpga_irq < (IH_FPGA_BASE + NR_FPGA_IRQS)) && stat;
+               for (fpga_irq = OMAP1510_IH_FPGA_BASE;
+                       (fpga_irq < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS)) && stat;
                        fpga_irq++, stat >>= 1) {
                        if (stat & 1) {
                                d = irq_desc + fpga_irq;
@@ -162,7 +152,7 @@ static struct irqchip omap_fpga_irq = {
  * interrupts at the interrupt controller via disable_irq/enable_irq
  * could pose a problem.
  */
-void fpga_init_irq(void)
+void omap1510_fpga_init_irq(void)
 {
        int i;
 
@@ -170,9 +160,9 @@ void fpga_init_irq(void)
        __raw_writeb(0, OMAP1510_FPGA_IMR_HI);
        __raw_writeb(0, INNOVATOR_FPGA_IMR2);
 
-       for (i = IH_FPGA_BASE; i < (IH_FPGA_BASE + NR_FPGA_IRQS); i++) {
+       for (i = OMAP1510_IH_FPGA_BASE; i < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS); i++) {
 
-               if (i == INT_FPGA_TS) {
+               if (i == OMAP1510_INT_FPGA_TS) {
                        /*
                         * The touchscreen interrupt is level-sensitive, so
                         * we'll use the regular mask_ack routine for it.
@@ -201,9 +191,7 @@ void fpga_init_irq(void)
        omap_request_gpio(13);
        omap_set_gpio_direction(13, 1);
        omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE);
-       set_irq_chained_handler(INT_FPGA, innovator_fpga_IRQ_demux);
+       set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
 }
 
-EXPORT_SYMBOL(fpga_init_irq);
-EXPORT_SYMBOL(fpga_read);
-EXPORT_SYMBOL(fpga_write);
+EXPORT_SYMBOL(omap1510_fpga_init_irq);
diff --git a/arch/arm/mach-omap/leds-h2p2-debug.c b/arch/arm/mach-omap/leds-h2p2-debug.c
new file mode 100644 (file)
index 0000000..8ff27af
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * linux/arch/arm/mach-omap/leds-h2p2-debug.c
+ *
+ * Copyright 2003 by Texas Instruments Incorporated
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/version.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <asm/arch/fpga.h>
+
+#include "leds.h"
+
+void h2p2_dbg_leds_event(led_event_t evt)
+{
+       unsigned long flags;
+       static unsigned long hw_led_state = 0;
+
+       local_irq_save(flags);
+
+       switch (evt) {
+       case led_start:
+               hw_led_state |= H2P2_DBG_FPGA_LED_STARTSTOP;
+               break;
+
+       case led_stop:
+               hw_led_state &= ~H2P2_DBG_FPGA_LED_STARTSTOP;
+               break;
+
+       case led_claim:
+               hw_led_state |= H2P2_DBG_FPGA_LED_CLAIMRELEASE;
+               break;
+
+       case led_release:
+               hw_led_state &= ~H2P2_DBG_FPGA_LED_CLAIMRELEASE;
+               break;
+
+#ifdef CONFIG_LEDS_TIMER
+       case led_timer:
+               /*
+                * Toggle Timer LED
+                */
+               if (hw_led_state & H2P2_DBG_FPGA_LED_TIMER)
+                       hw_led_state &= ~H2P2_DBG_FPGA_LED_TIMER;
+               else
+                       hw_led_state |= H2P2_DBG_FPGA_LED_TIMER;
+               break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+       case led_idle_start:
+               hw_led_state |= H2P2_DBG_FPGA_LED_IDLE;
+               break;
+
+       case led_idle_end:
+               hw_led_state &= ~H2P2_DBG_FPGA_LED_IDLE;
+               break;
+#endif
+
+       case led_halted:
+               if (hw_led_state & H2P2_DBG_FPGA_LED_HALTED)
+                       hw_led_state &= ~H2P2_DBG_FPGA_LED_HALTED;
+               else
+                       hw_led_state |= H2P2_DBG_FPGA_LED_HALTED;
+               break;
+
+       case led_green_on:
+               break;
+
+       case led_green_off:
+               break;
+
+       case led_amber_on:
+               break;
+
+       case led_amber_off:
+               break;
+
+       case led_red_on:
+               break;
+
+       case led_red_off:
+               break;
+
+       default:
+               break;
+       }
+
+
+       /*
+        *  Actually burn the LEDs
+        */
+       __raw_writew(~hw_led_state & 0xffff, H2P2_DBG_FPGA_LEDS);
+
+       local_irq_restore(flags);
+}
index e3f378b..b6d0c72 100644 (file)
@@ -3,6 +3,7 @@
  *
  * OMAP LEDs dispatcher
  */
+#include <linux/kernel.h>
 #include <linux/init.h>
 
 #include <asm/leds.h>
 #include "leds.h"
 
 static int __init
-omap1510_leds_init(void)
+omap_leds_init(void)
 {
        if (machine_is_omap_innovator())
                leds_event = innovator_leds_event;
 
-       else if (machine_is_omap_perseus2()) {
-               leds_event = perseus2_leds_event;
+       else if (machine_is_omap_h2() || machine_is_omap_perseus2()) {
+               leds_event = h2p2_dbg_leds_event;
        }
 
        leds_event(led_start);
        return 0;
 }
 
-__initcall(omap1510_leds_init);
+__initcall(omap_leds_init);
index ba2eb59..7571e2d 100644 (file)
@@ -1,2 +1,2 @@
 extern void innovator_leds_event(led_event_t evt);
-extern void perseus2_leds_event(led_event_t evt);
+extern void h2p2_dbg_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-omap/mcbsp.c b/arch/arm/mach-omap/mcbsp.c
new file mode 100644 (file)
index 0000000..d334395
--- /dev/null
@@ -0,0 +1,669 @@
+/*
+ * linux/arch/arm/omap/mcbsp.c
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Samuel Ortiz <samuel.ortiz@nokia.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.
+ *
+ * Multichannel mode not supported.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/mcbsp.h>
+
+#ifdef CONFIG_MCBSP_DEBUG
+#define DBG(x...)      printk(x)
+#else
+#define DBG(x...)      do { } while (0)
+#endif
+
+struct omap_mcbsp {
+       u32                          io_base;
+       u8                           id;
+       u8                           free;
+       omap_mcbsp_word_length       rx_word_length;
+       omap_mcbsp_word_length       tx_word_length;
+
+       /* IRQ based TX/RX */
+       int                          rx_irq;
+       int                          tx_irq;
+
+       /* DMA stuff */
+       u8                           dma_rx_sync;
+       short                        dma_rx_lch;
+       u8                           dma_tx_sync;
+       short                        dma_tx_lch;
+
+       /* Completion queues */
+       struct completion            tx_irq_completion;
+       struct completion            rx_irq_completion;
+       struct completion            tx_dma_completion;
+       struct completion            rx_dma_completion;
+
+       spinlock_t                   lock;
+};
+
+static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
+
+
+static void omap_mcbsp_dump_reg(u8 id)
+{
+       DBG("**** MCBSP%d regs ****\n", mcbsp[id].id);
+       DBG("DRR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2));
+       DBG("DRR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1));
+       DBG("DXR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2));
+       DBG("DXR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1));
+       DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2));
+       DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1));
+       DBG("RCR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2));
+       DBG("RCR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1));
+       DBG("XCR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2));
+       DBG("XCR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1));
+       DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2));
+       DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1));
+       DBG("PCR0:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0));
+       DBG("***********************\n");
+}
+
+
+static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
+
+       DBG("TX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2));
+
+       complete(&mcbsp_tx->tx_irq_completion);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct omap_mcbsp * mcbsp_rx = (struct omap_mcbsp *)(dev_id);
+
+       DBG("RX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2));
+
+       complete(&mcbsp_rx->rx_irq_completion);
+       return IRQ_HANDLED;
+}
+
+
+static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
+{
+       struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
+
+       DBG("TX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2));
+
+       /* We can free the channels */
+       omap_free_dma(mcbsp_dma_tx->dma_tx_lch);
+       mcbsp_dma_tx->dma_tx_lch = -1;
+
+       complete(&mcbsp_dma_tx->tx_dma_completion);
+}
+
+static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
+{
+       struct omap_mcbsp * mcbsp_dma_rx = (struct omap_mcbsp *)(data);
+
+       DBG("RX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2));
+
+       /* We can free the channels */
+       omap_free_dma(mcbsp_dma_rx->dma_rx_lch);
+       mcbsp_dma_rx->dma_rx_lch = -1;
+
+       complete(&mcbsp_dma_rx->rx_dma_completion);
+}
+
+
+/*
+ * omap_mcbsp_config simply write a config to the
+ * appropriate McBSP.
+ * You either call this function or set the McBSP registers
+ * by yourself before calling omap_mcbsp_start().
+ */
+
+void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config)
+{
+       u32 io_base = mcbsp[id].io_base;
+
+       DBG("OMAP-McBSP: McBSP%d  io_base: 0x%8x\n", id+1, io_base);
+
+       /* We write the given config */
+       OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2);
+       OMAP_MCBSP_WRITE(io_base, SPCR1, config->spcr1);
+       OMAP_MCBSP_WRITE(io_base, RCR2, config->rcr2);
+       OMAP_MCBSP_WRITE(io_base, RCR1, config->rcr1);
+       OMAP_MCBSP_WRITE(io_base, XCR2, config->xcr2);
+       OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1);
+       OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2);
+       OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1);
+       OMAP_MCBSP_WRITE(io_base, SRGR2, config->mcr2);
+       OMAP_MCBSP_WRITE(io_base, SRGR1, config->mcr1);
+       OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
+}
+
+
+
+static int omap_mcbsp_check(unsigned int id)
+{
+       if (cpu_is_omap730()) {
+               if (id > OMAP_MAX_MCBSP_COUNT - 1) {
+                      printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
+                      return -1;
+               }
+               return 0;
+       }
+
+       if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
+               if (id > OMAP_MAX_MCBSP_COUNT) {
+                       printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
+                       return -1;
+               }
+               return 0;
+       }
+
+       return -1;
+}
+
+#define DSP_RSTCT2              0xe1008014
+
+static void omap_mcbsp_dsp_request(void)
+{
+       if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
+               omap_writew((omap_readw(ARM_RSTCT1) | (1 << 1) | (1 << 2)),
+                           ARM_RSTCT1);
+               omap_writew((omap_readw(ARM_CKCTL) | 1 << EN_DSPCK),
+                           ARM_CKCTL);
+               omap_writew((omap_readw(ARM_IDLECT2) | (1 << EN_APICK)),
+                           ARM_IDLECT2);
+
+               /* enable 12MHz clock to mcbsp 1 & 3 */
+               __raw_writew(__raw_readw(DSP_IDLECT2) | (1 << EN_XORPCK),
+                            DSP_IDLECT2);
+               __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
+                            DSP_RSTCT2);
+       }
+}
+
+static void omap_mcbsp_dsp_free(void)
+{
+       /* Useless for now */
+}
+
+
+int omap_mcbsp_request(unsigned int id)
+{
+       int err;
+
+       if (omap_mcbsp_check(id) < 0)
+               return -EINVAL;
+
+       /*
+        * On 1510, 1610 and 1710, McBSP1 and McBSP3
+        * are DSP public peripherals.
+        */
+       if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
+               omap_mcbsp_dsp_request();
+
+       spin_lock(&mcbsp[id].lock);
+       if (!mcbsp[id].free) {
+               printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
+               spin_unlock(&mcbsp[id].lock);
+               return -1;
+       }
+
+       mcbsp[id].free = 0;
+       spin_unlock(&mcbsp[id].lock);
+
+       /* We need to get IRQs here */
+       err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
+                         "McBSP",
+                         (void *) (&mcbsp[id]));
+       if (err != 0) {
+               printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
+                      mcbsp[id].tx_irq, mcbsp[id].id);
+               return err;
+       }
+
+       init_completion(&(mcbsp[id].tx_irq_completion));
+
+
+       err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
+                         "McBSP",
+                         (void *) (&mcbsp[id]));
+       if (err != 0) {
+               printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
+                      mcbsp[id].rx_irq, mcbsp[id].id);
+               free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+               return err;
+       }
+
+       init_completion(&(mcbsp[id].rx_irq_completion));
+       return 0;
+
+}
+
+void omap_mcbsp_free(unsigned int id)
+{
+       if (omap_mcbsp_check(id) < 0)
+               return;
+
+       if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
+               omap_mcbsp_dsp_free();
+
+       spin_lock(&mcbsp[id].lock);
+       if (mcbsp[id].free) {
+               printk (KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n", id + 1);
+               spin_unlock(&mcbsp[id].lock);
+               return;
+       }
+
+       mcbsp[id].free = 1;
+       spin_unlock(&mcbsp[id].lock);
+
+       /* Free IRQs */
+       free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
+       free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+}
+
+/*
+ * Here we start the McBSP, by enabling the sample
+ * generator, both transmitter and receivers,
+ * and the frame sync.
+ */
+void omap_mcbsp_start(unsigned int id)
+{
+       u32 io_base;
+       u16 w;
+
+       if (omap_mcbsp_check(id) < 0)
+               return;
+
+       io_base = mcbsp[id].io_base;
+
+       mcbsp[id].rx_word_length = ((OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7);
+       mcbsp[id].tx_word_length = ((OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7);
+
+       /* Start the sample generator */
+       w = OMAP_MCBSP_READ(io_base, SPCR2);
+       OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
+
+       /* Enable transmitter and receiver */
+       w = OMAP_MCBSP_READ(io_base, SPCR2);
+       OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1);
+
+       w = OMAP_MCBSP_READ(io_base, SPCR1);
+       OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1);
+
+       udelay(100);
+
+       /* Start frame sync */
+       w = OMAP_MCBSP_READ(io_base, SPCR2);
+       OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
+
+       /* Dump McBSP Regs */
+       omap_mcbsp_dump_reg(id);
+
+}
+
+void omap_mcbsp_stop(unsigned int id)
+{
+       u32 io_base;
+       u16 w;
+
+       if (omap_mcbsp_check(id) < 0)
+               return;
+
+       io_base = mcbsp[id].io_base;
+
+        /* Reset transmitter */
+       w = OMAP_MCBSP_READ(io_base, SPCR2);
+       OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1));
+
+       /* Reset receiver */
+       w = OMAP_MCBSP_READ(io_base, SPCR1);
+       OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1));
+
+       /* Reset the sample rate generator */
+       w = OMAP_MCBSP_READ(io_base, SPCR2);
+       OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
+}
+
+
+/*
+ * IRQ based word transmission.
+ */
+void omap_mcbsp_xmit_word(unsigned int id, u32 word)
+{
+       u32 io_base;
+       omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length;
+
+       if (omap_mcbsp_check(id) < 0)
+               return;
+
+       io_base = mcbsp[id].io_base;
+
+       wait_for_completion(&(mcbsp[id].tx_irq_completion));
+
+       if (word_length > OMAP_MCBSP_WORD_16)
+               OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
+       OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
+}
+
+u32 omap_mcbsp_recv_word(unsigned int id)
+{
+       u32 io_base;
+       u16 word_lsb, word_msb = 0;
+       omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length;
+
+       if (omap_mcbsp_check(id) < 0)
+               return -EINVAL;
+
+       io_base = mcbsp[id].io_base;
+
+       wait_for_completion(&(mcbsp[id].rx_irq_completion));
+
+       if (word_length > OMAP_MCBSP_WORD_16)
+               word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+       word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+       return (word_lsb | (word_msb << 16));
+}
+
+
+/*
+ * Simple DMA based buffer rx/tx routines.
+ * Nothing fancy, just a single buffer tx/rx through DMA.
+ * The DMA resources are released once the transfer is done.
+ * For anything fancier, you should use your own customized DMA
+ * routines and callbacks.
+ */
+int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
+{
+       int dma_tx_ch;
+
+       if (omap_mcbsp_check(id) < 0)
+               return -EINVAL;
+
+       if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback,
+                            &mcbsp[id],
+                            &dma_tx_ch)) {
+               printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id+1);
+               return -EAGAIN;
+       }
+       mcbsp[id].dma_tx_lch = dma_tx_ch;
+
+       DBG("TX DMA on channel %d\n", dma_tx_ch);
+
+       init_completion(&(mcbsp[id].tx_dma_completion));
+
+       omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
+                                    OMAP_DMA_DATA_TYPE_S16,
+                                    length >> 1, 1,
+                                    OMAP_DMA_SYNC_ELEMENT);
+
+       omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
+                                OMAP_DMA_PORT_TIPB,
+                                OMAP_DMA_AMODE_CONSTANT,
+                                mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1);
+
+       omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
+                               OMAP_DMA_PORT_EMIFF,
+                               OMAP_DMA_AMODE_POST_INC,
+                               buffer);
+
+       omap_start_dma(mcbsp[id].dma_tx_lch);
+       wait_for_completion(&(mcbsp[id].tx_dma_completion));
+       return 0;
+}
+
+
+int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
+{
+       int dma_rx_ch;
+
+       if (omap_mcbsp_check(id) < 0)
+               return -EINVAL;
+
+       if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback,
+                            &mcbsp[id],
+                            &dma_rx_ch)) {
+               printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id+1);
+               return -EAGAIN;
+       }
+       mcbsp[id].dma_rx_lch = dma_rx_ch;
+
+       DBG("RX DMA on channel %d\n", dma_rx_ch);
+
+       init_completion(&(mcbsp[id].rx_dma_completion));
+
+       omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
+                                    OMAP_DMA_DATA_TYPE_S16,
+                                    length >> 1, 1,
+                                    OMAP_DMA_SYNC_ELEMENT);
+
+       omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
+                               OMAP_DMA_PORT_TIPB,
+                               OMAP_DMA_AMODE_CONSTANT,
+                               mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1);
+
+       omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
+                                OMAP_DMA_PORT_EMIFF,
+                                OMAP_DMA_AMODE_POST_INC,
+                                buffer);
+
+       omap_start_dma(mcbsp[id].dma_rx_lch);
+       wait_for_completion(&(mcbsp[id].rx_dma_completion));
+       return 0;
+}
+
+
+/*
+ * SPI wrapper.
+ * Since SPI setup is much simpler than the generic McBSP one,
+ * this wrapper just need an omap_mcbsp_spi_cfg structure as an input.
+ * Once this is done, you can call omap_mcbsp_start().
+ */
+void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg)
+{
+       struct omap_mcbsp_reg_cfg mcbsp_cfg;
+
+       if (omap_mcbsp_check(id) < 0)
+               return;
+
+       memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));
+
+       /* SPI has only one frame */
+       mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0));
+       mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0));
+
+        /* Clock stop mode */
+       if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY)
+               mcbsp_cfg.spcr1 |= (1 << 12);
+       else
+               mcbsp_cfg.spcr1 |= (3 << 11);
+
+       /* Set clock parities */
+       if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING)
+               mcbsp_cfg.pcr0 |= CLKRP;
+       else
+               mcbsp_cfg.pcr0 &= ~CLKRP;
+
+       if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING)
+               mcbsp_cfg.pcr0 &= ~CLKXP;
+       else
+               mcbsp_cfg.pcr0 |= CLKXP;
+
+       /* Set SCLKME to 0 and CLKSM to 1 */
+       mcbsp_cfg.pcr0 &= ~SCLKME;
+       mcbsp_cfg.srgr2 |= CLKSM;
+
+       /* Set FSXP */
+       if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH)
+               mcbsp_cfg.pcr0 &= ~FSXP;
+       else
+               mcbsp_cfg.pcr0 |= FSXP;
+
+       if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) {
+               mcbsp_cfg.pcr0 |= CLKXM;
+               mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div -1);
+               mcbsp_cfg.pcr0 |= FSXM;
+               mcbsp_cfg.srgr2 &= ~FSGM;
+               mcbsp_cfg.xcr2 |= XDATDLY(1);
+               mcbsp_cfg.rcr2 |= RDATDLY(1);
+       }
+       else {
+               mcbsp_cfg.pcr0 &= ~CLKXM;
+               mcbsp_cfg.srgr1 |= CLKGDV(1);
+               mcbsp_cfg.pcr0 &= ~FSXM;
+               mcbsp_cfg.xcr2 &= ~XDATDLY(3);
+               mcbsp_cfg.rcr2 &= ~RDATDLY(3);
+       }
+
+       mcbsp_cfg.xcr2 &= ~XPHASE;
+       mcbsp_cfg.rcr2 &= ~RPHASE;
+
+       omap_mcbsp_config(id, &mcbsp_cfg);
+}
+
+
+/*
+ * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
+ * 730 has only 2 McBSP, and both of them are MPU peripherals.
+ */
+struct omap_mcbsp_info {
+       u32 virt_base;
+       u8 dma_rx_sync, dma_tx_sync;
+       u16 rx_irq, tx_irq;
+};
+
+#ifdef CONFIG_ARCH_OMAP730
+static const struct omap_mcbsp_info mcbsp_730[] = {
+       [0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE),
+               .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
+               .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
+               .rx_irq = INT_730_McBSP1RX,
+               .tx_irq = INT_730_McBSP1TX },
+       [1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE),
+               .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
+               .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
+               .rx_irq = INT_730_McBSP2RX,
+               .tx_irq = INT_730_McBSP2TX },
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1510
+static const struct omap_mcbsp_info mcbsp_1510[] = {
+       [0] = { .virt_base = OMAP1510_MCBSP1_BASE,
+               .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
+               .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
+               .rx_irq = INT_McBSP1RX,
+               .tx_irq = INT_McBSP1TX },
+       [1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE),
+               .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
+               .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
+               .rx_irq = INT_1510_SPI_RX,
+               .tx_irq = INT_1510_SPI_TX },
+       [2] = { .virt_base = OMAP1510_MCBSP3_BASE,
+               .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
+               .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
+               .rx_irq = INT_McBSP3RX,
+               .tx_irq = INT_McBSP3TX },
+};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+static const struct omap_mcbsp_info mcbsp_1610[] = {
+       [0] = { .virt_base = OMAP1610_MCBSP1_BASE,
+               .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
+               .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
+               .rx_irq = INT_McBSP1RX,
+               .tx_irq = INT_McBSP1TX },
+       [1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE),
+               .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
+               .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
+               .rx_irq = INT_1610_McBSP2_RX,
+               .tx_irq = INT_1610_McBSP2_TX },
+       [2] = { .virt_base = OMAP1610_MCBSP3_BASE,
+               .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
+               .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
+               .rx_irq = INT_McBSP3RX,
+               .tx_irq = INT_McBSP3TX },
+};
+#endif
+
+static int __init omap_mcbsp_init(void)
+{
+       int mcbsp_count = 0, i;
+       static const struct omap_mcbsp_info *mcbsp_info;
+
+       printk("Initializing OMAP McBSP system\n");
+#ifdef CONFIG_ARCH_OMAP730
+       if (cpu_is_omap730()) {
+               mcbsp_info = mcbsp_730;
+               mcbsp_count = ARRAY_SIZE(mcbsp_730);
+       }
+#endif
+#ifdef CONFIG_ARCH_OMAP1510
+       if (cpu_is_omap1510()) {
+               mcbsp_info = mcbsp_1510;
+               mcbsp_count = ARRAY_SIZE(mcbsp_1510);
+       }
+#endif
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+       if (cpu_is_omap1610() || cpu_is_omap1710()) {
+               mcbsp_info = mcbsp_1610;
+               mcbsp_count = ARRAY_SIZE(mcbsp_1610);
+       }
+#endif
+       for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
+               if (i >= mcbsp_count) {
+                       mcbsp[i].io_base = 0;
+                       mcbsp[i].free = 0;
+                        continue;
+               }
+               mcbsp[i].id = i + 1;
+               mcbsp[i].free = 1;
+               mcbsp[i].dma_tx_lch = -1;
+               mcbsp[i].dma_rx_lch = -1;
+
+               mcbsp[i].io_base = mcbsp_info[i].virt_base;
+               mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
+               mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
+               mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
+               mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync;
+               spin_lock_init(&mcbsp[i].lock);
+       }
+
+       return 0;
+}
+
+
+arch_initcall(omap_mcbsp_init);
+
+EXPORT_SYMBOL(omap_mcbsp_config);
+EXPORT_SYMBOL(omap_mcbsp_request);
+EXPORT_SYMBOL(omap_mcbsp_free);
+EXPORT_SYMBOL(omap_mcbsp_start);
+EXPORT_SYMBOL(omap_mcbsp_stop);
+EXPORT_SYMBOL(omap_mcbsp_xmit_word);
+EXPORT_SYMBOL(omap_mcbsp_recv_word);
+EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
+EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
+EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
index 944c294..93c7f4a 100644 (file)
@@ -59,8 +59,8 @@ int ocpi_enable(void)
 
        /* Make sure there's clock for OCPI */
 
-#ifdef CONFIG_ARCH_OMAP1610
-        if (cpu_is_omap1610()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+        if (cpu_is_omap1610() || cpu_is_omap1710()) {
                val = omap_readl(OMAP1610_ARM_IDLECT3);
                val |= EN_OCPI_CK;
                val &= ~IDLOCPI_ARM;
diff --git a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c
new file mode 100644 (file)
index 0000000..f3451d2
--- /dev/null
@@ -0,0 +1,541 @@
+/*
+ * arch/arm/mach-omap/usb.c -- platform level USB initialization
+ *
+ * Copyright (C) 2004 Texas Instruments, 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
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/usb_otg.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+
+/* These routines should handle the standard chip-specific modes
+ * for usb0/1/2 ports, covering basic mux and transceiver setup.
+ * Call omap_usb_init() once, from INIT_MACHINE().
+ *
+ * Some board-*.c files will need to set up additional mux options,
+ * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.
+ */
+
+/* TESTED ON:
+ *  - 1611B H2 (with usb1 mini-AB)
+ *  - 1510 Innovator with built-in transceiver (custom cable feeding 5V VBUS)
+ *  - 1710 custom development board using alternate pin group
+ */
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_OMAP_OTG
+
+static struct otg_transceiver *xceiv;
+
+/**
+ * otg_get_transceiver - find the (single) OTG transceiver driver
+ *
+ * Returns the transceiver driver, after getting a refcount to it; or
+ * null if there is no such transceiver.  The caller is responsible for
+ * releasing that count.
+ */
+struct otg_transceiver *otg_get_transceiver(void)
+{
+       if (xceiv)
+               get_device(xceiv->dev);
+       return xceiv;
+}
+EXPORT_SYMBOL(otg_get_transceiver);
+
+int otg_set_transceiver(struct otg_transceiver *x)
+{
+       if (xceiv && x)
+               return -EBUSY;
+       xceiv = x;
+       return 0;
+}
+EXPORT_SYMBOL(otg_set_transceiver);
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
+{
+       u32     syscon1 = 0;
+
+       if (nwires == 0) {
+               USB_TRANSCEIVER_CTRL_REG &= ~(1 << 3);
+               return 0;
+       }
+
+       /*
+        * VP and VM are needed for all active usb0 configurations.
+        * USB0_VP and USB0_VM are always set on 1510, there's no muxing
+        * available for them.
+        */
+       if (nwires >= 2 && !cpu_is_omap1510()) {
+               omap_cfg_reg(AA9_USB0_VP);
+               omap_cfg_reg(R9_USB0_VM);
+       }
+
+       /* internal transceiver */
+       if (nwires == 2) {
+               if (cpu_is_omap1510()) {
+                       /* This works for OHCI on 1510-Innovator, nothing to mux */
+                       return 0;
+               }
+
+#if 0
+               /* NOTE:  host OR device mode for now, no OTG */
+               USB_TRANSCEIVER_CTRL_REG &= ~(3 << 4);
+               if (is_device) {
+                       omap_cfg_reg(W4_USB_PUEN);
+                       omap_cfg_reg(R18_1510_USB_GPIO0);
+                       // omap_cfg_reg(USB0_VBUS);
+                       // omap_cfg_reg(USB0_PUEN);
+                       // USB_TRANSCEIVER_CTRL_REG.CONF_USB0_PORT_R = 7
+                       // when USB0_PUEN is needed
+               } else /* host mode needs D+ and D- pulldowns */
+                       USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
+               return 3 << 16;
+#else
+               /* FIXME: 1610 needs to return the right value here */
+               printk(KERN_ERR "usb0 internal transceiver, nyet\n");
+               return 0;
+#endif
+       }
+
+       /* alternate pin config, external transceiver */
+       omap_cfg_reg(V6_USB0_TXD);
+       omap_cfg_reg(W9_USB0_TXEN);
+       omap_cfg_reg(W5_USB0_SE0);
+
+#ifdef CONFIG_ARCH_OMAP_USB_SPEED
+       /* FIXME: there's good chance that pin V9 is used for MMC2 port cmddir */
+       omap_cfg_reg(V9_USB0_SPEED);
+       // omap_cfg_reg(V9_USB0_SUSP);
+#endif
+
+       if (nwires != 3)
+               omap_cfg_reg(Y5_USB0_RCV);
+
+       switch (nwires) {
+       case 3:
+               syscon1 = 2;
+               break;
+       case 4:
+               syscon1 = 1;
+               break;
+       case 6:
+               syscon1 = 3;
+               /* REVISIT: Is CONF_USB2_UNI_R only needed when nwires = 6? */
+               USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+               break;
+       default:
+               printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+                       0, nwires);
+       }
+       return syscon1 << 16;
+}
+
+static u32 __init omap_usb1_init(unsigned nwires)
+{
+       u32     syscon1 = 0;
+
+       if (nwires != 6)
+               USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R;
+       if (nwires == 0)
+               return 0;
+
+       /* external transceiver */
+       omap_cfg_reg(USB1_TXD);
+       omap_cfg_reg(USB1_TXEN);
+       if (cpu_is_omap1510()) {
+               omap_cfg_reg(USB1_SEO);
+               omap_cfg_reg(USB1_SPEED);
+               // SUSP
+       } else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
+               omap_cfg_reg(W13_1610_USB1_SE0);
+               omap_cfg_reg(R13_1610_USB1_SPEED);
+               // SUSP
+       } else {
+               pr_debug("usb unrecognized\n");
+       }
+       if (nwires != 3)
+               omap_cfg_reg(USB1_RCV);
+
+       switch (nwires) {
+       case 3:
+               syscon1 = 2;
+               break;
+       case 4:
+               syscon1 = 1;
+               break;
+       case 6:
+               syscon1 = 3;
+               omap_cfg_reg(USB1_VP);
+               omap_cfg_reg(USB1_VM);
+               USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R;
+               break;
+       default:
+               printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+                       1, nwires);
+       }
+       return syscon1 << 20;
+}
+
+static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
+{
+       u32     syscon1 = 0;
+
+       if (alt_pingroup)
+               return 0;
+       if (nwires != 6)
+               USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
+       if (nwires == 0)
+               return 0;
+
+       /* external transceiver */
+       if (cpu_is_omap1510()) {
+               omap_cfg_reg(USB2_TXD);
+               omap_cfg_reg(USB2_TXEN);
+               omap_cfg_reg(USB2_SEO);
+               if (nwires != 3)
+                       omap_cfg_reg(USB2_RCV);
+       } else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
+               omap_cfg_reg(V6_USB2_TXD);
+               omap_cfg_reg(W9_USB2_TXEN);
+               omap_cfg_reg(W5_USB2_SE0);
+               if (nwires != 3)
+                       omap_cfg_reg(Y5_USB2_RCV);
+       } else {
+               pr_debug("usb unrecognized\n");
+       }
+       // omap_cfg_reg(USB2_SUSP);
+       // FIXME omap_cfg_reg(USB2_SPEED);
+
+       switch (nwires) {
+       case 3:
+               syscon1 = 2;
+               break;
+       case 4:
+               syscon1 = 1;
+               break;
+       case 6:
+               syscon1 = 3;
+               if (cpu_is_omap1510()) {
+                       omap_cfg_reg(USB2_VP);
+                       omap_cfg_reg(USB2_VM);
+               } else {
+                       omap_cfg_reg(AA9_USB2_VP);
+                       omap_cfg_reg(R9_USB2_VM);
+               }
+               USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+               break;
+       default:
+               printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+                       2, nwires);
+       }
+       return syscon1 << 24;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if    defined(CONFIG_USB_GADGET_OMAP) || \
+       defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) || \
+       (defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG))
+static void usb_release(struct device *dev)
+{
+       /* normally not freed */
+}
+#endif
+
+#ifdef CONFIG_USB_GADGET_OMAP
+
+static struct resource udc_resources[] = {
+       /* order is significant! */
+       {               /* registers */
+               .start          = IO_ADDRESS(UDC_BASE),
+               .end            = IO_ADDRESS(UDC_BASE + 0xff),
+               .flags          = IORESOURCE_MEM,
+       }, {            /* general IRQ */
+               .start          = IH2_BASE + 20,
+               .flags          = IORESOURCE_IRQ,
+       }, {            /* PIO IRQ */
+               .start          = IH2_BASE + 30,
+               .flags          = IORESOURCE_IRQ,
+       }, {            /* SOF IRQ */
+               .start          = IH2_BASE + 29,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static u64 udc_dmamask = ~(u32)0;
+
+static struct platform_device udc_device = {
+       .name           = "omap_udc",
+       .id             = -1,
+       .dev = {
+               .release                = usb_release,
+               .dma_mask               = &udc_dmamask,
+               .coherent_dma_mask      = 0xffffffff,
+       },
+       .num_resources  = ARRAY_SIZE(udc_resources),
+       .resource       = udc_resources,
+};
+
+#endif
+
+#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+
+/* The dmamask must be set for OHCI to work */
+static u64 ohci_dmamask = ~(u32)0;
+
+static struct resource ohci_resources[] = {
+       {
+               .start  = IO_ADDRESS(OMAP_OHCI_BASE),
+               .end    = IO_ADDRESS(OMAP_OHCI_BASE + 4096),
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = INT_USB_HHC_1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device ohci_device = {
+       .name                   = "ohci",
+       .id                     = -1,
+       .dev = {
+               .release                = usb_release,
+               .dma_mask               = &ohci_dmamask,
+               .coherent_dma_mask      = 0x0fffffff,
+       },
+       .num_resources  = ARRAY_SIZE(ohci_resources),
+       .resource               = ohci_resources,
+};
+
+#endif
+
+#if    defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG)
+
+static struct resource otg_resources[] = {
+       /* order is significant! */
+       {
+               .start          = IO_ADDRESS(OTG_BASE),
+               .end            = IO_ADDRESS(OTG_BASE + 0xff),
+               .flags          = IORESOURCE_MEM,
+       }, {
+               .start          = IH2_BASE + 8,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device otg_device = {
+       .name           = "omap_otg",
+       .id             = -1,
+       .dev = {
+               .release                = usb_release,
+       },
+       .num_resources  = ARRAY_SIZE(otg_resources),
+       .resource       = otg_resources,
+};
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+// FIXME correct answer depends on hmc_mode,
+// as does any nonzero value for config->otg port number
+#define        is_usb0_device(config)  0
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_OMAP_OTG
+
+void __init
+omap_otg_init(struct omap_usb_config *config)
+{
+       u32             syscon = OTG_SYSCON_1_REG & 0xffff;
+       int             status;
+       int             alt_pingroup = 0;
+
+       /* NOTE:  no bus or clock setup (yet?) */
+
+       syscon = OTG_SYSCON_1_REG & 0xffff;
+       if (!(syscon & OTG_RESET_DONE))
+               pr_debug("USB resets not complete?\n");
+
+       // OTG_IRQ_EN_REG = 0;
+
+       /* pin muxing and transceiver pinouts */
+       if (config->pins[0] > 2)        /* alt pingroup 2 */
+               alt_pingroup = 1;
+       syscon |= omap_usb0_init(config->pins[0], is_usb0_device(config));
+       syscon |= omap_usb1_init(config->pins[1]);
+       syscon |= omap_usb2_init(config->pins[2], alt_pingroup);
+       pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon);
+       OTG_SYSCON_1_REG = syscon;
+
+       syscon = config->hmc_mode;
+       syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */;
+       if (config->otg || config->register_host)
+               syscon |= UHOST_EN;
+#ifdef CONFIG_USB_OTG
+       if (config->otg)
+               syscon |= OTG_EN;
+#endif
+       pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon);
+       OTG_SYSCON_2_REG = syscon;
+
+       printk("USB: hmc %d", config->hmc_mode);
+       if (alt_pingroup)
+               printk(", usb2 alt %d wires", config->pins[2]);
+       else if (config->pins[0])
+               printk(", usb0 %d wires%s", config->pins[2],
+                       is_usb0_device(config) ? " (dev)" : "");
+       if (config->pins[1])
+               printk(", usb1 %d wires", config->pins[1]);
+       if (!alt_pingroup && config->pins[2])
+               printk(", usb2 %d wires", config->pins[2]);
+       if (config->otg)
+               printk(", Mini-AB on usb%d", config->otg - 1);
+       printk("\n");
+
+       /* don't clock unused USB controllers  */
+       syscon = OTG_SYSCON_1_REG;
+       syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN;
+
+#ifdef CONFIG_USB_GADGET_OMAP
+       if (config->otg || config->register_dev) {
+               syscon &= ~DEV_IDLE_EN;
+               udc_device.dev.platform_data = config;
+               status = platform_device_register(&udc_device);
+               if (status)
+                       pr_debug("can't register UDC device, %d\n", status);
+       }
+#endif
+
+#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+       if (config->otg || config->register_host) {
+               syscon &= ~HST_IDLE_EN;
+               ohci_device.dev.platform_data = config;
+               status = platform_device_register(&ohci_device);
+               if (status)
+                       pr_debug("can't register OHCI device, %d\n", status);
+       }
+#endif
+
+#ifdef CONFIG_USB_OTG
+       if (config->otg) {
+               syscon &= ~OTG_IDLE_EN;
+               if (cpu_is_omap730())
+                       otg_resources[1].start = INT_730_USB_OTG;
+               status = platform_device_register(&otg_device);
+               // ...
+       }
+#endif
+       pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon);
+       OTG_SYSCON_1_REG = syscon;
+
+       status = 0;
+}
+
+#else
+static inline void omap_otg_init(struct omap_usb_config *config) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_OMAP1510
+
+static void __init omap_1510_usb_init(struct omap_usb_config *config)
+{
+       int status;
+       unsigned int val;
+
+       omap_usb0_init(config->pins[0], is_usb0_device(config));
+       omap_usb1_init(config->pins[1]);
+       omap_usb2_init(config->pins[2], 0);
+
+       val = omap_readl(MOD_CONF_CTRL_0) & ~(0x3f << 1);
+       val |= (config->hmc_mode << 1);
+       omap_writel(val, MOD_CONF_CTRL_0);
+
+       // FIXME this has a UDC controller too
+
+#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+       if (config->otg || config->register_host) {
+               ohci_device.dev.platform_data = config;
+               status = platform_device_register(&ohci_device);
+               if (status)
+                       pr_debug("can't register OHCI device, %d\n", status);
+       }
+       // FIXME completely untested ...
+#endif
+
+}
+
+#else
+static inline void omap_1510_usb_init(struct omap_usb_config *config) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static struct omap_usb_config platform_data;
+
+static int __init
+omap_usb_init(void)
+{
+       const struct omap_usb_config *config;
+
+       config = omap_get_config(OMAP_TAG_USB, struct omap_usb_config);
+       if (config == NULL) {
+               printk(KERN_ERR "USB: No board-specific platform config found\n");
+               return -ENODEV;
+       }
+       platform_data = *config;
+
+       if (cpu_is_omap730()
+                       || cpu_is_omap1610()
+                       || cpu_is_omap1710()
+                       || cpu_is_omap5912())
+               omap_otg_init(&platform_data);
+       else if (cpu_is_omap1510())
+               omap_1510_usb_init(&platform_data);
+       else {
+               printk(KERN_ERR "USB: No init for your chip yet\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+subsys_initcall(omap_usb_init);
index c771e43..a676a86 100644 (file)
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
+#include <asm/arch/pxa-regs.h>
 
 #include "generic.h"
 
 
 /*
- * This is for IRQs known as PXA_IRQ([8...31]).
+ * This is for peripheral IRQs internal to the PXA chip.
  */
 
-static void pxa_mask_irq(unsigned int irq)
+static void pxa_mask_low_irq(unsigned int irq)
 {
        ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
 }
 
-static void pxa_unmask_irq(unsigned int irq)
+static void pxa_unmask_low_irq(unsigned int irq)
 {
        ICMR |= (1 << (irq + PXA_IRQ_SKIP));
 }
 
-static struct irqchip pxa_internal_chip = {
-       .ack            = pxa_mask_irq,
-       .mask           = pxa_mask_irq,
-       .unmask         = pxa_unmask_irq,
+static struct irqchip pxa_internal_chip_low = {
+       .ack            = pxa_mask_low_irq,
+       .mask           = pxa_mask_low_irq,
+       .unmask         = pxa_unmask_low_irq,
 };
 
+#if PXA_INTERNAL_IRQS > 32
+
+/*
+ * This is for the second set of internal IRQs as found on the PXA27x.
+ */
+
+static void pxa_mask_high_irq(unsigned int irq)
+{
+       ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP));
+}
+
+static void pxa_unmask_high_irq(unsigned int irq)
+{
+       ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
+}
+
+static struct irqchip pxa_internal_chip_high = {
+       .ack            = pxa_mask_high_irq,
+       .mask           = pxa_mask_high_irq,
+       .unmask         = pxa_unmask_high_irq,
+};
+
+#endif
+
 /*
  * PXA GPIO edge detection for IRQs:
  * IRQs are generated on Falling-Edge, Rising-Edge, or both.
  * Use this instead of directly setting GRER/GFER.
  */
 
-static long GPIO_IRQ_rising_edge[3];
-static long GPIO_IRQ_falling_edge[3];
-static long GPIO_IRQ_mask[3];
+static long GPIO_IRQ_rising_edge[4];
+static long GPIO_IRQ_falling_edge[4];
+static long GPIO_IRQ_mask[4];
 
 static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
 {
@@ -106,13 +131,13 @@ static void pxa_ack_low_gpio(unsigned int irq)
 
 static struct irqchip pxa_low_gpio_chip = {
        .ack            = pxa_ack_low_gpio,
-       .mask           = pxa_mask_irq,
-       .unmask         = pxa_unmask_irq,
+       .mask           = pxa_mask_low_irq,
+       .unmask         = pxa_unmask_low_irq,
        .type           = pxa_gpio_irq_type,
 };
 
 /*
- * Demux handler for GPIO 2-80 edge detect interrupts
+ * Demux handler for GPIO>=2 edge detect interrupts
  */
 
 static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
@@ -169,6 +194,23 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
                        } while (mask);
                        loop = 1;
                }
+
+#if PXA_LAST_GPIO >= 96
+               mask = GEDR3;
+               if (mask) {
+                       GEDR3 = mask;
+                       irq = IRQ_GPIO(96);
+                       desc = irq_desc + irq;
+                       do {
+                               if (mask & 1)
+                                       desc->handle(irq, desc, regs);
+                               irq++;
+                               desc++;
+                               mask >>= 1;
+                       } while (mask);
+                       loop = 1;
+               }
+#endif
        } while (loop);
 }
 
@@ -214,12 +256,25 @@ void __init pxa_init_irq(void)
        ICLR = 0;
 
        /* clear all GPIO edge detects */
-       GFER0 = GFER1 = GFER2 = 0;
-       GRER0 = GRER1 = GRER2 = 0;
+       GFER0 = 0;
+       GFER1 = 0;
+       GFER2 = 0;
+       GRER0 = 0;
+       GRER1 = 0;
+       GRER2 = 0;
        GEDR0 = GEDR0;
        GEDR1 = GEDR1;
        GEDR2 = GEDR2;
 
+#ifdef CONFIG_PXA27x
+       /* And similarly for the extra regs on the PXA27x */
+       ICMR2 = 0;
+       ICLR2 = 0;
+       GFER3 = 0;
+       GRER3 = 0;
+       GEDR3 = GEDR3;
+#endif
+
        /* only unmasked interrupts kick us out of idle */
        ICCR = 1;
 
@@ -227,10 +282,18 @@ void __init pxa_init_irq(void)
        GPIO_IRQ_mask[0] = 3;
 
        for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
-               set_irq_chip(irq, &pxa_internal_chip);
+               set_irq_chip(irq, &pxa_internal_chip_low);
+               set_irq_handler(irq, do_level_IRQ);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+
+#if PXA_INTERNAL_IRQS > 32
+       for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
+               set_irq_chip(irq, &pxa_internal_chip_high);
                set_irq_handler(irq, do_level_IRQ);
                set_irq_flags(irq, IRQF_VALID);
        }
+#endif
 
        for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
                set_irq_chip(irq, &pxa_low_gpio_chip);
@@ -238,13 +301,13 @@ void __init pxa_init_irq(void)
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
-       for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) {
+       for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) {
                set_irq_chip(irq, &pxa_muxed_gpio_chip);
                set_irq_handler(irq, do_edge_IRQ);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
-       /* Install handler for GPIO 2-80 edge detect interrupts */
-       set_irq_chip(IRQ_GPIO_2_80, &pxa_internal_chip);
-       set_irq_chained_handler(IRQ_GPIO_2_80, pxa_gpio_demux_handler);
+       /* Install handler for GPIO>=2 edge detect interrupts */
+       set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
+       set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
 }
index 8403f67..bbd3f87 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/leds.h>
 #include <asm/system.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/mainstone.h>
 
 #include "leds.h"
index 155b595..219fd4e 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/mainstone.h>
 #include <asm/arch/pxafb.h>
 
index 4115091..e887b71 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/pm.h>
 
 #include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
 
 #include "generic.h"
 
index b1573c8..e5e97fe 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <asm/arch/pxa-regs.h>
 #include <linux/init.h>
 #include <linux/pm.h>
 
index 1892639..be00614 100644 (file)
@@ -16,6 +16,8 @@
 #include <asm/assembler.h>
 #include <asm/hardware.h>
 
+#include <asm/arch/pxa-regs.h>
+
                .text
 
 /*
@@ -64,6 +66,37 @@ ENTRY(pxa_cpu_suspend)
        @ prepare pointer to physical address 0 (virtual mapping in generic.c)
        mov     r2, #UNCACHED_PHYS_0
 
+       @ Intel PXA255 Specification Update notes problems
+       @ about suspending with PXBus operating above 133MHz
+       @ (see Errata 31, GPIO output signals, ... unpredictable in sleep
+       @
+       @ We keep the change-down close to the actual suspend on SDRAM
+       @ as possible to eliminate messing about with the refresh clock
+       @ as the system will restore with the original speed settings
+       @
+       @ Ben Dooks, 13-Sep-2004
+
+       ldr     r6, =CCCR
+       ldr     r8, [r6]                @ keep original value for resume
+
+       @ ensure x1 for run and turbo mode with memory clock
+       bic     r7, r8, #CCCR_M_MASK | CCCR_N_MASK
+       orr     r7, r7, #(1<<5) | (2<<7)
+
+       @ check that the memory frequency is within limits
+       and     r14, r7, #CCCR_L_MASK
+       teq     r14, #1
+       bicne   r7, r7, #CCCR_L_MASK
+       orrne   r7, r7, #1                      @@ 99.53MHz
+
+       @ get ready for the change
+       @ note, since we are making turbo=run, do not remove the turbo
+       @ as this may cause non-turbo mode on resume
+       mrc     p14, 0, r0, c6, c0, 0
+       bic     r0, r0, #2                      @ clear change bit
+       mcr     p14, 0, r0, c6, c0, 0
+       orr     r0, r0, #2                      @ initiate change bit
+
        @ align execution to a cache line
        b       1f
 
@@ -74,6 +107,13 @@ ENTRY(pxa_cpu_suspend)
        @ All needed values are now in registers.
        @ These last instructions should be in cache
 
+       @ initiate the frequency change...
+       str     r7, [r6]
+       mcr     p14, 0, r0, c6, c0, 0
+
+       @ restore the original cpu speed value for resume
+       str     r8, [r6]
+
        @ put SDRAM into self-refresh
        str     r5, [r4]
 
@@ -83,8 +123,7 @@ ENTRY(pxa_cpu_suspend)
        @ enter sleep mode
        mcr     p14, 0, r1, c7, c0, 0
 
-20:    nop
-       b       20b                             @ loop waiting for sleep
+20:    b       20b                             @ loop waiting for sleep
 
 /*
  * cpu_pxa_resume()
index 7e89235..a49fc02 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
+#include <asm/arch/pxa-regs.h>
 
 
 static inline unsigned long pxa_get_rtc_time(void)
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
new file mode 100644 (file)
index 0000000..a12ade7
--- /dev/null
@@ -0,0 +1,310 @@
+/* linux/arch/arm/mach-s3c2410/clock.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 Clock control support
+ *
+ * Based on, and code from linux/arch/arm/mach-versatile/clock.c
+ **
+ **  Copyright (C) 2004 ARM Limited.
+ **  Written by Deep Blue Solutions Limited.
+ *
+ *
+ * This program is free software; you can redistribute 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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/hardware/clock.h>
+#include <asm/arch/regs-clock.h>
+
+#include "clock.h"
+
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+
+
+/* old functions */
+
+void s3c2410_clk_enable(unsigned int clocks, unsigned int enable)
+{
+       unsigned long clkcon;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       clkcon = __raw_readl(S3C2410_CLKCON);
+       clkcon &= ~clocks;
+
+       if (enable)
+               clkcon |= clocks;
+
+       __raw_writel(clkcon, S3C2410_CLKCON);
+
+       local_irq_restore(flags);
+}
+
+
+/* Clock API calls */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       struct clk *p;
+       struct clk *clk = ERR_PTR(-ENOENT);
+
+       down(&clocks_sem);
+       list_for_each_entry(p, &clocks, list) {
+               if (strcmp(id, p->name) == 0 &&
+                   try_module_get(p->owner)) {
+                       clk = p;
+                       break;
+               }
+       }
+       up(&clocks_sem);
+
+       return clk;
+}
+
+void clk_put(struct clk *clk)
+{
+       module_put(clk->owner);
+}
+
+int clk_enable(struct clk *clk)
+{
+       if (clk->ctrlbit != 0)
+               s3c2410_clk_enable(clk->ctrlbit, 1);
+
+       return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+       s3c2410_clk_enable(clk->ctrlbit, 0);
+}
+
+
+int clk_use(struct clk *clk)
+{
+       atomic_inc(&clk->used);
+       return 0;
+}
+
+
+void clk_unuse(struct clk *clk)
+{
+       atomic_dec(&clk->used);
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       if (clk->parent != NULL)
+               return clk->parent->rate;
+
+       return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       return rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       return -EINVAL;
+}
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+       return clk->parent;
+}
+
+EXPORT_SYMBOL(clk_get);
+EXPORT_SYMBOL(clk_put);
+EXPORT_SYMBOL(clk_enable);
+EXPORT_SYMBOL(clk_disable);
+EXPORT_SYMBOL(clk_use);
+EXPORT_SYMBOL(clk_unuse);
+EXPORT_SYMBOL(clk_get_rate);
+EXPORT_SYMBOL(clk_round_rate);
+EXPORT_SYMBOL(clk_set_rate);
+EXPORT_SYMBOL(clk_get_parent);
+
+/* base clocks */
+
+static struct clk clk_f = {
+       .name          = "fclk",
+       .rate          = 0,
+       .parent        = NULL,
+       .ctrlbit       = 0
+};
+
+static struct clk clk_h = {
+       .name          = "hclk",
+       .rate          = 0,
+       .parent        = NULL,
+       .ctrlbit       = 0
+};
+
+static struct clk clk_p = {
+       .name          = "pclk",
+       .rate          = 0,
+       .parent        = NULL,
+       .ctrlbit       = 0
+};
+
+/* clock definitions */
+
+static struct clk init_clocks[] = {
+       { .name    = "nand",
+         .parent  = &clk_h,
+         .ctrlbit = S3C2410_CLKCON_NAND
+       },
+       { .name    = "lcd",
+         .parent  = &clk_h,
+         .ctrlbit = S3C2410_CLKCON_LCDC
+       },
+       { .name    = "usb-host",
+         .parent  = &clk_h,
+         .ctrlbit =   S3C2410_CLKCON_USBH
+       },
+       { .name    = "usb-device",
+         .parent  = &clk_h,
+         .ctrlbit = S3C2410_CLKCON_USBD
+       },
+       { .name    = "timers",
+         .parent  = &clk_p,
+         .ctrlbit = S3C2410_CLKCON_PWMT
+       },
+       { .name    = "sdi",
+         .parent  = &clk_p,
+         .ctrlbit = S3C2410_CLKCON_SDI
+       },
+       { .name    = "uart0",
+         .parent  = &clk_p,
+         .ctrlbit = S3C2410_CLKCON_UART0
+       },
+       { .name    = "uart1",
+         .parent  = &clk_p,
+         .ctrlbit = S3C2410_CLKCON_UART1
+       },
+       { .name    = "uart2",
+         .parent  = &clk_p,
+         .ctrlbit = S3C2410_CLKCON_UART2
+       },
+       { .name    = "gpio",
+         .parent  = &clk_p,
+         .ctrlbit = S3C2410_CLKCON_GPIO
+       },
+       { .name    = "rtc",
+         .parent  = &clk_p,
+         .ctrlbit = S3C2410_CLKCON_RTC
+       },
+       { .name    = "adc",
+         .parent  = &clk_p,
+         .ctrlbit = S3C2410_CLKCON_ADC
+       },
+       { .name    = "i2c",
+         .parent  = &clk_p,
+         .ctrlbit = S3C2410_CLKCON_IIC
+       },
+       { .name    = "iis",
+         .parent  = &clk_p,
+         .ctrlbit = S3C2410_CLKCON_IIS
+       },
+       { .name    = "spi",
+         .parent  = &clk_p,
+         .ctrlbit = S3C2410_CLKCON_SPI
+       },
+       { .name    = "watchdog",
+         .parent  = &clk_p,
+         .ctrlbit = 0
+       }
+};
+
+/* initialise the clock system */
+
+int s3c2410_register_clock(struct clk *clk)
+{
+       clk->owner = THIS_MODULE;
+       atomic_set(&clk->used, 0);
+
+       /* add to the list of available clocks */
+
+       down(&clocks_sem);
+       list_add(&clk->list, &clocks);
+       up(&clocks_sem);
+
+       return 0;
+}
+
+/* initalise all the clocks */
+
+static int __init s3c2410_init_clocks(void)
+{
+       struct clk *clkp = init_clocks;
+       int ptr;
+       int ret;
+
+       printk(KERN_INFO "S3C2410 Clock control, (c) 2004 Simtec Electronics\n");
+
+       /* initialise the main system clocks */
+
+       clk_h.rate = s3c2410_hclk;
+       clk_p.rate = s3c2410_pclk;
+       clk_f.rate = s3c2410_fclk;
+
+       /* set the enabled clocks to a minimal (known) state */
+       __raw_writel(S3C2410_CLKCON_PWMT | S3C2410_CLKCON_UART0 | S3C2410_CLKCON_UART1 | S3C2410_CLKCON_UART2 | S3C2410_CLKCON_GPIO | S3C2410_CLKCON_RTC, S3C2410_CLKCON);
+
+       /* register our clocks */
+
+       if (s3c2410_register_clock(&clk_f) < 0)
+               printk(KERN_ERR "failed to register cpu fclk\n");
+
+       if (s3c2410_register_clock(&clk_h) < 0)
+               printk(KERN_ERR "failed to register cpu hclk\n");
+
+       if (s3c2410_register_clock(&clk_p) < 0)
+               printk(KERN_ERR "failed to register cpu pclk\n");
+
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+               ret = s3c2410_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+       }
+
+       return 0;
+}
+
+arch_initcall(s3c2410_init_clocks);
+
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
new file mode 100644 (file)
index 0000000..4c7b94e
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * linux/arch/arm/mach-s3c2410/clock.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Written by Ben Dooks, <ben@simtec.co.uk>
+ *
+ * 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.
+*/
+
+struct clk {
+       struct list_head      list;
+       struct module        *owner;
+       struct clk           *parent;
+       const char           *name;
+       atomic_t              used;
+       unsigned long         rate;
+       unsigned long         ctrlbit;
+};
diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
new file mode 100644 (file)
index 0000000..42eec79
--- /dev/null
@@ -0,0 +1,152 @@
+/* linux/arch/arm/mach-s3c2410/cpu.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX CPU Support
+ *
+ * This program is free software; you can redistribute 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/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/regs-gpio.h>
+
+#include "cpu.h"
+#include "s3c2410.h"
+#include "s3c2440.h"
+
+struct cpu_table {
+       unsigned long   idcode;
+       unsigned long   idmask;
+       void            (*map_io)(struct map_desc *mach_desc, int size);
+       int             (*init)(void);
+       const char      *name;
+};
+
+/* table of supported CPUs */
+
+static const char name_s3c2410[]  = "S3C2410";
+static const char name_s3c2440[]  = "S3C2440";
+static const char name_s3c2410a[] = "S3C2410A";
+static const char name_s3c2440a[] = "S3C2440A";
+
+static struct cpu_table cpu_ids[] __initdata = {
+       {
+               .idcode = 0x32410000,
+               .idmask = 0xffffffff,
+               .map_io = s3c2410_map_io,
+               .init   = s3c2410_init,
+               .name   = name_s3c2410
+       },
+       {
+               .idcode = 0x3241002,
+               .idmask = 0xffffffff,
+               .map_io = s3c2410_map_io,
+               .init   = s3c2410_init,
+               .name   = name_s3c2410a
+       },
+       {
+               .idcode = 0x32440000,
+               .idmask = 0xffffffff,
+               .map_io = s3c2440_map_io,
+               .init   = s3c2440_init,
+               .name   = name_s3c2440
+       },
+       {
+               .idcode = 0x32440001,
+               .idmask = 0xffffffff,
+               .map_io = s3c2440_map_io,
+               .init   = s3c2440_init,
+               .name   = name_s3c2440a
+       }
+};
+
+/* minimal IO mapping */
+
+static struct map_desc s3c_iodesc[] __initdata = {
+       IODESC_ENT(GPIO),
+       IODESC_ENT(IRQ),
+       IODESC_ENT(MEMCTRL),
+       IODESC_ENT(UART)
+};
+
+
+static struct cpu_table *
+s3c_lookup_cpu(unsigned long idcode)
+{
+       struct cpu_table *tab;
+       int count;
+
+       tab = cpu_ids;
+       for (count = 0; count < ARRAY_SIZE(cpu_ids); count++) {
+               if ((idcode & tab->idmask) == tab->idcode)
+                       return tab;
+       }
+
+       return NULL;
+}
+
+static struct cpu_table *cpu;
+
+void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
+{
+       unsigned long idcode;
+
+       /* initialise the io descriptors we need for initialisation */
+       iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
+
+       idcode = __raw_readl(S3C2410_GSTATUS1);
+       cpu = s3c_lookup_cpu(idcode);
+
+       if (cpu == NULL) {
+               printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode);
+               panic("Unknown S3C24XX CPU");
+       }
+
+       if (cpu->map_io == NULL || cpu->init == NULL) {
+               printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
+               panic("Unsupported S3C24XX CPU");
+       }
+
+       printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
+
+       (cpu->map_io)(mach_desc, size);
+}
+
+static int __init s3c_arch_init(void)
+{
+       // do the correct init for cpu
+
+       if (cpu == NULL)
+               panic("s3c_arch_init: NULL cpu\n");
+
+       return (cpu->init)();
+}
+
+arch_initcall(s3c_arch_init);
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
new file mode 100644 (file)
index 0000000..b0053d7
--- /dev/null
@@ -0,0 +1,41 @@
+/* arch/arm/mach-s3c2410/cpu.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU support
+ *
+ * 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.
+ *
+ * Modifications:
+ *     24-Aug-2004 BJD  Start of generic S3C24XX support
+*/
+
+#define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE }
+
+#ifndef MHZ
+#define MHZ (1000*1000)
+#endif
+
+#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
+
+#ifdef CONFIG_CPU_S3C2410
+extern  int s3c2410_init(void);
+extern void s3c2410_map_io(struct map_desc *mach_desc, int size);
+#else
+#define s3c2410_map_io NULL
+#define s3c2410_init NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2440
+extern  int s3c2440_init(void);
+extern void s3c2440_map_io(struct map_desc *mach_desc, int size);
+#else
+#define s3c2440_map_io NULL
+#define s3c2440_init NULL
+#endif
+
+extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
+
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
new file mode 100644 (file)
index 0000000..7cf560c
--- /dev/null
@@ -0,0 +1,442 @@
+/* linux/arch/arm/mach-s3c2410/devs.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Base S3C2410 platform device definitions
+ *
+ * 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.
+ *
+ * Modifications:
+ *     29-Aug-2004 BJD  Added timers 0 through 3
+ *     29-Aug-2004 BJD  Changed index of devices we only have one of to -1
+ *     21-Aug-2004 BJD  Added IRQ_TICK to RTC resources
+ *     18-Aug-2004 BJD  Created initial version
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "devs.h"
+
+/* USB Host Controller */
+
+static struct resource s3c_usb_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_USBHOST,
+               .end   = S3C2410_PA_USBHOST + S3C2410_SZ_USBHOST,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_USBH,
+               .end   = IRQ_USBH,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static u64 s3c_device_usb_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb = {
+       .name             = "s3c2410-ohci",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s3c_usb_resource),
+       .resource         = s3c_usb_resource,
+       .dev              = {
+               .dma_mask = &s3c_device_usb_dmamask,
+               .coherent_dma_mask = 0xffffffffUL
+       }
+};
+
+EXPORT_SYMBOL(s3c_device_usb);
+
+/* LCD Controller */
+
+static struct resource s3c_lcd_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_LCD,
+               .end   = S3C2410_PA_LCD + S3C2410_SZ_LCD,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_LCD,
+               .end   = IRQ_LCD,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_lcd = {
+       .name             = "s3c2410-lcd",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s3c_lcd_resource),
+       .resource         = s3c_lcd_resource,
+       .dev              = {
+               .dma_mask = &s3c_device_lcd_dmamask,
+               .coherent_dma_mask = 0xffffffffUL
+       }
+};
+
+EXPORT_SYMBOL(s3c_device_lcd);
+
+/* NAND Controller */
+
+static struct resource s3c_nand_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_NAND,
+               .end   = S3C2410_PA_NAND + S3C2410_SZ_NAND,
+               .flags = IORESOURCE_MEM,
+       }
+};
+
+struct platform_device s3c_device_nand = {
+       .name             = "s3c2410-nand",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s3c_nand_resource),
+       .resource         = s3c_nand_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_nand);
+
+/* USB Device (Gadget)*/
+
+static struct resource s3c_usbgadget_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_USBDEV,
+               .end   = S3C2410_PA_USBDEV + S3C2410_SZ_USBDEV,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_USBD,
+               .end   = IRQ_USBD,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+struct platform_device s3c_device_usbgadget = {
+       .name             = "s3c2410-usbgadget",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s3c_usbgadget_resource),
+       .resource         = s3c_usbgadget_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_usbgadget);
+
+/* Watchdog */
+
+static struct resource s3c_wdt_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_WATCHDOG,
+               .end   = S3C2410_PA_WATCHDOG + S3C2410_SZ_WATCHDOG,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_WDT,
+               .end   = IRQ_WDT,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+struct platform_device s3c_device_wdt = {
+       .name             = "s3c2410-wdt",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s3c_wdt_resource),
+       .resource         = s3c_wdt_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_wdt);
+
+/* I2C */
+
+static struct resource s3c_i2c_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_IIC,
+               .end   = S3C2410_PA_IIC + S3C2410_SZ_IIC,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_IIC,
+               .end   = IRQ_IIC,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+struct platform_device s3c_device_i2c = {
+       .name             = "s3c2410-i2c",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s3c_i2c_resource),
+       .resource         = s3c_i2c_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_i2c);
+
+/* IIS */
+
+static struct resource s3c_iis_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_IIS,
+               .end   = S3C2410_PA_IIS + S3C2410_SZ_IIS,
+               .flags = IORESOURCE_MEM,
+       }
+};
+
+static u64 s3c_device_iis_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_iis = {
+       .name             = "s3c2410-iis",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s3c_iis_resource),
+       .resource         = s3c_iis_resource,
+       .dev              = {
+               .dma_mask = &s3c_device_iis_dmamask,
+               .coherent_dma_mask = 0xffffffffUL
+       }
+};
+
+EXPORT_SYMBOL(s3c_device_iis);
+
+/* RTC */
+
+static struct resource s3c_rtc_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_RTC,
+               .end   = S3C2410_PA_RTC + 0xff,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_RTC,
+               .end   = IRQ_RTC,
+               .flags = IORESOURCE_IRQ,
+       },
+       [2] = {
+               .start = IRQ_TICK,
+               .end   = IRQ_TICK,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+struct platform_device s3c_device_rtc = {
+       .name             = "s3c2410-rtc",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s3c_rtc_resource),
+       .resource         = s3c_rtc_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_rtc);
+
+/* ADC */
+
+static struct resource s3c_adc_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_ADC,
+               .end   = S3C2410_PA_ADC + S3C2410_SZ_ADC,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_TC,
+               .end   = IRQ_ADC,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+struct platform_device s3c_device_adc = {
+       .name             = "s3c2410-adc",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s3c_adc_resource),
+       .resource         = s3c_adc_resource,
+};
+
+/* SDI */
+
+static struct resource s3c_sdi_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_SDI,
+               .end   = S3C2410_PA_SDI + S3C2410_SZ_SDI,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_SDI,
+               .end   = IRQ_SDI,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+struct platform_device s3c_device_sdi = {
+       .name             = "s3c2410-sdi",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s3c_sdi_resource),
+       .resource         = s3c_sdi_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_sdi);
+
+/* SPI (0) */
+
+static struct resource s3c_spi0_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_SPI,
+               .end   = S3C2410_PA_SPI + 0x1f,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_SPI0,
+               .end   = IRQ_SPI0,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+struct platform_device s3c_device_spi0 = {
+       .name             = "s3c2410-spi",
+       .id               = 0,
+       .num_resources    = ARRAY_SIZE(s3c_spi0_resource),
+       .resource         = s3c_spi0_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_spi0);
+
+/* SPI (1) */
+
+static struct resource s3c_spi1_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_SPI + 0x20,
+               .end   = S3C2410_PA_SPI + 0x20 + 0x1f,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_SPI1,
+               .end   = IRQ_SPI1,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+struct platform_device s3c_device_spi1 = {
+       .name             = "s3c2410-spi",
+       .id               = 1,
+       .num_resources    = ARRAY_SIZE(s3c_spi1_resource),
+       .resource         = s3c_spi1_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_spi1);
+
+/* pwm timer blocks */
+
+static struct resource s3c_timer0_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_TIMER + 0x0C,
+               .end   = S3C2410_PA_TIMER + 0x0C + 0xB,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_TIMER0,
+               .end   = IRQ_TIMER0,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+struct platform_device s3c_device_timer0 = {
+       .name             = "s3c2410-timer",
+       .id               = 0,
+       .num_resources    = ARRAY_SIZE(s3c_timer0_resource),
+       .resource         = s3c_timer0_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer0);
+
+/* timer 1 */
+
+static struct resource s3c_timer1_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_TIMER + 0x18,
+               .end   = S3C2410_PA_TIMER + 0x23,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_TIMER1,
+               .end   = IRQ_TIMER1,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+struct platform_device s3c_device_timer1 = {
+       .name             = "s3c2410-timer",
+       .id               = 1,
+       .num_resources    = ARRAY_SIZE(s3c_timer1_resource),
+       .resource         = s3c_timer1_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer1);
+
+/* timer 2 */
+
+static struct resource s3c_timer2_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_TIMER + 0x24,
+               .end   = S3C2410_PA_TIMER + 0x2F,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_TIMER2,
+               .end   = IRQ_TIMER2,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+struct platform_device s3c_device_timer2 = {
+       .name             = "s3c2410-timer",
+       .id               = 2,
+       .num_resources    = ARRAY_SIZE(s3c_timer2_resource),
+       .resource         = s3c_timer2_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer2);
+
+/* timer 3 */
+
+static struct resource s3c_timer3_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_TIMER + 0x30,
+               .end   = S3C2410_PA_TIMER + 0x3B,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_TIMER3,
+               .end   = IRQ_TIMER3,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+struct platform_device s3c_device_timer3 = {
+       .name             = "s3c2410-timer",
+       .id               = 3,
+       .num_resources    = ARRAY_SIZE(s3c_timer3_resource),
+       .resource         = s3c_timer3_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer3);
diff --git a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h
new file mode 100644 (file)
index 0000000..08a4416
--- /dev/null
@@ -0,0 +1,36 @@
+/* arch/arm/mach-s3c2410/devs.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2410 standard platform devices
+ *
+ * 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.
+ *
+ * Modifications:
+ *      18-Aug-2004 BJD  Created initial version
+ *     27-Aug-2004 BJD  Added timers 0 through 3
+*/
+
+extern struct platform_device s3c_device_usb;
+extern struct platform_device s3c_device_lcd;
+extern struct platform_device s3c_device_wdt;
+extern struct platform_device s3c_device_i2c;
+extern struct platform_device s3c_device_iis;
+extern struct platform_device s3c_device_rtc;
+extern struct platform_device s3c_device_adc;
+extern struct platform_device s3c_device_sdi;
+
+extern struct platform_device s3c_device_spi0;
+extern struct platform_device s3c_device_spi1;
+
+extern struct platform_device s3c_device_nand;
+
+extern struct platform_device s3c_device_timer0;
+extern struct platform_device s3c_device_timer1;
+extern struct platform_device s3c_device_timer2;
+extern struct platform_device s3c_device_timer3;
+
+extern struct platform_device s3c_device_usbgadget;
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
new file mode 100644 (file)
index 0000000..819e5af
--- /dev/null
@@ -0,0 +1,1085 @@
+/* linux/arch/arm/mach-bast/dma.c
+ *
+ * (c) 2003,2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 DMA core
+ *
+ * http://www.simtec.co.uk/products/EB2410ITX/
+ *
+ * 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.
+ *
+ * Changelog:
+ *  08-Aug-2004 BJD  Apply rmk's suggestions
+ *  21-Jul-2004 BJD  Ported to linux 2.6
+ *  12-Jul-2004 BJD  Finished re-write and change of API
+ *  06-Jul-2004 BJD  Rewrote dma code to try and cope with various problems
+ *  23-May-2003 BJD  Created file
+ *  19-Aug-2003 BJD  Cleanup, header fix, added URL
+ *
+ * This file is based on the Sangwook Lee/Samsung patches, re-written due
+ * to various ommisions from the code (such as flexible dma configuration)
+ * for use with the BAST system board.
+ *
+ * The re-write is pretty much complete, and should be good enough for any
+ * possible DMA function
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <asm/mach/dma.h>
+#include <asm/arch/map.h>
+
+/* io map for dma */
+static void *dma_base;
+
+/* dma channel state information */
+s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS];
+
+/* debugging functions */
+
+#define BUF_MAGIC (0xcafebabe)
+
+#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
+
+#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
+
+#if 1
+#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
+#else
+static inline void
+dma_wrreg(s3c2410_dma_chan_t *chan, int reg, unsigned long val)
+{
+       pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
+       writel(val, dma_regaddr(chan, reg));
+}
+
+#endif
+
+#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
+
+/* captured register state for debug */
+
+struct s3c2410_dma_regstate {
+       unsigned long         dcsrc;
+       unsigned long         disrc;
+       unsigned long         dstat;
+       unsigned long         dcon;
+       unsigned long         dmsktrig;
+};
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+
+/* dmadbg_showregs
+ *
+ * simple debug routine to print the current state of the dma registers
+*/
+
+static void
+dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs)
+{
+       regs->dcsrc    = dma_rdreg(chan, S3C2410_DMA_DCSRC);
+       regs->disrc    = dma_rdreg(chan, S3C2410_DMA_DISRC);
+       regs->dstat    = dma_rdreg(chan, S3C2410_DMA_DSTAT);
+       regs->dcon     = dma_rdreg(chan, S3C2410_DMA_DCON);
+       regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+}
+
+static void
+dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan,
+                struct s3c2410_dma_regstate *regs)
+{
+       printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
+              chan->number, fname, line,
+              regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
+              regs->dcon);
+}
+
+static void
+dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan)
+{
+       struct s3c2410_dma_regstate state;
+
+       dmadbg_capture(chan, &state);
+
+       printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
+              chan->number, fname, line, chan->load_state,
+              chan->curr, chan->next, chan->end);
+
+       dmadbg_showregs(fname, line, chan, &state);
+}
+
+#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
+#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
+#else
+#define dbg_showregs(chan) do { } while(0)
+#define dbg_showchan(chan) do { } while(0)
+#endif /* CONFIG_S3C2410_DMA_DEBUG */
+
+#define check_channel(chan) \
+  do { if ((chan) >= S3C2410_DMA_CHANNELS) { \
+    printk(KERN_ERR "%s: invalid channel %d\n", __FUNCTION__, (chan)); \
+    return -EINVAL; \
+  } } while(0)
+
+
+/* s3c2410_dma_stats_timeout
+ *
+ * Update DMA stats from timeout info
+*/
+
+static void
+s3c2410_dma_stats_timeout(s3c2410_dma_stats_t *stats, int val)
+{
+       if (stats == NULL)
+               return;
+
+       if (val > stats->timeout_longest)
+               stats->timeout_longest = val;
+       if (val < stats->timeout_shortest)
+               stats->timeout_shortest = val;
+
+       stats->timeout_avg += val;
+}
+
+/* s3c2410_dma_waitforload
+ *
+ * wait for the DMA engine to load a buffer, and update the state accordingly
+*/
+
+static int
+s3c2410_dma_waitforload(s3c2410_dma_chan_t *chan, int line)
+{
+       int timeout = chan->load_timeout;
+       int took;
+
+       if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
+               printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
+               return 0;
+       }
+
+       if (chan->stats != NULL)
+               chan->stats->loads++;
+
+       while (--timeout > 0) {
+               if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
+                       took = chan->load_timeout - timeout;
+
+                       s3c2410_dma_stats_timeout(chan->stats, took);
+
+                       switch (chan->load_state) {
+                       case S3C2410_DMALOAD_1LOADED:
+                               chan->load_state = S3C2410_DMALOAD_1RUNNING;
+                               break;
+
+                       default:
+                               printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
+                       }
+
+                       return 1;
+               }
+       }
+
+       if (chan->stats != NULL) {
+               chan->stats->timeout_failed++;
+       }
+
+       return 0;
+}
+
+
+
+/* s3c2410_dma_loadbuffer
+ *
+ * load a buffer, and update the channel state
+*/
+
+static inline int
+s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan,
+                      s3c2410_dma_buf_t *buf)
+{
+       unsigned long reload;
+
+       pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
+                buf, (unsigned long)buf->data, buf->size);
+
+       if (buf == NULL) {
+               dmawarn("buffer is NULL\n");
+               return -EINVAL;
+       }
+
+       /* check the state of the channel before we do anything */
+
+       if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+               dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
+       }
+
+       if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
+               dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
+       }
+
+       /* it would seem sensible if we are the last buffer to not bother
+        * with the auto-reload bit, so that the DMA engine will not try
+        * and load another transfer after this one has finished...
+        */
+       if (chan->load_state == S3C2410_DMALOAD_NONE) {
+               pr_debug("load_state is none, checking for noreload (next=%p)\n",
+                        buf->next);
+               reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
+       } else {
+               pr_debug("load_state is %d => autoreload\n", chan->load_state);
+               reload = S3C2410_DCON_AUTORELOAD;
+       }
+
+       writel(buf->data, chan->addr_reg);
+
+       dma_wrreg(chan, S3C2410_DMA_DCON,
+                 chan->dcon | reload | (buf->size/chan->xfer_unit));
+
+       chan->next = buf->next;
+
+       /* update the state of the channel */
+
+       switch (chan->load_state) {
+       case S3C2410_DMALOAD_NONE:
+               chan->load_state = S3C2410_DMALOAD_1LOADED;
+               break;
+
+       case S3C2410_DMALOAD_1RUNNING:
+               chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
+               break;
+
+       default:
+               dmawarn("dmaload: unknown state %d in loadbuffer\n",
+                       chan->load_state);
+               break;
+       }
+
+       return 0;
+}
+
+/* s3c2410_dma_call_op
+ *
+ * small routine to call the op routine with the given op if it has been
+ * registered
+*/
+
+static void
+s3c2410_dma_call_op(s3c2410_dma_chan_t *chan, s3c2410_chan_op_t op)
+{
+       if (chan->op_fn != NULL) {
+               (chan->op_fn)(chan, op);
+       }
+}
+
+/* s3c2410_dma_buffdone
+ *
+ * small wrapper to check if callback routine needs to be called, and
+ * if so, call it
+*/
+
+static inline void
+s3c2410_dma_buffdone(s3c2410_dma_chan_t *chan, s3c2410_dma_buf_t *buf,
+                    s3c2410_dma_buffresult_t result)
+{
+       pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
+                chan->callback_fn, buf, buf->id, buf->size, result);
+
+       if (chan->callback_fn != NULL) {
+               (chan->callback_fn)(chan, buf->id, buf->size, result);
+       }
+}
+
+/* s3c2410_dma_start
+ *
+ * start a dma channel going
+*/
+
+static int s3c2410_dma_start(s3c2410_dma_chan_t *chan)
+{
+       unsigned long tmp;
+       unsigned long flags;
+
+       pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
+
+       local_irq_save(flags);
+
+       if (chan->state == S3C2410_DMA_RUNNING) {
+               pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
+               local_irq_restore(flags);
+               return 0;
+       }
+
+       chan->state = S3C2410_DMA_RUNNING;
+
+       /* check wether there is anything to load, and if not, see
+        * if we can find anything to load
+        */
+
+       if (chan->load_state == S3C2410_DMALOAD_NONE) {
+               if (chan->next == NULL) {
+                       printk(KERN_ERR "dma%d: channel has nothing loaded\n",
+                              chan->number);
+                       chan->state = S3C2410_DMA_IDLE;
+                       local_irq_restore(flags);
+                       return -EINVAL;
+               }
+
+               s3c2410_dma_loadbuffer(chan, chan->next);
+       }
+
+       dbg_showchan(chan);
+
+       /* enable the channel */
+
+       if (!chan->irq_enabled) {
+               enable_irq(chan->irq);
+               chan->irq_enabled = 1;
+       }
+
+       /* start the channel going */
+
+       tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+       tmp &= ~S3C2410_DMASKTRIG_STOP;
+       tmp |= S3C2410_DMASKTRIG_ON;
+       dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+       pr_debug("wrote %08lx to DMASKTRIG\n", tmp);
+
+#if 0
+       /* the dma buffer loads should take care of clearing the AUTO
+        * reloading feature */
+       tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+       tmp &= ~S3C2410_DCON_NORELOAD;
+       dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+       s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
+
+       dbg_showchan(chan);
+
+       local_irq_restore(flags);
+       return 0;
+}
+
+/* s3c2410_dma_canload
+ *
+ * work out if we can queue another buffer into the DMA engine
+*/
+
+static int
+s3c2410_dma_canload(s3c2410_dma_chan_t *chan)
+{
+       if (chan->load_state == S3C2410_DMALOAD_NONE ||
+           chan->load_state == S3C2410_DMALOAD_1RUNNING)
+               return 1;
+
+       return 0;
+}
+
+
+/* s3c2410_dma_enqueue
+ *
+ * queue an given buffer for dma transfer.
+ *
+ * id         the device driver's id information for this buffer
+ * data       the physical address of the buffer data
+ * size       the size of the buffer in bytes
+ *
+ * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
+ * is checked, and if set, the channel is started. If this flag isn't set,
+ * then an error will be returned.
+ *
+ * It is possible to queue more than one DMA buffer onto a channel at
+ * once, and the code will deal with the re-loading of the next buffer
+ * when necessary.
+*/
+
+int s3c2410_dma_enqueue(unsigned int channel, void *id,
+                       dma_addr_t data, int size)
+{
+       s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+       s3c2410_dma_buf_t *buf;
+       unsigned long flags;
+
+       check_channel(channel);
+
+       pr_debug("%s: id=%p, data=%08x, size=%d\n",
+                __FUNCTION__, id, (unsigned int)data, size);
+
+       buf = (s3c2410_dma_buf_t *)kmalloc(sizeof(*buf), GFP_ATOMIC);
+       if (buf == NULL) {
+               pr_debug("%s: out of memory (%d alloc)\n",
+                        __FUNCTION__, sizeof(*buf));
+               return -ENOMEM;
+       }
+
+       pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
+
+       //dbg_showchan(chan);
+
+       buf->next  = NULL;
+       buf->data  = buf->ptr = data;
+       buf->size  = size;
+       buf->id    = id;
+       buf->magic = BUF_MAGIC;
+
+       local_irq_save(flags);
+
+       if (chan->curr == NULL) {
+               /* we've got nothing loaded... */
+               pr_debug("%s: buffer %p queued onto empty channel\n",
+                        __FUNCTION__, buf);
+
+               chan->curr = buf;
+               chan->end  = buf;
+               chan->next = NULL;
+       } else {
+               pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
+                        chan->number, __FUNCTION__, buf);
+
+               if (chan->end == NULL)
+                       pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
+                                chan->number, __FUNCTION__, chan);
+
+               chan->end->next = buf;
+               chan->end = buf;
+       }
+
+       /* if necessary, update the next buffer field */
+       if (chan->next == NULL)
+               chan->next = buf;
+
+       /* check to see if we can load a buffer */
+       if (chan->state == S3C2410_DMA_RUNNING) {
+               if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
+                       if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+                               printk(KERN_ERR "dma%d: loadbuffer:"
+                                      "timeout loading buffer\n",
+                                      chan->number);
+                               dbg_showchan(chan);
+                               local_irq_restore(flags);
+                               return -EINVAL;
+                       }
+               }
+
+               while (s3c2410_dma_canload(chan) && chan->next != NULL) {
+                       s3c2410_dma_loadbuffer(chan, chan->next);
+               }
+       } else if (chan->state == S3C2410_DMA_IDLE) {
+               if (chan->flags & S3C2410_DMAF_AUTOSTART) {
+                       s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
+               } else {
+                       printk(KERN_DEBUG "dma%d: cannot load onto stopped channel'n", chan->number);
+                       local_irq_restore(flags);
+                       return -EINVAL;
+               }
+       }
+
+       local_irq_restore(flags);
+       return 0;
+}
+
+static inline void
+s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf)
+{
+       int magicok = (buf->magic == BUF_MAGIC);
+
+       buf->magic = -1;
+
+       if (magicok) {
+               kfree(buf);
+       } else {
+               printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
+       }
+}
+
+/* s3c2410_dma_lastxfer
+ *
+ * called when the system is out of buffers, to ensure that the channel
+ * is prepared for shutdown.
+*/
+
+static inline void
+s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan)
+{
+       pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
+                chan->number, chan->load_state);
+
+       switch (chan->load_state) {
+       case S3C2410_DMALOAD_NONE:
+               break;
+
+       case S3C2410_DMALOAD_1LOADED:
+               if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+                               /* flag error? */
+                       printk(KERN_ERR "dma%d: timeout waiting for load\n",
+                              chan->number);
+                       return;
+               }
+               break;
+
+       default:
+               pr_debug("dma%d: lastxfer: unhandled load_state %d with no next",
+                        chan->number, chan->load_state);
+               return;
+
+       }
+
+       /* hopefully this'll shut the damned thing up after the transfer... */
+       dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
+}
+
+
+#define dmadbg2(x...)
+
+static irqreturn_t
+s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
+{
+       s3c2410_dma_chan_t *chan = (s3c2410_dma_chan_t *)devpw;
+       s3c2410_dma_buf_t  *buf;
+
+       buf = chan->curr;
+
+       dbg_showchan(chan);
+
+       /* modify the channel state */
+
+       switch (chan->load_state) {
+       case S3C2410_DMALOAD_1RUNNING:
+               /* TODO - if we are running only one buffer, we probably
+                * want to reload here, and then worry about the buffer
+                * callback */
+
+               chan->load_state = S3C2410_DMALOAD_NONE;
+               break;
+
+       case S3C2410_DMALOAD_1LOADED:
+               /* iirc, we should go back to NONE loaded here, we
+                * had a buffer, and it was never verified as being
+                * loaded.
+                */
+
+               chan->load_state = S3C2410_DMALOAD_NONE;
+               break;
+
+       case S3C2410_DMALOAD_1LOADED_1RUNNING:
+               /* we'll worry about checking to see if another buffer is
+                * ready after we've called back the owner. This should
+                * ensure we do not wait around too long for the DMA
+                * engine to start the next transfer
+                */
+
+               chan->load_state = S3C2410_DMALOAD_1LOADED;
+               break;
+
+       case S3C2410_DMALOAD_NONE:
+               printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
+                      chan->number);
+               break;
+
+       default:
+               printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
+                      chan->number, chan->load_state);
+               break;
+       }
+
+       if (buf != NULL) {
+               /* update the chain to make sure that if we load any more
+                * buffers when we call the callback function, things should
+                * work properly */
+
+               chan->curr = buf->next;
+               buf->next  = NULL;
+
+               if (buf->magic != BUF_MAGIC) {
+                       printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
+                              chan->number, __FUNCTION__, buf);
+                       return IRQ_HANDLED;
+               }
+
+               s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
+
+               /* free resouces */
+               s3c2410_dma_freebuf(buf);
+       } else {
+       }
+
+       if (chan->next != NULL) {
+               unsigned long flags;
+
+               switch (chan->load_state) {
+               case S3C2410_DMALOAD_1RUNNING:
+                       /* don't need to do anything for this state */
+                       break;
+
+               case S3C2410_DMALOAD_NONE:
+                       /* can load buffer immediately */
+                       break;
+
+               case S3C2410_DMALOAD_1LOADED:
+                       if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+                               /* flag error? */
+                               printk(KERN_ERR "dma%d: timeout waiting for load\n",
+                                      chan->number);
+                               return IRQ_HANDLED;
+                       }
+
+                       break;
+
+               default:
+                       printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
+                              chan->number, chan->load_state);
+                       return IRQ_HANDLED;
+               }
+
+               local_irq_save(flags);
+               s3c2410_dma_loadbuffer(chan, chan->next);
+               local_irq_restore(flags);
+       } else {
+               s3c2410_dma_lastxfer(chan);
+
+               /* see if we can stop this channel.. */
+               if (chan->load_state == S3C2410_DMALOAD_NONE) {
+                       pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
+                                chan->number, jiffies);
+                       s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+
+
+/* s3c2410_request_dma
+ *
+ * get control of an dma channel
+*/
+
+int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client,
+                       void *dev)
+{
+       s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+       unsigned long flags;
+       int err;
+
+       pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
+                channel, client->name, dev);
+
+       check_channel(channel);
+
+       local_irq_save(flags);
+
+       dbg_showchan(chan);
+
+       if (chan->in_use) {
+               if (client != chan->client) {
+                       printk(KERN_ERR "dma%d: already in use\n", channel);
+                       local_irq_restore(flags);
+                       return -EBUSY;
+               } else {
+                       printk(KERN_ERR "dma%d: client already has channel\n", channel);
+               }
+       }
+
+       chan->client = client;
+       chan->in_use = 1;
+
+       if (!chan->irq_claimed) {
+               pr_debug("dma%d: %s : requesting irq %d\n",
+                        channel, __FUNCTION__, chan->irq);
+
+               err = request_irq(chan->irq, s3c2410_dma_irq, SA_INTERRUPT,
+                                 client->name, (void *)chan);
+
+               if (err) {
+                       chan->in_use = 0;
+                       local_irq_restore(flags);
+
+                       printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
+                              client->name, chan->irq, chan->number);
+                       return err;
+               }
+
+               chan->irq_claimed = 1;
+               chan->irq_enabled = 1;
+       }
+
+       local_irq_restore(flags);
+
+       /* need to setup */
+
+       pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
+
+       return 0;
+}
+
+/* s3c2410_dma_free
+ *
+ * release the given channel back to the system, will stop and flush
+ * any outstanding transfers, and ensure the channel is ready for the
+ * next claimant.
+ *
+ * Note, although a warning is currently printed if the freeing client
+ * info is not the same as the registrant's client info, the free is still
+ * allowed to go through.
+*/
+
+int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client)
+{
+       s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+       unsigned long flags;
+
+       check_channel(channel);
+
+       local_irq_save(flags);
+
+
+       if (chan->client != client) {
+               printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
+                      channel, chan->client, client);
+       }
+
+       /* sort out stopping and freeing the channel */
+
+       if (chan->state != S3C2410_DMA_IDLE) {
+               pr_debug("%s: need to stop dma channel %p\n",
+                      __FUNCTION__, chan);
+
+               /* possibly flush the channel */
+               s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
+       }
+
+       chan->client = NULL;
+       chan->in_use = 0;
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
+{
+       unsigned long tmp;
+       unsigned long flags;
+
+       pr_debug("%s:\n", __FUNCTION__);
+
+       dbg_showchan(chan);
+
+       local_irq_save(flags);
+
+       s3c2410_dma_call_op(chan,  S3C2410_DMAOP_STOP);
+
+       tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+       tmp |= S3C2410_DMASKTRIG_STOP;
+       dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+#if 0
+       /* should also clear interrupts, according to WinCE BSP */
+       tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+       tmp |= S3C2410_DCON_NORELOAD;
+       dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+       chan->state      = S3C2410_DMA_IDLE;
+       chan->load_state = S3C2410_DMALOAD_NONE;
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+/* s3c2410_dma_flush
+ *
+ * stop the channel, and remove all current and pending transfers
+*/
+
+static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan)
+{
+       s3c2410_dma_buf_t *buf, *next;
+       unsigned long flags;
+
+       pr_debug("%s:\n", __FUNCTION__);
+
+       local_irq_save(flags);
+
+       if (chan->state != S3C2410_DMA_IDLE) {
+               pr_debug("%s: stopping channel...\n", __FUNCTION__ );
+               s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
+       }
+
+       buf = chan->curr;
+       if (buf == NULL)
+               buf = chan->next;
+
+       chan->curr = chan->next = chan->end = NULL;
+
+       if (buf != NULL) {
+               for ( ; buf != NULL; buf = next) {
+                       next = buf->next;
+
+                       pr_debug("%s: free buffer %p, next %p\n",
+                              __FUNCTION__, buf, buf->next);
+
+                       s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
+                       s3c2410_dma_freebuf(buf);
+               }
+       }
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+
+int
+s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op)
+{
+       s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+       check_channel(channel);
+
+       switch (op) {
+       case S3C2410_DMAOP_START:
+               return s3c2410_dma_start(chan);
+
+       case S3C2410_DMAOP_STOP:
+               return s3c2410_dma_dostop(chan);
+
+       case S3C2410_DMAOP_PAUSE:
+               return -ENOENT;
+
+       case S3C2410_DMAOP_RESUME:
+               return -ENOENT;
+
+       case S3C2410_DMAOP_FLUSH:
+               return s3c2410_dma_flush(chan);
+
+       case S3C2410_DMAOP_TIMEOUT:
+               return 0;
+
+       }
+
+       return -ENOENT;      /* unknown, don't bother */
+}
+
+
+/* DMA configuration for each channel
+ *
+ * DISRCC -> source of the DMA (AHB,APB)
+ * DISRC  -> source address of the DMA
+ * DIDSTC -> destination of the DMA (AHB,APD)
+ * DIDST  -> destination address of the DMA
+*/
+
+/* s3c2410_dma_config
+ *
+ * xfersize:     size of unit in bytes (1,2,4)
+ * dcon:         base value of the DCONx register
+*/
+
+int s3c2410_dma_config(dmach_t channel,
+                      int xferunit,
+                      int dcon)
+{
+       s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+       pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
+                __FUNCTION__, channel, xferunit, dcon);
+
+       check_channel(channel);
+
+       switch (xferunit) {
+       case 1:
+               dcon |= S3C2410_DCON_BYTE;
+               break;
+
+       case 2:
+               dcon |= S3C2410_DCON_HALFWORD;
+               break;
+
+       case 4:
+               dcon |= S3C2410_DCON_WORD;
+               break;
+
+       default:
+               pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
+               return -EINVAL;
+       }
+
+       dcon |= S3C2410_DCON_HWTRIG;
+       dcon |= S3C2410_DCON_INTREQ;
+
+       pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
+
+       chan->dcon = dcon;
+       chan->xfer_unit = xferunit;
+
+       return 0;
+}
+
+
+int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
+{
+       s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+       check_channel(channel);
+
+       pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
+
+       chan->flags = flags;
+
+       return 0;
+}
+
+/* do we need to protect the settings of the fields from
+ * irq?
+*/
+
+int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
+{
+       s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+       check_channel(channel);
+
+       pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
+
+       chan->op_fn = rtn;
+
+       return 0;
+}
+
+int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
+{
+       s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+       check_channel(channel);
+
+       pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
+
+       chan->callback_fn = rtn;
+
+       return 0;
+}
+
+/* s3c2410_dma_devconfig
+ *
+ * configure the dma source/destination hardware type and address
+ *
+ * source:    S3C2410_DMASRC_HW: source is hardware
+ *            S3C2410_DMASRC_MEM: source is memory
+ *
+ * hwcfg:     the value for xxxSTCn register,
+ *            bit 0: 0=increment pointer, 1=leave pointer
+ *            bit 1: 0=soucre is AHB, 1=soucre is APB
+ *
+ * devaddr:   physical address of the source
+*/
+
+int s3c2410_dma_devconfig(int channel,
+                         s3c2410_dmasrc_t source,
+                         int hwcfg,
+                         unsigned long devaddr)
+{
+       s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+       check_channel(channel);
+
+       pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
+                __FUNCTION__, (int)source, hwcfg, devaddr);
+
+       chan->source = source;
+       chan->dev_addr = devaddr;
+
+       switch (source) {
+       case S3C2410_DMASRC_HW:
+               /* source is hardware */
+               pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
+                        __FUNCTION__, devaddr, hwcfg);
+               dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
+               dma_wrreg(chan, S3C2410_DMA_DISRC,  devaddr);
+               dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
+
+               chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
+               return 0;
+
+       case S3C2410_DMASRC_MEM:
+               /* source is memory */
+               pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
+                         __FUNCTION__, devaddr, hwcfg);
+               dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
+               dma_wrreg(chan, S3C2410_DMA_DIDST,  devaddr);
+               dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
+
+               chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
+               return 0;
+       }
+
+       printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
+       return -EINVAL;
+}
+
+/* initialisation code */
+
+static int __init s3c2410_init_dma(void)
+{
+       int channel;
+       s3c2410_dma_chan_t *cp;
+
+       printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n");
+
+       dma_base = ioremap(S3C2410_PA_DMA, 0x200);
+       if (dma_base == NULL) {
+               printk(KERN_ERR "dma failed to remap register block\n");
+               return -ENOMEM;
+       }
+
+       for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
+               cp = &s3c2410_chans[channel];
+
+               memset(cp, 0, sizeof(s3c2410_dma_chan_t));
+
+               /* dma channel irqs are in order.. */
+               cp->number = channel;
+               cp->irq    = channel + IRQ_DMA0;
+               cp->regs   = (unsigned long)dma_base + (channel*0x40);
+
+               /* point current stats somewhere */
+               cp->stats  = &cp->stats_store;
+               cp->stats_store.timeout_shortest = LONG_MAX;
+
+               /* basic channel configuration */
+
+               cp->load_timeout = 1<<18;
+
+               printk("DMA channel %d at %08lx, irq %d\n",
+                      cp->number, cp->regs, cp->irq);
+       }
+
+       return 0;
+}
+
+__initcall(s3c2410_init_dma);
index 450b132..8996725 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
+ * Changelog
+ *     13-Sep-2004  BJD  Implemented change of MISCCR
+ *     14-Sep-2004  BJD  Added getpin call
+ *     14-Sep-2004  BJD  Fixed bug in setpin() call
+ *     30-Sep-2004  BJD  Fixed cfgpin() mask bug
+ *     01-Oct-2004  BJD  Added getcfg() to get pin configuration
+ *     01-Oct-2004  BJD  Fixed mask bug in pullup() call
+ *     01-Oct-2004  BJD  Added getirq() to turn pin into irqno
+ *     04-Oct-2004  BJD  Added irq filter controls for GPIO
  */
 
 
 void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
 {
        unsigned long base = S3C2410_GPIO_BASE(pin);
-       unsigned long shift = 1;
-       unsigned long mask = 3;
+       unsigned long mask;
        unsigned long con;
        unsigned long flags;
 
        if (pin < S3C2410_GPIO_BANKB) {
-               shift = 0;
-               mask  = 1;
+               mask = 1 << S3C2410_GPIO_OFFSET(pin);
+       } else {
+               mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
        }
 
-       mask <<= S3C2410_GPIO_OFFSET(pin);
-
        local_irq_save(flags);
 
-       con = __raw_readl(base + 0x00);
-
-       con &= mask << shift;
+       con  = __raw_readl(base + 0x00);
+       con &= ~mask;
        con |= function;
 
        __raw_writel(con, base + 0x00);
@@ -60,6 +66,20 @@ void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
        local_irq_restore(flags);
 }
 
+unsigned int s3c2410_gpio_getcfg(unsigned int pin)
+{
+       unsigned long base = S3C2410_GPIO_BASE(pin);
+       unsigned long mask;
+
+       if (pin < S3C2410_GPIO_BANKB) {
+               mask = 1 << S3C2410_GPIO_OFFSET(pin);
+       } else {
+               mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
+       }
+
+       return __raw_readl(base) & mask;
+}
+
 void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
 {
        unsigned long base = S3C2410_GPIO_BASE(pin);
@@ -73,7 +93,7 @@ void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
        local_irq_save(flags);
 
        up = __raw_readl(base + 0x08);
-       up &= 1 << offs;
+       up &= ~(1L << offs);
        up |= to << offs;
        __raw_writel(up, base + 0x08);
 
@@ -90,9 +110,85 @@ void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
        local_irq_save(flags);
 
        dat = __raw_readl(base + 0x04);
-       dat &= 1 << offs;
+       dat &= ~(1 << offs);
        dat |= to << offs;
        __raw_writel(dat, base + 0x04);
 
        local_irq_restore(flags);
 }
+
+unsigned int s3c2410_gpio_getpin(unsigned int pin)
+{
+       unsigned long base = S3C2410_GPIO_BASE(pin);
+       unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+
+       return __raw_readl(base + 0x04) & (1<< offs);
+}
+
+unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
+{
+       unsigned long flags;
+       unsigned long misccr;
+
+       local_irq_save(flags);
+       misccr = __raw_readl(S3C2410_MISCCR);
+       misccr &= ~clear;
+       misccr ^= change;
+       __raw_writel(misccr, S3C2410_MISCCR);
+       local_irq_restore(flags);
+
+       return misccr;
+}
+
+int s3c2410_gpio_getirq(unsigned int pin)
+{
+       if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23)
+               return -1;      /* not valid interrupts */
+
+       if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
+               return -1;      /* not valid pin */
+
+       if (pin < S3C2410_GPF4)
+               return (pin - S3C2410_GPF0) + IRQ_EINT0;
+
+       if (pin < S3C2410_GPG0)
+               return (pin - S3C2410_GPF4) + IRQ_EINT4;
+
+       return (pin - S3C2410_GPG0) + IRQ_EINT8;
+}
+
+int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+                          unsigned int config)
+{
+       unsigned long reg = S3C2410_EINFLT0;
+       unsigned long flags;
+       unsigned long val;
+
+       if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
+               return -1;
+
+       config &= 0xff;
+
+       pin -= S3C2410_GPG8_EINT16;
+       reg += pin & ~3;
+
+       local_irq_save(flags);
+
+       /* update filter width and clock source */
+
+       val = __raw_readl(reg);
+       val &= ~(0xff << ((pin & 3) * 8));
+       val |= config << ((pin & 3) * 8);
+       __raw_writel(val, reg);
+
+       /* update filter enable */
+
+       val = __raw_readl(S3C2410_EXTINT2);
+       val &= ~(1 << ((pin * 4) + 3));
+       val |= on << ((pin * 4) + 3);
+       __raw_writel(val, S3C2410_EXTINT2);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
index 878b974..1951a03 100644 (file)
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-s3c2410/irq.c
  *
- * Copyright (c) 2003 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- */
+ * Changelog:
+ *
+ *   22-Jul-2004  Ben Dooks <ben@simtec.co.uk>
+ *                Fixed compile warnings
+ *
+ *   22-Jul-2004  Roc Wu <cooloney@yahoo.com.cn>
+ *                Fixed s3c_extirq_type
+ *
+ *   21-Jul-2004  Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
+ *                Addition of ADC/TC demux
+ *
+ *   04-Oct-2004  Klaus Fetscher <k.fetscher@fetron.de>
+ *               Fix for set_irq_type() on low EINT numbers
+ *
+ *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
+ *               Tidy up KF's patch and sort out new release
+*/
 
 
 #include <linux/init.h>
 #include <asm/mach/irq.h>
 
 #include <asm/arch/regs-irq.h>
-#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
 
-#if 0
-#include <asm/debug-ll.h>
-#endif
 
 #define irqdbf(x...)
 #define irqdbf2(x...)
@@ -177,12 +190,84 @@ s3c_irqext_unmask(unsigned int irqno)
        s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
 }
 
-/* todo - put type handler in here */
-
 static int
 s3c_irqext_type(unsigned int irq, unsigned int type)
 {
-       irqdbf("s3c_irqext_type: called for irq %d, type %d\n", irq, type);
+       unsigned long extint_reg;
+       unsigned long gpcon_reg;
+       unsigned long gpcon_offset, extint_offset;
+       unsigned long newvalue = 0, value;
+
+       if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
+       {
+               gpcon_reg = S3C2410_GPFCON;
+               extint_reg = S3C2410_EXTINT0;
+               gpcon_offset = (irq - IRQ_EINT0) * 2;
+               extint_offset = (irq - IRQ_EINT0) * 4;
+       }
+       else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
+       {
+               gpcon_reg = S3C2410_GPFCON;
+               extint_reg = S3C2410_EXTINT0;
+               gpcon_offset = (irq - (EXTINT_OFF)) * 2;
+               extint_offset = (irq - (EXTINT_OFF)) * 4;
+       }
+       else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
+       {
+               gpcon_reg = S3C2410_GPGCON;
+               extint_reg = S3C2410_EXTINT1;
+               gpcon_offset = (irq - IRQ_EINT8) * 2;
+               extint_offset = (irq - IRQ_EINT8) * 4;
+       }
+       else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
+       {
+               gpcon_reg = S3C2410_GPGCON;
+               extint_reg = S3C2410_EXTINT2;
+               gpcon_offset = (irq - IRQ_EINT8) * 2;
+               extint_offset = (irq - IRQ_EINT16) * 4;
+       } else
+               return -1;
+
+       /* Set the GPIO to external interrupt mode */
+       value = __raw_readl(gpcon_reg);
+       value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
+       __raw_writel(value, gpcon_reg);
+
+       /* Set the external interrupt to pointed trigger type */
+       switch (type)
+       {
+               case IRQT_NOEDGE:
+                       printk(KERN_WARNING "No edge setting!\n");
+                       break;
+
+               case IRQT_RISING:
+                       newvalue = S3C2410_EXTINT_RISEEDGE;
+                       break;
+
+               case IRQT_FALLING:
+                       newvalue = S3C2410_EXTINT_FALLEDGE;
+                       break;
+
+               case IRQT_BOTHEDGE:
+                       newvalue = S3C2410_EXTINT_BOTHEDGE;
+                       break;
+
+               case IRQT_LOW:
+                       newvalue = S3C2410_EXTINT_LOWLEV;
+                       break;
+
+               case IRQT_HIGH:
+                       newvalue = S3C2410_EXTINT_HILEV;
+                       break;
+
+               default:
+                       printk(KERN_ERR "No such irq type %d", type);
+                       return -1;
+       }
+
+       value = __raw_readl(extint_reg);
+       value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
+       __raw_writel(value, extint_reg);
 
        return 0;
 }
@@ -194,6 +279,13 @@ static struct irqchip s3c_irqext_chip = {
        .type       = s3c_irqext_type
 };
 
+static struct irqchip s3c_irq_eint0t4 = {
+       .ack       = s3c_irq_ack,
+       .mask      = s3c_irq_mask,
+       .unmask    = s3c_irq_unmask,
+       .type      = s3c_irqext_type
+};
+
 /* mask values for the parent registers for each of the interrupt types */
 
 #define INTMSK_UART0    (1UL << (IRQ_UART0 - IRQ_EINT0))
@@ -368,37 +460,37 @@ static struct irqchip s3c_irq_adc = {
        .ack        = s3c_irq_adc_ack,
 };
 
-#if 0
-/* LCD (todo) */
-
-static void
-s3c_irq_lcd_mask(unsigned int irqno)
+/* irq demux for adc */
+static void s3c_irq_demux_adc(unsigned int irq,
+                             struct irqdesc *desc,
+                             struct pt_regs *regs)
 {
+       unsigned int subsrc, submsk;
+       unsigned int offset = 9;
+       struct irqdesc *mydesc;
 
-}
-
-static void
-s3c_irq_lcd_unmask(unsigned int irqno)
-{
+       /* read the current pending interrupts, and the mask
+        * for what it is available */
 
-}
+       subsrc = __raw_readl(S3C2410_SUBSRCPND);
+       submsk = __raw_readl(S3C2410_INTSUBMSK);
 
-static void
-s3c_irq_lcd_ack(unsigned int irqno)
-{
+       subsrc &= ~submsk;
+       subsrc >>= offset;
+       subsrc &= 3;
 
+       if (subsrc != 0) {
+               if (subsrc & 1) {
+                       mydesc = irq_desc + IRQ_TC;
+                       mydesc->handle( IRQ_TC, mydesc, regs);
+               }
+               if (subsrc & 2) {
+                       mydesc = irq_desc + IRQ_ADC;
+                       mydesc->handle(IRQ_ADC, mydesc, regs);
+               }
+       }
 }
 
-static struct irqchip s3c_irq_lcd = {
-       .mask       = s3c_irq_lcd_mask,
-       .unmask     = s3c_irq_lcd_unmask,
-       .ack        = s3c_irq_lcd_ack,
-};
-#endif
-
-/* irq demux */
-
-
 static void s3c_irq_demux_uart(unsigned int start,
                               struct pt_regs *regs)
 {
@@ -466,11 +558,15 @@ s3c_irq_demux_uart2(unsigned int irq,
        s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
 }
 
-
+/* s3c2410_init_irq
+ *
+ * Initialise S3C2410 IRQ system
+*/
 
 void __init s3c2410_init_irq(void)
 {
        unsigned long pend;
+       unsigned long last;
        int irqno;
        int i;
 
@@ -478,48 +574,51 @@ void __init s3c2410_init_irq(void)
 
        /* first, clear all interrupts pending... */
 
+       last = 0;
        for (i = 0; i < 4; i++) {
                pend = __raw_readl(S3C2410_EINTPEND);
-               if (pend == 0)
+
+               if (pend == 0 || pend == last)
                        break;
+
                __raw_writel(pend, S3C2410_EINTPEND);
                printk("irq: clearing pending ext status %08x\n", (int)pend);
+               last = pend;
        }
 
+       last = 0;
        for (i = 0; i < 4; i++) {
                pend = __raw_readl(S3C2410_INTPND);
-               if (pend == 0)
+
+               if (pend == 0 || pend == last)
                        break;
+
                __raw_writel(pend, S3C2410_SRCPND);
                __raw_writel(pend, S3C2410_INTPND);
                printk("irq: clearing pending status %08x\n", (int)pend);
+               last = pend;
        }
 
+       last = 0;
        for (i = 0; i < 4; i++) {
                pend = __raw_readl(S3C2410_SUBSRCPND);
 
-               if (pend == 0)
+               if (pend == 0 || pend == last)
                        break;
 
                printk("irq: clearing subpending status %08x\n", (int)pend);
                __raw_writel(pend, S3C2410_SUBSRCPND);
+               last = pend;
        }
 
        /* register the main interrupts */
 
        irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
 
-       for (irqno = IRQ_EINT0; irqno < IRQ_ADCPARENT; irqno++) {
+       for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) {
                /* set all the s3c2410 internal irqs */
 
                switch (irqno) {
-
-               case IRQ_EINT4t7:
-               case IRQ_EINT8t23:
-                       /* these are already dealt with, so should never
-                        * appear */
-                       break;
-
                        /* deal with the special IRQs (cascaded) */
 
                case IRQ_UART0:
@@ -549,12 +648,18 @@ void __init s3c2410_init_irq(void)
        set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
        set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
        set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
-       //set_irq_chained_handler(IRQ_LCD, s3c_irq_demux_);
-       //set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_);
+       set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
 
 
        /* external interrupts */
 
+       for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
+               irqdbf("registering irq %d (ext int)\n", irqno);
+               set_irq_chip(irqno, &s3c_irq_eint0t4);
+               set_irq_handler(irqno, do_edge_IRQ);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+
        for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
                irqdbf("registering irq %d (extended s3c irq)\n", irqno);
                set_irq_chip(irqno, &s3c_irqext_chip);
index bfadbd4..9f42865 100644 (file)
@@ -47,7 +47,8 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
-
+#include "devs.h"
+#include "cpu.h"
 
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
@@ -87,11 +88,24 @@ static struct s3c2410_uartcfg smdk2410_uartcfgs[] = {
        }
 };
 
+static struct platform_device *smdk2410_devices[] __initdata = {
+       &s3c_device_usb,
+       &s3c_device_lcd,
+       &s3c_device_wdt,
+       &s3c_device_i2c,
+       &s3c_device_iis,
+};
+
+static struct s3c2410_board smdk2410_board __initdata = {
+       .devices       = smdk2410_devices,
+       .devices_count = ARRAY_SIZE(smdk2410_devices)
+};
 
 void __init smdk2410_map_io(void)
 {
-       s3c2410_map_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
-       s3c2410_uartcfgs = smdk2410_uartcfgs;
+       s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
+       s3c2410_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
+       s3c2410_set_board(&smdk2410_board);
 }
 
 void __init smdk2410_init_irq(void)
@@ -113,3 +127,5 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
      INITIRQ(smdk2410_init_irq)
      INITTIME(smdk2410_init_time)
 MACHINE_END
+
+
diff --git a/arch/arm/mach-s3c2410/s3c2440-dsc.c b/arch/arm/mach-s3c2410/s3c2440-dsc.c
new file mode 100644 (file)
index 0000000..fb30783
--- /dev/null
@@ -0,0 +1,57 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440-dsc.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 Drive Strength Control support
+ *
+ * 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.
+ *
+ * Modifications:
+ *     29-Aug-2004 BJD  Start of drive-strength control
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2440.h"
+#include "cpu.h"
+
+int s3c2440_set_dsc(unsigned int pin, unsigned int value)
+{
+       unsigned long base;
+       unsigned long val;
+       unsigned long flags;
+       unsigned long mask;
+
+       base = (pin & S3C2440_SELECT_DSC1) ? S3C2440_DSC1 : S3C2440_DSC0;
+       mask = 3 << S3C2440_DSC_GETSHIFT(pin);
+
+       local_irq_save(flags);
+
+       val = __raw_readl(base);
+       val &= ~mask;
+       val |= value & mask;
+       __raw_writel(val, base);
+
+       local_irq_restore(flags);
+       return 0;
+}
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
new file mode 100644 (file)
index 0000000..f4bb10c
--- /dev/null
@@ -0,0 +1,192 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 Mobile CPU support
+ *
+ * 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.
+ *
+ * Modifications:
+ *     24-Aug-2004 BJD  Start of s3c2440 support
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+
+#include "s3c2440.h"
+#include "cpu.h"
+
+int s3c2440_clock_tick_rate = 12*1000*1000;  /* current timers at 12MHz */
+
+/* clock info */
+
+unsigned long s3c2440_baseclk = 12*1000*1000;  /* assume base is 12MHz */
+unsigned long s3c2440_hdiv;
+
+unsigned long s3c2440_fclk;
+unsigned long s3c2440_hclk;
+unsigned long s3c2440_pclk;
+
+static struct map_desc s3c2440_iodesc[] __initdata = {
+       IODESC_ENT(USBHOST),
+       IODESC_ENT(CLKPWR),
+       IODESC_ENT(LCD),
+       IODESC_ENT(TIMER),
+       IODESC_ENT(ADC),
+};
+
+static struct resource s3c_uart0_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_UART0,
+               .end   = S3C2410_PA_UART0 + 0x3fff,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_S3CUART_RX0,
+               .end   = IRQ_S3CUART_ERR0,
+               .flags = IORESOURCE_IRQ,
+       }
+
+};
+
+static struct resource s3c_uart1_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_UART1,
+               .end   = S3C2410_PA_UART1 + 0x3fff,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_S3CUART_RX1,
+               .end   = IRQ_S3CUART_ERR1,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static struct resource s3c_uart2_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_UART2,
+               .end   = S3C2410_PA_UART2 + 0x3fff,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_S3CUART_RX2,
+               .end   = IRQ_S3CUART_ERR2,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+/* our uart devices */
+
+static struct platform_device s3c_uart0 = {
+       .name             = "s3c2440-uart",
+       .id               = 0,
+       .num_resources    = ARRAY_SIZE(s3c_uart0_resource),
+       .resource         = s3c_uart0_resource,
+};
+
+
+static struct platform_device s3c_uart1 = {
+       .name             = "s3c2440-uart",
+       .id               = 1,
+       .num_resources    = ARRAY_SIZE(s3c_uart1_resource),
+       .resource         = s3c_uart1_resource,
+};
+
+static struct platform_device s3c_uart2 = {
+       .name             = "s3c2440-uart",
+       .id               = 2,
+       .num_resources    = ARRAY_SIZE(s3c_uart2_resource),
+       .resource         = s3c_uart2_resource,
+};
+
+static struct platform_device *uart_devices[] __initdata = {
+       &s3c_uart0,
+       &s3c_uart1,
+       &s3c_uart2
+};
+
+void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
+{
+       unsigned long tmp;
+       unsigned long camdiv;
+
+       /* register our io-tables */
+
+       iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc));
+       iotable_init(mach_desc, size);
+
+       /* now we've got our machine bits initialised, work out what
+        * clocks we've got */
+
+       s3c2440_fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON),
+                                      s3c2440_baseclk);
+
+       tmp = __raw_readl(S3C2410_CLKDIVN);
+       camdiv = __raw_readl(S3C2440_CAMDIVN);
+
+       /* work out clock scalings */
+
+       switch (tmp & S3C2440_CLKDIVN_HDIVN_MASK) {
+       case S3C2440_CLKDIVN_HDIVN_1:
+               s3c2440_hdiv = 1;
+               break;
+
+       case S3C2440_CLKDIVN_HDIVN_2:
+               s3c2440_hdiv = 1;
+               break;
+
+       case S3C2440_CLKDIVN_HDIVN_4_8:
+               s3c2440_hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+               break;
+
+       case S3C2440_CLKDIVN_HDIVN_3_6:
+               s3c2440_hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 6 : 3;
+               break;
+       }
+
+       s3c2440_hclk = s3c2440_fclk / s3c2440_hdiv;
+       s3c2440_pclk = s3c2440_hclk / ((tmp & S3C2440_CLKDIVN_PDIVN) ? 2 : 1);
+
+       /* print brieft summary of clocks, etc */
+
+       printk("S3C2440: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+              print_mhz(s3c2440_fclk), print_mhz(s3c2440_hclk),
+              print_mhz(s3c2440_pclk));
+}
+
+
+
+int __init s3c2440_init(void)
+{
+       int ret;
+
+       printk("S3C2440: Initialising architecture\n");
+
+       ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices));
+       if (ret)
+               return ret;
+
+       // todo: board specific inits?
+
+       return ret;
+}
+
diff --git a/arch/arm/mach-s3c2410/s3c2440.h b/arch/arm/mach-s3c2410/s3c2440.h
new file mode 100644 (file)
index 0000000..bf49a66
--- /dev/null
@@ -0,0 +1,18 @@
+/* arch/arm/mach-s3c2410/s3c2440.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2440 cpu support
+ *
+ * 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.
+ *
+ * Modifications:
+ *     24-Aug-2004 BJD  Start of S3C2440 CPU support
+*/
+
+extern void s3c2440_init_irq(void);
+
+extern void s3c2440_init_time(void);
index 62d89d9..04ba5df 100644 (file)
 #include <asm/irq.h>
 #include <asm/arch/map.h>
 #include <asm/arch/regs-timer.h>
+#include <asm/arch/regs-irq.h>
 #include <asm/mach/time.h>
 
 static unsigned long timer_startval;
 static unsigned long timer_ticks_usec;
 
-#ifdef CONFIG_S3C2410_RTC
-extern void s3c2410_rtc_check();
-#endif
 
 /* with an 12MHz clock, we get 12 ticks per-usec
  */
@@ -49,15 +47,30 @@ extern void s3c2410_rtc_check();
  * will have been disabled by do_gettimeoffset()
  * IRQs are disabled before entering here from do_gettimeofday()
  */
+
+#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0))
+
 static unsigned long s3c2410_gettimeoffset (void)
 {
        unsigned long tdone;
        unsigned long usec;
+       unsigned long irqpend;
 
        /* work out how many ticks have gone since last timer interrupt */
 
        tdone = timer_startval - __raw_readl(S3C2410_TCNTO(4));
 
+       /* check to see if there is an interrupt pending */
+
+       irqpend = __raw_readl(S3C2410_SRCPND);
+       if (irqpend & SRCPND_TIMER4) {
+               /* re-read the timer, and try and fix up for the missed
+                * interrupt */
+
+               tdone = timer_startval - __raw_readl(S3C2410_TCNTO(4));
+               tdone += 1<<16;
+       }
+
        /* currently, tcnt is in 12MHz units, but this may change
         * for non-bast machines...
         */
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
new file mode 100644 (file)
index 0000000..b8f8ded
--- /dev/null
@@ -0,0 +1,123 @@
+/* linux/arch/arm/mach-s3c2410/usb-simtec.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.simtec.co.uk/products/EB2410ITX/
+ *
+ * Simtec BAST and Thorcom VR1000 USB port support functions
+ *
+ * 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.
+ *
+ * Modifications:
+ *     14-Sep-2004 BJD  Created
+*/
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/bast-map.h>
+#include <asm/arch/bast-irq.h>
+#include <asm/arch/usb-control.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include "devs.h"
+#include "usb-simtec.h"
+
+/* control power and monitor over-current events on various Simtec
+ * designed boards.
+*/
+
+static void
+usb_simtec_powercontrol(int port, int to)
+{
+       pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
+
+       if (port == 1) {
+               s3c2410_gpio_setpin(S3C2410_GPB4, to ? 0:1);
+               pr_debug("GPBDAT now %08x\n", __raw_readl(S3C2410_GPBDAT));
+       }
+}
+
+static irqreturn_t
+usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs)
+{
+       struct s3c2410_hcd_info *info = (struct s3c2410_hcd_info *)pw;
+
+       if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) {
+               pr_debug("usb_simtec: over-current irq (oc detected)\n");
+               s3c2410_report_oc(info, 3);
+       } else {
+               pr_debug("usb_simtec: over-current irq (oc cleared)\n");
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on)
+{
+       int ret;
+
+       if (on) {
+               pr_debug("claiming usb overccurent\n");
+               ret = request_irq(IRQ_USBOC, usb_simtec_ocirq, SA_INTERRUPT,
+                                 "usb-oc", info);
+               if (ret != 0) {
+                       printk(KERN_ERR "failed to request usb oc irq\n");
+               }
+
+               set_irq_type(IRQ_USBOC, IRQT_BOTHEDGE);
+       } else {
+               free_irq(IRQ_USBOC, NULL);
+       }
+}
+
+static struct s3c2410_hcd_info usb_simtec_info = {
+       .port[0]        = {
+               .flags  = S3C_HCDFLG_USED
+       },
+       .port[1]        = {
+               .flags  = S3C_HCDFLG_USED
+       },
+
+       .power_control  = usb_simtec_powercontrol,
+       .enable_oc      = usb_simtec_enableoc,
+};
+
+
+int usb_simtec_init(void)
+{
+       printk("USB Power Control, (c) 2004 Simtec Electronics\n");
+       s3c_device_usb.dev.platform_data = &usb_simtec_info;
+
+       s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
+       s3c2410_gpio_setpin(S3C2410_GPB4, 1);
+
+       pr_debug("GPB: CON=%08x, DAT=%08x\n",
+                __raw_readl(S3C2410_GPBCON), __raw_readl(S3C2410_GPBDAT));
+
+       if (0) {
+               s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST,
+                                     S3C2410_MISCCR_USBDEV);
+       }
+
+       return 0;
+}
diff --git a/arch/arm/mach-s3c2410/usb-simtec.h b/arch/arm/mach-s3c2410/usb-simtec.h
new file mode 100644 (file)
index 0000000..92c0cc8
--- /dev/null
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-s3c2410/usb-simtec.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.simtec.co.uk/products/EB2410ITX/
+ *
+ * Simtec BAST and Thorcom VR1000 USB port support functions
+ *
+ * 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.
+ *
+ * Modifications:
+ *     20-Aug-2004 BJD  Created
+*/
+
+extern int usb_simtec_init(void);
+
index 2532b7f..7120ec5 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/hardware.h>
 #include <asm/memory.h>
 #include <asm/system.h>
+#include <asm/mach/time.h>
 
 extern void sa1100_cpu_suspend(void);
 extern void sa1100_cpu_resume(void);
@@ -44,7 +45,7 @@ extern void sa1100_cpu_resume(void);
  */
 enum { SLEEP_SAVE_SP = 0,
 
-       SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
+       SLEEP_SAVE_OIER,
        SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
 
        SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
@@ -58,18 +59,19 @@ enum {      SLEEP_SAVE_SP = 0,
 
 static int sa11x0_pm_enter(u32 state)
 {
-       unsigned long sleep_save[SLEEP_SAVE_SIZE];
-       unsigned long delta, gpio;
+       unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
+       struct timespec delta, rtc;
 
        if (state != PM_SUSPEND_MEM)
                return -EINVAL;
 
        /* preserve current time */
-       delta = xtime.tv_sec - RCNR;
+       rtc.tv_sec = RCNR;
+       rtc.tv_nsec = 0;
+       save_time_delta(&delta, &rtc);
        gpio = GPLR;
 
        /* save vital registers */
-       SAVE(OSCR);
        SAVE(OSMR0);
        SAVE(OSMR1);
        SAVE(OSMR2);
@@ -131,11 +133,14 @@ static int sa11x0_pm_enter(u32 state)
        RESTORE(OSMR1);
        RESTORE(OSMR2);
        RESTORE(OSMR3);
-       RESTORE(OSCR);
        RESTORE(OIER);
 
+       /* OSMR0 is the system timer: make sure OSCR is sufficiently behind */
+       OSCR = OSMR0 - LATCH;
+
        /* restore current time */
-       xtime.tv_sec = RCNR + delta;
+       rtc.tv_sec = RCNR;
+       restore_time_delta(&delta, &rtc);
 
        return 0;
 }
index fc764e1..ccf316c 100644 (file)
@@ -3,7 +3,8 @@
 #
 
 obj-y                          := consistent.o extable.o fault-armv.o \
-                                  fault.o init.o ioremap.o mmap.o mm-armv.o
+                                  fault.o flush.o init.o ioremap.o mmap.o \
+                                  mm-armv.o
 
 obj-$(CONFIG_MODULES)          += proc-syms.o
 
index 922e05a..fd0584a 100644 (file)
@@ -23,7 +23,6 @@ ENTRY(v5tj_early_abort)
        mrc     p15, 0, r0, c6, c0, 0           @ get FAR
        bic     r1, r1, #1 << 11 | 1 << 10      @ clear bits 11 and 10 of FSR
        tst     r3, #PSR_J_BIT                  @ Java?
-       orrne   r1, r1, #1 << 11                @ always assume write
        movne   pc, lr
        tst     r3, #PSR_T_BIT                  @ Thumb?
        ldrneh  r3, [r2]                        @ read aborted thumb instruction
index 6659439..e199478 100644 (file)
@@ -57,6 +57,19 @@ ENTRY(v3_flush_user_cache_range)
  *     - end    - virtual end address
  */
 ENTRY(v3_coherent_kern_range)
+       /* FALLTHROUGH */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start  - virtual start address
+ *     - end    - virtual end address
+ */
+ENTRY(v3_coherent_user_range)
        mov     pc, lr
 
 /*
@@ -116,6 +129,7 @@ ENTRY(v3_cache_fns)
        .long   v3_flush_user_cache_all
        .long   v3_flush_user_cache_range
        .long   v3_coherent_kern_range
+       .long   v3_coherent_user_range
        .long   v3_flush_kern_dcache_page
        .long   v3_dma_inv_range
        .long   v3_dma_clean_range
index bbc822f..b8ad5d5 100644 (file)
@@ -59,6 +59,19 @@ ENTRY(v4_flush_user_cache_range)
  *     - end    - virtual end address
  */
 ENTRY(v4_coherent_kern_range)
+       /* FALLTHROUGH */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start  - virtual start address
+ *     - end    - virtual end address
+ */
+ENTRY(v4_coherent_user_range)
        mov     pc, lr
 
 /*
@@ -118,6 +131,7 @@ ENTRY(v4_cache_fns)
        .long   v4_flush_user_cache_all
        .long   v4_flush_user_cache_range
        .long   v4_coherent_kern_range
+       .long   v4_coherent_user_range
        .long   v4_flush_kern_dcache_page
        .long   v4_dma_inv_range
        .long   v4_dma_clean_range
index 4f7c918..5c4055b 100644 (file)
@@ -121,6 +121,19 @@ ENTRY(v4wb_flush_kern_dcache_page)
  *     - end    - virtual end address
  */
 ENTRY(v4wb_coherent_kern_range)
+       /* fall through */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start  - virtual start address
+ *     - end    - virtual end address
+ */
+ENTRY(v4wb_coherent_user_range)
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
@@ -195,6 +208,7 @@ ENTRY(v4wb_cache_fns)
        .long   v4wb_flush_user_cache_all
        .long   v4wb_flush_user_cache_range
        .long   v4wb_coherent_kern_range
+       .long   v4wb_coherent_user_range
        .long   v4wb_flush_kern_dcache_page
        .long   v4wb_dma_inv_range
        .long   v4wb_dma_clean_range
index 61c9fc6..9bcabd8 100644 (file)
@@ -97,6 +97,19 @@ ENTRY(v4wt_flush_user_cache_range)
  *     - end    - virtual end address
  */
 ENTRY(v4wt_coherent_kern_range)
+       /* FALLTRHOUGH */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start  - virtual start address
+ *     - end    - virtual end address
+ */
+ENTRY(v4wt_coherent_user_range)
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:     mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
        add     r0, r0, #CACHE_DLINESIZE
@@ -167,6 +180,7 @@ ENTRY(v4wt_cache_fns)
        .long   v4wt_flush_user_cache_all
        .long   v4wt_flush_user_cache_range
        .long   v4wt_coherent_kern_range
+       .long   v4wt_coherent_user_range
        .long   v4wt_flush_kern_dcache_page
        .long   v4wt_dma_inv_range
        .long   v4wt_dma_clean_range
index e6a139e..402dad2 100644 (file)
@@ -31,14 +31,46 @@ static spinlock_t v6_lock = SPIN_LOCK_UNLOCKED;
 
 #define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
 
+/*
+ * Copy the user page.  No aliasing to deal with so we can just
+ * attack the kernel's existing mapping of these pages.
+ */
+void v6_copy_user_page_nonaliasing(void *kto, const void *kfrom, unsigned long vaddr)
+{
+       copy_page(kto, kfrom);
+}
+
+/*
+ * Clear the user page.  No aliasing to deal with so we can just
+ * attack the kernel's existing mapping of this page.
+ */
+void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr)
+{
+       clear_page(kaddr);
+}
+
 /*
  * Copy the page, taking account of the cache colour.
  */
-void v6_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
+void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
 {
        unsigned int offset = DCACHE_COLOUR(vaddr);
        unsigned long from, to;
 
+       /*
+        * Discard data in the kernel mapping for the new page.
+        * FIXME: needs this MCRR to be supported.
+        */
+       __asm__("mcrr   p15, 0, %1, %0, c6      @ 0xec401f06"
+          :
+          : "r" (kto),
+            "r" ((unsigned long)kto + PAGE_SIZE - L1_CACHE_BYTES)
+          : "cc");
+
+       /*
+        * Now copy the page using the same cache colour as the
+        * pages ultimate destination.
+        */
        spin_lock(&v6_lock);
 
        set_pte(from_pte + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot));
@@ -55,11 +87,30 @@ void v6_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
        spin_unlock(&v6_lock);
 }
 
-void v6_clear_user_page(void *kaddr, unsigned long vaddr)
+/*
+ * Clear the user page.  We need to deal with the aliasing issues,
+ * so remap the kernel page into the same cache colour as the user
+ * page.
+ */
+void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
 {
        unsigned int offset = DCACHE_COLOUR(vaddr);
        unsigned long to = to_address + (offset << PAGE_SHIFT);
 
+       /*
+        * Discard data in the kernel mapping for the new page
+        * FIXME: needs this MCRR to be supported.
+        */
+       __asm__("mcrr   p15, 0, %1, %0, c6      @ 0xec401f06"
+          :
+          : "r" (kaddr),
+            "r" ((unsigned long)kaddr + PAGE_SIZE - L1_CACHE_BYTES)
+          : "cc");
+
+       /*
+        * Now clear the page using the same cache colour as
+        * the pages ultimate destination.
+        */
        spin_lock(&v6_lock);
 
        set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
@@ -70,26 +121,31 @@ void v6_clear_user_page(void *kaddr, unsigned long vaddr)
 }
 
 struct cpu_user_fns v6_user_fns __initdata = {
-       .cpu_clear_user_page    = v6_clear_user_page,
-       .cpu_copy_user_page     = v6_copy_user_page,
+       .cpu_clear_user_page    = v6_clear_user_page_nonaliasing,
+       .cpu_copy_user_page     = v6_copy_user_page_nonaliasing,
 };
 
 static int __init v6_userpage_init(void)
 {
-       pgd_t *pgd;
-       pmd_t *pmd;
-
-       pgd = pgd_offset_k(from_address);
-       pmd = pmd_alloc(&init_mm, pgd, from_address);
-       if (!pmd)
-               BUG();
-       from_pte = pte_alloc_kernel(&init_mm, pmd, from_address);
-       if (!from_pte)
-               BUG();
-
-       to_pte = pte_alloc_kernel(&init_mm, pmd, to_address);
-       if (!to_pte)
-               BUG();
+       if (cache_is_vipt_aliasing()) {
+               pgd_t *pgd;
+               pmd_t *pmd;
+
+               pgd = pgd_offset_k(from_address);
+               pmd = pmd_alloc(&init_mm, pgd, from_address);
+               if (!pmd)
+                       BUG();
+               from_pte = pte_alloc_kernel(&init_mm, pmd, from_address);
+               if (!from_pte)
+                       BUG();
+
+               to_pte = pte_alloc_kernel(&init_mm, pmd, to_address);
+               if (!to_pte)
+                       BUG();
+
+               cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing;
+               cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing;
+       }
 
        return 0;
 }
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
new file mode 100644 (file)
index 0000000..ff5f62c
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *  linux/arch/arm/mm/flush.c
+ *
+ *  Copyright (C) 1995-2002 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.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+
+#include <asm/cacheflush.h>
+#include <asm/system.h>
+
+static void __flush_dcache_page(struct address_space *mapping, struct page *page)
+{
+       struct mm_struct *mm = current->active_mm;
+       struct vm_area_struct *mpnt;
+       struct prio_tree_iter iter;
+       pgoff_t pgoff;
+
+       /*
+        * Writeback any data associated with the kernel mapping of this
+        * page.  This ensures that data in the physical page is mutually
+        * coherent with the kernels mapping.
+        */
+       __cpuc_flush_dcache_page(page_address(page));
+
+       /*
+        * If there's no mapping pointer here, then this page isn't
+        * visible to userspace yet, so there are no cache lines
+        * associated with any other aliases.
+        */
+       if (!mapping)
+               return;
+
+       /*
+        * There are possible user space mappings of this page:
+        * - VIVT cache: we need to also write back and invalidate all user
+        *   data in the current VM view associated with this page.
+        * - aliasing VIPT: we only need to find one mapping of this page.
+        */
+       pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+
+       flush_dcache_mmap_lock(mapping);
+       vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
+               unsigned long offset;
+
+               /*
+                * If this VMA is not in our MM, we can ignore it.
+                */
+               if (mpnt->vm_mm != mm)
+                       continue;
+               if (!(mpnt->vm_flags & VM_MAYSHARE))
+                       continue;
+               offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
+               flush_cache_page(mpnt, mpnt->vm_start + offset);
+               if (cache_is_vipt())
+                       break;
+       }
+       flush_dcache_mmap_unlock(mapping);
+}
+
+/*
+ * Ensure cache coherency between kernel mapping and userspace mapping
+ * of this page.
+ *
+ * We have three cases to consider:
+ *  - VIPT non-aliasing cache: fully coherent so nothing required.
+ *  - VIVT: fully aliasing, so we need to handle every alias in our
+ *          current VM view.
+ *  - VIPT aliasing: need to handle one alias in our current VM view.
+ *
+ * If we need to handle aliasing:
+ *  If the page only exists in the page cache and there are no user
+ *  space mappings, we can be lazy and remember that we may have dirty
+ *  kernel cache lines for later.  Otherwise, we assume we have
+ *  aliasing mappings.
+ */
+void flush_dcache_page(struct page *page)
+{
+       struct address_space *mapping = page_mapping(page);
+
+       if (cache_is_vipt_nonaliasing())
+               return;
+
+       if (mapping && !mapping_mapped(mapping))
+               set_bit(PG_dcache_dirty, &page->flags);
+       else
+               __flush_dcache_page(mapping, page);
+}
+EXPORT_SYMBOL(flush_dcache_page);
index 7fe21a9..1267ab5 100644 (file)
@@ -196,6 +196,19 @@ ENTRY(arm1020_flush_user_cache_range)
  *     - end   - virtual end address
  */
 ENTRY(arm1020_coherent_kern_range)
+       /* FALLTRHOUGH */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm1020_coherent_user_range)
        mov     ip, #0
        bic     r0, r0, #CACHE_DLINESIZE - 1
        mcr     p15, 0, ip, c7, c10, 4
@@ -317,6 +330,7 @@ ENTRY(arm1020_cache_fns)
        .long   arm1020_flush_user_cache_all
        .long   arm1020_flush_user_cache_range
        .long   arm1020_coherent_kern_range
+       .long   arm1020_coherent_user_range
        .long   arm1020_flush_kern_dcache_page
        .long   arm1020_dma_inv_range
        .long   arm1020_dma_clean_range
index 0332c3e..947790d 100644 (file)
@@ -193,6 +193,18 @@ ENTRY(arm1020e_flush_user_cache_range)
  *     - end   - virtual end address
  */
 ENTRY(arm1020e_coherent_kern_range)
+       /* FALLTHROUGH */
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm1020e_coherent_user_range)
        mov     ip, #0
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:
@@ -304,6 +316,7 @@ ENTRY(arm1020e_cache_fns)
        .long   arm1020e_flush_user_cache_all
        .long   arm1020e_flush_user_cache_range
        .long   arm1020e_coherent_kern_range
+       .long   arm1020e_coherent_user_range
        .long   arm1020e_flush_kern_dcache_page
        .long   arm1020e_dma_inv_range
        .long   arm1020e_dma_clean_range
@@ -495,7 +508,7 @@ __arm1020e_proc_info:
        b       __arm1020e_setup
        .long   cpu_arch_name
        .long   cpu_elf_name
-       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_EDSP
        .long   cpu_arm1020e_name
        .long   arm1020e_processor_functions
        .long   v4wbi_tlb_fns
index 35a5c2f..7c84263 100644 (file)
@@ -180,6 +180,19 @@ ENTRY(arm1022_flush_user_cache_range)
  *     - end   - virtual end address
  */
 ENTRY(arm1022_coherent_kern_range)
+       /* FALLTHROUGH */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm1022_coherent_user_range)
        mov     ip, #0
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:
@@ -291,6 +304,7 @@ ENTRY(arm1022_cache_fns)
        .long   arm1022_flush_user_cache_all
        .long   arm1022_flush_user_cache_range
        .long   arm1022_coherent_kern_range
+       .long   arm1022_coherent_user_range
        .long   arm1022_flush_kern_dcache_page
        .long   arm1022_dma_inv_range
        .long   arm1022_dma_clean_range
@@ -475,7 +489,7 @@ __arm1022_proc_info:
        b       __arm1022_setup
        .long   cpu_arch_name
        .long   cpu_elf_name
-       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_EDSP
        .long   cpu_arm1022_name
        .long   arm1022_processor_functions
        .long   v4wbi_tlb_fns
index 0009f2d..38a06cb 100644 (file)
@@ -175,6 +175,18 @@ ENTRY(arm1026_flush_user_cache_range)
  *     - end   - virtual end address
  */
 ENTRY(arm1026_coherent_kern_range)
+       /* FALLTHROUGH */
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm1026_coherent_user_range)
        mov     ip, #0
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:
@@ -286,6 +298,7 @@ ENTRY(arm1026_cache_fns)
        .long   arm1026_flush_user_cache_all
        .long   arm1026_flush_user_cache_range
        .long   arm1026_coherent_kern_range
+       .long   arm1026_coherent_user_range
        .long   arm1026_flush_kern_dcache_page
        .long   arm1026_dma_inv_range
        .long   arm1026_dma_clean_range
@@ -471,7 +484,7 @@ __arm1026_proc_info:
        b       __arm1026_setup
        .long   cpu_arch_name
        .long   cpu_elf_name
-       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT
+       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
        .long   cpu_arm1026_name
        .long   arm1026_processor_functions
        .long   v4wbi_tlb_fns
index 3922a82..8c9204a 100644 (file)
@@ -182,6 +182,19 @@ ENTRY(arm920_flush_user_cache_range)
  *     - end   - virtual end address
  */
 ENTRY(arm920_coherent_kern_range)
+       /* FALLTHROUGH */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start, end.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm920_coherent_user_range)
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
@@ -277,6 +290,7 @@ ENTRY(arm920_cache_fns)
        .long   arm920_flush_user_cache_all
        .long   arm920_flush_user_cache_range
        .long   arm920_coherent_kern_range
+       .long   arm920_coherent_user_range
        .long   arm920_flush_kern_dcache_page
        .long   arm920_dma_inv_range
        .long   arm920_dma_clean_range
index 8606511..13e65cb 100644 (file)
@@ -184,6 +184,19 @@ ENTRY(arm922_flush_user_cache_range)
  *     - end   - virtual end address
  */
 ENTRY(arm922_coherent_kern_range)
+       /* FALLTHROUGH */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start, end.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm922_coherent_user_range)
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
@@ -279,6 +292,7 @@ ENTRY(arm922_cache_fns)
        .long   arm922_flush_user_cache_all
        .long   arm922_flush_user_cache_range
        .long   arm922_coherent_kern_range
+       .long   arm922_coherent_user_range
        .long   arm922_flush_kern_dcache_page
        .long   arm922_dma_inv_range
        .long   arm922_dma_clean_range
index 917eb5e..e8b3ff1 100644 (file)
@@ -225,6 +225,19 @@ ENTRY(arm925_flush_user_cache_range)
  *     - end   - virtual end address
  */
 ENTRY(arm925_coherent_kern_range)
+       /* FALLTHROUGH */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start, end.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm925_coherent_user_range)
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
@@ -329,6 +342,7 @@ ENTRY(arm925_cache_fns)
        .long   arm925_flush_user_cache_all
        .long   arm925_flush_user_cache_range
        .long   arm925_coherent_kern_range
+       .long   arm925_coherent_user_range
        .long   arm925_flush_kern_dcache_page
        .long   arm925_dma_inv_range
        .long   arm925_dma_clean_range
index 9b098e0..5631c8b 100644 (file)
@@ -185,6 +185,19 @@ ENTRY(arm926_flush_user_cache_range)
  *     - end   - virtual end address
  */
 ENTRY(arm926_coherent_kern_range)
+       /* FALLTHROUGH */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start, end.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm926_coherent_user_range)
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
@@ -289,6 +302,7 @@ ENTRY(arm926_cache_fns)
        .long   arm926_flush_user_cache_all
        .long   arm926_flush_user_cache_range
        .long   arm926_coherent_kern_range
+       .long   arm926_coherent_user_range
        .long   arm926_flush_kern_dcache_page
        .long   arm926_dma_inv_range
        .long   arm926_dma_clean_range
@@ -473,7 +487,7 @@ __arm926_proc_info:
        b       __arm926_setup
        .long   cpu_arch_name
        .long   cpu_elf_name
-       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | HWCAP_JAVA
+       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
        .long   cpu_arm926_name
        .long   arm926_processor_functions
        .long   v4wbi_tlb_fns
index 8df666f..6c5f0fe 100644 (file)
@@ -22,10 +22,10 @@ EXPORT_SYMBOL(processor);
 #endif
 
 #ifndef MULTI_CACHE
-EXPORT_SYMBOL_NOVERS(__cpuc_flush_kern_all);
-EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_all);
-EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_range);
-EXPORT_SYMBOL_NOVERS(__cpuc_coherent_kern_range);
+EXPORT_SYMBOL(__cpuc_flush_kern_all);
+EXPORT_SYMBOL(__cpuc_flush_user_all);
+EXPORT_SYMBOL(__cpuc_flush_user_range);
+EXPORT_SYMBOL(__cpuc_coherent_kern_range);
 #else
 EXPORT_SYMBOL(cpu_cache);
 #endif
index c22cc36..0a4ff26 100644 (file)
@@ -189,12 +189,10 @@ cpu_v6_name:
  *     - cache type register is implemented
  */
 __v6_setup:
-       mrc     p15, 0, r10, c0, c0, 1          @ read cache type register
-       tst     r10, #1 << 24                   @ Harvard cache?
        mov     r10, #0
-       mcrne   p15, 0, r10, c7, c14, 0         @ clean+invalidate D cache
-       mcrne   p15, 0, r10, c7, c5, 0          @ invalidate I cache
-       mcreq   p15, 0, r10, c7, c15, 0         @ clean+invalidate cache
+       mcr     p15, 0, r10, c7, c14, 0         @ clean+invalidate D cache
+       mcr     p15, 0, r10, c7, c5, 0          @ invalidate I cache
+       mcr     p15, 0, r10, c7, c15, 0         @ clean+invalidate cache
        mcr     p15, 0, r10, c7, c10, 4         @ drain write buffer
        mcr     p15, 0, r10, c8, c7, 0          @ invalidate I + D TLBs
        mcr     p15, 0, r10, c2, c0, 2          @ TTB control register
@@ -258,7 +256,7 @@ __v6_proc_info:
        b       __v6_setup
        .long   cpu_arch_name
        .long   cpu_elf_name
-       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_FAST_MULT | HWCAP_VFP
+       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA
        .long   cpu_v6_name
        .long   v6_processor_functions
        .long   v6wbi_tlb_fns
index 2ad4575..95fb63f 100644 (file)
@@ -42,8 +42,13 @@ static inline void loadDouble(const unsigned int Fn, const unsigned int __user *
        unsigned int *p;
        p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
        fpa11->fType[Fn] = typeDouble;
+#ifdef __ARMEB__
+       get_user(p[0], &pMem[0]);       /* sign & exponent */
+       get_user(p[1], &pMem[1]);
+#else
        get_user(p[0], &pMem[1]);
        get_user(p[1], &pMem[0]);       /* sign & exponent */
+#endif
 }
 
 #ifdef CONFIG_FPE_NWFPE_XP
@@ -140,8 +145,13 @@ static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
                val.f = fpa11->fpreg[Fn].fDouble;
        }
 
+#ifdef __ARMEB__
+       put_user(val.i[0], &pMem[0]);   /* msw */
+       put_user(val.i[1], &pMem[1]);   /* lsw */
+#else
        put_user(val.i[1], &pMem[0]);   /* msw */
        put_user(val.i[0], &pMem[1]);   /* lsw */
+#endif
 }
 
 #ifdef CONFIG_FPE_NWFPE_XP
index 284874b..447653d 100644 (file)
@@ -7,7 +7,7 @@
  * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
  * @remark Copyright 2004 Intel Corporation
  * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
- * @remark Copyright 2004 Oprofile Authors
+ * @remark Copyright 2004 OProfile Authors
  *
  * @remark Read the file COPYING
  *
@@ -30,6 +30,7 @@
 #define PMN_RESET      0x002   /* Reset event counters */
 #define        CCNT_RESET      0x004   /* Reset clock counter */
 #define        PMU_RESET       (CCNT_RESET | PMN_RESET)
+#define PMU_CNT64      0x008   /* Make CCNT count every 64th cycle */
 
 /* TODO do runtime detection */
 #ifdef CONFIG_ARCH_IOP310
@@ -125,12 +126,15 @@ static struct pmu_type *pmu;
 
 static void write_pmnc(u32 val)
 {
-       /* upper 4bits and 7, 11 are write-as-0 */
-       val &= 0xffff77f;
-       if (pmu->id == PMU_XSC1)
+       if (pmu->id == PMU_XSC1) {
+               /* upper 4bits and 7, 11 are write-as-0 */
+               val &= 0xffff77f;
                __asm__ __volatile__ ("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
-       else
+       } else {
+               /* bits 4-23 are write-as-0, 24-31 are write ignored */
+               val &= 0xf;
                __asm__ __volatile__ ("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
+       }
 }
 
 static u32 read_pmnc(void)
@@ -139,8 +143,11 @@ static u32 read_pmnc(void)
 
        if (pmu->id == PMU_XSC1)
                __asm__ __volatile__ ("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
-       else
+       else {
                __asm__ __volatile__ ("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
+               /* bits 1-2 and 4-23 are read-unpredictable */
+               val &= 0xff000009;
+       }
 
        return val;
 }
@@ -249,7 +256,7 @@ static int xscale_setup_ctrs(void)
        int i;
 
        for (i = CCNT; i < MAX_COUNTERS; i++) {
-               if (counter_config[i].event)
+               if (counter_config[i].enabled)
                        continue;
 
                counter_config[i].event = EVT_UNUSED;
@@ -336,7 +343,7 @@ static void inline __xsc2_check_ctrs(void)
 
 static irqreturn_t xscale_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
 {
-       unsigned long eip = instruction_pointer(regs);
+       unsigned long pc = profile_pc(regs);
        int i, is_kernel = !user_mode(regs);
        u32 pmnc;
 
@@ -350,7 +357,7 @@ static irqreturn_t xscale_pmu_interrupt(int irq, void *arg, struct pt_regs *regs
                        continue;
 
                write_counter(i, -(u32)results[i].reset_counter);
-               oprofile_add_sample(eip, is_kernel, i, smp_processor_id());
+               oprofile_add_sample(pc, is_kernel, i, smp_processor_id());
                results[i].ovf--;
        }
 
@@ -386,8 +393,10 @@ static int xscale_pmu_start(void)
 
        if (pmu->id == PMU_XSC1)
                pmnc |= pmu->int_enable;
-       else
+       else {
                __asm__ __volatile__ ("mcr p14, 0, %0, c4, c1, 0" : : "r" (pmu->int_enable));
+               pmnc &= ~PMU_CNT64;
+       }
 
        pmnc |= PMU_ENABLE;
        write_pmnc(pmnc);
diff --git a/arch/arm26/Kconfig.debug b/arch/arm26/Kconfig.debug
new file mode 100644 (file)
index 0000000..e2c920d
--- /dev/null
@@ -0,0 +1,60 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+# RMK wants arm kernels compiled with frame pointers so hardwire this to y.
+# If you know what you are doing and are willing to live without stack
+# traces, you can get a slightly smaller kernel by setting this option to
+# n, but then RMK will have to kill you ;).
+config FRAME_POINTER
+       bool
+       default y
+       help
+         If you say N here, the resulting kernel will be slightly smaller and
+         faster. However, when a problem occurs with the kernel, the
+         information that is reported is severely limited. Most people
+         should say Y here.
+
+config DEBUG_USER
+       bool "Verbose user fault messages"
+       help
+         When a user program crashes due to an exception, the kernel can
+         print a brief message explaining what the problem was. This is
+         sometimes helpful for debugging but serves no purpose on a
+         production system. Most people should say N here.
+
+config DEBUG_WAITQ
+       bool "Wait queue debugging"
+       depends on DEBUG_KERNEL
+
+config DEBUG_ERRORS
+       bool "Verbose kernel error messages"
+       depends on DEBUG_KERNEL
+       help
+         This option controls verbose debugging information which can be
+         printed when the kernel detects an internal error. This debugging
+         information is useful to kernel hackers when tracking down problems,
+         but mostly meaningless to other people. It's safe to say Y unless
+         you are concerned with the code size or don't want to see these
+         messages.
+
+config DEBUG_INFO
+       bool "Include GDB debugging information in kernel binary"
+       help
+         Say Y here to include source-level debugging information in the
+         `vmlinux' binary image. This is handy if you want to use gdb or
+         addr2line to debug the kernel. It has no impact on the in-memory
+         footprint of the running kernel but it can increase the amount of
+         time and disk space needed for compilation of the kernel. If in
+         doubt say N.
+
+# These options are only for real kernel hackers who want to get their hands dirty.
+config DEBUG_LL
+       bool "Kernel low-level debugging functions"
+       depends on DEBUG_KERNEL
+       help
+         Say Y here to include definitions of printascii, printchar, printhex
+         in the kernel.  This is helpful if you are debugging code that
+         executes before the console is initialized.
+
+endmenu
index 3b0294a..631c20a 100644 (file)
@@ -8,8 +8,7 @@
 # Copyright (C) 1995-2001 by Russell King
 
 LDFLAGS_vmlinux        :=-p -X
-LDFLAGS_BLOB   :=--format binary
-AFLAGS_vmlinux.lds.o = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
+CPPFLAGS_vmlinux.lds = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
 OBJCOPYFLAGS   :=-O binary -R .note -R .comment -S
 GZFLAGS                :=-9
 
@@ -28,7 +27,6 @@ CFLAGS                +=-mapcs-26 -mcpu=arm3 -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uar
 AFLAGS         +=-mapcs-26 -mcpu=arm3 -mno-fpu -msoft-float -Wa,-mno-fpu
 
 head-y         := arch/arm26/machine/head.o arch/arm26/kernel/init_task.o
-LDFLAGS_BLOB   += --oformat elf32-littlearm
 
 ifeq ($(CONFIG_XIP_KERNEL),y)
   TEXTADDR      := 0x03880000
index 3d992e5..004dd81 100644 (file)
@@ -67,12 +67,12 @@ initrd:
 
 install: $(obj)/Image
        $(CONFIG_SHELL) $(obj)/install.sh \
-       $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \
+       $(KERNELRELEASE) \
        $(obj)/Image System.map "$(INSTALL_PATH)"
 
 zinstall: $(obj)/zImage
        $(CONFIG_SHELL) $(obj)/install.sh \
-       $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \
+       $(KERNELRELEASE) \
        $(obj)/zImage System.map "$(INSTALL_PATH)"
 
 subdir-            := compressed
index 7e10b55..e2e5503 100644 (file)
@@ -14,5 +14,5 @@ obj-y         := compat.o dma.o entry.o irq.o   \
 obj-$(CONFIG_FIQ)              += fiq.o
 obj-$(CONFIG_MODULES)          += armksyms.o
 
-extra-y := init_task.o vmlinux.lds.s
+extra-y := init_task.o vmlinux.lds
 
index c540f22..bd6c306 100644 (file)
@@ -95,7 +95,7 @@ EXPORT_SYMBOL(ret_from_exception);
 EXPORT_SYMBOL(kd_mksound);
 #endif
 
-EXPORT_SYMBOL_NOVERS(__do_softirq);
+EXPORT_SYMBOL(__do_softirq);
 
        /* platform dependent support */
 EXPORT_SYMBOL(dump_thread);
@@ -125,71 +125,71 @@ EXPORT_SYMBOL(__csum_ipv6_magic);
 
        /* io */
 #ifndef __raw_readsb
-EXPORT_SYMBOL_NOVERS(__raw_readsb);
+EXPORT_SYMBOL(__raw_readsb);
 #endif
 #ifndef __raw_readsw
-EXPORT_SYMBOL_NOVERS(__raw_readsw);
+EXPORT_SYMBOL(__raw_readsw);
 #endif
 #ifndef __raw_readsl
-EXPORT_SYMBOL_NOVERS(__raw_readsl);
+EXPORT_SYMBOL(__raw_readsl);
 #endif
 #ifndef __raw_writesb
-EXPORT_SYMBOL_NOVERS(__raw_writesb);
+EXPORT_SYMBOL(__raw_writesb);
 #endif
 #ifndef __raw_writesw
-EXPORT_SYMBOL_NOVERS(__raw_writesw);
+EXPORT_SYMBOL(__raw_writesw);
 #endif
 #ifndef __raw_writesl
-EXPORT_SYMBOL_NOVERS(__raw_writesl);
+EXPORT_SYMBOL(__raw_writesl);
 #endif
 
        /* string / mem functions */
-EXPORT_SYMBOL_NOVERS(strcpy);
-EXPORT_SYMBOL_NOVERS(strncpy);
-EXPORT_SYMBOL_NOVERS(strcat);
-EXPORT_SYMBOL_NOVERS(strncat);
-EXPORT_SYMBOL_NOVERS(strcmp);
-EXPORT_SYMBOL_NOVERS(strncmp);
-EXPORT_SYMBOL_NOVERS(strchr);
-EXPORT_SYMBOL_NOVERS(strlen);
-EXPORT_SYMBOL_NOVERS(strnlen);
-EXPORT_SYMBOL_NOVERS(strpbrk);
-EXPORT_SYMBOL_NOVERS(strrchr);
-EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(__memzero);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(__memzero);
 
        /* user mem (segment) */
 EXPORT_SYMBOL(uaccess_kernel);
 EXPORT_SYMBOL(uaccess_user);
 
-EXPORT_SYMBOL_NOVERS(__get_user_1);
-EXPORT_SYMBOL_NOVERS(__get_user_2);
-EXPORT_SYMBOL_NOVERS(__get_user_4);
-EXPORT_SYMBOL_NOVERS(__get_user_8);
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+EXPORT_SYMBOL(__get_user_8);
 
-EXPORT_SYMBOL_NOVERS(__put_user_1);
-EXPORT_SYMBOL_NOVERS(__put_user_2);
-EXPORT_SYMBOL_NOVERS(__put_user_4);
-EXPORT_SYMBOL_NOVERS(__put_user_8);
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
 
        /* gcc lib functions */
-EXPORT_SYMBOL_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__divsi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(__modsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__ucmpdi2);
-EXPORT_SYMBOL_NOVERS(__udivdi3);
-EXPORT_SYMBOL_NOVERS(__umoddi3);
-EXPORT_SYMBOL_NOVERS(__udivmoddi4);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
-EXPORT_SYMBOL_NOVERS(__umodsi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__udivdi3);
+EXPORT_SYMBOL(__umoddi3);
+EXPORT_SYMBOL(__udivmoddi4);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
 
        /* bitops */
 EXPORT_SYMBOL(_set_bit_le);
@@ -214,10 +214,10 @@ EXPORT_SYMBOL(sys_exit);
 EXPORT_SYMBOL(sys_wait4);
 
        /* semaphores */
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_interruptible_failed);
-EXPORT_SYMBOL_NOVERS(__down_trylock_failed);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_interruptible_failed);
+EXPORT_SYMBOL(__down_trylock_failed);
+EXPORT_SYMBOL(__up_wakeup);
 
 EXPORT_SYMBOL(get_wchan);
 
index 16cf7db..bf05f15 100644 (file)
@@ -465,9 +465,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
                return;
        }
 
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, tsk);
+       force_sigsegv(sig, tsk);
 }
 
 /*
index 0d1cdd5..431f9f8 100644 (file)
@@ -256,7 +256,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct
        if (!newsp)
                newsp = regs->ARM_sp;
 
-       return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
+       return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
 }
 
 asmlinkage int sys_vfork(struct pt_regs *regs)
index af2905a..dbbc214 100644 (file)
@@ -67,28 +67,6 @@ static unsigned long dummy_gettimeoffset(void)
  */
 unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset;
 
-/*
- * Handle kernel profile stuff...
- */
-static inline void do_profile(struct pt_regs *regs)
-{
-       if (!user_mode(regs) &&
-           prof_buffer &&
-           current->pid) {
-               unsigned long pc = instruction_pointer(regs);
-               extern int _stext;
-
-               pc -= (unsigned long)&_stext;
-
-               pc >>= prof_shift;
-
-               if (pc >= prof_len)
-                       pc = prof_len - 1;
-
-               prof_buffer[pc] += 1;
-       }
-}
-
 static unsigned long next_rtc_update;
 
 /*
@@ -189,7 +167,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
         do_timer(regs);
         do_set_rtc(); //FIME - EVERY timer IRQ?
-        do_profile(regs);
+        profile_tick(CPU_PROFILING, regs);
        return IRQ_HANDLED; //FIXME - is this right?
 }
 
index 61eedf0..cbbda27 100644 (file)
@@ -34,9 +34,6 @@ SECTIONS
                __early_begin = .;
                        *(__early_param)
                __early_end = .;
-               __start___param = .;
-                       *(__param)
-               __stop___param = .;
                __initcall_start = .;
                        *(.initcall1.init)
                        *(.initcall2.init)
index 2393f38..128eb91 100644 (file)
@@ -35,9 +35,6 @@ SECTIONS
                __early_begin = .;
                        *(__early_param)
                __early_end = .;
-               __start___param = .;
-                       *(__param)
-               __stop___param = .;
                __initcall_start = .;
                        *(.initcall1.init)
                        *(.initcall2.init)
diff --git a/arch/cris/Kconfig.debug b/arch/cris/Kconfig.debug
new file mode 100644 (file)
index 0000000..9864aad
--- /dev/null
@@ -0,0 +1,28 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
+config PROFILE
+       bool "Kernel profiling support"
+
+config PROFILE_SHIFT
+       int "Profile shift count"
+       depends on PROFILE
+       default "2"
+
+config ETRAX_KGDB
+       bool "Use kernel GDB debugger"
+       ---help---
+         The CRIS version of gdb can be used to remotely debug a running
+         Linux kernel via the serial debug port.  Provided you have gdb-cris
+         installed, run gdb-cris vmlinux, then type
+
+         (gdb) set remotebaud 115200           <- kgdb uses 115200 as default
+         (gdb) target remote /dev/ttyS0        <- maybe you use another port
+
+         This should connect you to your booted kernel (or boot it now if you
+         didn't before).  The kernel halts when it boots, waiting for gdb if
+         this option is turned on!
+
+endmenu
index df03dea..720b9c1 100644 (file)
@@ -183,7 +183,7 @@ paging_init(void)
         * mem_map page array.
         */
 
-       free_area_init_node(0, &contig_page_data, 0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
+       free_area_init_node(0, &contig_page_data, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
        mem_map = contig_page_data.node_mem_map;
 }
 
index 6b73a2c..9e134c6 100644 (file)
@@ -64,9 +64,6 @@ SECTIONS
        __setup_start = .;
        .init.setup : { *(.init.setup) }
        __setup_end = .;
-       __start___param = .;
-       __param : { *(__param) }
-       __stop___param = .;
        .initcall.init : {
                __initcall_start = .;
                *(.initcall1.init);
index 6ded633..7141bbe 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
@@ -91,8 +90,8 @@ EXPORT_SYMBOL(prepare_rx_descriptor);
 #undef memset
 extern void * memset(void *, int, __kernel_size_t);
 extern void * memcpy(void *, const void *, __kernel_size_t);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
 
 #ifdef CONFIG_ETRAX_FAST_TIMER
 /* Fast timer functions */
diff --git a/arch/h8300/Kconfig.debug b/arch/h8300/Kconfig.debug
new file mode 100644 (file)
index 0000000..55034d0
--- /dev/null
@@ -0,0 +1,68 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config FULLDEBUG
+       bool "Full Symbolic/Source Debugging support"
+       help
+         Enable debugging symbols on kernel build.
+
+config HIGHPROFILE
+       bool "Use fast second timer for profiling"
+       help
+         Use a fast secondary clock to produce profiling information.
+
+config NO_KERNEL_MSG
+       bool "Suppress Kernel BUG Messages"
+       help
+         Do not output any debug BUG messages within the kernel.
+
+config GDB_MAGICPRINT
+       bool "Message Output for GDB MagicPrint service"
+       depends on (H8300H_SIM || H8S_SIM)
+       help
+         kernel messages output useing MagicPrint service from GDB
+
+config SYSCALL_PRINT
+       bool "SystemCall trace print"
+       help
+         outout history of systemcall
+
+config GDB_DEBUG
+       bool "Use gdb stub"
+       depends on (!H8300H_SIM && !H8S_SIM)
+       help
+         gdb stub exception support
+
+config CONFIG_SH_STANDARD_BIOS
+       bool "Use gdb protocol serial console"
+       depends on (!H8300H_SIM && !H8S_SIM)
+       help
+         serial console output using GDB protocol.
+         Require eCos/RedBoot
+
+config DEFAULT_CMDLINE
+       bool "Use buildin commandline"
+       default n
+       help
+         buildin kernel commandline enabled.
+
+config KERNEL_COMMAND
+       string "Buildin commmand string"
+       depends on DEFAULT_CMDLINE
+       help
+         buildin kernel commandline strings.
+
+config BLKDEV_RESERVE
+       bool "BLKDEV Reserved Memory"
+       default n
+       help
+         Reserved BLKDEV area.
+
+config CONFIG_BLKDEV_RESERVE_ADDRESS
+       hex 'start address'
+       depends on BLKDEV_RESERVE
+       help
+         BLKDEV start address.
+
+endmenu
index 5e50c08..b78b82a 100644 (file)
@@ -12,9 +12,9 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
+#include <linux/hardirq.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/ptrace.h>
 
 #define DEFINE(sym, val) \
index 7246e29..edb3c41 100644 (file)
 #include <linux/init.h>
 #include <linux/random.h>
 #include <linux/bootmem.h>
+#include <linux/hardirq.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/io.h>
 #include <asm/setup.h>
-#include <asm/hardirq.h>
 #include <asm/errno.h>
 
 /*
index 87e2849..0b293d6 100644 (file)
@@ -36,24 +36,6 @@ u64 jiffies_64;
 
 EXPORT_SYMBOL(jiffies_64);
 
-static inline void do_profile (unsigned long pc)
-{
-       if (prof_buffer && current->pid) {
-               extern int _stext;
-               pc -= (unsigned long) &_stext;
-               pc >>= prof_shift;
-               if (pc < prof_len)
-                       ++prof_buffer[pc];
-               else
-               /*
-                * Don't ignore out-of-bounds PC values silently,
-                * put them into the last histogram slot, so if
-                * present, they will show up as a sharp peak.
-                */
-                       ++prof_buffer[prof_len-1];
-       }
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -64,10 +46,7 @@ static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
        platform_timer_eoi();
 
        do_timer(regs);
-
-       if (!user_mode(regs))
-               do_profile(regs->pc);
-
+       profile_tick(CPU_PROFILING, regs);
 }
 
 void time_init(void)
index 6691d0b..5aa688d 100644 (file)
@@ -32,6 +32,7 @@
    of the assembly has to go. */
 
 #include <net/checksum.h>
+#include <linux/module.h>
 
 static inline unsigned short from32to16(unsigned long x)
 {
index bbefac4..5441cdd 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/random.h>
+#include <linux/hardirq.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -29,7 +30,6 @@
 #include <asm/io.h>
 #include <asm/setup.h>
 #include <asm/gpio.h>
-#include <asm/hardirq.h>
 #include <asm/regs267x.h>
 #include <asm/errno.h>
 
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
new file mode 100644 (file)
index 0000000..cf069b7
--- /dev/null
@@ -0,0 +1,80 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config EARLY_PRINTK
+       bool "Early printk" if EMBEDDED
+       default y
+       help
+         Write kernel log output directly into the VGA buffer or to a serial
+         port.
+
+         This is useful for kernel debugging when your machine crashes very
+         early before the console code is initialized. For normal operation
+         it is not recommended because it looks ugly and doesn't cooperate
+         with klogd/syslogd or the X server. You should normally N here,
+         unless you want to debug such a crash.
+
+config DEBUG_STACKOVERFLOW
+       bool "Check for stack overflows"
+       depends on DEBUG_KERNEL
+
+config KPROBES
+       bool "Kprobes"
+       depends on DEBUG_KERNEL
+       help
+         Kprobes allows you to trap at almost any kernel address and
+         execute a callback function.  register_kprobe() establishes
+         a probepoint and specifies the callback.  Kprobes is useful
+         for kernel debugging, non-intrusive instrumentation and testing.
+         If in doubt, say "N".
+
+config DEBUG_STACK_USAGE
+       bool "Stack utilization instrumentation"
+       depends on DEBUG_KERNEL
+       help
+         Enables the display of the minimum amount of free stack which each
+         task has ever had available in the sysrq-T and sysrq-P debug output.
+
+         This option will slow down process creation somewhat.
+
+config DEBUG_PAGEALLOC
+       bool "Page alloc debugging"
+       depends on DEBUG_KERNEL
+       help
+         Unmap pages from the kernel linear mapping after free_pages().
+         This results in a large slowdown, but helps to find certain types
+         of memory corruptions.
+
+config 4KSTACKS
+       bool "Use 4Kb for kernel stacks instead of 8Kb"
+       help
+         If you say Y here the kernel will use a 4Kb stacksize for the
+         kernel stack attached to each process/thread. This facilitates
+         running more threads on a system and also reduces the pressure
+         on the VM subsystem for higher order allocations. This option
+         will also use IRQ stacks to compensate for the reduced stackspace.
+
+config SCHEDSTATS
+       bool "Collect scheduler statistics"
+       depends on DEBUG_KERNEL && PROC_FS
+       help
+         If you say Y here, additional code will be inserted into the
+         scheduler and related routines to collect statistics about
+         scheduler behavior and provide them in /proc/schedstat.  These
+         stats may be useful for both tuning and debugging the scheduler
+         If you aren't debugging the scheduler or trying to tune a specific
+         application, you can say N to avoid the very slight overhead
+         this adds.
+
+config X86_FIND_SMP_CONFIG
+       bool
+       depends on X86_LOCAL_APIC || X86_VOYAGER
+       default y
+
+config X86_MPPARSE
+       bool
+       depends on X86_LOCAL_APIC && !X86_VISWS
+       default y
+
+endmenu
index e85f482..394814e 100644 (file)
@@ -286,23 +286,20 @@ static void __init init_c3(struct cpuinfo_x86 *c)
                c->x86_capability[5] = cpuid_edx(0xC0000001);
        }
 
-       switch (c->x86_model) {
-               case 6 ... 8:           /* Cyrix III family */
-                       rdmsr (MSR_VIA_FCR, lo, hi);
-                       lo |= (1<<1 | 1<<7);    /* Report CX8 & enable PGE */
-                       wrmsr (MSR_VIA_FCR, lo, hi);
-
-                       set_bit(X86_FEATURE_CX8, c->x86_capability);
-                       set_bit(X86_FEATURE_3DNOW, c->x86_capability);
+       /* Cyrix III family needs CX8 & PGE explicity enabled. */
+       if (c->x86_model >=6 && c->x86_model <= 9) {
+               rdmsr (MSR_VIA_FCR, lo, hi);
+               lo |= (1<<1 | 1<<7);
+               wrmsr (MSR_VIA_FCR, lo, hi);
+               set_bit(X86_FEATURE_CX8, c->x86_capability);
+       }
 
-                       /* fall through */
+       /* Before Nehemiah, the C3's had 3dNOW! */
+       if (c->x86_model >=6 && c->x86_model <9)
+               set_bit(X86_FEATURE_3DNOW, c->x86_capability);
 
-               case 9: /* Nehemiah */
-               default:
-                       get_model_name(c);
-                       display_cacheinfo(c);
-                       break;
-       }
+       get_model_name(c);
+       display_cacheinfo(c);
 }
 
 static void __init init_centaur(struct cpuinfo_x86 *c)
index d285dc1..5cd4442 100644 (file)
@@ -88,6 +88,11 @@ config X86_POWERNOW_K7
 
          If in doubt, say N.
 
+config X86_POWERNOW_K7_ACPI
+       bool
+       depends on ((X86_POWERNOW_K7 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K7 = "y" && ACPI_PROCESSOR = "y"))
+       default y
+
 config X86_POWERNOW_K8
        tristate "AMD Opteron/Athlon64 PowerNow!"
        depends on CPU_FREQ && EXPERIMENTAL
@@ -98,6 +103,11 @@ config X86_POWERNOW_K8
 
          If in doubt, say N.
 
+config X86_POWERNOW_K8_ACPI
+       bool
+       depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y"))
+       default y
+
 config X86_GX_SUSPMOD
        tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
        depends on CPU_FREQ
index 8c05688..4ba9127 100644 (file)
@@ -108,13 +108,27 @@ acpi_processor_set_performance (
        u32                     value = 0;
        int                     i = 0;
        struct cpufreq_freqs    cpufreq_freqs;
+       cpumask_t               saved_mask;
+       int                     retval;
 
        ACPI_FUNCTION_TRACE("acpi_processor_set_performance");
 
+       /*
+        * TBD: Use something other than set_cpus_allowed.
+        * As set_cpus_allowed is a bit racy, 
+        * with any other set_cpus_allowed for this process.
+        */
+       saved_mask = current->cpus_allowed;
+       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       if (smp_processor_id() != cpu) {
+               return_VALUE(-EAGAIN);
+       }
+       
        if (state == data->acpi_data.state) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
                        "Already at target state (P%d)\n", state));
-               return_VALUE(0);
+               retval = 0;
+               goto migrate_end;
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n",
@@ -144,7 +158,8 @@ acpi_processor_set_performance (
        if (ret) {
                ACPI_DEBUG_PRINT((ACPI_DB_WARN,
                        "Invalid port width 0x%04x\n", bit_width));
-               return_VALUE(ret);
+               retval = ret;
+               goto migrate_end;
        }
 
        /*
@@ -166,7 +181,8 @@ acpi_processor_set_performance (
                if (ret) {      
                        ACPI_DEBUG_PRINT((ACPI_DB_WARN,
                                "Invalid port width 0x%04x\n", bit_width));
-                       return_VALUE(ret);
+                       retval = ret;
+                       goto migrate_end;
                }
                if (value == (u32) data->acpi_data.states[state].status)
                        break;
@@ -183,7 +199,8 @@ acpi_processor_set_performance (
                cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
                cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
                ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n"));
-               return_VALUE(-ENODEV);
+               retval = -ENODEV;
+               goto migrate_end;
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
@@ -192,7 +209,10 @@ acpi_processor_set_performance (
 
        data->acpi_data.state = state;
 
-       return_VALUE(0);
+       retval = 0;
+migrate_end:
+       set_cpus_allowed(current, saved_mask);
+       return_VALUE(retval);
 }
 
 
@@ -266,6 +286,69 @@ acpi_cpufreq_guess_freq (
        
 }
 
+
+/* 
+ * acpi_processor_cpu_init_pdc_est - let BIOS know about the SMP capabilities
+ * of this driver
+ * @perf: processor-specific acpi_io_data struct
+ * @cpu: CPU being initialized
+ *
+ * To avoid issues with legacy OSes, some BIOSes require to be informed of
+ * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC 
+ * accordingly, for Enhanced Speedstep. Actual call to _PDC is done in
+ * driver/acpi/processor.c
+ */
+static void 
+acpi_processor_cpu_init_pdc_est(
+               struct acpi_processor_performance *perf, 
+               unsigned int cpu,
+               struct acpi_object_list *obj_list
+               )
+{
+       union acpi_object *obj;
+       u32 *buf;
+       struct cpuinfo_x86 *c = cpu_data + cpu;
+       ACPI_FUNCTION_TRACE("acpi_processor_cpu_init_pdc_est");
+
+       if (!cpu_has(c, X86_FEATURE_EST))
+               return_VOID;
+
+       /* Initialize pdc. It will be used later. */
+       if (!obj_list)
+               return_VOID;
+               
+       if (!(obj_list->count && obj_list->pointer))
+               return_VOID;
+
+       obj = obj_list->pointer;
+       if ((obj->buffer.length == 12) && obj->buffer.pointer) {
+               buf = (u32 *)obj->buffer.pointer;
+                       buf[0] = ACPI_PDC_REVISION_ID;
+                       buf[1] = 1;
+                       buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
+               perf->pdc = obj_list;
+       }
+       return_VOID;
+}
+
+/* CPU specific PDC initialization */
+static void 
+acpi_processor_cpu_init_pdc(
+               struct acpi_processor_performance *perf, 
+               unsigned int cpu,
+               struct acpi_object_list *obj_list
+               )
+{
+       struct cpuinfo_x86 *c = cpu_data + cpu;
+       ACPI_FUNCTION_TRACE("acpi_processor_cpu_init_pdc");
+       perf->pdc = NULL;
+       if (cpu_has(c, X86_FEATURE_EST))
+               acpi_processor_cpu_init_pdc_est(perf, cpu, obj_list);
+       return_VOID;
+}
+
+
 static int
 acpi_cpufreq_cpu_init (
        struct cpufreq_policy   *policy)
@@ -275,7 +358,14 @@ acpi_cpufreq_cpu_init (
        struct cpufreq_acpi_io  *data;
        unsigned int            result = 0;
 
+       union acpi_object               arg0 = {ACPI_TYPE_BUFFER};
+       u32                             arg0_buf[3];
+       struct acpi_object_list         arg_list = {1, &arg0};
+
        ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_init");
+       /* setup arg_list for _PDC settings */
+        arg0.buffer.length = 12;
+        arg0.buffer.pointer = (u8 *) arg0_buf;
 
        data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
        if (!data)
@@ -284,7 +374,10 @@ acpi_cpufreq_cpu_init (
 
        acpi_io_data[cpu] = data;
 
+       acpi_processor_cpu_init_pdc(&data->acpi_data, cpu, &arg_list);
        result = acpi_processor_register_performance(&data->acpi_data, cpu);
+       data->acpi_data.pdc = NULL;
+
        if (result)
                goto err_free;
 
index fee8b5c..0d10c11 100644 (file)
@@ -52,7 +52,6 @@ struct mtrr_ops {
 };
 
 extern int generic_get_free_region(unsigned long base, unsigned long size);
-extern void generic_init_secondary(void);
 extern int generic_validate_add_page(unsigned long base, unsigned long size,
                                     unsigned int type);
 
index 3346657..8b25160 100644 (file)
@@ -56,6 +56,7 @@ static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int ex
  */
 asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
+       unsigned long i, max_long, bytes, bytes_updated;
        struct thread_struct * t = &current->thread;
        struct tss_struct * tss;
        unsigned long *bitmap;
@@ -81,16 +82,37 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 
        /*
         * do it in the per-thread copy and in the TSS ...
+        *
+        * Disable preemption via get_cpu() - we must not switch away
+        * because the ->io_bitmap_max value must match the bitmap
+        * contents:
         */
+       tss = &per_cpu(init_tss, get_cpu());
+
        set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
-       tss = init_tss + get_cpu();
-       if (tss->io_bitmap_base == IO_BITMAP_OFFSET) { /* already active? */
-               set_bitmap(tss->io_bitmap, from, num, !turn_on);
-       } else {
-               memcpy(tss->io_bitmap, t->io_bitmap_ptr, IO_BITMAP_BYTES);
-               tss->io_bitmap_base = IO_BITMAP_OFFSET; /* Activate it in the TSS */
-       }
+
+       /*
+        * Search for a (possibly new) maximum. This is simple and stupid,
+        * to keep it obviously correct:
+        */
+       max_long = 0;
+       for (i = 0; i < IO_BITMAP_LONGS; i++)
+               if (t->io_bitmap_ptr[i] != ~0UL)
+                       max_long = i;
+
+       bytes = (max_long + 1) * sizeof(long);
+       bytes_updated = max(bytes, t->io_bitmap_max);
+
+       t->io_bitmap_max = bytes;
+
+       /*
+        * Sets the lazy trigger so that the next I/O operation will
+        * reload the correct bitmap.
+        */
+       tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
+
        put_cpu();
+
        return 0;
 }
 
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
new file mode 100644 (file)
index 0000000..4d066cc
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ *  Kernel Probes (KProbes)
+ *  arch/i386/kernel/kprobes.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ *
+ * 2002-Oct    Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
+ *             Probes initial implementation ( includes contributions from
+ *             Rusty Russell).
+ * 2004-July   Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
+ *             interface to access function arguments.
+ */
+
+#include <linux/config.h>
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/spinlock.h>
+#include <linux/preempt.h>
+#include <asm/kdebug.h>
+
+/* kprobe_status settings */
+#define KPROBE_HIT_ACTIVE      0x00000001
+#define KPROBE_HIT_SS          0x00000002
+
+static struct kprobe *current_kprobe;
+static unsigned long kprobe_status, kprobe_old_eflags, kprobe_saved_eflags;
+static struct pt_regs jprobe_saved_regs;
+static long *jprobe_saved_esp;
+/* copy of the kernel stack at the probe fire time */
+static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
+
+/*
+ * returns non-zero if opcode modifies the interrupt flag.
+ */
+static inline int is_IF_modifier(kprobe_opcode_t opcode)
+{
+       switch (opcode) {
+       case 0xfa:              /* cli */
+       case 0xfb:              /* sti */
+       case 0xcf:              /* iret/iretd */
+       case 0x9d:              /* popf/popfd */
+               return 1;
+       }
+       return 0;
+}
+
+void arch_prepare_kprobe(struct kprobe *p)
+{
+       memcpy(p->insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+}
+
+static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
+{
+       *p->addr = p->opcode;
+       regs->eip = (unsigned long)p->addr;
+}
+
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+       regs->eflags |= TF_MASK;
+       regs->eflags &= ~IF_MASK;
+       regs->eip = (unsigned long)&p->insn;
+}
+
+/*
+ * Interrupts are disabled on entry as trap3 is an interrupt gate and they
+ * remain disabled thorough out this function.
+ */
+static inline int kprobe_handler(struct pt_regs *regs)
+{
+       struct kprobe *p;
+       int ret = 0;
+       u8 *addr = (u8 *) (regs->eip - 1);
+
+       /* We're in an interrupt, but this is clear and BUG()-safe. */
+       preempt_disable();
+
+       /* Check we're not actually recursing */
+       if (kprobe_running()) {
+               /* We *are* holding lock here, so this is safe.
+                  Disarm the probe we just hit, and ignore it. */
+               p = get_kprobe(addr);
+               if (p) {
+                       disarm_kprobe(p, regs);
+                       ret = 1;
+               } else {
+                       p = current_kprobe;
+                       if (p->break_handler && p->break_handler(p, regs)) {
+                               goto ss_probe;
+                       }
+               }
+               /* If it's not ours, can't be delete race, (we hold lock). */
+               goto no_kprobe;
+       }
+
+       lock_kprobes();
+       p = get_kprobe(addr);
+       if (!p) {
+               unlock_kprobes();
+               if (*addr != BREAKPOINT_INSTRUCTION) {
+                       /*
+                        * The breakpoint instruction was removed right
+                        * after we hit it.  Another cpu has removed
+                        * either a probepoint or a debugger breakpoint
+                        * at this address.  In either case, no further
+                        * handling of this interrupt is appropriate.
+                        */
+                       ret = 1;
+               }
+               /* Not one of ours: let kernel handle it */
+               goto no_kprobe;
+       }
+
+       kprobe_status = KPROBE_HIT_ACTIVE;
+       current_kprobe = p;
+       kprobe_saved_eflags = kprobe_old_eflags
+           = (regs->eflags & (TF_MASK | IF_MASK));
+       if (is_IF_modifier(p->opcode))
+               kprobe_saved_eflags &= ~IF_MASK;
+
+       if (p->pre_handler(p, regs)) {
+               /* handler has already set things up, so skip ss setup */
+               return 1;
+       }
+
+      ss_probe:
+       prepare_singlestep(p, regs);
+       kprobe_status = KPROBE_HIT_SS;
+       return 1;
+
+      no_kprobe:
+       preempt_enable_no_resched();
+       return ret;
+}
+
+/*
+ * Called after single-stepping.  p->addr is the address of the
+ * instruction whose first byte has been replaced by the "int 3"
+ * instruction.  To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction.  The address of this
+ * copy is p->insn.
+ *
+ * This function prepares to return from the post-single-step
+ * interrupt.  We have to fix up the stack as follows:
+ *
+ * 0) Except in the case of absolute or indirect jump or call instructions,
+ * the new eip is relative to the copied instruction.  We need to make
+ * it relative to the original instruction.
+ *
+ * 1) If the single-stepped instruction was pushfl, then the TF and IF
+ * flags are set in the just-pushed eflags, and may need to be cleared.
+ *
+ * 2) If the single-stepped instruction was a call, the return address
+ * that is atop the stack is the address following the copied instruction.
+ * We need to make it the address following the original instruction.
+ */
+static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+       unsigned long *tos = (unsigned long *)&regs->esp;
+       unsigned long next_eip = 0;
+       unsigned long copy_eip = (unsigned long)&p->insn;
+       unsigned long orig_eip = (unsigned long)p->addr;
+
+       switch (p->insn[0]) {
+       case 0x9c:              /* pushfl */
+               *tos &= ~(TF_MASK | IF_MASK);
+               *tos |= kprobe_old_eflags;
+               break;
+       case 0xe8:              /* call relative - Fix return addr */
+               *tos = orig_eip + (*tos - copy_eip);
+               break;
+       case 0xff:
+               if ((p->insn[1] & 0x30) == 0x10) {
+                       /* call absolute, indirect */
+                       /* Fix return addr; eip is correct. */
+                       next_eip = regs->eip;
+                       *tos = orig_eip + (*tos - copy_eip);
+               } else if (((p->insn[1] & 0x31) == 0x20) ||     /* jmp near, absolute indirect */
+                          ((p->insn[1] & 0x31) == 0x21)) {     /* jmp far, absolute indirect */
+                       /* eip is correct. */
+                       next_eip = regs->eip;
+               }
+               break;
+       case 0xea:              /* jmp absolute -- eip is correct */
+               next_eip = regs->eip;
+               break;
+       default:
+               break;
+       }
+
+       regs->eflags &= ~TF_MASK;
+       if (next_eip) {
+               regs->eip = next_eip;
+       } else {
+               regs->eip = orig_eip + (regs->eip - copy_eip);
+       }
+}
+
+/*
+ * Interrupts are disabled on entry as trap1 is an interrupt gate and they
+ * remain disabled thoroughout this function.  And we hold kprobe lock.
+ */
+static inline int post_kprobe_handler(struct pt_regs *regs)
+{
+       if (!kprobe_running())
+               return 0;
+
+       if (current_kprobe->post_handler)
+               current_kprobe->post_handler(current_kprobe, regs, 0);
+
+       resume_execution(current_kprobe, regs);
+       regs->eflags |= kprobe_saved_eflags;
+
+       unlock_kprobes();
+       preempt_enable_no_resched();
+
+       /*
+        * if somebody else is singlestepping across a probe point, eflags
+        * will have TF set, in which case, continue the remaining processing
+        * of do_debug, as if this is not a probe hit.
+        */
+       if (regs->eflags & TF_MASK)
+               return 0;
+
+       return 1;
+}
+
+/* Interrupts disabled, kprobe_lock held. */
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+       if (current_kprobe->fault_handler
+           && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+               return 1;
+
+       if (kprobe_status & KPROBE_HIT_SS) {
+               resume_execution(current_kprobe, regs);
+               regs->eflags |= kprobe_old_eflags;
+
+               unlock_kprobes();
+               preempt_enable_no_resched();
+       }
+       return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
+                            void *data)
+{
+       struct die_args *args = (struct die_args *)data;
+       switch (val) {
+       case DIE_INT3:
+               if (kprobe_handler(args->regs))
+                       return NOTIFY_STOP;
+               break;
+       case DIE_DEBUG:
+               if (post_kprobe_handler(args->regs))
+                       return NOTIFY_STOP;
+               break;
+       case DIE_GPF:
+               if (kprobe_running() &&
+                   kprobe_fault_handler(args->regs, args->trapnr))
+                       return NOTIFY_STOP;
+               break;
+       case DIE_PAGE_FAULT:
+               if (kprobe_running() &&
+                   kprobe_fault_handler(args->regs, args->trapnr))
+                       return NOTIFY_STOP;
+               break;
+       default:
+               break;
+       }
+       return NOTIFY_DONE;
+}
+
+int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       struct jprobe *jp = container_of(p, struct jprobe, kp);
+       unsigned long addr;
+
+       jprobe_saved_regs = *regs;
+       jprobe_saved_esp = &regs->esp;
+       addr = (unsigned long)jprobe_saved_esp;
+
+       /*
+        * TBD: As Linus pointed out, gcc assumes that the callee
+        * owns the argument space and could overwrite it, e.g.
+        * tailcall optimization. So, to be absolutely safe
+        * we also save and restore enough stack bytes to cover
+        * the argument area.
+        */
+       memcpy(jprobes_stack, (kprobe_opcode_t *) addr, MIN_STACK_SIZE(addr));
+       regs->eflags &= ~IF_MASK;
+       regs->eip = (unsigned long)(jp->entry);
+       return 1;
+}
+
+void jprobe_return(void)
+{
+       preempt_enable_no_resched();
+       asm volatile ("       xchgl   %%ebx,%%esp     \n"
+                     "       int3                      \n"::"b"
+                     (jprobe_saved_esp):"memory");
+}
+void jprobe_return_end(void)
+{
+};
+
+int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       u8 *addr = (u8 *) (regs->eip - 1);
+       unsigned long stack_addr = (unsigned long)jprobe_saved_esp;
+       struct jprobe *jp = container_of(p, struct jprobe, kp);
+
+       if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
+               if (&regs->esp != jprobe_saved_esp) {
+                       struct pt_regs *saved_regs =
+                           container_of(jprobe_saved_esp, struct pt_regs, esp);
+                       printk("current esp %p does not match saved esp %p\n",
+                              &regs->esp, jprobe_saved_esp);
+                       printk("Saved registers for jprobe %p\n", jp);
+                       show_registers(saved_regs);
+                       printk("Current registers\n");
+                       show_registers(regs);
+                       BUG();
+               }
+               *regs = jprobe_saved_regs;
+               memcpy((kprobe_opcode_t *) stack_addr, jprobes_stack,
+                      MIN_STACK_SIZE(stack_addr));
+               return 1;
+       }
+       return 0;
+}
index 10dc6b7..982fe8c 100644 (file)
 #include <linux/pci.h>
 #include <asm/io.h>
 
+struct dma_coherent_mem {
+       void            *virt_base;
+       u32             device_base;
+       int             size;
+       int             flags;
+       unsigned long   *bitmap;
+};
+
 void *dma_alloc_coherent(struct device *dev, size_t size,
                           dma_addr_t *dma_handle, int gfp)
 {
        void *ret;
+       struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+       int order = get_order(size);
        /* ignore region specifiers */
        gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
 
+       if (mem) {
+               int page = bitmap_find_free_region(mem->bitmap, mem->size,
+                                                    order);
+               if (page >= 0) {
+                       *dma_handle = mem->device_base + (page << PAGE_SHIFT);
+                       ret = mem->virt_base + (page << PAGE_SHIFT);
+                       memset(ret, 0, size);
+                       return ret;
+               }
+               if (mem->flags & DMA_MEMORY_EXCLUSIVE)
+                       return NULL;
+       }
+
        if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
                gfp |= GFP_DMA;
 
-       ret = (void *)__get_free_pages(gfp, get_order(size));
+       ret = (void *)__get_free_pages(gfp, order);
 
        if (ret != NULL) {
                memset(ret, 0, size);
@@ -35,5 +58,89 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
 void dma_free_coherent(struct device *dev, size_t size,
                         void *vaddr, dma_addr_t dma_handle)
 {
-       free_pages((unsigned long)vaddr, get_order(size));
+       struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+       int order = get_order(size);
+       
+       if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
+               int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+
+               bitmap_release_region(mem->bitmap, page, order);
+       } else
+               free_pages((unsigned long)vaddr, order);
+}
+
+int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+                               dma_addr_t device_addr, size_t size, int flags)
+{
+       void __iomem *mem_base;
+       int pages = size >> PAGE_SHIFT;
+       int bitmap_size = (pages + 31)/32;
+
+       if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
+               goto out;
+       if (!size)
+               goto out;
+       if (dev->dma_mem)
+               goto out;
+
+       /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
+
+       mem_base = ioremap(bus_addr, size);
+       if (!mem_base)
+               goto out;
+
+       dev->dma_mem = kmalloc(GFP_KERNEL, sizeof(struct dma_coherent_mem));
+       if (!dev->dma_mem)
+               goto out;
+       memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem));
+       dev->dma_mem->bitmap = kmalloc(GFP_KERNEL, bitmap_size);
+       if (!dev->dma_mem->bitmap)
+               goto free1_out;
+       memset(dev->dma_mem->bitmap, 0, bitmap_size);
+
+       dev->dma_mem->virt_base = mem_base;
+       dev->dma_mem->device_base = device_addr;
+       dev->dma_mem->size = pages;
+       dev->dma_mem->flags = flags;
+
+       if (flags & DMA_MEMORY_MAP)
+               return DMA_MEMORY_MAP;
+
+       return DMA_MEMORY_IO;
+
+ free1_out:
+       kfree(dev->dma_mem->bitmap);
+ out:
+       return 0;
+}
+EXPORT_SYMBOL(dma_declare_coherent_memory);
+
+void dma_release_declared_memory(struct device *dev)
+{
+       struct dma_coherent_mem *mem = dev->dma_mem;
+       
+       if(!mem)
+               return;
+       dev->dma_mem = NULL;
+       kfree(mem->bitmap);
+       kfree(mem);
+}
+EXPORT_SYMBOL(dma_release_declared_memory);
+
+void *dma_mark_declared_memory_occupied(struct device *dev,
+                                       dma_addr_t device_addr, size_t size)
+{
+       struct dma_coherent_mem *mem = dev->dma_mem;
+       int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       int pos, err;
+
+       if (!mem)
+               return ERR_PTR(-EINVAL);
+
+       pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
+       err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
+       if (err != 0)
+               return ERR_PTR(err);
+       return mem->virt_base + (pos << PAGE_SHIFT);
 }
+EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
index f8dcf5d..a9711fc 100644 (file)
@@ -200,6 +200,18 @@ unsigned long long monotonic_clock(void)
 }
 EXPORT_SYMBOL(monotonic_clock);
 
+#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
+unsigned long profile_pc(struct pt_regs *regs)
+{
+       unsigned long pc = instruction_pointer(regs);
+
+       if (in_lock_functions(pc))
+               return *(unsigned long *)(regs->ebp + 4);
+
+       return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+#endif
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
@@ -321,11 +333,12 @@ static int time_suspend(struct sys_device *dev, u32 state)
 
 static int time_resume(struct sys_device *dev)
 {
+       unsigned long flags;
        unsigned long sec = get_cmos_time() + clock_cmos_diff;
-       write_seqlock_irq(&xtime_lock);
+       write_seqlock_irqsave(&xtime_lock, flags);
        xtime.tv_sec = sec;
        xtime.tv_nsec = 0;
-       write_sequnlock_irq(&xtime_lock);
+       write_sequnlock_irqrestore(&xtime_lock, flags);
        return 0;
 }
 
index 7ddbf1c..a433cb0 100644 (file)
@@ -7,6 +7,9 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/irq.h>
+#include <linux/sysdev.h>
+#include <linux/timex.h>
+#include <asm/delay.h>
 #include <asm/mpspec.h>
 #include <asm/timer.h>
 #include <asm/smp.h>
@@ -156,3 +159,44 @@ struct timer_opts timer_pit = {
        .monotonic_clock = monotonic_clock_pit,
        .delay = delay_pit,
 };
+
+void setup_pit_timer(void)
+{
+       extern spinlock_t i8253_lock;
+       unsigned long flags;
+
+       spin_lock_irqsave(&i8253_lock, flags);
+       outb_p(0x34,PIT_MODE);          /* binary, mode 2, LSB/MSB, ch 0 */
+       udelay(10);
+       outb_p(LATCH & 0xff , PIT_CH0); /* LSB */
+       udelay(10);
+       outb(LATCH >> 8 , PIT_CH0);     /* MSB */
+       spin_unlock_irqrestore(&i8253_lock, flags);
+}
+
+static int timer_resume(struct sys_device *dev)
+{
+       setup_pit_timer();
+       return 0;
+}
+
+static struct sysdev_class timer_sysclass = {
+       set_kset_name("timer"),
+       .resume = timer_resume,
+};
+
+static struct sys_device device_timer = {
+       .id     = 0,
+       .cls    = &timer_sysclass,
+};
+
+static int __init init_timer_sysfs(void)
+{
+       int error = sysdev_class_register(&timer_sysclass);
+       if (!error)
+               error = sysdev_register(&device_timer);
+       return error;
+}
+
+device_initcall(init_timer_sysfs);
+
diff --git a/arch/i386/kernel/vsyscall.lds.S b/arch/i386/kernel/vsyscall.lds.S
new file mode 100644 (file)
index 0000000..3a8329d
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Linker script for vsyscall DSO.  The vsyscall page is an ELF shared
+ * object prelinked to its virtual address, and with only one read-only
+ * segment (that fits in one page).  This script controls its layout.
+ */
+#include <asm/asm_offsets.h>
+
+SECTIONS
+{
+  . = VSYSCALL_BASE + SIZEOF_HEADERS;
+
+  .hash           : { *(.hash) }               :text
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+
+  /* This linker script is used both with -r and with -shared.
+     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.  */
+  . = VSYSCALL_BASE + 0x400;
+
+  .text           : { *(.text) }               :text =0x90909090
+
+  .eh_frame_hdr   : { *(.eh_frame_hdr) }       :text :eh_frame_hdr
+  .eh_frame       : { KEEP (*(.eh_frame)) }    :text
+  .dynamic        : { *(.dynamic) }            :text :dynamic
+  .useless        : {
+       *(.got.plt) *(.got)
+       *(.data .data.* .gnu.linkonce.d.*)
+       *(.dynbss)
+       *(.bss .bss.* .gnu.linkonce.b.*)
+  }                                            :text
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+  text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+  dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+  eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+  LINUX_2.5 {
+    global:
+       __kernel_vsyscall;
+       __kernel_sigreturn;
+       __kernel_rt_sigreturn;
+
+    local: *;
+  };
+}
+
+/* The ELF entry point can be used to set the AT_SYSINFO value.  */
+ENTRY(__kernel_vsyscall);
index d6fc84f..01f8b1a 100644 (file)
@@ -2,9 +2,9 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/sched.h>
+#include <linux/hardirq.h>
 
 #include <asm/i387.h>
-#include <asm/hardirq.h> 
 
 
 /*
index 784576c..1d1954a 100644 (file)
@@ -51,27 +51,74 @@ struct mip_reg              *host_reg;
 int                    mip_port;
 unsigned long          mip_addr, host_addr;
 
+#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
+static unsigned long cycle_irqs = 0;
+static unsigned long free_irqs = 0;
+static int gsi_map[MAX_GSI_MAPSIZE] = { [0 ... MAX_GSI_MAPSIZE-1] = -1 };
+
+/*
+ * GSI override for ES7000 platforms.
+ */
+
+static int __init
+es7000_gsi_override(int ioapic, int gsi)
+{
+       static int newgsi = 0;
+
+       if (gsi_map[gsi] != -1)
+               gsi = gsi_map[gsi];
+       else if (cycle_irqs ^ free_irqs) {
+               newgsi = find_next_bit(&cycle_irqs, IOAPIC_GSI_BOUND(0), newgsi);
+               __set_bit(newgsi, &free_irqs);
+               gsi_map[gsi] = newgsi;
+               gsi = newgsi;
+               newgsi++;
+               Dprintk("es7000_gsi_override: free_irqs = 0x%lx\n", free_irqs);
+       }
+
+       return gsi;
+}
+
 static int __init
 es7000_rename_gsi(int ioapic, int gsi)
 {
+       static int initialized = 0;
+       int i;
+
+       /*
+        * These should NEVER be true at this point but we'd rather be
+        * safe than sorry.
+        */
+       if (acpi_disabled || acpi_pci_disabled || acpi_noirq)
+               return gsi;
+
        if (ioapic)
-               return gsi;
-       else {
-               if (gsi == 0)
-                       return 13;
-               if (gsi == 1)
-                       return 16;
-               if (gsi == 4)
-                       return 17;
-               if (gsi == 6)
-                       return 18;
-               if (gsi == 7)
-                       return 19;
-               if (gsi == 8)
-                       return 20;
-               return gsi;
-        }
+               return gsi;
+
+       if (!initialized) {
+               unsigned long tmp_irqs = 0;
+
+               for (i = 0; i < nr_ioapic_registers[0]; i++)
+                       __set_bit(mp_irqs[i].mpc_srcbusirq, &tmp_irqs);
+
+               cycle_irqs = (~tmp_irqs & io_apic_irqs & ((1 << IOAPIC_GSI_BOUND(0)) - 1));
+
+               initialized = 1;
+               Dprintk("es7000_rename_gsi: cycle_irqs = 0x%lx\n", cycle_irqs);
+       }
+
+       for (i = 0; i < nr_ioapic_registers[0]; i++) {
+               if (mp_irqs[i].mpc_srcbusirq == gsi) {
+                       if (mp_irqs[i].mpc_dstirq == gsi)
+                               return gsi;
+                       else
+                               return es7000_gsi_override(0, gsi);
+               }
+       }
+
+       return gsi;
 }
+#endif // (CONFIG_X86_IO_APIC) && (CONFIG_ACPI_INTERPRETER || CONFIG_ACPI_BOOT)
 
 /*
  * Parse the OEM Table
@@ -193,7 +240,7 @@ find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length)
                        }
                }
        }
-       printk("ES7000: did not find Unisys ACPI OEM table!\n");
+       Dprintk("ES7000: did not find Unisys ACPI OEM table!\n");
        return -1;
 }
 
@@ -237,7 +284,7 @@ es7000_mip_write(struct mip_reg *mip_reg)
        }
 
        status = ((unsigned long long)mip_reg->off_0 &
-               (unsigned long long)0xffff0000000000) >> 48;
+               (unsigned long long)0xffff0000000000ULL) >> 48;
        mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 &
                (unsigned long long)~MIP_VALID);
        return status;
index f88a6c8..a6270ee 100644 (file)
@@ -57,7 +57,8 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
         * Fall back to the standard layout if the personality
         * bit is set, or if the expected stack growth is unlimited:
         */
-       if (sysctl_legacy_va_layout || (current->personality & ADDR_COMPAT_LAYOUT) ||
+       if (sysctl_legacy_va_layout ||
+                       (current->personality & ADDR_COMPAT_LAYOUT) ||
                        current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
                mm->mmap_base = TASK_UNMAPPED_BASE;
                mm->get_unmapped_area = arch_get_unmapped_area;
@@ -65,7 +66,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
        } else {
                mm->mmap_base = mmap_base(mm);
                mm->get_unmapped_area = arch_get_unmapped_area_topdown;
-               mm->get_unmapped_exec_area = arch_get_unmapped_exec_area;
                mm->unmap_area = arch_unmap_area_topdown;
        }
 }
index 5f6cc84..0d4e00f 100644 (file)
@@ -70,7 +70,7 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
 
        /* enable active counters */
        for (i = 0; i < NUM_COUNTERS; ++i) {
-               if (counter_config[i].event) {
+               if (counter_config[i].enabled) {
                        reset_value[i] = counter_config[i].count;
 
                        CTR_WRITE(counter_config[i].count, msrs, i);
@@ -96,7 +96,7 @@ static int athlon_check_ctrs(unsigned int const cpu,
 {
        unsigned int low, high;
        int i;
-       unsigned long eip = instruction_pointer(regs);
+       unsigned long eip = profile_pc(regs);
        int is_kernel = !user_mode(regs);
 
        for (i = 0 ; i < NUM_COUNTERS; ++i) {
index 21578b2..0cc8065 100644 (file)
@@ -67,7 +67,7 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
 
        /* enable active counters */
        for (i = 0; i < NUM_COUNTERS; ++i) {
-               if (counter_config[i].event) {
+               if (counter_config[i].enabled) {
                        reset_value[i] = counter_config[i].count;
 
                        CTR_WRITE(counter_config[i].count, msrs, i);
@@ -91,7 +91,7 @@ static int ppro_check_ctrs(unsigned int const cpu,
 {
        unsigned int low, high;
        int i;
-       unsigned long eip = instruction_pointer(regs);
+       unsigned long eip = profile_pc(regs);
        int is_kernel = !user_mode(regs);
  
        for (i = 0 ; i < NUM_COUNTERS; ++i) {
index 383827d..88c832a 100644 (file)
@@ -70,7 +70,7 @@ static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
        int i;
 
        DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
-       for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
+       list_for_each(ln, &b->devices) {
                d = pci_dev_b(ln);
                if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
                        seen_host_bridge++;
index 2ebc7c6..ec859ad 100644 (file)
@@ -164,7 +164,7 @@ static void __init pcibios_allocate_resources(int pass)
        }
 }
 
-static void __init pcibios_assign_resources(void)
+static int __init pcibios_assign_resources(void)
 {
        struct pci_dev *dev = NULL;
        int idx;
@@ -204,6 +204,7 @@ static void __init pcibios_assign_resources(void)
                                pci_assign_resource(dev, PCI_ROM_RESOURCE);
                }
        }
+       return 0;
 }
 
 void __init pcibios_resource_survey(void)
@@ -212,9 +213,14 @@ void __init pcibios_resource_survey(void)
        pcibios_allocate_bus_resources(&pci_root_buses);
        pcibios_allocate_resources(0);
        pcibios_allocate_resources(1);
-       pcibios_assign_resources();
 }
 
+/**
+ * called in fs_initcall (one below subsys_initcall),
+ * give a chance for motherboard reserve resources
+ */
+fs_initcall(pcibios_assign_resources);
+
 int pcibios_enable_resources(struct pci_dev *dev, int mask)
 {
        u16 cmd, old_cmd;
index 0b95fc4..f42c453 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * Copyright (C) 2004 Matthew Wilcox <matthew@wil.cx>
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * This code is released under the GNU General Public License version 2.
+ */
+
 /*
  * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
  */
@@ -9,7 +16,7 @@
 /* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
 u32 pci_mmcfg_base_addr;
 
-#define mmcfg_virt_addr (fix_to_virt(FIX_PCIE_MCFG))
+#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
 
 /* The base address of the last MMCONFIG device accessed */
 static u32 mmcfg_last_accessed_device;
index d774500..c804673 100644 (file)
@@ -100,10 +100,7 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
        }
        pcibios_last_bus = -1;
 }
-
-struct pci_fixup pcibios_fixups[] = {
-       { PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82451NX,    pci_fixup_i450nx },
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
 
 static int __init pci_numa_init(void)
 {
index 700188d..50fc1f3 100644 (file)
@@ -365,7 +365,7 @@ void __devinit pcibios_sort(void)
                idx = found = 0;
                while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) {
                        idx++;
-                       for (ln=pci_devices.next; ln != &pci_devices; ln=ln->next) {
+                       list_for_each(ln, &pci_devices) {
                                d = pci_dev_g(ln);
                                if (d->bus->number == bus && d->devfn == devfn) {
                                        list_del(&d->global_list);
index 2e1c9ab..8cfa4e8 100644 (file)
@@ -1,3 +1,2 @@
 obj-$(CONFIG_PM)               += cpu.o
-obj-$(CONFIG_PM_DISK)          += pmdisk.o
 obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
new file mode 100644 (file)
index 0000000..19edc8b
--- /dev/null
@@ -0,0 +1,64 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+choice
+       prompt "Physical memory granularity"
+       default IA64_GRANULE_64MB
+
+config IA64_GRANULE_16MB
+       bool "16MB"
+       help
+         IA-64 identity-mapped regions use a large page size called "granules".
+
+         Select "16MB" for a small granule size.
+         Select "64MB" for a large granule size.  This is the current default.
+
+config IA64_GRANULE_64MB
+       bool "64MB"
+       depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_SGI_SN2)
+
+endchoice
+
+config IA64_PRINT_HAZARDS
+       bool "Print possible IA-64 dependency violations to console"
+       depends on DEBUG_KERNEL
+       help
+         Selecting this option prints more information for Illegal Dependency
+         Faults, that is, for Read-after-Write (RAW), Write-after-Write (WAW),
+         or Write-after-Read (WAR) violations.  This option is ignored if you
+         are compiling for an Itanium A step processor
+         (CONFIG_ITANIUM_ASTEP_SPECIFIC).  If you're unsure, select Y.
+
+config DISABLE_VHPT
+       bool "Disable VHPT"
+       depends on DEBUG_KERNEL
+       help
+         The Virtual Hash Page Table (VHPT) enhances virtual address
+         translation performance.  Normally you want the VHPT active but you
+         can select this option to disable the VHPT for debugging.  If you're
+         unsure, answer N.
+
+config IA64_DEBUG_CMPXCHG
+       bool "Turn on compare-and-exchange bug checking (slow!)"
+       depends on DEBUG_KERNEL
+       help
+         Selecting this option turns on bug checking for the IA-64
+         compare-and-exchange instructions.  This is slow!  Itaniums
+         from step B3 or later don't have this problem. If you're unsure,
+         select N.
+
+config IA64_DEBUG_IRQ
+       bool "Turn on irq debug checks (slow!)"
+       depends on DEBUG_KERNEL
+       help
+         Selecting this option turns on bug checking for the IA-64 irq_save
+         and restore instructions.  It's useful for tracking down spinlock
+         problems, but slow!  If you're unsure, select N.
+
+config SYSVIPC_COMPAT
+       bool
+       depends on COMPAT && SYSVIPC
+       default y
+
+endmenu
diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig
new file mode 100644 (file)
index 0000000..f16fd2e
--- /dev/null
@@ -0,0 +1,1132 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Tue Sep 28 13:26:53 2004
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_HOTPLUG=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+# CONFIG_IA64_GENERIC is not set
+CONFIG_IA64_DIG=y
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+CONFIG_ITANIUM=y
+# CONFIG_MCKINLEY is not set
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_IA64_BRL_EMU=y
+# CONFIG_ITANIUM_BSTEP_SPECIFIC is not set
+CONFIG_IA64_L1_CACHE_SHIFT=6
+# CONFIG_NUMA is not set
+# CONFIG_VIRTUAL_MEM_MAP is not set
+# CONFIG_IA64_CYCLONE is not set
+CONFIG_IOSAPIC=y
+CONFIG_FORCE_MAX_ZONEORDER=18
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_PREEMPT=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_IA32_SUPPORT=y
+CONFIG_COMPAT=y
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_ACPI=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# 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_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_SIZE=4096
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=m
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=m
+# 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 is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=m
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# 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
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+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
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# 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_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+CONFIG_SCSI_QLOGIC_1280=y
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# 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_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# 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=y
+# CONFIG_EEPRO100_PIO 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_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY 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_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO 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_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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW 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_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+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 is not set
+CONFIG_EFI_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=m
+CONFIG_AGP_I460=m
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+CONFIG_DRM_R128=m
+# CONFIG_DRM_RADEON is not set
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# 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_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X 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
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+# CONFIG_SND_SEQUENCER_OSS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_OPL3_LIB=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CS46XX is not set
+CONFIG_SND_CS4281=m
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VX222 is not set
+
+#
+# ALSA USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+CONFIG_USB_UHCI_HCD=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_AUDIO=m
+CONFIG_USB_BLUETOOTH_TTY=m
+CONFIG_USB_MIDI=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# 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_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# 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_TIGL 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_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR 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_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=y
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# 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=y
+# CONFIG_MSDOS_FS is not set
+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=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# 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=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_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 is not set
+# 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=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_EFI_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=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=m
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_IA64_GRANULE_16MB is not set
+CONFIG_IA64_GRANULE_64MB=y
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC 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_WHIRLPOOL is not set
+CONFIG_CRYPTO_DES=y
+# 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_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
index e64003e..a268473 100644 (file)
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc1
+# Tue Aug 24 15:08:24 2004
 #
 
 #
@@ -126,6 +128,7 @@ CONFIG_PCI_NAMES=y
 CONFIG_HOTPLUG_PCI=m
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 CONFIG_HOTPLUG_PCI_ACPI=m
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
 # CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
@@ -172,6 +175,7 @@ CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_SIZE=4096
 
@@ -313,6 +317,7 @@ CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=m
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
@@ -365,6 +370,7 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -575,6 +581,7 @@ CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_STALDRV is not set
+CONFIG_SGI_SNSC=y
 
 #
 # Serial drivers
@@ -766,6 +773,7 @@ CONFIG_USB=m
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 
 #
 # USB Host Controller Drivers
@@ -918,6 +926,8 @@ CONFIG_UDF_NLS=y
 CONFIG_FAT_FS=y
 # CONFIG_MSDOS_FS is not set
 CONFIG_VFAT_FS=y
+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
@@ -945,7 +955,6 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -970,6 +979,7 @@ CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
 CONFIG_SMB_NLS_DEFAULT=y
 CONFIG_SMB_NLS_REMOTE="cp437"
@@ -1006,7 +1016,7 @@ CONFIG_EFI_PARTITION=y
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
 CONFIG_NLS_CODEPAGE_775=m
 CONFIG_NLS_CODEPAGE_850=m
@@ -1030,7 +1040,7 @@ CONFIG_NLS_ISO8859_8=m
 CONFIG_NLS_CODEPAGE_1250=m
 CONFIG_NLS_CODEPAGE_1251=m
 # CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_2=m
 CONFIG_NLS_ISO8859_3=m
 CONFIG_NLS_ISO8859_4=m
@@ -1067,18 +1077,18 @@ CONFIG_CRC32=y
 #
 # Kernel hacking
 #
-CONFIG_IA64_GRANULE_16MB=y
-# CONFIG_IA64_GRANULE_64MB is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_IA64_PRINT_HAZARDS is not set
-# CONFIG_DISABLE_VHPT is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
-# CONFIG_DEBUG_INFO is not set
 CONFIG_SYSVIPC_COMPAT=y
 
 #
@@ -1101,11 +1111,12 @@ CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES_GENERIC 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_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
new file mode 100644 (file)
index 0000000..ce94125
--- /dev/null
@@ -0,0 +1,1028 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Tue Sep 28 09:03:25 2004
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=20
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+# CONFIG_IA64_GENERIC is not set
+CONFIG_IA64_DIG=y
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_IA64_L1_CACHE_SHIFT=7
+# CONFIG_NUMA is not set
+CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+CONFIG_FORCE_MAX_ZONEORDER=18
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_PREEMPT is not set
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_IA32_SUPPORT=y
+CONFIG_COMPAT=y
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_ACPI=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=m
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_ACPI=m
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# 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_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_SIZE=4096
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=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 is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# 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
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# 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
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+
+#
+# SCSI low-level drivers
+#
+# 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_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+CONFIG_SCSI_QLOGIC_FC=y
+# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
+CONFIG_SCSI_QLOGIC_1280=y
+CONFIG_SCSI_QLA2XXX=y
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_MAX_SGE=40
+# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 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=m
+# CONFIG_EEPRO100_PIO is not set
+CONFIG_E100=m
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+CONFIG_TIGON3=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO 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_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=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+CONFIG_GAMEPORT=m
+CONFIG_SOUND_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_VORTEX is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# CONFIG_GAMEPORT_CS461x is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW 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_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_ACPI=y
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+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 is not set
+CONFIG_EFI_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=m
+CONFIG_AGP_I460=m
+CONFIG_DRM=y
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_RAW_DRIVER=m
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+CONFIG_HPET_MMAP=y
+CONFIG_MAX_RAW_DEVS=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_UHCI_HCD=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# 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_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# 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_TIGL 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_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# 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=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+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_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# 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=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_POSIX is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_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 is not set
+# 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=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+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 is not set
+CONFIG_NLS_ISO8859_1=y
+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
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WHIRLPOOL is not set
+CONFIG_CRYPTO_DES=m
+# 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_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
index e9eda73..7ef08d3 100644 (file)
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2-aegl
+# Mon Sep 27 19:03:13 2004
 #
 
 #
@@ -7,33 +9,45 @@
 #
 CONFIG_EXPERIMENTAL=y
 # CONFIG_CLEAN_COMPILE is not set
-CONFIG_STANDALONE=y
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
 
 #
 # Processor type and features
@@ -44,54 +58,53 @@ CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_EFI=y
-# CONFIG_ITANIUM is not set
-CONFIG_MCKINLEY=y
+CONFIG_GENERIC_IOMAP=y
 # CONFIG_IA64_GENERIC is not set
 # CONFIG_IA64_DIG is not set
 CONFIG_IA64_HP_ZX1=y
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
-CONFIG_ACPI=y
-CONFIG_ACPI_INTERPRETER=y
-CONFIG_ACPI_KERNEL_CONFIG=y
 CONFIG_IA64_L1_CACHE_SHIFT=7
-# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set
 # CONFIG_NUMA is not set
 CONFIG_VIRTUAL_MEM_MAP=y
-CONFIG_IA64_MCA=y
 # CONFIG_IA64_CYCLONE is not set
-CONFIG_PM=y
 CONFIG_IOSAPIC=y
 CONFIG_FORCE_MAX_ZONEORDER=18
-# CONFIG_HUGETLB_PAGE_SIZE_4GB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_1GB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set
-CONFIG_HUGETLB_PAGE_SIZE_64MB=y
-# CONFIG_HUGETLB_PAGE_SIZE_16MB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
-CONFIG_IA64_PAL_IDLE=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=16
+# CONFIG_HOTPLUG_CPU is not set
 # CONFIG_PREEMPT is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
 CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_ACPI=y
+
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
 CONFIG_ACPI_BUTTON=y
 CONFIG_ACPI_FAN=y
 CONFIG_ACPI_PROCESSOR=y
@@ -101,8 +114,13 @@ CONFIG_ACPI_BUS=y
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_PCI=y
 CONFIG_ACPI_SYSTEM=y
+
+#
+# Bus options (PCI, PCMCIA)
+#
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
 
@@ -112,6 +130,7 @@ CONFIG_PCI_NAMES=y
 CONFIG_HOTPLUG_PCI=y
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 CONFIG_HOTPLUG_PCI_ACPI=y
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
 # CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
@@ -122,20 +141,27 @@ CONFIG_HOTPLUG_PCI_ACPI=y
 # CONFIG_PCMCIA is not set
 
 #
-# Parallel port support
+# Device Drivers
 #
-# CONFIG_PARPORT is not set
 
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
 
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
 #
 # Plug and Play support
 #
@@ -143,7 +169,6 @@ CONFIG_HOTPLUG_PCI_ACPI=y
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -151,10 +176,11 @@ CONFIG_HOTPLUG_PCI_ACPI=y
 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=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_DCSSBLK is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -165,9 +191,9 @@ CONFIG_BLK_DEV_IDE=y
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -187,7 +213,6 @@ CONFIG_BLK_DEV_GENERIC=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 # CONFIG_IDEDMA_PCI_AUTO is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
@@ -208,32 +233,12 @@ CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
 
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=y
-CONFIG_FUSION_BOOT=y
-CONFIG_FUSION_MAX_SGE=40
-
 #
 # SCSI device support
 #
@@ -254,21 +259,28 @@ CONFIG_CHR_DEV_SG=y
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_REPORT_LUNS=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
 #
 # SCSI low-level drivers
 #
 # 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_ADVANSYS is not set
-CONFIG_SCSI_MEGARAID=y
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
@@ -285,6 +297,7 @@ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
@@ -301,6 +314,28 @@ CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
 
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_MAX_SGE=40
+# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
 #
 # Networking support
 #
@@ -322,19 +357,17 @@ CONFIG_IP_MULTICAST=y
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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_TUNNEL is not set
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -353,10 +386,11 @@ CONFIG_IP_NF_ARPTABLES=y
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP 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
@@ -371,21 +405,27 @@ CONFIG_IPV6_SCTP__=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -429,6 +469,7 @@ CONFIG_E100=y
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -441,7 +482,6 @@ CONFIG_E1000=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 CONFIG_TIGON3=y
 
@@ -449,47 +489,39 @@ CONFIG_TIGON3=y
 # Ethernet (10000 Mbit)
 #
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
 #
 # CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
 
 #
-# Amateur Radio support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_HAMRADIO is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# IrDA (infrared) support
+# Wan interfaces
 #
-# CONFIG_IRDA is not set
+# 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
 
 #
-# Bluetooth support
+# ISDN subsystem
 #
-# CONFIG_BT is not set
+# CONFIG_ISDN is not set
 
 #
-# ISDN subsystem
+# Telephony Support
 #
-# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
 
 #
 # Input device support
@@ -518,6 +550,7 @@ CONFIG_SERIO=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -541,7 +574,6 @@ CONFIG_HW_CONSOLE=y
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_HCDP=y
 CONFIG_SERIAL_8250_ACPI=y
 CONFIG_SERIAL_8250_NR_UARTS=8
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -559,12 +591,6 @@ CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
 #
 # IPMI
 #
@@ -575,8 +601,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
-# CONFIG_GEN_RTC is not set
 CONFIG_EFI_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -585,7 +609,6 @@ CONFIG_EFI_RTC=y
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
 CONFIG_AGP=y
 CONFIG_AGP_HP_ZX1=y
 CONFIG_DRM=y
@@ -596,6 +619,7 @@ CONFIG_DRM_RADEON=y
 # CONFIG_DRM_MGA is not set
 # CONFIG_DRM_SIS is not set
 # CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
 
 #
 # I2C support
@@ -608,11 +632,13 @@ CONFIG_I2C_CHARDEV=y
 #
 CONFIG_I2C_ALGOBIT=y
 CONFIG_I2C_ALGOPCF=y
+# 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
@@ -630,29 +656,55 @@ CONFIG_I2C_ALGOPCF=y
 # 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
 
 #
-# I2C Hardware Sensors Chip support
+# Hardware Sensors Chip support
 #
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
 
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
 #
 # Multimedia devices
 #
@@ -663,6 +715,167 @@ CONFIG_I2C_ALGOPCF=y
 #
 # CONFIG_DVB is not set
 
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# 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_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_DEBUG=y
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY 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_PM3 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# 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
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_BANDWIDTH=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# 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_TIGL 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_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
 #
 # File systems
 #
@@ -693,6 +906,7 @@ CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 # CONFIG_ZISOFS is not set
 CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -700,6 +914,8 @@ CONFIG_UDF_FS=y
 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
 
 #
@@ -707,6 +923,7 @@ CONFIG_VFAT_FS=y
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
@@ -747,11 +964,12 @@ CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=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_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -769,7 +987,6 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
@@ -803,6 +1020,7 @@ CONFIG_NLS_CODEPAGE_874=y
 CONFIG_NLS_ISO8859_8=y
 # CONFIG_NLS_CODEPAGE_1250 is not set
 CONFIG_NLS_CODEPAGE_1251=y
+# CONFIG_NLS_ASCII is not set
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_2=y
 CONFIG_NLS_ISO8859_3=y
@@ -818,227 +1036,12 @@ CONFIG_NLS_KOI8_R=y
 CONFIG_NLS_KOI8_U=y
 CONFIG_NLS_UTF8=y
 
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
-CONFIG_FB_RADEON=y
-CONFIG_FB_RADEON_I2C=y
-CONFIG_FB_RADEON_DEBUG=y
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY 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_PM3 is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# 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
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-# CONFIG_SND_SEQ_DUMMY is not set
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# PCI devices
-#
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
-CONFIG_SND_FM801=y
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VX222 is not set
-
-#
-# ALSA USB devices
-#
-# CONFIG_SND_USB_AUDIO is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-CONFIG_USB_BANDWIDTH=y
-# CONFIG_USB_DYNAMIC_MINORS is not set
-
-#
-# USB Host Controller Drivers
-#
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_UHCI_HCD=y
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-CONFIG_USB_STORAGE=y
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-
-#
-# USB Human Interface Devices (HID)
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_XPAD is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network adaptors
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET is not set
-
-#
-# 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_TIGL 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_LED is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
 #
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 
 #
 # Profiling support
@@ -1048,18 +1051,19 @@ CONFIG_CRC32=y
 #
 # Kernel hacking
 #
-CONFIG_IA64_GRANULE_16MB=y
-# CONFIG_IA64_GRANULE_64MB is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_IA64_PRINT_HAZARDS=y
-# CONFIG_DISABLE_VHPT is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+CONFIG_IA64_PRINT_HAZARDS=y
+# CONFIG_DISABLE_VHPT is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_SYSVIPC_COMPAT=y
 
 #
 # Security options
@@ -1069,4 +1073,26 @@ CONFIG_MAGIC_SYSRQ=y
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC 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_WHIRLPOOL is not set
+CONFIG_CRYPTO_DES=y
+# 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_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
index 5333e61..e50c446 100644 (file)
@@ -191,7 +191,7 @@ static unsigned long iovp_shift;
 static unsigned long iovp_mask;
 
 struct ioc {
-       void            *ioc_hpa;       /* I/O MMU base address */
+       void __iomem    *ioc_hpa;       /* I/O MMU base address */
        char            *res_map;       /* resource map, bit == pdir entry */
        u64             *pdir_base;     /* physical base address */
        unsigned long   ibase;          /* pdir IOV Space base */
@@ -203,6 +203,9 @@ struct ioc {
                                        /* clearing pdir to prevent races with allocations. */
        unsigned int    res_bitshift;   /* from the RIGHT! */
        unsigned int    res_size;       /* size of resource map in bytes */
+#ifdef CONFIG_NUMA
+       unsigned int    node;           /* node where this IOC lives */
+#endif
 #if DELAYED_RESOURCE_CNT > 0
        spinlock_t      saved_lock;     /* may want to try to get this on a separate cacheline */
                                        /* than res_lock for bigger systems. */
@@ -1057,7 +1060,24 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int
        struct ioc *ioc;
        void *addr;
 
+       ioc = GET_IOC(dev);
+       ASSERT(ioc);
+
+#ifdef CONFIG_NUMA
+       {
+               struct page *page;
+               page = alloc_pages_node(ioc->node == MAX_NUMNODES ?
+                                       numa_node_id() : ioc->node, flags,
+                                       get_order(size));
+
+               if (unlikely(!page))
+                       return NULL;
+
+               addr = page_address(page);
+       }
+#else
        addr = (void *) __get_free_pages(flags, get_order(size));
+#endif
        if (unlikely(!addr))
                return NULL;
 
@@ -1081,8 +1101,6 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int
         * If device can't bypass or bypass is disabled, pass the 32bit fake
         * device to map single to get an iova mapping.
         */
-       ioc = GET_IOC(dev);
-       ASSERT(ioc);
        *dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0);
 
        return addr;
@@ -1135,7 +1153,7 @@ sba_fill_pdir(
 {
        struct scatterlist *dma_sg = startsg;   /* pointer to current DMA */
        int n_mappings = 0;
-       u64 *pdirp = 0;
+       u64 *pdirp = NULL;
        unsigned long dma_offset = 0;
 
        dma_sg--;
@@ -1799,6 +1817,10 @@ ioc_show(struct seq_file *s, void *v)
 
        seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n",
                ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF));
+#ifdef CONFIG_NUMA
+       if (ioc->node != MAX_NUMNODES)
+               seq_printf(s, "NUMA node       : %d\n", ioc->node);
+#endif
        seq_printf(s, "IOVA size       : %ld MB\n", ((ioc->pdir_size >> 3) * iovp_size)/(1024*1024));
        seq_printf(s, "IOVA page size  : %ld kb\n", iovp_size/1024);
 
@@ -1853,7 +1875,7 @@ ioc_proc_init(void)
 {
        struct proc_dir_entry *dir, *entry;
 
-       dir = proc_mkdir("bus/mckinley", 0);
+       dir = proc_mkdir("bus/mckinley", NULL);
        if (!dir)
                return;
 
@@ -1899,6 +1921,58 @@ sba_connect_bus(struct pci_bus *bus)
        printk(KERN_WARNING "No IOC for PCI Bus %04x:%02x in ACPI\n", pci_domain_nr(bus), bus->number);
 }
 
+#ifdef CONFIG_NUMA
+static void __init
+sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
+{
+       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+       union acpi_object *obj;
+       acpi_handle phandle;
+       unsigned int node;
+
+       ioc->node = MAX_NUMNODES;
+
+       /*
+        * Check for a _PXM on this node first.  We don't typically see
+        * one here, so we'll end up getting it from the parent.
+        */
+       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer))) {
+               if (ACPI_FAILURE(acpi_get_parent(handle, &phandle)))
+                       return;
+
+               /* Reset the acpi buffer */
+               buffer.length = ACPI_ALLOCATE_BUFFER;
+               buffer.pointer = NULL;
+
+               if (ACPI_FAILURE(acpi_evaluate_object(phandle, "_PXM", NULL,
+                                                     &buffer)))
+                       return;
+       }
+
+       if (!buffer.length || !buffer.pointer)
+               return;
+
+       obj = buffer.pointer;
+
+       if (obj->type != ACPI_TYPE_INTEGER ||
+           obj->integer.value >= MAX_PXM_DOMAINS) {
+               acpi_os_free(buffer.pointer);
+               return;
+       }
+
+       node = pxm_to_nid_map[obj->integer.value];
+       acpi_os_free(buffer.pointer);
+
+       if (node >= MAX_NUMNODES || !node_online(node))
+               return;
+
+       ioc->node = node;
+       return;
+}
+#else
+#define sba_map_ioc_to_node(ioc, handle)
+#endif
+
 static int __init
 acpi_sba_ioc_add(struct acpi_device *device)
 {
@@ -1941,6 +2015,8 @@ acpi_sba_ioc_add(struct acpi_device *device)
        if (!ioc)
                return 1;
 
+       /* setup NUMA node association */
+       sba_map_ioc_to_node(ioc, device->handle);
        return 0;
 }
 
index 3812778..af4b714 100644 (file)
 #define _INLINE_ inline
 #endif
 
-#ifndef MIN
-#define MIN(a,b)       ((a) < (b) ? (a) : (b))
-#endif
-
 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
 
 #define SSC_GETCHAR    21
@@ -275,7 +271,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
         * Then from the beginning of the buffer until necessary
         */
 
-       count = MIN(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE),
+       count = min(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE),
                    SERIAL_XMIT_SIZE - info->xmit.tail);
        console->write(console, info->xmit.buf+info->xmit.tail, count);
 
@@ -1055,7 +1051,7 @@ simrs_init (void)
                        ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq);
                }
 
-               printk(KERN_INFO "ttyS%02d at 0x%04lx (irq = %d) is a %s\n",
+               printk(KERN_INFO "ttyS%d at 0x%04lx (irq = %d) is a %s\n",
                       state->line,
                       state->port, state->irq,
                       uart_config[state->type].name);
index 36f8d42..b68534d 100644 (file)
@@ -103,11 +103,15 @@ static inline int
 elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpregset_t *fpu)
 {
        struct ia32_user_i387_struct *fpstate = (void*)fpu;
+       mm_segment_t old_fs;
 
        if (!tsk->used_math)
                return 0;
-
-       save_ia32_fpstate(tsk, fpstate);
+       
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       save_ia32_fpstate(tsk, (struct ia32_user_i387_struct __user *) fpstate);
+       set_fs(old_fs);
 
        return 1;
 }
@@ -117,11 +121,15 @@ static inline int
 elf_core_copy_task_xfpregs(struct task_struct *tsk, elf_fpxregset_t *xfpu)
 {
        struct ia32_user_fxsr_struct *fpxstate = (void*) xfpu;
+       mm_segment_t old_fs;
 
        if (!tsk->used_math)
                return 0;
 
-       save_ia32_fpxstate(tsk, fpxstate);
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       save_ia32_fpxstate(tsk, (struct ia32_user_fxsr_struct __user *) fpxstate);
+       set_fs(old_fs);
 
        return 1;
 }
index 4cc8242..a152738 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Hewlett-Packard Co
+ * Copyright (C) 2001, 2004 Hewlett-Packard Co
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Adapted from arch/i386/kernel/ldt.c
 
 #include "ia32priv.h"
 
-#define P(p)   ((void *) (unsigned long) (p))
-
 /*
  * read_ldt() is not really atomic - this is not a problem since synchronization of reads
  * and writes done to the LDT has to be assured by user-space anyway. Writes are atomic,
  * to protect the security checks done on new descriptors.
  */
 static int
-read_ldt (void *ptr, unsigned long bytecount)
+read_ldt (void __user *ptr, unsigned long bytecount)
 {
-       char *src, *dst, buf[256];      /* temporary buffer (don't overflow kernel stack!) */
        unsigned long bytes_left, n;
+       char __user *src, *dst;
+       char buf[256];  /* temporary buffer (don't overflow kernel stack!) */
 
        if (bytecount > IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE)
                bytecount = IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE;
 
        bytes_left = bytecount;
 
-       src = (void *) IA32_LDT_OFFSET;
+       src = (void __user *) IA32_LDT_OFFSET;
        dst = ptr;
 
        while (bytes_left) {
@@ -61,7 +60,7 @@ read_ldt (void *ptr, unsigned long bytecount)
 }
 
 static int
-read_default_ldt (void * ptr, unsigned long bytecount)
+read_default_ldt (void __user * ptr, unsigned long bytecount)
 {
        unsigned long size;
        int err;
@@ -80,7 +79,7 @@ read_default_ldt (void * ptr, unsigned long bytecount)
 }
 
 static int
-write_ldt (void * ptr, unsigned long bytecount, int oldmode)
+write_ldt (void __user * ptr, unsigned long bytecount, int oldmode)
 {
        struct ia32_user_desc ldt_info;
        __u64 entry;
@@ -120,7 +119,7 @@ write_ldt (void * ptr, unsigned long bytecount, int oldmode)
         * memory, but we still need to guard against out-of-memory, hence we must use
         * put_user().
         */
-       ret = __put_user(entry, (__u64 *) IA32_LDT_OFFSET + ldt_info.entry_number);
+       ret = __put_user(entry, (__u64 __user *) IA32_LDT_OFFSET + ldt_info.entry_number);
        ia32_load_segment_descriptors(current);
        return ret;
 }
@@ -132,16 +131,16 @@ sys32_modify_ldt (int func, unsigned int ptr, unsigned int bytecount)
 
        switch (func) {
              case 0:
-               ret = read_ldt(P(ptr), bytecount);
+               ret = read_ldt(compat_ptr(ptr), bytecount);
                break;
              case 1:
-               ret = write_ldt(P(ptr), bytecount, 1);
+               ret = write_ldt(compat_ptr(ptr), bytecount, 1);
                break;
              case 2:
-               ret = read_default_ldt(P(ptr), bytecount);
+               ret = read_default_ldt(compat_ptr(ptr), bytecount);
                break;
              case 0x11:
-               ret = write_ldt(P(ptr), bytecount, 0);
+               ret = write_ldt(compat_ptr(ptr), bytecount, 0);
                break;
        }
        return ret;
index b70f6de..2623df5 100644 (file)
@@ -62,7 +62,7 @@ acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor *id,
        struct acpi_vendor_info info;
 
        info.descriptor = id;
-       info.data = 0;
+       info.data = NULL;
 
        acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match, &info);
        if (!info.data)
index f166571..b1ab994 100644 (file)
@@ -34,6 +34,11 @@ void foo(void)
 
        BLANK();
 
+       DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+       DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
+
+       BLANK();
+
        DEFINE(IA64_TASK_BLOCKED_OFFSET,offsetof (struct task_struct, blocked));
        DEFINE(IA64_TASK_CLEAR_CHILD_TID_OFFSET,offsetof (struct task_struct, clear_child_tid));
        DEFINE(IA64_TASK_GROUP_LEADER_OFFSET, offsetof (struct task_struct, group_leader));
@@ -188,18 +193,10 @@ void foo(void)
        DEFINE(IA64_CLONE_VM, CLONE_VM);
 
        BLANK();
-    /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
-       DEFINE(IA64_CPUINFO_ITM_DELTA_OFFSET, offsetof (struct cpuinfo_ia64, itm_delta));
-       DEFINE(IA64_CPUINFO_ITM_NEXT_OFFSET, offsetof (struct cpuinfo_ia64, itm_next));
        DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET, offsetof (struct cpuinfo_ia64, nsec_per_cyc));
        DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec));
 
 
-       DEFINE(CLONE_IDLETASK_BIT, 12);
-#if CLONE_IDLETASK != (1 << 12)
-# error "CLONE_IDLETASK_BIT incorrect, please fix"
-#endif
-
        DEFINE(CLONE_SETTLS_BIT, 19);
 #if CLONE_SETTLS != (1<<19)
 # error "CLONE_SETTLS_BIT incorrect, please fix"
@@ -207,5 +204,21 @@ void foo(void)
 
        BLANK();
        DEFINE(IA64_MCA_TLB_INFO_SIZE, sizeof (struct ia64_mca_tlb_info));
+       /* used by head.S */
+       DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET, offsetof (struct cpuinfo_ia64, nsec_per_cyc));
 
+       BLANK();
+       /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
+       DEFINE(IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET, offsetof (struct time_interpolator, addr));
+       DEFINE(IA64_TIME_INTERPOLATOR_SOURCE_OFFSET, offsetof (struct time_interpolator, source));
+       DEFINE(IA64_TIME_INTERPOLATOR_SHIFT_OFFSET, offsetof (struct time_interpolator, shift));
+       DEFINE(IA64_TIME_INTERPOLATOR_NSEC_OFFSET, offsetof (struct time_interpolator, nsec_per_cyc));
+       DEFINE(IA64_TIME_INTERPOLATOR_OFFSET_OFFSET, offsetof (struct time_interpolator, offset));
+       DEFINE(IA64_TIME_INTERPOLATOR_LAST_CYCLE_OFFSET, offsetof (struct time_interpolator, last_cycle));
+       DEFINE(IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET, offsetof (struct time_interpolator, last_counter));
+       DEFINE(IA64_TIME_INTERPOLATOR_JITTER_OFFSET, offsetof (struct time_interpolator, jitter));
+       DEFINE(IA64_TIME_SOURCE_CPU, TIME_SOURCE_CPU);
+       DEFINE(IA64_TIME_SOURCE_MMIO64, TIME_SOURCE_MMIO64);
+       DEFINE(IA64_TIME_SOURCE_MMIO32, TIME_SOURCE_MMIO32);
+       DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec));
 }
index 19300e9..f8261d3 100644 (file)
@@ -1,6 +1,8 @@
+#include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/time.h>
 #include <linux/errno.h>
+#include <asm/io.h>
 
 /* IBM Summit (EXA) Cyclone counter code*/
 #define CYCLONE_CBAR_ADDR 0xFEB00CD0
@@ -15,62 +17,10 @@ void __init cyclone_setup(void)
        use_cyclone = 1;
 }
 
-static u32* volatile cyclone_timer;    /* Cyclone MPMC0 register */
-static u32 last_update_cyclone;
-
-static unsigned long offset_base;
-
-static unsigned long get_offset_cyclone(void)
-{
-       u32 now;
-       unsigned long offset;
-
-       /* Read the cyclone timer */
-       now = readl(cyclone_timer);
-       /* .. relative to previous update*/
-       offset = now - last_update_cyclone;
-
-       /* convert cyclone ticks to nanoseconds */
-       offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ;
-
-       /* our adjusted time in nanoseconds */
-       return offset_base + offset;
-}
-
-static void update_cyclone(long delta_nsec)
-{
-       u32 now;
-       unsigned long offset;
-
-       /* Read the cyclone timer */
-       now = readl(cyclone_timer);
-       /* .. relative to previous update*/
-       offset = now - last_update_cyclone;
-
-       /* convert cyclone ticks to nanoseconds */
-       offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ;
-
-       offset += offset_base;
-
-       /* Be careful about signed/unsigned comparisons here: */
-       if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
-               offset_base = offset - delta_nsec;
-       else
-               offset_base = 0;
-
-       last_update_cyclone = now;
-}
-
-static void reset_cyclone(void)
-{
-       offset_base = 0;
-       last_update_cyclone = readl(cyclone_timer);
-}
 
 struct time_interpolator cyclone_interpolator = {
-       .get_offset =   get_offset_cyclone,
-       .update =       update_cyclone,
-       .reset =        reset_cyclone,
+       .source =       TIME_SOURCE_MMIO32,
+       .shift =        32,
        .frequency =    CYCLONE_TIMER_FREQ,
        .drift =        -100,
 };
@@ -81,6 +31,7 @@ int __init init_cyclone_clock(void)
        u64 base;       /* saved cyclone base address */
        u64 offset;     /* offset from pageaddr to cyclone_timer register */
        int i;
+       u32* volatile cyclone_timer;    /* Cyclone MPMC0 register */
 
        if (!use_cyclone)
                return -ENODEV;
@@ -148,7 +99,7 @@ int __init init_cyclone_clock(void)
                }
        }
        /* initialize last tick */
-       last_update_cyclone = readl(cyclone_timer);
+       cyclone_interpolator.addr = cyclone_timer;
        register_time_interpolator(&cyclone_interpolator);
 
        return 0;
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
new file mode 100644 (file)
index 0000000..90ed84b
--- /dev/null
@@ -0,0 +1,639 @@
+/*
+ * File:       mca_drv.c
+ * Purpose:    Generic MCA handling layer
+ *
+ * Copyright (C) 2004 FUJITSU LIMITED
+ * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kallsyms.h>
+#include <linux/smp_lock.h>
+#include <linux/bootmem.h>
+#include <linux/acpi.h>
+#include <linux/timer.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/workqueue.h>
+#include <linux/mm.h>
+
+#include <asm/delay.h>
+#include <asm/machvec.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/sal.h>
+#include <asm/mca.h>
+
+#include <asm/irq.h>
+#include <asm/hw_irq.h>
+
+#include "mca_drv.h"
+
+/* max size of SAL error record (default) */
+static int sal_rec_max = 10000;
+
+/* from mca.c */
+static ia64_mca_sal_to_os_state_t *sal_to_os_handoff_state;
+static ia64_mca_os_to_sal_state_t *os_to_sal_handoff_state;
+
+/* from mca_drv_asm.S */
+extern void *mca_handler_bhhook(void);
+
+static spinlock_t mca_bh_lock = SPIN_LOCK_UNLOCKED;
+
+typedef enum {
+       MCA_IS_LOCAL  = 0,
+       MCA_IS_GLOBAL = 1
+} mca_type_t;
+
+#define MAX_PAGE_ISOLATE 32
+
+static struct page *page_isolate[MAX_PAGE_ISOLATE];
+static int num_page_isolate = 0;
+
+typedef enum {
+       ISOLATE_NG = 0,
+       ISOLATE_OK = 1
+} isolate_status_t;
+
+/*
+ *  This pool keeps pointers to the section part of SAL error record
+ */
+static struct {
+       slidx_list_t *buffer; /* section pointer list pool */
+       int          cur_idx; /* Current index of section pointer list pool */
+       int          max_idx; /* Maximum index of section pointer list pool */
+} slidx_pool;
+
+/**
+ * mca_page_isolate - isolate a poisoned page in order not to use it later
+ * @paddr:     poisoned memory location
+ *
+ * Return value:
+ *     ISOLATE_OK / ISOLATE_NG
+ */
+
+static isolate_status_t
+mca_page_isolate(unsigned long paddr)
+{
+       int i;
+       struct page *p;
+
+       /* whether physical address is valid or not */
+       if ( !ia64_phys_addr_valid(paddr) ) 
+               return ISOLATE_NG;
+
+       /* convert physical address to physical page number */
+       p = pfn_to_page(paddr>>PAGE_SHIFT);
+
+       /* check whether a page number have been already registered or not */
+       for( i = 0; i < num_page_isolate; i++ )
+               if( page_isolate[i] == p )
+                       return ISOLATE_OK; /* already listed */
+
+       /* limitation check */
+       if( num_page_isolate == MAX_PAGE_ISOLATE ) 
+               return ISOLATE_NG;
+
+       /* kick pages having attribute 'SLAB' or 'Reserved' */
+       if( PageSlab(p) || PageReserved(p) ) 
+               return ISOLATE_NG;
+
+       /* add attribute 'Reserved' and register the page */
+       SetPageReserved(p);
+       page_isolate[num_page_isolate++] = p;
+
+       return ISOLATE_OK;
+}
+
+/**
+ * mca_hanlder_bh - Kill the process which occurred memory read error
+ * @paddr:     poisoned address received from MCA Handler
+ */
+
+void
+mca_handler_bh(unsigned long paddr)
+{
+       printk(KERN_DEBUG "OS_MCA: process [pid: %d](%s) encounters MCA.\n",
+               current->pid, current->comm);
+
+       spin_lock(&mca_bh_lock);
+       if (mca_page_isolate(paddr) == ISOLATE_OK) {
+               printk(KERN_DEBUG "Page isolation: ( %lx ) success.\n", paddr);
+       } else {
+               printk(KERN_DEBUG "Page isolation: ( %lx ) failure.\n", paddr);
+       }
+       spin_unlock(&mca_bh_lock);
+
+       /* This process is about to be killed itself */
+       force_sig(SIGKILL, current);
+       schedule();
+}
+
+/**
+ * mca_make_peidx - Make index of processor error section
+ * @slpi:      pointer to record of processor error section
+ * @peidx:     pointer to index of processor error section
+ */
+
+static void 
+mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
+{
+       /* 
+        * calculate the start address of
+        *   "struct cpuid_info" and "sal_processor_static_info_t".
+        */
+       u64 total_check_num = slpi->valid.num_cache_check
+                               + slpi->valid.num_tlb_check
+                               + slpi->valid.num_bus_check
+                               + slpi->valid.num_reg_file_check
+                               + slpi->valid.num_ms_check;
+       u64 head_size = sizeof(sal_log_mod_error_info_t) * total_check_num
+                       + sizeof(sal_log_processor_info_t);
+       u64 mid_size  = slpi->valid.cpuid_info * sizeof(struct sal_cpuid_info);
+
+       peidx_head(peidx)   = slpi;
+       peidx_mid(peidx)    = (struct sal_cpuid_info *)
+               (slpi->valid.cpuid_info ? ((char*)slpi + head_size) : NULL);
+       peidx_bottom(peidx) = (sal_processor_static_info_t *)
+               (slpi->valid.psi_static_struct ?
+                       ((char*)slpi + head_size + mid_size) : NULL);
+}
+
+/**
+ * mca_make_slidx -  Make index of SAL error record 
+ * @buffer:    pointer to SAL error record
+ * @slidx:     pointer to index of SAL error record
+ *
+ * Return value:
+ *     1 if record has platform error / 0 if not
+ */
+#define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \
+        { slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \
+          hl->hdr = ptr; \
+          list_add(&hl->list, &(sect)); \
+          slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; }
+
+static int 
+mca_make_slidx(void *buffer, slidx_table_t *slidx)
+{
+       int platform_err = 0;
+       int record_len = ((sal_log_record_header_t*)buffer)->len;
+       u32 ercd_pos;
+       int sects;
+       sal_log_section_hdr_t *sp;
+
+       /*
+        * Initialize index referring current record
+        */
+       INIT_LIST_HEAD(&(slidx->proc_err));
+       INIT_LIST_HEAD(&(slidx->mem_dev_err));
+       INIT_LIST_HEAD(&(slidx->sel_dev_err));
+       INIT_LIST_HEAD(&(slidx->pci_bus_err));
+       INIT_LIST_HEAD(&(slidx->smbios_dev_err));
+       INIT_LIST_HEAD(&(slidx->pci_comp_err));
+       INIT_LIST_HEAD(&(slidx->plat_specific_err));
+       INIT_LIST_HEAD(&(slidx->host_ctlr_err));
+       INIT_LIST_HEAD(&(slidx->plat_bus_err));
+       INIT_LIST_HEAD(&(slidx->unsupported));
+
+       /*
+        * Extract a Record Header
+        */
+       slidx->header = buffer;
+
+       /*
+        * Extract each section records
+        * (arranged from "int ia64_log_platform_info_print()")
+        */
+       for (ercd_pos = sizeof(sal_log_record_header_t), sects = 0;
+               ercd_pos < record_len; ercd_pos += sp->len, sects++) {
+               sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos);
+               if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) {
+                       LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp);
+               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) {
+                       platform_err = 1;
+                       LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp);
+               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) {
+                       platform_err = 1;
+                       LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp);
+               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) {
+                       platform_err = 1;
+                       LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp);
+               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) {
+                       platform_err = 1;
+                       LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp);
+               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) {
+                       platform_err = 1;
+                       LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp);
+               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) {
+                       platform_err = 1;
+                       LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp);
+               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) {
+                       platform_err = 1;
+                       LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp);
+               } else if (!efi_guidcmp(sp->guid, SAL_PLAT_BUS_ERR_SECT_GUID)) {
+                       platform_err = 1;
+                       LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp);
+               } else {
+                       LOG_INDEX_ADD_SECT_PTR(slidx->unsupported, sp);
+               }
+       }
+       slidx->n_sections = sects;
+
+       return platform_err;
+}
+
+/**
+ * init_record_index_pools - Initialize pool of lists for SAL record index
+ *
+ * Return value:
+ *     0 on Success / -ENOMEM on Failure
+ */
+static int 
+init_record_index_pools(void)
+{
+       int i;
+       int rec_max_size;  /* Maximum size of SAL error records */
+       int sect_min_size; /* Minimum size of SAL error sections */
+       /* minimum size table of each section */
+       static int sal_log_sect_min_sizes[] = { 
+               sizeof(sal_log_processor_info_t) + sizeof(sal_processor_static_info_t),
+               sizeof(sal_log_mem_dev_err_info_t),
+               sizeof(sal_log_sel_dev_err_info_t),
+               sizeof(sal_log_pci_bus_err_info_t),
+               sizeof(sal_log_smbios_dev_err_info_t),
+               sizeof(sal_log_pci_comp_err_info_t),
+               sizeof(sal_log_plat_specific_err_info_t),
+               sizeof(sal_log_host_ctlr_err_info_t),
+               sizeof(sal_log_plat_bus_err_info_t),
+       };
+
+       /*
+        * MCA handler cannot allocate new memory on flight,
+        * so we preallocate enough memory to handle a SAL record.
+        *
+        * Initialize a handling set of slidx_pool:
+        *   1. Pick up the max size of SAL error records
+        *   2. Pick up the min size of SAL error sections
+        *   3. Allocate the pool as enough to 2 SAL records
+        *     (now we can estimate the maxinum of section in a record.)
+        */
+
+       /* - 1 - */
+       rec_max_size = sal_rec_max;
+
+       /* - 2 - */
+       sect_min_size = sal_log_sect_min_sizes[0];
+       for (i = 1; i < sizeof sal_log_sect_min_sizes/sizeof(size_t); i++)
+               if (sect_min_size > sal_log_sect_min_sizes[i])
+                       sect_min_size = sal_log_sect_min_sizes[i];
+
+       /* - 3 - */
+       slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
+       slidx_pool.buffer = (slidx_list_t *) kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
+
+       return slidx_pool.buffer ? 0 : -ENOMEM;
+}
+
+
+/*****************************************************************************
+ * Recovery functions                                                        *
+ *****************************************************************************/
+
+/**
+ * is_mca_global - Check whether this MCA is global or not
+ * @peidx:     pointer of index of processor error section
+ * @pbci:      pointer to pal_bus_check_info_t
+ *
+ * Return value:
+ *     MCA_IS_LOCAL / MCA_IS_GLOBAL
+ */
+
+static mca_type_t
+is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+{
+       pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+
+       /* 
+        * PAL can request a rendezvous, if the MCA has a global scope.
+        * If "rz_always" flag is set, SAL requests MCA rendezvous 
+        * in spite of global MCA.
+        * Therefore it is local MCA when rendezvous has not been requested.
+        * Failed to rendezvous, the system must be down.
+        */
+       switch (sal_to_os_handoff_state->imsto_rendez_state) {
+               case -1: /* SAL rendezvous unsuccessful */
+                       return MCA_IS_GLOBAL;
+               case  0: /* SAL rendezvous not required */
+                       return MCA_IS_LOCAL;
+               case  1: /* SAL rendezvous successful int */
+               case  2: /* SAL rendezvous successful int with init */
+               default:
+                       break;
+       }
+
+       /*
+        * If One or more Cache/TLB/Reg_File/Uarch_Check is here,
+        * it would be a local MCA. (i.e. processor internal error)
+        */
+       if (psp->tc || psp->cc || psp->rc || psp->uc)
+               return MCA_IS_LOCAL;
+       
+       /*
+        * Bus_Check structure with Bus_Check.ib (internal bus error) flag set
+        * would be a global MCA. (e.g. a system bus address parity error)
+        */
+       if (!pbci || pbci->ib)
+               return MCA_IS_GLOBAL;
+
+       /*
+        * Bus_Check structure with Bus_Check.eb (external bus error) flag set
+        * could be either a local MCA or a global MCA.
+        *
+        * Referring Bus_Check.bsi:
+        *   0: Unknown/unclassified
+        *   1: BERR#
+        *   2: BINIT#
+        *   3: Hard Fail
+        * (FIXME: Are these SGI specific or generic bsi values?)
+        */
+       if (pbci->eb)
+               switch (pbci->bsi) {
+                       case 0:
+                               /* e.g. a load from poisoned memory */
+                               return MCA_IS_LOCAL;
+                       case 1:
+                       case 2:
+                       case 3:
+                               return MCA_IS_GLOBAL;
+               }
+
+       return MCA_IS_GLOBAL;
+}
+
+/**
+ * recover_from_read_error - Try to recover the errors which type are "read"s.
+ * @slidx:     pointer of index of SAL error record
+ * @peidx:     pointer of index of processor error section
+ * @pbci:      pointer of pal_bus_check_info
+ *
+ * Return value:
+ *     1 on Success / 0 on Failure
+ */
+
+static int
+recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+{
+       sal_log_mod_error_info_t *smei;
+       pal_min_state_area_t *pmsa;
+       struct ia64_psr *psr1, *psr2;
+       ia64_fptr_t *mca_hdlr_bh = (ia64_fptr_t*)mca_handler_bhhook;
+
+       /* Is target address valid? */
+       if (!pbci->tv)
+               return 0;
+
+       /*
+        * cpu read or memory-mapped io read
+        *
+        *    offending process  affected process  OS MCA do
+        *     kernel mode        kernel mode       down system
+        *     kernel mode        user   mode       kill the process
+        *     user   mode        kernel mode       down system (*)
+        *     user   mode        user   mode       kill the process
+        *
+        * (*) You could terminate offending user-mode process
+        *    if (pbci->pv && pbci->pl != 0) *and* if you sure
+        *    the process not have any locks of kernel.
+        */
+
+       psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
+
+       /*
+        *  Check the privilege level of interrupted context.
+        *   If it is user-mode, then terminate affected process.
+        */
+       if (psr1->cpl != 0) {
+               smei = peidx_bus_check(peidx, 0);
+               if (smei->valid.target_identifier) {
+                       /*
+                        *  setup for resume to bottom half of MCA,
+                        * "mca_handler_bhhook"
+                        */
+                       pmsa = (pal_min_state_area_t *)(sal_to_os_handoff_state->pal_min_state | (6ul<<61));
+                       /* pass to bhhook as 1st argument (gr8) */
+                       pmsa->pmsa_gr[8-1] = smei->target_identifier;
+                       /* set interrupted return address (but no use) */
+                       pmsa->pmsa_br0 = pmsa->pmsa_iip;
+                       /* change resume address to bottom half */
+                       pmsa->pmsa_iip = mca_hdlr_bh->fp;
+                       pmsa->pmsa_gr[1-1] = mca_hdlr_bh->gp;
+                       /* set cpl with kernel mode */
+                       psr2 = (struct ia64_psr *)&pmsa->pmsa_ipsr;
+                       psr2->cpl = 0;
+                       psr2->ri  = 0;
+
+                       return 1;
+               }
+
+       }
+
+       return 0;
+}
+
+/**
+ * recover_from_platform_error - Recover from platform error.
+ * @slidx:     pointer of index of SAL error record
+ * @peidx:     pointer of index of processor error section
+ * @pbci:      pointer of pal_bus_check_info
+ *
+ * Return value:
+ *     1 on Success / 0 on Failure
+ */
+
+static int
+recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+{
+       int status = 0;
+       pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+
+       if (psp->bc && pbci->eb && pbci->bsi == 0) {
+               switch(pbci->type) {
+               case 1: /* partial read */
+               case 3: /* full line(cpu) read */
+               case 9: /* I/O space read */
+                       status = recover_from_read_error(slidx, peidx, pbci);
+                       break;
+               case 0: /* unknown */
+               case 2: /* partial write */
+               case 4: /* full line write */
+               case 5: /* implicit or explicit write-back operation */
+               case 6: /* snoop probe */
+               case 7: /* incoming or outgoing ptc.g */
+               case 8: /* write coalescing transactions */
+               case 10: /* I/O space write */
+               case 11: /* inter-processor interrupt message(IPI) */
+               case 12: /* interrupt acknowledge or external task priority cycle */
+               default:
+                       break;
+               }
+       }
+
+       return status;
+}
+
+/**
+ * recover_from_processor_error
+ * @platform:  whether there are some platform error section or not
+ * @slidx:     pointer of index of SAL error record
+ * @peidx:     pointer of index of processor error section
+ * @pbci:      pointer of pal_bus_check_info
+ *
+ * Return value:
+ *     1 on Success / 0 on Failure
+ */
+/*
+ *  Later we try to recover when below all conditions are satisfied.
+ *   1. Only one processor error section is exist.
+ *   2. BUS_CHECK is exist and the others are not exist.(Except TLB_CHECK)
+ *   3. The entry of BUS_CHECK_INFO is 1.
+ *   4. "External bus error" flag is set and the others are not set.
+ */
+
+static int
+recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+{
+       pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+
+       /* 
+        * We cannot recover errors with other than bus_check.
+        */
+       if (psp->cc || psp->rc || psp->uc) 
+               return 0;
+
+       /*
+        * If there is no bus error, record is weird but we need not to recover.
+        */
+       if (psp->bc == 0 || pbci == NULL)
+               return 1;
+
+       /*
+        * Sorry, we cannot handle so many.
+        */
+       if (peidx_bus_check_num(peidx) > 1)
+               return 0;
+       /*
+        * Well, here is only one bus error.
+        */
+       if (pbci->ib || pbci->cc)
+               return 0;
+       if (pbci->eb && pbci->bsi > 0)
+               return 0;
+       if (psp->ci == 0)
+               return 0;
+
+       /*
+        * This is a local MCA and estimated as recoverble external bus error.
+        * (e.g. a load from poisoned memory)
+        * This means "there are some platform errors".
+        */
+       if (platform) 
+               return recover_from_platform_error(slidx, peidx, pbci);
+       /* 
+        * On account of strange SAL error record, we cannot recover. 
+        */
+       return 0;
+}
+
+/**
+ * mca_try_to_recover - Try to recover from MCA
+ * @rec:       pointer to a SAL error record
+ *
+ * Return value:
+ *     1 on Success / 0 on Failure
+ */
+
+static int
+mca_try_to_recover(void *rec, 
+       ia64_mca_sal_to_os_state_t *sal_to_os_state,
+       ia64_mca_os_to_sal_state_t *os_to_sal_state)
+{
+       int platform_err;
+       int n_proc_err;
+       slidx_table_t slidx;
+       peidx_table_t peidx;
+       pal_bus_check_info_t pbci;
+
+       /* handoff state from/to mca.c */
+       sal_to_os_handoff_state = sal_to_os_state;
+       os_to_sal_handoff_state = os_to_sal_state;
+
+       /* Make index of SAL error record */
+       platform_err = mca_make_slidx(rec, &slidx);
+
+       /* Count processor error sections */
+       n_proc_err = slidx_count(&slidx, proc_err);
+
+        /* Now, OS can recover when there is one processor error section */
+       if (n_proc_err > 1)
+               return 0;
+       else if (n_proc_err == 0) {
+               /* Weird SAL record ... We need not to recover */
+
+               return 1;
+       }
+
+       /* Make index of processor error section */
+       mca_make_peidx((sal_log_processor_info_t*)slidx_first_entry(&slidx.proc_err)->hdr, &peidx);
+
+       /* Extract Processor BUS_CHECK[0] */
+       *((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0);
+
+       /* Check whether MCA is global or not */
+       if (is_mca_global(&peidx, &pbci))
+               return 0;
+       
+       /* Try to recover a processor error */
+       return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci);
+}
+
+/*
+ * =============================================================================
+ */
+
+int __init mca_external_handler_init(void)
+{
+       if (init_record_index_pools())
+               return -ENOMEM;
+
+       /* register external mca handlers */
+       if (ia64_reg_MCA_extension(mca_try_to_recover)){        
+               printk(KERN_ERR "ia64_reg_MCA_extension failed.\n");
+               kfree(slidx_pool.buffer);
+               return -EFAULT;
+       }
+       return 0;
+}
+
+void __exit mca_external_handler_exit(void)
+{
+       /* unregister external mca handlers */
+       ia64_unreg_MCA_extension();
+       kfree(slidx_pool.buffer);
+}
+
+module_init(mca_external_handler_init);
+module_exit(mca_external_handler_exit);
+
+module_param(sal_rec_max, int, 0644);
+MODULE_PARM_DESC(sal_rec_max, "Max size of SAL error record");
+
+MODULE_DESCRIPTION("ia64 platform dependent mca handler driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h
new file mode 100644 (file)
index 0000000..0227b76
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * File:       mca_drv.h
+ * Purpose:    Define helpers for Generic MCA handling
+ *
+ * Copyright (C) 2004 FUJITSU LIMITED
+ * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ */
+/*
+ * Processor error section: 
+ *
+ *  +-sal_log_processor_info_t *info-------------+
+ *  | sal_log_section_hdr_t header;              |
+ *  | ...                                        |
+ *  | sal_log_mod_error_info_t info[0];          |
+ *  +-+----------------+-------------------------+
+ *    | CACHE_CHECK    |  ^ num_cache_check v
+ *    +----------------+
+ *    | TLB_CHECK      |  ^ num_tlb_check v
+ *    +----------------+
+ *    | BUS_CHECK      |  ^ num_bus_check v
+ *    +----------------+
+ *    | REG_FILE_CHECK |  ^ num_reg_file_check v
+ *    +----------------+
+ *    | MS_CHECK       |  ^ num_ms_check v
+ *  +-struct cpuid_info *id----------------------+
+ *  | regs[5];                                   |
+ *  | reserved;                                  |
+ *  +-sal_processor_static_info_t *regs----------+
+ *  | valid;                                     |
+ *  | ...                                        |
+ *  | fr[128];                                   |
+ *  +--------------------------------------------+
+ */
+
+/* peidx: index of processor error section */
+typedef struct peidx_table {
+       sal_log_processor_info_t        *info;
+       struct sal_cpuid_info           *id;
+       sal_processor_static_info_t     *regs;
+} peidx_table_t;
+
+#define peidx_head(p)   (((p)->info))
+#define peidx_mid(p)    (((p)->id))
+#define peidx_bottom(p) (((p)->regs))
+
+#define peidx_psp(p)           (&(peidx_head(p)->proc_state_parameter))
+#define peidx_field_valid(p)   (&(peidx_head(p)->valid))
+#define peidx_minstate_area(p) (&(peidx_bottom(p)->min_state_area))
+
+#define peidx_cache_check_num(p)    (peidx_head(p)->valid.num_cache_check)
+#define peidx_tlb_check_num(p)      (peidx_head(p)->valid.num_tlb_check)
+#define peidx_bus_check_num(p)      (peidx_head(p)->valid.num_bus_check)
+#define peidx_reg_file_check_num(p) (peidx_head(p)->valid.num_reg_file_check)
+#define peidx_ms_check_num(p)       (peidx_head(p)->valid.num_ms_check)
+
+#define peidx_cache_check_idx(p, n)    (n)
+#define peidx_tlb_check_idx(p, n)      (peidx_cache_check_idx(p, peidx_cache_check_num(p)) + n)
+#define peidx_bus_check_idx(p, n)      (peidx_tlb_check_idx(p, peidx_tlb_check_num(p)) + n)
+#define peidx_reg_file_check_idx(p, n) (peidx_bus_check_idx(p, peidx_bus_check_num(p)) + n)
+#define peidx_ms_check_idx(p, n)       (peidx_reg_file_check_idx(p, peidx_reg_file_check_num(p)) + n)
+
+#define peidx_mod_error_info(p, name, n) \
+({     int __idx = peidx_##name##_idx(p, n); \
+       sal_log_mod_error_info_t *__ret = NULL; \
+       if (peidx_##name##_num(p) > n) /*BUG*/ \
+               __ret = &(peidx_head(p)->info[__idx]); \
+       __ret; })
+
+#define peidx_cache_check(p, n)    peidx_mod_error_info(p, cache_check, n)
+#define peidx_tlb_check(p, n)      peidx_mod_error_info(p, tlb_check, n)
+#define peidx_bus_check(p, n)      peidx_mod_error_info(p, bus_check, n)
+#define peidx_reg_file_check(p, n) peidx_mod_error_info(p, reg_file_check, n)
+#define peidx_ms_check(p, n)       peidx_mod_error_info(p, ms_check, n)
+
+#define peidx_check_info(proc, name, n) \
+({ \
+       sal_log_mod_error_info_t *__info = peidx_mod_error_info(proc, name, n);\
+       u64 __temp = __info && __info->valid.check_info \
+               ? __info->check_info : 0; \
+       __temp; })
+
+/* slidx: index of SAL log error record */
+
+typedef struct slidx_list {
+       struct list_head list;
+       sal_log_section_hdr_t *hdr;
+} slidx_list_t;
+
+typedef struct slidx_table {
+       sal_log_record_header_t *header;
+       int n_sections;                 /* # of section headers */
+       struct list_head proc_err;
+       struct list_head mem_dev_err;
+       struct list_head sel_dev_err;
+       struct list_head pci_bus_err;
+       struct list_head smbios_dev_err;
+       struct list_head pci_comp_err;
+       struct list_head plat_specific_err;
+       struct list_head host_ctlr_err;
+       struct list_head plat_bus_err;
+       struct list_head unsupported;   /* list of unsupported sections */
+} slidx_table_t;
+
+#define slidx_foreach_entry(pos, head) \
+       list_for_each_entry(pos, head, list)
+#define slidx_first_entry(head) \
+       (((head)->next != (head)) ? list_entry((head)->next, typeof(slidx_list_t), list) : NULL)
+#define slidx_count(slidx, sec) \
+({     int __count = 0; \
+       slidx_list_t *__pos; \
+       slidx_foreach_entry(__pos, &((slidx)->sec)) { __count++; }\
+       __count; })
+
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
new file mode 100644 (file)
index 0000000..bcfa05a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * File:        mca_drv_asm.S
+ * Purpose:     Assembly portion of Generic MCA handling
+ *
+ * Copyright (C) 2004 FUJITSU LIMITED
+ * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ */
+#include <linux/config.h>
+#include <linux/threads.h>
+
+#include <asm/asmmacro.h>
+#include <asm/processor.h>
+
+GLOBAL_ENTRY(mca_handler_bhhook)
+       invala                                          // clear RSE ?
+       ;;                                              //
+       cover                                           // 
+       ;;                                              //
+       clrrrb                                          //
+       ;;                                              
+       alloc           r16=ar.pfs,0,2,1,0              // make a new frame
+       ;;
+       mov             r13=IA64_KR(CURRENT)            // current task pointer
+       ;;
+       adds            r12=IA64_TASK_THREAD_KSP_OFFSET,r13
+       ;;
+       ld8             r12=[r12]                       // stack pointer
+       ;;
+       mov             loc0=r16
+       movl            loc1=mca_handler_bh             // recovery C function
+       ;;
+       mov             out0=r8                         // poisoned address
+       mov             b6=loc1
+       ;;
+       mov             loc1=rp
+       ;;
+       br.call.sptk.many    rp=b6                      // not return ...
+       ;;
+       mov             ar.pfs=loc0
+       mov             rp=loc1
+       ;;
+       mov             r8=r0
+       br.ret.sptk.many rp
+       ;;
+END(mca_handler_bhhook)
index 540301f..b1460dc 100644 (file)
@@ -54,8 +54,7 @@
 (pUStk)        mov ar.rsc=0x3;         /* set eager mode, pl 0, little-endian, loadrs=0 */             \
 
 #define MINSTATE_END_SAVE_MIN_PHYS                                                             \
-       or r12=r12,r14;         /* make sp a kernel virtual address */                          \
-       or r13=r13,r14;         /* make `current' a kernel virtual address */                   \
+       dep r12=-1,r12,61,3;            /* make sp a kernel virtual address */                  \
        ;;
 
 #ifdef MINSTATE_VIRT
@@ -65,7 +64,7 @@
 #endif
 
 #ifdef MINSTATE_PHYS
-# define MINSTATE_GET_CURRENT(reg)     mov reg=IA64_KR(CURRENT);; dep reg=0,reg,61,3
+# define MINSTATE_GET_CURRENT(reg)     mov reg=IA64_KR(CURRENT);; tpa reg=reg
 # define MINSTATE_START_SAVE_MIN       MINSTATE_START_SAVE_MIN_PHYS
 # define MINSTATE_END_SAVE_MIN         MINSTATE_END_SAVE_MIN_PHYS
 #endif
        ;;                                                                                      \
 .mem.offset 0,0; st8.spill [r16]=r15,16;                                                       \
 .mem.offset 8,0; st8.spill [r17]=r14,16;                                                       \
-       dep r14=-1,r0,61,3;                                                                     \
        ;;                                                                                      \
 .mem.offset 0,0; st8.spill [r16]=r2,16;                                                                \
 .mem.offset 8,0; st8.spill [r17]=r3,16;                                                                \
index ef04f5d..367804a 100644 (file)
@@ -65,21 +65,21 @@ void
 ia64_patch_imm64 (u64 insn_addr, u64 val)
 {
        ia64_patch(insn_addr,
-                  0x01fffefe000, (  ((val & 0x8000000000000000) >> 27) /* bit 63 -> 36 */
-                                  | ((val & 0x0000000000200000) <<  0) /* bit 21 -> 21 */
-                                  | ((val & 0x00000000001f0000) <<  6) /* bit 16 -> 22 */
-                                  | ((val & 0x000000000000ff80) << 20) /* bit  7 -> 27 */
-                                  | ((val & 0x000000000000007f) << 13) /* bit  0 -> 13 */));
-       ia64_patch(insn_addr - 1, 0x1ffffffffff, val >> 22);
+                  0x01fffefe000UL, (  ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
+                                    | ((val & 0x0000000000200000UL) <<  0) /* bit 21 -> 21 */
+                                    | ((val & 0x00000000001f0000UL) <<  6) /* bit 16 -> 22 */
+                                    | ((val & 0x000000000000ff80UL) << 20) /* bit  7 -> 27 */
+                                    | ((val & 0x000000000000007fUL) << 13) /* bit  0 -> 13 */));
+       ia64_patch(insn_addr - 1, 0x1ffffffffffUL, val >> 22);
 }
 
 void
 ia64_patch_imm60 (u64 insn_addr, u64 val)
 {
        ia64_patch(insn_addr,
-                  0x011ffffe000, (  ((val & 0x0800000000000000) >> 23) /* bit 59 -> 36 */
-                                  | ((val & 0x00000000000fffff) << 13) /* bit  0 -> 13 */));
-       ia64_patch(insn_addr - 1, 0x1fffffffffc, val >> 18);
+                  0x011ffffe000UL, (  ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
+                                    | ((val & 0x00000000000fffffUL) << 13) /* bit  0 -> 13 */));
+       ia64_patch(insn_addr - 1, 0x1fffffffffcUL, val >> 18);
 }
 
 /*
@@ -130,10 +130,10 @@ ia64_patch_mckinley_e9 (unsigned long start, unsigned long end)
 
        while (offp < (s32 *) end) {
                wp = (u64 *) ia64_imva((char *) offp + *offp);
-               wp[0] = 0x0000000100000000; /* nop.m 0; nop.i 0; nop.i 0 */
-               wp[1] = 0x0004000000000200;
-               wp[2] = 0x0000000100000011; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
-               wp[3] = 0x0084006880000200;
+               wp[0] = 0x0000000100000000UL; /* nop.m 0; nop.i 0; nop.i 0 */
+               wp[1] = 0x0004000000000200UL;
+               wp[2] = 0x0000000100000011UL; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
+               wp[3] = 0x0084006880000200UL;
                ia64_fc(wp); ia64_fc(wp + 2);
                ++offp;
        }
index a0420ae..500e105 100644 (file)
@@ -268,7 +268,7 @@ salinfo_event_open(struct inode *inode, struct file *file)
 }
 
 static ssize_t
-salinfo_event_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct proc_dir_entry *entry = PDE(inode);
@@ -417,11 +417,16 @@ retry:
 
        if (!data->saved_num)
                call_on_cpu(cpu, salinfo_log_read_cpu, data);
-       data->state = data->log_size ? STATE_LOG_RECORD : STATE_NO_DATA;
+       if (!data->log_size) {
+               data->state = STATE_NO_DATA;
+               clear_bit(cpu, &data->cpu_event);
+       } else {
+               data->state = STATE_LOG_RECORD;
+       }
 }
 
 static ssize_t
-salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct proc_dir_entry *entry = PDE(inode);
@@ -478,7 +483,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu)
 }
 
 static ssize_t
-salinfo_log_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct proc_dir_entry *entry = PDE(inode);
index 55e5275..37b986c 100644 (file)
@@ -17,7 +17,7 @@ struct sigframe {
         * End of architected state.
         */
 
-       void *handler;                  /* pointer to the plabel of the signal handler */
+       void __user *handler;           /* pointer to the plabel of the signal handler */
        struct siginfo info;
        struct sigcontext sc;
 };
index eddde60..88d8b21 100644 (file)
@@ -93,7 +93,7 @@ sys_getpagesize (void)
 }
 
 asmlinkage unsigned long
-ia64_shmat (int shmid, void *shmaddr, int shmflg)
+ia64_shmat (int shmid, void __user *shmaddr, int shmflg)
 {
        unsigned long raddr;
        int retval;
@@ -183,7 +183,7 @@ static inline unsigned long
 do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff)
 {
        unsigned long roff;
-       struct file *file = 0;
+       struct file *file = NULL;
 
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
        if (!(flags & MAP_ANONYMOUS)) {
index b1a68e4..46dad0d 100644 (file)
@@ -760,7 +760,7 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
                return -1;
        }
        /* this assumes little-endian byte-order: */
-       if (copy_from_user(&val, (void *) ifa, len))
+       if (copy_from_user(&val, (void __user *) ifa, len))
                return -1;
        setreg(ld.r1, val, 0, regs);
 
@@ -869,7 +869,7 @@ emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
         *
         * extract the value to be stored
         */
-       getreg(ld.imm, &r2, 0, regs);
+       getreg(ld.imm, &r2, NULL, regs);
 
        /*
         * we rely on the macros in unaligned.h for now i.e.,
@@ -887,7 +887,7 @@ emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
        }
 
        /* this assumes little-endian byte-order: */
-       if (copy_to_user((void *) ifa, &r2, len))
+       if (copy_to_user((void __user *) ifa, &r2, len))
                return -1;
 
        /*
@@ -1036,8 +1036,8 @@ emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs
                 * This assumes little-endian byte-order.  Note that there is no "ldfpe"
                 * instruction:
                 */
-               if (copy_from_user(&fpr_init[0], (void *) ifa, len)
-                   || copy_from_user(&fpr_init[1], (void *) (ifa + len), len))
+               if (copy_from_user(&fpr_init[0], (void __user *) ifa, len)
+                   || copy_from_user(&fpr_init[1], (void __user *) (ifa + len), len))
                        return -1;
 
                DPRINT("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld.r1, ld.imm, ld.x6_sz);
@@ -1138,7 +1138,7 @@ emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
         * See comments in ldX for descriptions on how the various loads are handled.
         */
        if (ld.x6_op != 0x2) {
-               if (copy_from_user(&fpr_init, (void *) ifa, len))
+               if (copy_from_user(&fpr_init, (void __user *) ifa, len))
                        return -1;
 
                DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz);
@@ -1230,7 +1230,7 @@ emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
        DDUMP("fpr_init =", &fpr_init, len);
        DDUMP("fpr_final =", &fpr_final, len);
 
-       if (copy_to_user((void *) ifa, &fpr_final, len))
+       if (copy_to_user((void __user *) ifa, &fpr_final, len))
                return -1;
 
        /*
@@ -1351,7 +1351,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
        DPRINT("iip=%lx ifa=%lx isr=%lx (ei=%d, sp=%d)\n",
               regs->cr_iip, ifa, regs->cr_ipsr, ipsr->ri, ipsr->it);
 
-       if (__copy_from_user(bundle, (void *) regs->cr_iip, 16))
+       if (__copy_from_user(bundle, (void __user *) regs->cr_iip, 16))
                goto failure;
 
        /*
@@ -1496,7 +1496,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
        si.si_signo = SIGBUS;
        si.si_errno = 0;
        si.si_code = BUS_ADRALN;
-       si.si_addr = (void *) ifa;
+       si.si_addr = (void __user *) ifa;
        si.si_flags = 0;
        si.si_isr = 0;
        si.si_imm = 0;
index 5791221..b9f0db4 100644 (file)
@@ -42,6 +42,7 @@ SECTIONS
        *(.text.ivt)
        *(.text)
        SCHED_TEXT
+       LOCK_TEXT
        *(.gnu.linkonce.t*)
     }
   .text2 : AT(ADDR(.text2) - LOAD_OFFSET)
@@ -135,12 +136,6 @@ SECTIONS
          *(.init.setup)
          __setup_end = .;
        }
-  __param : AT(ADDR(__param) - LOAD_OFFSET)
-        {
-         __start___param = .;
-         *(__param)
-         __stop___param = .;
-       }
   .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET)
        {
          __initcall_start = .;
index 269dcc2..ca7ba1e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Network Checksum & Copy routine
  *
- * Copyright (C) 1999, 2003 Hewlett-Packard Co
+ * Copyright (C) 1999, 2003-2004 Hewlett-Packard Co
  *     Stephane Eranian <eranian@hpl.hp.com>
  *
  * Most of the code has been imported from Linux/Alpha
@@ -105,7 +105,7 @@ out:
 extern unsigned long do_csum(const unsigned char *, long);
 
 static unsigned int
-do_csum_partial_copy_from_user (const char *src, char *dst, int len,
+do_csum_partial_copy_from_user (const char __user *src, char *dst, int len,
                                unsigned int psum, int *errp)
 {
        unsigned long result;
@@ -129,10 +129,10 @@ do_csum_partial_copy_from_user (const char *src, char *dst, int len,
 }
 
 unsigned int
-csum_partial_copy_from_user(const char *src, char *dst, int len,
-                           unsigned int sum, int *errp)
+csum_partial_copy_from_user (const char __user *src, char *dst, int len,
+                            unsigned int sum, int *errp)
 {
-       if (!access_ok(src, len, VERIFY_READ)) {
+       if (!access_ok(VERIFY_READ, src, len)) {
                *errp = -EFAULT;
                memset(dst, 0, len);
                return sum;
@@ -142,7 +142,7 @@ csum_partial_copy_from_user(const char *src, char *dst, int len,
 }
 
 unsigned int
-csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum)
+csum_partial_copy_nocheck(const char __user *src, char *dst, int len, unsigned int sum)
 {
        return do_csum_partial_copy_from_user(src, dst, len, sum, NULL);
 }
index 90f0f30..2bc5be8 100644 (file)
@@ -9,7 +9,7 @@
  * This needs to be optimized.
  */
 void
-__ia64_memcpy_fromio (void *to, unsigned long from, long count)
+__ia64_memcpy_fromio (void *to, volatile void __iomem *from, long count)
 {
        char *dst = to;
 
@@ -25,7 +25,7 @@ EXPORT_SYMBOL(__ia64_memcpy_fromio);
  * This needs to be optimized.
  */
 void
-__ia64_memcpy_toio (unsigned long to, void *from, long count)
+__ia64_memcpy_toio (volatile void __iomem *to, void *from, long count)
 {
        char *src = from;
 
@@ -41,7 +41,7 @@ EXPORT_SYMBOL(__ia64_memcpy_toio);
  * This needs to be optimized.
  */
 void
-__ia64_memset_c_io (unsigned long dst, unsigned long c, long count)
+__ia64_memset_c_io (volatile void __iomem *dst, unsigned long c, long count)
 {
        unsigned char ch = (char)(c & 0xff);
 
@@ -111,49 +111,49 @@ __ia64_outl (unsigned int val, unsigned long port)
 }
 
 unsigned char
-__ia64_readb (void *addr)
+__ia64_readb (void __iomem *addr)
 {
        return ___ia64_readb (addr);
 }
 
 unsigned short
-__ia64_readw (void *addr)
+__ia64_readw (void __iomem *addr)
 {
        return ___ia64_readw (addr);
 }
 
 unsigned int
-__ia64_readl (void *addr)
+__ia64_readl (void __iomem *addr)
 {
        return ___ia64_readl (addr);
 }
 
 unsigned long
-__ia64_readq (void *addr)
+__ia64_readq (void __iomem *addr)
 {
        return ___ia64_readq (addr);
 }
 
 unsigned char
-__ia64_readb_relaxed (void *addr)
+__ia64_readb_relaxed (void __iomem *addr)
 {
        return ___ia64_readb (addr);
 }
 
 unsigned short
-__ia64_readw_relaxed (void *addr)
+__ia64_readw_relaxed (void __iomem *addr)
 {
        return ___ia64_readw (addr);
 }
 
 unsigned int
-__ia64_readl_relaxed (void *addr)
+__ia64_readl_relaxed (void __iomem *addr)
 {
        return ___ia64_readl (addr);
 }
 
 unsigned long
-__ia64_readq_relaxed (void *addr)
+__ia64_readq_relaxed (void __iomem *addr)
 {
        return ___ia64_readq (addr);
 }
index 781e23e..9d4486f 100644 (file)
@@ -11,6 +11,7 @@
  * 03/05/07 davidm     Switch from PCI-DMA to generic device DMA API.
  * 00/12/13 davidm     Rename to swiotlb.c and add mark_clean() to avoid
  *                     unnecessary i-cache flushing.
+ * 04/07/.. ak          Better overflow handling. Assorted fixes.
  */
 
 #include <linux/cache.h>
@@ -20,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/ctype.h>
 
 #include <asm/io.h>
 #include <asm/pci.h>
@@ -46,6 +48,8 @@
  */
 #define IO_TLB_SHIFT 11
 
+int swiotlb_force;
+
 /*
  * Used to do a quick range check in swiotlb_unmap_single and swiotlb_sync_single_*, to see
  * if the memory was in fact allocated by this API.
@@ -55,8 +59,16 @@ static char *io_tlb_start, *io_tlb_end;
 /*
  * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and io_tlb_end.
  * This is command line adjustable via setup_io_tlb_npages.
+ * Default to 64MB.
+ */
+static unsigned long io_tlb_nslabs = 32768;
+
+/* 
+ * When the IOMMU overflows we return a fallback buffer. This sets the size.
  */
-static unsigned long io_tlb_nslabs = 1024;
+static unsigned long io_tlb_overflow = 32*1024;
+
+void *io_tlb_overflow_buffer; 
 
 /*
  * This is a free list describing the number of free entries available from each index
@@ -78,15 +90,19 @@ static spinlock_t io_tlb_lock = SPIN_LOCK_UNLOCKED;
 static int __init
 setup_io_tlb_npages (char *str)
 {
-       io_tlb_nslabs = simple_strtoul(str, NULL, 0) << (PAGE_SHIFT - IO_TLB_SHIFT);
-
-       /* avoid tail segment of size < IO_TLB_SEGSIZE */
-       io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
-
+       if (isdigit(*str)) { 
+               io_tlb_nslabs = simple_strtoul(str, &str, 0) << (PAGE_SHIFT - IO_TLB_SHIFT);
+               /* avoid tail segment of size < IO_TLB_SEGSIZE */
+               io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
+       }
+       if (*str == ',')
+               ++str;
+       if (!strcmp(str, "force"))
+               swiotlb_force = 1;
        return 1;
 }
 __setup("swiotlb=", setup_io_tlb_npages);
-
+/* make io_tlb_overflow tunable too? */
 
 /*
  * Statically reserve bounce buffer space and initialize bounce buffer data structures for
@@ -102,7 +118,7 @@ swiotlb_init (void)
         */
        io_tlb_start = alloc_bootmem_low_pages(io_tlb_nslabs * (1 << IO_TLB_SHIFT));
        if (!io_tlb_start)
-               BUG();
+               panic("Cannot allocate SWIOTLB buffer");
        io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT);
 
        /*
@@ -115,11 +131,23 @@ swiotlb_init (void)
                io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
        io_tlb_index = 0;
        io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *));
-
-       printk(KERN_INFO "Placing software IO TLB between 0x%p - 0x%p\n",
-              (void *) io_tlb_start, (void *) io_tlb_end);
+       
+       /* 
+        * Get the overflow emergency buffer 
+        */
+       io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); 
+       printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n",
+              virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end));
 }
 
+static inline int address_needs_mapping(struct device *hwdev, dma_addr_t addr)
+{ 
+       dma_addr_t mask = 0xffffffff; 
+       if (hwdev && hwdev->dma_mask) 
+               mask = *hwdev->dma_mask; 
+       return (addr & ~mask) != 0;             
+} 
+
 /*
  * Allocates bounce buffer and returns its kernel virtual address.
  */
@@ -184,11 +212,8 @@ map_single (struct device *hwdev, char *buffer, size_t size, int dir)
                                index = 0;
                } while (index != wrap);
 
-               /*
-                * XXX What is a suitable recovery mechanism here?  We cannot
-                * sleep because we are called from with in interrupts!
-                */
-               panic("map_single: could not allocate software IO TLB (%ld bytes)", size);
+               spin_unlock_irqrestore(&io_tlb_lock, flags);
+               return NULL;
        }
   found:
        spin_unlock_irqrestore(&io_tlb_lock, flags);
@@ -285,7 +310,7 @@ swiotlb_alloc_coherent (struct device *hwdev, size_t size, dma_addr_t *dma_handl
 
        memset(ret, 0, size);
        dev_addr = virt_to_phys(ret);
-       if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
+       if (address_needs_mapping(hwdev,dev_addr))
                panic("swiotlb_alloc_consistent: allocated memory is out of range for device");
        *dma_handle = dev_addr;
        return ret;
@@ -297,6 +322,28 @@ swiotlb_free_coherent (struct device *hwdev, size_t size, void *vaddr, dma_addr_
        free_pages((unsigned long) vaddr, get_order(size));
 }
 
+static void swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
+{
+       /* 
+        * Ran out of IOMMU space for this operation. This is very bad.
+        * Unfortunately the drivers cannot handle this operation properly.
+        * unless they check for pci_dma_mapping_error (most don't)
+        * When the mapping is small enough return a static buffer to limit
+        * the damage, or panic when the transfer is too big. 
+        */ 
+       
+       printk(KERN_ERR 
+  "PCI-DMA: Out of SW-IOMMU space for %lu bytes at device %s\n",
+              size, dev ? dev->bus_id : "?");
+
+       if (size > io_tlb_overflow && do_panic) {
+               if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
+                       panic("PCI-DMA: Memory would be corrupted\n");
+               if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) 
+                       panic("PCI-DMA: Random memory would be DMAed\n"); 
+       } 
+} 
+
 /*
  * Map a single buffer of the indicated size for DMA in streaming mode.  The PCI address
  * to use is returned.
@@ -308,13 +355,14 @@ dma_addr_t
 swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir)
 {
        unsigned long dev_addr = virt_to_phys(ptr);
+       void *map; 
 
        if (dir == DMA_NONE)
                BUG();
        /*
         * Check if the PCI device can DMA to ptr... if so, just return ptr
         */
-       if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) == 0)
+       if (!address_needs_mapping(hwdev, dev_addr) && !swiotlb_force) 
                /*
                 * Device is bit capable of DMA'ing to the buffer... just return the PCI
                 * address of ptr
@@ -324,12 +372,18 @@ swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir)
        /*
         * get a bounce buffer:
         */
-       dev_addr = virt_to_phys(map_single(hwdev, ptr, size, dir));
+       map = map_single(hwdev, ptr, size, dir);
+       if (!map) { 
+               swiotlb_full(hwdev, size, dir, 1);              
+               map = io_tlb_overflow_buffer; 
+       }
+
+       dev_addr = virt_to_phys(map);
 
        /*
         * Ensure that the address returned is DMA'ble:
         */
-       if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
+       if (address_needs_mapping(hwdev, dev_addr))
                panic("map_single: bounce buffer is not DMA'ble");
 
        return dev_addr;
@@ -437,9 +491,17 @@ swiotlb_map_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int di
        for (i = 0; i < nelems; i++, sg++) {
                addr = SG_ENT_VIRT_ADDRESS(sg);
                dev_addr = virt_to_phys(addr);
-               if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
-                       sg->dma_address = (dma_addr_t) map_single(hwdev, addr, sg->length, dir);
-               else
+               if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) {
+                       sg->dma_address = (dma_addr_t) virt_to_phys(map_single(hwdev, addr, sg->length, dir));
+                       if (!sg->dma_address) {
+                               /* Don't panic here, we expect pci_map_sg users
+                                  to do proper error handling. */
+                               swiotlb_full(hwdev, sg->length, dir, 0); 
+                               swiotlb_unmap_sg(hwdev, sg - i, i, dir);
+                               sg[0].dma_length = 0;
+                               return 0;
+                       }
+               } else
                        sg->dma_address = dev_addr;
                sg->dma_length = sg->length;
        }
@@ -460,7 +522,7 @@ swiotlb_unmap_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int
 
        for (i = 0; i < nelems; i++, sg++)
                if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
-                       unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir);
+                       unmap_single(hwdev, (void *) phys_to_virt(sg->dma_address), sg->dma_length, dir);
                else if (dir == DMA_FROM_DEVICE)
                        mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
 }
@@ -501,7 +563,7 @@ swiotlb_sync_sg_for_device (struct device *hwdev, struct scatterlist *sg, int ne
 int
 swiotlb_dma_mapping_error (dma_addr_t dma_addr)
 {
-       return 0;
+       return (dma_addr == virt_to_phys(io_tlb_overflow_buffer));
 }
 
 /*
index 2353cc7..99edfed 100644 (file)
@@ -77,7 +77,7 @@ search_extable (const struct exception_table_entry *first,
                 else
                         last = mid - 1;
         }
-        return 0;
+        return NULL;
 }
 
 void
index bfac82f..56e6f61 100644 (file)
@@ -16,6 +16,10 @@ config OPROFILE
          whole system, include the kernel, kernel modules, libraries,
          and applications.
 
+         Due to firmware bugs, you may need to use the "nohalt" boot
+         option if you're using OProfile with the hardware performance
+         counters.
+
          If unsure, say N.
 
 endmenu
index 06e7c81..29aeef4 100644 (file)
@@ -7,3 +7,4 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
                timer_int.o )
 
 oprofile-y := $(DRIVER_OBJS) init.o
+oprofile-$(CONFIG_PERFMON) += perfmon.o
index 558561d..6d0c132 100644 (file)
 #include <linux/init.h>
 #include <linux/errno.h>
  
-extern void timer_init(struct oprofile_operations ** ops);
+extern int perfmon_init(struct oprofile_operations ** ops);
+extern void perfmon_exit(void);
 
 int __init oprofile_arch_init(struct oprofile_operations ** ops)
 {
+#ifdef CONFIG_PERFMON
+       return perfmon_init(ops);
+#endif
        return -ENODEV;
 }
 
 
 void oprofile_arch_exit(void)
 {
+#ifdef CONFIG_PERFMON
+       perfmon_exit();
+#endif
 }
diff --git a/arch/ia64/oprofile/perfmon.c b/arch/ia64/oprofile/perfmon.c
new file mode 100644 (file)
index 0000000..bfc82cc
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * @file perfmon.c
+ *
+ * @remark Copyright 2003 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@movementarian.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/oprofile.h>
+#include <linux/sched.h>
+#include <asm/perfmon.h>
+#include <asm/ptrace.h>
+#include <asm/errno.h>
+
+static int allow_ints;
+
+static int
+perfmon_handler(struct task_struct *task, void *buf, pfm_ovfl_arg_t *arg,
+                struct pt_regs *regs, unsigned long stamp)
+{
+       int cpu = smp_processor_id();
+       unsigned long eip = instruction_pointer(regs);
+       int event = arg->pmd_eventid;
+       arg->ovfl_ctrl.bits.reset_ovfl_pmds = 1;
+
+       /* the owner of the oprofile event buffer may have exited
+        * without perfmon being shutdown (e.g. SIGSEGV)
+        */
+       if (allow_ints)
+               oprofile_add_sample(eip, !user_mode(regs), event, cpu);
+       return 0;
+}
+
+
+static int perfmon_start(void)
+{
+       allow_ints = 1;
+       return 0;
+}
+
+
+static void perfmon_stop(void)
+{
+       allow_ints = 0;
+}
+
+
+#define OPROFILE_FMT_UUID { \
+       0x77, 0x7a, 0x6e, 0x61, 0x20, 0x65, 0x73, 0x69, 0x74, 0x6e, 0x72, 0x20, 0x61, 0x65, 0x0a, 0x6c }
+
+static pfm_buffer_fmt_t oprofile_fmt = {
+       .fmt_name           = "oprofile_format",
+       .fmt_uuid           = OPROFILE_FMT_UUID,
+       .fmt_handler        = perfmon_handler,
+};
+
+
+static char * get_cpu_type(void)
+{
+       __u8 family = local_cpu_data->family;
+
+       switch (family) {
+               case 0x07:
+                       return "ia64/itanium";
+               case 0x1f:
+                       return "ia64/itanium2";
+               default:
+                       return "ia64/ia64";
+       }
+}
+
+
+/* all the ops are handled via userspace for IA64 perfmon */
+static struct oprofile_operations perfmon_ops = {
+       .start = perfmon_start,
+       .stop = perfmon_stop,
+};
+
+static int using_perfmon;
+
+int perfmon_init(struct oprofile_operations ** ops)
+{
+       int ret = pfm_register_buffer_fmt(&oprofile_fmt);
+       if (ret)
+               return -ENODEV;
+
+       perfmon_ops.cpu_type = get_cpu_type();
+       *ops = &perfmon_ops;
+       using_perfmon = 1;
+       printk(KERN_INFO "oprofile: using perfmon.\n");
+       return 0;
+}
+
+
+void perfmon_exit(void)
+{
+       if (!using_perfmon)
+               return;
+
+       pfm_unregister_buffer_fmt(oprofile_fmt.fmt_uuid);
+}
index 0143b81..170bde4 100644 (file)
@@ -10,4 +10,4 @@
 #
 
 obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
-        prominfo_proc.o timer.o timer_interrupt.o
+        prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
new file mode 100644 (file)
index 0000000..8a810d3
--- /dev/null
@@ -0,0 +1,652 @@
+/* 
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ *
+ * SGI Altix topology and hardware performance monitoring API.
+ * Mark Goodwin <markgw@sgi.com>. 
+ *
+ * Creates /proc/sgi_sn/sn_topology (read-only) to export
+ * info about Altix nodes, routers, CPUs and NumaLink
+ * interconnection/topology.
+ *
+ * Also creates a dynamic misc device named "sn_hwperf"
+ * that supports an ioctl interface to call down into SAL
+ * to discover hw objects, topology and to read/write
+ * memory mapped registers, e.g. for performance monitoring.
+ * The "sn_hwperf" device is registered only after the procfs
+ * file is first opened, i.e. only if/when it's needed. 
+ *
+ * This API is used by SGI Performance Co-Pilot and other
+ * tools, see http://oss.sgi.com/projects/pcp
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/seq_file.h>
+#include <linux/miscdevice.h>
+#include <linux/cpumask.h>
+#include <linux/smp_lock.h>
+#include <asm/processor.h>
+#include <asm/topology.h>
+#include <asm/smp.h>
+#include <asm/semaphore.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <asm-ia64/sal.h>
+#include <asm-ia64/sn/sn_sal.h>
+#include <asm-ia64/sn/sn2/sn_hwperf.h>
+
+static void *sn_hwperf_salheap = NULL;
+static int sn_hwperf_obj_cnt = 0;
+static nasid_t sn_hwperf_master_nasid = INVALID_NASID;
+static int sn_hwperf_init(void);
+static DECLARE_MUTEX(sn_hwperf_init_mutex);
+
+static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret)
+{
+       int e;
+       u64 sz;
+       struct sn_hwperf_object_info *objbuf = NULL;
+
+       if ((e = sn_hwperf_init()) < 0) {
+               printk("sn_hwperf_init failed: err %d\n", e);
+               goto out;
+       }
+
+       sz = sn_hwperf_obj_cnt * sizeof(struct sn_hwperf_object_info);
+       if ((objbuf = (struct sn_hwperf_object_info *) vmalloc(sz)) == NULL) {
+               printk("sn_hwperf_enum_objects: vmalloc(%d) failed\n", (int)sz);
+               e = -ENOMEM;
+               goto out;
+       }
+
+       e = ia64_sn_hwperf_op(sn_hwperf_master_nasid, SN_HWPERF_ENUM_OBJECTS,
+               0, sz, (u64) objbuf, 0, 0, NULL);
+       if (e != SN_HWPERF_OP_OK) {
+               e = -EINVAL;
+               vfree(objbuf);
+       }
+
+out:
+       *nobj = sn_hwperf_obj_cnt;
+       *ret = objbuf;
+       return e;
+}
+
+static int sn_hwperf_geoid_to_cnode(char *location)
+{
+       int cnode;
+       int mod, slot, slab;
+       int cmod, cslot, cslab;
+
+       if (sscanf(location, "%03dc%02d#%d", &mod, &slot, &slab) != 3)
+               return -1;
+       for (cnode = 0; cnode < numnodes; cnode++) {
+               /* XXX: need a better way than this ... */
+               if (sscanf(NODEPDA(cnode)->hwg_node_name,
+                  "hw/module/%03dc%02d/slab/%d", &cmod, &cslot, &cslab) == 3) {
+                       if (mod == cmod && slot == cslot && slab == cslab)
+                               break;
+               }
+       }
+
+       return cnode < numnodes ? cnode : -1;
+}
+
+static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj)
+{
+       if (!obj->sn_hwp_this_part)
+               return -1;
+       return sn_hwperf_geoid_to_cnode(obj->location);
+}
+
+static int sn_hwperf_generic_ordinal(struct sn_hwperf_object_info *obj,
+                               struct sn_hwperf_object_info *objs)
+{
+       int ordinal;
+       struct sn_hwperf_object_info *p;
+
+       for (ordinal=0, p=objs; p != obj; p++) {
+               if (SN_HWPERF_FOREIGN(p))
+                       continue;
+               if (p->location[3] == obj->location[3])
+                       ordinal++;
+       }
+
+       return ordinal;
+}
+
+#ifndef MODULE_IOBRICK 
+/* this will be available when ioif TIO support is added */
+#define MODULE_IOBRICK (MODULE_OPUSBRICK+1)
+#endif
+
+static const char *sn_hwperf_get_brickname(struct sn_hwperf_object_info *obj,
+                               struct sn_hwperf_object_info *objs, int *ordinal)
+{
+       int i;
+       const char *objtype = NULL;
+
+       for (i=0; i < MAX_BRICK_TYPES; i++) {
+               if (brick_types[i] != obj->location[3])
+                       continue;
+               switch (i) {
+               case MODULE_CBRICK:
+                   objtype = "node";
+                   *ordinal = sn_hwperf_obj_to_cnode(obj); /* cnodeid */
+                   break;
+
+               case MODULE_RBRICK:
+                   objtype = "router";
+                   *ordinal = sn_hwperf_generic_ordinal(obj, objs);
+                   break;
+
+               case MODULE_IOBRICK:
+                   objtype = "ionode";
+                   *ordinal = sn_hwperf_generic_ordinal(obj, objs);
+                   break;
+               }
+               break;
+       }
+
+       if (i == MAX_BRICK_TYPES) {
+               objtype = "other";
+               *ordinal = sn_hwperf_generic_ordinal(obj, objs);
+       }
+
+       return objtype;
+}
+
+static int sn_topology_show(struct seq_file *s, void *d)
+{
+       int sz;
+       int pt;
+       int e;
+       int i;
+       int j;
+       const char *brickname;
+       int ordinal;
+       cpumask_t cpumask;
+       char slice;
+       struct cpuinfo_ia64 *c;
+       struct sn_hwperf_port_info *ptdata;
+       struct sn_hwperf_object_info *p;
+       struct sn_hwperf_object_info *obj = d;  /* this object */
+       struct sn_hwperf_object_info *objs = s->private; /* all objects */
+
+       if (obj == objs) {
+               seq_printf(s, "# sn_topology version 1\n");
+               seq_printf(s, "# objtype ordinal location partition"
+                       " [attribute value [, ...]]\n");
+       }
+
+       if (SN_HWPERF_FOREIGN(obj)) {
+               /* private in another partition: not interesting */
+               return 0;
+       }
+
+       for (i = 0; obj->name[i]; i++) {
+               if (obj->name[i] == ' ')
+                       obj->name[i] = '_';
+       }
+
+       brickname = sn_hwperf_get_brickname(obj, objs, &ordinal);
+       seq_printf(s, "%s %d %s %s asic %s", brickname, ordinal, obj->location,
+               obj->sn_hwp_this_part ? "local" : "shared", obj->name);
+
+       if (obj->location[3] != 'c')
+               seq_putc(s, '\n');
+       else {
+               seq_printf(s, ", nasid 0x%x", cnodeid_to_nasid(ordinal));
+               for (i=0; i < numnodes; i++) {
+                       seq_printf(s, i ? ":%d" : ", dist %d",
+                               node_distance(ordinal, i));
+               }
+               seq_putc(s, '\n');
+
+               /*
+                * CPUs on this node
+                */
+               cpumask = node_to_cpumask(ordinal);
+               for_each_online_cpu(i) {
+                       if (cpu_isset(i, cpumask)) {
+                               slice = 'a' + cpuid_to_slice(i);
+                               c = cpu_data(i);
+                               seq_printf(s, "cpu %d %s%c local"
+                                       " freq %luMHz, arch ia64",
+                                       i, obj->location, slice,
+                                       c->proc_freq / 1000000);
+                               for_each_online_cpu(j) {
+                                       seq_printf(s, j ? ":%d" : ", dist %d",
+                                               node_distance(
+                                                   cpuid_to_cnodeid(i),
+                                                   cpuid_to_cnodeid(j)));
+                               }
+                               seq_putc(s, '\n');
+                       }
+               }
+       }
+
+       if (obj->ports) {
+               /*
+                * numalink ports
+                */
+               sz = obj->ports * sizeof(struct sn_hwperf_port_info);
+               if ((ptdata = vmalloc(sz)) == NULL)
+                       return -ENOMEM;
+               e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
+                                     SN_HWPERF_ENUM_PORTS, obj->id, sz,
+                                     (u64) ptdata, 0, 0, NULL);
+               if (e != SN_HWPERF_OP_OK)
+                       return -EINVAL;
+               for (ordinal=0, p=objs; p != obj; p++) {
+                       if (!SN_HWPERF_FOREIGN(p))
+                               ordinal += p->ports;
+               }
+               for (pt = 0; pt < obj->ports; pt++) {
+                       for (p = objs, i = 0; i < sn_hwperf_obj_cnt; i++, p++) {
+                               if (ptdata[pt].conn_id == p->id) {
+                                       break;
+                               }
+                       }
+                       if (i >= sn_hwperf_obj_cnt)
+                               continue;
+                       seq_printf(s, "numalink %d %s-%d",
+                           ordinal+pt, obj->location, ptdata[pt].port);
+
+                       if (obj->sn_hwp_this_part && p->sn_hwp_this_part)
+                               /* both ends local to this partition */
+                               seq_puts(s, " local");
+                       else if (!obj->sn_hwp_this_part && !p->sn_hwp_this_part)
+                               /* both ends of the link in foreign partiton */
+                               seq_puts(s, " foreign");
+                       else
+                               /* link straddles a partition */
+                               seq_puts(s, " shared");
+
+                       /*
+                        * Unlikely, but strictly should query the LLP config
+                        * registers because an NL4R can be configured to run
+                        * NL3 protocol, even when not talking to an NL3 router.
+                        * Ditto for node-node.
+                        */
+                       seq_printf(s, " endpoint %s-%d, protocol %s\n",
+                               p->location, ptdata[pt].conn_port,
+                               strcmp(obj->name, "NL3Router") == 0 ||
+                               strcmp(p->name, "NL3Router") == 0 ?
+                               "LLP3" : "LLP4");
+               }
+               vfree(ptdata);
+       }
+
+       return 0;
+}
+
+static void *sn_topology_start(struct seq_file *s, loff_t * pos)
+{
+       struct sn_hwperf_object_info *objs = s->private;
+
+       if (*pos < sn_hwperf_obj_cnt)
+               return (void *)(objs + *pos);
+
+       return NULL;
+}
+
+static void *sn_topology_next(struct seq_file *s, void *v, loff_t * pos)
+{
+       ++*pos;
+       return sn_topology_start(s, pos);
+}
+
+static void sn_topology_stop(struct seq_file *m, void *v)
+{
+       return;
+}
+
+/*
+ * /proc/sgi_sn/sn_topology, read-only using seq_file
+ */
+static struct seq_operations sn_topology_seq_ops = {
+       .start = sn_topology_start,
+       .next = sn_topology_next,
+       .stop = sn_topology_stop,
+       .show = sn_topology_show
+};
+
+struct sn_hwperf_op_info {
+       u64 op;
+       struct sn_hwperf_ioctl_args *a;
+       void *p;
+       int *v0;
+       int ret;
+};
+
+static void sn_hwperf_call_sal(void *info)
+{
+       struct sn_hwperf_op_info *op_info = info;
+       int r;
+
+       r = ia64_sn_hwperf_op(sn_hwperf_master_nasid, op_info->op,
+                     op_info->a->arg, op_info->a->sz,
+                     (u64) op_info->p, 0, 0, op_info->v0);
+       op_info->ret = r;
+}
+
+static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info)
+{
+       u32 cpu;
+       u32 use_ipi;
+       int r = 0;
+       cpumask_t save_allowed;
+       
+       cpu = (op_info->a->arg & SN_HWPERF_ARG_CPU_MASK) >> 32;
+       use_ipi = op_info->a->arg & SN_HWPERF_ARG_USE_IPI_MASK;
+       op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK;
+
+       if (cpu != SN_HWPERF_ARG_ANY_CPU) {
+               if (cpu >= num_online_cpus() || !cpu_online(cpu)) {
+                       r = -EINVAL;
+                       goto out;
+               }
+       }
+
+       if (cpu == SN_HWPERF_ARG_ANY_CPU || cpu == get_cpu()) {
+               /* don't care, or already on correct cpu */
+               sn_hwperf_call_sal(op_info);
+       }
+       else {
+               if (use_ipi) {
+                       /* use an interprocessor interrupt to call SAL */
+                       smp_call_function_single(cpu, sn_hwperf_call_sal,
+                               op_info, 1, 1);
+               }
+               else {
+                       /* migrate the task before calling SAL */ 
+                       save_allowed = current->cpus_allowed;
+                       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+                       sn_hwperf_call_sal(op_info);
+                       set_cpus_allowed(current, save_allowed);
+               }
+       }
+       r = op_info->ret;
+
+out:
+       return r;
+}
+
+/*
+ * ioctl for "sn_hwperf" misc device
+ */
+static int
+sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
+{
+       struct sn_hwperf_ioctl_args a;
+       struct cpuinfo_ia64 *cdata;
+       struct sn_hwperf_object_info *objs;
+       struct sn_hwperf_object_info *cpuobj;
+       struct sn_hwperf_op_info op_info;
+       void *p = NULL;
+       int nobj;
+       char slice;
+       int node;
+       int r;
+       int v0;
+       int i;
+       int j;
+
+       unlock_kernel();
+
+       /* only user requests are allowed here */
+       if ((op & SN_HWPERF_OP_MASK) < 10) {
+               r = -EINVAL;
+               goto error;
+       }
+       r = copy_from_user(&a, (const void *)arg,
+               sizeof(struct sn_hwperf_ioctl_args));
+       if (r != 0) {
+               r = -EFAULT;
+               goto error;
+       }
+
+       /*
+        * Allocate memory to hold a kernel copy of the user buffer. The
+        * buffer contents are either copied in or out (or both) of user
+        * space depending on the flags encoded in the requested operation.
+        */
+       if (a.ptr) {
+               p = vmalloc(a.sz);
+               if (!p) {
+                       r = -ENOMEM;
+                       goto error;
+               }
+       }
+
+       if (op & SN_HWPERF_OP_MEM_COPYIN) {
+               r = copy_from_user(p, (const void *)a.ptr, a.sz);
+               if (r != 0) {
+                       r = -EFAULT;
+                       goto error;
+               }
+       }
+
+       switch (op) {
+       case SN_HWPERF_GET_CPU_INFO:
+               if (a.sz == sizeof(u64)) {
+                       /* special case to get size needed */
+                       *(u64 *) p = (u64) num_online_cpus() *
+                               sizeof(struct sn_hwperf_object_info);
+               } else
+               if (a.sz < num_online_cpus() * sizeof(struct sn_hwperf_object_info)) {
+                       r = -ENOMEM;
+                       goto error;
+               } else
+               if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
+                       memset(p, 0, a.sz);
+                       for (i = 0; i < nobj; i++) {
+                               node = sn_hwperf_obj_to_cnode(objs + i);
+                               for_each_online_cpu(j) {
+                                       if (node != cpu_to_node(j))
+                                               continue;
+                                       cpuobj = (struct sn_hwperf_object_info *) p + j;
+                                       slice = 'a' + cpuid_to_slice(j);
+                                       cdata = cpu_data(j);
+                                       cpuobj->id = j;
+                                       snprintf(cpuobj->name,
+                                                sizeof(cpuobj->name),
+                                                "CPU %luMHz %s",
+                                                cdata->proc_freq / 1000000,
+                                                cdata->vendor);
+                                       snprintf(cpuobj->location,
+                                                sizeof(cpuobj->location),
+                                                "%s%c", objs[i].location,
+                                                slice);
+                               }
+                       }
+
+                       vfree(objs);
+               }
+               break;
+
+       case SN_HWPERF_GET_NODE_NASID:
+               if (a.sz != sizeof(u64) ||
+                  (node = a.arg) < 0 || node >= numnodes) {
+                       r = -EINVAL;
+                       goto error;
+               }
+               *(u64 *)p = (u64)cnodeid_to_nasid(node);
+               break;
+
+       case SN_HWPERF_GET_OBJ_NODE:
+               if (a.sz != sizeof(u64) || a.arg < 0) {
+                       r = -EINVAL;
+                       goto error;
+               }
+               if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
+                       if (a.arg >= nobj) {
+                               r = -EINVAL;
+                               vfree(objs);
+                               goto error;
+                       }
+                       if (objs[(i = a.arg)].id != a.arg) {
+                               for (i = 0; i < nobj; i++) {
+                                       if (objs[i].id == a.arg)
+                                               break;
+                               }
+                       }
+                       if (i == nobj) {
+                               r = -EINVAL;
+                               vfree(objs);
+                               goto error;
+                       }
+                       *(u64 *)p = (u64)sn_hwperf_obj_to_cnode(objs + i);
+                       vfree(objs);
+               }
+               break;
+
+       case SN_HWPERF_GET_MMRS:
+       case SN_HWPERF_SET_MMRS:
+       case SN_HWPERF_OBJECT_DISTANCE:
+               op_info.p = p;
+               op_info.a = &a;
+               op_info.v0 = &v0;
+               op_info.op = op;
+               r = sn_hwperf_op_cpu(&op_info);
+               break;
+
+       default:
+               /* all other ops are a direct SAL call */
+               r = ia64_sn_hwperf_op(sn_hwperf_master_nasid, op,
+                             a.arg, a.sz, (u64) p, 0, 0, &v0);
+               a.v0 = v0;
+               break;
+       }
+
+       if (op & SN_HWPERF_OP_MEM_COPYOUT) {
+               r = copy_to_user((void *)a.ptr, p, a.sz);
+               if (r != 0) {
+                       r = -EFAULT;
+                       goto error;
+               }
+       }
+
+error:
+       if (p)
+               vfree(p);
+
+       lock_kernel();
+       return r;
+}
+
+static struct file_operations sn_hwperf_fops = {
+       .ioctl = sn_hwperf_ioctl,
+};
+
+static struct miscdevice sn_hwperf_dev = {
+       MISC_DYNAMIC_MINOR,
+       "sn_hwperf",
+       &sn_hwperf_fops
+};
+
+static int sn_hwperf_init(void)
+{
+       u64 v;
+       int salr;
+       int e = 0;
+
+       /* single threaded, once-only initialization */
+       down(&sn_hwperf_init_mutex);
+       if (sn_hwperf_salheap) {
+               up(&sn_hwperf_init_mutex);
+               return e;
+       }
+
+       /*
+        * The PROM code needs a fixed reference node. For convenience the
+        * same node as the console I/O is used.
+        */
+       sn_hwperf_master_nasid = (nasid_t) ia64_sn_get_console_nasid();
+
+       /*
+        * Request the needed size and install the PROM scratch area.
+        * The PROM keeps various tracking bits in this memory area.
+        */
+       salr = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
+                                (u64) SN_HWPERF_GET_HEAPSIZE, 0,
+                                (u64) sizeof(u64), (u64) &v, 0, 0, NULL);
+       if (salr != SN_HWPERF_OP_OK) {
+               e = -EINVAL;
+               goto out;
+       }
+
+       if ((sn_hwperf_salheap = vmalloc(v)) == NULL) {
+               e = -ENOMEM;
+               goto out;
+       }
+       salr = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
+                                SN_HWPERF_INSTALL_HEAP, 0, v,
+                                (u64) sn_hwperf_salheap, 0, 0, NULL);
+       if (salr != SN_HWPERF_OP_OK) {
+               e = -EINVAL;
+               goto out;
+       }
+
+       salr = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
+                                SN_HWPERF_OBJECT_COUNT, 0,
+                                sizeof(u64), (u64) &v, 0, 0, NULL);
+       if (salr != SN_HWPERF_OP_OK) {
+               e = -EINVAL;
+               goto out;
+       }
+       sn_hwperf_obj_cnt = (int)v;
+
+out:
+       if (e < 0 && sn_hwperf_salheap) {
+               vfree(sn_hwperf_salheap);
+               sn_hwperf_salheap = NULL;
+               sn_hwperf_obj_cnt = 0;
+       }
+
+       if (!e) {
+               /*
+                * Register a dynamic misc device for ioctl. Platforms
+                * supporting hotplug will create /dev/sn_hwperf, else
+                * user can to look up the minor number in /proc/misc.
+                */
+               if ((e = misc_register(&sn_hwperf_dev)) != 0) {
+                       printk(KERN_ERR "sn_hwperf_init: misc register "
+                              "for \"sn_hwperf\" failed, err %d\n", e);
+               }
+       }
+
+       up(&sn_hwperf_init_mutex);
+       return e;
+}
+
+int sn_topology_open(struct inode *inode, struct file *file)
+{
+       int e;
+       struct seq_file *seq;
+       struct sn_hwperf_object_info *objbuf;
+       int nobj;
+
+       if ((e = sn_hwperf_enum_objects(&nobj, &objbuf)) == 0) {
+               e = seq_open(file, &sn_topology_seq_ops);
+               seq = file->private_data;
+               seq->private = objbuf;
+       }
+
+       return e;
+}
+
+int sn_topology_release(struct inode *inode, struct file *file)
+{
+       struct seq_file *seq = file->private_data;
+
+       if (seq->private)
+               vfree(seq->private);
+       return seq_release(inode, file);
+}
index 1484079..55c1065 100644 (file)
@@ -3,74 +3,48 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.
  */
 #include <linux/config.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/sn_sal.h>
 
-
-static int partition_id_read_proc(char *page, char **start, off_t off,
-               int count, int *eof, void *data) {
-
-       return sprintf(page, "%d\n", sn_local_partid());
+static int partition_id_show(struct seq_file *s, void *p)
+{
+       seq_printf(s, "%d\n", sn_local_partid());
+       return 0;
 }
 
-static struct proc_dir_entry * sgi_proc_dir;
-
-void
-register_sn_partition_id(void) {
-       struct proc_dir_entry *entry;
-
-       if (!sgi_proc_dir) {
-               sgi_proc_dir = proc_mkdir("sgi_sn", 0);
-       }
-       entry = create_proc_entry("partition_id", 0444, sgi_proc_dir);
-       if (entry) {
-               entry->nlink = 1;
-               entry->data = 0;
-               entry->read_proc = partition_id_read_proc;
-               entry->write_proc = NULL;
-       }
+static int partition_id_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, partition_id_show, NULL);
 }
 
-static int
-system_serial_number_read_proc(char *page, char **start, off_t off,
-               int count, int *eof, void *data) {
-       return sprintf(page, "%s\n", sn_system_serial_number());
+static int system_serial_number_show(struct seq_file *s, void *p)
+{
+       seq_printf(s, "%s\n", sn_system_serial_number());
+       return 0;
 }
 
-static int
-licenseID_read_proc(char *page, char **start, off_t off,
-               int count, int *eof, void *data) {
-       return sprintf(page, "0x%lx\n",sn_partition_serial_number_val());
+static int system_serial_number_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, system_serial_number_show, NULL);
 }
 
-void
-register_sn_serial_numbers(void) {
-       struct proc_dir_entry *entry;
+static int licenseID_show(struct seq_file *s, void *p)
+{
+       seq_printf(s, "0x%lx\n", sn_partition_serial_number_val());
+       return 0;
+}
 
-       if (!sgi_proc_dir) {
-               sgi_proc_dir = proc_mkdir("sgi_sn", 0);
-       }
-       entry = create_proc_entry("system_serial_number", 0444, sgi_proc_dir);
-       if (entry) {
-               entry->nlink = 1;
-               entry->data = 0;
-               entry->read_proc = system_serial_number_read_proc;
-               entry->write_proc = NULL;
-       }
-       entry = create_proc_entry("licenseID", 0444, sgi_proc_dir);
-       if (entry) {
-               entry->nlink = 1;
-               entry->data = 0;
-               entry->read_proc = licenseID_read_proc;
-               entry->write_proc = NULL;
-       }
+static int licenseID_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, licenseID_show, NULL);
 }
 
 /*
@@ -81,48 +55,90 @@ register_sn_serial_numbers(void) {
  */
 int sn_force_interrupt_flag = 1;
 
-static int
-sn_force_interrupt_read_proc(char *page, char **start, off_t off,
-               int count, int *eof, void *data) {
-       if (sn_force_interrupt_flag) {
-               return sprintf(page, "Force interrupt is enabled\n");
-       }
-       return sprintf(page, "Force interrupt is disabled\n");
+static int sn_force_interrupt_show(struct seq_file *s, void *p)
+{
+       seq_printf(s, "Force interrupt is %s\n",
+               sn_force_interrupt_flag ? "enabled" : "disabled");
+       return 0;
 }
 
-static int 
-sn_force_interrupt_write_proc(struct file *file, const char *buffer,
-                                        unsigned long count, void *data)
+static ssize_t sn_force_interrupt_write_proc(struct file *file,
+               const __user char *buffer, size_t count, loff_t *data)
 {
-       if (*buffer == '0') {
-               sn_force_interrupt_flag = 0;
-       } else {
-               sn_force_interrupt_flag = 1;
-       }
-       return 1;
+       sn_force_interrupt_flag = (*buffer == '0') ? 0 : 1;
+       return count;
 }
 
-void
-register_sn_force_interrupt(void) {
-       struct proc_dir_entry *entry;
+static int sn_force_interrupt_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, sn_force_interrupt_show, NULL);
+}
 
-       if (!sgi_proc_dir) {
-               sgi_proc_dir = proc_mkdir("sgi_sn", 0);
-       }
-       entry = create_proc_entry("sn_force_interrupt",0444, sgi_proc_dir);
-       if (entry) {
-               entry->nlink = 1;
-               entry->data = 0;
-               entry->read_proc = sn_force_interrupt_read_proc;
-               entry->write_proc = sn_force_interrupt_write_proc;
+static int coherence_id_show(struct seq_file *s, void *p)
+{
+       seq_printf(s, "%d\n", cpuid_to_coherence_id(smp_processor_id()));
+       return 0;
+}
+
+static int coherence_id_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, coherence_id_show, NULL);
+}
+
+static struct proc_dir_entry *sn_procfs_create_entry(
+       const char *name, struct proc_dir_entry *parent,
+       int (*openfunc)(struct inode *, struct file *),
+       int (*releasefunc)(struct inode *, struct file *))
+{
+       struct proc_dir_entry *e = create_proc_entry(name, 0444, parent);
+
+       if (e) {
+               e->proc_fops = (struct file_operations *)kmalloc(
+                       sizeof(struct file_operations), GFP_KERNEL);
+               if (e->proc_fops) {
+                       memset(e->proc_fops, 0, sizeof(struct file_operations));
+                       e->proc_fops->open = openfunc;
+                       e->proc_fops->read = seq_read;
+                       e->proc_fops->llseek = seq_lseek;
+                       e->proc_fops->release = releasefunc;
+               }
        }
+
+       return e;
 }
 
-void
-register_sn_procfs(void) {
-       register_sn_partition_id();
-       register_sn_serial_numbers();
-       register_sn_force_interrupt();
+/* /proc/sgi_sn/sn_topology uses seq_file, see sn_hwperf.c */
+extern int sn_topology_open(struct inode *, struct file *);
+extern int sn_topology_release(struct inode *, struct file *);
+
+void register_sn_procfs(void)
+{
+       static struct proc_dir_entry *sgi_proc_dir = NULL;
+       struct proc_dir_entry *e;
+
+       BUG_ON(sgi_proc_dir != NULL);
+       if (!(sgi_proc_dir = proc_mkdir("sgi_sn", 0)))
+               return;
+
+       sn_procfs_create_entry("partition_id", sgi_proc_dir,
+               partition_id_open, single_release);
+
+       sn_procfs_create_entry("system_serial_number", sgi_proc_dir,
+               system_serial_number_open, single_release);
+
+       sn_procfs_create_entry("licenseID", sgi_proc_dir, 
+               licenseID_open, single_release);
+
+       e = sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir, 
+               sn_force_interrupt_open, single_release);
+       if (e) 
+               e->proc_fops->write = sn_force_interrupt_write_proc;
+
+       sn_procfs_create_entry("coherence_id", sgi_proc_dir, 
+               coherence_id_open, single_release);
+       
+       sn_procfs_create_entry("sn_topology", sgi_proc_dir,
+               sn_topology_open, sn_topology_release);
 }
 
 #endif /* CONFIG_PROC_FS */
index 57844fe..85f7d21 100644 (file)
 
 
 extern unsigned long sn_rtc_cycles_per_second;
-static volatile unsigned long last_wall_rtc;
 
-static unsigned long rtc_offset;       /* updated only when xtime write-lock is held! */
-static long rtc_nsecs_per_cycle;
-static long rtc_per_timer_tick;
-
-static unsigned long
-getoffset(void)
-{
-       return rtc_offset + (GET_RTC_COUNTER() - last_wall_rtc)*rtc_nsecs_per_cycle;
-}
-
-
-static void
-update(long delta_nsec)
-{
-       unsigned long rtc_counter = GET_RTC_COUNTER();
-       unsigned long offset = rtc_offset + (rtc_counter - last_wall_rtc)*rtc_nsecs_per_cycle;
-
-       /* Be careful about signed/unsigned comparisons here: */
-       if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
-               rtc_offset = offset - delta_nsec;
-       else
-               rtc_offset = 0;
-       last_wall_rtc = rtc_counter;
-}
-
-
-static void
-reset(void)
-{
-       rtc_offset = 0;
-       last_wall_rtc = GET_RTC_COUNTER();
-}
-
-
-static struct time_interpolator sn2_interpolator = {
-       .get_offset =   getoffset,
-       .update =       update,
-       .reset =        reset
-};
+static struct time_interpolator sn2_interpolator;
 
 void __init
 sn_timer_init(void)
 {
        sn2_interpolator.frequency = sn_rtc_cycles_per_second;
        sn2_interpolator.drift = -1;    /* unknown */
+       sn2_interpolator.shift = 10;    /* RTC is 54 bits maximum shift is 10 */
+       sn2_interpolator.addr = RTC_COUNTER_ADDR;
+       sn2_interpolator.source = TIME_SOURCE_MMIO64;
        register_time_interpolator(&sn2_interpolator);
-
-       rtc_per_timer_tick = sn_rtc_cycles_per_second / HZ;
-       rtc_nsecs_per_cycle = 1000000000 / sn_rtc_cycles_per_second;
-
-       last_wall_rtc = GET_RTC_COUNTER();
 }
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
new file mode 100644 (file)
index 0000000..bacc0b2
--- /dev/null
@@ -0,0 +1,441 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+mainmenu "Linux Kernel Configuration"
+
+config M32R
+       bool
+       default y
+
+config SBUS
+       bool
+
+config UID16
+       bool
+       default y
+
+config GENERIC_ISA_DMA
+       bool
+       default y
+
+source "init/Kconfig"
+
+
+menu "Processor type and features"
+
+choice
+       prompt "Platform Type"
+       default PLAT_MAPPI
+
+config PLAT_MAPPI
+       bool "Mappi-I"
+       help
+         The Mappi-I is an FPGA board for SOC (System-On-a-Chip) prototyping.
+         You can operate a Linux system on this board by using an M32R
+         softmacro core, which is a fully-synthesizable functional model
+         described in Verilog-HDL.
+
+         The Mappi-I board was the first platform, which had been used
+         to port and develop a Linux system for the M32R processor.
+         Currently, the Mappi-II, an heir to the Mappi-I, is available.
+
+config PLAT_USRV
+       bool "uServer"
+
+config PLAT_M32700UT
+       bool "M32700UT"
+       help
+         The M3T-M32700UT is an evaluation board based on uT-Engine
+         specification.  This board has an M32700 (Chaos) evaluation chip.
+         You can say Y for SMP, because the M32700 is a single chip
+         multiprocessor.
+
+config PLAT_OPSPUT
+       bool "OPSPUT"
+       help
+         The OPSPUT is an evaluation board based on uT-Engine
+         specification.  This board has a OPSP-REP chip.
+
+config PLAT_OAKS32R
+       bool "OAKS32R"
+       help
+         The OAKS32R is a tiny, inexpensive evaluation board.
+         Please note that if you say Y here and choose chip "M32102",
+         say N for MMU and select a no-MMU version kernel, otherwise
+         a kernel with MMU support will not work, because the M32102
+         is a microcontroller for embedded systems and it has no MMU.
+
+config PLAT_MAPPI2
+       bool "Mappi-II(M3A-ZA36/M3A-ZA52)"
+
+endchoice
+
+choice
+       prompt "Processor family"
+       default CHIP_M32700
+
+config CHIP_M32700
+       bool "M32700 (Chaos)"
+
+config CHIP_M32102
+       bool "M32102"
+
+config CHIP_VDEC2
+       bool "VDEC2"
+
+config CHIP_OPSP
+       bool "OPSP"
+
+endchoice
+
+config MMU
+       bool "Support for memory management hardware"
+       depends on CHIP_M32700 || CHIP_VDEC2 || CHIP_OPSP
+       default y
+
+config TLB_ENTRIES
+       int "TLB Entries"
+       depends on CHIP_M32700 || CHIP_VDEC2 || CHIP_OPSP
+       default 32 if CHIP_M32700 || CHIP_OPSP
+       default 16 if CHIP_VDEC2
+
+
+config ISA_M32R
+        bool
+       depends on CHIP_M32102
+       default y
+
+config ISA_M32R2
+       bool
+       depends on CHIP_M32700 || CHIP_VDEC2 || CHIP_OPSP
+       default y
+
+config ISA_DSP_LEVEL2
+       bool
+       depends on CHIP_M32700 || CHIP_OPSP
+       default y
+
+config ISA_DUAL_ISSUE
+       bool
+       depends on CHIP_M32700 || CHIP_OPSP
+       default y
+
+config BUS_CLOCK
+       int "Bus Clock [Hz] (integer)"
+       default "70000000" if PLAT_MAPPI
+       default "25000000" if PLAT_USRV
+       default "50000000" if PLAT_M32700UT
+       default "50000000" if PLAT_OPSPUT
+       default "33333333" if PLAT_OAKS32R
+       default "20000000" if PLAT_MAPPI2
+
+config TIMER_DIVIDE
+       int "Timer divider (integer)"
+       default "128"
+
+config CPU_LITTLE_ENDIAN
+        bool "Generate little endian code"
+       default n
+
+config MEMORY_START
+       hex "Physical memory start address (hex)"
+       default "08000000" if PLAT_MAPPI || PLAT_MAPPI2
+       default "08000000" if PLAT_USRV
+       default "08000000" if PLAT_M32700UT
+       default "08000000" if PLAT_OPSPUT
+       default "01000000" if PLAT_OAKS32R
+
+config MEMORY_SIZE
+       hex "Physical memory size (hex)"
+       default "04000000" if PLAT_MAPPI || PLAT_MAPPI2
+       default "02000000" if PLAT_USRV
+       default "01000000" if PLAT_M32700UT
+       default "01000000" if PLAT_OPSPUT
+       default "00800000" if PLAT_OAKS32R
+
+config NOHIGHMEM
+       bool
+       default y
+
+config DISCONTIGMEM
+       bool "Internal RAM Support"
+       depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP
+       default y
+
+config IRAM_START
+       hex "Internal memory start address (hex)"
+       default "00f00000"
+       depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM
+
+config IRAM_SIZE
+       hex "Internal memory size (hex)"
+       depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM
+       default "00080000" if CHIP_M32700
+       default "00010000" if CHIP_M32102 || CHIP_OPSP
+       default "00008000" if CHIP_VDEC2
+
+#
+# Define implied options from the CPU selection here
+#
+
+config RWSEM_GENERIC_SPINLOCK
+       bool
+       depends on M32R
+       default y
+
+config RWSEM_XCHGADD_ALGORITHM
+       bool
+       default n
+
+config PREEMPT
+       bool "Preemptible Kernel"
+       help
+         This option reduces the latency of the kernel when reacting to
+         real-time or interactive events by allowing a low priority process to
+         be preempted even if it is in kernel mode executing a system call.
+         This allows applications to run more reliably even when the system is
+         under load.
+
+         Say Y here if you are building a kernel for a desktop, embedded
+         or real-time system.  Say N if you are unsure.
+
+config HAVE_DEC_LOCK
+       bool
+       depends on (SMP || PREEMPT)
+       default n
+
+config SMP
+       bool "Symmetric multi-processing support"
+       ---help---
+         This enables support for systems with more than one CPU. If you have
+         a system with only one CPU, like most personal computers, say N. If
+         you have a system with more than one CPU, say Y.
+
+         If you say N here, the kernel will run on single and multiprocessor
+         machines, but will use only one CPU of a multiprocessor machine. If
+         you say Y here, the kernel will run on many, but not all,
+         singleprocessor machines. On a singleprocessor machine, the kernel
+         will run faster if you say N here.
+
+         People using multiprocessor machines who say Y here should also say
+         Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
+         Management" code will be disabled if you say Y here.
+
+         See also the <file:Documentation/smp.tex>,
+         <file:Documentation/smp.txt> and the SMP-HOWTO available at
+         <http://www.linuxdoc.org/docs.html#howto>.
+
+         If you don't know what to do here, say N.
+
+config CHIP_M32700_TS1
+       bool "Workaround code for the M32700 TS1 chip's bug"
+       depends on (CHIP_M32700 && SMP)
+       default n
+
+config NR_CPUS
+       int "Maximum number of CPUs (2-32)"
+       range 2 32
+       depends on SMP
+       default "2"
+       help
+         This allows you to specify the maximum number of CPUs which this
+         kernel will support.  The maximum supported value is 32 and the
+         minimum value which makes sense is 2.
+
+         This is purely to save memory - each supported CPU adds
+         approximately eight kilobytes to the kernel image.
+
+# Common NUMA Features
+config NUMA
+       bool "Numa Memory Allocation Support"
+       depends on SMP
+       default n
+
+# turning this on wastes a bunch of space.
+# Summit needs it only when NUMA is on
+config BOOT_IOREMAP
+       bool
+       depends on NUMA
+       default n
+
+endmenu
+
+
+menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
+
+config PCI
+       bool "PCI support"
+       default n
+       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
+         your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+         VESA. If you have PCI, say Y, otherwise N.
+
+         The PCI-HOWTO, available from
+         <http://www.linuxdoc.org/docs.html#howto>, contains valuable
+         information about which PCI hardware does work under Linux and which
+         doesn't.
+
+choice
+       prompt "PCI access mode"
+       depends on PCI
+       default PCI_GOANY
+
+config PCI_GOBIOS
+       bool "BIOS"
+       ---help---
+         On PCI systems, the BIOS can be used to detect the PCI devices and
+         determine their configuration. However, some old PCI motherboards
+         have BIOS bugs and may crash if this is done. Also, some embedded
+         PCI-based systems don't have any BIOS at all. Linux can also try to
+         detect the PCI hardware directly without using the BIOS.
+
+         With this option, you can specify how Linux should detect the PCI
+         devices. If you choose "BIOS", the BIOS will be used, if you choose
+         "Direct", the BIOS won't be used, and if you choose "Any", the
+         kernel will try the direct access method and falls back to the BIOS
+         if that doesn't work. If unsure, go with the default, which is
+         "Any".
+
+config PCI_GODIRECT
+       bool "Direct"
+
+config PCI_GOANY
+       bool "Any"
+
+endchoice
+
+config PCI_BIOS
+       bool
+       depends on PCI && (PCI_GOBIOS || PCI_GOANY)
+       default y
+
+config PCI_DIRECT
+       bool
+       depends on PCI && (PCI_GODIRECT || PCI_GOANY)
+       default y
+
+source "drivers/pci/Kconfig"
+
+config ISA
+       bool "ISA support"
+       help
+         Find out whether you have ISA slots on your motherboard.  ISA is the
+         name of a bus system, i.e. the way the CPU talks to the other stuff
+         inside your box.  If you have ISA, say Y, otherwise N.
+
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+endmenu
+
+
+menu "Executable file formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/m32r/oprofile/Kconfig"
+
+menu "Kernel hacking"
+
+config DEBUG_KERNEL
+       bool "Kernel debugging"
+       help
+         Say Y here if you are developing drivers or trying to debug and
+         identify kernel problems.
+
+config DEBUG_STACKOVERFLOW
+       bool "Check for stack overflows"
+       depends on DEBUG_KERNEL
+
+config DEBUG_SLAB
+       bool "Debug memory allocations"
+       depends on DEBUG_KERNEL
+       help
+         Say Y here to have the kernel do limited verification on memory
+         allocation as well as poisoning memory on free to catch use of freed
+         memory.
+
+config DEBUG_IOVIRT
+       bool "Memory mapped I/O debugging"
+       depends on DEBUG_KERNEL
+       help
+         Say Y here to get warned whenever an attempt is made to do I/O on
+         obviously invalid addresses such as those generated when ioremap()
+         calls are forgotten.  Memory mapped I/O will go through an extra
+         check to catch access to unmapped ISA addresses, an access method
+         that can still be used by old drivers that are being ported from
+         2.0/2.2.
+
+config MAGIC_SYSRQ
+       bool "Magic SysRq key"
+       depends on DEBUG_KERNEL
+       help
+         If you say Y here, you will have some control over the system even
+         if the system crashes for example during kernel debugging (e.g., you
+         will be able to flush the buffer cache to disk, reboot the system
+         immediately or dump some status information). This is accomplished
+         by pressing various keys while holding SysRq (Alt+PrintScreen). It
+         also works on a serial console (on PC hardware at least), if you
+         send a BREAK and then within 5 seconds a command keypress. The
+         keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
+         unless you really know what this hack does.
+
+config DEBUG_SPINLOCK
+       bool "Spinlock debugging"
+       depends on DEBUG_KERNEL
+       help
+         Say Y here and build SMP to catch missing spinlock initialization
+         and certain other kinds of spinlock errors commonly made.  This is
+         best used in conjunction with the NMI watchdog so that spinlock
+         deadlocks are also debuggable.
+
+config DEBUG_PAGEALLOC
+       bool "Page alloc debugging"
+       depends on DEBUG_KERNEL
+       help
+         Unmap pages from the kernel linear mapping after free_pages().
+         This results in a large slowdown, but helps to find certain types
+         of memory corruptions.
+
+config DEBUG_INFO
+       bool "Compile the kernel with debug info"
+       depends on DEBUG_KERNEL
+       help
+          If you say Y here the resulting kernel image will include
+         debugging info resulting in a larger kernel image.
+         Say Y here only if you plan to use gdb to debug the kernel.
+         If you don't debug the kernel, you can say N.
+
+config DEBUG_SPINLOCK_SLEEP
+       bool "Sleep-inside-spinlock checking"
+       help
+         If you say Y here, various routines which may sleep will become very
+         noisy if they are called with a spinlock held.
+
+config FRAME_POINTER
+       bool "Compile the kernel with frame pointers"
+       help
+         If you say Y here the resulting kernel image will be slightly larger
+         and slower, but it will give very useful debugging information.
+         If you don't debug the kernel, you can say N, but we may not be able
+         to solve problems without frame pointers.
+
+endmenu
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
diff --git a/arch/m32r/Makefile b/arch/m32r/Makefile
new file mode 100644 (file)
index 0000000..63ea62a
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# m32r/Makefile
+#
+
+LDFLAGS                :=
+OBJCOPYFLAGS   := -O binary -R .note -R .comment -S
+LDFLAGS_vmlinux        := -e startup_32
+LDFLAGS_BLOB   := --format binary --oformat elf32-m32r
+
+CFLAGS += -pipe -fno-schedule-insns
+CFLAGS_KERNEL += -mmodel=medium
+CFLAGS_MODULE += -mmodel=large
+
+ifdef CONFIG_CHIP_VDEC2
+cflags-$(CONFIG_ISA_M32R2)     += -DNO_FPU -Wa,-bitinst
+aflags-$(CONFIG_ISA_M32R2)     += -DNO_FPU -Wa,-bitinst
+else
+cflags-$(CONFIG_ISA_M32R2)     += -DNO_FPU -m32r2
+aflags-$(CONFIG_ISA_M32R2)     += -DNO_FPU -m32r2
+endif
+
+cflags-$(CONFIG_ISA_M32R)      += -DNO_FPU
+aflags-$(CONFIG_ISA_M32R)      += -DNO_FPU -Wa,-no-bitinst
+
+CFLAGS += $(cflags-y)
+AFLAGS += $(aflags-y)
+
+CHECKFLAGS     := $(CHECK) -D__m32r__
+
+head-y := arch/m32r/kernel/head.o arch/m32r/kernel/init_task.o
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+
+libs-y += arch/m32r/lib/ $(LIBGCC)
+core-y += arch/m32r/kernel/    \
+          arch/m32r/mm/        \
+          arch/m32r/boot/
+
+drivers-$(CONFIG_OPROFILE)     += arch/m32r/oprofile/
+
+boot := arch/m32r/boot
+
+.PHONY: zImage
+
+zImage: vmlinux
+       $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+compressed: zImage
+
+archclean:
+       $(Q)$(MAKE) $(clean)=$(boot)
+
+define archhelp
+       @echo '  zImage                 - Compressed kernel image (arch/m32r/boot/zImage)'
+endef
diff --git a/arch/m32r/boot/Makefile b/arch/m32r/boot/Makefile
new file mode 100644 (file)
index 0000000..af2cef4
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# arch/m32r/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.
+
+targets := zImage
+subdir- := compressed
+
+obj-y  := setup.o
+
+$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+       $(call if_changed,objcopy)
+       @echo 'Kernel: $@ is ready'
+
+$(obj)/compressed/vmlinux: FORCE
+       $(Q)$(MAKE) $(build)=$(obj)/compressed $@
+
diff --git a/arch/m32r/boot/compressed/Makefile b/arch/m32r/boot/compressed/Makefile
new file mode 100644 (file)
index 0000000..a8f130d
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# 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 \
+                  m32r-sio.o piggy.o vmlinux.lds
+EXTRA_AFLAGS   := -traditional
+
+OBJECTS = $(obj)/head.o $(obj)/misc.o $(obj)/m32r_sio.o
+
+#
+# IMAGE_OFFSET is the load offset of the compression loader
+#
+#IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_MEMORY_START)+0x2000])
+#IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_MEMORY_START)+0x00400000])
+
+LDFLAGS_vmlinux := -T
+
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(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)
+
+$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.S FORCE
+       $(CPP) $(EXTRA_AFLAGS) -C -P -I include $< >$@
+
+LDFLAGS_piggy.o := -r --format binary --oformat elf32-m32r-linux -T
+OBJCOPYFLAGS += -R .empty_zero_page
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
+       $(call if_changed,ld)
diff --git a/arch/m32r/boot/compressed/boot.h b/arch/m32r/boot/compressed/boot.h
new file mode 100644 (file)
index 0000000..9272e38
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 1. load vmlinuz
+ *
+ * CONFIG_MEMORY_START         +-----------------------+
+ *                             |        vmlinuz        |
+ *                             +-----------------------+
+ * 2. decompressed
+ *
+ * CONFIG_MEMORY_START         +-----------------------+
+ *                             |        vmlinuz        |
+ *                             +-----------------------+
+ *                             |                       |
+ * BOOT_RELOC_ADDR             +-----------------------+
+ *                             |                       |
+ * KERNEL_DECOMPRESS_ADDR      +-----------------------+
+ *                             |       vmlinux         |
+ *                             +-----------------------+
+ *
+ * 3. relocate copy & jump code
+ *
+ * CONFIG_MEMORY_START         +-----------------------+
+ *                             |        vmlinuz        |
+ *                             +-----------------------+
+ *                             |                       |
+ * BOOT_RELOC_ADDR             +-----------------------+
+ *                             |    boot(copy&jump)    |
+ * KERNEL_DECOMPRESS_ADDR      +-----------------------+
+ *                             |       vmlinux         |
+ *                             +-----------------------+
+ *
+ * 4. relocate decompressed kernel
+ *
+ * CONFIG_MEMORY_START         +-----------------------+
+ *                             |        vmlinux        |
+ *                             +-----------------------+
+ *                             |                       |
+ * BOOT_RELOC_ADDR             +-----------------------+
+ *                             |     boot(copy&jump)   |
+ * KERNEL_DECOMPRESS_ADDR      +-----------------------+
+ *                             |                       |
+ *                             +-----------------------+
+ *
+ */
+#ifdef __ASSEMBLY__
+#define __val(x)       x
+#else
+#define __val(x)       (x)
+#endif
+
+#define DECOMPRESS_OFFSET_BASE __val(0x00900000)
+#define BOOT_RELOC_SIZE                __val(0x00001000)
+
+#define KERNEL_EXEC_ADDR       __val(CONFIG_MEMORY_START)
+#define KERNEL_DECOMPRESS_ADDR __val(CONFIG_MEMORY_START + \
+                                     DECOMPRESS_OFFSET_BASE + BOOT_RELOC_SIZE)
+#define KERNEL_ENTRY           __val(CONFIG_MEMORY_START + 0x1000)
+
+#define BOOT_EXEC_ADDR         __val(CONFIG_MEMORY_START)
+#define BOOT_RELOC_ADDR                __val(CONFIG_MEMORY_START + DECOMPRESS_OFFSET_BASE)
diff --git a/arch/m32r/boot/compressed/head.S b/arch/m32r/boot/compressed/head.S
new file mode 100644 (file)
index 0000000..28de481
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ *  linux/arch/m32r/boot/compressed/head.S
+ *
+ *  Copyright (c) 2001-2003    Hiroyuki Kondo, Hirokazu Takata,
+ *                             Hitoshi Yamamoto, Takeo Takahashi
+ *  Copyright (c) 2004         Hirokazu Takata
+ */
+
+       .text
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/assembler.h>
+
+       .global startup
+       __ALIGN
+startup:
+       ldi     r0, #0x0000                     /* SPI, disable EI */
+       mvtc    r0, psw
+
+/*
+ * Clear BSS first so that there are no surprises...
+ */
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+       LDIMM   (r2, __bss_start)
+       LDIMM   (r3, _end)
+       sub     r3, r2          ; BSS size in bytes
+       ; R4 = BSS size in longwords (rounded down)
+       mv      r4, r3              ||  ldi     r1, #0
+       srli    r4, #4              ||  addi    r2, #-4
+       beqz    r4, .Lendloop1
+.Lloop1:
+#ifndef CONFIG_CHIP_M32310
+       ; Touch memory for the no-write-allocating cache.
+       ld      r0, @(4,r2)
+#endif
+       st      r1, @+r2            ||  addi    r4, #-1
+       st      r1, @+r2
+       st      r1, @+r2
+       st      r1, @+r2            ||  cmpeq   r1, r4  ; R4 = 0?
+       bnc     .Lloop1
+.Lendloop1:
+       and3    r4, r3, #15
+       addi    r2, #4
+       beqz    r4, .Lendloop2
+.Lloop2:
+       stb     r1, @r2             ||  addi    r4, #-1
+       addi    r2, #1
+       bnez    r4, .Lloop2
+.Lendloop2:
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+       LDIMM   (r2, __bss_start)
+       LDIMM   (r3, _end)
+       sub     r3, r2          ; BSS size in bytes
+       mv      r4, r3
+       srli    r4, #2          ; R4 = BSS size in longwords (rounded down)
+       ldi     r1, #0          ; clear R1 for longwords store
+       addi    r2, #-4         ; account for pre-inc store
+       beqz    r4, .Lendloop1  ; any more to go?
+.Lloop1:
+       st      r1, @+r2        ; yep, zero out another longword
+       addi    r4, #-1         ; decrement count
+       bnez    r4, .Lloop1     ; go do some more
+.Lendloop1:
+       and3    r4, r3, #3      ; get no. of remaining BSS bytes to clear
+       addi    r2, #4          ; account for pre-inc store
+       beqz    r4, .Lendloop2  ; any more to go?
+.Lloop2:
+       stb     r1, @r2         ; yep, zero out another byte
+       addi    r2, #1          ; bump address
+       addi    r4, #-1         ; decrement count
+       bnez    r4, .Lloop2     ; go do some more
+.Lendloop2:
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+       seth    r0, #shigh(stack_start)
+       ld      sp, @(r0, low(stack_start))     /* set stack point */
+
+/*
+ * decompress the kernel
+ */
+       bl      decompress_kernel
+
+#if defined(CONFIG_CHIP_M32700)
+       /* Cache flush */
+       ldi     r0, -1
+       ldi     r1, 0xd0        ; invalidate i-cache, copy back d-cache
+       stb     r1, @r0
+#else
+#error "put your cache flush function, please"
+#endif
+        seth   r0, #high(CONFIG_MEMORY_START)
+        or3    r0, r0, #0x2000
+        jmp    r0
+
+       .balign 512
+fake_headers_as_bzImage:
+       .short  0
+       .ascii  "HdrS"
+       .short  0x0202
+       .short  0
+       .short  0
+       .byte   0x00, 0x10
+       .short  0
+       .byte   0
+       .byte   1
+       .byte   0x00, 0x80
+       .long   0
+       .long   0
+
diff --git a/arch/m32r/boot/compressed/install.sh b/arch/m32r/boot/compressed/install.sh
new file mode 100644 (file)
index 0000000..6d72e9e
--- /dev/null
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# arch/sh/boot/install.sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+# Adapted from code in arch/i386/boot/install.sh by Russell King
+# Adapted from code in arch/arm/boot/install.sh by Stuart Menefy
+# Adapted from code in arch/sh/boot/install.sh by Takeo Takahashi
+#
+# "make install" script for sh architecture
+#
+# Arguments:
+#   $1 - kernel version
+#   $2 - kernel image file
+#   $3 - kernel map file
+#   $4 - default install path (blank if root directory)
+#
+
+# User may have a custom install script
+
+if [ -x /sbin/installkernel ]; then
+  exec /sbin/installkernel "$@"
+fi
+
+if [ "$2" = "zImage" ]; then
+# Compressed install
+  echo "Installing compressed kernel"
+  if [ -f $4/vmlinuz-$1 ]; then
+    mv $4/vmlinuz-$1 $4/vmlinuz.old
+  fi
+
+  if [ -f $4/System.map-$1 ]; then
+    mv $4/System.map-$1 $4/System.old
+  fi
+
+  cat $2 > $4/vmlinuz-$1
+  cp $3 $4/System.map-$1
+else
+# Normal install
+  echo "Installing normal kernel"
+  if [ -f $4/vmlinux-$1 ]; then
+    mv $4/vmlinux-$1 $4/vmlinux.old
+  fi
+
+  if [ -f $4/System.map ]; then
+    mv $4/System.map $4/System.old
+  fi
+
+  cat $2 > $4/vmlinux-$1
+  cp $3 $4/System.map
+fi
diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c
new file mode 100644 (file)
index 0000000..469c4dc
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * arch/m32r/boot/compressed/m32r_sio.c
+ *
+ * 2003-02-12: Takeo Takahashi
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+void putc(char c);
+
+int puts(const char *s)
+{
+       char c;
+       while ((c = *s++)) putc(c);
+       return 0;
+}
+
+#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT)
+#define USE_FPGA_MAP   0
+
+#if USE_FPGA_MAP
+/*
+ * fpga configuration program uses MMU, and define map as same as
+ * M32104 uT-Engine board.
+ */
+#define BOOT_SIO0STS   (volatile unsigned short *)(0x02c00000 + 0x20006)
+#define BOOT_SIO0TXB   (volatile unsigned short *)(0x02c00000 + 0x2000c)
+#else
+#undef PLD_BASE
+#define PLD_BASE       0xa4c00000
+#define BOOT_SIO0STS   PLD_ESIO0STS
+#define BOOT_SIO0TXB   PLD_ESIO0TXB
+#endif
+
+void putc(char c)
+{
+
+       while ((*BOOT_SIO0STS & 0x3) != 0x3) ;
+       if (c == '\n') {
+               *BOOT_SIO0TXB = '\r';
+               while ((*BOOT_SIO0STS & 0x3) != 0x3) ;
+       }
+       *BOOT_SIO0TXB = c;
+}
+#else
+void putc(char c)
+{
+       /* do nothing */
+}
+#endif
diff --git a/arch/m32r/boot/compressed/misc.c b/arch/m32r/boot/compressed/misc.c
new file mode 100644 (file)
index 0000000..4661d38
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * arch/m32r/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 SH by Stuart Menefy, Aug 1999
+ *
+ * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
+ *
+ * 2003-02-12: Support M32R by Takeo Takahashi
+ *             This is based on arch/sh/boot/compressed/misc.c.
+ */
+
+#include <linux/config.h>
+#include <linux/string.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;  /* 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 */
+#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;
+static uch *output_data;
+static unsigned long output_ptr;
+
+
+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 **);
+
+extern 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"
+
+static void *malloc(int size)
+{
+       void *p;
+
+       if (size <0) error("Malloc error\n");
+       if (free_mem_ptr == 0) error("Memory error\n");
+
+       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("\nOut of memory\n");
+
+       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;
+}
+
+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\n");
+       }
+
+       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];
+
+/* return decompressed size */
+long decompress_kernel(void)
+{
+       insize = 0;
+       inptr = 0;
+       bytes_out = 0;
+       outcnt = 0;
+       output_data = 0;
+       output_ptr = CONFIG_MEMORY_START + 0x2000;
+       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");
+       return bytes_out;
+}
diff --git a/arch/m32r/boot/compressed/vmlinux.lds.S b/arch/m32r/boot/compressed/vmlinux.lds.S
new file mode 100644 (file)
index 0000000..20a9e94
--- /dev/null
@@ -0,0 +1,23 @@
+#include <linux/config.h>
+
+OUTPUT_ARCH(m32r)
+ENTRY(startup)
+SECTIONS
+{
+  . = CONFIG_MEMORY_START + 0x00400000;
+
+  _text = .;
+  .text : { *(.text) } = 0
+  .rodata : { *(.rodata) }
+  _etext = .;
+
+  . = ALIGN(32) + (. & (32 - 1));
+  .data : { *(.data) }
+  _edata  =  .;
+
+  . = ALIGN(32 / 8);
+  __bss_start = .;
+  .bss : { *(.bss) }
+  . = ALIGN(32 / 8);
+  _end = . ;
+}
diff --git a/arch/m32r/boot/compressed/vmlinux.scr b/arch/m32r/boot/compressed/vmlinux.scr
new file mode 100644 (file)
index 0000000..a084903
--- /dev/null
@@ -0,0 +1,9 @@
+SECTIONS
+{
+  .data : {
+       input_len = .;
+       LONG(input_data_end - input_data) input_data = .;
+       *(.data)
+       input_data_end = .;
+       }
+}
diff --git a/arch/m32r/boot/setup.S b/arch/m32r/boot/setup.S
new file mode 100644 (file)
index 0000000..9be5917
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *  linux/arch/m32r/boot/setup.S -- A setup code.
+ *
+ *  Copyright (C) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *  and Hitoshi Yamamoto
+ *
+ */
+/* $Id$ */
+
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <linux/config.h>
+#include <asm/assembler.h>
+#include <asm/mmu_context.h>
+#include <asm/m32r.h>
+
+/*
+ * References to members of the boot_cpu_data structure.
+ */
+
+#define CPU_PARAMS     boot_cpu_data
+#define M32R_MCICAR     0xfffffff0
+#define M32R_MCDCAR     0xfffffff4
+#define        M32R_MCCR        0xfffffffc
+#define M32R_BSCR0      0xffffffd2
+
+;BSEL
+#define BSEL0CR0        0x00ef5000
+#define        BSEL0CR1         0x00ef5004
+#define BSEL1CR0        0x00ef5100
+#define BSEL1CR1        0x00ef5104
+#define BSEL0CR0_VAL    0x00000000
+#define BSEL0CR1_VAL    0x01200100
+#define BSEL1CR0_VAL    0x01018000
+#define BSEL1CR1_VAL    0x00200001
+
+;SDRAMC
+#define SDRAMC_SDRF0    0x00ef6000
+#define SDRAMC_SDRF1    0x00ef6004
+#define SDRAMC_SDIR0    0x00ef6008
+#define SDRAMC_SDIR1    0x00ef600c
+#define SDRAMC_SD0ADR   0x00ef6020
+#define SDRAMC_SD0ER    0x00ef6024
+#define SDRAMC_SD0TR    0x00ef6028
+#define SDRAMC_SD0MOD   0x00ef602c
+#define SDRAMC_SD1ADR   0x00ef6040
+#define SDRAMC_SD1ER    0x00ef6044
+#define SDRAMC_SD1TR    0x00ef6048
+#define SDRAMC_SD1MOD   0x00ef604c
+#define SDRAM0          0x18000000
+#define SDRAM1          0x1c000000
+
+/*------------------------------------------------------------------------
+ * start up
+ */
+
+/*------------------------------------------------------------------------
+ * Kernel entry
+ */
+       .section .boot, "ax"
+ENTRY(boot)
+
+/* Set cache mode */
+#if defined(CONFIG_CHIP_XNUX2)
+       ldi     r0, #-2              ;LDIMM     (r0, M32R_MCCR)
+       ldi     r1, #0x0101             ; cache on (with invalidation)
+;      ldi     r1, #0x00               ; cache off
+       sth     r1, @r0
+#elif defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_VDEC2) \
+    || defined(CONFIG_CHIP_OPSP)
+       ldi     r0, #-4              ;LDIMM     (r0, M32R_MCCR)
+       ldi     r1, #0x73               ; cache on (with invalidation)
+;      ldi     r1, #0x00               ; cache off
+       st      r1, @r0
+#else
+#error unknown chip configuration
+#endif
+
+#ifdef CONFIG_SMP
+       ;; if not BSP (CPU#0) goto AP_loop
+       seth    r5, #shigh(M32R_CPUID_PORTL)
+       ld      r5, @(low(M32R_CPUID_PORTL), r5)
+       bnez    r5, AP_loop
+#if !defined(CONFIG_PLAT_USRV)
+       ;; boot AP
+       ld24    r5, #0xeff2f8           ; IPICR7
+       ldi     r6, #0x2                ; IPI to CPU1
+       st      r6, @r5
+#endif
+#endif
+
+/*
+ *  Now, Jump to stext
+ *        if with MMU,    TLB on.
+ *        if with no MMU, only jump.
+ */
+       .global eit_vector
+mmu_on:
+       LDIMM   (r13, stext)
+#ifdef CONFIG_MMU
+       bl      init_tlb
+       LDIMM   (r2, eit_vector)                ; set EVB(cr5)
+       mvtc    r2, cr5
+       seth    r0, #high(MMU_REG_BASE)         ; Set MMU_REG_BASE higher
+       or3     r0, r0, #low(MMU_REG_BASE)      ; Set MMU_REG_BASE lower
+       ldi     r1, #0x01
+       st      r1, @(MATM_offset,r0)           ; Set MATM (T bit ON)
+       ld      r0, @(MATM_offset,r0)           ; Check
+#else
+       seth    r0,#high(M32R_MCDCAR)
+       or3     r0,r0,#low(M32R_MCDCAR)
+       ld24    r1,#0x8080
+       st      r1,@r0
+#endif /* CONFIG_MMU */
+       jmp     r13
+       nop
+       nop
+
+#ifdef CONFIG_SMP
+/*
+ * AP wait loop
+ */
+ENTRY(AP_loop)
+       ;; disable interrupt
+       clrpsw  #0x40
+       ;; reset EVB
+       LDIMM   (r4, _AP_RE)
+       seth    r5, #high(__PAGE_OFFSET)
+       or3     r5, r5, #low(__PAGE_OFFSET)
+       not     r5, r5
+       and     r4, r5
+       mvtc    r4, cr5
+       ;; disable maskable interrupt
+       seth    r4, #high(M32R_ICU_IMASK_PORTL)
+       or3     r4, r4, #low(M32R_ICU_IMASK_PORTL)
+       ldi     r5, #0
+       st      r5, @r4
+       ld      r5, @r4
+       ;; enable only IPI
+       setpsw  #0x40
+       ;; LOOOOOOOOOOOOOOP!!!
+       .fillinsn
+2:
+       nop
+       nop
+       bra     2b
+       nop
+       nop
+
+#ifdef CONFIG_CHIP_M32700_TS1
+       .global dcache_dummy
+       .balign 16, 0
+dcache_dummy:
+       .byte   16
+#endif /* CONFIG_CHIP_M32700_TS1 */
+#endif /* CONFIG_SMP */
+
+       .end
+
diff --git a/arch/m32r/defconfig b/arch/m32r/defconfig
new file mode 100644 (file)
index 0000000..984701b
--- /dev/null
@@ -0,0 +1,635 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+# CONFIG_IKCONFIG_PROC is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+CONFIG_PLAT_M32700UT=y
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=50000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+# CONFIG_M32RPCC is not set
+CONFIG_M32R_CFC=y
+CONFIG_M32700UT_CFC=y
+CONFIG_CFC_NUM=1
+# CONFIG_MTD_M32R is not set
+CONFIG_M32R_SMC91111=y
+CONFIG_M32700UT_DS1302=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+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 is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG 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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_NETDEVICES is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 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
+
+#
+# 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_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_M32R_SIO is not set
+CONFIG_SERIAL_M32R_PLDSIO=y
+CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_CPIA is not set
+CONFIG_M32R_AR=y
+CONFIG_M32R_AR_VGA=y
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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 is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile
new file mode 100644 (file)
index 0000000..cfd690b
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Makefile for the Linux/M32R kernel.
+#
+
+extra-y        := head.o init_task.o vmlinux.lds
+
+obj-y  := process.o entry.o traps.o align.o irq.o setup.o time.o \
+       m32r_ksyms.o sys_m32r.o semaphore.o signal.o ptrace.o
+
+obj-$(CONFIG_SMP)              += smp.o smpboot.o
+obj-$(CONFIG_PLAT_MAPPI)       += setup_mappi.o io_mappi.o
+obj-$(CONFIG_PLAT_MAPPI2)      += setup_mappi2.o io_mappi2.o
+obj-$(CONFIG_PLAT_USRV)                += setup_usrv.o io_usrv.o
+obj-$(CONFIG_PLAT_M32700UT)    += setup_m32700ut.o io_m32700ut.o
+obj-$(CONFIG_PLAT_OPSPUT)      += setup_opsput.o io_opsput.o
+obj-$(CONFIG_MODULES)          += module.o
+obj-$(CONFIG_PLAT_OAKS32R)     += setup_oaks32r.o io_oaks32r.o
+
+EXTRA_AFLAGS   := -traditional
+
diff --git a/arch/m32r/kernel/align.c b/arch/m32r/kernel/align.c
new file mode 100644 (file)
index 0000000..48ec297
--- /dev/null
@@ -0,0 +1,585 @@
+/*
+ * align.c - address exception handler for M32R
+ *
+ * Copyright (c) 2003 Hitoshi Yamamoto
+ */
+
+#include <linux/config.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+static int get_reg(struct pt_regs *regs, int nr)
+{
+       int val;
+
+       if (nr < 4)
+               val = *(unsigned long *)(&regs->r0 + nr);
+       else if (nr < 7)
+               val = *(unsigned long *)(&regs->r4 + (nr - 4));
+       else if (nr < 13)
+               val = *(unsigned long *)(&regs->r7 + (nr - 7));
+       else
+               val = *(unsigned long *)(&regs->fp + (nr - 13));
+
+       return val;
+}
+
+static void set_reg(struct pt_regs *regs, int nr, int val)
+{
+       if (nr < 4)
+               *(unsigned long *)(&regs->r0 + nr) = val;
+       else if (nr < 7)
+               *(unsigned long *)(&regs->r4 + (nr - 4)) = val;
+       else if (nr < 13)
+               *(unsigned long *)(&regs->r7 + (nr - 7)) = val;
+       else
+               *(unsigned long *)(&regs->fp + (nr - 13)) = val;
+}
+
+#define REG1(insn)     (((insn) & 0x0f00) >> 8)
+#define REG2(insn)     ((insn) & 0x000f)
+#define PSW_BC         0x100
+
+/* O- instruction */
+#define ISA_LD1                0x20c0  /* ld Rdest, @Rsrc */
+#define ISA_LD2                0x20e0  /* ld Rdest, @Rsrc+ */
+#define ISA_LDH                0x20a0  /* ldh Rdest, @Rsrc */
+#define ISA_LDUH       0x20b0  /* lduh Rdest, @Rsrc */
+#define ISA_ST1                0x2040  /* st Rsrc1, @Rsrc2 */
+#define ISA_ST2                0x2060  /* st Rsrc1, @+Rsrc2 */
+#define ISA_ST3                0x2070  /* st Rsrc1, @-Rsrc2 */
+#define ISA_STH1       0x2020  /* sth Rsrc1, @Rsrc2 */
+#define ISA_STH2       0x2030  /* sth Rsrc1, @Rsrc2+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+/* OS instruction */
+#define ISA_ADD                0x00a0  /* add Rdest, Rsrc */
+#define ISA_ADDI       0x4000  /* addi Rdest, #imm8 */
+#define ISA_ADDX       0x0090  /* addx Rdest, Rsrc */
+#define ISA_AND                0x00c0  /* and Rdest, Rsrc */
+#define ISA_CMP                0x0040  /* cmp Rsrc1, Rsrc2 */
+#define ISA_CMPEQ      0x0060  /* cmpeq Rsrc1, Rsrc2 */
+#define ISA_CMPU       0x0050  /* cmpu Rsrc1, Rsrc2 */
+#define ISA_CMPZ       0x0070  /* cmpz Rsrc */
+#define ISA_LDI                0x6000  /* ldi Rdest, #imm8 */
+#define ISA_MV         0x1080  /* mv Rdest, Rsrc */
+#define ISA_NEG                0x0030  /* neg Rdest, Rsrc */
+#define ISA_NOP                0x7000  /* nop */
+#define ISA_NOT                0x00b0  /* not Rdest, Rsrc */
+#define ISA_OR         0x00e0  /* or Rdest, Rsrc */
+#define ISA_SUB                0x0020  /* sub Rdest, Rsrc */
+#define ISA_SUBX       0x0010  /* subx Rdest, Rsrc */
+#define ISA_XOR                0x00d0  /* xor Rdest, Rsrc */
+
+/* -S instruction */
+#define ISA_MUL                0x1060  /* mul Rdest, Rsrc */
+#define ISA_MULLO_A0   0x3010  /* mullo Rsrc1, Rsrc2, A0 */
+#define ISA_MULLO_A1   0x3090  /* mullo Rsrc1, Rsrc2, A1 */
+#define ISA_MVFACMI_A0 0x50f2  /* mvfacmi Rdest, A0 */
+#define ISA_MVFACMI_A1 0x50f6  /* mvfacmi Rdest, A1 */
+
+static int emu_addi(unsigned short insn, struct pt_regs *regs)
+{
+       char imm = (char)(insn & 0xff);
+       int dest = REG1(insn);
+       int val;
+
+       val = get_reg(regs, dest);
+       val += imm;
+       set_reg(regs, dest, val);
+
+       return 0;
+}
+
+static int emu_ldi(unsigned short insn, struct pt_regs *regs)
+{
+       char imm = (char)(insn & 0xff);
+
+       set_reg(regs, REG1(insn), (int)imm);
+
+       return 0;
+}
+
+static int emu_add(unsigned short insn, struct pt_regs *regs)
+{
+       int dest = REG1(insn);
+       int src = REG2(insn);
+       int val;
+
+       val = get_reg(regs, dest);
+       val += get_reg(regs, src);
+       set_reg(regs, dest, val);
+
+       return 0;
+}
+
+static int emu_addx(unsigned short insn, struct pt_regs *regs)
+{
+       int dest = REG1(insn);
+       unsigned int val, tmp;
+
+       val = regs->psw & PSW_BC ? 1 : 0;
+       tmp = get_reg(regs, dest);
+       val += tmp;
+       val += (unsigned int)get_reg(regs, REG2(insn));
+       set_reg(regs, dest, val);
+
+       /* C bit set */
+       if (val < tmp)
+               regs->psw |= PSW_BC;
+       else
+               regs->psw &= ~(PSW_BC);
+
+       return 0;
+}
+
+static int emu_and(unsigned short insn, struct pt_regs *regs)
+{
+       int dest = REG1(insn);
+       int val;
+
+       val = get_reg(regs, dest);
+       val &= get_reg(regs, REG2(insn));
+       set_reg(regs, dest, val);
+
+       return 0;
+}
+
+static int emu_cmp(unsigned short insn, struct pt_regs *regs)
+{
+       if (get_reg(regs, REG1(insn)) < get_reg(regs, REG2(insn)))
+               regs->psw |= PSW_BC;
+       else
+               regs->psw &= ~(PSW_BC);
+
+       return 0;
+}
+
+static int emu_cmpeq(unsigned short insn, struct pt_regs *regs)
+{
+       if (get_reg(regs, REG1(insn)) == get_reg(regs, REG2(insn)))
+               regs->psw |= PSW_BC;
+       else
+               regs->psw &= ~(PSW_BC);
+
+       return 0;
+}
+
+static int emu_cmpu(unsigned short insn, struct pt_regs *regs)
+{
+       if ((unsigned int)get_reg(regs, REG1(insn))
+               < (unsigned int)get_reg(regs, REG2(insn)))
+               regs->psw |= PSW_BC;
+       else
+               regs->psw &= ~(PSW_BC);
+
+       return 0;
+}
+
+static int emu_cmpz(unsigned short insn, struct pt_regs *regs)
+{
+       if (!get_reg(regs, REG2(insn)))
+               regs->psw |= PSW_BC;
+       else
+               regs->psw &= ~(PSW_BC);
+
+       return 0;
+}
+
+static int emu_mv(unsigned short insn, struct pt_regs *regs)
+{
+       int val;
+
+       val = get_reg(regs, REG2(insn));
+       set_reg(regs, REG1(insn), val);
+
+       return 0;
+}
+
+static int emu_neg(unsigned short insn, struct pt_regs *regs)
+{
+       int val;
+
+       val = get_reg(regs, REG2(insn));
+       set_reg(regs, REG1(insn), 0 - val);
+
+       return 0;
+}
+
+static int emu_not(unsigned short insn, struct pt_regs *regs)
+{
+       int val;
+
+       val = get_reg(regs, REG2(insn));
+       set_reg(regs, REG1(insn), ~val);
+
+       return 0;
+}
+
+static int emu_or(unsigned short insn, struct pt_regs *regs)
+{
+       int dest = REG1(insn);
+       int val;
+
+       val = get_reg(regs, dest);
+       val |= get_reg(regs, REG2(insn));
+       set_reg(regs, dest, val);
+
+       return 0;
+}
+
+static int emu_sub(unsigned short insn, struct pt_regs *regs)
+{
+       int dest = REG1(insn);
+       int val;
+
+       val = get_reg(regs, dest);
+       val -= get_reg(regs, REG2(insn));
+       set_reg(regs, dest, val);
+
+       return 0;
+}
+
+static int emu_subx(unsigned short insn, struct pt_regs *regs)
+{
+       int dest = REG1(insn);
+       unsigned int val, tmp;
+
+       val = tmp = get_reg(regs, dest);
+       val -= (unsigned int)get_reg(regs, REG2(insn));
+       val -= regs->psw & PSW_BC ? 1 : 0;
+       set_reg(regs, dest, val);
+
+       /* C bit set */
+       if (val > tmp)
+               regs->psw |= PSW_BC;
+       else
+               regs->psw &= ~(PSW_BC);
+
+       return 0;
+}
+
+static int emu_xor(unsigned short insn, struct pt_regs *regs)
+{
+       int dest = REG1(insn);
+       unsigned int val;
+
+       val = (unsigned int)get_reg(regs, dest);
+       val ^= (unsigned int)get_reg(regs, REG2(insn));
+       set_reg(regs, dest, val);
+
+       return 0;
+}
+
+static int emu_mul(unsigned short insn, struct pt_regs *regs)
+{
+       int dest = REG1(insn);
+       int reg1, reg2;
+
+       reg1 = get_reg(regs, dest);
+       reg2 = get_reg(regs, REG2(insn));
+
+       __asm__ __volatile__ (
+               "mul    %0, %1;         \n\t"
+               : "+r" (reg1) : "r" (reg2)
+       );
+
+       set_reg(regs, dest, reg1);
+
+       return 0;
+}
+
+static int emu_mullo_a0(unsigned short insn, struct pt_regs *regs)
+{
+       int reg1, reg2;
+
+       reg1 = get_reg(regs, REG1(insn));
+       reg2 = get_reg(regs, REG2(insn));
+
+       __asm__ __volatile__ (
+               "mullo          %0, %1, a0;     \n\t"
+               "mvfachi        %0, a0;         \n\t"
+               "mvfaclo        %1, a0;         \n\t"
+               : "+r" (reg1), "+r" (reg2)
+       );
+
+       regs->acc0h = reg1;
+       regs->acc0l = reg2;
+
+       return 0;
+}
+
+static int emu_mullo_a1(unsigned short insn, struct pt_regs *regs)
+{
+       int reg1, reg2;
+
+       reg1 = get_reg(regs, REG1(insn));
+       reg2 = get_reg(regs, REG2(insn));
+
+       __asm__ __volatile__ (
+               "mullo          %0, %1, a0;     \n\t"
+               "mvfachi        %0, a0;         \n\t"
+               "mvfaclo        %1, a0;         \n\t"
+               : "+r" (reg1), "+r" (reg2)
+       );
+
+       regs->acc1h = reg1;
+       regs->acc1l = reg2;
+
+       return 0;
+}
+
+static int emu_mvfacmi_a0(unsigned short insn, struct pt_regs *regs)
+{
+       unsigned long val;
+
+       val = (regs->acc0h << 16) | (regs->acc0l >> 16);
+       set_reg(regs, REG1(insn), (int)val);
+
+       return 0;
+}
+
+static int emu_mvfacmi_a1(unsigned short insn, struct pt_regs *regs)
+{
+       unsigned long val;
+
+       val = (regs->acc1h << 16) | (regs->acc1l >> 16);
+       set_reg(regs, REG1(insn), (int)val);
+
+       return 0;
+}
+
+static int emu_m32r2(unsigned short insn, struct pt_regs *regs)
+{
+       int res = -1;
+
+       if ((insn & 0x7fff) == ISA_NOP) /* nop */
+               return 0;
+
+       switch(insn & 0x7000) {
+       case ISA_ADDI:          /* addi Rdest, #imm8 */
+               res = emu_addi(insn, regs);
+               break;
+       case ISA_LDI:           /* ldi Rdest, #imm8 */
+               res = emu_ldi(insn, regs);
+               break;
+       default:
+               break;
+       }
+
+       if (!res)
+               return 0;
+
+       switch(insn & 0x70f0) {
+       case ISA_ADD:           /* add Rdest, Rsrc */
+               res = emu_add(insn, regs);
+               break;
+       case ISA_ADDX:          /* addx Rdest, Rsrc */
+               res = emu_addx(insn, regs);
+               break;
+       case ISA_AND:           /* and Rdest, Rsrc */
+               res = emu_and(insn, regs);
+               break;
+       case ISA_CMP:           /* cmp Rsrc1, Rsrc2 */
+               res = emu_cmp(insn, regs);
+               break;
+       case ISA_CMPEQ:         /* cmpeq Rsrc1, Rsrc2 */
+               res = emu_cmpeq(insn, regs);
+               break;
+       case ISA_CMPU:          /* cmpu Rsrc1, Rsrc2 */
+               res = emu_cmpu(insn, regs);
+               break;
+       case ISA_CMPZ:          /* cmpz Rsrc */
+               res = emu_cmpz(insn, regs);
+               break;
+       case ISA_MV:            /* mv Rdest, Rsrc */
+               res = emu_mv(insn, regs);
+               break;
+       case ISA_NEG:           /* neg Rdest, Rsrc */
+               res = emu_neg(insn, regs);
+               break;
+       case ISA_NOT:           /* not Rdest, Rsrc */
+               res = emu_not(insn, regs);
+               break;
+       case ISA_OR:            /* or Rdest, Rsrc */
+               res = emu_or(insn, regs);
+               break;
+       case ISA_SUB:           /* sub Rdest, Rsrc */
+               res = emu_sub(insn, regs);
+               break;
+       case ISA_SUBX:          /* subx Rdest, Rsrc */
+               res = emu_subx(insn, regs);
+               break;
+       case ISA_XOR:           /* xor Rdest, Rsrc */
+               res = emu_xor(insn, regs);
+               break;
+       case ISA_MUL:           /* mul Rdest, Rsrc */
+               res = emu_mul(insn, regs);
+               break;
+       case ISA_MULLO_A0:      /* mullo Rsrc1, Rsrc2 */
+               res = emu_mullo_a0(insn, regs);
+               break;
+       case ISA_MULLO_A1:      /* mullo Rsrc1, Rsrc2 */
+               res = emu_mullo_a1(insn, regs);
+               break;
+       default:
+               break;
+       }
+
+       if (!res)
+               return 0;
+
+       switch(insn & 0x70ff) {
+       case ISA_MVFACMI_A0:    /* mvfacmi Rdest */
+               res = emu_mvfacmi_a0(insn, regs);
+               break;
+       case ISA_MVFACMI_A1:    /* mvfacmi Rdest */
+               res = emu_mvfacmi_a1(insn, regs);
+               break;
+       default:
+               break;
+       }
+
+       return res;
+}
+
+#endif /* CONFIG_ISA_DUAL_ISSUE */
+
+/*
+ * ld   : ?010 dest 1100 src
+ *        0010 dest 1110 src : ld Rdest, @Rsrc+
+ * ldh  : ?010 dest 1010 src
+ * lduh : ?010 dest 1011 src
+ * st   : ?010 src1 0100 src2
+ *        0010 src1 0110 src2 : st Rsrc1, @+Rsrc2
+ *        0010 src1 0111 src2 : st Rsrc1, @-Rsrc2
+ * sth  : ?010 src1 0010 src2
+ */
+
+static int insn_check(unsigned long insn, struct pt_regs *regs,
+       unsigned char **ucp)
+{
+       int res = 0;
+
+       /*
+        * 32bit insn
+        *  ld Rdest, @(disp16, Rsrc)
+        *  st Rdest, @(disp16, Rsrc)
+        */
+       if (insn & 0x80000000) {        /* 32bit insn */
+               *ucp += (short)(insn & 0x0000ffff);
+               regs->bpc += 4;
+       } else {                        /* 16bit insn */
+#ifdef CONFIG_ISA_DUAL_ISSUE
+               /* parallel exec check */
+               if (!(regs->bpc & 0x2) && insn & 0x8000) {
+                       res = emu_m32r2((unsigned short)insn, regs);
+                       regs->bpc += 4;
+               } else
+#endif /* CONFIG_ISA_DUAL_ISSUE */
+                       regs->bpc += 2;
+       }
+
+       return res;
+}
+
+static int emu_ld(unsigned long insn32, struct pt_regs *regs)
+{
+       unsigned char *ucp;
+       unsigned long val;
+       unsigned short insn16;
+       int size, src;
+
+       insn16 = insn32 >> 16;
+       src = REG2(insn16);
+       ucp = (unsigned char *)get_reg(regs, src);
+
+       if (insn_check(insn32, regs, &ucp))
+               return -1;
+
+       size = insn16 & 0x0040 ? 4 : 2;
+       if (copy_from_user(&val, ucp, size))
+               return -1;
+
+       if (size == 2)
+               val >>= 16;
+
+       /* ldh sign check */
+       if ((insn16 & 0x00f0) == 0x00a0 && (val & 0x8000))
+               val |= 0xffff0000;
+
+       set_reg(regs, REG1(insn16), val);
+
+       /* ld increment check */
+       if ((insn16 & 0xf0f0) == ISA_LD2)       /* ld Rdest, @Rsrc+ */
+               set_reg(regs, src, (unsigned long)(ucp + 4));
+
+       return 0;
+}
+
+static int emu_st(unsigned long insn32, struct pt_regs *regs)
+{
+       unsigned char *ucp;
+       unsigned long val;
+       unsigned short insn16;
+       int size, src2;
+
+       insn16 = insn32 >> 16;
+       src2 = REG2(insn16);
+
+       ucp = (unsigned char *)get_reg(regs, src2);
+
+       if (insn_check(insn32, regs, &ucp))
+               return -1;
+
+       size = insn16 & 0x0040 ? 4 : 2;
+       val = get_reg(regs, REG1(insn16));
+       if (size == 2)
+               val <<= 16;
+
+       /* st inc/dec check */
+       if ((insn16 & 0xf0e0) == 0x2060) {
+               if (insn16 & 0x0010)
+                       ucp -= 4;
+               else
+                       ucp += 4;
+
+               set_reg(regs, src2, (unsigned long)ucp);
+       }
+
+       if (copy_to_user(ucp, &val, size))
+               return -1;
+
+       /* sth inc check */
+       if ((insn16 & 0xf0f0) == ISA_STH2) {
+               ucp += 2;
+               set_reg(regs, src2, (unsigned long)ucp);
+       }
+
+       return 0;
+}
+
+int handle_unaligned_access(unsigned long insn32, struct pt_regs *regs)
+{
+       unsigned short insn16;
+       int res;
+
+       insn16 = insn32 >> 16;
+
+       /* ld or st check */
+       if ((insn16 & 0x7000) != 0x2000)
+               return -1;
+
+       /* insn alignment check */
+       if ((insn16 & 0x8000) && (regs->bpc & 3))
+               return -1;
+
+       if (insn16 & 0x0080)    /* ld */
+               res = emu_ld(insn32, regs);
+       else                    /* st */
+               res = emu_st(insn32, regs);
+
+       return res;
+}
+
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
new file mode 100644 (file)
index 0000000..29b0d8d
--- /dev/null
@@ -0,0 +1,999 @@
+/*
+ *  linux/arch/m32r/kernel/entry.S
+ *
+ *  Copyright (c) 2001, 2002  Hirokazu Takata, Hitoshi Yamamoto, H. Kondo
+ *  Copyright (c) 2003  Hitoshi Yamamoto
+ *  Copyright (c) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ *
+ *  Taken from i386 version.
+ *    Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ * entry.S 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.
+ *
+ * NOTE: This code handles signal-recognition, which happens every time
+ * after a timer-interrupt and after each system call.
+ *
+ * Stack layout in 'ret_from_system_call':
+ *     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,
+ *     ptrace.c and ptrace.h
+ *
+ * M32Rx/M32R2                         M32R
+ *       @(sp)      - r4               ditto
+ *       @(0x04,sp) - r5               ditto
+ *       @(0x08,sp) - r6               ditto
+ *       @(0x0c,sp) - *pt_regs         ditto
+ *       @(0x10,sp) - r0               ditto
+ *       @(0x14,sp) - r1               ditto
+ *       @(0x18,sp) - r2               ditto
+ *       @(0x1c,sp) - r3               ditto
+ *       @(0x20,sp) - r7               ditto
+ *       @(0x24,sp) - r8               ditto
+ *       @(0x28,sp) - r9               ditto
+ *       @(0x2c,sp) - r10              ditto
+ *       @(0x30,sp) - r11              ditto
+ *       @(0x34,sp) - r12              ditto
+ *       @(0x38,sp) - syscall_nr       ditto
+ *       @(0x3c,sp) - acc0h            @(0x3c,sp) - acch
+ *       @(0x40,sp) - acc0l            @(0x40,sp) - accl
+ *       @(0x44,sp) - acc1h            @(0x44,sp) - psw
+ *       @(0x48,sp) - acc1l            @(0x48,sp) - bpc
+ *       @(0x4c,sp) - psw              @(0x4c,sp) - bbpsw
+ *       @(0x50,sp) - bpc              @(0x50,sp) - bbpc
+ *       @(0x54,sp) - bbpsw            @(0x54,sp) - spu (cr3)
+ *       @(0x58,sp) - bbpc             @(0x58,sp) - fp (r13)
+ *       @(0x5c,sp) - spu (cr3)                @(0x5c,sp) - lr (r14)
+ *       @(0x60,sp) - fp (r13)         @(0x60,sp) - spi (cr12)
+ *       @(0x64,sp) - lr (r14)         @(0x64,sp) - orig_r0
+ *       @(0x68,sp) - spi (cr2)
+ *       @(0x6c,sp) - orig_r0
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/irq.h>
+#include <asm/unistd.h>
+#include <asm/assembler.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <asm/segment.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/m32r.h>
+#include <asm/mmu_context.h>
+
+#if !defined(CONFIG_MMU)
+#define sys_madvise             sys_ni_syscall
+#define sys_readahead           sys_ni_syscall
+#define sys_mprotect            sys_ni_syscall
+#define sys_msync               sys_ni_syscall
+#define sys_mlock               sys_ni_syscall
+#define sys_munlock             sys_ni_syscall
+#define sys_mlockall            sys_ni_syscall
+#define sys_munlockall          sys_ni_syscall
+#define sys_mremap              sys_ni_syscall
+#define sys_mincore             sys_ni_syscall
+#endif /* CONFIG_MMU */
+
+#define R4(reg)                        @reg
+#define R5(reg)                        @(0x04,reg)
+#define R6(reg)                        @(0x08,reg)
+#define PTREGS(reg)            @(0x0C,reg)
+#define R0(reg)                        @(0x10,reg)
+#define R1(reg)                        @(0x14,reg)
+#define R2(reg)                        @(0x18,reg)
+#define R3(reg)                        @(0x1C,reg)
+#define R7(reg)                        @(0x20,reg)
+#define R8(reg)                        @(0x24,reg)
+#define R9(reg)                        @(0x28,reg)
+#define R10(reg)               @(0x2C,reg)
+#define R11(reg)               @(0x30,reg)
+#define R12(reg)               @(0x34,reg)
+#define SYSCALL_NR(reg)                @(0x38,reg)
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+#define ACC0H(reg)             @(0x3C,reg)
+#define ACC0L(reg)             @(0x40,reg)
+#define ACC1H(reg)             @(0x44,reg)
+#define ACC1L(reg)             @(0x48,reg)
+#define PSW(reg)               @(0x4C,reg)
+#define BPC(reg)               @(0x50,reg)
+#define BBPSW(reg)             @(0x54,reg)
+#define BBPC(reg)              @(0x58,reg)
+#define SPU(reg)               @(0x5C,reg)
+#define FP(reg)                        @(0x60,reg)  /* FP = R13 */
+#define LR(reg)                        @(0x64,reg)
+#define SP(reg)                        @(0x68,reg)
+#define ORIG_R0(reg)           @(0x6C,reg)
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define ACCH(reg)              @(0x3C,reg)
+#define ACCL(reg)              @(0x40,reg)
+#define PSW(reg)               @(0x44,reg)
+#define BPC(reg)               @(0x48,reg)
+#define BBPSW(reg)             @(0x4C,reg)
+#define BBPC(reg)              @(0x50,reg)
+#define SPU(reg)               @(0x54,reg)
+#define FP(reg)                        @(0x58,reg)  /* FP = R13 */
+#define LR(reg)                        @(0x5C,reg)
+#define SP(reg)                        @(0x60,reg)
+#define ORIG_R0(reg)           @(0x64,reg)
+#else
+#error unknown isa configuration
+#endif
+
+CF_MASK                = 0x00000001
+TF_MASK                = 0x00000100
+IF_MASK                = 0x00000200
+DF_MASK                = 0x00000400
+NT_MASK                = 0x00004000
+VM_MASK                = 0x00020000
+
+#ifdef CONFIG_PREEMPT
+#define preempt_stop(x)                CLI(x)
+#else
+#define preempt_stop(x)
+#define resume_kernel          restore_all
+#endif
+
+ENTRY(ret_from_fork)
+       ld      r0, @sp+
+       bl      schedule_tail
+       GET_THREAD_INFO(r8)
+       bra     syscall_exit
+
+/*
+ * Return to user mode is not as complex as all this looks,
+ * but we want the default path for a system call return to
+ * go as quickly as possible which is why some of this is
+ * less clear than it otherwise should be.
+ */
+
+       ; userspace resumption stub bypassing syscall exit tracing
+       ALIGN
+ret_from_exception:
+       preempt_stop(r4)
+ret_from_intr:
+       ld      r4, PSW(sp)
+#ifdef CONFIG_ISA_M32R2
+       and3    r4, r4, #0x8800         ; check BSM and BPM bits
+#else
+       and3    r4, r4, #0x8000         ; check BSM bit
+#endif
+       beqz    r4, resume_kernel
+ENTRY(resume_userspace)
+       CLI(r4)                         ; make sure we don't miss an interrupt
+                                       ; setting need_resched or sigpending
+                                       ; between sampling and the iret
+       GET_THREAD_INFO(r8)
+       ld      r9, @(TI_FLAGS, r8)
+       and3    r4, r9, #_TIF_WORK_MASK ; is there any work to be done on
+                                       ; int/exception return?
+       bnez    r4, work_pending
+       bra     restore_all
+
+#ifdef CONFIG_PREEMPT
+ENTRY(resume_kernel)
+       GET_THREAD_INFO(r8)
+       ld      r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ?
+       bnez    r9, restore_all
+need_resched:
+       ld      r9, @(TI_FLAGS, r8)     ; need_resched set ?
+       and3    r4, r9, #_TIF_NEED_RESCHED
+       beqz    r4, restore_all
+       ld      r4, PSW(sp)             ; interrupts off (exception path) ?
+       and3    r4, r4, #0x4000
+       beqz    r4, restore_all
+       LDIMM   (r4, PREEMPT_ACTIVE)
+       st      r4, @(TI_PRE_COUNT, r8)
+       STI(r4)
+       bl      schedule
+       ldi     r4, #0
+       st      r4, @(TI_PRE_COUNT, r8)
+       CLI(r4)
+       bra     need_resched
+#endif
+
+       ; system call handler stub
+ENTRY(system_call)
+       SWITCH_TO_KERNEL_STACK
+       SAVE_ALL
+       STI(r4)                         ; Enable interrupt
+       st      sp, PTREGS(sp)          ; implicit pt_regs parameter
+       cmpui   r7, #NR_syscalls
+       bnc     syscall_badsys
+       st      r7, SYSCALL_NR(sp)      ; syscall_nr
+                                       ; system call tracing in operation
+       GET_THREAD_INFO(r8)
+       ld      r9, @(TI_FLAGS, r8)
+       and3    r4, r9, #_TIF_SYSCALL_TRACE
+       bnez    r4, syscall_trace_entry
+syscall_call:
+       slli    r7, #2                  ; table jump for the system call
+       LDIMM   (r4, sys_call_table)
+       add     r7, r4
+       ld      r7, @r7
+       jl      r7                      ; execute system call
+       st      r0, R0(sp)              ; save the return value
+syscall_exit:
+       CLI(r4)                         ; make sure we don't miss an interrupt
+                                       ; setting need_resched or sigpending
+                                       ; between sampling and the iret
+       ld      r9, @(TI_FLAGS, r8)
+       and3    r4, r9, #_TIF_ALLWORK_MASK      ; current->work
+       bnez    r4, syscall_exit_work
+restore_all:
+       RESTORE_ALL
+
+       # perform work that needs to be done immediately before resumption
+       # r9 : frags
+       ALIGN
+work_pending:
+       and3    r4, r9, #_TIF_NEED_RESCHED
+       beqz    r4, work_notifysig
+work_resched:
+       bl      schedule
+       CLI(r4)                         ; make sure we don't miss an interrupt
+                                       ; setting need_resched or sigpending
+                                       ; between sampling and the iret
+       ld      r9, @(TI_FLAGS, r8)
+       and3    r4, r9, #_TIF_WORK_MASK ; is there any work to be done other
+                                       ; than syscall tracing?
+       beqz    r4, restore_all
+       and3    r4, r4, #_TIF_NEED_RESCHED
+       bnez    r4, work_resched
+
+work_notifysig:                                ; deal with pending signals and
+                                       ; notify-resume requests
+       mv      r0, sp                  ; arg1 : struct pt_regs *regs
+       ldi     r1, #0                  ; arg2 : sigset_t *oldset
+       mv      r2, r9                  ; arg3 : __u32 thread_info_flags
+       bl      do_notify_resume
+       bra     restore_all
+
+       ; perform syscall exit tracing
+       ALIGN
+syscall_trace_entry:
+       ldi     r4, #-ENOSYS
+       st      r4, R0(sp)
+       bl      do_syscall_trace
+       ld      r0, ORIG_R0(sp)
+       ld      r1, R1(sp)
+       ld      r2, R2(sp)
+       ld      r3, R3(sp)
+       ld      r4, R4(sp)
+       ld      r5, R5(sp)
+       ld      r6, R6(sp)
+       ld      r7, SYSCALL_NR(sp)
+       cmpui   r7, #NR_syscalls
+       bc      syscall_call
+       bra     syscall_exit
+
+       ; perform syscall exit tracing
+       ALIGN
+syscall_exit_work:
+       ld      r9, @(TI_FLAGS, r8)
+       and3    r4, r9, #_TIF_SYSCALL_TRACE
+       beqz    r4, work_pending
+       STI(r4)                         ; could let do_syscall_trace() call
+                                       ; schedule() instead
+       bl      do_syscall_trace
+       bra     resume_userspace
+
+       ALIGN
+syscall_fault:
+       SAVE_ALL
+       GET_THREAD_INFO(r8)
+       ldi     r4, #-EFAULT
+       st      r4, R0(sp)
+       bra     resume_userspace
+
+       ALIGN
+syscall_badsys:
+       ldi     r4, #-ENOSYS
+       st      r4, R0(sp)
+       bra     resume_userspace
+
+       .global eit_vector
+
+       .equ ei_vec_table, eit_vector + 0x0200
+
+/*
+ * EI handler routine
+ */
+ENTRY(ei_handler)
+#if defined(CONFIG_CHIP_M32700)
+       SWITCH_TO_KERNEL_STACK
+       ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
+#endif
+       SAVE_ALL
+       mv      r1, sp                  ; arg1(regs)
+#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \
+       || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
+       || defined(CONFIG_CHIP_OPSP)
+
+;    GET_ICU_STATUS;
+       seth    r0, #shigh(M32R_ICU_ISTS_ADDR)
+       ld      r0, @(low(M32R_ICU_ISTS_ADDR),r0)
+       st      r0, @-sp
+#if defined(CONFIG_SMP)
+       /*
+        * If IRQ == 0      --> Nothing to do,  Not write IMASK
+        * If IRQ == IPI    --> Do IPI handler, Not write IMASK
+        * If IRQ != 0, IPI --> Do do_IRQ(),    Write IMASK
+        */
+       slli    r0, #4
+       srli    r0, #24                 ; r0(irq_num<<2)
+       ;; IRQ exist check
+#if defined(CONFIG_CHIP_M32700)
+       /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
+       beqz    r0, 3f                  ; if (!irq_num) goto exit
+#else
+       beqz    r0, 1f                  ; if (!irq_num) goto exit
+#endif /* WORKAROUND */
+       ;; IPI check
+       cmpi    r0, #(M32R_IRQ_IPI0<<2) ; ISN < IPI0 check
+       bc      2f
+       cmpi    r0, #((M32R_IRQ_IPI7+1)<<2)     ; ISN > IPI7 check
+       bnc     2f
+       LDIMM   (r2, ei_vec_table)
+       add     r2, r0
+       ld      r2, @r2
+       beqz    r2, 1f                  ; if (no IPI handler) goto exit
+       mv      r0, r1                  ; arg0(regs)
+       jl      r2
+       .fillinsn
+1:
+       addi    sp, #4
+       bra     ret_to_intr
+#if defined(CONFIG_CHIP_M32700)
+       /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
+       .fillinsn
+3:
+       ld24    r14, #0x00070000
+       seth    r0, #shigh(M32R_ICU_IMASK_ADDR)
+       st      r14, @(low(M32R_ICU_IMASK_ADDR), r0)
+       addi    sp, #4
+       bra     ret_to_intr
+#endif /* WORKAROUND */
+       ;; do_IRQ
+       .fillinsn
+2:
+       srli    r0, #2
+#if defined(CONFIG_PLAT_USRV)
+       add3    r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
+       bnez    r2, 9f
+       ; read ICU status register of PLD
+       seth    r0, #high(PLD_ICUISTS)
+       or3     r0, r0, #low(PLD_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       addi    r0, #(M32700UT_PLD_IRQ_BASE)
+       .fillinsn
+9:
+#elif defined(CONFIG_PLAT_M32700UT)
+       add3    r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
+       bnez    r2, check_int0
+       ; read ICU status register of PLD
+       seth    r0, #high(PLD_ICUISTS)
+       or3     r0, r0, #low(PLD_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       addi    r0, #(M32700UT_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_int0:
+       add3    r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
+       bnez    r2, check_int2
+       ; read ICU status of LAN-board
+       seth    r0, #high(M32700UT_LAN_ICUISTS)
+       or3     r0, r0, #low(M32700UT_LAN_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       add3    r0, r0, #(M32700UT_LAN_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_int2:
+       add3    r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
+       bnez    r2, check_end
+       ; read ICU status of LCD-board
+       seth    r0, #high(M32700UT_LCD_ICUISTS)
+       or3     r0, r0, #low(M32700UT_LCD_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       add3    r0, r0, #(M32700UT_LCD_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_end:
+#elif defined(CONFIG_PLAT_OPSPUT)
+       add3    r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
+       bnez    r2, check_int0
+       ; read ICU status register of PLD
+       seth    r0, #high(PLD_ICUISTS)
+       or3     r0, r0, #low(PLD_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       addi    r0, #(OPSPUT_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_int0:
+       add3    r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
+       bnez    r2, check_int2
+       ; read ICU status of LAN-board
+       seth    r0, #high(OPSPUT_LAN_ICUISTS)
+       or3     r0, r0, #low(OPSPUT_LAN_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       add3    r0, r0, #(OPSPUT_LAN_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_int2:
+       add3    r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
+       bnez    r2, check_end
+       ; read ICU status of LCD-board
+       seth    r0, #high(OPSPUT_LCD_ICUISTS)
+       or3     r0, r0, #low(OPSPUT_LCD_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       add3    r0, r0, #(OPSPUT_LCD_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_end:
+#endif  /* CONFIG_PLAT_OPSPUT */
+       bl      do_IRQ                  ; r0(irq), r1(regs)
+#else  /* not CONFIG_SMP */
+       srli    r0, #22                 ; r0(irq)
+#if defined(CONFIG_PLAT_USRV)
+       add3    r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
+       bnez    r2, 1f
+       ; read ICU status register of PLD
+       seth    r0, #high(PLD_ICUISTS)
+       or3     r0, r0, #low(PLD_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       addi    r0, #(M32700UT_PLD_IRQ_BASE)
+       .fillinsn
+1:
+#elif defined(CONFIG_PLAT_M32700UT)
+       add3    r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
+       bnez    r2, check_int0
+       ; read ICU status register of PLD
+       seth    r0, #high(PLD_ICUISTS)
+       or3     r0, r0, #low(PLD_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       addi    r0, #(M32700UT_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_int0:
+       add3    r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
+       bnez    r2, check_int2
+       ; read ICU status of LAN-board
+       seth    r0, #high(M32700UT_LAN_ICUISTS)
+       or3     r0, r0, #low(M32700UT_LAN_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       add3    r0, r0, #(M32700UT_LAN_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_int2:
+       add3    r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
+       bnez    r2, check_end
+       ; read ICU status of LCD-board
+       seth    r0, #high(M32700UT_LCD_ICUISTS)
+       or3     r0, r0, #low(M32700UT_LCD_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       add3    r0, r0, #(M32700UT_LCD_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_end:
+#elif defined(CONFIG_PLAT_OPSPUT)
+       add3    r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
+       bnez    r2, check_int0
+       ; read ICU status register of PLD
+       seth    r0, #high(PLD_ICUISTS)
+       or3     r0, r0, #low(PLD_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       addi    r0, #(OPSPUT_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_int0:
+       add3    r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
+       bnez    r2, check_int2
+       ; read ICU status of LAN-board
+       seth    r0, #high(OPSPUT_LAN_ICUISTS)
+       or3     r0, r0, #low(OPSPUT_LAN_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       add3    r0, r0, #(OPSPUT_LAN_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_int2:
+       add3    r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
+       bnez    r2, check_end
+       ; read ICU status of LCD-board
+       seth    r0, #high(OPSPUT_LCD_ICUISTS)
+       or3     r0, r0, #low(OPSPUT_LCD_ICUISTS)
+       lduh    r0, @r0
+       slli    r0, #21
+       srli    r0, #27                         ; ISN
+       add3    r0, r0, #(OPSPUT_LCD_PLD_IRQ_BASE)
+       bra     check_end
+       .fillinsn
+check_end:
+#endif  /* CONFIG_PLAT_OPSPUT */
+       bl      do_IRQ
+#endif  /* CONFIG_SMP */
+       ld      r14, @sp+
+       seth    r0, #shigh(M32R_ICU_IMASK_ADDR)
+       st      r14, @(low(M32R_ICU_IMASK_ADDR),r0)
+#else
+#error no chip configuration
+#endif
+ret_to_intr:
+       bra  ret_from_intr
+
+/*
+ * Default EIT handler
+ */
+       ALIGN
+int_msg:
+       .asciz  "Unknown interrupt\n"
+       .byte   0
+
+ENTRY(default_eit_handler)
+       push    r0
+       mvfc    r0, psw
+       push    r1
+       push    r2
+       push    r3
+       push    r0
+       LDIMM   (r0, __KERNEL_DS)
+       mv      r0, r1
+       mv      r0, r2
+       LDIMM   (r0, int_msg)
+       bl      printk
+       pop     r0
+       pop     r3
+       pop     r2
+       pop     r1
+       mvtc    r0, psw
+       pop     r0
+infinit:
+       bra     infinit
+
+#ifdef CONFIG_MMU
+/*
+ * Access Exception handler
+ */
+ENTRY(ace_handler)
+       SWITCH_TO_KERNEL_STACK
+       SAVE_ALL
+
+       seth    r2, #shigh(MMU_REG_BASE)        /* Check status register */
+       ld      r4, @(low(MESTS_offset),r2)
+       st      r4, @(low(MESTS_offset),r2)
+       srl3    r1, r4, #4
+#ifdef CONFIG_CHIP_M32700
+       and3    r1, r1, #0x0000ffff
+       ; WORKAROUND: ignore TME bit for the M32700(TS1).
+#endif /* CONFIG_CHIP_M32700 */
+       beqz    r1, inst
+oprand:
+       ld      r2, @(low(MDEVA_offset),r2)     ; set address
+       srli    r2, #12
+       slli    r2, #12
+       srli    r1, #1
+       bra     1f
+inst:
+       and3    r1, r4, #2
+       srli    r1, #1
+       or3     r1, r1, #8
+       mvfc    r2, bpc                         ; set address
+       .fillinsn
+1:
+       mvfc    r3, psw
+       mv      r0, sp
+       and3    r3, r3, 0x800
+       srli    r3, #9
+       or      r1, r3
+       /*
+        * do_page_fault():
+        *    r0 : struct pt_regs *regs
+        *    r1 : unsigned long error-code
+        *    r2 : unsigned long address
+        * error-code:
+        *    +------+------+------+------+
+        *    | bit3 | bit2 | bit1 | bit0 |
+        *    +------+------+------+------+
+        *    bit 3 == 0:means data,          1:means instruction
+        *    bit 2 == 0:means kernel,        1:means user-mode
+        *    bit 1 == 0:means read,          1:means write
+        *    bit 0 == 0:means no page found  1:means protection fault
+        *
+        */
+       bl      do_page_fault
+       bra     ret_from_intr
+#endif  /* CONFIG_MMU */
+
+
+ENTRY(alignment_check)
+/* void alignment_check(int error_code) */
+       SWITCH_TO_KERNEL_STACK
+       SAVE_ALL
+       ldi     r1, #0x30                       ; error_code
+       mv      r0, sp                          ; pt_regs
+       bl      do_alignment_check
+error_code:
+       bra     ret_from_exception
+
+ENTRY(rie_handler)
+/* void rie_handler(int error_code) */
+       SWITCH_TO_KERNEL_STACK
+       SAVE_ALL
+       mvfc    r0, bpc
+       ld      r1, @r0
+       seth    r0, #0xa0f0
+       st      r1, @r0
+       ldi     r1, #0x20                       ; error_code
+       mv      r0, sp                          ; pt_regs
+       bl      do_rie_handler
+       bra     error_code
+
+ENTRY(pie_handler)
+/* void pie_handler(int error_code) */
+       SWITCH_TO_KERNEL_STACK
+       SAVE_ALL
+       ldi     r1, #0                          ; error_code ; FIXME
+       mv      r0, sp                          ; pt_regs
+       bl      do_pie_handler
+       bra     error_code
+
+ENTRY(debug_trap)
+       .global withdraw_debug_trap
+       /* void debug_trap(void) */
+       SWITCH_TO_KERNEL_STACK
+       SAVE_ALL
+       mv      r0, sp                          ; pt_regs
+       bl      withdraw_debug_trap
+       ldi     r1, #0                          ; error_code
+       mv      r0, sp                          ; pt_regs
+       bl      do_debug_trap
+       bra     error_code
+
+
+/* Cache flushing handler */
+ENTRY(cache_flushing_handler)
+       .global _flush_cache_all
+       /* void _flush_cache_all(void); */
+       SWITCH_TO_KERNEL_STACK
+       push    r0
+       push    r1
+       push    r2
+       push    r3
+       push    r4
+       push    r5
+       push    r6
+       push    r7
+       push    lr
+       bl      _flush_cache_all
+       pop     lr
+       pop     r7
+       pop     r6
+       pop     r5
+       pop     r4
+       pop     r3
+       pop     r2
+       pop     r1
+       pop     r0
+       rte
+
+.data
+ENTRY(sys_call_table)
+       .long sys_restart_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_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_lchown
+       .long sys_ni_syscall            /* old break syscall holder */
+       .long sys_stat
+       .long sys_lseek
+       .long sys_getpid                /* 20 */
+       .long sys_mount
+       .long sys_oldumount
+       .long sys_setuid
+       .long sys_getuid
+       .long sys_stime                 /* 25 */
+       .long sys_ptrace
+       .long sys_alarm
+       .long sys_fstat
+       .long sys_pause
+       .long sys_utime                 /* 30 */
+       .long sys_cacheflush            /* for M32R */ /* old stty syscall holder */
+       .long sys_cachectl              /* for M32R */ /* 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_signal
+       .long sys_geteuid
+       .long sys_getegid               /* 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            /* sys_olduname */
+       .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_sigaction
+       .long sys_sgetmask
+       .long sys_ssetmask
+       .long sys_setreuid              /* 70 */
+       .long sys_setregid
+       .long sys_sigsuspend
+       .long sys_sigpending
+       .long sys_sethostname
+       .long sys_setrlimit             /* 75 */
+       .long sys_getrlimit
+       .long sys_getrusage
+       .long sys_gettimeofday
+       .long sys_settimeofday
+       .long sys_getgroups             /* 80 */
+       .long sys_setgroups
+       .long sys_ni_syscall            /* sys_oldselect */
+       .long sys_symlink
+       .long sys_lstat
+       .long sys_readlink              /* 85 */
+       .long sys_uselib
+       .long sys_swapon
+       .long sys_reboot
+       .long old_readdir
+       .long sys_ni_syscall            /* 90 - old_mmap syscall holder */
+       .long sys_munmap
+       .long sys_truncate
+       .long sys_ftruncate
+       .long sys_fchmod
+       .long sys_fchown                /* 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            /* ioperm */
+       .long sys_socketcall
+       .long sys_syslog
+       .long sys_setitimer
+       .long sys_getitimer             /* 105 */
+       .long sys_newstat
+       .long sys_newlstat
+       .long sys_newfstat
+       .long sys_uname
+       .long sys_ni_syscall            /* 110  -  iopl */
+       .long sys_vhangup
+       .long sys_ni_syscall            /* for idle */
+       .long sys_ni_syscall            /* for vm86old */
+       .long sys_wait4
+       .long sys_swapoff               /* 115 */
+       .long sys_sysinfo
+       .long sys_ipc
+       .long sys_fsync
+       .long sys_sigreturn
+       .long sys_clone                 /* 120 */
+       .long sys_setdomainname
+       .long sys_newuname
+       .long sys_ni_syscall            /* sys_modify_ldt */
+       .long sys_adjtimex
+       .long sys_mprotect              /* 125 */
+       .long sys_sigprocmask
+       .long sys_ni_syscall            /* sys_create_module */
+       .long sys_init_module
+       .long sys_delete_module
+       .long sys_ni_syscall            /* 130 sys_get_kernel_syms */
+       .long sys_quotactl
+       .long sys_getpgid
+       .long sys_fchdir
+       .long sys_bdflush
+       .long sys_sysfs                 /* 135 */
+       .long sys_personality
+       .long sys_ni_syscall            /* for afs_syscall */
+       .long sys_setfsuid
+       .long sys_setfsgid
+       .long sys_llseek                /* 140 */
+       .long sys_getdents
+       .long sys_select
+       .long sys_flock
+       .long sys_msync
+       .long sys_readv                 /* 145 */
+       .long sys_writev
+       .long sys_getsid
+       .long sys_fdatasync
+       .long sys_sysctl
+       .long sys_mlock                 /* 150 */
+       .long sys_munlock
+       .long sys_mlockall
+       .long 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_mremap
+       .long sys_setresuid
+       .long sys_getresuid             /* 165 */
+       .long sys_tas                   /* vm86 */
+       .long sys_ni_syscall            /* sys_query_module */
+       .long sys_poll
+       .long sys_nfsservctl
+       .long sys_setresgid             /* 170 */
+       .long sys_getresgid
+       .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_chown
+       .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_lchown
+       .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_chown
+       .long sys_setuid
+       .long sys_setgid
+       .long sys_setfsuid              /* 215 */
+       .long sys_setfsgid
+       .long sys_pivot_root
+       .long sys_mincore
+       .long sys_madvise
+       .long sys_getdents64            /* 220 */
+       .long sys_fcntl64
+       .long sys_ni_syscall            /* reserved for TUX */
+       .long sys_ni_syscall            /* Reserved for Security */
+       .long sys_gettid
+       .long sys_readahead             /* 225 */
+       .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            /* reserved for "set_thread_area" system call */
+       .long sys_ni_syscall            /* reserved for "get_thread_area" system call */
+       .long sys_io_setup              /* 245 */
+       .long sys_io_destroy
+       .long sys_io_getevents
+       .long sys_io_submit
+       .long sys_io_cancel
+       .long sys_fadvise64             /* 250 */
+       .long sys_ni_syscall
+       .long sys_exit_group
+       .long sys_lookup_dcookie
+       .long sys_epoll_create
+       .long sys_epoll_ctl             /* 255 */
+       .long sys_epoll_wait
+       .long sys_remap_file_pages
+       .long sys_set_tid_address
+       .long sys_timer_create
+       .long sys_timer_settime         /* 260 */
+       .long sys_timer_gettime
+       .long sys_timer_getoverrun
+       .long sys_timer_delete
+       .long sys_clock_settime
+       .long sys_clock_gettime         /* 265 */
+       .long sys_clock_getres
+       .long sys_clock_nanosleep
+       .long sys_statfs64
+       .long sys_fstatfs64
+       .long sys_tgkill                /* 270 */
+       .long sys_utimes
+       .long sys_fadvise64_64
+       .long sys_ni_syscall            /* Reserved for sys_vserver */
+        .long sys_ni_syscall           /* Reserved for sys_mbind */
+        .long sys_ni_syscall           /* Reserved for sys_get_mempolicy */
+        .long sys_ni_syscall           /* Reserved for sys_set_mempolicy */
+        .long sys_mq_open
+        .long sys_mq_unlink
+        .long sys_mq_timedsend
+        .long sys_mq_timedreceive       /* 280 */
+        .long sys_mq_notify
+        .long sys_mq_getsetattr
+        .long sys_ni_syscall            /* reserved for kexec */
+       .long sys_waitid
+
+syscall_table_size=(.-sys_call_table)
+
diff --git a/arch/m32r/kernel/head.S b/arch/m32r/kernel/head.S
new file mode 100644 (file)
index 0000000..3e83173
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ *  linux/arch/m32r/kernel/head.S
+ *
+ *  M32R startup code.
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ */
+
+/* $Id$ */
+
+#include <linux/init.h>
+__INIT
+__INITDATA
+
+       .text
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/assembler.h>
+#include <asm/m32r.h>
+#include <asm/mmu_context.h>
+
+/*
+ * References to members of the boot_cpu_data structure.
+ */
+       .text
+       .global start_kernel
+       .global __bss_start
+       .global _end
+ENTRY(stext)
+ENTRY(_stext)
+ENTRY(startup_32)
+       /* Setup up the stack pointer */
+       LDIMM   (r0, spi_stack_top)
+       LDIMM   (r1, spu_stack_top)
+       mvtc    r0, spi
+       mvtc    r1, spu
+
+       /* Initilalize PSW */
+       ldi     r0, #0x0000             /* use SPI, disable EI */
+       mvtc    r0, psw
+
+       /* Set up the stack pointer */
+       LDIMM   (r0, stack_start)
+       ld      r0, @r0
+       mvtc    r0, spi
+
+/*
+ * Clear BSS first so that there are no surprises...
+ */
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+       LDIMM   (r2, __bss_start)
+       LDIMM   (r3, _end)
+       sub     r3, r2          ; BSS size in bytes
+       ; R4 = BSS size in longwords (rounded down)
+       mv      r4, r3              ||  ldi     r1, #0
+       srli    r4, #4              ||  addi    r2, #-4
+       beqz    r4, .Lendloop1
+.Lloop1:
+#ifndef CONFIG_CHIP_M32310
+       ; Touch memory for the no-write-allocating cache.
+       ld      r0, @(4,r2)
+#endif
+       st      r1, @+r2            ||  addi    r4, #-1
+       st      r1, @+r2
+       st      r1, @+r2
+       st      r1, @+r2            ||  cmpeq   r1, r4  ; R4 = 0?
+       bnc     .Lloop1
+.Lendloop1:
+       and3    r4, r3, #15
+       addi    r2, #4
+       beqz    r4, .Lendloop2
+.Lloop2:
+       stb     r1, @r2             ||  addi    r4, #-1
+       addi    r2, #1
+       bnez    r4, .Lloop2
+.Lendloop2:
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+       LDIMM   (r2, __bss_start)
+       LDIMM   (r3, _end)
+       sub     r3, r2          ; BSS size in bytes
+       mv      r4, r3
+       srli    r4, #2          ; R4 = BSS size in longwords (rounded down)
+       ldi     r1, #0          ; clear R1 for longwords store
+       addi    r2, #-4         ; account for pre-inc store
+       beqz    r4, .Lendloop1  ; any more to go?
+.Lloop1:
+       st      r1, @+r2        ; yep, zero out another longword
+       addi    r4, #-1         ; decrement count
+       bnez    r4, .Lloop1     ; go do some more
+.Lendloop1:
+       and3    r4, r3, #3      ; get no. of remaining BSS bytes to clear
+       addi    r2, #4          ; account for pre-inc store
+       beqz    r4, .Lendloop2  ; any more to go?
+.Lloop2:
+       stb     r1, @r2         ; yep, zero out another byte
+       addi    r2, #1          ; bump address
+       addi    r4, #-1         ; decrement count
+       bnez    r4, .Lloop2     ; go do some more
+.Lendloop2:
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+#if 0  /* M32R_FIXME */
+/*
+ * Copy data segment from ROM to RAM.
+ */
+       .global ROM_D, TOP_DATA, END_DATA
+
+       LDIMM   (r1, ROM_D)
+       LDIMM   (r2, TOP_DATA)
+       LDIMM   (r3, END_DATA)
+       addi    r2, #-4
+       addi    r3, #-4
+loop1:
+       ld      r0, @r1+
+       st      r0, @+r2
+       cmp     r2, r3
+       bc      loop1
+#endif /* 0 */
+
+/* Jump to kernel */
+       LDIMM   (r2, start_kernel)
+       jl      r2
+       .fillinsn
+1:
+       bra     1b              ; main should never return here, but
+                               ; just in case, we know what happens.
+
+#ifdef CONFIG_SMP
+/*
+ * AP startup routine
+ */
+       .text
+       .global eit_vector
+ENTRY(startup_AP)
+;; setup EVB
+       LDIMM  (r4, eit_vector)
+       mvtc   r4, cr5
+
+;; enable MMU
+       LDIMM   (r2, init_tlb)
+       jl      r2
+       seth  r4, #high(MATM)
+       or3   r4, r4, #low(MATM)
+       ldi   r5, #0x01
+       st    r5, @r4            ; Set MATM Reg(T bit ON)
+       ld    r6, @r4            ; MATM Check
+       LDIMM (r5, 1f)
+       jmp   r5                 ; enable MMU
+       nop
+       .fillinsn
+1:
+;; ISN check
+       ld    r6, @r4            ; MATM Check
+       seth  r4, #high(M32R_ICU_ISTS_ADDR)
+       or3   r4, r4, #low(M32R_ICU_ISTS_ADDR)
+       ld    r5, @r4           ; Read ISTSi reg.
+       mv    r6, r5
+       slli  r5, #13  ; PIML check
+       srli  r5, #13  ;
+       seth  r4, #high(M32R_ICU_IMASK_ADDR)
+       or3   r4, r4, #low(M32R_ICU_IMASK_ADDR)
+       st    r5, @r4           ; Write IMASKi reg.
+       slli  r6, #4   ; ISN check
+       srli  r6, #26  ;
+       seth  r4, #high(M32R_IRQ_IPI5)
+       or3   r4, r4, #low(M32R_IRQ_IPI5)
+       bne   r4, r6, 2f  ; if (ISN != CPU_BOOT_IPI) goto sleep;
+
+;; check cpu_bootout_map and set cpu_bootin_map
+       LDIMM (r4, cpu_bootout_map)
+       ld    r4, @r4
+       seth  r5, #high(M32R_CPUID_PORTL)
+       or3   r5, r5, #low(M32R_CPUID_PORTL)
+       ld    r5, @r5
+       ldi   r6, #1
+       sll   r6, r5
+       and   r4, r6
+       beqz  r4, 2f
+       LDIMM (r4, cpu_bootin_map)
+       ld    r5, @r4
+       or    r5, r6
+       st    r6, @r4
+
+;; clear PSW
+       ldi   r4, #0
+       mvtc  r4, psw
+
+;; setup SPI
+       LDIMM (r4, stack_start)
+       ld    r4, @r4
+       mvtc  r4, spi
+
+;; setup BPC (start_secondary)
+       LDIMM (r4, start_secondary)
+       mvtc  r4, bpc
+
+       rte  ; goto startup_secondary
+       nop
+       nop
+
+       .fillinsn
+2:
+       ;; disable MMU
+       seth  r4, #high(MATM)
+       or3   r4, r4, #low(MATM)
+       ldi   r5, #0
+       st    r5, @r4            ; Set MATM Reg(T bit OFF)
+       ld    r6, @r4            ; MATM Check
+       LDIMM (r4, 3f)
+       seth  r5, #high(__PAGE_OFFSET)
+       or3   r5, r5, #low(__PAGE_OFFSET)
+       not   r5, r5
+       and   r4, r5
+       jmp   r4                 ; disable MMU
+       nop
+       .fillinsn
+3:
+       ;; SLEEP and wait IPI
+       LDIMM (r4, AP_loop)
+       seth  r5, #high(__PAGE_OFFSET)
+       or3   r5, r5, #low(__PAGE_OFFSET)
+       not   r5, r5
+       and   r4, r5
+       jmp   r4
+       nop
+       nop
+#endif  /* CONFIG_SMP */
+
+ENTRY(stack_start)
+       .long   init_thread_union+8192
+       .long   __KERNEL_DS
+
+/*
+ * This is initialized to create a identity-mapping at 0-4M (for bootup
+ * purposes) and another mapping of the 0-4M area at virtual address
+ * PAGE_OFFSET.
+ */
+       .text
+
+#define  MOUNT_ROOT_RDONLY    1
+#define  RAMDISK_FLAGS        0                ; 1024KB
+#define  ORIG_ROOT_DEV        0x0100   ; /dev/ram0 (major:01, minor:00)
+#define  LOADER_TYPE          1                ; (??? - non-zero value seems
+                                       ; to be needed to boot from initrd)
+
+#define  COMMAND_LINE ""
+
+       .section        .empty_zero_page, "aw"
+ENTRY(empty_zero_page)
+       .long   MOUNT_ROOT_RDONLY               /* offset: +0x00 */
+       .long   RAMDISK_FLAGS
+       .long   ORIG_ROOT_DEV
+       .long   LOADER_TYPE
+       .long   0       /* INITRD_START */      /* +0x10 */
+       .long   0       /* INITRD_SIZE */
+       .long   0       /* CPU_CLOCK */
+       .long   0       /* BUS_CLOCK */
+       .long   0       /* TIMER_DIVIDE */      /* +0x20 */
+       .balign 256,0
+       .asciz  COMMAND_LINE
+       .byte   0
+       .balign 4096,0,4096
+
+/*------------------------------------------------------------------------
+ * Stack area
+ */
+       .section .spi
+       ALIGN
+       .global spi_stack_top
+       .zero   1024
+spi_stack_top:
+
+       .section .spu
+       ALIGN
+       .global spu_stack_top
+       .zero   1024
+spu_stack_top:
+
+       .end
diff --git a/arch/m32r/kernel/init_task.c b/arch/m32r/kernel/init_task.c
new file mode 100644 (file)
index 0000000..9e508fd
--- /dev/null
@@ -0,0 +1,41 @@
+/* orig : i386 init_task.c */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.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 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) };
+
+/*
+ * 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);
+
diff --git a/arch/m32r/kernel/io_m32700ut.c b/arch/m32r/kernel/io_m32700ut.c
new file mode 100644 (file)
index 0000000..501b755
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ *  linux/arch/m32r/kernel/io_mappi.c
+ *
+ *  Typical I/O routines for M32700UT board.
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Takeo Takahashi
+ *
+ *  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/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0   (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
+#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
+
+#define PORT2ADDR(port)  _port2addr(port)
+#define PORT2ADDR_USB(port) _port2addr_usb(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET);
+}
+
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+static __inline__ void *__port2addr_ata(unsigned long port)
+{
+       static int      dummy_reg;
+
+       switch (port) {
+       case 0x1f0:     return (void *)0xac002000;
+       case 0x1f1:     return (void *)0xac012800;
+       case 0x1f2:     return (void *)0xac012002;
+       case 0x1f3:     return (void *)0xac012802;
+       case 0x1f4:     return (void *)0xac012004;
+       case 0x1f5:     return (void *)0xac012804;
+       case 0x1f6:     return (void *)0xac012006;
+       case 0x1f7:     return (void *)0xac012806;
+       case 0x3f6:     return (void *)0xac01200e;
+       default:        return (void *)&dummy_reg;
+       }
+}
+#endif
+
+/*
+ * M32700UT-LAN is located in the extended bus space
+ * from 0x10000000 to 0x13ffffff on physical address.
+ * The base address of LAN controller(LAN91C111) is 0x300.
+ */
+#define LAN_IOSTART    0x300
+#define LAN_IOEND      0x320
+static __inline__ void *_port2addr_ne(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+}
+static __inline__ void *_port2addr_usb(unsigned long port)
+{
+  return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000);
+}
+
+static __inline__ void delay(void)
+{
+       __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+#define PORT2ADDR_NE(port)  _port2addr_ne(port)
+
+static __inline__ unsigned char _ne_inb(void *portp)
+{
+       return *(volatile unsigned char *)portp;
+}
+
+static __inline__ unsigned short _ne_inw(void *portp)
+{
+       return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
+}
+
+static __inline__ void _ne_insb(void *portp, void * addr, unsigned long count)
+{
+       unsigned char *buf = (unsigned char *)addr;
+
+       while (count--) *buf++ = _ne_inb(portp);
+}
+
+static __inline__ void _ne_outb(unsigned char b, void *portp)
+{
+       *(volatile unsigned char *)portp = b;
+}
+
+static __inline__ void _ne_outw(unsigned short w, void *portp)
+{
+       *(volatile unsigned short *)portp = cpu_to_le16(w);
+}
+
+unsigned char _inb(unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               return _ne_inb(PORT2ADDR_NE(port));
+
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               return *(volatile unsigned char *)__port2addr_ata(port);
+       }
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned char b;
+          pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+          return b;
+       } else
+#endif
+
+       return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               return _ne_inw(PORT2ADDR_NE(port));
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               return *(volatile unsigned short *)__port2addr_ata(port);
+       }
+#endif
+#if defined(CONFIG_USB)
+       else if(port >= 0x340 && port < 0x3a0)
+         return *(volatile unsigned short *)PORT2ADDR_USB(port);
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned short w;
+          pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+          return w;
+       } else
+#endif
+       return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned long l;
+          pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
+          return l;
+       } else
+#endif
+       return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+       unsigned char  v;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               v = _ne_inb(PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               return *(volatile unsigned char *)__port2addr_ata(port);
+       } else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned char b;
+          pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+          return b;
+       } else
+#endif
+               v = *(volatile unsigned char *)PORT2ADDR(port);
+
+       delay();
+       return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+       unsigned short  v;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               v = _ne_inw(PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               return *(volatile unsigned short *)__port2addr_ata(port);
+       } else
+#endif
+#if defined(CONFIG_USB)
+         if(port >= 0x340 && port < 0x3a0)
+           return *(volatile unsigned short *)PORT2ADDR_USB(port);
+       else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned short w;
+          pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+          return w;
+       } else
+#endif
+               v = *(volatile unsigned short *)PORT2ADDR(port);
+
+       delay();
+       return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+       unsigned long  v;
+
+       v = *(volatile unsigned long *)PORT2ADDR(port);
+       delay();
+       return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outb(b, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               *(volatile unsigned char *)__port2addr_ata(port) = b;
+       } else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+       } else
+#endif
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outw(w, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               *(volatile unsigned short *)__port2addr_ata(port) = w;
+       } else
+#endif
+#if defined(CONFIG_USB)
+       if(port >= 0x340 && port < 0x3a0)
+         *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+       else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+       } else
+#endif
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
+       } else
+#endif
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outb(b, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               *(volatile unsigned char *)__port2addr_ata(port) = b;
+       } else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+       } else
+#endif
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+
+       delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outw(w, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               *(volatile unsigned short *)__port2addr_ata(port) = w;
+       } else
+#endif
+#if defined(CONFIG_USB)
+         if(port >= 0x340 && port < 0x3a0)
+           *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+       else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+       } else
+#endif
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+
+       delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_insb(PORT2ADDR_NE(port), addr, count);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               unsigned char *buf = addr;
+               unsigned char *portp = __port2addr_ata(port);
+               while(count--) *buf++ = *(volatile unsigned char *)portp;
+       }
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+         else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+       }
+#endif
+       else {
+               unsigned char *buf = addr;
+               unsigned char *portp = PORT2ADDR(port);
+               while(count--) *buf++ = *(volatile unsigned char *)portp;
+       }
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND) {
+               /*
+                * This portion is only used by smc91111.c to read data
+                * from the DATA_REG. Do not swap the data.
+                */
+               portp = PORT2ADDR_NE(port);
+               while (count--) *buf++ = *(volatile unsigned short *)portp;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               portp = __port2addr_ata(port);
+               while (count--) *buf++ = *(volatile unsigned short *)portp;
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while (count--) *buf++ = *(volatile unsigned short *)portp;
+       }
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned long *buf = addr;
+       unsigned long *portp;
+
+       portp = PORT2ADDR(port);
+       while (count--) *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned char *buf = addr;
+       unsigned char *portp;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND) {
+               portp = PORT2ADDR_NE(port);
+               while (count--) _ne_outb(*buf++, portp);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               portp = __port2addr_ata(port);
+               while(count--) *(volatile unsigned char *)portp = *buf++;
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while(count--) *(volatile unsigned char *)portp = *buf++;
+       }
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND) {
+               /*
+                * This portion is only used by smc91111.c to write data
+                * into the DATA_REG. Do not swap the data.
+                */
+               portp = PORT2ADDR_NE(port);
+               while(count--) *(volatile unsigned short *)portp = *buf++;
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               portp = __port2addr_ata(port);
+               while(count--) *(volatile unsigned short *)portp = *buf++;
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while(count--) *(volatile unsigned short *)portp = *buf++;
+       }
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned long *buf = addr;
+       unsigned char *portp;
+
+       portp = PORT2ADDR(port);
+       while(count--) *(volatile unsigned long *)portp = *buf++;
+}
diff --git a/arch/m32r/kernel/io_mappi.c b/arch/m32r/kernel/io_mappi.c
new file mode 100644 (file)
index 0000000..74aeca6
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ *  linux/arch/m32r/kernel/io_mappi.c
+ *
+ *  Typical I/O routines for Mappi board.
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ */
+
+/* $Id: io_mappi.c,v 1.9 2003/12/02 07:18:08 fujiwara Exp $ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0   (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+#define M32R_PCC_IOSTART1 0x2000
+#define M32R_PCC_IOEND1   (M32R_PCC_IOSTART1 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite(int, unsigned long, void *, size_t, size_t, int);
+#endif /* CONFIG_PCMCIA && CONFIG_M32RPCC */
+
+#define PORT2ADDR(port)  _port2addr(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET);
+}
+
+static __inline__ void *_port2addr_ne(unsigned long port)
+{
+       return (void *)((port<<1) + NONCACHE_OFFSET + 0x0C000000);
+}
+
+static __inline__ void delay(void)
+{
+       __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+#define PORT2ADDR_NE(port)  _port2addr_ne(port)
+
+static __inline__ unsigned char _ne_inb(void *portp)
+{
+       return (unsigned char) *(volatile unsigned short *)portp;
+}
+
+static __inline__ unsigned short _ne_inw(void *portp)
+{
+       unsigned short tmp;
+
+       tmp = *(volatile unsigned short *)portp;
+       return le16_to_cpu(tmp);
+}
+
+static __inline__ void _ne_outb(unsigned char b, void *portp)
+{
+       *(volatile unsigned short *)portp = (unsigned short)b;
+}
+
+static __inline__ void _ne_outw(unsigned short w, void *portp)
+{
+       *(volatile unsigned short *)portp = cpu_to_le16(w);
+}
+
+unsigned char _inb(unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               return _ne_inb(PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+        if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned char b;
+          pcc_ioread(0, port, &b, sizeof(b), 1, 0);
+          return b;
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+         unsigned char b;
+          pcc_ioread(1, port, &b, sizeof(b), 1, 0);
+          return b;
+       } else
+#endif
+
+       return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               return _ne_inw(PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned short w;
+          pcc_ioread(0, port, &w, sizeof(w), 1, 0);
+          return w;
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          unsigned short w;
+          pcc_ioread(1, port, &w, sizeof(w), 1, 0);
+          return w;
+       } else
+#endif
+       return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned long l;
+          pcc_ioread(0, port, &l, sizeof(l), 1, 0);
+          return l;
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          unsigned short l;
+          pcc_ioread(1, port, &l, sizeof(l), 1, 0);
+          return l;
+       } else
+#endif
+       return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+       unsigned char  v;
+
+       if (port >= 0x300 && port < 0x320)
+               v = _ne_inb(PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned char b;
+          pcc_ioread(0, port, &b, sizeof(b), 1, 0);
+          return b;
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+         unsigned char b;
+          pcc_ioread(1, port, &b, sizeof(b), 1, 0);
+          return b;
+       } else
+#endif
+               v = *(volatile unsigned char *)PORT2ADDR(port);
+
+       delay();
+       return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+       unsigned short  v;
+
+       if (port >= 0x300 && port < 0x320)
+               v = _ne_inw(PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned short w;
+          pcc_ioread(0, port, &w, sizeof(w), 1, 0);
+          return w;
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          unsigned short w;
+          pcc_ioread(1, port, &w, sizeof(w), 1, 0);
+          return w;
+       } else
+#endif
+               v = *(volatile unsigned short *)PORT2ADDR(port);
+
+       delay();
+       return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+       unsigned long  v;
+
+       v = *(volatile unsigned long *)PORT2ADDR(port);
+       delay();
+       return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               _ne_outb(b, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite(0, port, &b, sizeof(b), 1, 0);
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          pcc_iowrite(1, port, &b, sizeof(b), 1, 0);
+       } else
+#endif
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               _ne_outw(w, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite(0, port, &w, sizeof(w), 1, 0);
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          pcc_iowrite(1, port, &w, sizeof(w), 1, 0);
+       } else
+#endif
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite(0, port, &l, sizeof(l), 1, 0);
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          pcc_iowrite(1, port, &l, sizeof(l), 1, 0);
+       } else
+#endif
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               _ne_outb(b, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite(0, port, &b, sizeof(b), 1, 0);
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          pcc_iowrite(1, port, &b, sizeof(b), 1, 0);
+       } else
+#endif
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+
+       delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               _ne_outw(w, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite(0, port, &w, sizeof(w), 1, 0);
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          pcc_iowrite(1, port, &w, sizeof(w), 1, 0);
+       } else
+#endif
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+
+       delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= 0x300 && port < 0x320){
+               portp = PORT2ADDR_NE(port);
+               while(count--) *buf++ = *(volatile unsigned char *)portp;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_ioread(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          pcc_ioread(1, port, (void *)addr, sizeof(unsigned char), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while(count--) *buf++ = *(volatile unsigned char *)portp;
+       }
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= 0x300 && port < 0x320) {
+               portp = PORT2ADDR_NE(port);
+               while (count--) *buf++ = _ne_inw(portp);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_ioread(0, port, (void *)addr, sizeof(unsigned short), count, 1);
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          pcc_ioread(1, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while (count--) *buf++ = *(volatile unsigned short *)portp;
+       }
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned long *buf = addr;
+       unsigned long *portp;
+
+       portp = PORT2ADDR(port);
+       while (count--) *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned char *buf = addr;
+       unsigned char *portp;
+
+       if (port >= 0x300 && port < 0x320) {
+               portp = PORT2ADDR_NE(port);
+               while (count--) _ne_outb(*buf++, portp);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+       } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          pcc_iowrite(1, port, (void *)addr, sizeof(unsigned char), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while(count--) *(volatile unsigned char *)portp = *buf++;
+       }
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= 0x300 && port < 0x320) {
+               portp = PORT2ADDR_NE(port);
+               while (count--) _ne_outw(*buf++, portp);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite(0, port, (void *)addr, sizeof(unsigned short), count, 1);
+       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+          pcc_iowrite(1, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while(count--) *(volatile unsigned short *)portp = *buf++;
+       }
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned long *buf = addr;
+       unsigned char *portp;
+
+       portp = PORT2ADDR(port);
+       while(count--) *(volatile unsigned long *)portp = *buf++;
+}
diff --git a/arch/m32r/kernel/io_mappi2.c b/arch/m32r/kernel/io_mappi2.c
new file mode 100644 (file)
index 0000000..7705fb0
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ *  linux/arch/m32r/kernel/io_mappi2.c
+ *
+ *  Typical I/O routines for Mappi2 board.
+ *
+ *  Copyright (c) 2001-2003  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+/* $Id:$ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0   (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
+#endif /* CONFIG_PCMCIA && CONFIG_MAPPI2_CFC */
+
+#define PORT2ADDR(port)      _port2addr(port)
+#define PORT2ADDR_NE(port)   _port2addr_ne(port)
+#define PORT2ADDR_USB(port)  _port2addr_usb(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET);
+}
+
+#define LAN_IOSTART    0x300
+#define LAN_IOEND      0x320
+#ifdef CONFIG_CHIP_OPSP
+static __inline__ void *_port2addr_ne(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+}
+#else
+static __inline__ void *_port2addr_ne(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET + 0x04000000);
+}
+#endif
+static __inline__ void *_port2addr_usb(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET + 0x14000000);
+}
+static __inline__ void delay(void)
+{
+       __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+static __inline__ unsigned char _ne_inb(void *portp)
+{
+       return (unsigned char) *(volatile unsigned char *)portp;
+}
+
+static __inline__ unsigned short _ne_inw(void *portp)
+{
+#if 1  /* byte swap */
+       unsigned short tmp,tmp2;
+       tmp = *(volatile unsigned short *)portp;
+       tmp2 = (tmp>>8|tmp<<8);
+       return tmp2;
+#else
+       return *(volatile unsigned short *)portp;
+#endif
+}
+
+static __inline__ void _ne_insb(void *portp, void * addr, unsigned long count)
+{
+       unsigned short tmp;
+       unsigned char *buf = addr;
+
+       tmp = *(volatile unsigned char *)portp;
+       while (count--) *buf++ = *(volatile unsigned char *)portp;
+}
+
+static __inline__ void _ne_outb(unsigned char b, void *portp)
+{
+       *(volatile unsigned char *)portp = (unsigned char)b;
+}
+
+static __inline__ void _ne_outw(unsigned short w, void *portp)
+{
+       *(volatile unsigned short *)portp = (w>>8|w<<8);
+}
+
+unsigned char _inb(unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               return _ne_inb(PORT2ADDR_NE(port));
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned char b;
+          pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+          return b;
+       } else
+#endif
+
+       return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               return _ne_inw(PORT2ADDR_NE(port));
+#if defined(CONFIG_USB)
+        else if (port >= 0x340 && port < 0x3a0)
+         return *(volatile unsigned short *)PORT2ADDR_USB(port);
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+         else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned short w;
+          pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+          return w;
+       } else
+#endif
+       return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned long l;
+          pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
+          return l;
+       } else
+#endif
+       return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+       unsigned char  v;
+
+       if (port >= 0x300 && port < 0x320)
+               v = _ne_inb(PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned char b;
+          pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+          return b;
+       } else
+#endif
+               v = *(volatile unsigned char *)PORT2ADDR(port);
+
+       delay();
+       return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+       unsigned short  v;
+
+       if (port >= 0x300 && port < 0x320)
+               v = _ne_inw(PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_USB)
+         if (port >= 0x340 && port < 0x3a0)
+               v = *(volatile unsigned short *)PORT2ADDR_USB(port);
+         else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned short w;
+          pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+          return w;
+       } else
+#endif
+               v = *(volatile unsigned short *)PORT2ADDR(port);
+
+       delay();
+       return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+       unsigned long  v;
+
+       v = *(volatile unsigned long *)PORT2ADDR(port);
+       delay();
+       return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outb(b, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+       } else
+#endif
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outw(w, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_USB)
+         if (port >= 0x340 && port < 0x3a0)
+           *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+       else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+       } else
+#endif
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
+       } else
+#endif
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outb(b, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+       } else
+#endif
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+
+       delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outw(w, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_USB)
+         if (port >= 0x340 && port < 0x3a0)
+               *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+       else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+       } else
+#endif
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+
+       delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_insb(PORT2ADDR_NE(port), addr, count);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+         else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+       }
+#endif
+       else {
+               unsigned char *buf = addr;
+               unsigned char *portp = PORT2ADDR(port);
+               while(count--) *buf++ = *(volatile unsigned char *)portp;
+       }
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               portp = PORT2ADDR_NE(port);
+               while (count--) *buf++ = *(volatile unsigned short *)portp;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while (count--) *buf++ = *(volatile unsigned short *)portp;
+       }
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned long *buf = addr;
+       unsigned long *portp;
+
+       portp = PORT2ADDR(port);
+       while (count--) *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned char *buf = addr;
+       unsigned char *portp;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               portp = PORT2ADDR_NE(port);
+               while (count--) _ne_outb(*buf++, portp);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while(count--) *(volatile unsigned char *)portp = *buf++;
+       }
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               portp = PORT2ADDR_NE(port);
+               while (count--) *(volatile unsigned short *)portp = *buf++;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while(count--) *(volatile unsigned short *)portp = *buf++;
+       }
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned long *buf = addr;
+       unsigned char *portp;
+
+       portp = PORT2ADDR(port);
+       while(count--) *(volatile unsigned long *)portp = *buf++;
+}
diff --git a/arch/m32r/kernel/io_oaks32r.c b/arch/m32r/kernel/io_oaks32r.c
new file mode 100644 (file)
index 0000000..7fcbf20
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ *  linux/arch/m32r/kernel/io_oaks32r.c
+ *
+ *  Typical I/O routines for OAKS32R board.
+ *
+ *  Copyright (c) 2001-2004  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+
+#define PORT2ADDR(port)  _port2addr(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET);
+}
+
+static __inline__  void *_port2addr_ne(unsigned long port)
+{
+       return (void *)((port<<1) + NONCACHE_OFFSET + 0x02000000);
+}
+
+static __inline__ void delay(void)
+{
+       __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+#define PORT2ADDR_NE(port)  _port2addr_ne(port)
+
+static __inline__ unsigned char _ne_inb(void *portp)
+{
+       return *(volatile unsigned char *)(portp+1);
+}
+
+static __inline__ unsigned short _ne_inw(void *portp)
+{
+       unsigned short tmp;
+
+       tmp = *(unsigned short *)(portp) & 0xff;
+       tmp |= *(unsigned short *)(portp+2) << 8;
+       return tmp;
+}
+
+static __inline__  void _ne_insb(void *portp, void * addr, unsigned long count)
+{
+       unsigned char *buf = addr;
+       while (count--) *buf++ = *(volatile unsigned char *)(portp+1);
+}
+
+static __inline__ void _ne_outb(unsigned char b, void *portp)
+{
+       *(volatile unsigned char *)(portp+1) = b;
+}
+
+static __inline__ void _ne_outw(unsigned short w, void *portp)
+{
+  *(volatile unsigned short *)portp =  (w >> 8);
+  *(volatile unsigned short *)(portp+2) =  (w & 0xff);
+}
+
+unsigned char _inb(unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               return _ne_inb(PORT2ADDR_NE(port));
+
+       return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               return _ne_inw(PORT2ADDR_NE(port));
+
+       return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+       return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+       unsigned char  v;
+
+       if (port >= 0x300 && port < 0x320)
+               v = _ne_inb(PORT2ADDR_NE(port));
+       else
+               v = *(volatile unsigned char *)PORT2ADDR(port);
+
+       delay();
+       return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+       unsigned short  v;
+
+       if (port >= 0x300 && port < 0x320)
+               v = _ne_inw(PORT2ADDR_NE(port));
+       else
+               v = *(volatile unsigned short *)PORT2ADDR(port);
+
+       delay();
+       return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+       unsigned long  v;
+
+       v = *(volatile unsigned long *)PORT2ADDR(port);
+       delay();
+       return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               _ne_outb(b, PORT2ADDR_NE(port));
+       else
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               _ne_outw(w, PORT2ADDR_NE(port));
+       else
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               _ne_outb(b, PORT2ADDR_NE(port));
+       else
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+
+       delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+       if (port >= 0x300 && port < 0x320)
+               _ne_outw(w, PORT2ADDR_NE(port));
+       else
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+
+       delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+       if (port >= 0x300 && port < 0x320)
+               _ne_insb(PORT2ADDR_NE(port), addr, count);
+       else {
+               unsigned char *buf = addr;
+               unsigned char *portp = PORT2ADDR(port);
+               while(count--) *buf++ = *(volatile unsigned char *)portp;
+       }
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= 0x300 && port < 0x320) {
+               portp = PORT2ADDR_NE(port);
+               while (count--) *buf++ = _ne_inw(portp);
+       } else {
+               portp = PORT2ADDR(port);
+               while (count--) *buf++ = *(volatile unsigned short *)portp;
+       }
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned long *buf = addr;
+       unsigned long *portp;
+
+       portp = PORT2ADDR(port);
+       while (count--) *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned char *buf = addr;
+       unsigned char *portp;
+
+       if (port >= 0x300 && port < 0x320) {
+               portp = PORT2ADDR_NE(port);
+               while (count--) _ne_outb(*buf++, portp);
+       } else {
+               portp = PORT2ADDR(port);
+               while(count--) *(volatile unsigned char *)portp = *buf++;
+       }
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= 0x300 && port < 0x320) {
+               portp = PORT2ADDR_NE(port);
+               while (count--) _ne_outw(*buf++, portp);
+       } else {
+               portp = PORT2ADDR(port);
+               while(count--) *(volatile unsigned short *)portp = *buf++;
+       }
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned long *buf = addr;
+       unsigned char *portp;
+
+       portp = PORT2ADDR(port);
+       while(count--) *(volatile unsigned long *)portp = *buf++;
+}
diff --git a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c
new file mode 100644 (file)
index 0000000..642376e
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ *  linux/arch/m32r/kernel/io_mappi.c
+ *
+ *  Typical I/O routines for OPSPUT board.
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Takeo Takahashi
+ *
+ *  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/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0   (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
+#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
+
+#define PORT2ADDR(port)  _port2addr(port)
+#define PORT2ADDR_USB(port) _port2addr_usb(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET);
+}
+
+/*
+ * OPSPUT-LAN is located in the extended bus space
+ * from 0x10000000 to 0x13ffffff on physical address.
+ * The base address of LAN controller(LAN91C111) is 0x300.
+ */
+#define LAN_IOSTART    0x300
+#define LAN_IOEND      0x320
+static __inline__ void *_port2addr_ne(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+}
+static __inline__ void *_port2addr_usb(unsigned long port)
+{
+  return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000);
+}
+
+static __inline__ void delay(void)
+{
+       __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+#define PORT2ADDR_NE(port)  _port2addr_ne(port)
+
+static __inline__ unsigned char _ne_inb(void *portp)
+{
+       return *(volatile unsigned char *)portp;
+}
+
+static __inline__ unsigned short _ne_inw(void *portp)
+{
+       return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
+}
+
+static __inline__ void _ne_insb(void *portp, void * addr, unsigned long count)
+{
+       unsigned char *buf = (unsigned char *)addr;
+
+       while (count--) *buf++ = _ne_inb(portp);
+}
+
+static __inline__ void _ne_outb(unsigned char b, void *portp)
+{
+       *(volatile unsigned char *)portp = b;
+}
+
+static __inline__ void _ne_outw(unsigned short w, void *portp)
+{
+       *(volatile unsigned short *)portp = cpu_to_le16(w);
+}
+
+unsigned char _inb(unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               return _ne_inb(PORT2ADDR_NE(port));
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned char b;
+          pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+          return b;
+       } else
+#endif
+
+       return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               return _ne_inw(PORT2ADDR_NE(port));
+#if defined(CONFIG_USB)
+       else if(port >= 0x340 && port < 0x3a0)
+         return *(volatile unsigned short *)PORT2ADDR_USB(port);
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+         else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned short w;
+          pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+          return w;
+       } else
+#endif
+       return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned long l;
+          pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
+          return l;
+       } else
+#endif
+       return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+       unsigned char  v;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               v = _ne_inb(PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned char b;
+          pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+          return b;
+       } else
+#endif
+               v = *(volatile unsigned char *)PORT2ADDR(port);
+
+       delay();
+       return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+       unsigned short  v;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               v = _ne_inw(PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_USB)
+         if(port >= 0x340 && port < 0x3a0)
+           return *(volatile unsigned short *)PORT2ADDR_USB(port);
+       else
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          unsigned short w;
+          pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+          return w;
+       } else
+#endif
+               v = *(volatile unsigned short *)PORT2ADDR(port);
+
+       delay();
+       return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+       unsigned long  v;
+
+       v = *(volatile unsigned long *)PORT2ADDR(port);
+       delay();
+       return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outb(b, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+       } else
+#endif
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outw(w, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_USB)
+       if(port >= 0x340 && port < 0x3a0)
+         *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+       else
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+       } else
+#endif
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
+       } else
+#endif
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outb(b, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+       } else
+#endif
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+
+       delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_outw(w, PORT2ADDR_NE(port));
+       else
+#if defined(CONFIG_USB)
+         if(port >= 0x340 && port < 0x3a0)
+           *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+       else
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+       } else
+#endif
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+
+       delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+       if (port >= LAN_IOSTART && port < LAN_IOEND)
+               _ne_insb(PORT2ADDR_NE(port), addr, count);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+         else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+       }
+#endif
+       else {
+               unsigned char *buf = addr;
+               unsigned char *portp = PORT2ADDR(port);
+               while(count--) *buf++ = *(volatile unsigned char *)portp;
+       }
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND) {
+               /*
+                * This portion is only used by smc91111.c to read data
+                * from the DATA_REG. Do not swap the data.
+                */
+               portp = PORT2ADDR_NE(port);
+               while (count--) *buf++ = *(volatile unsigned short *)portp;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while (count--) *buf++ = *(volatile unsigned short *)portp;
+       }
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned long *buf = addr;
+       unsigned long *portp;
+
+       portp = PORT2ADDR(port);
+       while (count--) *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned char *buf = addr;
+       unsigned char *portp;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND) {
+               portp = PORT2ADDR_NE(port);
+               while (count--) _ne_outb(*buf++, portp);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while(count--) *(volatile unsigned char *)portp = *buf++;
+       }
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND) {
+               /*
+                * This portion is only used by smc91111.c to write data
+                * into the DATA_REG. Do not swap the data.
+                */
+               portp = PORT2ADDR_NE(port);
+               while(count--) *(volatile unsigned short *)portp = *buf++;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+       } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+          pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while(count--) *(volatile unsigned short *)portp = *buf++;
+       }
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned long *buf = addr;
+       unsigned char *portp;
+
+       portp = PORT2ADDR(port);
+       while(count--) *(volatile unsigned long *)portp = *buf++;
+}
diff --git a/arch/m32r/kernel/io_usrv.c b/arch/m32r/kernel/io_usrv.c
new file mode 100644 (file)
index 0000000..cc77ced
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ *  linux/arch/m32r/kernel/io_usrv.c
+ *
+ *  Typical I/O routines for uServer board.
+ *
+ *  Copyright (c) 2001 - 2003  Hiroyuki Kondo, Hirokazu Takata,
+ *                             Hitoshi Yamamoto, Takeo Takahashi
+ *
+ *  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/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+
+#include <linux/types.h>
+#include "../drivers/m32r_cfc.h"
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
+#define CFC_IOSTART    CFC_IOPORT_BASE
+#define CFC_IOEND      (CFC_IOSTART + (M32R_PCC_MAPSIZE * M32R_MAX_PCC) - 1)
+
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+#define UART0_REGSTART         0x04c20000
+#define UART1_REGSTART         0x04c20100
+#define UART_IOMAP_SIZE                8
+#define UART0_IOSTART          0x3f8
+#define UART0_IOEND            (UART0_IOSTART + UART_IOMAP_SIZE - 1)
+#define UART1_IOSTART          0x2f8
+#define UART1_IOEND            (UART1_IOSTART + UART_IOMAP_SIZE - 1)
+#endif /* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
+
+#define PORT2ADDR(port)        _port2addr(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+       if (port >= UART0_IOSTART && port <= UART0_IOEND)
+               port = ((port - UART0_IOSTART) << 1) + UART0_REGSTART;
+       else if (port >= UART1_IOSTART && port <= UART1_IOEND)
+               port = ((port - UART1_IOSTART) << 1) + UART1_REGSTART;
+#endif /* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
+       return (void *)(port + NONCACHE_OFFSET);
+}
+
+static __inline__ void delay(void)
+{
+       __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+unsigned char _inb(unsigned long port)
+{
+       if (port >= CFC_IOSTART && port <= CFC_IOEND) {
+               unsigned char b;
+               pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+               return b;
+       } else
+               return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+       if (port >= CFC_IOSTART && port <= CFC_IOEND) {
+               unsigned short w;
+               pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+               return w;
+       } else
+               return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+       if (port >= CFC_IOSTART && port <= CFC_IOEND) {
+               unsigned long l;
+               pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
+               return l;
+       } else
+               return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+       unsigned char b;
+
+       if (port >= CFC_IOSTART && port <= CFC_IOEND) {
+               pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+               return b;
+       } else {
+               b = *(volatile unsigned char *)PORT2ADDR(port);
+               delay();
+               return b;
+       }
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+       unsigned short w;
+
+       if (port >= CFC_IOSTART && port <= CFC_IOEND) {
+               pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+               return w;
+       } else {
+               w = *(volatile unsigned short *)PORT2ADDR(port);
+               delay();
+               return w;
+       }
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+       unsigned long v;
+
+       v = *(volatile unsigned long *)PORT2ADDR(port);
+       delay();
+
+       return v;
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+       if (port >= CFC_IOSTART && port <= CFC_IOEND)
+               pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+       else
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+       if (port >= CFC_IOSTART && port <= CFC_IOEND)
+               pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+       else
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+       if (port >= CFC_IOSTART && port <= CFC_IOEND)
+               pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
+       else
+               *(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+       if (port >= CFC_IOSTART && port <= CFC_IOEND)
+               pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+       else
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+       delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+       if (port >= CFC_IOSTART && port <= CFC_IOEND)
+               pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+       else
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+       delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+       if (port >= CFC_IOSTART && port <= CFC_IOEND)
+               pcc_ioread_byte(0, port, addr, sizeof(unsigned char), count, 1);
+       else {
+               unsigned char *buf = addr;
+               unsigned char *portp = PORT2ADDR(port);
+               while(count--) *buf++ = *(volatile unsigned char *)portp;
+       }
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= CFC_IOSTART && port <= CFC_IOEND)
+               pcc_ioread_word(0, port, addr, sizeof(unsigned short), count,
+                       1);
+       else {
+               portp = PORT2ADDR(port);
+               while (count--) *buf++ = *(volatile unsigned short *)portp;
+       }
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned long *buf = addr;
+       unsigned long *portp;
+
+       portp = PORT2ADDR(port);
+       while (count--)
+               *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned char *buf = addr;
+       unsigned char *portp;
+
+       if (port >= CFC_IOSTART && port <= CFC_IOEND)
+               pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
+                       count, 1);
+       else {
+               portp = PORT2ADDR(port);
+               while (count--)
+                       *(volatile unsigned char *)portp = *buf++;
+       }
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= CFC_IOSTART && port <= CFC_IOEND)
+               pcc_iowrite_word(0, port, (void *)addr, sizeof(unsigned short),
+                       count, 1);
+       else {
+               portp = PORT2ADDR(port);
+               while (count--)
+                       *(volatile unsigned short *)portp = *buf++;
+       }
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+       const unsigned long *buf = addr;
+       unsigned char *portp;
+
+       portp = PORT2ADDR(port);
+       while (count--)
+               *(volatile unsigned long *)portp = *buf++;
+}
diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c
new file mode 100644 (file)
index 0000000..ba13577
--- /dev/null
@@ -0,0 +1,1020 @@
+/*
+ * linux/arch/m32r/kernel/irq.c
+ *
+ *  Copyright (c) 2003, 2004 Hitoshi Yamamoto
+ *
+ *  Taken from i386 2.6.4 version.
+ */
+
+/*
+ *     linux/arch/i386/kernel/irq.c
+ *
+ *     Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ * This file contains the code used by various IRQ handling routines:
+ * asking for different IRQ's should be done through these routines
+ * instead of just grabbing them. Thus setups with different IRQ numbers
+ * shouldn't result in any weird surprises, and installing new handlers
+ * should be easier.
+ */
+
+/*
+ * (mostly architecture independent, will move to kernel/irq.c in 2.5.)
+ *
+ * IRQs are in fact implemented a bit like signal handlers for the kernel.
+ * Naturally it's not a 1:1 relation, but there are similarities.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/irq.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+#include <asm/irq.h>
+
+/*
+ * Linux has a controller-independent x86 interrupt architecture.
+ * every controller has a 'controller-template', that is used
+ * by the main code to do the right thing. Each driver-visible
+ * interrupt source is transparently wired to the apropriate
+ * controller. Thus drivers need not be aware of the
+ * interrupt-controller.
+ *
+ * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
+ * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
+ * (IO-APICs assumed to be messaging to Pentium local-APICs)
+ *
+ * the code is designed to be easily extended with new/different
+ * interrupt controllers, without having to do assembly magic.
+ */
+
+/*
+ * Controller mappings for all interrupt sources:
+ */
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
+       [0 ... NR_IRQS-1] = {
+               .handler = &no_irq_type,
+               .lock = SPIN_LOCK_UNLOCKED
+       }
+};
+
+static void register_irq_proc (unsigned int irq);
+
+/*
+ * Special irq handlers.
+ */
+
+irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{ return IRQ_NONE; }
+
+/*
+ * Generic no controller code
+ */
+
+static void enable_none(unsigned int irq) { }
+static unsigned int startup_none(unsigned int irq) { return 0; }
+static void disable_none(unsigned int irq) { }
+static void ack_none(unsigned int irq)
+{
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves, it doesn't deserve
+ * a generic callback i think.
+ */
+       printk("unexpected IRQ trap at vector %02x\n", irq);
+}
+
+/* startup is the same as "enable", shutdown is same as "disable" */
+#define shutdown_none  disable_none
+#define end_none       enable_none
+
+struct hw_interrupt_type no_irq_type = {
+       "none",
+       startup_none,
+       shutdown_none,
+       enable_none,
+       disable_none,
+       ack_none,
+       end_none
+};
+
+atomic_t irq_err_count;
+atomic_t irq_mis_count;
+
+/*
+ * Generic, controller-independent functions:
+ */
+
+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_printf(p, "           ");
+               for (j=0; j<NR_CPUS; j++)
+                       if (cpu_online(j))
+                               seq_printf(p, "CPU%d       ",j);
+               seq_putc(p, '\n');
+       }
+
+       if (i < NR_IRQS) {
+               spin_lock_irqsave(&irq_desc[i].lock, flags);
+               action = irq_desc[i].action;
+               if (!action)
+                       goto skip;
+               seq_printf(p, "%3d: ",i);
+#ifndef CONFIG_SMP
+               seq_printf(p, "%10u ", kstat_irqs(i));
+#else
+               for (j = 0; j < NR_CPUS; j++)
+                       if (cpu_online(j))
+                               seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#endif
+               seq_printf(p, " %14s", irq_desc[i].handler->typename);
+               seq_printf(p, "  %s", action->name);
+
+               for (action=action->next; action; action = action->next)
+                       seq_printf(p, ", %s", action->name);
+
+               seq_putc(p, '\n');
+skip:
+               spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+       } else if (i == NR_IRQS) {
+               seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+               seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+       }
+       return 0;
+}
+
+#ifdef CONFIG_SMP
+inline void synchronize_irq(unsigned int irq)
+{
+       while (irq_desc[irq].status & IRQ_INPROGRESS)
+               cpu_relax();
+}
+#endif
+
+/*
+ * This should really return information about whether
+ * we should do bottom half handling etc. Right now we
+ * end up _always_ checking the bottom half, which is a
+ * waste of time and is not what some drivers would
+ * prefer.
+ */
+int handle_IRQ_event(unsigned int irq,
+               struct pt_regs *regs, struct irqaction *action)
+{
+       int status = 1; /* Force the "do bottom halves" bit */
+       int ret, retval = 0;
+
+       if (!(action->flags & SA_INTERRUPT))
+               local_irq_enable();
+
+       do {
+               ret = action->handler(irq, action->dev_id, regs);
+               if (ret == IRQ_HANDLED)
+                       status |= action->flags;
+               action = action->next;
+               retval |= ret;
+       } while (action);
+       if (status & SA_SAMPLE_RANDOM)
+               add_interrupt_randomness(irq);
+       local_irq_disable();
+       return retval;
+}
+
+static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
+{
+       struct irqaction *action;
+
+       if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
+               printk(KERN_ERR "irq event %d: bogus return value %x\n",
+                               irq, action_ret);
+       } else {
+               printk(KERN_ERR "irq %d: nobody cared!\n", irq);
+       }
+       dump_stack();
+       printk(KERN_ERR "handlers:\n");
+       action = desc->action;
+       do {
+               printk(KERN_ERR "[<%p>]", action->handler);
+               print_symbol(" (%s)",
+                       (unsigned long)action->handler);
+               printk("\n");
+               action = action->next;
+       } while (action);
+}
+
+static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
+{
+       static int count = 100;
+
+       if (count) {
+               count--;
+               __report_bad_irq(irq, desc, action_ret);
+       }
+}
+
+static int noirqdebug;
+
+static int __init noirqdebug_setup(char *str)
+{
+       noirqdebug = 1;
+       printk("IRQ lockup detection disabled\n");
+       return 1;
+}
+
+__setup("noirqdebug", noirqdebug_setup);
+
+/*
+ * If 99,900 of the previous 100,000 interrupts have not been handled then
+ * assume that the IRQ is stuck in some manner.  Drop a diagnostic and try to
+ * turn the IRQ off.
+ *
+ * (The other 100-of-100,000 interrupts may have been a correctly-functioning
+ *  device sharing an IRQ with the failing one)
+ *
+ * Called under desc->lock
+ */
+static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret)
+{
+       if (action_ret != IRQ_HANDLED) {
+               desc->irqs_unhandled++;
+               if (action_ret != IRQ_NONE)
+                       report_bad_irq(irq, desc, action_ret);
+       }
+
+       desc->irq_count++;
+       if (desc->irq_count < 100000)
+               return;
+
+       desc->irq_count = 0;
+       if (desc->irqs_unhandled > 99900) {
+               /*
+                * The interrupt is stuck
+                */
+               __report_bad_irq(irq, desc, action_ret);
+               /*
+                * Now kill the IRQ
+                */
+               printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
+               desc->status |= IRQ_DISABLED;
+               desc->handler->disable(irq);
+       }
+       desc->irqs_unhandled = 0;
+}
+
+/*
+ * Generic enable/disable code: this just calls
+ * down into the PIC-specific version for the actual
+ * hardware disable after having gotten the irq
+ * controller lock.
+ */
+
+/**
+ *     disable_irq_nosync - disable an irq without waiting
+ *     @irq: Interrupt to disable
+ *
+ *     Disable the selected interrupt line.  Disables and Enables are
+ *     nested.
+ *     Unlike disable_irq(), this function does not ensure existing
+ *     instances of the IRQ handler have completed before returning.
+ *
+ *     This function may be called from IRQ context.
+ */
+
+inline void disable_irq_nosync(unsigned int irq)
+{
+       irq_desc_t *desc = irq_desc + irq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&desc->lock, flags);
+       if (!desc->depth++) {
+               desc->status |= IRQ_DISABLED;
+               desc->handler->disable(irq);
+       }
+       spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+/**
+ *     disable_irq - disable an irq and wait for completion
+ *     @irq: Interrupt to disable
+ *
+ *     Disable the selected interrupt line.  Enables and Disables are
+ *     nested.
+ *     This function waits for any pending IRQ handlers for this interrupt
+ *     to complete before returning. If you use this function while
+ *     holding a resource the IRQ handler may need you will deadlock.
+ *
+ *     This function may be called - with care - from IRQ context.
+ */
+
+void disable_irq(unsigned int irq)
+{
+       irq_desc_t *desc = irq_desc + irq;
+       disable_irq_nosync(irq);
+       if (desc->action)
+               synchronize_irq(irq);
+}
+
+/**
+ *     enable_irq - enable handling of an irq
+ *     @irq: Interrupt to enable
+ *
+ *     Undoes the effect of one call to disable_irq().  If this
+ *     matches the last disable, processing of interrupts on this
+ *     IRQ line is re-enabled.
+ *
+ *     This function may be called from IRQ context.
+ */
+
+void enable_irq(unsigned int irq)
+{
+       irq_desc_t *desc = irq_desc + irq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&desc->lock, flags);
+       switch (desc->depth) {
+       case 1: {
+               unsigned int status = desc->status & ~IRQ_DISABLED;
+               desc->status = status;
+               if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+                       desc->status = status | IRQ_REPLAY;
+                       hw_resend_irq(desc->handler,irq);
+               }
+               desc->handler->enable(irq);
+               /* fall-through */
+       }
+       default:
+               desc->depth--;
+               break;
+       case 0:
+               printk("enable_irq(%u) unbalanced from %p\n", irq,
+                      __builtin_return_address(0));
+       }
+       spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs)
+{
+       /*
+        * We ack quickly, we don't want the irq controller
+        * thinking we're snobs just because some other CPU has
+        * disabled global interrupts (we have already done the
+        * INT_ACK cycles, it's too late to try to pretend to the
+        * controller that we aren't taking the interrupt).
+        *
+        * 0 return value means that this irq is already being
+        * handled by some other CPU. (or is disabled)
+        */
+       irq_desc_t *desc = irq_desc + irq;
+       struct irqaction * action;
+       unsigned int status;
+
+       irq_enter();
+
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+       /* FIXME M32R */
+#endif
+       kstat_this_cpu.irqs[irq]++;
+       spin_lock(&desc->lock);
+       desc->handler->ack(irq);
+       /*
+          REPLAY is when Linux resends an IRQ that was dropped earlier
+          WAITING is used by probe to mark irqs that are being tested
+          */
+       status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
+       status |= IRQ_PENDING; /* we _want_ to handle it */
+
+       /*
+        * If the IRQ is disabled for whatever reason, we cannot
+        * use the action we have.
+        */
+       action = NULL;
+       if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
+               action = desc->action;
+               status &= ~IRQ_PENDING; /* we commit to handling */
+               status |= IRQ_INPROGRESS; /* we are handling it */
+       }
+       desc->status = status;
+
+       /*
+        * If there is no IRQ handler or it was disabled, exit early.
+          Since we set PENDING, if another processor is handling
+          a different instance of this same irq, the other processor
+          will take care of it.
+        */
+       if (unlikely(!action))
+               goto out;
+
+       /*
+        * Edge triggered interrupts need to remember
+        * pending events.
+        * This applies to any hw interrupts that allow a second
+        * instance of the same irq to arrive while we are in do_IRQ
+        * or in the handler. But the code here only handles the _second_
+        * instance of the irq, not the third or fourth. So it is mostly
+        * useful for irq hardware that does not mask cleanly in an
+        * SMP environment.
+        */
+       for (;;) {
+               irqreturn_t action_ret;
+
+               spin_unlock(&desc->lock);
+               action_ret = handle_IRQ_event(irq, regs, action);
+               spin_lock(&desc->lock);
+               if (!noirqdebug)
+                       note_interrupt(irq, desc, action_ret);
+               if (likely(!(desc->status & IRQ_PENDING)))
+                       break;
+               desc->status &= ~IRQ_PENDING;
+       }
+       desc->status &= ~IRQ_INPROGRESS;
+
+out:
+       /*
+        * The ->end() handler has to deal with interrupts which got
+        * disabled while the handler was running.
+        */
+       desc->handler->end(irq);
+       spin_unlock(&desc->lock);
+
+       irq_exit();
+
+#if defined(CONFIG_SMP)
+       if (irq == M32R_IRQ_MFT2)
+               smp_send_timer();
+#endif /* CONFIG_SMP */
+
+       return 1;
+}
+
+int can_request_irq(unsigned int irq, unsigned long irqflags)
+{
+       struct irqaction *action;
+
+       if (irq >= NR_IRQS)
+               return 0;
+       action = irq_desc[irq].action;
+       if (action) {
+               if (irqflags & action->flags & SA_SHIRQ)
+                       action = NULL;
+       }
+       return !action;
+}
+
+/**
+ *     request_irq - allocate an interrupt line
+ *     @irq: Interrupt line to allocate
+ *     @handler: Function to be called when the IRQ occurs
+ *     @irqflags: Interrupt type flags
+ *     @devname: An ascii name for the claiming device
+ *     @dev_id: A cookie passed back to the handler function
+ *
+ *     This call allocates interrupt resources and enables the
+ *     interrupt line and IRQ handling. From the point this
+ *     call is made your handler function may be invoked. Since
+ *     your handler function must clear any interrupt the board
+ *     raises, you must take care both to initialise your hardware
+ *     and to set up the interrupt handler in the right order.
+ *
+ *     Dev_id must be globally unique. Normally the address of the
+ *     device data structure is used as the cookie. Since the handler
+ *     receives this value it makes sense to use it.
+ *
+ *     If your interrupt is shared you must pass a non NULL dev_id
+ *     as this is required when freeing the interrupt.
+ *
+ *     Flags:
+ *
+ *     SA_SHIRQ                Interrupt is shared
+ *
+ *     SA_INTERRUPT            Disable local interrupts while processing
+ *
+ *     SA_SAMPLE_RANDOM        The interrupt can be used for entropy
+ *
+ */
+
+int request_irq(unsigned int irq,
+               irqreturn_t (*handler)(int, void *, struct pt_regs *),
+               unsigned long irqflags,
+               const char * devname,
+               void *dev_id)
+{
+       int retval;
+       struct irqaction * action;
+
+#if 1
+       /*
+        * Sanity-check: shared interrupts should REALLY pass in
+        * a real dev-ID, otherwise we'll have trouble later trying
+        * to figure out which interrupt is which (messes up the
+        * interrupt freeing logic etc).
+        */
+       if (irqflags & SA_SHIRQ) {
+               if (!dev_id)
+                       printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
+       }
+#endif
+
+       if (irq >= NR_IRQS)
+               return -EINVAL;
+       if (!handler)
+               return -EINVAL;
+
+       action = (struct irqaction *)
+                       kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
+       if (!action)
+               return -ENOMEM;
+
+       action->handler = handler;
+       action->flags = irqflags;
+       cpus_clear(action->mask);
+       action->name = devname;
+       action->next = NULL;
+       action->dev_id = dev_id;
+
+       retval = setup_irq(irq, action);
+       if (retval)
+               kfree(action);
+       return retval;
+}
+
+EXPORT_SYMBOL(request_irq);
+
+/**
+ *     free_irq - free an interrupt
+ *     @irq: Interrupt line to free
+ *     @dev_id: Device identity to free
+ *
+ *     Remove an interrupt handler. The handler is removed and if the
+ *     interrupt line is no longer in use by any driver it is disabled.
+ *     On a shared IRQ the caller must ensure the interrupt is disabled
+ *     on the card it drives before calling this function. The function
+ *     does not return until any executing interrupts for this IRQ
+ *     have completed.
+ *
+ *     This function must not be called from interrupt context.
+ */
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+       irq_desc_t *desc;
+       struct irqaction **p;
+       unsigned long flags;
+
+       if (irq >= NR_IRQS)
+               return;
+
+       desc = irq_desc + irq;
+       spin_lock_irqsave(&desc->lock,flags);
+       p = &desc->action;
+       for (;;) {
+               struct irqaction * action = *p;
+               if (action) {
+                       struct irqaction **pp = p;
+                       p = &action->next;
+                       if (action->dev_id != dev_id)
+                               continue;
+
+                       /* Found it - now remove it from the list of entries */
+                       *pp = action->next;
+                       if (!desc->action) {
+                               desc->status |= IRQ_DISABLED;
+                               desc->handler->shutdown(irq);
+                       }
+                       spin_unlock_irqrestore(&desc->lock,flags);
+
+                       /* Wait to make sure it's not being used on another CPU */
+                       synchronize_irq(irq);
+                       kfree(action);
+                       return;
+               }
+               printk("Trying to free free IRQ%d\n",irq);
+               spin_unlock_irqrestore(&desc->lock,flags);
+               return;
+       }
+}
+
+EXPORT_SYMBOL(free_irq);
+
+/*
+ * IRQ autodetection code..
+ *
+ * This depends on the fact that any interrupt that
+ * comes in on to an unassigned handler will get stuck
+ * with "IRQ_WAITING" cleared and the interrupt
+ * disabled.
+ */
+
+static DECLARE_MUTEX(probe_sem);
+
+/**
+ *     probe_irq_on    - begin an interrupt autodetect
+ *
+ *     Commence probing for an interrupt. The interrupts are scanned
+ *     and a mask of potential interrupt lines is returned.
+ *
+ */
+
+unsigned long probe_irq_on(void)
+{
+       unsigned int i;
+       irq_desc_t *desc;
+       unsigned long val;
+       unsigned long delay;
+
+       down(&probe_sem);
+       /*
+        * something may have generated an irq long ago and we want to
+        * flush such a longstanding irq before considering it as spurious.
+        */
+       for (i = NR_IRQS-1; i > 0; i--)  {
+               desc = irq_desc + i;
+
+               spin_lock_irq(&desc->lock);
+               if (!irq_desc[i].action)
+                       irq_desc[i].handler->startup(i);
+               spin_unlock_irq(&desc->lock);
+       }
+
+       /* Wait for longstanding interrupts to trigger. */
+       for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
+               /* about 20ms delay */ barrier();
+
+       /*
+        * enable any unassigned irqs
+        * (we must startup again here because if a longstanding irq
+        * happened in the previous stage, it may have masked itself)
+        */
+       for (i = NR_IRQS-1; i > 0; i--) {
+               desc = irq_desc + i;
+
+               spin_lock_irq(&desc->lock);
+               if (!desc->action) {
+                       desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
+                       if (desc->handler->startup(i))
+                               desc->status |= IRQ_PENDING;
+               }
+               spin_unlock_irq(&desc->lock);
+       }
+
+       /*
+        * Wait for spurious interrupts to trigger
+        */
+       for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
+               /* about 100ms delay */ barrier();
+
+       /*
+        * Now filter out any obviously spurious interrupts
+        */
+       val = 0;
+       for (i = 0; i < NR_IRQS; i++) {
+               irq_desc_t *desc = irq_desc + i;
+               unsigned int status;
+
+               spin_lock_irq(&desc->lock);
+               status = desc->status;
+
+               if (status & IRQ_AUTODETECT) {
+                       /* It triggered already - consider it spurious. */
+                       if (!(status & IRQ_WAITING)) {
+                               desc->status = status & ~IRQ_AUTODETECT;
+                               desc->handler->shutdown(i);
+                       } else
+                               if (i < 32)
+                                       val |= 1 << i;
+               }
+               spin_unlock_irq(&desc->lock);
+       }
+
+       return val;
+}
+
+EXPORT_SYMBOL(probe_irq_on);
+
+/*
+ * Return a mask of triggered interrupts (this
+ * can handle only legacy ISA interrupts).
+ */
+
+/**
+ *     probe_irq_mask - scan a bitmap of interrupt lines
+ *     @val:   mask of interrupts to consider
+ *
+ *     Scan the ISA bus interrupt lines and return a bitmap of
+ *     active interrupts. The interrupt probe logic state is then
+ *     returned to its previous value.
+ *
+ *     Note: we need to scan all the irq's even though we will
+ *     only return ISA irq numbers - just so that we reset them
+ *     all to a known state.
+ */
+unsigned int probe_irq_mask(unsigned long val)
+{
+       int i;
+       unsigned int mask;
+
+       mask = 0;
+       for (i = 0; i < NR_IRQS; i++) {
+               irq_desc_t *desc = irq_desc + i;
+               unsigned int status;
+
+               spin_lock_irq(&desc->lock);
+               status = desc->status;
+
+               if (status & IRQ_AUTODETECT) {
+                       if (i < 16 && !(status & IRQ_WAITING))
+                               mask |= 1 << i;
+
+                       desc->status = status & ~IRQ_AUTODETECT;
+                       desc->handler->shutdown(i);
+               }
+               spin_unlock_irq(&desc->lock);
+       }
+       up(&probe_sem);
+
+       return mask & val;
+}
+
+/*
+ * Return the one interrupt that triggered (this can
+ * handle any interrupt source).
+ */
+
+/**
+ *     probe_irq_off   - end an interrupt autodetect
+ *     @val: mask of potential interrupts (unused)
+ *
+ *     Scans the unused interrupt lines and returns the line which
+ *     appears to have triggered the interrupt. If no interrupt was
+ *     found then zero is returned. If more than one interrupt is
+ *     found then minus the first candidate is returned to indicate
+ *     their is doubt.
+ *
+ *     The interrupt probe logic state is returned to its previous
+ *     value.
+ *
+ *     BUGS: When used in a module (which arguably shouldnt happen)
+ *     nothing prevents two IRQ probe callers from overlapping. The
+ *     results of this are non-optimal.
+ */
+
+int probe_irq_off(unsigned long val)
+{
+       int i, irq_found, nr_irqs;
+
+       nr_irqs = 0;
+       irq_found = 0;
+       for (i = 0; i < NR_IRQS; i++) {
+               irq_desc_t *desc = irq_desc + i;
+               unsigned int status;
+
+               spin_lock_irq(&desc->lock);
+               status = desc->status;
+
+               if (status & IRQ_AUTODETECT) {
+                       if (!(status & IRQ_WAITING)) {
+                               if (!nr_irqs)
+                                       irq_found = i;
+                               nr_irqs++;
+                       }
+                       desc->status = status & ~IRQ_AUTODETECT;
+                       desc->handler->shutdown(i);
+               }
+               spin_unlock_irq(&desc->lock);
+       }
+       up(&probe_sem);
+
+       if (nr_irqs > 1)
+               irq_found = -irq_found;
+       return irq_found;
+}
+
+EXPORT_SYMBOL(probe_irq_off);
+
+/* this was setup_x86_irq but it seems pretty generic */
+int setup_irq(unsigned int irq, struct irqaction * new)
+{
+       int shared = 0;
+       unsigned long flags;
+       struct irqaction *old, **p;
+       irq_desc_t *desc = irq_desc + irq;
+
+       if (desc->handler == &no_irq_type)
+               return -ENOSYS;
+       /*
+        * Some drivers like serial.c use request_irq() heavily,
+        * so we have to be careful not to interfere with a
+        * running system.
+        */
+       if (new->flags & SA_SAMPLE_RANDOM) {
+               /*
+                * This function might sleep, we want to call it first,
+                * outside of the atomic block.
+                * Yes, this might clear the entropy pool if the wrong
+                * driver is attempted to be loaded, without actually
+                * installing a new handler, but is this really a problem,
+                * only the sysadmin is able to do this.
+                */
+               rand_initialize_irq(irq);
+       }
+
+       /*
+        * The following block of code has to be executed atomically
+        */
+       spin_lock_irqsave(&desc->lock,flags);
+       p = &desc->action;
+       if ((old = *p) != NULL) {
+               /* Can't share interrupts unless both agree to */
+               if (!(old->flags & new->flags & SA_SHIRQ)) {
+                       spin_unlock_irqrestore(&desc->lock,flags);
+                       return -EBUSY;
+               }
+
+               /* add new interrupt at end of irq queue */
+               do {
+                       p = &old->next;
+                       old = *p;
+               } while (old);
+               shared = 1;
+       }
+
+       *p = new;
+
+       if (!shared) {
+               desc->depth = 0;
+               desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
+               desc->handler->startup(irq);
+       }
+       spin_unlock_irqrestore(&desc->lock,flags);
+
+       register_irq_proc(irq);
+       return 0;
+}
+
+static struct proc_dir_entry * root_irq_dir;
+static struct proc_dir_entry * irq_dir [NR_IRQS];
+
+#ifdef CONFIG_SMP
+
+static struct proc_dir_entry *smp_affinity_entry[NR_IRQS];
+
+cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
+
+static int irq_affinity_read_proc(char *page, char **start, off_t off,
+                       int count, int *eof, void *data)
+{
+       int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
+       if (count - len < 2)
+               return -EINVAL;
+       len += sprintf(page + len, "\n");
+       return len;
+}
+
+static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
+                                       unsigned long count, void *data)
+{
+       int irq = (long)data, full_count = count, err;
+       cpumask_t new_value, tmp;
+
+       if (!irq_desc[irq].handler->set_affinity)
+               return -EIO;
+
+       err = cpumask_parse(buffer, count, new_value);
+       if (err)
+               return err;
+
+       /*
+        * Do not allow disabling IRQs completely - it's a too easy
+        * way to make the system unusable accidentally :-) At least
+        * one online CPU still has to be targeted.
+        */
+       cpus_and(tmp, new_value, cpu_online_map);
+       if (cpus_empty(tmp))
+               return -EINVAL;
+
+       irq_affinity[irq] = new_value;
+       irq_desc[irq].handler->set_affinity(irq,
+                                       cpumask_of_cpu(first_cpu(new_value)));
+
+       return full_count;
+}
+
+#endif
+
+static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
+                       int count, int *eof, void *data)
+{
+       int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
+       if (count - len < 2)
+               return -EINVAL;
+       len += sprintf(page + len, "\n");
+       return len;
+}
+
+static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
+                                       unsigned long count, void *data)
+{
+       cpumask_t *mask = (cpumask_t *)data;
+       unsigned long full_count = count, err;
+       cpumask_t new_value;
+
+       err = cpumask_parse(buffer, count, new_value);
+       if (err)
+               return err;
+
+       *mask = new_value;
+       return full_count;
+}
+
+#define MAX_NAMELEN 10
+
+static void register_irq_proc (unsigned int irq)
+{
+       char name [MAX_NAMELEN];
+
+       if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
+                       irq_dir[irq])
+               return;
+
+       memset(name, 0, MAX_NAMELEN);
+       sprintf(name, "%d", irq);
+
+       /* create /proc/irq/1234 */
+       irq_dir[irq] = proc_mkdir(name, root_irq_dir);
+
+#ifdef CONFIG_SMP
+       {
+               struct proc_dir_entry *entry;
+
+               /* create /proc/irq/1234/smp_affinity */
+               entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
+
+               if (entry) {
+                       entry->nlink = 1;
+                       entry->data = (void *)(long)irq;
+                       entry->read_proc = irq_affinity_read_proc;
+                       entry->write_proc = irq_affinity_write_proc;
+               }
+
+               smp_affinity_entry[irq] = entry;
+       }
+#endif
+}
+
+unsigned long prof_cpu_mask = -1;
+
+void init_irq_proc (void)
+{
+       struct proc_dir_entry *entry;
+       int i;
+
+       /* create /proc/irq */
+       root_irq_dir = proc_mkdir("irq", NULL);
+
+       /* create /proc/irq/prof_cpu_mask */
+       entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
+
+       if (!entry)
+           return;
+
+       entry->nlink = 1;
+       entry->data = (void *)&prof_cpu_mask;
+       entry->read_proc = prof_cpu_mask_read_proc;
+       entry->write_proc = prof_cpu_mask_write_proc;
+
+       /*
+        * Create entries for all existing IRQs.
+        */
+       for (i = 0; i < NR_IRQS; i++)
+               register_irq_proc(i);
+}
+
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
new file mode 100644 (file)
index 0000000..f5aa076
--- /dev/null
@@ -0,0 +1,141 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+#include <linux/sched.h>
+#include <linux/in6.h>
+#include <linux/interrupt.h>
+#include <linux/smp_lock.h>
+#include <linux/string.h>
+
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/tlbflush.h>
+
+extern void dump_thread(struct pt_regs *, struct user *);
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
+extern struct drive_info_struct drive_info;
+EXPORT_SYMBOL(drive_info);
+#endif
+
+/* platform dependent support */
+EXPORT_SYMBOL(boot_cpu_data);
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(disable_irq_nosync);
+EXPORT_SYMBOL(kernel_thread);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down_trylock);
+
+/* Networking helper routines. */
+/* Delay loops */
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__delay);
+EXPORT_SYMBOL(__const_udelay);
+
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strstr);
+
+EXPORT_SYMBOL(strncpy_from_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(clear_user);
+EXPORT_SYMBOL(__clear_user);
+EXPORT_SYMBOL(__generic_copy_from_user);
+EXPORT_SYMBOL(__generic_copy_to_user);
+EXPORT_SYMBOL(strnlen_user);
+
+#ifdef CONFIG_SMP
+#ifdef CONFIG_CHIP_M32700_TS1
+extern void *dcache_dummy;
+EXPORT_SYMBOL(dcache_dummy);
+#endif
+EXPORT_SYMBOL(cpu_data);
+EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(cpu_callout_map);
+
+/* Global SMP stuff */
+EXPORT_SYMBOL(synchronize_irq);
+EXPORT_SYMBOL(smp_call_function);
+
+/* TLB flushing */
+EXPORT_SYMBOL(smp_flush_tlb_page);
+EXPORT_SYMBOL_GPL(smp_flush_tlb_all);
+#endif
+
+/* compiler generated symbol */
+extern void __ashldi3(void);
+extern void __ashrdi3(void);
+extern void __lshldi3(void);
+extern void __lshrdi3(void);
+extern void __muldi3(void);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__lshldi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__muldi3);
+
+/* memory and string operations */
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(memcpy);
+/* EXPORT_SYMBOL(memcpy_fromio); // not implement yet */
+/* EXPORT_SYMBOL(memcpy_toio); // not implement yet */
+EXPORT_SYMBOL(memset);
+/* EXPORT_SYMBOL(memset_io); // not implement yet */
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(copy_page);
+EXPORT_SYMBOL(clear_page);
+
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strncpy);
+
+EXPORT_SYMBOL(_inb);
+EXPORT_SYMBOL(_inw);
+EXPORT_SYMBOL(_inl);
+EXPORT_SYMBOL(_outb);
+EXPORT_SYMBOL(_outw);
+EXPORT_SYMBOL(_outl);
+EXPORT_SYMBOL(_inb_p);
+EXPORT_SYMBOL(_inw_p);
+EXPORT_SYMBOL(_inl_p);
+EXPORT_SYMBOL(_outb_p);
+EXPORT_SYMBOL(_outw_p);
+EXPORT_SYMBOL(_outl_p);
+EXPORT_SYMBOL(_insb);
+EXPORT_SYMBOL(_insw);
+EXPORT_SYMBOL(_insl);
+EXPORT_SYMBOL(_outsb);
+EXPORT_SYMBOL(_outsw);
+EXPORT_SYMBOL(_outsl);
+EXPORT_SYMBOL(_readb);
+EXPORT_SYMBOL(_readw);
+EXPORT_SYMBOL(_readl);
+EXPORT_SYMBOL(_writeb);
+EXPORT_SYMBOL(_writew);
+EXPORT_SYMBOL(_writel);
+
diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c
new file mode 100644 (file)
index 0000000..2d5c384
--- /dev/null
@@ -0,0 +1,253 @@
+/*  Kernel module help for M32R.
+
+    This program is free software; you can redistribute 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/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+       if (size == 0)
+               return NULL;
+       return vmalloc_exec(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+       vfree(module_region);
+       /* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+                             Elf_Shdr *sechdrs,
+                             char *secstrings,
+                             struct module *mod)
+{
+       return 0;
+}
+
+#define COPY_UNALIGNED_WORD(sw, tw, align) \
+{ \
+       void *__s = &(sw), *__t = &(tw); \
+       unsigned short *__s2 = __s, *__t2 =__t; \
+       unsigned char *__s1 = __s, *__t1 =__t; \
+       switch ((align)) \
+       { \
+       case 0: \
+               *(unsigned long *) __t = *(unsigned long *) __s; \
+               break; \
+       case 2: \
+               *__t2++ = *__s2++; \
+               *__t2 = *__s2; \
+               break; \
+       default: \
+               *__t1++ = *__s1++; \
+               *__t1++ = *__s1++; \
+               *__t1++ = *__s1++; \
+               *__t1 = *__s1; \
+               break; \
+       } \
+}
+
+#define COPY_UNALIGNED_HWORD(sw, tw, align) \
+  { \
+    void *__s = &(sw), *__t = &(tw); \
+    unsigned short *__s2 = __s, *__t2 =__t; \
+    unsigned char *__s1 = __s, *__t1 =__t; \
+    switch ((align)) \
+    { \
+    case 0: \
+      *__t2 = *__s2; \
+      break; \
+    default: \
+      *__t1++ = *__s1++; \
+      *__t1 = *__s1; \
+      break; \
+    } \
+  }
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+                  const char *strtab,
+                  unsigned int symindex,
+                  unsigned int relsec,
+                  struct module *me)
+{
+       unsigned int i;
+       Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+       Elf32_Sym *sym;
+       Elf32_Addr relocation;
+       uint32_t *location;
+       uint32_t value;
+       unsigned short *hlocation;
+       unsigned short hvalue;
+       int svalue;
+       int align;
+
+       DEBUGP("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 */
+               location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+                       + rel[i].r_offset;
+               /* 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);
+               relocation = sym->st_value + rel[i].r_addend;
+               align = (int)location & 3;
+
+               switch (ELF32_R_TYPE(rel[i].r_info)) {
+               case R_M32R_32_RELA:
+                       COPY_UNALIGNED_WORD (*location, value, align);
+                       value += relocation;
+                       COPY_UNALIGNED_WORD (value, *location, align);
+                       break;
+               case R_M32R_HI16_ULO_RELA:
+                       COPY_UNALIGNED_WORD (*location, value, align);
+                        relocation = (relocation >>16) & 0xffff;
+                       /* RELA must has 0 at relocation field. */
+                       value += relocation;
+                       COPY_UNALIGNED_WORD (value, *location, align);
+                       break;
+               case R_M32R_HI16_SLO_RELA:
+                       COPY_UNALIGNED_WORD (*location, value, align);
+                       if (relocation & 0x8000) relocation += 0x10000;
+                        relocation = (relocation >>16) & 0xffff;
+                       /* RELA must has 0 at relocation field. */
+                       value += relocation;
+                       COPY_UNALIGNED_WORD (value, *location, align);
+                       break;
+               case R_M32R_16_RELA:
+                       hlocation = (unsigned short *)location;
+                        relocation = relocation & 0xffff;
+                       /* RELA must has 0 at relocation field. */
+                       hvalue = relocation;
+                       COPY_UNALIGNED_WORD (hvalue, *hlocation, align);
+                       break;
+               case R_M32R_SDA16_RELA:
+               case R_M32R_LO16_RELA:
+                       COPY_UNALIGNED_WORD (*location, value, align);
+                        relocation = relocation & 0xffff;
+                       /* RELA must has 0 at relocation field. */
+                       value += relocation;
+                       COPY_UNALIGNED_WORD (value, *location, align);
+                       break;
+               case R_M32R_24_RELA:
+                       COPY_UNALIGNED_WORD (*location, value, align);
+                        relocation = relocation & 0xffffff;
+                       /* RELA must has 0 at relocation field. */
+                       value += relocation;
+                       COPY_UNALIGNED_WORD (value, *location, align);
+                       break;
+               case R_M32R_18_PCREL_RELA:
+                       relocation = (relocation - (Elf32_Addr) location);
+                       if (relocation < -0x20000 || 0x1fffc < relocation)
+                               {
+                                       printk(KERN_ERR "module %s: relocation overflow: %u\n",
+                                       me->name, relocation);
+                                       return -ENOEXEC;
+                               }
+                       COPY_UNALIGNED_WORD (*location, value, align);
+                       if (value & 0xffff)
+                               {
+                                       /* RELA must has 0 at relocation field. */
+                                       printk(KERN_ERR "module %s: illegal relocation field: %u\n",
+                                       me->name, value);
+                                       return -ENOEXEC;
+                               }
+                        relocation = (relocation >> 2) & 0xffff;
+                       value += relocation;
+                       COPY_UNALIGNED_WORD (value, *location, align);
+                       break;
+               case R_M32R_10_PCREL_RELA:
+                       hlocation = (unsigned short *)location;
+                       relocation = (relocation - (Elf32_Addr) location);
+                       COPY_UNALIGNED_HWORD (*hlocation, hvalue, align);
+                       svalue = (int)hvalue;
+                       svalue = (signed char)svalue << 2;
+                       relocation += svalue;
+                        relocation = (relocation >> 2) & 0xff;
+                       hvalue = hvalue & 0xff00;
+                       hvalue += relocation;
+                       COPY_UNALIGNED_HWORD (hvalue, *hlocation, align);
+                       break;
+               case R_M32R_26_PCREL_RELA:
+                       relocation = (relocation - (Elf32_Addr) location);
+                       if (relocation < -0x2000000 || 0x1fffffc < relocation)
+                               {
+                                       printk(KERN_ERR "module %s: relocation overflow: %u\n",
+                                       me->name, relocation);
+                                       return -ENOEXEC;
+                               }
+                       COPY_UNALIGNED_WORD (*location, value, align);
+                       if (value & 0xffffff)
+                               {
+                                       /* RELA must has 0 at relocation field. */
+                                       printk(KERN_ERR "module %s: illegal relocation field: %u\n",
+                                       me->name, value);
+                                       return -ENOEXEC;
+                               }
+                        relocation = (relocation >> 2) & 0xffffff;
+                       value += relocation;
+                       COPY_UNALIGNED_WORD (value, *location, align);
+                       break;
+               default:
+                       printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+                              me->name, ELF32_R_TYPE(rel[i].r_info));
+                       return -ENOEXEC;
+               }
+       }
+       return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+                      const char *strtab,
+                      unsigned int symindex,
+                      unsigned int relsec,
+                      struct module *me)
+{
+#if 0
+       printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
+              me->name);
+       return -ENOEXEC;
+#endif
+       return 0;
+
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+                   const Elf_Shdr *sechdrs,
+                   struct module *me)
+{
+       return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
new file mode 100644 (file)
index 0000000..9e7de27
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ *  linux/arch/m32r/kernel/process.c
+ *    orig : sh
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ *  Taken from sh version.
+ *    Copyright (C) 1995  Linus Torvalds
+ *    SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
+ */
+
+#undef DEBUG_PROCESS
+#ifdef DEBUG_PROCESS
+#define DPRINTK(fmt, args...)  printk("%s:%d:%s: " fmt, __FILE__, __LINE__, \
+  __FUNCTION__, ##args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#include <linux/fs.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/hardirq.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/mmu_context.h>
+#include <asm/elf.h>
+#include <asm/m32r.h>
+
+#include <linux/err.h>
+
+static int hlt_counter=0;
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+       return tsk->thread.lr;
+}
+
+/*
+ * Powermanagement idle function, if any..
+ */
+void (*pm_idle)(void) = NULL;
+
+void disable_hlt(void)
+{
+       hlt_counter++;
+}
+
+EXPORT_SYMBOL(disable_hlt);
+
+void enable_hlt(void)
+{
+       hlt_counter--;
+}
+
+EXPORT_SYMBOL(enable_hlt);
+
+/*
+ * We use this is we don't have any better
+ * idle routine..
+ */
+void default_idle(void)
+{
+       /* M32R_FIXME: Please use "cpu_sleep" mode.  */
+       cpu_relax();
+}
+
+/*
+ * On SMP it's slightly faster (but much more power-consuming!)
+ * to poll the ->work.need_resched flag instead of waiting for the
+ * cross-CPU IPI to arrive. Use this option with caution.
+ */
+static void poll_idle (void)
+{
+       /* M32R_FIXME */
+       cpu_relax();
+}
+
+/*
+ * 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) {
+               while (!need_resched()) {
+                       void (*idle)(void) = pm_idle;
+
+                       if (!idle)
+                               idle = default_idle;
+
+                       idle();
+               }
+               schedule();
+       }
+}
+
+void machine_restart(char *__unused)
+{
+       printk("Please push reset button!\n");
+       while (1)
+               cpu_relax();
+}
+
+EXPORT_SYMBOL(machine_restart);
+
+void machine_halt(void)
+{
+       printk("Please push reset button!\n");
+       while (1)
+               cpu_relax();
+}
+
+EXPORT_SYMBOL(machine_halt);
+
+void machine_power_off(void)
+{
+       /* M32R_FIXME */
+}
+
+EXPORT_SYMBOL(machine_power_off);
+
+static int __init idle_setup (char *str)
+{
+       if (!strncmp(str, "poll", 4)) {
+               printk("using poll in idle threads.\n");
+               pm_idle = poll_idle;
+       } else if (!strncmp(str, "sleep", 4)) {
+               printk("using sleep in idle threads.\n");
+               pm_idle = default_idle;
+       }
+
+       return 1;
+}
+
+__setup("idle=", idle_setup);
+
+void show_regs(struct pt_regs * regs)
+{
+       printk("\n");
+       printk("BPC[%08lx]:PSW[%08lx]:LR [%08lx]:FP [%08lx]\n", \
+         regs->bpc, regs->psw, regs->lr, regs->fp);
+       printk("BBPC[%08lx]:BBPSW[%08lx]:SPU[%08lx]:SPI[%08lx]\n", \
+         regs->bbpc, regs->bbpsw, regs->spu, regs->spi);
+       printk("R0 [%08lx]:R1 [%08lx]:R2 [%08lx]:R3 [%08lx]\n", \
+         regs->r0, regs->r1, regs->r2, regs->r3);
+       printk("R4 [%08lx]:R5 [%08lx]:R6 [%08lx]:R7 [%08lx]\n", \
+         regs->r4, regs->r5, regs->r6, regs->r7);
+       printk("R8 [%08lx]:R9 [%08lx]:R10[%08lx]:R11[%08lx]\n", \
+         regs->r8, regs->r9, regs->r10, regs->r11);
+       printk("R12[%08lx]\n", \
+         regs->r12);
+
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+       printk("ACC0H[%08lx]:ACC0L[%08lx]\n", \
+         regs->acc0h, regs->acc0l);
+       printk("ACC1H[%08lx]:ACC1L[%08lx]\n", \
+         regs->acc1h, regs->acc1l);
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+       printk("ACCH[%08lx]:ACCL[%08lx]\n", \
+         regs->acch, regs->accl);
+#else
+#error unknown isa configuration
+#endif
+}
+
+/*
+ * Create a kernel thread
+ */
+
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ * NOTE! Only a kernel-only process(ie the swapper or direct descendants
+ * who haven't done an "execve()") should use this: it will work within
+ * a system call from a "real" process, but the process memory space will
+ * not be free'd until both the parent and the child have exited.
+ */
+static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg)
+{
+       fn(arg);
+       do_exit(-1);
+}
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+       struct pt_regs regs;
+
+       memset(&regs, 0, sizeof (regs));
+       regs.r1 = (unsigned long)fn;
+       regs.r2 = (unsigned long)arg;
+
+       regs.bpc = (unsigned long)kernel_thread_helper;
+
+       regs.psw = M32R_PSW_BIE;
+
+       /* Ok, create the new process. */
+       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
+               NULL);
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+       /* Nothing to do. */
+       DPRINTK("pid = %d\n", current->pid);
+}
+
+void flush_thread(void)
+{
+       DPRINTK("pid = %d\n", current->pid);
+       memset(&current->thread.debug_trap, 0, sizeof(struct debug_trap));
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+       /* do nothing */
+       DPRINTK("pid = %d\n", dead_task->pid);
+}
+
+/* Fill in the fpu structure for a core dump.. */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
+{
+       return 0; /* Task didn't use the fpu at all. */
+}
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long spu,
+       unsigned long unused, struct task_struct *tsk, struct pt_regs *regs)
+{
+       struct pt_regs *childregs;
+       unsigned long sp = (unsigned long)tsk->thread_info + THREAD_SIZE;
+       extern void ret_from_fork(void);
+
+       tsk->set_child_tid = tsk->clear_child_tid = NULL;
+
+       /* Copy registers */
+       sp -= sizeof (struct pt_regs);
+       childregs = (struct pt_regs *)sp;
+       *childregs = *regs;
+
+       childregs->spu = spu;
+       childregs->r0 = 0;      /* Child gets zero as return value */
+       regs->r0 = tsk->pid;
+       tsk->thread.sp = (unsigned long)childregs;
+       tsk->thread.lr = (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)
+{
+       /* M32R_FIXME */
+}
+
+/*
+ * Capture the user space registers if the task is not running (in user space)
+ */
+int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
+{
+       /* M32R_FIXME */
+       return 1;
+}
+
+asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2,
+       unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
+       struct pt_regs regs)
+{
+#ifdef CONFIG_MMU
+       return do_fork(SIGCHLD, regs.spu, &regs, 0, NULL, NULL);
+#else
+       return -EINVAL;
+#endif /* CONFIG_MMU */
+}
+
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+       unsigned long r2, unsigned long r3, unsigned long r4, unsigned long r5,
+       unsigned long r6, struct pt_regs regs)
+{
+       if (!newsp)
+               newsp = regs.spu;
+
+       return do_fork(clone_flags, newsp, &regs, 0, NULL, NULL);
+}
+
+/*
+ * This is trivial, and on the face of it looks like it
+ * could equally well be done in user mode.
+ *
+ * Not so, for quite unobvious reasons - register pressure.
+ * In user mode vfork() cannot have a stack frame, and if
+ * done by calling the "clone()" system call directly, you
+ * do not have enough call-clobbered registers to hold all
+ * the information you need.
+ */
+asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2,
+       unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
+       struct pt_regs regs)
+{
+       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, &regs, 0,
+                       NULL, NULL);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv, char __user * __user *uenvp,
+  unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
+  struct pt_regs regs)
+{
+       int error;
+       char *filename;
+
+       filename = getname(ufilename);
+       error = PTR_ERR(filename);
+       if (IS_ERR(filename))
+               goto out;
+
+       error = do_execve(filename, uargv, uenvp, &regs);
+       if (error == 0)
+               current->ptrace &= ~PT_DTRACE;
+       putname(filename);
+out:
+       return error;
+}
+
+/*
+ * These bracket the sleeping functions..
+ */
+#define first_sched    ((unsigned long) scheduling_functions_start_here)
+#define last_sched     ((unsigned long) scheduling_functions_end_here)
+
+unsigned long get_wchan(struct task_struct *p)
+{
+       /* M32R_FIXME */
+       return (0);
+}
+
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
new file mode 100644 (file)
index 0000000..ab4137a
--- /dev/null
@@ -0,0 +1,858 @@
+/*
+ * linux/arch/m32r/kernel/ptrace.c
+ *
+ * Copyright (C) 2002  Hirokazu Takata, Takeo Takahashi
+ * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ *
+ * Original x86 implementation:
+ *     By Ross Biro 1/23/92
+ *     edited by Linus Torvalds
+ *
+ * Some code taken from sh version:
+ *   Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
+ * Some code taken from arm version:
+ *   Copyright (C) 2000 Russell King
+ */
+
+#include <linux/config.h>
+#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/string.h>
+
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/mmu_context.h>
+
+/*
+ * 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));
+}
+
+/*
+ * This routine will get a word off of the process kernel stack.
+ */
+static inline unsigned long int
+get_stack_long(struct task_struct *task, int offset)
+{
+       unsigned long *stack;
+
+       stack = (unsigned long *)get_user_regs(task);
+
+       return stack[offset];
+}
+
+/*
+ * This routine will put a word on the process kernel stack.
+ */
+static inline int
+put_stack_long(struct task_struct *task, int offset, unsigned long data)
+{
+       unsigned long *stack;
+
+       stack = (unsigned long *)get_user_regs(task);
+       stack[offset] = data;
+
+       return 0;
+}
+
+static int reg_offset[] = {
+       PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
+       PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_FP, PT_LR, PT_SPU,
+};
+
+/*
+ * Read the word at offset "off" into the "struct user".  We
+ * actually access the pt_regs stored on the kernel stack.
+ */
+static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
+                           unsigned long __user *data)
+{
+       unsigned long tmp;
+#ifndef NO_FPU
+       struct user * dummy = NULL;
+#endif
+
+       if ((off & 3) || (off < 0) || (off > sizeof(struct user) - 3))
+               return -EIO;
+
+       off >>= 2;
+       switch (off) {
+       case PT_EVB:
+               __asm__ __volatile__ (
+                       "mvfc   %0, cr5 \n\t"
+                       : "=r" (tmp)
+               );
+               break;
+       case PT_CBR: {
+                       unsigned long psw;
+                       psw = get_stack_long(tsk, PT_PSW);
+                       tmp = ((psw >> 8) & 1);
+               }
+               break;
+       case PT_PSW: {
+                       unsigned long psw, bbpsw;
+                       psw = get_stack_long(tsk, PT_PSW);
+                       bbpsw = get_stack_long(tsk, PT_BBPSW);
+                       tmp = ((psw >> 8) & 0xff) | ((bbpsw & 0xff) << 8);
+               }
+               break;
+       case PT_PC:
+               tmp = get_stack_long(tsk, PT_BPC);
+               break;
+       case PT_BPC:
+               off = PT_BBPC;
+               /* fall through */
+       default:
+               if (off < (sizeof(struct pt_regs) >> 2))
+                       tmp = get_stack_long(tsk, off);
+#ifndef NO_FPU
+               else if (off >= (long)(&dummy->fpu >> 2) &&
+                        off < (long)(&dummy->u_fpvalid >> 2)) {
+                       if (!tsk->used_math) {
+                               if (off == (long)(&dummy->fpu.fpscr >> 2))
+                                       tmp = FPSCR_INIT;
+                               else
+                                       tmp = 0;
+                       } else
+                               tmp = ((long *)(&tsk->thread.fpu >> 2))
+                                       [off - (long)&dummy->fpu];
+               } else if (off == (long)(&dummy->u_fpvalid >> 2))
+                       tmp = tsk->used_math;
+#endif /* not NO_FPU */
+               else
+                       tmp = 0;
+       }
+
+       return put_user(tmp, data);
+}
+
+static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
+                            unsigned long data)
+{
+       int ret = -EIO;
+#ifndef NO_FPU
+       struct user * dummy = NULL;
+#endif
+
+       if ((off & 3) || off < 0 ||
+           off > sizeof(struct user) - 3)
+               return -EIO;
+
+       off >>= 2;
+       switch (off) {
+       case PT_EVB:
+       case PT_BPC:
+       case PT_SPI:
+               /* We don't allow to modify evb. */
+               ret = 0;
+               break;
+       case PT_PSW:
+       case PT_CBR: {
+                       /* We allow to modify only cbr in psw */
+                       unsigned long psw;
+                       psw = get_stack_long(tsk, PT_PSW);
+                       psw = (psw & ~0x100) | ((data & 1) << 8);
+                       ret = put_stack_long(tsk, PT_PSW, psw);
+               }
+               break;
+       case PT_PC:
+               off = PT_BPC;
+               data &= ~1;
+               /* fall through */
+       default:
+               if (off < (sizeof(struct pt_regs) >> 2))
+                       ret = put_stack_long(tsk, off, data);
+#ifndef NO_FPU
+               else if (off >= (long)(&dummy->fpu >> 2) &&
+                        off < (long)(&dummy->u_fpvalid >> 2)) {
+                       tsk->used_math = 1;
+                       ((long *)&tsk->thread.fpu)
+                               [off - (long)&dummy->fpu] = data;
+                       ret = 0;
+               } else if (off == (long)(&dummy->u_fpvalid >> 2)) {
+                       tsk->used_math = data ? 1 : 0;
+                       ret = 0;
+               }
+#endif /* not NO_FPU */
+               break;
+       }
+
+       return ret;
+}
+
+/*
+ * Get all user integer registers.
+ */
+static 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;
+}
+
+/*
+ * Set all user integer registers.
+ */
+static int ptrace_setregs(struct task_struct *tsk, void __user *uregs)
+{
+       struct pt_regs newregs;
+       int ret;
+
+       ret = -EFAULT;
+       if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
+               struct pt_regs *regs = get_user_regs(tsk);
+               *regs = newregs;
+               ret = 0;
+       }
+
+       return ret;
+}
+
+
+static inline int
+check_condition_bit(struct task_struct *child)
+{
+       return (int)((get_stack_long(child, PT_PSW) >> 8) & 1);
+}
+
+static int
+check_condition_src(unsigned long op, unsigned long regno1,
+                   unsigned long regno2, struct task_struct *child)
+{
+       unsigned long reg1, reg2;
+
+       reg2 = get_stack_long(child, reg_offset[regno2]);
+
+       switch (op) {
+       case 0x0: /* BEQ */
+               reg1 = get_stack_long(child, reg_offset[regno1]);
+               return reg1 == reg2;
+       case 0x1: /* BNE */
+               reg1 = get_stack_long(child, reg_offset[regno1]);
+               return reg1 != reg2;
+       case 0x8: /* BEQZ */
+               return reg2 == 0;
+       case 0x9: /* BNEZ */
+               return reg2 != 0;
+       case 0xa: /* BLTZ */
+               return (int)reg2 < 0;
+       case 0xb: /* BGEZ */
+               return (int)reg2 >= 0;
+       case 0xc: /* BLEZ */
+               return (int)reg2 <= 0;
+       case 0xd: /* BGTZ */
+               return (int)reg2 > 0;
+       default:
+               /* never reached */
+               return 0;
+       }
+}
+
+static void
+compute_next_pc_for_16bit_insn(unsigned long insn, unsigned long pc,
+                              unsigned long *next_pc,
+                              struct task_struct *child)
+{
+       unsigned long op, op2, op3;
+       unsigned long disp;
+       unsigned long regno;
+       int parallel = 0;
+
+       if (insn & 0x00008000)
+               parallel = 1;
+       if (pc & 3)
+               insn &= 0x7fff; /* right slot */
+       else
+               insn >>= 16;    /* left slot */
+
+       op = (insn >> 12) & 0xf;
+       op2 = (insn >> 8) & 0xf;
+       op3 = (insn >> 4) & 0xf;
+
+       if (op == 0x7) {
+               switch (op2) {
+               case 0xd: /* BNC */
+               case 0x9: /* BNCL */
+                       if (!check_condition_bit(child)) {
+                               disp = (long)(insn << 24) >> 22;
+                               *next_pc = (pc & ~0x3) + disp;
+                               return;
+                       }
+                       break;
+               case 0x8: /* BCL */
+               case 0xc: /* BC */
+                       if (check_condition_bit(child)) {
+                               disp = (long)(insn << 24) >> 22;
+                               *next_pc = (pc & ~0x3) + disp;
+                               return;
+                       }
+                       break;
+               case 0xe: /* BL */
+               case 0xf: /* BRA */
+                       disp = (long)(insn << 24) >> 22;
+                       *next_pc = (pc & ~0x3) + disp;
+                       return;
+                       break;
+               }
+       } else if (op == 0x1) {
+               switch (op2) {
+               case 0x0:
+                       if (op3 == 0xf) { /* TRAP */
+#if 1
+                               /* pass through */
+#else
+                               /* kernel space is not allowed as next_pc */
+                               unsigned long evb;
+                               unsigned long trapno;
+                               trapno = insn & 0xf;
+                               __asm__ __volatile__ (
+                                       "mvfc %0, cr5\n"
+                                       :"=r"(evb)
+                                       :
+                               );
+                               *next_pc = evb + (trapno << 2);
+                               return;
+#endif
+                       } else if (op3 == 0xd) { /* RTE */
+                               *next_pc = get_stack_long(child, PT_BPC);
+                               return;
+                       }
+                       break;
+               case 0xc: /* JC */
+                       if (op3 == 0xc && check_condition_bit(child)) {
+                               regno = insn & 0xf;
+                               *next_pc = get_stack_long(child,
+                                                         reg_offset[regno]);
+                               return;
+                       }
+                       break;
+               case 0xd: /* JNC */
+                       if (op3 == 0xc && !check_condition_bit(child)) {
+                               regno = insn & 0xf;
+                               *next_pc = get_stack_long(child,
+                                                         reg_offset[regno]);
+                               return;
+                       }
+                       break;
+               case 0xe: /* JL */
+               case 0xf: /* JMP */
+                       if (op3 == 0xc) { /* JMP */
+                               regno = insn & 0xf;
+                               *next_pc = get_stack_long(child,
+                                                         reg_offset[regno]);
+                               return;
+                       }
+                       break;
+               }
+       }
+       if (parallel)
+               *next_pc = pc + 4;
+       else
+               *next_pc = pc + 2;
+}
+
+static void
+compute_next_pc_for_32bit_insn(unsigned long insn, unsigned long pc,
+                              unsigned long *next_pc,
+                              struct task_struct *child)
+{
+       unsigned long op;
+       unsigned long op2;
+       unsigned long disp;
+       unsigned long regno1, regno2;
+
+       op = (insn >> 28) & 0xf;
+       if (op == 0xf) {        /* branch 24-bit relative */
+               op2 = (insn >> 24) & 0xf;
+               switch (op2) {
+               case 0xd:       /* BNC */
+               case 0x9:       /* BNCL */
+                       if (!check_condition_bit(child)) {
+                               disp = (long)(insn << 8) >> 6;
+                               *next_pc = (pc & ~0x3) + disp;
+                               return;
+                       }
+                       break;
+               case 0x8:       /* BCL */
+               case 0xc:       /* BC */
+                       if (check_condition_bit(child)) {
+                               disp = (long)(insn << 8) >> 6;
+                               *next_pc = (pc & ~0x3) + disp;
+                               return;
+                       }
+                       break;
+               case 0xe:       /* BL */
+               case 0xf:       /* BRA */
+                       disp = (long)(insn << 8) >> 6;
+                       *next_pc = (pc & ~0x3) + disp;
+                       return;
+               }
+       } else if (op == 0xb) { /* branch 16-bit relative */
+               op2 = (insn >> 20) & 0xf;
+               switch (op2) {
+               case 0x0: /* BEQ */
+               case 0x1: /* BNE */
+               case 0x8: /* BEQZ */
+               case 0x9: /* BNEZ */
+               case 0xa: /* BLTZ */
+               case 0xb: /* BGEZ */
+               case 0xc: /* BLEZ */
+               case 0xd: /* BGTZ */
+                       regno1 = ((insn >> 24) & 0xf);
+                       regno2 = ((insn >> 16) & 0xf);
+                       if (check_condition_src(op2, regno1, regno2, child)) {
+                               disp = (long)(insn << 16) >> 14;
+                               *next_pc = (pc & ~0x3) + disp;
+                               return;
+                       }
+                       break;
+               }
+       }
+       *next_pc = pc + 4;
+}
+
+static inline void
+compute_next_pc(unsigned long insn, unsigned long pc,
+               unsigned long *next_pc, struct task_struct *child)
+{
+       if (insn & 0x80000000)
+               compute_next_pc_for_32bit_insn(insn, pc, next_pc, child);
+       else
+               compute_next_pc_for_16bit_insn(insn, pc, next_pc, child);
+}
+
+static int
+register_debug_trap(struct task_struct *child, unsigned long next_pc,
+       unsigned long next_insn, unsigned long *code)
+{
+       struct debug_trap *p = &child->thread.debug_trap;
+       unsigned long addr = next_pc & ~3;
+
+       if (p->nr_trap != 0) {
+               printk("kernel BUG at %s %d: p->nr_trap = %d\n",
+                                       __FILE__, __LINE__, p->nr_trap);
+               return -1;
+       }
+       p->addr = addr;
+       p->insn = next_insn;
+       p->nr_trap++;
+       if (next_pc & 3) {
+               *code = (next_insn & 0xffff0000) | 0x10f1;
+               /* xxx --> TRAP1 */
+       } else {
+               if ((next_insn & 0x80000000) || (next_insn & 0x8000)) {
+                       *code = 0x10f17000;
+                       /* TRAP1 --> NOP */
+               } else {
+                       *code = (next_insn & 0xffff) | 0x10f10000;
+                       /* TRAP1 --> xxx */
+               }
+       }
+       return 0;
+}
+
+int withdraw_debug_trap_for_signal(struct task_struct *child)
+{
+       struct debug_trap *p = &child->thread.debug_trap;
+       int nr_trap = p->nr_trap;
+
+       if (nr_trap) {
+               access_process_vm(child, p->addr, &p->insn, sizeof(p->insn), 1);
+               p->nr_trap = 0;
+               p->addr = 0;
+               p->insn = 0;
+       }
+       return nr_trap;
+}
+
+static int
+unregister_debug_trap(struct task_struct *child, unsigned long addr,
+                     unsigned long *code)
+{
+       struct debug_trap *p = &child->thread.debug_trap;
+
+       if (p->nr_trap != 1 || p->addr != addr) {
+               /* The trap may be requested from debugger.
+                * ptrace should do nothing in this case.
+                */
+               return 0;
+       }
+       *code = p->insn;
+       p->insn = 0;
+       p->addr = 0;
+       p->nr_trap--;
+       return 1;
+}
+
+static void
+unregister_all_debug_traps(struct task_struct *child)
+{
+       struct debug_trap *p = &child->thread.debug_trap;
+
+       if (p->nr_trap) {
+               access_process_vm(child, p->addr, &p->insn, sizeof(p->insn), 1);
+               p->addr = 0;
+               p->insn = 0;
+               p->nr_trap = 0;
+       }
+}
+
+static inline void
+invalidate_cache(void)
+{
+#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP)
+
+       _flush_cache_copyback_all();
+
+#else  /* ! CONFIG_CHIP_M32700 */
+
+       /* Invalidate cache */
+       __asm__ __volatile__ (
+                "ldi    r0, #-1                                        \n\t"
+                "ldi    r1, #0                                 \n\t"
+                "stb    r1, @r0                ; cache off             \n\t"
+                ";                                             \n\t"
+                "ldi    r0, #-2                                        \n\t"
+                "ldi    r1, #1                                 \n\t"
+                "stb    r1, @r0                ; cache invalidate      \n\t"
+                ".fillinsn                                     \n"
+                "0:                                            \n\t"
+                "ldb    r1, @r0                ; invalidate check      \n\t"
+                "bnez   r1, 0b                                 \n\t"
+                ";                                             \n\t"
+                "ldi    r0, #-1                                        \n\t"
+                "ldi    r1, #1                                 \n\t"
+                "stb    r1, @r0                ; cache on              \n\t"
+               : : : "r0", "r1", "memory"
+       );
+       /* FIXME: copying-back d-cache and invalidating i-cache are needed.
+        */
+#endif /* CONFIG_CHIP_M32700 */
+}
+
+/* Embed a debug trap (TRAP1) code */
+static int
+embed_debug_trap(struct task_struct *child, unsigned long next_pc)
+{
+       unsigned long next_insn, code;
+       unsigned long addr = next_pc & ~3;
+
+       if (access_process_vm(child, addr, &next_insn, sizeof(next_insn), 0)
+           != sizeof(next_insn)) {
+               return -1; /* error */
+       }
+
+       /* Set a trap code. */
+       if (register_debug_trap(child, next_pc, next_insn, &code)) {
+               return -1; /* error */
+       }
+       if (access_process_vm(child, addr, &code, sizeof(code), 1)
+           != sizeof(code)) {
+               return -1; /* error */
+       }
+       return 0; /* success */
+}
+
+void
+embed_debug_trap_for_signal(struct task_struct *child)
+{
+       unsigned long next_pc;
+       unsigned long pc, insn;
+       int ret;
+
+       pc = get_stack_long(child, PT_BPC);
+       ret = access_process_vm(child, pc&~3, &insn, sizeof(insn), 0);
+       if (ret != sizeof(insn)) {
+               printk("kernel BUG at %s %d: access_process_vm returns %d\n",
+                      __FILE__, __LINE__, ret);
+               return;
+       }
+       compute_next_pc(insn, pc, &next_pc, child);
+       if (next_pc & 0x80000000) {
+               printk("kernel BUG at %s %d: next_pc = 0x%08x\n",
+                      __FILE__, __LINE__, (int)next_pc);
+               return;
+       }
+       if (embed_debug_trap(child, next_pc)) {
+               printk("kernel BUG at %s %d: embed_debug_trap error\n",
+                      __FILE__, __LINE__);
+               return;
+       }
+       invalidate_cache();
+}
+
+void
+withdraw_debug_trap(struct pt_regs *regs)
+{
+       unsigned long addr;
+       unsigned long code;
+
+       addr = (regs->bpc - 2) & ~3;
+       regs->bpc -= 2;
+       if (unregister_debug_trap(current, addr, &code)) {
+           access_process_vm(current, addr, &code, sizeof(code), 1);
+           invalidate_cache();
+       }
+}
+
+static void
+init_debug_traps(struct task_struct *child)
+{
+       struct debug_trap *p = &child->thread.debug_trap;
+       p->nr_trap = 0;
+       p->addr = 0;
+       p->insn = 0;
+}
+
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure single step bits etc are not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+       /* nothing to do.. */
+}
+
+static int
+do_ptrace(long request, struct task_struct *child, long addr, long data)
+{
+       unsigned long tmp;
+       int ret;
+
+       switch (request) {
+       /*
+        * read word at location "addr" in the child process.
+        */
+       case PTRACE_PEEKTEXT:
+       case PTRACE_PEEKDATA:
+               ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+               if (ret == sizeof(tmp))
+                       ret = put_user(tmp,(unsigned long __user *) data);
+               else
+                       ret = -EIO;
+               break;
+
+       /*
+        * read the word at location addr in the USER area.
+        */
+       case PTRACE_PEEKUSR:
+               ret = ptrace_read_user(child, addr,
+                                      (unsigned long __user *)data);
+               break;
+
+       /*
+        * write the word at location addr.
+        */
+       case PTRACE_POKETEXT:
+       case PTRACE_POKEDATA:
+               ret = access_process_vm(child, addr, &data, sizeof(data), 1);
+               if (ret == sizeof(data)) {
+                       ret = 0;
+                       if (request == PTRACE_POKETEXT) {
+                               invalidate_cache();
+                       }
+               } else {
+                       ret = -EIO;
+               }
+               break;
+
+       /*
+        * write the word at location addr in the USER area.
+        */
+       case PTRACE_POKEUSR:
+               ret = ptrace_write_user(child, addr, data);
+               break;
+
+       /*
+        * continue/restart and stop at next (return from) syscall
+        */
+       case PTRACE_SYSCALL:
+       case PTRACE_CONT:
+               ret = -EIO;
+               if ((unsigned long) data > _NSIG)
+                       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;
+               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: {
+               ret = 0;
+               unregister_all_debug_traps(child);
+               invalidate_cache();
+               if (child->state == TASK_ZOMBIE)        /* already dead */
+                       break;
+               child->exit_code = SIGKILL;
+               wake_up_process(child);
+               break;
+       }
+
+       /*
+        * execute single instruction.
+        */
+       case PTRACE_SINGLESTEP: {
+               unsigned long next_pc;
+               unsigned long pc, insn;
+
+               ret = -EIO;
+               if ((unsigned long) data > _NSIG)
+                       break;
+               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+               if ((child->ptrace & PT_DTRACE) == 0) {
+                       /* Spurious delayed TF traps may occur */
+                       child->ptrace |= PT_DTRACE;
+               }
+
+               /* Compute next pc.  */
+               pc = get_stack_long(child, PT_BPC);
+
+               if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
+                   != sizeof(insn))
+                       break;
+
+               compute_next_pc(insn, pc, &next_pc, child);
+               if (next_pc & 0x80000000)
+                       break;
+
+               if (embed_debug_trap(child, next_pc))
+                       break;
+
+               invalidate_cache();
+               child->exit_code = data;
+
+               /* give it a chance to run. */
+               wake_up_process(child);
+               ret = 0;
+               break;
+       }
+
+       /*
+        * detach a process that was attached.
+        */
+       case PTRACE_DETACH:
+               ret = 0;
+               ret = ptrace_detach(child, data);
+               break;
+
+       case PTRACE_GETREGS:
+               ret = ptrace_getregs(child, (void __user *)data);
+               break;
+
+       case PTRACE_SETREGS:
+               ret = ptrace_setregs(child, (void __user *)data);
+               break;
+
+       default:
+               ret = ptrace_request(child, request, addr, data);
+               break;
+       }
+
+       return ret;
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+       struct task_struct *child;
+       int ret;
+
+       lock_kernel();
+       ret = -EPERM;
+       if (request == PTRACE_TRACEME) {
+               /* are we already being traced? */
+               if (current->ptrace & PT_PTRACED)
+                       goto out;
+               /* set the ptrace bit in the process flags. */
+               current->ptrace |= PT_PTRACED;
+               ret = 0;
+               goto out;
+       }
+       ret = -ESRCH;
+       read_lock(&tasklist_lock);
+       child = find_task_by_pid(pid);
+       if (child)
+               get_task_struct(child);
+       read_unlock(&tasklist_lock);
+       if (!child)
+               goto out;
+
+       ret = -EPERM;
+       if (pid == 1)           /* you may not mess with init */
+               goto out;
+
+       if (request == PTRACE_ATTACH) {
+               ret = ptrace_attach(child);
+               if (ret == 0)
+                       init_debug_traps(child);
+               goto out_tsk;
+       }
+
+       ret = ptrace_check_attach(child, request == PTRACE_KILL);
+       if (ret == 0)
+               ret = do_ptrace(request, child, addr, data);
+
+out_tsk:
+       put_task_struct(child);
+out:
+       unlock_kernel();
+
+       return ret;
+}
+
+/* notification of system call entry/exit
+ * - triggered by current->work.syscall_trace
+ */
+void do_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/m32r/kernel/semaphore.c b/arch/m32r/kernel/semaphore.c
new file mode 100644 (file)
index 0000000..358f217
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ *  linux/arch/m32r/semaphore.c
+ *    orig : i386 2.6.4
+ *
+ *  M32R semaphore implementation.
+ *
+ *     Copyright (c) 2002 - 2004 Hitoshi Yamamoto
+ */
+
+/*
+ * i386 semaphore implementation.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * Portions Copyright 1999 Red Hat, 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.
+ *
+ * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@redhat.com>
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <asm/semaphore.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to acquire the semaphore, while the "sleeping"
+ * variable is a count of such acquires.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * "sleeping" and the contention routine ordering is protected
+ * by the spinlock in the semaphore's waitqueue head.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+
+/*
+ * Logic:
+ *  - only on a boundary condition do we need to care. When we go
+ *    from a negative count to a non-negative, we wake people up.
+ *  - when we go from a non-negative count to a negative do we
+ *    (a) synchronize with the "sleeper" count and (b) make sure
+ *    that we're on the wakeup list before we synchronize so that
+ *    we cannot lose wakeup events.
+ */
+
+asmlinkage void __up(struct semaphore *sem)
+{
+       wake_up(&sem->wait);
+}
+
+asmlinkage void __sched __down(struct semaphore * sem)
+{
+       struct task_struct *tsk = current;
+       DECLARE_WAITQUEUE(wait, tsk);
+       unsigned long flags;
+
+       tsk->state = TASK_UNINTERRUPTIBLE;
+       spin_lock_irqsave(&sem->wait.lock, flags);
+       add_wait_queue_exclusive_locked(&sem->wait, &wait);
+
+       sem->sleepers++;
+       for (;;) {
+               int sleepers = sem->sleepers;
+
+               /*
+                * Add "everybody else" into it. They aren't
+                * playing, because we own the spinlock in
+                * the wait_queue_head.
+                */
+               if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+                       sem->sleepers = 0;
+                       break;
+               }
+               sem->sleepers = 1;      /* us - see -1 above */
+               spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+               schedule();
+
+               spin_lock_irqsave(&sem->wait.lock, flags);
+               tsk->state = TASK_UNINTERRUPTIBLE;
+       }
+       remove_wait_queue_locked(&sem->wait, &wait);
+       wake_up_locked(&sem->wait);
+       spin_unlock_irqrestore(&sem->wait.lock, flags);
+       tsk->state = TASK_RUNNING;
+}
+
+asmlinkage int __sched __down_interruptible(struct semaphore * sem)
+{
+       int retval = 0;
+       struct task_struct *tsk = current;
+       DECLARE_WAITQUEUE(wait, tsk);
+       unsigned long flags;
+
+       tsk->state = TASK_INTERRUPTIBLE;
+       spin_lock_irqsave(&sem->wait.lock, flags);
+       add_wait_queue_exclusive_locked(&sem->wait, &wait);
+
+       sem->sleepers++;
+       for (;;) {
+               int sleepers = sem->sleepers;
+
+               /*
+                * With signals pending, this turns into
+                * the trylock failure case - we won't be
+                * sleeping, and we* can't get the lock as
+                * it has contention. Just correct the count
+                * and exit.
+                */
+               if (signal_pending(current)) {
+                       retval = -EINTR;
+                       sem->sleepers = 0;
+                       atomic_add(sleepers, &sem->count);
+                       break;
+               }
+
+               /*
+                * Add "everybody else" into it. They aren't
+                * playing, because we own the spinlock in
+                * wait_queue_head. The "-1" is because we're
+                * still hoping to get the semaphore.
+                */
+               if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+                       sem->sleepers = 0;
+                       break;
+               }
+               sem->sleepers = 1;      /* us - see -1 above */
+               spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+               schedule();
+
+               spin_lock_irqsave(&sem->wait.lock, flags);
+               tsk->state = TASK_INTERRUPTIBLE;
+       }
+       remove_wait_queue_locked(&sem->wait, &wait);
+       wake_up_locked(&sem->wait);
+       spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+       tsk->state = TASK_RUNNING;
+       return retval;
+}
+
+/*
+ * Trylock failed - make sure we correct for
+ * having decremented the count.
+ *
+ * We could have done the trylock with a
+ * single "cmpxchg" without failure cases,
+ * but then it wouldn't work on a 386.
+ */
+asmlinkage int __down_trylock(struct semaphore * sem)
+{
+       int sleepers;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sem->wait.lock, flags);
+       sleepers = sem->sleepers + 1;
+       sem->sleepers = 0;
+
+       /*
+        * Add "everybody else" and us into it. They aren't
+        * playing, because we own the spinlock in the
+        * wait_queue_head.
+        */
+       if (!atomic_add_negative(sleepers, &sem->count)) {
+               wake_up_locked(&sem->wait);
+       }
+
+       spin_unlock_irqrestore(&sem->wait.lock, flags);
+       return 1;
+}
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
new file mode 100644 (file)
index 0000000..db9589c
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ *  linux/arch/m32r/kernel/setup.c
+ *
+ *  Setup routines for Renesas M32R
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ */
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/stddef.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/console.h>
+#include <linux/initrd.h>
+#include <linux/major.h>
+#include <linux/root_dev.h>
+#include <linux/seq_file.h>
+#include <linux/timex.h>
+#include <linux/tty.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/m32r.h>
+#include <asm/setup.h>
+#include <asm/sections.h>
+
+#ifdef CONFIG_MMU
+extern void init_mmu(void);
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)  \
+       || defined(CONFIG_BLK_DEV_IDE_MODULE)                   \
+       || defined(CONFIG_BLK_DEV_HD_MODULE)
+struct drive_info_struct { char dummy[32]; } drive_info;
+#endif
+
+extern char _end[];
+
+/*
+ * Machine setup..
+ */
+struct cpuinfo_m32r boot_cpu_data;
+
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload;  /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;  /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;  /* starting block # of image */
+#endif
+
+#if defined(CONFIG_VGA_CONSOLE)
+struct screen_info screen_info = {
+       .orig_video_lines      = 25,
+       .orig_video_cols       = 80,
+       .orig_video_mode       = 0,
+       .orig_video_ega_bx     = 0,
+       .orig_video_isVGA      = 1,
+       .orig_video_points     = 8
+};
+#endif
+
+extern int root_mountflags;
+
+static char command_line[COMMAND_LINE_SIZE];
+
+static struct resource data_resource = {
+       .name   = "Kernel data",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource code_resource = {
+       .name   = "Kernel code",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+unsigned long memory_start;
+unsigned long memory_end;
+
+void __init setup_arch(char **);
+int get_cpuinfo(char *);
+
+static __inline__ void parse_mem_cmdline(char ** cmdline_p)
+{
+       char c = ' ';
+       char *to = command_line;
+       char *from = COMMAND_LINE;
+       int len = 0;
+       int usermem = 0;
+
+       /* Save unparsed command line copy for /proc/cmdline */
+       memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+       saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+
+       memory_start = (unsigned long)CONFIG_MEMORY_START+PAGE_OFFSET;
+       memory_end = memory_start+(unsigned long)CONFIG_MEMORY_SIZE;
+
+       for ( ; ; ) {
+               if (c == ' ' && !memcmp(from, "mem=", 4)) {
+                       if (to != command_line)
+                               to--;
+
+                       {
+                               unsigned long mem_size;
+
+                               usermem = 1;
+                               mem_size = memparse(from+4, &from);
+                               memory_end = memory_start + mem_size;
+                       }
+               }
+               c = *(from++);
+               if (!c)
+                       break;
+
+               if (COMMAND_LINE_SIZE <= ++len)
+                       break;
+
+               *(to++) = c;
+       }
+       *to = '\0';
+       *cmdline_p = command_line;
+       if (usermem)
+               printk(KERN_INFO "user-defined physical RAM map:\n");
+}
+
+#ifndef CONFIG_DISCONTIGMEM
+static unsigned long __init setup_memory(void)
+{
+       unsigned long start_pfn, max_low_pfn, bootmap_size;
+
+       start_pfn = PFN_UP( __pa(_end) );
+       max_low_pfn = PFN_DOWN( __pa(memory_end) );
+
+       /*
+        * Initialize the boot-time allocator (with low memory only):
+        */
+       bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
+               CONFIG_MEMORY_START>>PAGE_SHIFT, max_low_pfn);
+
+       /*
+        * Register fully available low RAM pages with the bootmem allocator.
+        */
+       {
+               unsigned long curr_pfn;
+               unsigned long last_pfn;
+               unsigned long pages;
+
+               /*
+                * We are rounding up the start address of usable memory:
+                */
+               curr_pfn = PFN_UP(__pa(memory_start));
+
+               /*
+                * ... and at the end of the usable range downwards:
+                */
+               last_pfn = PFN_DOWN(__pa(memory_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));
+       }
+
+       /*
+        * Reserve the kernel text and
+        * Reserve the bootmem bitmap. We do this in two steps (first step
+        * was init_bootmem()), because this catches the (definitely buggy)
+        * case of us accidentally initializing the bootmem allocator with
+        * an invalid RAM area.
+        */
+       reserve_bootmem(CONFIG_MEMORY_START + PAGE_SIZE,
+               (PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE - 1)
+               - CONFIG_MEMORY_START);
+
+       /*
+        * reserve physical page 0 - it's a special BIOS page on many boxes,
+        * enabling clean reboots, SMP operation, laptop functions.
+        */
+       reserve_bootmem(CONFIG_MEMORY_START, PAGE_SIZE);
+
+       /*
+        * reserve memory hole
+        */
+#ifdef CONFIG_MEMHOLE
+       reserve_bootmem(CONFIG_MEMHOLE_START, CONFIG_MEMHOLE_SIZE);
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (LOADER_TYPE && INITRD_START) {
+               if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
+                       reserve_bootmem(INITRD_START, INITRD_SIZE);
+                       initrd_start = INITRD_START ?
+                               INITRD_START + PAGE_OFFSET : 0;
+
+                       initrd_end = initrd_start + INITRD_SIZE;
+                       printk("initrd:start[%08lx],size[%08lx]\n",
+                               initrd_start, INITRD_SIZE);
+               } else {
+                       printk("initrd extends beyond end of memory "
+                               "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+                               INITRD_START + INITRD_SIZE,
+                               max_low_pfn << PAGE_SHIFT);
+
+                       initrd_start = 0;
+               }
+       }
+#endif
+
+       return max_low_pfn;
+}
+#else  /* CONFIG_DISCONTIGMEM */
+extern unsigned long setup_memory(void);
+#endif /* CONFIG_DISCONTIGMEM */
+
+#define M32R_PCC_PCATCR        0x00ef7014      /* will move to m32r.h */
+
+void __init setup_arch(char **cmdline_p)
+{
+       ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
+
+       boot_cpu_data.cpu_clock = M32R_CPUCLK;
+       boot_cpu_data.bus_clock = M32R_BUSCLK;
+       boot_cpu_data.timer_divide = M32R_TIMER_DIVIDE;
+
+#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;
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+       conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+       conswitchp = &dummy_con;
+#endif
+#endif
+
+#ifdef CONFIG_DISCONTIGMEM
+       numnodes = 2;
+#endif /* CONFIG_DISCONTIGMEM */
+
+       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_mem_cmdline(cmdline_p);
+
+       setup_memory();
+
+       paging_init();
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ *     Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+       struct cpuinfo_m32r *c = v;
+       unsigned long cpu = c - cpu_data;
+
+#ifdef CONFIG_SMP
+       if (!cpu_online(cpu))
+               return 0;
+#endif  /* CONFIG_SMP */
+
+       seq_printf(m, "processor\t: %ld\n", cpu);
+
+#ifdef CONFIG_CHIP_VDEC2
+       seq_printf(m, "cpu family\t: VDEC2\n"
+               "cache size\t: Unknown\n");
+#elif  CONFIG_CHIP_M32700
+       seq_printf(m,"cpu family\t: M32700\n"
+               "cache size\t: I-8KB/D-8KB\n");
+#elif  CONFIG_CHIP_M32102
+       seq_printf(m,"cpu family\t: M32102\n"
+               "cache size\t: I-8KB\n");
+#elif  CONFIG_CHIP_OPSP
+       seq_printf(m,"cpu family\t: OPSP\n"
+               "cache size\t: I-8KB/D-8KB\n");
+#elif  CONFIG_CHIP_MP
+       seq_printf(m, "cpu family\t: M32R-MP\n"
+               "cache size\t: I-xxKB/D-xxKB\n");
+#else
+       seq_printf(m, "cpu family\t: Unknown\n");
+#endif
+       seq_printf(m, "bogomips\t: %lu.%02lu\n",
+               c->loops_per_jiffy/(500000/HZ),
+               (c->loops_per_jiffy/(5000/HZ)) % 100);
+#ifdef CONFIG_PLAT_MAPPI
+       seq_printf(m, "Machine\t\t: Mappi Evaluation board\n");
+#elif CONFIG_PLAT_MAPPI2
+       seq_printf(m, "Machine\t\t: Mappi-II Evaluation board\n");
+#elif  CONFIG_PLAT_M32700UT
+       seq_printf(m, "Machine\t\t: M32700UT Evaluation board\n");
+#elif  CONFIG_PLAT_OPSPUT
+       seq_printf(m, "Machine\t\t: OPSPUT Evaluation board\n");
+#elif  CONFIG_PLAT_USRV
+       seq_printf(m, "Machine\t\t: uServer\n");
+#elif  CONFIG_PLAT_OAKS32R
+       seq_printf(m, "Machine\t\t: OAKS32R\n");
+#else
+       seq_printf(m, "Machine\t\t: Unknown\n");
+#endif
+
+#define PRINT_CLOCK(name, value)                               \
+       seq_printf(m, name " clock\t: %d.%02dMHz\n",            \
+               ((value) / 1000000), ((value) % 1000000)/10000)
+
+       PRINT_CLOCK("CPU", (int)c->cpu_clock);
+       PRINT_CLOCK("Bus", (int)c->bus_clock);
+
+       seq_printf(m, "\n");
+
+       return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+       return *pos < NR_CPUS ? cpu_data + *pos : 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,
+};
+#endif  /* CONFIG_PROC_FS */
+
+unsigned long cpu_initialized __initdata = 0;
+
+/*
+ * cpu_init() initializes state that is per-CPU. Some data is already
+ * initialized (naturally) in the bootstrap process.
+ * We reload them nevertheless, this function acts as a
+ * 'CPU state barrier', nothing should get across.
+ */
+#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2)   \
+       || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
+       || defined(CONFIG_CHIP_OPSP)
+void __init cpu_init (void)
+{
+       int cpu_id = smp_processor_id();
+
+       if (test_and_set_bit(cpu_id, &cpu_initialized)) {
+               printk(KERN_WARNING "CPU#%d already initialized!\n", cpu_id);
+               for ( ; ; )
+                       local_irq_enable();
+       }
+       printk(KERN_INFO "Initializing CPU#%d\n", cpu_id);
+
+       /* Set up and load the per-CPU TSS and LDT */
+       atomic_inc(&init_mm.mm_count);
+       current->active_mm = &init_mm;
+       if (current->mm)
+               BUG();
+
+       /* Force FPU initialization */
+       current_thread_info()->status = 0;
+       current->used_math = 0;
+
+#ifdef CONFIG_MMU
+       /* Set up MMU */
+       init_mmu();
+#endif
+
+       /* Set up ICUIMASK */
+       outl(0x00070000, M32R_ICU_IMASK_PORTL);   /* imask=111 */
+}
+#endif  /* defined(CONFIG_CHIP_VDEC2) ... */
+
diff --git a/arch/m32r/kernel/setup_m32700ut.c b/arch/m32r/kernel/setup_m32700ut.c
new file mode 100644 (file)
index 0000000..5d0780b
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ *  linux/arch/m32r/kernel/setup_m32700ut.c
+ *
+ *  Setup routines for Renesas M32700UT Board
+ *
+ *  Copyright (c) 2002         Hiroyuki Kondo, Hirokazu Takata,
+ *                      Hitoshi Yamamoto, Takeo Takahashi
+ *
+ *  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/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+/*
+ * M32700 Interrupt Control Unit (Level 1)
+ */
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+       unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+static icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
+
+static void disable_m32700ut_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+       outl(data, port);
+}
+
+static void enable_m32700ut_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+       outl(data, port);
+}
+
+static void mask_and_ack_m32700ut(unsigned int irq)
+{
+       disable_m32700ut_irq(irq);
+}
+
+static void end_m32700ut_irq(unsigned int irq)
+{
+       enable_m32700ut_irq(irq);
+}
+
+static unsigned int startup_m32700ut_irq(unsigned int irq)
+{
+       enable_m32700ut_irq(irq);
+       return (0);
+}
+
+static void shutdown_m32700ut_irq(unsigned int irq)
+{
+       unsigned long port;
+
+       port = irq2port(irq);
+       outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type m32700ut_irq_type =
+{
+       "M32700UT-IRQ",
+       startup_m32700ut_irq,
+       shutdown_m32700ut_irq,
+       enable_m32700ut_irq,
+       disable_m32700ut_irq,
+       mask_and_ack_m32700ut,
+       end_m32700ut_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on M32700UT (Level 2)
+ */
+#define irq2pldirq(x)          ((x) - M32700UT_PLD_IRQ_BASE)
+#define pldirq2port(x)         (unsigned long)((int)PLD_ICUCR1 + \
+                                (((x) - 1) * sizeof(unsigned short)))
+
+typedef struct {
+       unsigned short icucr;  /* ICU Control Register */
+} pld_icu_data_t;
+
+static pld_icu_data_t pld_icu_data[M32700UT_NUM_PLD_IRQ];
+
+static void disable_m32700ut_pld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2pldirq(irq);
+//     disable_m32700ut_irq(M32R_IRQ_INT1);
+       port = pldirq2port(pldirq);
+       data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+       outw(data, port);
+}
+
+static void enable_m32700ut_pld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2pldirq(irq);
+//     enable_m32700ut_irq(M32R_IRQ_INT1);
+       port = pldirq2port(pldirq);
+       data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+       outw(data, port);
+}
+
+static void mask_and_ack_m32700ut_pld(unsigned int irq)
+{
+       disable_m32700ut_pld_irq(irq);
+//     mask_and_ack_m32700ut(M32R_IRQ_INT1);
+}
+
+static void end_m32700ut_pld_irq(unsigned int irq)
+{
+       enable_m32700ut_pld_irq(irq);
+       end_m32700ut_irq(M32R_IRQ_INT1);
+}
+
+static unsigned int startup_m32700ut_pld_irq(unsigned int irq)
+{
+       enable_m32700ut_pld_irq(irq);
+       return (0);
+}
+
+static void shutdown_m32700ut_pld_irq(unsigned int irq)
+{
+       unsigned long port;
+       unsigned int pldirq;
+
+       pldirq = irq2pldirq(irq);
+//     shutdown_m32700ut_irq(M32R_IRQ_INT1);
+       port = pldirq2port(pldirq);
+       outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type m32700ut_pld_irq_type =
+{
+       "M32700UT-PLD-IRQ",
+       startup_m32700ut_pld_irq,
+       shutdown_m32700ut_pld_irq,
+       enable_m32700ut_pld_irq,
+       disable_m32700ut_pld_irq,
+       mask_and_ack_m32700ut_pld,
+       end_m32700ut_pld_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on M32700UT-LAN (Level 2)
+ */
+#define irq2lanpldirq(x)       ((x) - M32700UT_LAN_PLD_IRQ_BASE)
+#define lanpldirq2port(x)      (unsigned long)((int)M32700UT_LAN_ICUCR1 + \
+                                (((x) - 1) * sizeof(unsigned short)))
+
+static pld_icu_data_t lanpld_icu_data[M32700UT_NUM_LAN_PLD_IRQ];
+
+static void disable_m32700ut_lanpld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2lanpldirq(irq);
+       port = lanpldirq2port(pldirq);
+       data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+       outw(data, port);
+}
+
+static void enable_m32700ut_lanpld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2lanpldirq(irq);
+       port = lanpldirq2port(pldirq);
+       data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+       outw(data, port);
+}
+
+static void mask_and_ack_m32700ut_lanpld(unsigned int irq)
+{
+       disable_m32700ut_lanpld_irq(irq);
+}
+
+static void end_m32700ut_lanpld_irq(unsigned int irq)
+{
+       enable_m32700ut_lanpld_irq(irq);
+       end_m32700ut_irq(M32R_IRQ_INT0);
+}
+
+static unsigned int startup_m32700ut_lanpld_irq(unsigned int irq)
+{
+       enable_m32700ut_lanpld_irq(irq);
+       return (0);
+}
+
+static void shutdown_m32700ut_lanpld_irq(unsigned int irq)
+{
+       unsigned long port;
+       unsigned int pldirq;
+
+       pldirq = irq2lanpldirq(irq);
+       port = lanpldirq2port(pldirq);
+       outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type m32700ut_lanpld_irq_type =
+{
+       "M32700UT-PLD-LAN-IRQ",
+       startup_m32700ut_lanpld_irq,
+       shutdown_m32700ut_lanpld_irq,
+       enable_m32700ut_lanpld_irq,
+       disable_m32700ut_lanpld_irq,
+       mask_and_ack_m32700ut_lanpld,
+       end_m32700ut_lanpld_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on M32700UT-LCD (Level 2)
+ */
+#define irq2lcdpldirq(x)       ((x) - M32700UT_LCD_PLD_IRQ_BASE)
+#define lcdpldirq2port(x)      (unsigned long)((int)M32700UT_LCD_ICUCR1 + \
+                                (((x) - 1) * sizeof(unsigned short)))
+
+static pld_icu_data_t lcdpld_icu_data[M32700UT_NUM_LCD_PLD_IRQ];
+
+static void disable_m32700ut_lcdpld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2lcdpldirq(irq);
+       port = lcdpldirq2port(pldirq);
+       data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+       outw(data, port);
+}
+
+static void enable_m32700ut_lcdpld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2lcdpldirq(irq);
+       port = lcdpldirq2port(pldirq);
+       data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+       outw(data, port);
+}
+
+static void mask_and_ack_m32700ut_lcdpld(unsigned int irq)
+{
+       disable_m32700ut_lcdpld_irq(irq);
+}
+
+static void end_m32700ut_lcdpld_irq(unsigned int irq)
+{
+       enable_m32700ut_lcdpld_irq(irq);
+       end_m32700ut_irq(M32R_IRQ_INT2);
+}
+
+static unsigned int startup_m32700ut_lcdpld_irq(unsigned int irq)
+{
+       enable_m32700ut_lcdpld_irq(irq);
+       return (0);
+}
+
+static void shutdown_m32700ut_lcdpld_irq(unsigned int irq)
+{
+       unsigned long port;
+       unsigned int pldirq;
+
+       pldirq = irq2lcdpldirq(irq);
+       port = lcdpldirq2port(pldirq);
+       outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type m32700ut_lcdpld_irq_type =
+{
+       "M32700UT-PLD-LCD-IRQ",
+       startup_m32700ut_lcdpld_irq,
+       shutdown_m32700ut_lcdpld_irq,
+       enable_m32700ut_lcdpld_irq,
+       disable_m32700ut_lcdpld_irq,
+       mask_and_ack_m32700ut_lcdpld,
+       end_m32700ut_lcdpld_irq
+};
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_SMC91X)
+       /* INT#0: LAN controller on M32700UT-LAN (SMC91C111)*/
+       irq_desc[M32700UT_LAN_IRQ_LAN].status = IRQ_DISABLED;
+       irq_desc[M32700UT_LAN_IRQ_LAN].handler = &m32700ut_lanpld_irq_type;
+       irq_desc[M32700UT_LAN_IRQ_LAN].action = 0;
+       irq_desc[M32700UT_LAN_IRQ_LAN].depth = 1;       /* disable nested irq */
+       lanpld_icu_data[irq2lanpldirq(M32700UT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;   /* "H" edge sense */
+       disable_m32700ut_lanpld_irq(M32700UT_LAN_IRQ_LAN);
+#endif  /* CONFIG_SMC91X */
+
+       /* MFT2 : system timer */
+       irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_MFT2].handler = &m32700ut_irq_type;
+       irq_desc[M32R_IRQ_MFT2].action = 0;
+       irq_desc[M32R_IRQ_MFT2].depth = 1;
+       icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+       disable_m32700ut_irq(M32R_IRQ_MFT2);
+
+       /* SIO0 : receive */
+       irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_R].handler = &m32700ut_irq_type;
+       irq_desc[M32R_IRQ_SIO0_R].action = 0;
+       irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+       icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+       disable_m32700ut_irq(M32R_IRQ_SIO0_R);
+
+       /* SIO0 : send */
+       irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_S].handler = &m32700ut_irq_type;
+       irq_desc[M32R_IRQ_SIO0_S].action = 0;
+       irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+       icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+       disable_m32700ut_irq(M32R_IRQ_SIO0_S);
+
+       /* SIO1 : receive */
+       irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_R].handler = &m32700ut_irq_type;
+       irq_desc[M32R_IRQ_SIO1_R].action = 0;
+       irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+       icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+       disable_m32700ut_irq(M32R_IRQ_SIO1_R);
+
+       /* SIO1 : send */
+       irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_S].handler = &m32700ut_irq_type;
+       irq_desc[M32R_IRQ_SIO1_S].action = 0;
+       irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+       icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+       disable_m32700ut_irq(M32R_IRQ_SIO1_S);
+
+       /* DMA1 : */
+       irq_desc[M32R_IRQ_DMA1].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_DMA1].handler = &m32700ut_irq_type;
+       irq_desc[M32R_IRQ_DMA1].action = 0;
+       irq_desc[M32R_IRQ_DMA1].depth = 1;
+       icu_data[M32R_IRQ_DMA1].icucr = 0;
+       disable_m32700ut_irq(M32R_IRQ_DMA1);
+
+#ifdef CONFIG_SERIAL_M32R_PLDSIO
+       /* INT#1: SIO0 Receive on PLD */
+       irq_desc[PLD_IRQ_SIO0_RCV].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_SIO0_RCV].handler = &m32700ut_pld_irq_type;
+       irq_desc[PLD_IRQ_SIO0_RCV].action = 0;
+       irq_desc[PLD_IRQ_SIO0_RCV].depth = 1;   /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
+       disable_m32700ut_pld_irq(PLD_IRQ_SIO0_RCV);
+
+       /* INT#1: SIO0 Send on PLD */
+       irq_desc[PLD_IRQ_SIO0_SND].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_SIO0_SND].handler = &m32700ut_pld_irq_type;
+       irq_desc[PLD_IRQ_SIO0_SND].action = 0;
+       irq_desc[PLD_IRQ_SIO0_SND].depth = 1;   /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
+       disable_m32700ut_pld_irq(PLD_IRQ_SIO0_SND);
+#endif  /* CONFIG_SERIAL_M32R_PLDSIO */
+
+       /* INT#1: CFC IREQ on PLD */
+       irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_CFIREQ].handler = &m32700ut_pld_irq_type;
+       irq_desc[PLD_IRQ_CFIREQ].action = 0;
+       irq_desc[PLD_IRQ_CFIREQ].depth = 1;     /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;       /* 'L' level sense */
+       disable_m32700ut_pld_irq(PLD_IRQ_CFIREQ);
+
+       /* INT#1: CFC Insert on PLD */
+       irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_CFC_INSERT].handler = &m32700ut_pld_irq_type;
+       irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+       irq_desc[PLD_IRQ_CFC_INSERT].depth = 1; /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00;   /* 'L' edge sense */
+       disable_m32700ut_pld_irq(PLD_IRQ_CFC_INSERT);
+
+       /* INT#1: CFC Eject on PLD */
+       irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_CFC_EJECT].handler = &m32700ut_pld_irq_type;
+       irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+       irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;  /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;    /* 'H' edge sense */
+       disable_m32700ut_pld_irq(PLD_IRQ_CFC_EJECT);
+
+       /*
+        * INT0# is used for LAN, DIO
+        * We enable it here.
+        */
+       icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
+       enable_m32700ut_irq(M32R_IRQ_INT0);
+
+       /*
+        * INT1# is used for UART, MMC, CF Controller in FPGA.
+        * We enable it here.
+        */
+       icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
+       enable_m32700ut_irq(M32R_IRQ_INT1);
+
+#if defined(CONFIG_USB)
+       outw(USBCR_OTGS, USBCR);        /* USBCR: non-OTG */
+
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].status = IRQ_DISABLED;
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].handler = &m32700ut_lcdpld_irq_type;
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].action = 0;
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].depth = 1;
+    lcdpld_icu_data[irq2lcdpldirq(M32700UT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01; /* "L" level sense */
+    disable_m32700ut_lcdpld_irq(M32700UT_LCD_IRQ_USB_INT1);
+#endif
+       /*
+        * INT2# is used for BAT, USB, AUDIO
+        * We enable it here.
+        */
+       icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
+       enable_m32700ut_irq(M32R_IRQ_INT2);
+
+//#if defined(CONFIG_M32R_AR_VGA)
+       /*
+        * INT3# is used for AR
+        */
+       irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_INT3].handler = &m32700ut_irq_type;
+       irq_desc[M32R_IRQ_INT3].action = 0;
+       irq_desc[M32R_IRQ_INT3].depth = 1;
+       icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+       disable_m32700ut_irq(M32R_IRQ_INT3);
+//#endif       /* CONFIG_M32R_ARV */
+}
+
+#define LAN_IOSTART     0x300
+#define LAN_IOEND       0x320
+static struct resource smc91x_resources[] = {
+       [0] = {
+               .start  = (LAN_IOSTART),
+               .end    = (LAN_IOEND),
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = M32700UT_LAN_IRQ_LAN,
+               .end    = M32700UT_LAN_IRQ_LAN,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device smc91x_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smc91x_resources),
+       .resource       = smc91x_resources,
+};
+
+static int __init platform_init(void)
+{
+       platform_device_register(&smc91x_device);
+       return 0;
+}
+arch_initcall(platform_init);
diff --git a/arch/m32r/kernel/setup_mappi.c b/arch/m32r/kernel/setup_mappi.c
new file mode 100644 (file)
index 0000000..523cee3
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ *  linux/arch/m32r/kernel/setup_mappi.c
+ *
+ *  Setup routines for Renesas MAPPI Board
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+       unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+icu_data_t icu_data[NR_IRQS];
+
+static void disable_mappi_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+       outl(data, port);
+}
+
+static void enable_mappi_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+       outl(data, port);
+}
+
+static void mask_and_ack_mappi(unsigned int irq)
+{
+       disable_mappi_irq(irq);
+}
+
+static void end_mappi_irq(unsigned int irq)
+{
+       enable_mappi_irq(irq);
+}
+
+static unsigned int startup_mappi_irq(unsigned int irq)
+{
+       enable_mappi_irq(irq);
+       return (0);
+}
+
+static void shutdown_mappi_irq(unsigned int irq)
+{
+       unsigned long port;
+
+       port = irq2port(irq);
+       outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type mappi_irq_type =
+{
+       "MAPPI-IRQ",
+       startup_mappi_irq,
+       shutdown_mappi_irq,
+       enable_mappi_irq,
+       disable_mappi_irq,
+       mask_and_ack_mappi,
+       end_mappi_irq
+};
+
+void __init init_IRQ(void)
+{
+       static int once = 0;
+
+       if (once)
+               return;
+       else
+               once++;
+
+#ifdef CONFIG_NE2000
+       /* INT0 : LAN controller (RTL8019AS) */
+       irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_INT0].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_INT0].action = 0;
+       irq_desc[M32R_IRQ_INT0].depth = 1;
+       icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+       disable_mappi_irq(M32R_IRQ_INT0);
+#endif /* CONFIG_M32R_NE2000 */
+
+       /* MFT2 : system timer */
+       irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_MFT2].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_MFT2].action = 0;
+       irq_desc[M32R_IRQ_MFT2].depth = 1;
+       icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+       disable_mappi_irq(M32R_IRQ_MFT2);
+
+#ifdef CONFIG_SERIAL_M32R_SIO
+       /* SIO0_R : uart receive data */
+       irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_R].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_SIO0_R].action = 0;
+       irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+       icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+       disable_mappi_irq(M32R_IRQ_SIO0_R);
+
+       /* SIO0_S : uart send data */
+       irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_S].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_SIO0_S].action = 0;
+       irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+       icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+       disable_mappi_irq(M32R_IRQ_SIO0_S);
+
+       /* SIO1_R : uart receive data */
+       irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_R].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_SIO1_R].action = 0;
+       irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+       icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+       disable_mappi_irq(M32R_IRQ_SIO1_R);
+
+       /* SIO1_S : uart send data */
+       irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_S].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_SIO1_S].action = 0;
+       irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+       icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+       disable_mappi_irq(M32R_IRQ_SIO1_S);
+#endif /* CONFIG_SERIAL_M32R_SIO */
+
+#if defined(CONFIG_M32RPCC)
+       /* INT1 : pccard0 interrupt */
+       irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_INT1].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_INT1].action = 0;
+       irq_desc[M32R_IRQ_INT1].depth = 1;
+       icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
+       disable_mappi_irq(M32R_IRQ_INT1);
+
+       /* INT2 : pccard1 interrupt */
+       irq_desc[M32R_IRQ_INT2].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_INT2].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_INT2].action = 0;
+       irq_desc[M32R_IRQ_INT2].depth = 1;
+       icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
+       disable_mappi_irq(M32R_IRQ_INT2);
+#endif /* CONFIG_M32RPCC */
+}
diff --git a/arch/m32r/kernel/setup_mappi2.c b/arch/m32r/kernel/setup_mappi2.c
new file mode 100644 (file)
index 0000000..92eb06e
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ *  linux/arch/m32r/kernel/setup_mappi.c
+ *
+ *  Setup routines for Renesas MAPPI-II(M3A-ZA36) Board
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+       unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+icu_data_t icu_data[NR_IRQS];
+
+static void disable_mappi2_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       if ((irq == 0) ||(irq >= NR_IRQS))  {
+               printk("bad irq 0x%08x\n", irq);
+               return;
+       }
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+       outl(data, port);
+}
+
+static void enable_mappi2_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       if ((irq == 0) ||(irq >= NR_IRQS))  {
+               printk("bad irq 0x%08x\n", irq);
+               return;
+       }
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+       outl(data, port);
+}
+
+static void mask_and_ack_mappi2(unsigned int irq)
+{
+       disable_mappi2_irq(irq);
+}
+
+static void end_mappi2_irq(unsigned int irq)
+{
+       enable_mappi2_irq(irq);
+}
+
+static unsigned int startup_mappi2_irq(unsigned int irq)
+{
+       enable_mappi2_irq(irq);
+       return (0);
+}
+
+static void shutdown_mappi2_irq(unsigned int irq)
+{
+       unsigned long port;
+
+       port = irq2port(irq);
+       outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type mappi2_irq_type =
+{
+       "MAPPI2-IRQ",
+       startup_mappi2_irq,
+       shutdown_mappi2_irq,
+       enable_mappi2_irq,
+       disable_mappi2_irq,
+       mask_and_ack_mappi2,
+       end_mappi2_irq
+};
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_SMC91X)
+       /* INT0 : LAN controller (SMC91111) */
+       irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_INT0].handler = &mappi2_irq_type;
+       irq_desc[M32R_IRQ_INT0].action = 0;
+       irq_desc[M32R_IRQ_INT0].depth = 1;
+       icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+       disable_mappi2_irq(M32R_IRQ_INT0);
+#endif  /* CONFIG_SMC91X */
+
+       /* MFT2 : system timer */
+       irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_MFT2].handler = &mappi2_irq_type;
+       irq_desc[M32R_IRQ_MFT2].action = 0;
+       irq_desc[M32R_IRQ_MFT2].depth = 1;
+       icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+       disable_mappi2_irq(M32R_IRQ_MFT2);
+
+#ifdef CONFIG_SERIAL_M32R_SIO
+       /* SIO0_R : uart receive data */
+       irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_R].handler = &mappi2_irq_type;
+       irq_desc[M32R_IRQ_SIO0_R].action = 0;
+       irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+       icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+       disable_mappi2_irq(M32R_IRQ_SIO0_R);
+
+       /* SIO0_S : uart send data */
+       irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_S].handler = &mappi2_irq_type;
+       irq_desc[M32R_IRQ_SIO0_S].action = 0;
+       irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+       icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+       disable_mappi2_irq(M32R_IRQ_SIO0_S);
+       /* SIO1_R : uart receive data */
+       irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_R].handler = &mappi2_irq_type;
+       irq_desc[M32R_IRQ_SIO1_R].action = 0;
+       irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+       icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+       disable_mappi2_irq(M32R_IRQ_SIO1_R);
+
+       /* SIO1_S : uart send data */
+       irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_S].handler = &mappi2_irq_type;
+       irq_desc[M32R_IRQ_SIO1_S].action = 0;
+       irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+       icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+       disable_mappi2_irq(M32R_IRQ_SIO1_S);
+#endif  /* CONFIG_M32R_USE_DBG_CONSOLE */
+
+#if defined(CONFIG_USB)
+       /* INT1 : USB Host controller interrupt */
+       irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_INT1].handler = &mappi2_irq_type;
+       irq_desc[M32R_IRQ_INT1].action = 0;
+       irq_desc[M32R_IRQ_INT1].depth = 1;
+       icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
+       disable_mappi2_irq(M32R_IRQ_INT1);
+#endif /* CONFIG_USB */
+
+#if defined(CONFIG_M32R_CFC)
+       /* ICUCR40: CFC IREQ */
+       irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_CFIREQ].handler = &mappi2_irq_type;
+       irq_desc[PLD_IRQ_CFIREQ].action = 0;
+       irq_desc[PLD_IRQ_CFIREQ].depth = 1;     /* disable nested irq */
+//     icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
+       icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
+       disable_mappi2_irq(PLD_IRQ_CFIREQ);
+
+       /* ICUCR41: CFC Insert */
+       irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_CFC_INSERT].handler = &mappi2_irq_type;
+       irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+       irq_desc[PLD_IRQ_CFC_INSERT].depth = 1; /* disable nested irq */
+       icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
+//     icu_data[PLD_IRQ_CFC_INSERT].icucr = 0;
+       disable_mappi2_irq(PLD_IRQ_CFC_INSERT);
+
+       /* ICUCR42: CFC Eject */
+       irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_CFC_EJECT].handler = &mappi2_irq_type;
+       irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+       irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;  /* disable nested irq */
+       icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+//     icu_data[PLD_IRQ_CFC_EJECT].icucr = 0;
+       disable_mappi2_irq(PLD_IRQ_CFC_EJECT);
+
+#endif /* CONFIG_MAPPI2_CFC */
+}
+
+#define LAN_IOSTART     0x300
+#define LAN_IOEND       0x320
+static struct resource smc91x_resources[] = {
+       [0] = {
+               .start  = (LAN_IOSTART),
+               .end    = (LAN_IOEND),
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = M32R_IRQ_INT0,
+               .end    = M32R_IRQ_INT0,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device smc91x_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smc91x_resources),
+       .resource       = smc91x_resources,
+};
+
+static int __init platform_init(void)
+{
+       platform_device_register(&smc91x_device);
+       return 0;
+}
+arch_initcall(platform_init);
diff --git a/arch/m32r/kernel/setup_oaks32r.c b/arch/m32r/kernel/setup_oaks32r.c
new file mode 100644 (file)
index 0000000..b048345
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ *  linux/arch/m32r/kernel/setup_oaks32r.c
+ *
+ *  Setup routines for OAKS32R Board
+ *
+ *  Copyright (c) 2002-2004   Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+       unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+icu_data_t icu_data[NR_IRQS];
+
+static void disable_oaks32r_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+       outl(data, port);
+}
+
+static void enable_oaks32r_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+       outl(data, port);
+}
+
+static void mask_and_ack_mappi(unsigned int irq)
+{
+       disable_oaks32r_irq(irq);
+}
+
+static void end_oaks32r_irq(unsigned int irq)
+{
+       enable_oaks32r_irq(irq);
+}
+
+static unsigned int startup_oaks32r_irq(unsigned int irq)
+{
+       enable_oaks32r_irq(irq);
+       return (0);
+}
+
+static void shutdown_oaks32r_irq(unsigned int irq)
+{
+       unsigned long port;
+
+       port = irq2port(irq);
+       outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type oaks32r_irq_type =
+{
+       "OAKS32R-IRQ",
+       startup_oaks32r_irq,
+       shutdown_oaks32r_irq,
+       enable_oaks32r_irq,
+       disable_oaks32r_irq,
+       mask_and_ack_mappi,
+       end_oaks32r_irq
+};
+
+void __init init_IRQ(void)
+{
+       static int once = 0;
+
+       if (once)
+               return;
+       else
+               once++;
+
+#ifdef CONFIG_NE2000
+       /* INT3 : LAN controller (RTL8019AS) */
+       irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_INT3].handler = &oaks32r_irq_type;
+       irq_desc[M32R_IRQ_INT3].action = 0;
+       irq_desc[M32R_IRQ_INT3].depth = 1;
+       icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+       disable_oaks32r_irq(M32R_IRQ_INT3);
+#endif /* CONFIG_M32R_NE2000 */
+
+       /* MFT2 : system timer */
+       irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_MFT2].handler = &oaks32r_irq_type;
+       irq_desc[M32R_IRQ_MFT2].action = 0;
+       irq_desc[M32R_IRQ_MFT2].depth = 1;
+       icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+       disable_oaks32r_irq(M32R_IRQ_MFT2);
+
+#ifdef CONFIG_SERIAL_M32R_SIO
+       /* SIO0_R : uart receive data */
+       irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_R].handler = &oaks32r_irq_type;
+       irq_desc[M32R_IRQ_SIO0_R].action = 0;
+       irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+       icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+       disable_oaks32r_irq(M32R_IRQ_SIO0_R);
+
+       /* SIO0_S : uart send data */
+       irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_S].handler = &oaks32r_irq_type;
+       irq_desc[M32R_IRQ_SIO0_S].action = 0;
+       irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+       icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+       disable_oaks32r_irq(M32R_IRQ_SIO0_S);
+
+       /* SIO1_R : uart receive data */
+       irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_R].handler = &oaks32r_irq_type;
+       irq_desc[M32R_IRQ_SIO1_R].action = 0;
+       irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+       icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+       disable_oaks32r_irq(M32R_IRQ_SIO1_R);
+
+       /* SIO1_S : uart send data */
+       irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_S].handler = &oaks32r_irq_type;
+       irq_desc[M32R_IRQ_SIO1_S].action = 0;
+       irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+       icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+       disable_oaks32r_irq(M32R_IRQ_SIO1_S);
+#endif /* CONFIG_SERIAL_M32R_SIO */
+
+}
diff --git a/arch/m32r/kernel/setup_opsput.c b/arch/m32r/kernel/setup_opsput.c
new file mode 100644 (file)
index 0000000..17a4d3e
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+ *  linux/arch/m32r/kernel/setup_opsput.c
+ *
+ *  Setup routines for Renesas OPSPUT Board
+ *
+ *  Copyright (c) 2002-2004
+ *     Hiroyuki Kondo, Hirokazu Takata,
+ *      Hitoshi Yamamoto, Takeo Takahashi, Mamoru Sakugawa
+ *
+ *  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/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+/*
+ * OPSP Interrupt Control Unit (Level 1)
+ */
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+       unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+static icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ];
+
+static void disable_opsput_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+       outl(data, port);
+}
+
+static void enable_opsput_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+       outl(data, port);
+}
+
+static void mask_and_ack_opsput(unsigned int irq)
+{
+       disable_opsput_irq(irq);
+}
+
+static void end_opsput_irq(unsigned int irq)
+{
+       enable_opsput_irq(irq);
+}
+
+static unsigned int startup_opsput_irq(unsigned int irq)
+{
+       enable_opsput_irq(irq);
+       return (0);
+}
+
+static void shutdown_opsput_irq(unsigned int irq)
+{
+       unsigned long port;
+
+       port = irq2port(irq);
+       outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type opsput_irq_type =
+{
+       "OPSPUT-IRQ",
+       startup_opsput_irq,
+       shutdown_opsput_irq,
+       enable_opsput_irq,
+       disable_opsput_irq,
+       mask_and_ack_opsput,
+       end_opsput_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on OPSPUT (Level 2)
+ */
+#define irq2pldirq(x)          ((x) - OPSPUT_PLD_IRQ_BASE)
+#define pldirq2port(x)         (unsigned long)((int)PLD_ICUCR1 + \
+                                (((x) - 1) * sizeof(unsigned short)))
+
+typedef struct {
+       unsigned short icucr;  /* ICU Control Register */
+} pld_icu_data_t;
+
+static pld_icu_data_t pld_icu_data[OPSPUT_NUM_PLD_IRQ];
+
+static void disable_opsput_pld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2pldirq(irq);
+//     disable_opsput_irq(M32R_IRQ_INT1);
+       port = pldirq2port(pldirq);
+       data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+       outw(data, port);
+}
+
+static void enable_opsput_pld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2pldirq(irq);
+//     enable_opsput_irq(M32R_IRQ_INT1);
+       port = pldirq2port(pldirq);
+       data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+       outw(data, port);
+}
+
+static void mask_and_ack_opsput_pld(unsigned int irq)
+{
+       disable_opsput_pld_irq(irq);
+//     mask_and_ack_opsput(M32R_IRQ_INT1);
+}
+
+static void end_opsput_pld_irq(unsigned int irq)
+{
+       enable_opsput_pld_irq(irq);
+       end_opsput_irq(M32R_IRQ_INT1);
+}
+
+static unsigned int startup_opsput_pld_irq(unsigned int irq)
+{
+       enable_opsput_pld_irq(irq);
+       return (0);
+}
+
+static void shutdown_opsput_pld_irq(unsigned int irq)
+{
+       unsigned long port;
+       unsigned int pldirq;
+
+       pldirq = irq2pldirq(irq);
+//     shutdown_opsput_irq(M32R_IRQ_INT1);
+       port = pldirq2port(pldirq);
+       outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type opsput_pld_irq_type =
+{
+       "OPSPUT-PLD-IRQ",
+       startup_opsput_pld_irq,
+       shutdown_opsput_pld_irq,
+       enable_opsput_pld_irq,
+       disable_opsput_pld_irq,
+       mask_and_ack_opsput_pld,
+       end_opsput_pld_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on OPSPUT-LAN (Level 2)
+ */
+#define irq2lanpldirq(x)       ((x) - OPSPUT_LAN_PLD_IRQ_BASE)
+#define lanpldirq2port(x)      (unsigned long)((int)OPSPUT_LAN_ICUCR1 + \
+                                (((x) - 1) * sizeof(unsigned short)))
+
+static pld_icu_data_t lanpld_icu_data[OPSPUT_NUM_LAN_PLD_IRQ];
+
+static void disable_opsput_lanpld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2lanpldirq(irq);
+       port = lanpldirq2port(pldirq);
+       data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+       outw(data, port);
+}
+
+static void enable_opsput_lanpld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2lanpldirq(irq);
+       port = lanpldirq2port(pldirq);
+       data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+       outw(data, port);
+}
+
+static void mask_and_ack_opsput_lanpld(unsigned int irq)
+{
+       disable_opsput_lanpld_irq(irq);
+}
+
+static void end_opsput_lanpld_irq(unsigned int irq)
+{
+       enable_opsput_lanpld_irq(irq);
+       end_opsput_irq(M32R_IRQ_INT0);
+}
+
+static unsigned int startup_opsput_lanpld_irq(unsigned int irq)
+{
+       enable_opsput_lanpld_irq(irq);
+       return (0);
+}
+
+static void shutdown_opsput_lanpld_irq(unsigned int irq)
+{
+       unsigned long port;
+       unsigned int pldirq;
+
+       pldirq = irq2lanpldirq(irq);
+       port = lanpldirq2port(pldirq);
+       outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type opsput_lanpld_irq_type =
+{
+       "OPSPUT-PLD-LAN-IRQ",
+       startup_opsput_lanpld_irq,
+       shutdown_opsput_lanpld_irq,
+       enable_opsput_lanpld_irq,
+       disable_opsput_lanpld_irq,
+       mask_and_ack_opsput_lanpld,
+       end_opsput_lanpld_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on OPSPUT-LCD (Level 2)
+ */
+#define irq2lcdpldirq(x)       ((x) - OPSPUT_LCD_PLD_IRQ_BASE)
+#define lcdpldirq2port(x)      (unsigned long)((int)OPSPUT_LCD_ICUCR1 + \
+                                (((x) - 1) * sizeof(unsigned short)))
+
+static pld_icu_data_t lcdpld_icu_data[OPSPUT_NUM_LCD_PLD_IRQ];
+
+static void disable_opsput_lcdpld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2lcdpldirq(irq);
+       port = lcdpldirq2port(pldirq);
+       data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+       outw(data, port);
+}
+
+static void enable_opsput_lcdpld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2lcdpldirq(irq);
+       port = lcdpldirq2port(pldirq);
+       data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+       outw(data, port);
+}
+
+static void mask_and_ack_opsput_lcdpld(unsigned int irq)
+{
+       disable_opsput_lcdpld_irq(irq);
+}
+
+static void end_opsput_lcdpld_irq(unsigned int irq)
+{
+       enable_opsput_lcdpld_irq(irq);
+       end_opsput_irq(M32R_IRQ_INT2);
+}
+
+static unsigned int startup_opsput_lcdpld_irq(unsigned int irq)
+{
+       enable_opsput_lcdpld_irq(irq);
+       return (0);
+}
+
+static void shutdown_opsput_lcdpld_irq(unsigned int irq)
+{
+       unsigned long port;
+       unsigned int pldirq;
+
+       pldirq = irq2lcdpldirq(irq);
+       port = lcdpldirq2port(pldirq);
+       outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type opsput_lcdpld_irq_type =
+{
+       "OPSPUT-PLD-LCD-IRQ",
+       startup_opsput_lcdpld_irq,
+       shutdown_opsput_lcdpld_irq,
+       enable_opsput_lcdpld_irq,
+       disable_opsput_lcdpld_irq,
+       mask_and_ack_opsput_lcdpld,
+       end_opsput_lcdpld_irq
+};
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_SMC91X)
+       /* INT#0: LAN controller on OPSPUT-LAN (SMC91C111)*/
+       irq_desc[OPSPUT_LAN_IRQ_LAN].status = IRQ_DISABLED;
+       irq_desc[OPSPUT_LAN_IRQ_LAN].handler = &opsput_lanpld_irq_type;
+       irq_desc[OPSPUT_LAN_IRQ_LAN].action = 0;
+       irq_desc[OPSPUT_LAN_IRQ_LAN].depth = 1; /* disable nested irq */
+       lanpld_icu_data[irq2lanpldirq(OPSPUT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;     /* "H" edge sense */
+       disable_opsput_lanpld_irq(OPSPUT_LAN_IRQ_LAN);
+#endif  /* CONFIG_SMC91X */
+
+       /* MFT2 : system timer */
+       irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_MFT2].handler = &opsput_irq_type;
+       irq_desc[M32R_IRQ_MFT2].action = 0;
+       irq_desc[M32R_IRQ_MFT2].depth = 1;
+       icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+       disable_opsput_irq(M32R_IRQ_MFT2);
+
+       /* SIO0 : receive */
+       irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_R].handler = &opsput_irq_type;
+       irq_desc[M32R_IRQ_SIO0_R].action = 0;
+       irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+       icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+       disable_opsput_irq(M32R_IRQ_SIO0_R);
+
+       /* SIO0 : send */
+       irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_S].handler = &opsput_irq_type;
+       irq_desc[M32R_IRQ_SIO0_S].action = 0;
+       irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+       icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+       disable_opsput_irq(M32R_IRQ_SIO0_S);
+
+       /* SIO1 : receive */
+       irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_R].handler = &opsput_irq_type;
+       irq_desc[M32R_IRQ_SIO1_R].action = 0;
+       irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+       icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+       disable_opsput_irq(M32R_IRQ_SIO1_R);
+
+       /* SIO1 : send */
+       irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_S].handler = &opsput_irq_type;
+       irq_desc[M32R_IRQ_SIO1_S].action = 0;
+       irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+       icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+       disable_opsput_irq(M32R_IRQ_SIO1_S);
+
+       /* DMA1 : */
+       irq_desc[M32R_IRQ_DMA1].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_DMA1].handler = &opsput_irq_type;
+       irq_desc[M32R_IRQ_DMA1].action = 0;
+       irq_desc[M32R_IRQ_DMA1].depth = 1;
+       icu_data[M32R_IRQ_DMA1].icucr = 0;
+       disable_opsput_irq(M32R_IRQ_DMA1);
+
+#ifdef CONFIG_SERIAL_M32R_PLDSIO
+       /* INT#1: SIO0 Receive on PLD */
+       irq_desc[PLD_IRQ_SIO0_RCV].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_SIO0_RCV].handler = &opsput_pld_irq_type;
+       irq_desc[PLD_IRQ_SIO0_RCV].action = 0;
+       irq_desc[PLD_IRQ_SIO0_RCV].depth = 1;   /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
+       disable_opsput_pld_irq(PLD_IRQ_SIO0_RCV);
+
+       /* INT#1: SIO0 Send on PLD */
+       irq_desc[PLD_IRQ_SIO0_SND].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_SIO0_SND].handler = &opsput_pld_irq_type;
+       irq_desc[PLD_IRQ_SIO0_SND].action = 0;
+       irq_desc[PLD_IRQ_SIO0_SND].depth = 1;   /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
+       disable_opsput_pld_irq(PLD_IRQ_SIO0_SND);
+#endif  /* CONFIG_SERIAL_M32R_PLDSIO */
+
+#if defined(CONFIG_M32R_CFC)
+       /* INT#1: CFC IREQ on PLD */
+       irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_CFIREQ].handler = &opsput_pld_irq_type;
+       irq_desc[PLD_IRQ_CFIREQ].action = 0;
+       irq_desc[PLD_IRQ_CFIREQ].depth = 1;     /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;       /* 'L' level sense */
+       disable_opsput_pld_irq(PLD_IRQ_CFIREQ);
+
+       /* INT#1: CFC Insert on PLD */
+       irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_CFC_INSERT].handler = &opsput_pld_irq_type;
+       irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+       irq_desc[PLD_IRQ_CFC_INSERT].depth = 1; /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00;   /* 'L' edge sense */
+       disable_opsput_pld_irq(PLD_IRQ_CFC_INSERT);
+
+       /* INT#1: CFC Eject on PLD */
+       irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_CFC_EJECT].handler = &opsput_pld_irq_type;
+       irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+       irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;  /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;    /* 'H' edge sense */
+       disable_opsput_pld_irq(PLD_IRQ_CFC_EJECT);
+#endif /* CONFIG_M32R_CFC */
+
+
+       /*
+        * INT0# is used for LAN, DIO
+        * We enable it here.
+        */
+       icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
+       enable_opsput_irq(M32R_IRQ_INT0);
+
+       /*
+        * INT1# is used for UART, MMC, CF Controller in FPGA.
+        * We enable it here.
+        */
+       icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
+       enable_opsput_irq(M32R_IRQ_INT1);
+
+#if defined(CONFIG_USB)
+       outw(USBCR_OTGS, USBCR);        /* USBCR: non-OTG */
+
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].status = IRQ_DISABLED;
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].handler = &opsput_lcdpld_irq_type;
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].action = 0;
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].depth = 1;
+    lcdpld_icu_data[irq2lcdpldirq(OPSPUT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;   /* "L" level sense */
+    disable_opsput_lcdpld_irq(OPSPUT_LCD_IRQ_USB_INT1);
+#endif
+       /*
+        * INT2# is used for BAT, USB, AUDIO
+        * We enable it here.
+        */
+       icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
+       enable_opsput_irq(M32R_IRQ_INT2);
+
+//#if defined(CONFIG_M32R_AR_VGA)
+       /*
+        * INT3# is used for AR
+        */
+       irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_INT3].handler = &opsput_irq_type;
+       irq_desc[M32R_IRQ_INT3].action = 0;
+       irq_desc[M32R_IRQ_INT3].depth = 1;
+       icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+       disable_opsput_irq(M32R_IRQ_INT3);
+//#endif       /* CONFIG_M32R_ARV */
+}
+
+#define LAN_IOSTART     0x300
+#define LAN_IOEND       0x320
+static struct resource smc91x_resources[] = {
+       [0] = {
+               .start  = (LAN_IOSTART),
+               .end    = (LAN_IOEND),
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = OPSPUT_LAN_IRQ_LAN,
+               .end    = OPSPUT_LAN_IRQ_LAN,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device smc91x_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smc91x_resources),
+       .resource       = smc91x_resources,
+};
+
+static int __init platform_init(void)
+{
+       platform_device_register(&smc91x_device);
+       return 0;
+}
+arch_initcall(platform_init);
diff --git a/arch/m32r/kernel/setup_usrv.c b/arch/m32r/kernel/setup_usrv.c
new file mode 100644 (file)
index 0000000..fe417be
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ *  linux/arch/m32r/kernel/setup_usrv.c
+ *
+ *  Setup routines for MITSUBISHI uServer
+ *
+ *  Copyright (c) 2001, 2002, 2003  Hiroyuki Kondo, Hirokazu Takata,
+ *                                  Hitoshi Yamamoto
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#if !defined(CONFIG_SMP)
+typedef struct {
+       unsigned long icucr;    /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
+
+static void disable_mappi_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+       outl(data, port);
+}
+
+static void enable_mappi_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+       outl(data, port);
+}
+
+static void mask_and_ack_mappi(unsigned int irq)
+{
+       disable_mappi_irq(irq);
+}
+
+static void end_mappi_irq(unsigned int irq)
+{
+       enable_mappi_irq(irq);
+}
+
+static unsigned int startup_mappi_irq(unsigned int irq)
+{
+       enable_mappi_irq(irq);
+       return 0;
+}
+
+static void shutdown_mappi_irq(unsigned int irq)
+{
+       unsigned long port;
+
+       port = irq2port(irq);
+       outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type mappi_irq_type =
+{
+       "M32700-IRQ",
+       startup_mappi_irq,
+       shutdown_mappi_irq,
+       enable_mappi_irq,
+       disable_mappi_irq,
+       mask_and_ack_mappi,
+       end_mappi_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on M32700UT (Level 2)
+ */
+#define irq2pldirq(x)          ((x) - M32700UT_PLD_IRQ_BASE)
+#define pldirq2port(x)         (unsigned long)((int)PLD_ICUCR1 + \
+                                (((x) - 1) * sizeof(unsigned short)))
+
+typedef struct {
+       unsigned short icucr;  /* ICU Control Register */
+} pld_icu_data_t;
+
+static pld_icu_data_t pld_icu_data[M32700UT_NUM_PLD_IRQ];
+
+static void disable_m32700ut_pld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2pldirq(irq);
+       port = pldirq2port(pldirq);
+       data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+       outw(data, port);
+}
+
+static void enable_m32700ut_pld_irq(unsigned int irq)
+{
+       unsigned long port, data;
+       unsigned int pldirq;
+
+       pldirq = irq2pldirq(irq);
+       port = pldirq2port(pldirq);
+       data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+       outw(data, port);
+}
+
+static void mask_and_ack_m32700ut_pld(unsigned int irq)
+{
+       disable_m32700ut_pld_irq(irq);
+}
+
+static void end_m32700ut_pld_irq(unsigned int irq)
+{
+       enable_m32700ut_pld_irq(irq);
+       end_mappi_irq(M32R_IRQ_INT1);
+}
+
+static unsigned int startup_m32700ut_pld_irq(unsigned int irq)
+{
+       enable_m32700ut_pld_irq(irq);
+       return 0;
+}
+
+static void shutdown_m32700ut_pld_irq(unsigned int irq)
+{
+       unsigned long port;
+       unsigned int pldirq;
+
+       pldirq = irq2pldirq(irq);
+       port = pldirq2port(pldirq);
+       outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type m32700ut_pld_irq_type =
+{
+       "USRV-PLD-IRQ",
+       startup_m32700ut_pld_irq,
+       shutdown_m32700ut_pld_irq,
+       enable_m32700ut_pld_irq,
+       disable_m32700ut_pld_irq,
+       mask_and_ack_m32700ut_pld,
+       end_m32700ut_pld_irq
+};
+
+void __init init_IRQ(void)
+{
+       static int once = 0;
+       int i;
+
+       if (once)
+               return;
+       else
+               once++;
+
+       /* MFT2 : system timer */
+       irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_MFT2].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_MFT2].action = 0;
+       irq_desc[M32R_IRQ_MFT2].depth = 1;
+       icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+       disable_mappi_irq(M32R_IRQ_MFT2);
+
+#if defined(CONFIG_SERIAL_M32R_SIO)
+       /* SIO0_R : uart receive data */
+       irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_R].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_SIO0_R].action = 0;
+       irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+       icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+       disable_mappi_irq(M32R_IRQ_SIO0_R);
+
+       /* SIO0_S : uart send data */
+       irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_S].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_SIO0_S].action = 0;
+       irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+       icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+       disable_mappi_irq(M32R_IRQ_SIO0_S);
+
+       /* SIO1_R : uart receive data */
+       irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_R].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_SIO1_R].action = 0;
+       irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+       icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+       disable_mappi_irq(M32R_IRQ_SIO1_R);
+
+       /* SIO1_S : uart send data */
+       irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_S].handler = &mappi_irq_type;
+       irq_desc[M32R_IRQ_SIO1_S].action = 0;
+       irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+       icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+       disable_mappi_irq(M32R_IRQ_SIO1_S);
+#endif  /* CONFIG_SERIAL_M32R_SIO */
+
+       /* INT#67-#71: CFC#0 IREQ on PLD */
+       for (i = 0 ; i < CONFIG_CFC_NUM ; i++ ) {
+               irq_desc[PLD_IRQ_CF0 + i].status = IRQ_DISABLED;
+               irq_desc[PLD_IRQ_CF0 + i].handler = &m32700ut_pld_irq_type;
+               irq_desc[PLD_IRQ_CF0 + i].action = 0;
+               irq_desc[PLD_IRQ_CF0 + i].depth = 1;    /* disable nested irq */
+               pld_icu_data[irq2pldirq(PLD_IRQ_CF0 + i)].icucr
+                       = PLD_ICUCR_ISMOD01;    /* 'L' level sense */
+               disable_m32700ut_pld_irq(PLD_IRQ_CF0 + i);
+       }
+
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+       /* INT#76: 16552D#0 IREQ on PLD */
+       irq_desc[PLD_IRQ_UART0].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_UART0].handler = &m32700ut_pld_irq_type;
+       irq_desc[PLD_IRQ_UART0].action = 0;
+       irq_desc[PLD_IRQ_UART0].depth = 1;      /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_UART0)].icucr
+               = PLD_ICUCR_ISMOD03;    /* 'H' level sense */
+       disable_m32700ut_pld_irq(PLD_IRQ_UART0);
+
+       /* INT#77: 16552D#1 IREQ on PLD */
+       irq_desc[PLD_IRQ_UART1].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_UART1].handler = &m32700ut_pld_irq_type;
+       irq_desc[PLD_IRQ_UART1].action = 0;
+       irq_desc[PLD_IRQ_UART1].depth = 1;      /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_UART1)].icucr
+               = PLD_ICUCR_ISMOD03;    /* 'H' level sense */
+       disable_m32700ut_pld_irq(PLD_IRQ_UART1);
+#endif /* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
+
+#if defined(CONFIG_IDC_AK4524) || defined(CONFIG_IDC_AK4524_MODULE)
+       /* INT#80: AK4524 IREQ on PLD */
+       irq_desc[PLD_IRQ_SNDINT].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_SNDINT].handler = &m32700ut_pld_irq_type;
+       irq_desc[PLD_IRQ_SNDINT].action = 0;
+       irq_desc[PLD_IRQ_SNDINT].depth = 1;     /* disable nested irq */
+       pld_icu_data[irq2pldirq(PLD_IRQ_SNDINT)].icucr
+               = PLD_ICUCR_ISMOD01;    /* 'L' level sense */
+       disable_m32700ut_pld_irq(PLD_IRQ_SNDINT);
+#endif /* CONFIG_IDC_AK4524 || CONFIG_IDC_AK4524_MODULE */
+
+       /*
+        * INT1# is used for UART, MMC, CF Controller in FPGA.
+        * We enable it here.
+        */
+       icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD11;
+       enable_mappi_irq(M32R_IRQ_INT1);
+}
+
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
new file mode 100644 (file)
index 0000000..cbfa674
--- /dev/null
@@ -0,0 +1,621 @@
+/*
+ *  linux/arch/m32r/kernel/signal.c
+ *
+ *  Copyright (c) 2003  Hitoshi Yamamoto
+ *
+ *  Taken from i386 version.
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
+ *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/personality.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+int do_signal(struct pt_regs *, sigset_t *);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int
+sys_sigsuspend(old_sigset_t mask, unsigned long r1,
+              unsigned long r2, unsigned long r3, unsigned long r4,
+              unsigned long r5, unsigned long r6, struct pt_regs regs)
+{
+       sigset_t saveset;
+
+       mask &= _BLOCKABLE;
+       spin_lock_irq(&current->sighand->siglock);
+       saveset = current->blocked;
+       siginitset(&current->blocked, mask);
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
+
+       regs.r0 = -EINTR;
+       while (1) {
+               current->state = TASK_INTERRUPTIBLE;
+               schedule();
+               if (do_signal(&regs, &saveset))
+                       return regs.r0;
+       }
+}
+
+asmlinkage int
+sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
+                 unsigned long r2, unsigned long r3, unsigned long r4,
+                 unsigned long r5, unsigned long r6, struct pt_regs regs)
+{
+       sigset_t saveset, newset;
+
+       /* XXX: Don't preclude handling different sized sigset_t's.  */
+       if (sigsetsize != sizeof(sigset_t))
+               return -EINVAL;
+
+       if (copy_from_user(&newset, unewset, sizeof(newset)))
+               return -EFAULT;
+       sigdelsetmask(&newset, ~_BLOCKABLE);
+
+       spin_lock_irq(&current->sighand->siglock);
+       saveset = current->blocked;
+       current->blocked = newset;
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
+
+       regs.r0 = -EINTR;
+       while (1) {
+               current->state = TASK_INTERRUPTIBLE;
+               schedule();
+               if (do_signal(&regs, &saveset))
+                       return regs.r0;
+       }
+}
+
+asmlinkage int
+sys_sigaction(int sig, const struct old_sigaction __user *act,
+             struct old_sigaction __user *oact)
+{
+       struct k_sigaction new_ka, old_ka;
+       int ret;
+
+       if (act) {
+               old_sigset_t mask;
+               if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+                   __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+                       return -EFAULT;
+               __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+               __get_user(mask, &act->sa_mask);
+               siginitset(&new_ka.sa.sa_mask, mask);
+       }
+
+       ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+       if (!ret && oact) {
+               if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+                   __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+                       return -EFAULT;
+               __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+               __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+       }
+
+       return ret;
+}
+
+asmlinkage int
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+               unsigned long r2, unsigned long r3, unsigned long r4,
+               unsigned long r5, unsigned long r6, struct pt_regs regs)
+{
+       return do_sigaltstack(uss, uoss, regs.spu);
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+
+struct sigframe
+{
+//     char *pretcode;
+       int sig;
+       struct sigcontext sc;
+//     struct _fpstate fpstate;
+       unsigned long extramask[_NSIG_WORDS-1];
+       char retcode[4];
+};
+
+struct rt_sigframe
+{
+//     char *pretcode;
+       int sig;
+       struct siginfo *pinfo;
+       void *puc;
+       struct siginfo info;
+       struct ucontext uc;
+//     struct _fpstate fpstate;
+       char retcode[8];
+};
+
+static int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
+                  int *r0_p)
+{
+       unsigned int err = 0;
+
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+#define COPY(x)                err |= __get_user(regs->x, &sc->sc_##x)
+       COPY(r4);
+       COPY(r5);
+       COPY(r6);
+       COPY(pt_regs);
+       /* COPY(r0); Skip r0 */
+       COPY(r1);
+       COPY(r2);
+       COPY(r3);
+       COPY(r7);
+       COPY(r8);
+       COPY(r9);
+       COPY(r10);
+       COPY(r11);
+       COPY(r12);
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+       COPY(acc0h);
+       COPY(acc0l);
+       COPY(acc1h);
+       COPY(acc1l);
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+       COPY(acch);
+       COPY(accl);
+#else
+#error unknown isa configuration
+#endif
+       COPY(psw);
+       COPY(bpc);
+       COPY(bbpsw);
+       COPY(bbpc);
+       COPY(spu);
+       COPY(fp);
+       COPY(lr);
+       COPY(spi);
+#undef COPY
+
+       regs->syscall_nr = -1;  /* disable syscall checks */
+       err |= __get_user(*r0_p, &sc->sc_r0);
+
+       return err;
+}
+
+asmlinkage int
+sys_sigreturn(unsigned long r0, unsigned long r1,
+             unsigned long r2, unsigned long r3, unsigned long r4,
+             unsigned long r5, unsigned long r6, struct pt_regs regs)
+{
+       struct sigframe __user *frame = (struct sigframe __user *)regs.spu;
+       sigset_t set;
+       int result;
+
+       if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+               goto badframe;
+       if (__get_user(set.sig[0], &frame->sc.oldmask)
+           || (_NSIG_WORDS > 1
+               && __copy_from_user(&set.sig[1], &frame->extramask,
+                                   sizeof(frame->extramask))))
+               goto badframe;
+
+       sigdelsetmask(&set, ~_BLOCKABLE);
+       spin_lock_irq(&current->sighand->siglock);
+       current->blocked = set;
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
+
+       if (restore_sigcontext(&regs, &frame->sc, &result))
+               goto badframe;
+       return result;
+
+badframe:
+       force_sig(SIGSEGV, current);
+       return 0;
+}
+
+asmlinkage int
+sys_rt_sigreturn(unsigned long r0, unsigned long r1,
+                unsigned long r2, unsigned long r3, unsigned long r4,
+                unsigned long r5, unsigned long r6, struct pt_regs regs)
+{
+       struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.spu;
+       sigset_t set;
+       stack_t st;
+       int result;
+
+       if (verify_area(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 (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &result))
+               goto badframe;
+
+       if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+               goto badframe;
+       /* It is more difficult to avoid calling this function than to
+          call it and ignore errors.  */
+       do_sigaltstack(&st, NULL, regs.spu);
+
+       return result;
+
+badframe:
+       force_sig(SIGSEGV, current);
+       return 0;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+static int
+setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
+                unsigned long mask)
+{
+       int err = 0;
+
+#define COPY(x)        err |= __put_user(regs->x, &sc->sc_##x)
+       COPY(r4);
+       COPY(r5);
+       COPY(r6);
+       COPY(pt_regs);
+       COPY(r0);
+       COPY(r1);
+       COPY(r2);
+       COPY(r3);
+       COPY(r7);
+       COPY(r8);
+       COPY(r9);
+       COPY(r10);
+       COPY(r11);
+       COPY(r12);
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+       COPY(acc0h);
+       COPY(acc0l);
+       COPY(acc1h);
+       COPY(acc1l);
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+       COPY(acch);
+       COPY(accl);
+#else
+#error unknown isa configuration
+#endif
+       COPY(psw);
+       COPY(bpc);
+       COPY(bbpsw);
+       COPY(bbpc);
+       COPY(spu);
+       COPY(fp);
+       COPY(lr);
+       COPY(spi);
+#undef COPY
+
+       err |= __put_user(mask, &sc->oldmask);
+
+       return err;
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline void __user *
+get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+{
+       /* This is the X/Open sanctioned signal stack switching.  */
+       if (ka->sa.sa_flags & SA_ONSTACK) {
+               if (sas_ss_flags(sp) == 0)
+                       sp = current->sas_ss_sp + current->sas_ss_size;
+       }
+
+       return (void __user *)((sp - frame_size) & -8ul);
+}
+
+static void setup_frame(int sig, struct k_sigaction *ka,
+                       sigset_t *set, struct pt_regs *regs)
+{
+       struct sigframe __user *frame;
+       int err = 0;
+       int signal;
+
+       frame = get_sigframe(ka, regs->spu, sizeof(*frame));
+
+       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+               goto give_sigsegv;
+
+       signal = current_thread_info()->exec_domain
+               && current_thread_info()->exec_domain->signal_invmap
+               && sig < 32
+               ? current_thread_info()->exec_domain->signal_invmap[sig]
+               : sig;
+
+       err |= __put_user(signal, &frame->sig);
+       if (err)
+               goto give_sigsegv;
+
+       err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
+       if (err)
+               goto give_sigsegv;
+
+       if (_NSIG_WORDS > 1) {
+               err |= __copy_to_user(frame->extramask, &set->sig[1],
+                                     sizeof(frame->extramask));
+               if (err)
+                       goto give_sigsegv;
+       }
+
+       if (ka->sa.sa_flags & SA_RESTORER)
+               regs->lr = (unsigned long)ka->sa.sa_restorer;
+       else {
+               /* This is : ldi r7, #__NR_sigreturn ; trap #2 */
+               unsigned long code = 0x670010f2 | (__NR_sigreturn << 16);
+
+               regs->lr = (unsigned long)frame->retcode;
+               err |= __put_user(code, (long __user *)(frame->retcode+0));
+               if (err)
+                       goto give_sigsegv;
+               flush_cache_sigtramp((unsigned long)frame->retcode);
+       }
+
+       /* Set up registers for signal handler */
+       regs->spu = (unsigned long)frame;
+       regs->r0 = signal;      /* Arg for signal handler */
+       regs->r1 = (unsigned long)&frame->sc;
+       regs->bpc = (unsigned long)ka->sa.sa_handler;
+
+       set_fs(USER_DS);
+
+#if DEBUG_SIG
+       printk("SIG deliver (%s:%d): sp=%p pc=%p\n",
+               current->comm, current->pid, frame, regs->pc);
+#endif
+
+       return;
+
+give_sigsegv:
+       force_sigsegv(sig, current);
+}
+
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+                          sigset_t *set, struct pt_regs *regs)
+{
+       struct rt_sigframe __user *frame;
+       int err = 0;
+       int signal;
+
+       frame = get_sigframe(ka, regs->spu, sizeof(*frame));
+
+       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+               goto give_sigsegv;
+
+       signal = current_thread_info()->exec_domain
+               && current_thread_info()->exec_domain->signal_invmap
+               && sig < 32
+               ? current_thread_info()->exec_domain->signal_invmap[sig]
+               : sig;
+
+       err |= __put_user(signal, &frame->sig);
+       if (err)
+               goto give_sigsegv;
+
+       err |= __put_user(&frame->info, &frame->pinfo);
+       err |= __put_user(&frame->uc, &frame->puc);
+       err |= copy_siginfo_to_user(&frame->info, info);
+       if (err)
+               goto give_sigsegv;
+
+       /* Create the ucontext.  */
+       err |= __put_user(0, &frame->uc.uc_flags);
+       err |= __put_user(0, &frame->uc.uc_link);
+       err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+       err |= __put_user(sas_ss_flags(regs->spu),
+                         &frame->uc.uc_stack.ss_flags);
+       err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+       err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
+       err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+       if (err)
+               goto give_sigsegv;
+
+       /* Set up to return from userspace.  */
+       if (ka->sa.sa_flags & SA_RESTORER)
+               regs->lr = (unsigned long)ka->sa.sa_restorer;
+       else {
+               /* This is : ldi r7, #__NR_rt_sigreturn ; trap #2 */
+               unsigned long code1 = 0x97f00000 | (__NR_rt_sigreturn);
+               unsigned long code2 = 0x10f2f000;
+
+               regs->lr = (unsigned long)frame->retcode;
+               err |= __put_user(code1, (long __user *)(frame->retcode+0));
+               err |= __put_user(code2, (long __user *)(frame->retcode+4));
+               if (err)
+                       goto give_sigsegv;
+               flush_cache_sigtramp((unsigned long)frame->retcode);
+       }
+
+       /* Set up registers for signal handler */
+       regs->spu = (unsigned long)frame;
+       regs->r0 = signal;      /* Arg for signal handler */
+       regs->r1 = (unsigned long)&frame->info;
+       regs->r2 = (unsigned long)&frame->uc;
+       regs->bpc = (unsigned long)ka->sa.sa_handler;
+
+       set_fs(USER_DS);
+
+#if DEBUG_SIG
+       printk("SIG deliver (%s:%d): sp=%p pc=%p\n",
+               current->comm, current->pid, frame, regs->pc);
+#endif
+
+       return;
+
+give_sigsegv:
+       force_sigsegv(sig, current);
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+
+static void
+handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
+             sigset_t *oldset, struct pt_regs *regs)
+{
+       unsigned short inst;
+
+       /* Are we from a system call? */
+       if (regs->syscall_nr >= 0) {
+               /* If so, check system call restarting.. */
+               switch (regs->r0) {
+                       case -ERESTART_RESTARTBLOCK:
+                       case -ERESTARTNOHAND:
+                               regs->r0 = -EINTR;
+                               break;
+
+                       case -ERESTARTSYS:
+                               if (!(ka->sa.sa_flags & SA_RESTART)) {
+                                       regs->r0 = -EINTR;
+                                       break;
+                               }
+                       /* fallthrough */
+                       case -ERESTARTNOINTR:
+                               regs->r0 = regs->orig_r0;
+                               inst = *(unsigned short *)(regs->bpc - 2);
+                               if ((inst & 0xfff0) == 0x10f0)  /* trap ? */
+                                       regs->bpc -= 2;
+                               else
+                                       regs->bpc -= 4;
+               }
+       }
+
+       /* Set up the stack frame */
+       if (ka->sa.sa_flags & SA_SIGINFO)
+               setup_rt_frame(sig, ka, info, oldset, regs);
+       else
+               setup_frame(sig, ka, oldset, regs);
+
+       if (!(ka->sa.sa_flags & SA_NODEFER)) {
+               spin_lock_irq(&current->sighand->siglock);
+               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+               sigaddset(&current->blocked,sig);
+               recalc_sigpending();
+               spin_unlock_irq(&current->sighand->siglock);
+       }
+}
+
+/*
+ * 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.
+ */
+int do_signal(struct pt_regs *regs, sigset_t *oldset)
+{
+       siginfo_t info;
+       int signr;
+       struct k_sigaction ka;
+       unsigned short inst;
+
+       /*
+        * We want the common case to go fast, which
+        * is why we may in certain cases get here from
+        * kernel mode. Just return without doing anything
+        * if so.
+        */
+       if (!user_mode(regs))
+               return 1;
+
+       if (current->flags & PF_FREEZE) {
+               refrigerator(0);
+               goto no_signal;
+       }
+
+       if (!oldset)
+               oldset = &current->blocked;
+
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+       if (signr > 0) {
+               /* Reenable any watchpoints before delivering the
+                * signal to user space. The processor register will
+                * have been cleared if the watchpoint triggered
+                * inside the kernel.
+                */
+
+               /* Whee!  Actually deliver the signal.  */
+               handle_signal(signr, &ka, &info, oldset, regs);
+               return 1;
+       }
+
+ no_signal:
+       /* Did we come from a system call? */
+       if (regs->syscall_nr >= 0) {
+               /* Restart the system call - no handlers present */
+               if (regs->r0 == -ERESTARTNOHAND ||
+                   regs->r0 == -ERESTARTSYS ||
+                   regs->r0 == -ERESTARTNOINTR) {
+                       regs->r0 = regs->orig_r0;
+                       inst = *(unsigned short *)(regs->bpc - 2);
+                       if ((inst & 0xfff0) == 0x10f0)  /* trap ? */
+                               regs->bpc -= 2;
+                       else
+                               regs->bpc -= 4;
+               }
+               if (regs->r0 == -ERESTART_RESTARTBLOCK){
+                       regs->r0 = regs->orig_r0;
+                       regs->r7 = __NR_restart_syscall;
+                       inst = *(unsigned short *)(regs->bpc - 2);
+                       if ((inst & 0xfff0) == 0x10f0)  /* trap ? */
+                               regs->bpc -= 2;
+                       else
+                               regs->bpc -= 4;
+               }
+       }
+       return 0;
+}
+
+/*
+ * notification of userspace execution resumption
+ * - triggered by current->work.notify_resume
+ */
+void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
+                     __u32 thread_info_flags)
+{
+       /* Pending single-step? */
+       if (thread_info_flags & _TIF_SINGLESTEP)
+               clear_thread_flag(TIF_SINGLESTEP);
+
+       /* deal with pending signal delivery */
+       if (thread_info_flags & _TIF_SIGPENDING)
+               do_signal(regs,oldset);
+
+       clear_thread_flag(TIF_IRET);
+}
diff --git a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c
new file mode 100644 (file)
index 0000000..2dc542e
--- /dev/null
@@ -0,0 +1,965 @@
+/*
+ *  linux/arch/m32r/kernel/smp.c
+ *
+ *  M32R SMP support routines.
+ *
+ *  Copyright (c) 2001, 2002  Hitoshi Yamamoto
+ *
+ *  Taken from i386 version.
+ *    (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+ *    (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
+ *
+ *  This code is released under the GNU General Public License version 2 or
+ *  later.
+ */
+
+#undef DEBUG_SMP
+
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/profile.h>
+#include <linux/cpu.h>
+
+#include <asm/cacheflush.h>
+#include <asm/pgalloc.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/m32r.h>
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Data structures and variables                                             */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*
+ * Structure and data for smp_call_function(). This is designed to minimise
+ * static memory requirements. It also looks cleaner.
+ */
+static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
+
+struct call_data_struct {
+       void (*func) (void *info);
+       void *info;
+       atomic_t started;
+       atomic_t finished;
+       int wait;
+} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
+
+static struct call_data_struct *call_data;
+
+/*
+ * For flush_cache_all()
+ */
+static spinlock_t flushcache_lock = SPIN_LOCK_UNLOCKED;
+static volatile unsigned long flushcache_cpumask = 0;
+
+/*
+ * For flush_tlb_others()
+ */
+static volatile cpumask_t flush_cpumask;
+static struct mm_struct *flush_mm;
+static struct vm_area_struct *flush_vma;
+static volatile unsigned long flush_va;
+static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED;
+#define FLUSH_ALL 0xffffffff
+
+DECLARE_PER_CPU(int, prof_multiplier);
+DECLARE_PER_CPU(int, prof_old_multiplier);
+DECLARE_PER_CPU(int, prof_counter);
+
+extern spinlock_t ipi_lock[];
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Function Prototypes                                                       */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+void smp_send_reschedule(int);
+void smp_reschedule_interrupt(void);
+
+void smp_flush_cache_all(void);
+void smp_flush_cache_all_interrupt(void);
+
+void smp_flush_tlb_all(void);
+static void flush_tlb_all_ipi(void *);
+
+void smp_flush_tlb_mm(struct mm_struct *);
+void smp_flush_tlb_range(struct vm_area_struct *, unsigned long, \
+       unsigned long);
+void smp_flush_tlb_page(struct vm_area_struct *, unsigned long);
+static void flush_tlb_others(cpumask_t, struct mm_struct *,
+       struct vm_area_struct *, unsigned long);
+void smp_invalidate_interrupt(void);
+
+void smp_send_stop(void);
+static void stop_this_cpu(void *);
+
+int smp_call_function(void (*) (void *), void *, int, int);
+void smp_call_function_interrupt(void);
+
+void smp_send_timer(void);
+void smp_ipi_timer_interrupt(struct pt_regs *);
+void smp_local_timer_interrupt(struct pt_regs *);
+
+void send_IPI_allbutself(int, int);
+static void send_IPI_mask(cpumask_t, int, int);
+unsigned long send_IPI_mask_phys(cpumask_t, int, int);
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Rescheduling request Routines                                             */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         smp_send_reschedule
+ *
+ * Description:  This routine requests other CPU to execute rescheduling.
+ *               1.Send 'RESCHEDULE_IPI' to other CPU.
+ *                 Request other CPU to execute 'smp_reschedule_interrupt()'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    cpu_id - Target CPU ID
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_send_reschedule(int cpu_id)
+{
+       WARN_ON(cpu_is_offline(cpu_id));
+       send_IPI_mask(cpumask_of_cpu(cpu_id), RESCHEDULE_IPI, 1);
+}
+
+/*==========================================================================*
+ * Name:         smp_reschedule_interrupt
+ *
+ * Description:  This routine executes on CPU which received
+ *               'RESCHEDULE_IPI'.
+ *               Rescheduling is processed at the exit of interrupt
+ *               operation.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_reschedule_interrupt(void)
+{
+       /* nothing to do */
+}
+
+/*==========================================================================*
+ * Name:         smp_flush_cache_all
+ *
+ * Description:  This routine sends a 'INVALIDATE_CACHE_IPI' to all other
+ *               CPUs in the system.
+ *
+ * Born on Date: 2003-05-28
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_flush_cache_all(void)
+{
+       cpumask_t cpumask;
+       unsigned long *mask;
+
+       preempt_disable();
+       cpumask = cpu_online_map;
+       cpu_clear(smp_processor_id(), cpumask);
+       spin_lock(&flushcache_lock);
+       mask=cpus_addr(cpumask);
+       atomic_set_mask(*mask, (atomic_t *)&flushcache_cpumask);
+       send_IPI_mask(cpumask, INVALIDATE_CACHE_IPI, 0);
+       _flush_cache_copyback_all();
+       while (flushcache_cpumask)
+               mb();
+       spin_unlock(&flushcache_lock);
+       preempt_enable();
+}
+
+void smp_flush_cache_all_interrupt(void)
+{
+       _flush_cache_copyback_all();
+       clear_bit(smp_processor_id(), &flushcache_cpumask);
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* TLB flush request Routins                                                 */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         smp_flush_tlb_all
+ *
+ * Description:  This routine flushes all processes TLBs.
+ *               1.Request other CPU to execute 'flush_tlb_all_ipi()'.
+ *               2.Execute 'do_flush_tlb_all_local()'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_flush_tlb_all(void)
+{
+       unsigned long flags;
+
+       preempt_disable();
+       local_irq_save(flags);
+       __flush_tlb_all();
+       local_irq_restore(flags);
+       smp_call_function(flush_tlb_all_ipi, 0, 1, 1);
+       preempt_enable();
+}
+
+/*==========================================================================*
+ * Name:         flush_tlb_all_ipi
+ *
+ * Description:  This routine flushes all local TLBs.
+ *               1.Execute 'do_flush_tlb_all_local()'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *info - not used
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+static void flush_tlb_all_ipi(void *info)
+{
+       __flush_tlb_all();
+}
+
+/*==========================================================================*
+ * Name:         smp_flush_tlb_mm
+ *
+ * Description:  This routine flushes the specified mm context TLB's.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *mm - a pointer to the mm struct for flush TLB
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_flush_tlb_mm(struct mm_struct *mm)
+{
+       int cpu_id = smp_processor_id();
+       cpumask_t cpu_mask;
+       unsigned long *mmc = &mm->context[cpu_id];
+       unsigned long flags;
+
+       preempt_disable();
+       cpu_mask = mm->cpu_vm_mask;
+       cpu_clear(cpu_id, cpu_mask);
+
+       if (*mmc != NO_CONTEXT) {
+               local_irq_save(flags);
+               *mmc = NO_CONTEXT;
+               if (mm == current->mm)
+                       activate_context(mm);
+               else
+                       cpu_clear(cpu_id, mm->cpu_vm_mask);
+               local_irq_restore(flags);
+       }
+       if (!cpus_empty(cpu_mask))
+               flush_tlb_others(cpu_mask, mm, NULL, FLUSH_ALL);
+
+       preempt_enable();
+}
+
+/*==========================================================================*
+ * Name:         smp_flush_tlb_range
+ *
+ * Description:  This routine flushes a range of pages.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *mm - a pointer to the mm struct for flush TLB
+ *               start - not used
+ *               end - not used
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+       unsigned long end)
+{
+       smp_flush_tlb_mm(vma->vm_mm);
+}
+
+/*==========================================================================*
+ * Name:         smp_flush_tlb_page
+ *
+ * Description:  This routine flushes one page.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *vma - a pointer to the vma struct include va
+ *               va - virtual address for flush TLB
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
+{
+       struct mm_struct *mm = vma->vm_mm;
+       int cpu_id = smp_processor_id();
+       cpumask_t cpu_mask;
+       unsigned long *mmc = &mm->context[cpu_id];
+       unsigned long flags;
+
+       preempt_disable();
+       cpu_mask = mm->cpu_vm_mask;
+       cpu_clear(cpu_id, cpu_mask);
+
+#ifdef DEBUG_SMP
+       if (!mm)
+               BUG();
+#endif
+
+       if (*mmc != NO_CONTEXT) {
+               local_irq_save(flags);
+               va &= PAGE_MASK;
+               va |= (*mmc & MMU_CONTEXT_ASID_MASK);
+               __flush_tlb_page(va);
+               local_irq_restore(flags);
+       }
+       if (!cpus_empty(cpu_mask))
+               flush_tlb_others(cpu_mask, mm, vma, va);
+
+       preempt_enable();
+}
+
+/*==========================================================================*
+ * Name:         flush_tlb_others
+ *
+ * Description:  This routine requests other CPU to execute flush TLB.
+ *               1.Setup parmeters.
+ *               2.Send 'INVALIDATE_TLB_IPI' to other CPU.
+ *                 Request other CPU to execute 'smp_invalidate_interrupt()'.
+ *               3.Wait for other CPUs operation finished.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    cpumask - bitmap of target CPUs
+ *               *mm -  a pointer to the mm struct for flush TLB
+ *               *vma -  a pointer to the vma struct include va
+ *               va - virtual address for flush TLB
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
+       struct vm_area_struct *vma, unsigned long va)
+{
+       unsigned long *mask;
+#ifdef DEBUG_SMP
+       unsigned long flags;
+       __save_flags(flags);
+       if (!(flags & 0x0040))  /* Interrupt Disable NONONO */
+               BUG();
+#endif /* DEBUG_SMP */
+
+       /*
+        * A couple of (to be removed) sanity checks:
+        *
+        * - we do not send IPIs to not-yet booted CPUs.
+        * - current CPU must not be in mask
+        * - mask must exist :)
+        */
+       BUG_ON(cpus_empty(cpumask));
+
+       BUG_ON(cpu_isset(smp_processor_id(), cpumask));
+       BUG_ON(!mm);
+
+       /* If a CPU which we ran on has gone down, OK. */
+       cpus_and(cpumask, cpumask, cpu_online_map);
+       if (cpus_empty(cpumask))
+               return;
+
+       /*
+        * i'm not happy about this global shared spinlock in the
+        * MM hot path, but we'll see how contended it is.
+        * Temporarily this turns IRQs off, so that lockups are
+        * detected by the NMI watchdog.
+        */
+       spin_lock(&tlbstate_lock);
+
+       flush_mm = mm;
+       flush_vma = vma;
+       flush_va = va;
+       mask=cpus_addr(cpumask);
+       atomic_set_mask(*mask, (atomic_t *)&flush_cpumask);
+
+       /*
+        * We have to send the IPI only to
+        * CPUs affected.
+        */
+       send_IPI_mask(cpumask, INVALIDATE_TLB_IPI, 0);
+
+       while (!cpus_empty(flush_cpumask)) {
+               /* nothing. lockup detection does not belong here */
+               mb();
+       }
+
+       flush_mm = NULL;
+       flush_vma = NULL;
+       flush_va = 0;
+       spin_unlock(&tlbstate_lock);
+}
+
+/*==========================================================================*
+ * Name:         smp_invalidate_interrupt
+ *
+ * Description:  This routine executes on CPU which received
+ *               'INVALIDATE_TLB_IPI'.
+ *               1.Flush local TLB.
+ *               2.Report flush TLB process was finished.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_invalidate_interrupt(void)
+{
+       int cpu_id = smp_processor_id();
+       unsigned long *mmc = &flush_mm->context[cpu_id];
+
+       if (!cpu_isset(cpu_id, flush_cpumask))
+               return;
+
+       if (flush_va == FLUSH_ALL) {
+               *mmc = NO_CONTEXT;
+               if (flush_mm == current->active_mm)
+                       activate_context(flush_mm);
+               else
+                       cpu_clear(cpu_id, flush_mm->cpu_vm_mask);
+       } else {
+               unsigned long va = flush_va;
+
+               if (*mmc != NO_CONTEXT) {
+                       va &= PAGE_MASK;
+                       va |= (*mmc & MMU_CONTEXT_ASID_MASK);
+                       __flush_tlb_page(va);
+               }
+       }
+       cpu_clear(cpu_id, flush_cpumask);
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Stop CPU request Routins                                                 */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         smp_send_stop
+ *
+ * Description:  This routine requests stop all CPUs.
+ *               1.Request other CPU to execute 'stop_this_cpu()'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_send_stop(void)
+{
+       smp_call_function(stop_this_cpu, NULL, 1, 0);
+}
+
+/*==========================================================================*
+ * Name:         stop_this_cpu
+ *
+ * Description:  This routine halt CPU.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+static void stop_this_cpu(void *dummy)
+{
+       int cpu_id = smp_processor_id();
+
+       /*
+        * Remove this CPU:
+        */
+       cpu_clear(cpu_id, cpu_online_map);
+
+       /*
+        * PSW IE = 1;
+        * IMASK = 0;
+        * goto SLEEP
+        */
+       local_irq_disable();
+       outl(0, M32R_ICU_IMASK_PORTL);
+       inl(M32R_ICU_IMASK_PORTL);      /* dummy read */
+       local_irq_enable();
+
+       for ( ; ; );
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Call function Routins                                                     */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         smp_call_function
+ *
+ * Description:  This routine sends a 'CALL_FUNCTION_IPI' to all other CPUs
+ *               in the system.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *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.
+ *
+ * Cautions:     You must not call this function with disabled interrupts or
+ *               from a hardware interrupt handler, you may call it from a
+ *               bottom half handler.
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
+       int wait)
+{
+       struct call_data_struct data;
+       int cpus;
+
+#ifdef DEBUG_SMP
+       unsigned long flags;
+       __save_flags(flags);
+       if (!(flags & 0x0040))  /* Interrupt Disable NONONO */
+               BUG();
+#endif /* DEBUG_SMP */
+
+       /* Holding any lock stops cpus from going down. */
+       spin_lock(&call_lock);
+       cpus = num_online_cpus() - 1;
+
+       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);
+       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_IPI, 0);
+
+       /* Wait for response */
+       while (atomic_read(&data.started) != cpus)
+               barrier();
+
+       if (wait)
+               while (atomic_read(&data.finished) != cpus)
+                       barrier();
+       spin_unlock(&call_lock);
+
+       return 0;
+}
+
+/*==========================================================================*
+ * Name:         smp_call_function_interrupt
+ *
+ * Description:  This routine executes on CPU which received
+ *               'CALL_FUNCTION_IPI'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_call_function_interrupt(void)
+{
+       void (*func) (void *info) = call_data->func;
+       void *info = call_data->info;
+       int wait = call_data->wait;
+
+       /*
+        * Notify initiating CPU that I've grabbed the data and am
+        * about to execute the function
+        */
+       mb();
+       atomic_inc(&call_data->started);
+       /*
+        * At this point the info structure may be out of scope unless wait==1
+        */
+       irq_enter();
+       (*func)(info);
+       irq_exit();
+
+       if (wait) {
+               mb();
+               atomic_inc(&call_data->finished);
+       }
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Timer Routins                                                             */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         smp_send_timer
+ *
+ * Description:  This routine sends a 'LOCAL_TIMER_IPI' to all other CPUs
+ *               in the system.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_send_timer(void)
+{
+       send_IPI_allbutself(LOCAL_TIMER_IPI, 1);
+}
+
+/*==========================================================================*
+ * Name:         smp_send_timer
+ *
+ * Description:  This routine executes on CPU which received
+ *               'LOCAL_TIMER_IPI'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *regs - a pointer to the saved regster info
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_ipi_timer_interrupt(struct pt_regs *regs)
+{
+       irq_enter();
+       smp_local_timer_interrupt(regs);
+       irq_exit();
+}
+
+/*==========================================================================*
+ * Name:         smp_local_timer_interrupt
+ *
+ * Description:  Local timer interrupt handler. It does both profiling and
+ *               process statistics/rescheduling.
+ *               We do profiling in every local tick, statistics/rescheduling
+ *               happen only every 'profiling multiplier' ticks. The default
+ *               multiplier is 1 and it can be changed by writing the new
+ *               multiplier value into /proc/profile.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *regs - a pointer to the saved regster info
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Original:     arch/i386/kernel/apic.c
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ * 2003-06-24 hy  use per_cpu structure.
+ *==========================================================================*/
+void smp_local_timer_interrupt(struct pt_regs *regs)
+{
+       int user = user_mode(regs);
+       int cpu_id = smp_processor_id();
+
+       /*
+        * The profiling function is SMP safe. (nothing can mess
+        * around with "current", and the profiling counters are
+        * updated with atomic operations). This is especially
+        * useful with a profiling multiplier != 1
+        */
+
+       profile_tick(CPU_PROFILING, regs);
+
+       if (--per_cpu(prof_counter, cpu_id) <= 0) {
+               /*
+                * The multiplier may have changed since the last time we got
+                * to this point as a result of the user writing to
+                * /proc/profile. In this case we need to adjust the APIC
+                * timer accordingly.
+                *
+                * Interrupts are already masked off at this point.
+                */
+               per_cpu(prof_counter, cpu_id)
+                       = per_cpu(prof_multiplier, cpu_id);
+               if (per_cpu(prof_counter, cpu_id)
+                       != per_cpu(prof_old_multiplier, cpu_id))
+               {
+                       per_cpu(prof_old_multiplier, cpu_id)
+                               = per_cpu(prof_counter, cpu_id);
+               }
+
+               update_process_times(user);
+       }
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Send IPI Routins                                                          */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         send_IPI_allbutself
+ *
+ * Description:  This routine sends a IPI to all other CPUs in the system.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    ipi_num - Number of IPI
+ *               try -  0 : Send IPI certainly.
+ *                     !0 : The following IPI is not sended when Target CPU
+ *                          has not received the before IPI.
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void send_IPI_allbutself(int ipi_num, int try)
+{
+       cpumask_t cpumask;
+
+       cpumask = cpu_online_map;
+       cpu_clear(smp_processor_id(), cpumask);
+
+       send_IPI_mask(cpumask, ipi_num, try);
+}
+
+/*==========================================================================*
+ * Name:         send_IPI_mask
+ *
+ * Description:  This routine sends a IPI to CPUs in the system.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    cpu_mask - Bitmap of target CPUs logical ID
+ *               ipi_num - Number of IPI
+ *               try -  0 : Send IPI certainly.
+ *                     !0 : The following IPI is not sended when Target CPU
+ *                          has not received the before IPI.
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+static void send_IPI_mask(cpumask_t cpumask, int ipi_num, int try)
+{
+       cpumask_t physid_mask, tmp;
+       int cpu_id, phys_id;
+       int num_cpus = num_online_cpus();
+
+       if (num_cpus <= 1)      /* NO MP */
+               return;
+
+       cpus_and(tmp, cpumask, cpu_online_map);
+       BUG_ON(!cpus_equal(cpumask, tmp));
+
+       physid_mask = CPU_MASK_NONE;
+       for_each_cpu_mask(cpu_id, cpumask){
+               if ((phys_id = cpu_to_physid(cpu_id)) != -1)
+                       cpu_set(phys_id, physid_mask);
+       }
+
+       send_IPI_mask_phys(physid_mask, ipi_num, try);
+}
+
+/*==========================================================================*
+ * Name:         send_IPI_mask_phys
+ *
+ * Description:  This routine sends a IPI to other CPUs in the system.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    cpu_mask - Bitmap of target CPUs physical ID
+ *               ipi_num - Number of IPI
+ *               try -  0 : Send IPI certainly.
+ *                     !0 : The following IPI is not sended when Target CPU
+ *                          has not received the before IPI.
+ *
+ * Returns:      IPICRi regster value.
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+unsigned long send_IPI_mask_phys(cpumask_t physid_mask, int ipi_num,
+       int try)
+{
+       spinlock_t *ipilock;
+       unsigned long flags = 0;
+       volatile unsigned long *ipicr_addr;
+       unsigned long ipicr_val;
+       unsigned long my_physid_mask;
+       unsigned long mask = cpus_addr(physid_mask)[0];
+
+
+       if (mask & ~physids_coerce(phys_cpu_present_map))
+               BUG();
+       if (ipi_num >= NR_IPIS)
+               BUG();
+
+       mask <<= IPI_SHIFT;
+       ipilock = &ipi_lock[ipi_num];
+       ipicr_addr = (volatile unsigned long *)(M32R_ICU_IPICR_ADDR
+               + (ipi_num << 2));
+       my_physid_mask = ~(1 << smp_processor_id());
+
+       /*
+        * lock ipi_lock[i]
+        * check IPICRi == 0
+        * write IPICRi (send IPIi)
+        * unlock ipi_lock[i]
+        */
+       __asm__ __volatile__ (
+               ";; LOCK ipi_lock[i]            \n\t"
+               ".fillinsn                      \n"
+               "1:                             \n\t"
+               "mvfc   %1, psw                 \n\t"
+               "clrpsw #0x40 -> nop            \n\t"
+               DCACHE_CLEAR("r4", "r5", "%2")
+               "lock   r4, @%2                 \n\t"
+               "addi   r4, #-1                 \n\t"
+               "unlock r4, @%2                 \n\t"
+               "mvtc   %1, psw                 \n\t"
+               "bnez   r4, 2f                  \n\t"
+               LOCK_SECTION_START(".balign 4 \n\t")
+               ".fillinsn                      \n"
+               "2:                             \n\t"
+               "ld     r4, @%2                 \n\t"
+               "blez   r4, 2b                  \n\t"
+               "bra    1b                      \n\t"
+               LOCK_SECTION_END
+               ";; CHECK IPICRi == 0           \n\t"
+               ".fillinsn                      \n"
+               "3:                             \n\t"
+               "ld     %0, @%3                 \n\t"
+               "and    %0, %6                  \n\t"
+               "beqz   %0, 4f                  \n\t"
+               "bnez   %5, 5f                  \n\t"
+               "bra    3b                      \n\t"
+               ";; WRITE IPICRi (send IPIi)    \n\t"
+               ".fillinsn                      \n"
+               "4:                             \n\t"
+               "st     %4, @%3                 \n\t"
+               ";; UNLOCK ipi_lock[i]          \n\t"
+               ".fillinsn                      \n"
+               "5:                             \n\t"
+               "ldi    r4, #1                  \n\t"
+               "st     r4, @%2                 \n\t"
+               : "=&r"(ipicr_val)
+               : "r"(flags), "r"(&ipilock->lock), "r"(ipicr_addr),
+                 "r"(mask), "r"(try), "r"(my_physid_mask)
+               : "memory", "r4"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r5"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+
+       return ipicr_val;
+}
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
new file mode 100644 (file)
index 0000000..6ac4f70
--- /dev/null
@@ -0,0 +1,635 @@
+/*
+ *  linux/arch/m32r/kernel/smpboot.c
+ *    orig : i386 2.4.10
+ *
+ *  M32R SMP booting functions
+ *
+ *  Copyright (c) 2001, 2002, 2003  Hitoshi Yamamoto
+ *
+ *  Taken from i386 version.
+ *       (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+ *       (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
+ *
+ *     Much of the core SMP work is based on previous work by Thomas Radke, to
+ *     whom a great many thanks are extended.
+ *
+ *     Thanks to Intel for making available several different Pentium,
+ *     Pentium Pro and Pentium-II/Xeon MP machines.
+ *     Original development of Linux SMP code supported by Caldera.
+ *
+ *     This code is released under the GNU General Public License version 2 or
+ *     later.
+ *
+ *     Fixes
+ *             Felix Koop      :       NR_CPUS used properly
+ *             Jose Renau      :       Handle single CPU case.
+ *             Alan Cox        :       By repeated request
+ *                                     8) - Total BogoMIP report.
+ *             Greg Wright     :       Fix for kernel stacks panic.
+ *             Erich Boleyn    :       MP v1.4 and additional changes.
+ *     Matthias Sattler        :       Changes for 2.1 kernel map.
+ *     Michel Lespinasse       :       Changes for 2.1 kernel map.
+ *     Michael Chastain        :       Change trampoline.S to gnu as.
+ *             Alan Cox        :       Dumb bug: 'B' step PPro's are fine
+ *             Ingo Molnar     :       Added APIC timers, based on code
+ *                                     from Jose Renau
+ *             Ingo Molnar     :       various cleanups and rewrites
+ *             Tigran Aivazian :       fixed "0.00 in /proc/uptime on SMP" bug.
+ *     Maciej W. Rozycki       :       Bits for genuine 82489DX APICs
+ *             Martin J. Bligh :       Added support for multi-quad systems
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+
+#define DEBUG_SMP
+#ifdef DEBUG_SMP
+#define Dprintk(x...) printk(x)
+#else
+#define Dprintk(x...)
+#endif
+
+extern int cpu_idle(void);
+extern cpumask_t cpu_initialized;
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Data structures and variables                                             */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/* Processor that is doing the boot up */
+static unsigned int bsp_phys_id = -1;
+
+/* Bitmask of physically existing CPUs */
+physid_mask_t phys_cpu_present_map;
+
+/* Bitmask of currently online CPUs */
+cpumask_t cpu_online_map;
+
+cpumask_t cpu_bootout_map;
+cpumask_t cpu_bootin_map;
+cpumask_t cpu_callout_map;
+static cpumask_t cpu_callin_map;
+
+/* Per CPU bogomips and other parameters */
+struct cpuinfo_m32r cpu_data[NR_CPUS] __cacheline_aligned;
+
+/* Set when the idlers are all forked */
+int smp_threads_ready;
+
+static int cpucount;
+static cpumask_t smp_commenced_mask;
+
+extern struct {
+       void * spi;
+       unsigned short ss;
+} stack_start;
+
+/* which physical physical ID maps to which logical CPU number */
+static volatile int physid_2_cpu[NR_CPUS];
+
+/* which logical CPU number maps to which physical ID */
+volatile int cpu_2_physid[NR_CPUS];
+
+DEFINE_PER_CPU(int, prof_multiplier) = 1;
+DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
+DEFINE_PER_CPU(int, prof_counter) = 1;
+
+spinlock_t ipi_lock[NR_IPIS];
+
+static unsigned int calibration_result;
+
+unsigned long cache_decay_ticks = HZ / 100;
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Function Prototypes                                                       */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+void smp_prepare_boot_cpu(void);
+void smp_prepare_cpus(unsigned int);
+static void smp_tune_scheduling(void);
+static void init_ipi_lock(void);
+static void do_boot_cpu(int);
+int __cpu_up(unsigned int);
+void smp_cpus_done(unsigned int);
+
+int start_secondary(void *);
+static void smp_callin(void);
+static void smp_online(void);
+
+static void show_mp_info(int);
+static void smp_store_cpu_info(int);
+static void show_cpu_info(int);
+int setup_profiling_timer(unsigned int);
+static void init_cpu_to_physid(void);
+static void map_cpu_to_physid(int, int);
+static void unmap_cpu_to_physid(int, int);
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Boot up APs Routins : BSP                                                 */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+void __devinit smp_prepare_boot_cpu(void)
+{
+       bsp_phys_id = hard_smp_processor_id();
+       physid_set(bsp_phys_id, phys_cpu_present_map);
+       cpu_set(0, cpu_online_map);     /* BSP's cpu_id == 0 */
+       cpu_set(0, cpu_callout_map);
+       cpu_set(0, cpu_callin_map);
+
+       /*
+        * Initialize the logical to physical CPU number mapping
+        */
+       init_cpu_to_physid();
+       map_cpu_to_physid(0, bsp_phys_id);
+       current_thread_info()->cpu = 0;
+}
+
+/*==========================================================================*
+ * Name:         smp_prepare_cpus (old smp_boot_cpus)
+ *
+ * Description:  This routine boot up APs.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ * 2003-06-24 hy  modify for linux-2.5.69
+ *
+ *==========================================================================*/
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+       int phys_id;
+       unsigned long nr_cpu;
+
+       nr_cpu = inl(M32R_FPGA_NUM_OF_CPUS_PORTL);
+       if (nr_cpu > NR_CPUS) {
+               printk(KERN_INFO "NUM_OF_CPUS reg. value [%ld] > NR_CPU [%d]",
+                       nr_cpu, NR_CPUS);
+               goto smp_done;
+       }
+       for (phys_id = 0 ; phys_id < nr_cpu ; phys_id++)
+               physid_set(phys_id, phys_cpu_present_map);
+
+       show_mp_info(nr_cpu);
+
+       init_ipi_lock();
+
+       /*
+        * Setup boot CPU information
+        */
+       smp_store_cpu_info(0); /* Final full version of the data */
+       smp_tune_scheduling();
+
+       /*
+        * If SMP should be disabled, then really disable it!
+        */
+       if (!max_cpus) {
+               printk(KERN_INFO "SMP mode deactivated by commandline.\n");
+               goto smp_done;
+       }
+
+       /*
+        * Now scan the CPU present map and fire up the other CPUs.
+        */
+       Dprintk("CPU present map : %lx\n", physids_coerce(phys_cpu_present_map));
+
+       for (phys_id = 0 ; phys_id < NR_CPUS ; phys_id++) {
+               /*
+                * Don't even attempt to start the boot CPU!
+                */
+               if (phys_id == bsp_phys_id)
+                       continue;
+
+               if (!physid_isset(phys_id, phys_cpu_present_map))
+                       continue;
+
+               if ((max_cpus >= 0) && (max_cpus <= cpucount + 1))
+                       continue;
+
+               do_boot_cpu(phys_id);
+
+               /*
+                * Make sure we unmap all failed CPUs
+                */
+               if (physid_to_cpu(phys_id) == -1) {
+                       physid_clear(phys_id, phys_cpu_present_map);
+                       printk("phys CPU#%d not responding - " \
+                               "cannot use it.\n", phys_id);
+               }
+       }
+
+smp_done:
+       Dprintk("Boot done.\n");
+}
+
+static void __init smp_tune_scheduling(void)
+{
+       /* Nothing to do. */
+}
+
+/*
+ * init_ipi_lock : Initialize IPI locks.
+ */
+static void __init init_ipi_lock(void)
+{
+       int ipi;
+
+       for (ipi = 0 ; ipi < NR_IPIS ; ipi++)
+               ipi_lock[ipi] = SPIN_LOCK_UNLOCKED;
+}
+
+/*==========================================================================*
+ * Name:         do_boot_cpu
+ *
+ * Description:  This routine boot up one AP.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    phys_id - Target CPU physical ID
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ * 2003-06-24 hy  modify for linux-2.5.69
+ *
+ *==========================================================================*/
+static void __init do_boot_cpu(int phys_id)
+{
+       struct task_struct *idle;
+       unsigned long send_status, boot_status;
+       int timeout, cpu_id;
+
+       cpu_id = ++cpucount;
+
+       /*
+        * We can't use kernel_thread since we must avoid to
+        * reschedule the child.
+        */
+       idle = fork_idle(cpu_id);
+       if (IS_ERR(idle))
+               panic("failed fork for CPU#%d.", cpu_id);
+
+       idle->thread.lr = (unsigned long)start_secondary;
+
+       map_cpu_to_physid(cpu_id, phys_id);
+
+       /* So we see what's up   */
+       printk("Booting processor %d/%d\n", phys_id, cpu_id);
+       stack_start.spi = (void *)idle->thread.sp;
+       idle->thread_info->cpu = cpu_id;
+
+       /*
+        * Send Startup IPI
+        *   1.IPI received by CPU#(phys_id).
+        *   2.CPU#(phys_id) enter startup_AP (arch/m32r/kernel/head.S)
+        *   3.CPU#(phys_id) enter start_secondary()
+        */
+       send_status = 0;
+       boot_status = 0;
+
+       cpu_set(phys_id, cpu_bootout_map);
+
+       /* Send Startup IPI */
+       send_IPI_mask_phys(cpumask_of_cpu(phys_id), CPU_BOOT_IPI, 0);
+
+       Dprintk("Waiting for send to finish...\n");
+       timeout = 0;
+
+       /* Wait 100[ms] */
+       do {
+               Dprintk("+");
+               udelay(1000);
+               send_status = !cpu_isset(phys_id, cpu_bootin_map);
+       } while (send_status && (timeout++ < 100));
+
+       Dprintk("After Startup.\n");
+
+       if (!send_status) {
+               /*
+                * allow APs to start initializing.
+                */
+               Dprintk("Before Callout %d.\n", cpu_id);
+               cpu_set(cpu_id, cpu_callout_map);
+               Dprintk("After Callout %d.\n", cpu_id);
+
+               /*
+                * Wait 5s total for a response
+                */
+               for (timeout = 0; timeout < 5000; timeout++) {
+                       if (cpu_isset(cpu_id, cpu_callin_map))
+                               break;  /* It has booted */
+                       udelay(1000);
+               }
+
+               if (cpu_isset(cpu_id, cpu_callin_map)) {
+                       /* number CPUs logically, starting from 1 (BSP is 0) */
+                       Dprintk("OK.\n");
+               } else {
+                       boot_status = 1;
+                       printk("Not responding.\n");
+               }
+       } else
+               printk("IPI never delivered???\n");
+
+       if (send_status || boot_status) {
+               unmap_cpu_to_physid(cpu_id, phys_id);
+               cpu_clear(cpu_id, cpu_callout_map);
+               cpu_clear(cpu_id, cpu_callin_map);
+               cpu_clear(cpu_id, cpu_initialized);
+               cpucount--;
+       }
+}
+
+int __devinit __cpu_up(unsigned int cpu_id)
+{
+       int timeout;
+
+       cpu_set(cpu_id, smp_commenced_mask);
+
+       /*
+        * Wait 5s total for a response
+        */
+       for (timeout = 0; timeout < 5000; timeout++) {
+               if (cpu_isset(cpu_id, cpu_online_map))
+                       break;
+               udelay(1000);
+       }
+       if (!cpu_isset(cpu_id, cpu_online_map))
+               BUG();
+
+       return 0;
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+       int cpu_id, timeout;
+       unsigned long bogosum = 0;
+
+       for (timeout = 0; timeout < 5000; timeout++) {
+               if (cpus_equal(cpu_callin_map, cpu_online_map))
+                       break;
+               udelay(1000);
+       }
+       if (!cpus_equal(cpu_callin_map, cpu_online_map))
+               BUG();
+
+       for (cpu_id = 0 ; cpu_id < num_online_cpus() ; cpu_id++)
+               show_cpu_info(cpu_id);
+
+       /*
+        * Allow the user to impress friends.
+        */
+       Dprintk("Before bogomips.\n");
+       if (cpucount) {
+               for_each_cpu_mask(cpu_id, cpu_online_map)
+                       bogosum += cpu_data[cpu_id].loops_per_jiffy;
+
+               printk(KERN_INFO "Total of %d processors activated " \
+                       "(%lu.%02lu BogoMIPS).\n", cpucount + 1,
+                       bogosum / (500000 / HZ),
+                       (bogosum / (5000 / HZ)) % 100);
+               Dprintk("Before bogocount - setting activated=1.\n");
+       }
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Activate a secondary processor Routins                                    */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         start_secondary
+ *
+ * Description:  This routine activate a secondary processor.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *unused - currently unused.
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ * 2003-06-24 hy  modify for linux-2.5.69
+ *
+ *==========================================================================*/
+int __init start_secondary(void *unused)
+{
+       cpu_init();
+       smp_callin();
+       while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
+               rep_nop();
+
+       smp_online();
+
+       /*
+        * low-memory mappings have been cleared, flush them from
+        * the local TLBs too.
+        */
+       local_flush_tlb_all();
+
+       return cpu_idle();
+}
+
+/*==========================================================================*
+ * Name:         smp_callin
+ *
+ * Description:  This routine activate a secondary processor.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ * 2003-06-24 hy  modify for linux-2.5.69
+ *
+ *==========================================================================*/
+static void __init smp_callin(void)
+{
+       int phys_id = hard_smp_processor_id();
+       int cpu_id = smp_processor_id();
+       unsigned long timeout;
+
+       if (cpu_isset(cpu_id, cpu_callin_map)) {
+               printk("huh, phys CPU#%d, CPU#%d already present??\n",
+                       phys_id, cpu_id);
+               BUG();
+       }
+       Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpu_id, phys_id);
+
+       /* Waiting 2s total for startup (udelay is not yet working) */
+       timeout = jiffies + (2 * HZ);
+       while (time_before(jiffies, timeout)) {
+               /* Has the boot CPU finished it's STARTUP sequence ? */
+               if (cpu_isset(cpu_id, cpu_callout_map))
+                       break;
+               rep_nop();
+       }
+
+       if (!time_before(jiffies, timeout)) {
+               printk("BUG: CPU#%d started up but did not get a callout!\n",
+                       cpu_id);
+               BUG();
+       }
+
+       /* Allow the master to continue. */
+       cpu_set(cpu_id, cpu_callin_map);
+}
+
+static void __init smp_online(void)
+{
+       int cpu_id = smp_processor_id();
+
+       local_irq_enable();
+
+       /* Get our bogomips. */
+       calibrate_delay();
+
+       /* Save our processor parameters */
+       smp_store_cpu_info(cpu_id);
+
+       cpu_set(cpu_id, cpu_online_map);
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Boot up CPUs common Routins                                               */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+static void __init show_mp_info(int nr_cpu)
+{
+       int i;
+       char cpu_model0[17], cpu_model1[17], cpu_ver[9];
+
+       strncpy(cpu_model0, (char *)M32R_FPGA_CPU_NAME_ADDR, 16);
+       strncpy(cpu_model1, (char *)M32R_FPGA_MODEL_ID_ADDR, 16);
+       strncpy(cpu_ver, (char *)M32R_FPGA_VERSION_ADDR, 8);
+
+       cpu_model0[16] = '\0';
+       for (i = 15 ; i >= 0 ; i--) {
+               if (cpu_model0[i] != ' ')
+                       break;
+               cpu_model0[i] = '\0';
+       }
+       cpu_model1[16] = '\0';
+       for (i = 15 ; i >= 0 ; i--) {
+               if (cpu_model1[i] != ' ')
+                       break;
+               cpu_model1[i] = '\0';
+       }
+       cpu_ver[8] = '\0';
+       for (i = 7 ; i >= 0 ; i--) {
+               if (cpu_ver[i] != ' ')
+                       break;
+               cpu_ver[i] = '\0';
+       }
+
+       printk(KERN_INFO "M32R-mp information\n");
+       printk(KERN_INFO "  On-chip CPUs : %d\n", nr_cpu);
+       printk(KERN_INFO "  CPU model : %s/%s(%s)\n", cpu_model0,
+               cpu_model1, cpu_ver);
+}
+
+/*
+ * The bootstrap kernel entry code has set these up. Save them for
+ * a given CPU
+ */
+static void __init smp_store_cpu_info(int cpu_id)
+{
+       struct cpuinfo_m32r *ci = cpu_data + cpu_id;
+
+       *ci = boot_cpu_data;
+       ci->loops_per_jiffy = loops_per_jiffy;
+}
+
+static void __init show_cpu_info(int cpu_id)
+{
+       struct cpuinfo_m32r *ci = &cpu_data[cpu_id];
+
+       printk("CPU#%d : ", cpu_id);
+
+#define PRINT_CLOCK(name, value) \
+       printk(name " clock %d.%02dMHz", \
+               ((value) / 1000000), ((value) % 1000000) / 10000)
+
+       PRINT_CLOCK("CPU", (int)ci->cpu_clock);
+       PRINT_CLOCK(", Bus", (int)ci->bus_clock);
+       printk(", loops_per_jiffy[%ld]\n", ci->loops_per_jiffy);
+}
+
+/*
+ * the frequency of the profiling timer can be changed
+ * by writing a multiplier value into /proc/profile.
+ */
+int setup_profiling_timer(unsigned int multiplier)
+{
+       int i;
+
+       /*
+        * Sanity check. [at least 500 APIC cycles should be
+        * between APIC interrupts as a rule of thumb, to avoid
+        * irqs flooding us]
+        */
+       if ( (!multiplier) || (calibration_result / multiplier < 500))
+               return -EINVAL;
+
+       /*
+        * Set the new multiplier for each CPU. CPUs don't start using the
+        * new values until the next timer interrupt in which they do process
+        * accounting. At that time they also adjust their APIC timers
+        * accordingly.
+        */
+       for (i = 0; i < NR_CPUS; ++i)
+               per_cpu(prof_multiplier, i) = multiplier;
+
+       return 0;
+}
+
+/* Initialize all maps between cpu number and apicids */
+static void __init init_cpu_to_physid(void)
+{
+       int  i;
+
+       for (i = 0 ; i < NR_CPUS ; i++) {
+               cpu_2_physid[i] = -1;
+               physid_2_cpu[i] = -1;
+       }
+}
+
+/*
+ * set up a mapping between cpu and apicid. Uses logical apicids for multiquad,
+ * else physical apic ids
+ */
+static void __init map_cpu_to_physid(int cpu_id, int phys_id)
+{
+       physid_2_cpu[phys_id] = cpu_id;
+       cpu_2_physid[cpu_id] = phys_id;
+}
+
+/*
+ * undo a mapping between cpu and apicid. Uses logical apicids for multiquad,
+ * else physical apic ids
+ */
+static void __init unmap_cpu_to_physid(int cpu_id, int phys_id)
+{
+       physid_2_cpu[phys_id] = -1;
+       cpu_2_physid[cpu_id] = -1;
+}
+
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c
new file mode 100644 (file)
index 0000000..f34fa19
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * linux/arch/m32r/kernel/sys_m32r.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/M32R platform.
+ *
+ * Taken from i386 version.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/syscalls.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/utsname.h>
+
+#include <asm/uaccess.h>
+#include <asm/cachectl.h>
+#include <asm/cacheflush.h>
+#include <asm/ipc.h>
+
+/*
+ * sys_tas() - test-and-set
+ * linuxthreads testing version
+ */
+#ifndef CONFIG_SMP
+asmlinkage int sys_tas(int *addr)
+{
+       int oldval;
+       unsigned long flags;
+
+       if (!access_ok(VERIFY_WRITE, addr, sizeof (int)))
+               return -EFAULT;
+       local_irq_save(flags);
+       oldval = *addr;
+       *addr = 1;
+       local_irq_restore(flags);
+       return oldval;
+}
+#else /* CONFIG_SMP */
+#include <linux/spinlock.h>
+
+static spinlock_t tas_lock = SPIN_LOCK_UNLOCKED;
+
+asmlinkage int sys_tas(int *addr)
+{
+       int oldval;
+
+       if (!access_ok(VERIFY_WRITE, addr, sizeof (int)))
+               return -EFAULT;
+
+       spin_lock(&tas_lock);
+       oldval = *addr;
+       *addr = 1;
+       spin_unlock(&tas_lock);
+
+       return oldval;
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * 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 r0, unsigned long r1, unsigned long r2,
+       unsigned long r3, unsigned long r4, unsigned long r5,
+       unsigned long r6, struct pt_regs regs)
+{
+       int fd[2];
+       int error;
+
+       error = do_pipe(fd);
+       if (!error) {
+               if (copy_to_user((void *)r0, (void *)fd, 2*sizeof(int)))
+                       error = -EFAULT;
+       }
+       return error;
+}
+
+asmlinkage long sys_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;
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys_ipc(uint call, int first, int second,
+                      int third, void __user *ptr, long fifth)
+{
+       int version, ret;
+
+       version = call >> 16; /* hack for backward compatibility */
+       call &= 0xffff;
+
+       switch (call) {
+       case SEMOP:
+               return sys_semtimedop(first, (struct sembuf __user *)ptr,
+                                     second, NULL);
+       case SEMTIMEDOP:
+               return sys_semtimedop(first, (struct sembuf __user *)ptr,
+                                     second, (const struct timespec __user *)fifth);
+       case SEMGET:
+               return sys_semget (first, second, third);
+       case SEMCTL: {
+               union semun fourth;
+               if (!ptr)
+                       return -EINVAL;
+               if (get_user(fourth.__pad, (void __user * __user *) ptr))
+                       return -EFAULT;
+               return sys_semctl (first, second, third, fourth);
+               }
+
+       case MSGSND:
+               return sys_msgsnd (first, (struct msgbuf __user *) ptr,
+                                  second, third);
+       case MSGRCV:
+               switch (version) {
+               case 0: {
+                       struct ipc_kludge tmp;
+                       if (!ptr)
+                               return -EINVAL;
+
+                       if (copy_from_user(&tmp,
+                                          (struct ipc_kludge __user *) ptr,
+                                          sizeof (tmp)))
+                               return -EFAULT;
+                       return sys_msgrcv (first, tmp.msgp, second,
+                                          tmp.msgtyp, third);
+                       }
+               default:
+                       return sys_msgrcv (first,
+                                          (struct msgbuf __user *) ptr,
+                                          second, fifth, third);
+               }
+       case MSGGET:
+               return sys_msgget ((key_t) first, second);
+       case MSGCTL:
+               return sys_msgctl (first, second,
+                                  (struct msqid_ds __user *) ptr);
+       case SHMAT: {
+               ulong raddr;
+
+               if ((ret = verify_area(VERIFY_WRITE, (ulong __user *) third,
+                                     sizeof(ulong))))
+                       return ret;
+               ret = do_shmat (first, (char __user *) ptr, second, &raddr);
+               if (ret)
+                       return ret;
+               return put_user (raddr, (ulong __user *) third);
+               }
+       case SHMDT:
+               return sys_shmdt ((char __user *)ptr);
+       case SHMGET:
+               return sys_shmget (first, second, third);
+       case SHMCTL:
+               return sys_shmctl (first, second,
+                                  (struct shmid_ds __user *) ptr);
+       default:
+               return -ENOSYS;
+       }
+}
+
+asmlinkage int sys_uname(struct old_utsname * name)
+{
+       int err;
+       if (!name)
+               return -EFAULT;
+       down_read(&uts_sem);
+       err=copy_to_user(name, &system_utsname, sizeof (*name));
+       up_read(&uts_sem);
+       return err?-EFAULT:0;
+}
+
+asmlinkage int sys_cacheflush(void *addr, int bytes, int cache)
+{
+       /* This should flush more selectivly ...  */
+       _flush_cache_all();
+       return 0;
+}
+
+asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
+{
+       /* Not implemented yet. */
+       return -ENOSYS;
+}
+
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
new file mode 100644 (file)
index 0000000..25a3166
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ *  linux/arch/m32r/kernel/time.c
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ *  Taken from i386 version.
+ *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *    Copyright (C) 1996, 1997, 1998  Ralf Baechle
+ *
+ *  This file contains the time handling details for PC-style clocks as
+ *  found in some MIPS systems.
+ *
+ *  Some code taken from sh version.
+ *    Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
+ *    Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
+ */
+
+#undef  DEBUG_TIMER
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/profile.h>
+
+#include <asm/io.h>
+#include <asm/m32r.h>
+
+#include <asm/hw_irq.h>
+
+#ifdef CONFIG_SMP
+extern void send_IPI_allbutself(int, int);
+extern void smp_local_timer_interrupt(struct pt_regs *);
+#endif
+
+u64 jiffies_64 = INITIAL_JIFFIES;
+
+EXPORT_SYMBOL(jiffies_64);
+
+extern unsigned long wall_jiffies;
+#define TICK_SIZE      (tick_nsec / 1000)
+
+/*
+ * Change this if you have some constant time drift
+ */
+
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
+
+static unsigned long latch;
+
+static unsigned long do_gettimeoffset(void)
+{
+       unsigned long  elapsed_time = 0;  /* [us] */
+
+#if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \
+       || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \
+       || defined(CONFIG_CHIP_OPSP)
+#ifndef CONFIG_SMP
+
+       unsigned long count;
+
+       /* timer count may underflow right here */
+       count = inl(M32R_MFT2CUT_PORTL);
+
+       if (inl(M32R_ICU_CR18_PORTL) & 0x00000100)      /* underflow check */
+               count = 0;
+
+       count = (latch - count) * TICK_SIZE;
+       elapsed_time = (count + latch / 2) / latch;
+       /* NOTE: LATCH is equal to the "interval" value (= reload count). */
+
+#else /* CONFIG_SMP */
+       unsigned long count;
+       static unsigned long p_jiffies = -1;
+       static unsigned long p_count = 0;
+
+       /* timer count may underflow right here */
+       count = inl(M32R_MFT2CUT_PORTL);
+
+       if (jiffies == p_jiffies && count > p_count)
+               count = 0;
+
+       p_jiffies = jiffies;
+       p_count = count;
+
+       count = (latch - count) * TICK_SIZE;
+       elapsed_time = (count + latch / 2) / latch;
+       /* NOTE: LATCH is equal to the "interval" value (= reload count). */
+#endif /* CONFIG_SMP */
+#elif defined(CONFIG_CHIP_M32310)
+#warning do_gettimeoffse not implemented
+#else
+#error no chip configuration
+#endif
+
+       return elapsed_time;
+}
+
+/*
+ * This version of gettimeofday has near microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+       unsigned long seq;
+       unsigned long usec, sec;
+       unsigned long max_ntp_tick = tick_usec - tickadj;
+
+       do {
+               unsigned long lost;
+
+               seq = read_seqbegin(&xtime_lock);
+
+               usec = do_gettimeoffset();
+               lost = jiffies - wall_jiffies;
+
+               /*
+                * If time_adjust is negative then NTP is slowing the clock
+                * so make sure not to go into next possible interval.
+                * Better to lose some accuracy than have time go backwards..
+                */
+               if (unlikely(time_adjust < 0)) {
+                       usec = min(usec, max_ntp_tick);
+                       if (lost)
+                               usec += lost * max_ntp_tick;
+               } else if (unlikely(lost))
+                       usec += lost * tick_usec;
+
+               sec = xtime.tv_sec;
+               usec += (xtime.tv_nsec / 1000);
+       } while (read_seqretry(&xtime_lock, seq));
+
+       while (usec >= 1000000) {
+               usec -= 1000000;
+               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 "xtime" correctly. However, the
+        * value in this location is the value at the most recent update of
+        * wall time.  Discover what correction gettimeofday() would have
+        * made, and then undo it!
+        */
+       nsec -= do_gettimeoffset() * NSEC_PER_USEC;
+       nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
+
+       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);
+
+       time_adjust = 0;                /* stop active adjtime() */
+       time_status |= STA_UNSYNC;
+       time_maxerror = NTP_PHASE_LIMIT;
+       time_esterror = NTP_PHASE_LIMIT;
+       write_sequnlock_irq(&xtime_lock);
+       clock_was_set();
+
+       return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you won't notice until after reboot!
+ */
+static __inline__ int set_rtc_mmss(unsigned long nowtime)
+{
+       return 0;
+}
+
+/* last time the cmos clock got updated */
+static long last_rtc_update = 0;
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+static __inline__ void do_timer_interrupt(int irq, void *dev_id,
+       struct pt_regs * regs)
+{
+       do_timer(regs);
+
+       /*
+        * If we have an externally synchronized Linux clock, then update
+        * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+        * called as close as possible to 500 ms before the new second starts.
+        */
+       if ((time_status & STA_UNSYNC) == 0
+               && xtime.tv_sec > last_rtc_update + 660
+               && (xtime.tv_nsec / 1000) >= 500000 - ((unsigned)TICK_SIZE) / 2
+               && (xtime.tv_nsec / 1000) <= 500000 + ((unsigned)TICK_SIZE) / 2)
+       {
+               if (set_rtc_mmss(xtime.tv_sec) == 0)
+                       last_rtc_update = xtime.tv_sec;
+               else    /* do it again in 60 s */
+                       last_rtc_update = xtime.tv_sec - 600;
+       }
+       /* As we return to user mode fire off the other CPU schedulers..
+          this is basically because we don't yet share IRQ's around.
+          This message is rigged to be safe on the 386 - basically it's
+          a hack, so don't look closely for now.. */
+
+#ifdef CONFIG_SMP
+       smp_local_timer_interrupt(regs);
+#endif
+}
+
+irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       write_seqlock(&xtime_lock);
+       do_timer_interrupt(irq, NULL, regs);
+       write_sequnlock(&xtime_lock);
+
+#ifndef CONFIG_SMP
+       profile_tick(CPU_PROFILING, regs);
+#endif
+
+       return IRQ_HANDLED;
+}
+
+struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE,
+                         "MFT2", NULL, NULL };
+
+void __init time_init(void)
+{
+       unsigned int epoch, year, mon, day, hour, min, sec;
+
+       sec = min = hour = day = mon = year = 0;
+       epoch = 0;
+
+       year = 23;
+       mon = 4;
+       day = 17;
+
+       /* Attempt to guess the epoch.  This is the same heuristic as in rtc.c
+          so no stupid things will happen to timekeeping.  Who knows, maybe
+          Ultrix also uses 1952 as epoch ...  */
+       if (year > 10 && year < 44)
+               epoch = 1980;
+       else if (year < 96)
+               epoch = 1952;
+       year += epoch;
+
+       xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+       xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+       wall_to_monotonic.tv_sec = -xtime.tv_sec;
+       wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+
+#if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \
+       || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \
+       || defined(CONFIG_CHIP_OPSP)
+
+       /* M32102 MFT setup */
+       setup_irq(M32R_IRQ_MFT2, &irq0);
+       {
+               unsigned long bus_clock;
+               unsigned short divide;
+
+               bus_clock = boot_cpu_data.bus_clock;
+               divide = boot_cpu_data.timer_divide;
+               latch = (bus_clock/divide + HZ / 2) / HZ;
+
+               printk("Timer start : latch = %ld\n", latch);
+
+               outl((M32R_MFTMOD_CC_MASK | M32R_MFTMOD_TCCR \
+                       |M32R_MFTMOD_CSSEL011), M32R_MFT2MOD_PORTL);
+               outl(latch, M32R_MFT2RLD_PORTL);
+               outl(latch, M32R_MFT2CUT_PORTL);
+               outl(0, M32R_MFT2CMPRLD_PORTL);
+               outl((M32R_MFTCR_MFT2MSK|M32R_MFTCR_MFT2EN), M32R_MFTCR_PORTL);
+       }
+
+#elif defined(CONFIG_CHIP_M32310)
+#warning time_init not implemented
+#else
+#error no chip configuration
+#endif
+}
+
+/*
+ *  Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+       return (unsigned long long)jiffies * (1000000000 / HZ);
+}
+
diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c
new file mode 100644 (file)
index 0000000..87fdc4d
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ *  linux/arch/m32r/kernel/traps.c
+ *
+ *  Copyright (C) 2001, 2002  Hirokazu Takata, Hiroyuki Kondo,
+ *                            Hitoshi Yamamoto
+ */
+
+/* $Id$ */
+
+/*
+ * 'traps.c' handles hardware traps and faults after we have saved some
+ * state in 'entry.S'.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kallsyms.h>
+#include <linux/stddef.h>
+#include <linux/ptrace.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+
+#include <asm/smp.h>
+
+#include <linux/module.h>
+
+asmlinkage void alignment_check(void);
+asmlinkage void ei_handler(void);
+asmlinkage void rie_handler(void);
+asmlinkage void debug_trap(void);
+asmlinkage void cache_flushing_handler(void);
+
+#ifdef CONFIG_SMP
+extern void smp_reschedule_interrupt(void);
+extern void smp_invalidate_interrupt(void);
+extern void smp_call_function_interrupt(void);
+extern void smp_ipi_timer_interrupt(void);
+extern void smp_flush_cache_all_interrupt(void);
+
+/*
+ * for Boot AP function
+ */
+asm (
+       "       .section .eit_vector4,\"ax\"    \n"
+       "       .global _AP_RE                  \n"
+       "       .global startup_AP              \n"
+       "_AP_RE:                                \n"
+       "       .fill 32, 4, 0                  \n"
+       "_AP_EI: bra    startup_AP              \n"
+       "       .previous                       \n"
+);
+#endif  /* CONFIG_SMP */
+
+extern unsigned long   eit_vector[];
+#define BRA_INSN(func, entry)  \
+       ((unsigned long)func - (unsigned long)eit_vector - entry*4)/4 \
+       + 0xff000000UL
+
+void   set_eit_vector_entries(void)
+{
+       extern void default_eit_handler(void);
+       extern void system_call(void);
+       extern void pie_handler(void);
+       extern void ace_handler(void);
+       extern void tme_handler(void);
+       extern void _flush_cache_copyback_all(void);
+
+       eit_vector[0] = 0xd0c00001; /* seth r0, 0x01 */
+       eit_vector[1] = BRA_INSN(default_eit_handler, 1);
+       eit_vector[4] = 0xd0c00010; /* seth r0, 0x10 */
+       eit_vector[5] = BRA_INSN(default_eit_handler, 5);
+       eit_vector[8] = BRA_INSN(rie_handler, 8);
+       eit_vector[12] = BRA_INSN(alignment_check, 12);
+       eit_vector[16] = 0xff000000UL;
+       eit_vector[17] = BRA_INSN(debug_trap, 17);
+       eit_vector[18] = BRA_INSN(system_call, 18);
+       eit_vector[19] = 0xff000000UL;
+       eit_vector[20] = 0xff000000UL;
+       eit_vector[21] = 0xff000000UL;
+       eit_vector[22] = 0xff000000UL;
+       eit_vector[23] = 0xff000000UL;
+       eit_vector[24] = 0xff000000UL;
+       eit_vector[25] = 0xff000000UL;
+       eit_vector[26] = 0xff000000UL;
+       eit_vector[27] = 0xff000000UL;
+       eit_vector[28] = BRA_INSN(cache_flushing_handler, 28);
+       eit_vector[29] = 0xff000000UL;
+       eit_vector[30] = 0xff000000UL;
+       eit_vector[31] = 0xff000000UL;
+       eit_vector[32] = BRA_INSN(ei_handler, 32);
+       eit_vector[64] = BRA_INSN(pie_handler, 64);
+       eit_vector[68] = BRA_INSN(ace_handler, 68);
+       eit_vector[72] = BRA_INSN(tme_handler, 72);
+#ifdef CONFIG_SMP
+       eit_vector[184] = (unsigned long)smp_reschedule_interrupt;
+       eit_vector[185] = (unsigned long)smp_invalidate_interrupt;
+       eit_vector[186] = (unsigned long)smp_call_function_interrupt;
+       eit_vector[187] = (unsigned long)smp_ipi_timer_interrupt;
+       eit_vector[188] = (unsigned long)smp_flush_cache_all_interrupt;
+       eit_vector[189] = 0;
+       eit_vector[190] = 0;
+       eit_vector[191] = 0;
+#endif
+       _flush_cache_copyback_all();
+}
+
+void __init trap_init(void)
+{
+       set_eit_vector_entries();
+
+       /*
+        * Should be a barrier for any external CPU state.
+        */
+       cpu_init();
+}
+
+int kstack_depth_to_print = 24;
+
+void show_trace(struct task_struct *task, unsigned long *stack)
+{
+       unsigned long addr;
+
+       if (!stack)
+               stack = (unsigned long*)&stack;
+
+       printk("Call Trace: ");
+       while (!kstack_end(stack)) {
+               addr = *stack++;
+               if (__kernel_text_address(addr)) {
+                       printk("[<%08lx>] ", addr);
+                       print_symbol("%s\n", addr);
+               }
+       }
+       printk("\n");
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+       unsigned long  *stack;
+       int  i;
+
+       /*
+        * debugging aid: "show_stack(NULL);" prints the
+        * back trace for this cpu.
+        */
+
+       if(sp==NULL) {
+               if (task)
+                       sp = (unsigned long *)task->thread.sp;
+               else
+                       sp=(unsigned long*)&sp;
+       }
+
+       stack = sp;
+       for(i=0; i < kstack_depth_to_print; i++) {
+               if (kstack_end(stack))
+                       break;
+               if (i && ((i % 4) == 0))
+                       printk("\n       ");
+               printk("%08lx ", *stack++);
+       }
+       printk("\n");
+       show_trace(task, sp);
+}
+
+void dump_stack(void)
+{
+       unsigned long stack;
+
+       show_trace(current, &stack);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+static void show_registers(struct pt_regs *regs)
+{
+       int i = 0;
+       int in_kernel = 1;
+       unsigned long sp;
+
+       printk("CPU:    %d\n", smp_processor_id());
+       show_regs(regs);
+
+       sp = (unsigned long) (1+regs);
+       if (user_mode(regs)) {
+               in_kernel = 0;
+               sp = regs->spu;
+               printk("SPU: %08lx\n", sp);
+       } else {
+               printk("SPI: %08lx\n", sp);
+       }
+       printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)",
+               current->comm, current->pid, 0xffff & i, 4096+(unsigned long)current);
+
+       /*
+        * When in-kernel, we also print out the stack and code at the
+        * time of the fault..
+        */
+       if (in_kernel) {
+               printk("\nStack: ");
+               show_stack(current, (unsigned long*) sp);
+
+               printk("\nCode: ");
+               if (regs->bpc < PAGE_OFFSET)
+                       goto bad;
+
+               for(i=0;i<20;i++) {
+                       unsigned char c;
+                       if (__get_user(c, &((unsigned char*)regs->bpc)[i])) {
+bad:
+                               printk(" Bad PC value.");
+                               break;
+                       }
+                       printk("%02x ", c);
+               }
+       }
+       printk("\n");
+}
+
+spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
+
+void die(const char * str, struct pt_regs * regs, long err)
+{
+       console_verbose();
+       spin_lock_irq(&die_lock);
+       bust_spinlocks(1);
+       printk("%s: %04lx\n", str, err & 0xffff);
+       show_registers(regs);
+       bust_spinlocks(0);
+       spin_unlock_irq(&die_lock);
+       do_exit(SIGSEGV);
+}
+
+static __inline__ void die_if_kernel(const char * str,
+       struct pt_regs * regs, long err)
+{
+       if (!user_mode(regs))
+               die(str, regs, err);
+}
+
+static __inline__ void do_trap(int trapnr, int signr, const char * str,
+       struct pt_regs * regs, long error_code, siginfo_t *info)
+{
+       if (user_mode(regs)) {
+               /* trap_signal */
+               struct task_struct *tsk = current;
+               tsk->thread.error_code = error_code;
+               tsk->thread.trap_no = trapnr;
+               if (info)
+                       force_sig_info(signr, info, tsk);
+               else
+                       force_sig(signr, tsk);
+               return;
+       } else {
+               /* kernel_trap */
+               if (!fixup_exception(regs))
+                       die(str, regs, error_code);
+               return;
+       }
+}
+
+#define DO_ERROR(trapnr, signr, str, name) \
+asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+{ \
+       do_trap(trapnr, signr, 0, regs, error_code, NULL); \
+}
+
+#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+{ \
+       siginfo_t info; \
+       info.si_signo = signr; \
+       info.si_errno = 0; \
+       info.si_code = sicode; \
+       info.si_addr = (void __user *)siaddr; \
+       do_trap(trapnr, signr, str, regs, error_code, &info); \
+}
+
+DO_ERROR( 1, SIGTRAP, "debug trap", debug_trap)
+DO_ERROR_INFO(0x20, SIGILL,  "reserved instruction ", rie_handler, ILL_ILLOPC, regs->bpc)
+DO_ERROR_INFO(0x100, SIGILL,  "privilege instruction", pie_handler, ILL_PRVOPC, regs->bpc)
+
+extern int handle_unaligned_access(unsigned long, struct pt_regs *);
+
+/* This code taken from arch/sh/kernel/traps.c */
+asmlinkage void do_alignment_check(struct pt_regs *regs, long error_code)
+{
+       mm_segment_t oldfs;
+       unsigned long insn;
+       int tmp;
+
+       oldfs = get_fs();
+
+       if (user_mode(regs)) {
+               local_irq_enable();
+               current->thread.error_code = error_code;
+               current->thread.trap_no = 0x17;
+
+               set_fs(USER_DS);
+               if (copy_from_user(&insn, (void *)regs->bpc, 4)) {
+                       set_fs(oldfs);
+                       goto uspace_segv;
+               }
+               tmp = handle_unaligned_access(insn, regs);
+               set_fs(oldfs);
+
+               if (!tmp)
+                       return;
+
+       uspace_segv:
+               printk(KERN_NOTICE "Killing process \"%s\" due to unaligned "
+                       "access\n", current->comm);
+               force_sig(SIGSEGV, current);
+       } else {
+               set_fs(KERNEL_DS);
+               if (copy_from_user(&insn, (void *)regs->bpc, 4)) {
+                       set_fs(oldfs);
+                       die("insn faulting in do_address_error", regs, 0);
+               }
+               handle_unaligned_access(insn, regs);
+               set_fs(oldfs);
+       }
+}
+
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
new file mode 100644 (file)
index 0000000..729a264
--- /dev/null
@@ -0,0 +1,143 @@
+/* ld script to make M32R Linux kernel
+ */
+
+#include <linux/config.h>
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+
+OUTPUT_ARCH(m32r)
+ENTRY(startup_32)
+#if defined(__LITTLE_ENDIAN__)
+       jiffies = jiffies_64;
+#else
+       jiffies = jiffies_64 + 4;
+#endif
+SECTIONS
+{
+  . = CONFIG_MEMORY_START + __PAGE_OFFSET;
+  eit_vector = .;
+
+  . = . + 0x1000;
+  .empty_zero_page : { *(.empty_zero_page) } = 0
+
+  /* read-only */
+  _text = .;                   /* Text and read-only data */
+  .boot : { *(.boot) } = 0
+  .text : {
+       *(.text)
+       SCHED_TEXT
+       LOCK_TEXT
+       *(.fixup)
+       *(.gnu.warning)
+       } = 0x9090
+#ifdef CONFIG_SMP
+  . = ALIGN(65536);
+  .eit_vector4 : { *(.eit_vector4) }
+#endif
+  _etext = .;                  /* End of text section */
+
+  . = ALIGN(16);               /* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  RODATA
+
+  /* writeable */
+  .data : {                    /* Data */
+       *(.spu)
+       *(.spi)
+       *(.data)
+       CONSTRUCTORS
+       }
+
+  . = ALIGN(4096);
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(4096);
+  __nosave_end = .;
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  _edata = .;                  /* End of data section */
+
+  . = ALIGN(8192);             /* init_task */
+  .data.init_task : { *(.data.init_task) }
+
+  /* will be freed after init */
+  . = ALIGN(4096);             /* Init code and data */
+  __init_begin = .;
+  .init.text : {
+       _sinittext = .;
+       *(.init.text)
+       _einittext = .;
+  }
+  .init.data : { *(.init.data) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .init.setup : { *(.init.setup) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : {
+       *(.initcall1.init)
+       *(.initcall2.init)
+       *(.initcall3.init)
+       *(.initcall4.init)
+       *(.initcall5.init)
+       *(.initcall6.init)
+       *(.initcall7.init)
+  }
+  __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
+  SECURITY_INIT
+  . = ALIGN(4);
+  __alt_instructions = .;
+  .altinstructions : { *(.altinstructions) }
+  __alt_instructions_end = .;
+  .altinstr_replacement : { *(.altinstr_replacement) }
+  /* .exit.text is discard at runtime, not link time, to deal with references
+     from .altinstructions and .eh_frame */
+  .exit.text : { *(.exit.text) }
+  .exit.data : { *(.exit.data) }
+  . = ALIGN(4096);
+  __initramfs_start = .;
+  .init.ramfs : { *(.init.ramfs) }
+  __initramfs_end = .;
+  . = ALIGN(32);
+  __per_cpu_start = .;
+  .data.percpu  : { *(.data.percpu) }
+  __per_cpu_end = .;
+  . = ALIGN(4096);
+  __init_end = .;
+  /* freed after init ends here */
+
+  __bss_start = .;             /* BSS */
+  .bss : { *(.bss) }
+  . = ALIGN(4);
+  __bss_stop = .;
+
+  _end = . ;
+
+  /* Sections to be discarded */
+  /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) }
+}
diff --git a/arch/m32r/lib/Makefile b/arch/m32r/lib/Makefile
new file mode 100644 (file)
index 0000000..e632d10
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for M32R-specific library files..
+#
+
+lib-y  := checksum.o ashxdi3.o memset.o memcpy.o getuser.o \
+         putuser.o delay.o strlen.o usercopy.o csum_partial_copy.o
+
diff --git a/arch/m32r/lib/ashxdi3.S b/arch/m32r/lib/ashxdi3.S
new file mode 100644 (file)
index 0000000..78effca
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * linux/arch/m32r/lib/ashxdi3.S
+ *
+ * Copyright (C) 2001,2002  Hiroyuki Kondo, and Hirokazu Takata
+ *
+ */
+/* $Id$ */
+
+#include <linux/config.h>
+
+;
+;      input   (r0,r1)  src
+;      input    r2      shift val
+;               r3      scratch
+;      output  (r0,r1)
+;
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+#ifndef __LITTLE_ENDIAN__
+
+       .text
+       .align  4
+       .globl __ashrdi3
+__ashrdi3:
+       cmpz    r2                  ||  ldi     r3, #32
+       jc      r14                 ||  cmpu    r2, r3
+       bc      1f
+    ;   case 32 =< shift
+       mv      r1, r0              ||  srai    r0, #31
+       addi    r2, #-32
+       sra     r1, r2
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r0              ||  srl     r1, r2
+       sra     r0, r2              ||  neg     r2, r2
+       sll     r3, r2
+       or      r1, r3              ||  jmp     r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+       cmpz    r2                  ||  ldi     r3, #32
+       jc      r14                 ||  cmpu    r2, r3
+       bc      1f
+    ;   case 32 =< shift
+       mv      r0, r1              ||  addi    r2, #-32
+       sll     r0, r2              ||  ldi     r1, #0
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r1              ||  sll     r0, r2
+       sll     r1, r2              ||  neg     r2, r2
+       srl     r3, r2
+       or      r0, r3              ||  jmp     r14
+
+       .align  4
+       .globl __lshrdi3
+__lshrdi3:
+       cmpz    r2                  ||  ldi     r3, #32
+       jc      r14                 ||  cmpu    r2, r3
+       bc      1f
+    ;   case 32 =< shift
+       mv      r1, r0              ||  addi    r2, #-32
+       ldi     r0, #0              ||  srl     r1, r2
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r0              ||  srl     r1, r2
+       srl     r0, r2              ||  neg     r2, r2
+       sll     r3, r2
+       or      r1, r3              ||  jmp     r14
+
+#else /* LITTLE_ENDIAN */
+
+       .text
+       .align  4
+       .globl __ashrdi3
+__ashrdi3:
+       cmpz    r2                  ||  ldi     r3, #32
+       jc      r14                 ||  cmpu    r2, r3
+       bc      1f
+    ;   case 32 =< shift
+       mv      r0, r1              ||  srai    r1, #31
+       addi    r2, #-32
+       sra     r0, r2
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r1              ||  srl     r0, r2
+       sra     r1, r2              ||  neg     r2, r2
+       sll     r3, r2
+       or      r0, r3              ||  jmp     r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+       cmpz    r2                  ||  ldi     r3, #32
+       jc      r14                 ||  cmpu    r2, r3
+       bc      1f
+    ;   case 32 =< shift
+       mv      r1, r0              ||  addi    r2, #-32
+       sll     r1, r2              ||  ldi     r0, #0
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r0              ||  sll     r1, r2
+       sll     r0, r2              ||  neg     r2, r2
+       srl     r3, r2
+       or      r1, r3              ||  jmp     r14
+
+       .align  4
+       .globl __lshrdi3
+__lshrdi3:
+       cmpz    r2                  ||  ldi     r3, #32
+       jc      r14                 ||  cmpu    r2, r3
+       bc      1f
+    ;   case 32 =< shift
+       mv      r0, r1              ||  addi    r2, #-32
+       ldi     r1, #0              ||  srl     r0, r2
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r1              ||  srl     r0, r2
+       srl     r1, r2              ||  neg     r2, r2
+       sll     r3, r2
+       or      r0, r3              ||  jmp     r14
+
+#endif
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+#ifndef __LITTLE_ENDIAN__
+
+       .text
+       .align  4
+       .globl __ashrdi3
+__ashrdi3:
+       beqz    r2, 2f
+       cmpui   r2, #32
+       bc      1f
+    ;   case 32 =< shift
+       mv      r1, r0
+       srai    r0, #31
+       addi    r2, #-32
+       sra     r1, r2
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r0
+       srl     r1, r2
+       sra     r0, r2
+       neg     r2, r2
+       sll     r3, r2
+       or      r1, r3
+       .fillinsn
+2:
+       jmp     r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+       beqz    r2, 2f
+       cmpui   r2, #32
+       bc      1f
+    ;   case 32 =< shift
+       mv      r0, r1
+       addi    r2, #-32
+       sll     r0, r2
+       ldi     r1, #0
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r1
+       sll     r0, r2
+       sll     r1, r2
+       neg     r2, r2
+       srl     r3, r2
+       or      r0, r3
+       .fillinsn
+2:
+       jmp     r14
+
+       .align  4
+       .globl __lshrdi3
+__lshrdi3:
+       beqz    r2, 2f
+       cmpui   r2, #32
+       bc      1f
+    ;   case 32 =< shift
+       mv      r1, r0
+       ldi     r0, #0
+       addi    r2, #-32
+       srl     r1, r2
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r0
+       srl     r1, r2
+       srl     r0, r2
+       neg     r2, r2
+       sll     r3, r2
+       or      r1, r3
+       .fillinsn
+2:
+       jmp     r14
+
+#else
+
+       .text
+       .align  4
+       .globl __ashrdi3
+__ashrdi3:
+       beqz    r2, 2f
+       cmpui   r2, #32
+       bc      1f
+    ;   case 32 =< shift
+       mv      r0, r1
+       srai    r1, #31
+       addi    r2, #-32
+       sra     r0, r2
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r1
+       srl     r0, r2
+       sra     r1, r2
+       neg     r2, r2
+       sll     r3, r2
+       or      r0, r3
+       .fillinsn
+2:
+       jmp     r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+       beqz    r2, 2f
+       cmpui   r2, #32
+       bc      1f
+    ;   case 32 =< shift
+       mv      r1, r0
+       addi    r2, #-32
+       sll     r1, r2
+       ldi     r0, #0
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r0
+       sll     r1, r2
+       sll     r0, r2
+       neg     r2, r2
+       srl     r3, r2
+       or      r1, r3
+       .fillinsn
+2:
+       jmp     r14
+
+       .align  4
+       .globl __lshrdi3
+__lshrdi3:
+       beqz    r2, 2f
+       cmpui   r2, #32
+       bc      1f
+    ;   case 32 =< shift
+       mv      r0, r1
+       ldi     r1, #0
+       addi    r2, #-32
+       srl     r0, r2
+       jmp     r14
+       .fillinsn
+1:  ;   case shift <32
+       mv      r3, r1
+       srl     r0, r2
+       srl     r1, r2
+       neg     r2, r2
+       sll     r3, r2
+       or      r0, r3
+       .fillinsn
+2:
+       jmp     r14
+
+#endif
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+       .end
+
diff --git a/arch/m32r/lib/checksum.S b/arch/m32r/lib/checksum.S
new file mode 100644 (file)
index 0000000..f6fc1bd
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * INET                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.
+ *
+ *             IP/TCP/UDP checksumming routines
+ *
+ * Authors:    Jorge Cwik, <jorge@laser.satlink.net>
+ *             Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *             Tom May, <ftom@netcom.com>
+ *              Pentium Pro/II routines:
+ *              Alexander Kjeldaas <astor@guardian.no>
+ *              Finn Arne Gangstad <finnag@guardian.no>
+ *             Lots of code moved from tcp.c and ip.c; see those files
+ *             for more names.
+ *
+ * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ *                          handling.
+ *             Andi Kleen,  add zeroing on error
+ *                   converted to pure assembler
+ *             Hirokazu Takata,Hiroyuki Kondo rewrite for the m32r architecture.
+ *
+ *             This program is free software; you can redistribute 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.
+ */
+/* $Id$ */
+
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+ */
+
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+       /*
+        * Experiments with Ethernet and SLIP connections show that buff
+        * is aligned on either a 2-byte or 4-byte boundary.  We get at
+        * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+        * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+        * alignment for the unrolled loop.
+        */
+
+       .text
+ENTRY(csum_partial)
+       ; Function args
+       ;  r0: unsigned char *buff
+       ;  r1: int len
+       ;  r2: unsigned int sum
+
+       push    r2                  ||  ldi     r2, #0
+       and3    r7, r0, #1              ; Check alignment.
+       beqz    r7, 1f                  ; Jump if alignment is ok.
+       ; 1-byte mis aligned
+       ldub    r4, @r0             ||  addi    r0, #1
+       ; clear c-bit || Alignment uses up bytes.
+       cmp     r0, r0              ||  addi    r1, #-1
+       ldi     r3, #0              ||  addx    r2, r4
+       addx    r2, r3
+       .fillinsn
+1:
+       and3    r4, r0, #2              ; Check alignment.
+       beqz    r4, 2f                  ; Jump if alignment is ok.
+       ; clear c-bit || Alignment uses up two bytes.
+       cmp     r0, r0              ||  addi    r1, #-2
+       bgtz    r1, 1f                  ; Jump if we had at least two bytes.
+       bra     4f                  ||  addi    r1, #2
+       .fillinsn                       ; len(r1) was < 2.  Deal with it.
+1:
+       ; 2-byte aligned
+       lduh    r4, @r0             ||  ldi     r3, #0
+       addx    r2, r4              ||  addi    r0, #2
+       addx    r2, r3
+       .fillinsn
+2:
+       ; 4-byte aligned
+       cmp     r0, r0                  ; clear c-bit
+       srl3    r6, r1, #5
+       beqz    r6, 2f
+       .fillinsn
+
+1:     ld      r3, @r0+
+       ld      r4, @r0+                                        ; +4
+       ld      r5, @r0+                                        ; +8
+       ld      r3, @r0+            ||  addx    r2, r3          ; +12
+       ld      r4, @r0+            ||  addx    r2, r4          ; +16
+       ld      r5, @r0+            ||  addx    r2, r5          ; +20
+       ld      r3, @r0+            ||  addx    r2, r3          ; +24
+       ld      r4, @r0+            ||  addx    r2, r4          ; +28
+       addx    r2, r5              ||  addi    r6, #-1
+       addx    r2, r3
+       addx    r2, r4
+       bnez    r6, 1b
+
+       addx    r2, r6                  ; r6=0
+       cmp     r0, r0                  ; This clears c-bit
+       .fillinsn
+2:     and3    r6, r1, #0x1c           ; withdraw len
+       beqz    r6, 4f
+       srli    r6, #2
+       .fillinsn
+
+3:     ld      r4, @r0+            ||  addi    r6, #-1
+       addx    r2, r4
+       bnez    r6, 3b
+
+       addx    r2, r6                  ; r6=0
+       cmp     r0, r0                  ; This clears c-bit
+       .fillinsn
+4:     and3    r1, r1, #3
+       beqz    r1, 7f                  ; if len == 0 goto end
+       and3    r6, r1, #2
+       beqz    r6, 5f                  ; if len < 2  goto 5f(1byte)
+       lduh    r4, @r0             ||  addi    r0, #2
+       addi    r1, #-2             ||  slli    r4, #16
+       addx    r2, r4
+       beqz    r1, 6f
+       .fillinsn
+5:     ldub    r4, @r0             ||  ldi     r1, #0
+#ifndef __LITTLE_ENDIAN__
+       slli    r4, #8
+#endif
+       addx    r2, r4
+       .fillinsn
+6:     addx    r2, r1
+       .fillinsn
+7:
+       and3    r0, r2, #0xffff
+       srli    r2, #16
+       add     r0, r2
+       srl3    r2, r0, #16
+       beqz    r2, 1f
+       addi    r0, #1
+       and3    r0, r0, #0xffff
+       .fillinsn
+1:
+       beqz    r7, 1f                  ; swap the upper byte for the lower
+       and3    r2, r0, #0xff
+       srl3    r0, r0, #8
+       slli    r2, #8
+       or      r0, r2
+       .fillinsn
+1:
+       pop     r2                  ||  cmp     r0, r0
+       addx    r0, r2              ||  ldi     r2, #0
+       addx    r0, r2
+       jmp     r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+       /*
+        * Experiments with Ethernet and SLIP connections show that buff
+        * is aligned on either a 2-byte or 4-byte boundary.  We get at
+        * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+        * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+        * alignment for the unrolled loop.
+        */
+
+       .text
+ENTRY(csum_partial)
+       ; Function args
+       ;  r0: unsigned char *buff
+       ;  r1: int len
+       ;  r2: unsigned int sum
+
+       push    r2
+       ldi     r2, #0
+       and3    r7, r0, #1              ; Check alignment.
+       beqz    r7, 1f                  ; Jump if alignment is ok.
+       ; 1-byte mis aligned
+       ldub    r4, @r0
+       addi    r0, #1
+       addi    r1, #-1                 ; Alignment uses up bytes.
+       cmp     r0, r0                  ; clear c-bit
+       ldi     r3, #0
+       addx    r2, r4
+       addx    r2, r3
+       .fillinsn
+1:
+       and3    r4, r0, #2              ; Check alignment.
+       beqz    r4, 2f                  ; Jump if alignment is ok.
+       addi    r1, #-2                 ; Alignment uses up two bytes.
+       cmp             r0, r0                  ; clear c-bit
+       bgtz    r1, 1f                  ; Jump if we had at least two bytes.
+       addi    r1, #2                  ; len(r1) was < 2.  Deal with it.
+       bra     4f
+       .fillinsn
+1:
+       ; 2-byte aligned
+       lduh    r4, @r0
+       addi    r0, #2
+       ldi             r3, #0
+       addx    r2, r4
+       addx    r2, r3
+       .fillinsn
+2:
+       ; 4-byte aligned
+       cmp     r0, r0                  ; clear c-bit
+       srl3    r6, r1, #5
+       beqz    r6, 2f
+       .fillinsn
+
+1:     ld      r3, @r0+
+       ld      r4, @r0+                ; +4
+       ld      r5, @r0+                ; +8
+       addx    r2, r3
+       addx    r2, r4
+       addx    r2, r5
+       ld      r3, @r0+                ; +12
+       ld      r4, @r0+                ; +16
+       ld      r5, @r0+                ; +20
+       addx    r2, r3
+       addx    r2, r4
+       addx    r2, r5
+       ld      r3, @r0+                ; +24
+       ld      r4, @r0+                ; +28
+       addi    r6, #-1
+       addx    r2, r3
+       addx    r2, r4
+       bnez    r6, 1b
+       addx    r2, r6                  ; r6=0
+       cmp     r0, r0                  ; This clears c-bit
+       .fillinsn
+
+2:     and3    r6, r1, #0x1c           ; withdraw len
+       beqz    r6, 4f
+       srli    r6, #2
+       .fillinsn
+
+3:     ld      r4, @r0+
+       addi    r6, #-1
+       addx    r2, r4
+       bnez    r6, 3b
+       addx    r2, r6                  ; r6=0
+       cmp     r0, r0                  ; This clears c-bit
+       .fillinsn
+
+4:     and3    r1, r1, #3
+       beqz    r1, 7f                  ; if len == 0 goto end
+       and3    r6, r1, #2
+       beqz    r6, 5f                  ; if len < 2  goto 5f(1byte)
+
+       lduh    r4, @r0
+       addi    r0, #2
+       addi    r1, #-2
+       slli    r4, #16
+       addx    r2, r4
+       beqz    r1, 6f
+       .fillinsn
+5:     ldub    r4, @r0
+#ifndef __LITTLE_ENDIAN__
+       slli    r4, #8
+#endif
+       addx    r2, r4
+       .fillinsn
+6:     ldi     r5, #0
+       addx    r2, r5
+       .fillinsn
+7:
+       and3    r0, r2, #0xffff
+       srli    r2, #16
+       add     r0, r2
+       srl3    r2, r0, #16
+       beqz    r2, 1f
+       addi    r0, #1
+       and3    r0, r0, #0xffff
+       .fillinsn
+1:
+       beqz    r7, 1f
+       mv      r2, r0
+       srl3    r0, r2, #8
+       and3    r2, r2, #0xff
+       slli    r2, #8
+       or      r0, r2
+       .fillinsn
+1:
+       pop     r2
+       cmp     r0, r0
+       addx    r0, r2
+       ldi     r2, #0
+       addx    r0, r2
+       jmp     r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst,
+                                 int len, int sum, int *src_err_ptr, int *dst_err_ptr)
+ */
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for all access types.
+ *
+ * FIXME: could someone double-check whether I haven't mixed up some SRC and
+ *       DST definitions? It's damn hard to trigger all cases.  I hope I got
+ *       them all but there's no guarantee.
+ */
+
+ENTRY(csum_partial_copy_generic)
+       nop
+       nop
+       nop
+       nop
+       jmp r14
+       nop
+       nop
+       nop
+
diff --git a/arch/m32r/lib/csum_partial_copy.c b/arch/m32r/lib/csum_partial_copy.c
new file mode 100644 (file)
index 0000000..22600fc
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * INET                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.
+ *
+ *             MIPS specific IP/TCP/UDP checksumming routines
+ *
+ * Authors:    Ralf Baechle, <ralf@waldorf-gmbh.de>
+ *             Lots of code moved from tcp.c and ip.c; see those files
+ *             for more names.
+ *
+ *             This program is free software; you can redistribute 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/types.h>
+
+#include <net/checksum.h>
+#include <asm/byteorder.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+/*
+ * Copy while checksumming, otherwise like csum_partial
+ */
+unsigned int csum_partial_copy_nocheck (const char *src, char *dst,
+                                        int len, unsigned int sum)
+{
+       sum = csum_partial(src, len, sum);
+       memcpy(dst, src, len);
+
+       return sum;
+}
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+
+/*
+ * Copy from userspace and compute checksum.  If we catch an exception
+ * then zero the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user (const char __user *src, char *dst,
+                                          int len, unsigned int sum,
+                                          int *err_ptr)
+{
+       int missing;
+
+       missing = copy_from_user(dst, src, len);
+       if (missing) {
+               memset(dst + len - missing, 0, missing);
+               *err_ptr = -EFAULT;
+       }
+
+       return csum_partial(dst, len-missing, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy_from_user);
diff --git a/arch/m32r/lib/delay.c b/arch/m32r/lib/delay.c
new file mode 100644 (file)
index 0000000..7afe66e
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/m32r/lib/delay.c
+ *
+ * Copyright (c) 2002  Hitoshi Yamamoto, Hirokazu Takata
+ * Copyright (c) 2004  Hirokazu Takata
+ */
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <linux/param.h>
+#ifdef CONFIG_SMP
+#include <linux/sched.h>
+#include <asm/current.h>
+#include <asm/smp.h>
+#endif  /* CONFIG_SMP */
+#include <asm/processor.h>
+
+void __delay(unsigned long loops)
+{
+#ifdef CONFIG_ISA_DUAL_ISSUE
+       __asm__ __volatile__ (
+               "beqz   %0, 2f                  \n\t"
+               "addi   %0, #-1                 \n\t"
+
+               " .fillinsn                     \n\t"
+               "1:                             \n\t"
+               "cmpz   %0  ||  addi  %0, #-1   \n\t"
+               "bc     2f  ||  cmpz  %0        \n\t"
+               "bc     2f  ||  addi  %0, #-1   \n\t"
+               "cmpz   %0  ||  addi  %0, #-1   \n\t"
+               "bc     2f  ||  cmpz  %0        \n\t"
+               "bnc    1b  ||  addi  %0, #-1   \n\t"
+               " .fillinsn                     \n\t"
+               "2:                             \n\t"
+               : "+r" (loops)
+               : "r" (0)
+               : "cbit"
+       );
+#else
+       __asm__ __volatile__ (
+               "beqz   %0, 2f                  \n\t"
+               " .fillinsn                     \n\t"
+               "1:                             \n\t"
+               "addi   %0, #-1                 \n\t"
+               "blez   %0, 2f                  \n\t"
+               "addi   %0, #-1                 \n\t"
+               "blez   %0, 2f                  \n\t"
+               "addi   %0, #-1                 \n\t"
+               "blez   %0, 2f                  \n\t"
+               "addi   %0, #-1                 \n\t"
+               "bgtz   %0, 1b                  \n\t"
+               " .fillinsn                     \n\t"
+               "2:i                            \n\t"
+               : "+r" (loops)
+               : "r" (0)
+       );
+#endif
+}
+
+void __const_udelay(unsigned long xloops)
+{
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+       /*
+        * loops [1] = (xloops >> 32) [sec] * loops_per_jiffy [1/jiffy]
+        *            * HZ [jiffy/sec]
+        *          = (xloops >> 32) [sec] * (loops_per_jiffy * HZ) [1/sec]
+        *          = (((xloops * loops_per_jiffy) >> 32) * HZ) [1]
+        *
+        * NOTE:
+        *   - '[]' depicts variable's dimension in the above equation.
+        *   - "rac" instruction rounds the accumulator in word size.
+        */
+       __asm__ __volatile__ (
+               "srli   %0, #1                          \n\t"
+               "mulwhi %0, %1  ; a0                    \n\t"
+               "mulwu1 %0, %1  ; a1                    \n\t"
+               "sadd           ; a0 += (a1 >> 16)      \n\t"
+               "rac    a0, a0, #1                      \n\t"
+               "mvfacmi %0, a0                         \n\t"
+               : "+r" (xloops)
+               : "r" (current_cpu_data.loops_per_jiffy)
+               : "a0", "a1"
+       );
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+       /*
+        * u64 ull;
+        * ull = (u64)xloops * (u64)current_cpu_data.loops_per_jiffy;
+        * xloops = (ull >> 32);
+        */
+       __asm__ __volatile__ (
+               "and3   r4, %0, #0xffff         \n\t"
+               "and3   r5, %1, #0xffff         \n\t"
+               "mul    r4, r5                  \n\t"
+               "srl3   r6, %0, #16             \n\t"
+               "srli   r4, #16                 \n\t"
+               "mul    r5, r6                  \n\t"
+               "add    r4, r5                  \n\t"
+               "and3   r5, %0, #0xffff         \n\t"
+               "srl3   r6, %1, #16             \n\t"
+               "mul    r5, r6                  \n\t"
+               "add    r4, r5                  \n\t"
+               "srl3   r5, %0, #16             \n\t"
+               "srli   r4, #16                 \n\t"
+               "mul    r5, r6                  \n\t"
+               "add    r4, r5                  \n\t"
+               "mv     %0, r4                  \n\t"
+               : "+r" (xloops)
+               : "r" (current_cpu_data.loops_per_jiffy)
+               : "r4", "r5", "r6"
+       );
+#else
+#error unknown isa configuration
+#endif
+       __delay(xloops * HZ);
+}
+
+void __udelay(unsigned long usecs)
+{
+       __const_udelay(usecs * 0x000010c7);  /* 2**32 / 1000000 (rounded up) */
+}
+
+void __ndelay(unsigned long nsecs)
+{
+       __const_udelay(nsecs * 0x00005);  /* 2**32 / 1000000000 (rounded up) */
+}
diff --git a/arch/m32r/lib/getuser.S b/arch/m32r/lib/getuser.S
new file mode 100644 (file)
index 0000000..58a0db0
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * __get_user functions.
+ *
+ * (C) Copyright 2001 Hirokazu Takata
+ *
+ * These functions have a non-standard call interface
+ * to make them more efficient, especially as they
+ * return an error value in addition to the "real"
+ * return value.
+ */
+
+#include <linux/config.h>
+
+/*
+ * __get_user_X
+ *
+ * Inputs:     r0 contains the address
+ *
+ * Outputs:    r0 is error code (0 or -EFAULT)
+ *             r1 contains zero-extended value
+ *
+ * These functions should not modify any other registers,
+ * as they get called from within inline assembly.
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+       .text
+       .balign 4
+       .globl __get_user_1
+__get_user_1:
+1:     ldub    r1, @r0             ||  ldi     r0, #0
+       jmp     r14
+
+       .balign 4
+       .globl __get_user_2
+__get_user_2:
+2:     lduh    r1, @r0             ||  ldi     r0, #0
+       jmp     r14
+
+       .balign 4
+       .globl __get_user_4
+__get_user_4:
+3:     ld      r1, @r0             ||  ldi     r0, #0
+       jmp     r14
+
+bad_get_user:
+       ldi     r1, #0              ||  ldi     r0, #-14
+       jmp     r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+       .text
+       .balign 4
+       .globl __get_user_1
+__get_user_1:
+1:     ldub    r1, @r0
+       ldi     r0, #0
+       jmp     r14
+
+       .balign 4
+       .globl __get_user_2
+__get_user_2:
+2:     lduh    r1, @r0
+       ldi     r0, #0
+       jmp     r14
+
+       .balign 4
+       .globl __get_user_4
+__get_user_4:
+3:     ld      r1, @r0
+       ldi     r0, #0
+       jmp     r14
+
+bad_get_user:
+       ldi     r1, #0
+       ldi     r0, #-14
+       jmp     r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+.section __ex_table,"a"
+       .long 1b,bad_get_user
+       .long 2b,bad_get_user
+       .long 3b,bad_get_user
+.previous
+
+       .end
diff --git a/arch/m32r/lib/memcpy.S b/arch/m32r/lib/memcpy.S
new file mode 100644 (file)
index 0000000..800898a
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  linux/arch/m32r/lib/memcpy.S
+ *
+ *  Copyright (C) 2001  Hiroyuki Kondo, and Hirokazu Takata
+ *  Copyright (C) 2004  Hirokazu Takata
+ *
+ *  void *memcopy(void *dst, const void *src, int n);
+ *
+ *        dst: r0
+ *        src: r1
+ *        n  : r2
+ */
+/* $Id$ */
+
+
+       .text
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+       .text
+ENTRY(memcpy)
+memcopy:
+       mv      r4, r0              ||  mv      r7, r0
+       or      r7, r1              ||  cmpz    r2
+       jc      r14                 ||  cmpeq   r0, r1  ; return if r2=0
+       jc      r14                                     ; return if r0=r1
+
+       and3    r7, r7, #3
+       bnez    r7, byte_copy
+       srl3    r3, r2, #2
+       and3    r2, r2, #3
+       beqz    r3, byte_copy
+       addi    r4, #-4
+word_copy:
+       ld      r7, @r1+            ||  addi    r3, #-1
+       st      r7, @+r4            ||  cmpz    r2
+       bnez    r3, word_copy
+       addi    r4, #4              ||  jc      r14     ; return if r2=0
+#if defined(CONFIG_ISA_M32R2)
+byte_copy:
+       ldb     r7, @r1             ||  addi    r1, #1
+       addi    r2, #-1             ||  stb     r7, @r4+
+       bnez    r2, byte_copy
+#elif defined(CONFIG_ISA_M32R)
+byte_copy:
+       ldb     r7, @r1             ||  addi    r1, #1
+       addi    r2, #-1             ||  stb     r7, @r4
+       addi    r4, #1
+       bnez    r2, byte_copy
+#else
+#error unknown isa configuration
+#endif
+end_memcopy:
+       jmp     r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+       .text
+ENTRY(memcpy)
+memcopy:
+       mv      r4, r0
+       mv      r7, r0
+       or      r7, r1
+       beq     r0, r1, end_memcopy
+       beqz    r2, end_memcopy
+
+       and3    r7, r7, #3
+       bnez    r7, byte_copy
+       srl3    r3, r2, #2
+       and3    r2, r2, #3
+       beqz    r3, byte_copy
+       addi    r4, #-4
+word_copy:
+       ld      r7, @r1+
+       addi    r3, #-1
+       st      r7, @+r4
+       bnez    r3, word_copy
+       beqz    r2, end_memcopy
+       addi    r4, #4
+byte_copy:
+       ldb     r7, @r1
+       addi    r1, #1
+       addi    r2, #-1
+       stb     r7, @r4
+       addi    r4, #1
+       bnez    r2, byte_copy
+end_memcopy:
+       jmp     r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+       .end
diff --git a/arch/m32r/lib/memset.S b/arch/m32r/lib/memset.S
new file mode 100644 (file)
index 0000000..7fe94b6
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ *  linux/arch/m32r/lib/memset.S
+ *
+ *  Copyright (C) 2001,2002  Hiroyuki Kondo, and Hirokazu Takata
+ *  Copyright (C) 2004  Hirokazu Takata
+ *
+ *  void *memset(void *dst, int val, int len);
+ *
+ *        dst: r0
+ *        val: r1
+ *        len: r2
+ *        ret: r0
+ *
+ */
+/* $Id$ */
+
+#include <linux/config.h>
+
+       .text
+       .global memset
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+       .align 4
+memset:
+       mv      r4, r0              ||  cmpz    r2
+       jc      r14
+       cmpui   r2, #16
+       bnc     qword_align_check
+       cmpui   r2, #4
+       bc      byte_set
+word_align_check:                      /* len >= 4 */
+       and3    r3, r4, #3
+       beqz    r3, word_set
+       addi    r3, #-4
+       neg     r3, r3                  /* r3 = -(r3 - 4) */
+align_word:
+       stb     r1, @r4             ||  addi    r4, #1
+       addi    r2, #-1             ||  addi    r3, #-1
+       bnez    r3, align_word
+       cmpui   r2, #4
+       bc      byte_set
+word_set:
+       and3    r1, r1, #0x00ff         /* r1: abababab <-- ??????ab */
+       sll3    r3, r1, #8
+       or      r1, r3              ||  addi    r4, #-4
+       sll3    r3, r1, #16
+       or      r1, r3              ||  addi    r2, #-4
+word_set_loop:
+       st      r1, @+r4            ||  addi    r2, #-4
+       bgtz    r2, word_set_loop
+       bnez    r2, byte_set_wrap
+       st      r1, @+r4
+       jmp     r14
+
+qword_align_check:                     /* len >= 16 */
+       and3    r3, r4, #15
+       bnez    r3, word_align_check
+qword_set:
+       and3    r1, r1, #0x00ff         /* r1: abababab <-- ??????ab */
+       sll3    r3, r1, #8
+       or      r1, r3              ||  addi    r4, #-4
+       sll3    r3, r1, #16
+       or      r1, r3              ||  ldi     r5, #16
+qword_set_loop:
+       ld      r3, @(4,r4)             /* cache line allocate */
+       st      r1, @+r4            ||  addi    r2, #-16
+       st      r1, @+r4            ||  cmpu    r2, r5
+       st      r1, @+r4
+       st      r1, @+r4
+       bnc     qword_set_loop      ||  cmpz    r2
+       jc      r14
+word_set_wrap:
+       cmpui   r2, #4
+       bc      byte_set
+       addi    r2, #-4
+       bra     word_set_loop
+
+byte_set_wrap:
+       addi    r2, #4
+       addi    r4, #4              ||  cmpz    r2
+       jc      r14
+#if defined(CONFIG_ISA_M32R2)
+byte_set:
+       addi    r2, #-1             ||  stb     r1, @r4+
+       bnez    r2, byte_set
+#elif defined(CONFIG_ISA_M32R)
+byte_set:
+       addi    r2, #-1             ||  stb     r1, @r4
+       addi    r4, #1
+       bnez    r2, byte_set
+#else
+#error unknown isa configuration
+#endif
+end_memset:
+       jmp     r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+       .align 4
+memset:
+       mv      r4, r0
+       beqz    r2, end_memset
+       cmpui   r2, #16
+       bnc     qword_align_check
+       cmpui   r2, #4
+       bc      byte_set
+word_align_check:                      /* len >= 4 */
+       and3    r3, r4, #3
+       beqz    r3, word_set
+       addi    r3, #-4
+       neg     r3, r3                  /* r3 = -(r3 - 4) */
+align_word:
+       stb     r1, @r4
+       addi    r4, #1
+       addi    r2, #-1
+       addi    r3, #-1
+       bnez    r3, align_word
+       cmpui   r2, #4
+       bc      byte_set
+word_set:
+       and3    r1, r1, #0x00ff         /* r1: abababab <-- ??????ab */
+       sll3    r3, r1, #8
+       or      r1, r3
+       sll3    r3, r1, #16
+       or      r1, r3
+       addi    r2, #-4
+       addi    r4, #-4
+word_set_loop:
+       st      r1, @+r4
+       addi    r2, #-4
+       bgtz    r2, word_set_loop
+       bnez    r2, byte_set_wrap
+       st      r1, @+r4
+       jmp     r14
+
+qword_align_check:                     /* len >= 16 */
+       and3    r3, r4, #15
+       bnez    r3, word_align_check
+qword_set:
+       and3    r1, r1, #0x00ff         /* r1: abababab <-- ??????ab */
+       sll3    r3, r1, #8
+       or      r1, r3
+       sll3    r3, r1, #16
+       or      r1, r3
+       addi    r4, #-4
+qword_set_loop:
+       ld      r3, @(4,r4)             /* cache line allocate */
+       addi    r2, #-16
+       st      r1, @+r4
+       st      r1, @+r4
+       cmpui   r2, #16
+       st      r1, @+r4
+       st      r1, @+r4
+       bnc     qword_set_loop
+       bnez    r2, word_set_wrap
+       jmp     r14
+word_set_wrap:
+       cmpui   r2, #4
+       bc      byte_set
+       addi    r2, #-4
+       bra     word_set_loop
+
+byte_set_wrap:
+       addi    r2, #4
+       addi    r4, #4
+       beqz    r2, end_memset
+byte_set:
+       addi    r2, #-1
+       stb     r1, @r4
+       addi    r4, #1
+       bnez    r2, byte_set
+end_memset:
+       jmp     r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+       .end
diff --git a/arch/m32r/lib/putuser.S b/arch/m32r/lib/putuser.S
new file mode 100644 (file)
index 0000000..218154c
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * __put_user functions.
+ *
+ * (C) Copyright 1998 Linus Torvalds
+ * (C) Copyright 2001 Hirokazu Takata
+ *
+ * These functions have a non-standard call interface
+ * to make them more efficient.
+ */
+
+#include <linux/config.h>
+
+/*
+ * __put_user_X
+ *
+ * Inputs:     r0 contains the address
+ *             r1 contains the value
+ *
+ * Outputs:    r0 is error code (0 or -EFAULT)
+ *             r1 is corrupted (will contain "current_task").
+ *
+ * These functions should not modify any other registers,
+ * as they get called from within inline assembly.
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+       .text
+       .balign 4
+       .globl __put_user_1
+__put_user_1:
+1:     stb     r1, @r0             ||  ldi     r0, #0
+       jmp     r14
+
+       .balign 4
+       .globl __put_user_2
+__put_user_2:
+2:     sth     r1, @r0             ||  ldi     r0, #0
+       jmp     r14
+
+       .balign 4
+       .globl __put_user_4
+__put_user_4:
+3:     st      r1, @r0             ||  ldi     r0, #0
+       jmp     r14
+
+bad_put_user:
+       ldi     r0, #-14            ||  jmp     r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+       .text
+       .balign 4
+       .globl __put_user_1
+__put_user_1:
+1:     stb     r1, @r0
+       ldi     r0, #0
+       jmp     r14
+
+       .balign 4
+       .globl __put_user_2
+__put_user_2:
+2:     sth     r1, @r0
+       ldi     r0, #0
+       jmp     r14
+
+       .balign 4
+       .globl __put_user_4
+__put_user_4:
+3:     st      r1, @r0
+       ldi     r0, #0
+       jmp     r14
+
+bad_put_user:
+       ldi     r0, #-14
+       jmp     r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+.section __ex_table,"a"
+       .long 1b,bad_put_user
+       .long 2b,bad_put_user
+       .long 3b,bad_put_user
+.previous
diff --git a/arch/m32r/lib/strlen.S b/arch/m32r/lib/strlen.S
new file mode 100644 (file)
index 0000000..8d23cfb
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  linux/arch/m32r/strlen.S --  strlen code.
+ *
+ *  Copyright (C) 2001  Hirokazu Takata
+ *
+ *  size_t strlen(const char *s);
+ *
+ */
+/* $Id$ */
+
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+       .text
+ENTRY(strlen)
+       mv      r6, r0              ||  ldi     r2, #0
+       and3    r0, r0, #3
+       bnez    r0, strlen_byte
+;
+strlen_word:
+       ld      r0, @r6+
+;
+       seth    r5, #high(0x01010101)
+       or3     r5, r5, #low(0x01010101)
+       sll3    r7, r5, #7
+strlen_word_loop:
+       ld      r1, @r6+            ||  not     r4, r0
+       sub     r0, r5              ||  and     r4, r7
+       and     r4, r0
+       bnez    r4, strlen_last_bytes
+       ld      r0, @r6+            ||  not     r4, r1
+       sub     r1, r5              ||  and     r4, r7
+       and     r4, r1              ||  addi    r2, #4
+       bnez    r4, strlen_last_bytes
+       addi    r2, #4              ||  bra.s   strlen_word_loop
+
+       ; NOTE: If a null char. exists, return 0.
+       ; if ((x - 0x01010101) & ~x & 0x80808080)
+       ;     return 0;
+;
+strlen_byte:
+       ldb     r1, @r6             ||  addi    r6, #1
+       beqz    r1, strlen_exit
+       addi    r2, #1              ||  bra.s   strlen_byte
+;
+strlen_last_bytes:
+       ldi     r0, #4              ||  addi    r6, #-8
+;
+strlen_byte_loop:
+       ldb     r1, @r6             ||  addi    r6, #1
+       addi    r0, #-1             ||  cmpz    r1
+       bc.s    strlen_exit         ||  cmpz    r0
+       addi    r2, #1              ||  bnc.s   strlen_byte_loop
+;
+strlen_exit:
+       mv      r0, r2              ||  jmp     r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+       .text
+ENTRY(strlen)
+       mv      r6, r0
+       ldi     r2, #0
+       and3    r0, r0, #3
+       bnez    r0, strlen_byte
+;
+strlen_word:
+       ld      r0, @r6+
+;
+       seth    r5, #high(0x01010101)
+       or3     r5, r5, #low(0x01010101)
+       sll3    r7, r5, #7
+strlen_word_loop:
+       ld      r1, @r6+
+       not     r4, r0          ; NOTE: If a null char. exists, return 0.
+       sub     r0, r5          ; if ((x - 0x01010101) & ~x & 0x80808080)
+       and     r4, r7          ;     return 0;
+       and     r4, r0
+       bnez    r4, strlen_last_bytes
+       addi    r2, #4
+;
+       ld      r0, @r6+
+       not     r4, r1          ; NOTE: If a null char. exists, return 0.
+       sub     r1, r5          ; if ((x - 0x01010101) & ~x & 0x80808080)
+       and     r4, r7          ;     return 0;
+       and     r4, r1
+       bnez    r4, strlen_last_bytes
+       addi    r2, #4
+       bra     strlen_word_loop
+;
+strlen_byte:
+       ldb     r1, @r6
+       addi    r6, #1
+       beqz    r1, strlen_exit
+       addi    r2, #1
+       bra     strlen_byte
+;
+strlen_last_bytes:
+       ldi     r0, #4
+       addi    r6, #-8
+;
+strlen_byte_loop:
+       ldb     r1, @r6
+       addi    r6, #1
+       addi    r0, #-1
+       beqz    r1, strlen_exit
+       addi    r2, #1
+       bnez    r0, strlen_byte_loop
+;
+strlen_exit:
+       mv      r0, r2
+       jmp     r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+       .end
diff --git a/arch/m32r/lib/usercopy.c b/arch/m32r/lib/usercopy.c
new file mode 100644 (file)
index 0000000..6c6855f
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * User address space access functions.
+ * The non inlined parts of asm-m32r/uaccess.h are here.
+ *
+ * Copyright 1997 Andi Kleen <ak@muc.de>
+ * Copyright 1997 Linus Torvalds
+ * Copyright 2001, 2002, 2004 Hirokazu Takata
+ */
+#include <linux/config.h>
+#include <linux/prefetch.h>
+#include <linux/string.h>
+#include <linux/thread_info.h>
+#include <asm/uaccess.h>
+
+unsigned long
+__generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+       prefetch(from);
+       if (access_ok(VERIFY_WRITE, to, n))
+               __copy_user(to,from,n);
+       return n;
+}
+
+unsigned long
+__generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+       prefetchw(to);
+       if (access_ok(VERIFY_READ, from, n))
+               __copy_user_zeroing(to,from,n);
+       else
+               memset(to, 0, n);
+       return n;
+}
+
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+#define __do_strncpy_from_user(dst,src,count,res)                      \
+do {                                                                   \
+       int __d0, __d1, __d2;                                           \
+       __asm__ __volatile__(                                           \
+               "       beqz    %1, 2f\n"                               \
+               "       .fillinsn\n"                                    \
+               "0:     ldb     r14, @%3    ||  addi    %3, #1\n"       \
+               "       stb     r14, @%4    ||  addi    %4, #1\n"       \
+               "       beqz    r14, 1f\n"                              \
+               "       addi    %1, #-1\n"                              \
+               "       bnez    %1, 0b\n"                               \
+               "       .fillinsn\n"                                    \
+               "1:     sub     %0, %1\n"                               \
+               "       .fillinsn\n"                                    \
+               "2:\n"                                                  \
+               ".section .fixup,\"ax\"\n"                              \
+               "       .balign 4\n"                                    \
+               "3:     seth    r14, #high(2b)\n"                       \
+               "       or3     r14, r14, #low(2b)\n"                   \
+               "       jmp     r14         ||  ldi     %0, #%5\n"      \
+               ".previous\n"                                           \
+               ".section __ex_table,\"a\"\n"                           \
+               "       .balign 4\n"                                    \
+               "       .long 0b,3b\n"                                  \
+               ".previous"                                             \
+               : "=r"(res), "=r"(count), "=&r" (__d0), "=&r" (__d1),   \
+                 "=&r" (__d2)                                          \
+               : "i"(-EFAULT), "0"(count), "1"(count), "3"(src),       \
+                 "4"(dst)                                              \
+               : "r14", "cbit", "memory");                             \
+} while (0)
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+#define __do_strncpy_from_user(dst,src,count,res)                      \
+do {                                                                   \
+       int __d0, __d1, __d2;                                           \
+       __asm__ __volatile__(                                           \
+               "       beqz    %1, 2f\n"                               \
+               "       .fillinsn\n"                                    \
+               "0:     ldb     r14, @%3\n"                             \
+               "       stb     r14, @%4\n"                             \
+               "       addi    %3, #1\n"                               \
+               "       addi    %4, #1\n"                               \
+               "       beqz    r14, 1f\n"                              \
+               "       addi    %1, #-1\n"                              \
+               "       bnez    %1, 0b\n"                               \
+               "       .fillinsn\n"                                    \
+               "1:     sub     %0, %1\n"                               \
+               "       .fillinsn\n"                                    \
+               "2:\n"                                                  \
+               ".section .fixup,\"ax\"\n"                              \
+               "       .balign 4\n"                                    \
+               "3:     ldi     %0, #%5\n"                              \
+               "       seth    r14, #high(2b)\n"                       \
+               "       or3     r14, r14, #low(2b)\n"                   \
+               "       jmp     r14\n"                                  \
+               ".previous\n"                                           \
+               ".section __ex_table,\"a\"\n"                           \
+               "       .balign 4\n"                                    \
+               "       .long 0b,3b\n"                                  \
+               ".previous"                                             \
+               : "=r"(res), "=r"(count), "=&r" (__d0), "=&r" (__d1),   \
+                 "=&r" (__d2)                                          \
+               : "i"(-EFAULT), "0"(count), "1"(count), "3"(src),       \
+                 "4"(dst)                                              \
+               : "r14", "cbit", "memory");                             \
+} while (0)
+
+#endif /* CONFIG_ISA_DUAL_ISSUE */
+
+long
+__strncpy_from_user(char *dst, const char *src, long count)
+{
+       long res;
+       __do_strncpy_from_user(dst, src, count, res);
+       return res;
+}
+
+long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+       long res = -EFAULT;
+       if (access_ok(VERIFY_READ, src, 1))
+               __do_strncpy_from_user(dst, src, count, res);
+       return res;
+}
+
+
+/*
+ * Zero Userspace
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+#define __do_clear_user(addr,size)                                     \
+do {                                                                   \
+       int __dst, __c;                                                 \
+       __asm__ __volatile__(                                           \
+               "       beqz    %1, 9f\n"                               \
+               "       and3    r14, %0, #3\n"                          \
+               "       bnez    r14, 2f\n"                              \
+               "       and3    r14, %1, #3\n"                          \
+               "       bnez    r14, 2f\n"                              \
+               "       and3    %1, %1, #3\n"                           \
+               "       beqz    %2, 2f\n"                               \
+               "       addi    %0, #-4\n"                              \
+               "       .fillinsn\n"                                    \
+               "0:     ; word clear \n"                                \
+               "       st      %6, @+%0    ||  addi    %2, #-1\n"      \
+               "       bnez    %2, 0b\n"                               \
+               "       beqz    %1, 9f\n"                               \
+               "       .fillinsn\n"                                    \
+               "2:     ; byte clear \n"                                \
+               "       stb     %6, @%0     ||  addi    %1, #-1\n"      \
+               "       addi    %0, #1\n"                               \
+               "       bnez    %1, 2b\n"                               \
+               "       .fillinsn\n"                                    \
+               "9:\n"                                                  \
+               ".section .fixup,\"ax\"\n"                              \
+               "       .balign 4\n"                                    \
+               "4:     slli    %2, #2\n"                               \
+               "       seth    r14, #high(9b)\n"                       \
+               "       or3     r14, r14, #low(9b)\n"                   \
+               "       jmp     r14         ||  add     %1, %2\n"       \
+               ".previous\n"                                           \
+               ".section __ex_table,\"a\"\n"                           \
+               "       .balign 4\n"                                    \
+               "       .long 0b,4b\n"                                  \
+               "       .long 2b,9b\n"                                  \
+               ".previous\n"                                           \
+               : "=&r"(__dst), "=&r"(size), "=&r"(__c)                 \
+               : "0"(addr), "1"(size), "2"(size / 4), "r"(0)           \
+               : "r14", "cbit", "memory");                             \
+} while (0)
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+#define __do_clear_user(addr,size)                                     \
+do {                                                                   \
+       int __dst, __c;                                                 \
+       __asm__ __volatile__(                                           \
+               "       beqz    %1, 9f\n"                               \
+               "       and3    r14, %0, #3\n"                          \
+               "       bnez    r14, 2f\n"                              \
+               "       and3    r14, %1, #3\n"                          \
+               "       bnez    r14, 2f\n"                              \
+               "       and3    %1, %1, #3\n"                           \
+               "       beqz    %2, 2f\n"                               \
+               "       addi    %0, #-4\n"                              \
+               "       .fillinsn\n"                                    \
+               "0:     st      %6, @+%0        ; word clear \n"        \
+               "       addi    %2, #-1\n"                              \
+               "       bnez    %2, 0b\n"                               \
+               "       beqz    %1, 9f\n"                               \
+               "       .fillinsn\n"                                    \
+               "2:     stb     %6, @%0         ; byte clear \n"        \
+               "       addi    %1, #-1\n"                              \
+               "       addi    %0, #1\n"                               \
+               "       bnez    %1, 2b\n"                               \
+               "       .fillinsn\n"                                    \
+               "9:\n"                                                  \
+               ".section .fixup,\"ax\"\n"                              \
+               "       .balign 4\n"                                    \
+               "4:     slli    %2, #2\n"                               \
+               "       add     %1, %2\n"                               \
+               "       seth    r14, #high(9b)\n"                       \
+               "       or3     r14, r14, #low(9b)\n"                   \
+               "       jmp     r14\n"                                  \
+               ".previous\n"                                           \
+               ".section __ex_table,\"a\"\n"                           \
+               "       .balign 4\n"                                    \
+               "       .long 0b,4b\n"                                  \
+               "       .long 2b,9b\n"                                  \
+               ".previous\n"                                           \
+               : "=&r"(__dst), "=&r"(size), "=&r"(__c)                 \
+               : "0"(addr), "1"(size), "2"(size / 4), "r"(0)           \
+               : "r14", "cbit", "memory");                             \
+} while (0)
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+unsigned long
+clear_user(void *to, unsigned long n)
+{
+       if (access_ok(VERIFY_WRITE, to, n))
+               __do_clear_user(to, n);
+       return n;
+}
+
+unsigned long
+__clear_user(void *to, unsigned long n)
+{
+       __do_clear_user(to, n);
+       return n;
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+long strnlen_user(const char *s, long n)
+{
+       unsigned long mask = -__addr_ok(s);
+       unsigned long res;
+
+       __asm__ __volatile__(
+               "       and     %0, %5      ||  mv      r1, %1\n"
+               "       beqz    %0, strnlen_exit\n"
+               "       and3    r0, %1, #3\n"
+               "       bnez    r0, strnlen_byte_loop\n"
+               "       cmpui   %0, #4\n"
+               "       bc      strnlen_byte_loop\n"
+               "strnlen_word_loop:\n"
+               "0:     ld      r0, @%1+\n"
+               "       pcmpbz  r0\n"
+               "       bc      strnlen_last_bytes_fixup\n"
+               "       addi    %0, #-4\n"
+               "       beqz    %0, strnlen_exit\n"
+               "       bgtz    %0, strnlen_word_loop\n"
+               "strnlen_last_bytes:\n"
+               "       mv      %0, %4\n"
+               "strnlen_last_bytes_fixup:\n"
+               "       addi    %1, #-4\n"
+               "strnlen_byte_loop:\n"
+               "1:     ldb     r0, @%1     ||  addi    %0, #-1\n"
+               "       beqz    r0, strnlen_exit\n"
+               "       addi    %1, #1\n"
+               "       bnez    %0, strnlen_byte_loop\n"
+               "strnlen_exit:\n"
+               "       sub     %1, r1\n"
+               "       add3    %0, %1, #1\n"
+               "       .fillinsn\n"
+               "9:\n"
+               ".section .fixup,\"ax\"\n"
+               "       .balign 4\n"
+               "4:     addi    %1, #-4\n"
+               "       .fillinsn\n"
+               "5:     seth    r1, #high(9b)\n"
+               "       or3     r1, r1, #low(9b)\n"
+               "       jmp     r1          ||  ldi     %0, #0\n"
+               ".previous\n"
+               ".section __ex_table,\"a\"\n"
+               "       .balign 4\n"
+               "       .long 0b,4b\n"
+               "       .long 1b,5b\n"
+               ".previous"
+               : "=&r" (res), "=r" (s)
+               : "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
+               : "r0", "r1", "cbit");
+
+       /* NOTE: strnlen_user() algorism:
+        * {
+        *   char *p;
+        *   for (p = s; n-- && *p != '\0'; ++p)
+        *     ;
+        *   return p - s + 1;
+        * }
+        */
+
+       /* NOTE: If a null char. exists, return 0.
+        * if ((x - 0x01010101) & ~x & 0x80808080)\n"
+        *   return 0;\n"
+        */
+
+       return res & mask;
+}
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+long strnlen_user(const char *s, long n)
+{
+       unsigned long mask = -__addr_ok(s);
+       unsigned long res;
+
+       __asm__ __volatile__(
+               "       and     %0, %5\n"
+               "       mv      r1, %1\n"
+               "       beqz    %0, strnlen_exit\n"
+               "       and3    r0, %1, #3\n"
+               "       bnez    r0, strnlen_byte_loop\n"
+               "       cmpui   %0, #4\n"
+               "       bc      strnlen_byte_loop\n"
+               "       sll3    r3, %6, #7\n"
+               "strnlen_word_loop:\n"
+               "0:     ld      r0, @%1+\n"
+               "       not     r2, r0\n"
+               "       sub     r0, %6\n"
+               "       and     r2, r3\n"
+               "       and     r2, r0\n"
+               "       bnez    r2, strnlen_last_bytes_fixup\n"
+               "       addi    %0, #-4\n"
+               "       beqz    %0, strnlen_exit\n"
+               "       bgtz    %0, strnlen_word_loop\n"
+               "strnlen_last_bytes:\n"
+               "       mv      %0, %4\n"
+               "strnlen_last_bytes_fixup:\n"
+               "       addi    %1, #-4\n"
+               "strnlen_byte_loop:\n"
+               "1:     ldb     r0, @%1\n"
+               "       addi    %0, #-1\n"
+               "       beqz    r0, strnlen_exit\n"
+               "       addi    %1, #1\n"
+               "       bnez    %0, strnlen_byte_loop\n"
+               "strnlen_exit:\n"
+               "       sub     %1, r1\n"
+               "       add3    %0, %1, #1\n"
+               "       .fillinsn\n"
+               "9:\n"
+               ".section .fixup,\"ax\"\n"
+               "       .balign 4\n"
+               "4:     addi    %1, #-4\n"
+               "       .fillinsn\n"
+               "5:     ldi     %0, #0\n"
+               "       seth    r1, #high(9b)\n"
+               "       or3     r1, r1, #low(9b)\n"
+               "       jmp     r1\n"
+               ".previous\n"
+               ".section __ex_table,\"a\"\n"
+               "       .balign 4\n"
+               "       .long 0b,4b\n"
+               "       .long 1b,5b\n"
+               ".previous"
+               : "=&r" (res), "=r" (s)
+               : "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
+               : "r0", "r1", "r2", "r3", "cbit");
+
+       /* NOTE: strnlen_user() algorism:
+        * {
+        *   char *p;
+        *   for (p = s; n-- && *p != '\0'; ++p)
+        *     ;
+        *   return p - s + 1;
+        * }
+        */
+
+       /* NOTE: If a null char. exists, return 0.
+        * if ((x - 0x01010101) & ~x & 0x80808080)\n"
+        *   return 0;\n"
+        */
+
+       return res & mask;
+}
+
+#endif /* CONFIG_ISA_DUAL_ISSUE */
+
diff --git a/arch/m32r/m32700ut/defconfig.m32700ut.smp b/arch/m32r/m32700ut/defconfig.m32700ut.smp
new file mode 100644 (file)
index 0000000..df7f9d0
--- /dev/null
@@ -0,0 +1,662 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=15
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+# CONFIG_IKCONFIG_PROC is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+CONFIG_PLAT_M32700UT=y
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=50000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+CONFIG_SMP=y
+CONFIG_CHIP_M32700_TS1=y
+CONFIG_NR_CPUS=2
+# CONFIG_NUMA is not set
+
+#
+# M32R drivers
+#
+# CONFIG_M32RPCC is not set
+CONFIG_M32R_CFC=y
+CONFIG_M32700UT_CFC=y
+CONFIG_CFC_NUM=1
+# CONFIG_MTD_M32R is not set
+CONFIG_M32R_SMC91111=y
+CONFIG_M32700UT_DS1302=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+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 is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG 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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_NETDEVICES is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 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
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_M32R_SIO is not set
+CONFIG_SERIAL_M32R_PLDSIO=y
+CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_CPIA is not set
+CONFIG_M32R_AR=y
+CONFIG_M32R_AR_VGA=y
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_EPSON_S1D13806=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_M32R_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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 is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/m32r/m32700ut/defconfig.m32700ut.up b/arch/m32r/m32700ut/defconfig.m32700ut.up
new file mode 100644 (file)
index 0000000..5a9da73
--- /dev/null
@@ -0,0 +1,659 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+# CONFIG_IKCONFIG_PROC is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+CONFIG_PLAT_M32700UT=y
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=50000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+# CONFIG_M32RPCC is not set
+CONFIG_M32R_CFC=y
+CONFIG_M32700UT_CFC=y
+CONFIG_CFC_NUM=1
+# CONFIG_MTD_M32R is not set
+CONFIG_M32R_SMC91111=y
+CONFIG_M32700UT_DS1302=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+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 is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG 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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_NETDEVICES is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 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
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_M32R_SIO is not set
+CONFIG_SERIAL_M32R_PLDSIO=y
+CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_CPIA is not set
+CONFIG_M32R_AR=y
+CONFIG_M32R_AR_VGA=y
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_EPSON_S1D13806=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_M32R_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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 is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/m32r/m32700ut/dot.gdbinit_200MHz_16MB b/arch/m32r/m32700ut/dot.gdbinit_200MHz_16MB
new file mode 100644 (file)
index 0000000..fa79cd9
--- /dev/null
@@ -0,0 +1,249 @@
+# .gdbinit file
+# $Id: dot.gdbinit_200MHz_16MB,v 1.1 2004/08/17 02:58:11 takata Exp $
+#-----
+# NOTE: this file is generated by a script, "gen_gdbinit.pl".
+# (Please type "gen_gdbinit.pl --help" and check the help message).
+# $ Id: gen_gdbinit.pl,v 1.12 2004/07/26 09:56:10 takata Exp $
+#-----
+# target platform: m32700ut
+
+# setting
+set width 0d70
+set radix 0d16
+
+debug_chaos
+
+# clk xin:cpu:bif:bus=25:200:50:50
+define clock_init
+  set *(unsigned long *)0x00ef4008 = 0x00000000
+  set *(unsigned long *)0x00ef4004 = 0
+  shell sleep 0.1
+  # NOTE: Please change the master clock source from PLL-clock to Xin-clock
+  # and switch off PLL, before resetting the clock gear ratio.
+
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 3
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x00000200
+end
+
+# Initialize SDRAM controller
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # Ch0-MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  # Ch0-TR
+  set *(unsigned long *)0x00ef6028 = 0x00041302
+  # Ch0-ADR (size:16MB)
+  set *(unsigned long *)0x00ef6020 = 0x08000002
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010517
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  SDRAM controller initialization
+  0x08000000 - 0x08ffffff (16MB)
+end
+
+# Initialize BSEL3 for UT-CFC
+define cfc_init
+  set $sfrbase = 0xa0ef0000
+# too fast
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x0b0b8000
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x00102204
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x1f1f8000
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x1f1f1fdf
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x0013220f
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x0013330f
+end
+document cfc_init
+  CF controller initialization
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb 0d32
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb 0d32
+end
+
+# Initialize TLB entries
+define init_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set *(unsigned long *)($addr + 0x4) = 0
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define tlb_init
+  set $itlb=0xfe000000
+  init_tlb_entries $itlb 0d32
+  set $dtlb=0xfe000800
+  init_tlb_entries $dtlb 0d32
+end
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set  = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+end
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+  clock_init
+  shell sleep 0.1
+  # SDRAM: 16MB
+  set *(unsigned long *)0x00ef6020 = 0x08000002
+  cfc_init
+  # USB
+  set *(unsigned short *)0xb0301000 = 0x100
+
+  set $evb=0x08000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x08002000
+  # INITRD_START
+  set *(unsigned long *)($param + 0x0010) = 0x082a0000
+  # INITRD_SIZE
+  set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d200000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d50000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x console=tty1 video=s1d13xxxfb:mode:240x320-16 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs,rsize=1024,wsize=1024 nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 mem=16M \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $fp = 0
+  set $pc = 0x08001000
+  set *(unsigned char *)0xffffffff = 0x03
+  si
+  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x08000030
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  set $pc = 0
+  b *0x04001000
+  b *0x08001000
+  b *0x08002000
+  si
+  c
+  tlb_init
+  del
+  setup
+  load_modules
+  boot
+end
+
+define si
+  stepi
+  x/i $pc
+  show_reg
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+set $pc = 0
+b *0x04001000
+b *0x08001000
+b *0x08002000
+c
+tlb_init
+del
+setup
+load_modules
+boot
+
diff --git a/arch/m32r/m32700ut/dot.gdbinit_300MHz_32MB b/arch/m32r/m32700ut/dot.gdbinit_300MHz_32MB
new file mode 100644 (file)
index 0000000..4df06e1
--- /dev/null
@@ -0,0 +1,249 @@
+# .gdbinit file
+# $Id: dot.gdbinit_300MHz_32MB,v 1.1 2004/08/17 02:58:11 takata Exp $
+#-----
+# NOTE: this file is generated by a script, "gen_gdbinit.pl".
+# (Please type "gen_gdbinit.pl --help" and check the help message).
+# $ Id: gen_gdbinit.pl,v 1.12 2004/07/26 09:56:10 takata Exp $
+#-----
+# target platform: m32700ut
+
+# setting
+set width 0d70
+set radix 0d16
+
+debug_chaos
+
+# clk xin:cpu:bif:bus=25:300:75:75
+define clock_init
+  set *(unsigned long *)0x00ef4008 = 0x00000000
+  set *(unsigned long *)0x00ef4004 = 0
+  shell sleep 0.1
+  # NOTE: Please change the master clock source from PLL-clock to Xin-clock
+  # and switch off PLL, before resetting the clock gear ratio.
+
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 5
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x00000200
+end
+
+# Initialize SDRAM controller
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # Ch0-MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  # Ch0-TR
+  set *(unsigned long *)0x00ef6028 = 0x00051502
+  # Ch0-ADR (size:16MB)
+  set *(unsigned long *)0x00ef6020 = 0x08000002
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010e24
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  SDRAM controller initialization
+  0x08000000 - 0x08ffffff (16MB)
+end
+
+# Initialize BSEL3 for UT-CFC
+define cfc_init
+  set $sfrbase = 0xa0ef0000
+# too fast
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x0b0b8000
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x00102204
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x1f1f8000
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x1f1f1fdf
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x0013220f
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x0013330f
+end
+document cfc_init
+  CF controller initialization
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb 0d32
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb 0d32
+end
+
+# Initialize TLB entries
+define init_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set *(unsigned long *)($addr + 0x4) = 0
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define tlb_init
+  set $itlb=0xfe000000
+  init_tlb_entries $itlb 0d32
+  set $dtlb=0xfe000800
+  init_tlb_entries $dtlb 0d32
+end
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set  = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+end
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+  clock_init
+  shell sleep 0.1
+  # SDRAM: 16MB
+  set *(unsigned long *)0x00ef6020 = 0x08000002
+  cfc_init
+  # USB
+  set *(unsigned short *)0xb0301000 = 0x100
+
+  set $evb=0x08000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x08002000
+  # INITRD_START
+  set *(unsigned long *)($param + 0x0010) = 0x082a0000
+  # INITRD_SIZE
+  set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d300000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d75000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x console=tty1 video=s1d13xxxfb:mode:240x320-16 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs,rsize=1024,wsize=1024 nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 mem=16M \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $fp = 0
+  set $pc = 0x08001000
+  set *(unsigned char *)0xffffffff = 0x03
+  si
+  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x08000030
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  set $pc = 0
+  b *0x04001000
+  b *0x08001000
+  b *0x08002000
+  si
+  c
+  tlb_init
+  del
+  setup
+  load_modules
+  boot
+end
+
+define si
+  stepi
+  x/i $pc
+  show_reg
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+set $pc = 0
+b *0x04001000
+b *0x08001000
+b *0x08002000
+c
+tlb_init
+del
+setup
+load_modules
+boot
+
diff --git a/arch/m32r/mappi/defconfig.nommu b/arch/m32r/mappi/defconfig.nommu
new file mode 100644 (file)
index 0000000..cae54bf
--- /dev/null
@@ -0,0 +1,529 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+# CONFIG_IKCONFIG_PROC is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+CONFIG_PLAT_MAPPI=y
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+# CONFIG_MMU is not set
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=50000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x00000000
+CONFIG_MEMORY_SIZE=0x00E00000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+# CONFIG_M32RPCC is not set
+CONFIG_M32R_NE2000=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_NETDEVICES is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 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
+
+#
+# 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_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_PLDSIO is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/m32r/mappi/defconfig.smp b/arch/m32r/mappi/defconfig.smp
new file mode 100644 (file)
index 0000000..b0fe571
--- /dev/null
@@ -0,0 +1,646 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=15
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+CONFIG_PLAT_MAPPI=y
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=10000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_NOHIGHMEM=y
+CONFIG_DISCONTIGMEM=y
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00080000
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+CONFIG_SMP=y
+CONFIG_CHIP_M32700_TS1=y
+CONFIG_NR_CPUS=2
+# CONFIG_NUMA is not set
+
+#
+# M32R drivers
+#
+CONFIG_M32RPCC=y
+CONFIG_M32R_NE2000=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE 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_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
+
+#
+# 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_BLKMTD 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
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_NETDEVICES is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 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
+
+#
+# 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_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_PLDSIO is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# 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 is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/m32r/mappi/defconfig.up b/arch/m32r/mappi/defconfig.up
new file mode 100644 (file)
index 0000000..b4ab5ff
--- /dev/null
@@ -0,0 +1,642 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+CONFIG_PLAT_MAPPI=y
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=10000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_NOHIGHMEM=y
+CONFIG_DISCONTIGMEM=y
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00080000
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+CONFIG_M32RPCC=y
+CONFIG_M32R_NE2000=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE 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_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
+
+#
+# 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_BLKMTD 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
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_NETDEVICES is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 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
+
+#
+# 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_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_PLDSIO is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# 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 is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND 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=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/m32r/mappi/dot.gdbinit b/arch/m32r/mappi/dot.gdbinit
new file mode 100644 (file)
index 0000000..ea566b6
--- /dev/null
@@ -0,0 +1,242 @@
+# .gdbinit file
+# $Id$
+#-----
+# NOTE: this file is generated by a script, "gen_gdbinit.pl".
+# (Please type "gen_gdbinit.pl --help" and check the help message).
+# $ Id: gen_gdbinit.pl,v 1.8 2004/02/27 07:08:32 takata Exp $
+#-----
+# target platform: mappi
+
+# setting
+set width 0d70
+set radix 0d16
+debug_chaos
+
+# clk xin:cpu:bif:bus=30:360:180:90
+define clock_init
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 1
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 5
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x00000200
+end
+
+# Initialize programmable ports
+define port_init
+  set $sfrbase = 0x00ef0000
+  set *(unsigned short *)0x00ef1060 = 0x5555
+  set *(unsigned short *)0x00ef1062 = 0x5555
+  set *(unsigned short *)0x00ef1064 = 0x5555
+  set *(unsigned short *)0x00ef1066 = 0x5555
+  set *(unsigned short *)0x00ef1068 = 0x5555
+  set *(unsigned short *)0x00ef106a = 0x0000
+  set *(unsigned short *)0x00ef106e = 0x5555
+  set *(unsigned short *)0x00ef1070 = 0x5555
+  # LED ON
+  set *(unsigned char *)($sfrbase + 0x1015) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1085) = 0xff
+  shell sleep 0.1
+  # LED OFF
+  set *(unsigned char *)($sfrbase + 0x1085) = 0x00
+end
+document port_init
+  P5=LED(output), P6.b4=LAN_RESET(output)
+end
+
+# Initialize SDRAM controller
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # Ch0-MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  # Ch0-TR
+  set *(unsigned long *)0x00ef6028 = 0x00051502
+  # Ch0-ADR (size:64MB)
+  set *(unsigned long *)0x00ef6020 = 0x08000004
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010e2b
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  SDRAM controller initialization
+  0x08000000 - 0x0bffffff (64MB)
+end
+
+# Initialize LAN controller
+define lanc_init
+  set $sfrbase = 0x00ef0000
+  # Set BSEL3 (BSEL3 for the Chaos's bselc)
+  set *(unsigned long *)($sfrbase + 0x5300) = 0x0a0a8040
+  set *(unsigned long *)($sfrbase + 0x5304) = 0x01120203
+  set *(unsigned long *)($sfrbase + 0x5308) = 0x00000001
+  # Reset (P5=LED,P6.b4=LAN_RESET)
+  set *(unsigned short *)($sfrbase + 0x106c) = 0x0000
+  set *(unsigned char *)($sfrbase + 0x1016) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1086) = 0xff
+  shell sleep 0.1
+  # swivel: 0=normal, 4=reverse
+#  set *(unsigned char *)($sfrbase + 0x1086) = 0x00
+  set *(unsigned char *)($sfrbase + 0x1086) = 0x04
+  set *(unsigned long *)(0x0c000330) = 0xffffffff
+  # Set mac address
+  set $lanc = (void*)0x0c000300
+  set *(unsigned long *)($lanc + 0x0000) = 0x00610010
+  set *(unsigned long *)($lanc + 0x0004) = 0x00200030
+  set *(unsigned long *)($lanc + 0x0008) = 0x00400050
+  set *(unsigned long *)($lanc + 0x000c) = 0x00600007
+end
+document lanc_init
+  LAN controller initialization
+  ex.) MAC address:  10 20 30 40 50 60
+end
+
+# LCD & CRT dual-head setting (8bpp)
+define dispc_init
+  set $sfrbase = 0x00ef0000
+  # BSEL4 Dispc
+  set *(unsigned long *)($sfrbase + 0x5400) = 0x0e0e8000
+  set *(unsigned long *)($sfrbase + 0x5404) = 0x0012220a
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb 0d32
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb 0d32
+end
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set  = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+end
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+  clock_init
+  shell sleep 0.1
+  port_init
+  sdram_init
+  lanc_init
+  dispc_init
+  set $evb=0x08000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x08002000
+  # INITRD_START
+  set *(unsigned long *)($param + 0x0010) = 0x082a0000
+  # INITRD_SIZE
+  set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d360000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d90000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.x nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $fp = 0
+  set $pc=0x08001000
+  si
+  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x08000030
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  setup
+  load_modules
+  boot
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+setup
+#load_module
+#set_breakpoints
+#boot
+
diff --git a/arch/m32r/mappi/dot.gdbinit.nommu b/arch/m32r/mappi/dot.gdbinit.nommu
new file mode 100644 (file)
index 0000000..1ca03f8
--- /dev/null
@@ -0,0 +1,245 @@
+# .gdbinit file
+# $Id$
+#-----
+# NOTE: this file is generated by a script, "gen_gdbinit.pl".
+# (Please type "gen_gdbinit.pl --help" and check the help message).
+# $ Id: gen_gdbinit.pl,v 1.5 2004/01/23 08:23:25 takata Exp $
+#-----
+# target platform: mappi
+
+# setting
+set width 0d70
+set radix 0d16
+debug_chaos
+
+# clk xin:cpu:bif:bus=25:200:50:50
+define clock_init
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 3
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x00000200
+end
+
+# Initialize programmable ports
+define port_init
+  set $sfrbase = 0x00ef0000
+  set *(unsigned short *)0x00ef1060 = 0x5555
+  set *(unsigned short *)0x00ef1062 = 0x5555
+  set *(unsigned short *)0x00ef1064 = 0x5555
+  set *(unsigned short *)0x00ef1066 = 0x5555
+  set *(unsigned short *)0x00ef1068 = 0x5555
+  set *(unsigned short *)0x00ef106a = 0x0000
+  set *(unsigned short *)0x00ef106e = 0x5555
+  set *(unsigned short *)0x00ef1070 = 0x5555
+  # LED ON
+  set *(unsigned char *)($sfrbase + 0x1015) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1085) = 0xff
+  shell sleep 0.1
+  # LED OFF
+  set *(unsigned char *)($sfrbase + 0x1085) = 0x00
+end
+document port_init
+  P5=LED(output), P6.b4=LAN_RESET(output)
+end
+
+# Initialize SDRAM controller
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # Ch0-MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  # Ch0-TR
+  set *(unsigned long *)0x00ef6028 = 0x00051502
+  # Ch0-ADR (size:64MB)
+  set *(unsigned long *)0x00ef6020 = 0x00000004
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010f05
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  SDRAM controller initialization
+  0x08000000 - 0x0bffffff (64MB)
+end
+
+# Initialize LAN controller
+define lanc_init
+  set $sfrbase = 0x00ef0000
+  # Set BSEL3 (BSEL3 for the Chaos's bselc)
+  set *(unsigned long *)($sfrbase + 0x5300) = 0x07078040
+  set *(unsigned long *)($sfrbase + 0x5304) = 0x01110102
+  set *(unsigned long *)($sfrbase + 0x5308) = 0x00000001
+  # Reset (P5=LED,P6.b4=LAN_RESET)
+  set *(unsigned short *)($sfrbase + 0x106c) = 0x0000
+  set *(unsigned char *)($sfrbase + 0x1016) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1086) = 0xff
+  shell sleep 0.1
+  # swivel: 0=normal, 4=reverse
+#  set *(unsigned char *)($sfrbase + 0x1086) = 0x00
+  set *(unsigned char *)($sfrbase + 0x1086) = 0x04
+  set *(unsigned long *)(0x0c000330) = 0xffffffff
+  # Set mac address
+  set $lanc = (void*)0x0c000300
+  set *(unsigned long *)($lanc + 0x0000) = 0x00610010
+  set *(unsigned long *)($lanc + 0x0004) = 0x00200030
+  set *(unsigned long *)($lanc + 0x0008) = 0x00400050
+  set *(unsigned long *)($lanc + 0x000c) = 0x00600007
+end
+document lanc_init
+  LAN controller initialization
+  ex.) MAC address:  10 20 30 40 50 60
+end
+
+# LCD & CRT dual-head setting (8bpp)
+define dispc_init
+  set $sfrbase = 0x00ef0000
+  # BSEL4 Dispc
+  set *(unsigned long *)($sfrbase + 0x5400) = 0x06078000
+  set *(unsigned long *)($sfrbase + 0x5404) = 0x00101101
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb 0d32
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb 0d32
+end
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set  = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+end
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+  clock_init
+  shell sleep 0.1
+  port_init
+  sdram_init
+  lanc_init
+  dispc_init
+  set $evb=0x00000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x00002000
+  # INITRD_START
+  #set *(unsigned long *)($param + 0x0010) = 0x082a0000
+  # INITRD_SIZE
+  #set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d200000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d50000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.bbox-httpd nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $fp = 0
+  set $pc=0x00001000
+  set *(long *)0xfffffff4=0x8080
+#  b load_flat_binary
+#  set *(unsigned char *)0x08001003=0x63
+#  set *(unsigned char *)0x08001003=0x02
+  si
+#  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x08000030
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  setup
+  load_modules
+  boot
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+setup
+load_modules
+boot
+
diff --git a/arch/m32r/mappi/dot.gdbinit.smp b/arch/m32r/mappi/dot.gdbinit.smp
new file mode 100644 (file)
index 0000000..db0274f
--- /dev/null
@@ -0,0 +1,344 @@
+# .gdbinit file
+# $Id$
+
+# setting
+set width 0d70
+set radix 0d16
+debug_chaos
+
+# clk xin:cpu:bif:bus=1:4:2:1
+define clock_init_on
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 1
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x1
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+#  set *(unsigned long *)0x00ef4008 = 0x0201
+end
+
+# clk xin:cpu:bif:bus=1:4:1:1
+define clock_init_on_1411
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x1
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+# clk xin:cpu:bif:bus=1:4:2:1
+define clock_init_on_1421
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 1
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x1
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+# clk xin:cpu:bif:bus=1:8:2:1
+define clock_init_on_1821
+  set *(unsigned long *)0x00ef4024 = 3
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x3
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+# clk xin:cpu:bif:bus=1:8:4:1
+define clock_init_on_1841
+  set *(unsigned long *)0x00ef4024 = 3
+  set *(unsigned long *)0x00ef4020 = 1
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x3
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+# clk xin:cpu:bif:bus=1:16:8:1
+define clock_init_on_11681
+  set *(unsigned long *)0x00ef4024 = 4
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x7
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+# clk xin:cpu:bif:bus=1:1:1:1
+define clock_init_off
+  # CPU
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  # BIF
+  set *(unsigned long *)0x00ef4020 = 0
+  # BUS
+  set *(unsigned long *)0x00ef4024 = 0
+  # PLL
+  set *(unsigned long *)0x00ef4008 = 0x0000
+end
+
+# Initialize programmable ports
+define port_init
+  set $sfrbase = 0x00ef0000
+  set *(unsigned short *)0x00ef1060 = 0x5555
+  set *(unsigned short *)0x00ef1062 = 0x5555
+  set *(unsigned short *)0x00ef1064 = 0x5555
+  set *(unsigned short *)0x00ef1066 = 0x5555
+  set *(unsigned short *)0x00ef1068 = 0x5555
+  set *(unsigned short *)0x00ef106a = 0x0000
+  set *(unsigned short *)0x00ef106e = 0x5555
+  set *(unsigned short *)0x00ef1070 = 0x5555
+  # LED ON
+  set *(unsigned char *)($sfrbase + 0x1015) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1085) = 0xff
+  shell sleep 0.1
+  # LED OFF
+  set *(unsigned char *)($sfrbase + 0x1085) = 0x00
+end
+document port_init
+  P5=LED(output), P6.b4=LAN_RESET(output)
+end
+
+# Initialize SDRAM controller for Mappi
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # Ch0-MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  # Ch0-TR
+  set *(unsigned long *)0x00ef6028 = 0x00010002
+  # Ch0-ADR
+  set *(unsigned long *)0x00ef6020 = 0x08000004
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010107
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  Mappi SDRAM controller initialization
+  0x08000000 - 0x0bffffff (64MB)
+end
+
+# Initialize LAN controller for Mappi
+define lanc_init
+  set $sfrbase = 0x00ef0000
+  # Set BSEL3 (BSEL3 for the Chaos's bselc)
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x01018040
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x01011101
+  set *(unsigned long *)($sfrbase + 0x5300) = 0x04048000
+  set *(unsigned long *)($sfrbase + 0x5304) = 0x01011103
+  set *(unsigned long *)($sfrbase + 0x5308) = 0x00000001
+  # Reset (P5=LED,P6.b4=LAN_RESET)
+  set *(unsigned short *)($sfrbase + 0x106c) = 0x0000
+  set *(unsigned char *)($sfrbase + 0x1016) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1086) = 0xff
+  shell sleep 0.1
+#  set *(unsigned char *)($sfrbase + 0x1086) = 0x00
+  set *(unsigned char *)($sfrbase + 0x1086) = 0x04
+  set *(unsigned long *)(0x0c000330) = 0xffffffff
+  # Set mac address
+  set $lanc = (void*)0x0c000300
+  set *(unsigned long *)($lanc + 0x0000) = 0x00610010
+  set *(unsigned long *)($lanc + 0x0004) = 0x00200030
+  set *(unsigned long *)($lanc + 0x0008) = 0x00400050
+  set *(unsigned long *)($lanc + 0x000c) = 0x00600007
+end
+document lanc_init
+  Mappi LAN controller initialization
+  ex.) MAC address:  10 20 30 40 50 60
+end
+
+# LCD & CRT dual-head setting (8bpp)
+define dispc_init
+  set $sfrbase = 0x00ef0000
+  # BSEL4 Dispc
+  # 20MHz
+#  set *(unsigned long *)($sfrbase + 0x5400) = 0x02028282
+#  set *(unsigned long *)($sfrbase + 0x5404) = 0x00122202
+  # 40MHz
+  set *(unsigned long *)($sfrbase + 0x5400) = 0x04048000
+  set *(unsigned long *)($sfrbase + 0x5404) = 0x00101103
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  use_mon_code
+  while ($i < 0d32 )
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb
+end
+
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set $task = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$fp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+end
+
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+#  clock_init_on_1411
+  clock_init_on_1421
+#  clock_init_on_1821
+#  clock_init_on_1841
+#  clock_init_on_11681
+#  clock_init_off
+  shell sleep 0.1
+  port_init
+  sdram_init
+  lanc_init
+  dispc_init
+  set $evb=0x08000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+#  load ramdisk_082a0000.mot
+#  load romfs_082a0000.mot
+#  use_mon_code
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x08002000
+  # INITRD_START
+# set *(unsigned long *)($param + 0x0010) = 0x082a0000
+  # INITRD_SIZE
+  set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d160000000
+#  set *(unsigned long *)($param + 0x0018) = 0d80000000
+#  set *(unsigned long *)($param + 0x0018) = 0d40000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d40000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=tty1 console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.x nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+#  set {char[0x200]}($param + 0x100) = "console=tty1 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.x nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $pc=0x08001000
+  set *(unsigned char *)0x08001003=0x03
+  si
+  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x08000030
+end
+
+## Boot MP
+define boot_mp
+  set_kernel_parameters
+  set *(unsigned long *)0x00f00000 = boot - 0x80000000
+  set *(unsigned long *)0x00eff2f8 = 0x2
+  x 0x00eff2f8
+
+  set $pc=0x08001000
+  si
+  c
+end
+document boot_mp
+  Boot BSP
+end
+
+## Boot UP
+define boot_up
+  set_kernel_parameters
+  set $pc=0x08001000
+  si
+  c
+end
+document boot_up
+  Boot BSP
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  setup
+  load_modules
+  boot_mp
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+setup
diff --git a/arch/m32r/mm/Makefile b/arch/m32r/mm/Makefile
new file mode 100644 (file)
index 0000000..c51c1c3
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Makefile for the Linux M32R-specific parts of the memory manager.
+#
+
+ifdef CONFIG_MMU
+obj-y  := init.o fault.o mmu.o extable.o ioremap.o cache.o page.o
+else
+obj-y  := init.o fault-nommu.o mmu.o extable.o ioremap-nommu.o cache.o page.o
+endif
+
+obj-$(CONFIG_DISCONTIGMEM)     += discontig.o
+
diff --git a/arch/m32r/mm/cache.c b/arch/m32r/mm/cache.c
new file mode 100644 (file)
index 0000000..e2dd92d
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  linux/arch/m32r/mm/cache.c
+ *
+ *  Copyright (C) 2002  Hirokazu Takata
+ */
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <asm/pgtable.h>
+
+#undef MCCR
+
+#if defined(CONFIG_CHIP_XNUX2) || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_OPSP)
+/* Cache Control Register */
+#define MCCR           ((volatile unsigned long*)0xfffffffc)
+#define MCCR_CC                (1UL << 7)      /* Cache mode modify bit */
+#define MCCR_IIV       (1UL << 6)      /* I-cache invalidate */
+#define MCCR_DIV       (1UL << 5)      /* D-cache invalidate */
+#define MCCR_DCB       (1UL << 4)      /* D-cache copy back */
+#define MCCR_ICM       (1UL << 1)      /* I-cache mode [0:off,1:on] */
+#define MCCR_DCM       (1UL << 0)      /* D-cache mode [0:off,1:on] */
+#define MCCR_ICACHE_INV                (MCCR_CC|MCCR_IIV)
+#define MCCR_DCACHE_CB         (MCCR_CC|MCCR_DCB)
+#define MCCR_DCACHE_CBINV      (MCCR_CC|MCCR_DIV|MCCR_DCB)
+#define CHECK_MCCR(mccr)       (mccr = *MCCR)
+#elif defined(CONFIG_CHIP_M32102)
+#define MCCR           ((volatile unsigned long*)0xfffffffc)
+#define MCCR_IIV       (1UL << 8)      /* I-cache invalidate */
+#define MCCR_ICACHE_INV                MCCR_IIV
+#endif /* CONFIG_CHIP_XNUX2 || CONFIG_CHIP_M32700 */
+
+#ifndef MCCR
+#error Unknown cache type.
+#endif
+
+
+/* Copy back and invalidate D-cache and invalidate I-cache all */
+void _flush_cache_all(void)
+{
+#if defined(CONFIG_CHIP_M32102)
+       *MCCR = MCCR_ICACHE_INV;
+#else
+       unsigned long mccr;
+
+       /* Copyback and invalidate D-cache */
+       /* Invalidate I-cache */
+       *MCCR = MCCR_ICACHE_INV | MCCR_DCACHE_CBINV;
+       while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */
+#endif
+}
+
+/* Copy back D-cache and invalidate I-cache all */
+void _flush_cache_copyback_all(void)
+{
+#if defined(CONFIG_CHIP_M32102)
+       *MCCR = MCCR_ICACHE_INV;
+#else
+       unsigned long mccr;
+
+       /* Copyback D-cache */
+       /* Invalidate I-cache */
+       *MCCR = MCCR_ICACHE_INV | MCCR_DCACHE_CB;
+       while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */
+
+#endif
+}
+
diff --git a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c
new file mode 100644 (file)
index 0000000..3e49ff6
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ *  linux/arch/m32r/mm/discontig.c
+ *
+ *  Discontig memory support
+ *
+ *  Copyright (c) 2003  Hitoshi Yamamoto
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/mmzone.h>
+#include <linux/initrd.h>
+
+#include <asm/setup.h>
+
+extern char _end[];
+
+struct pglist_data *node_data[MAX_NUMNODES];
+static bootmem_data_t node_bdata[MAX_NUMNODES] __initdata;
+
+pg_data_t m32r_node_data[MAX_NUMNODES];
+
+/* Memory profile */
+typedef struct {
+       unsigned long start_pfn;
+       unsigned long pages;
+       unsigned long holes;
+       unsigned long free_pfn;
+} mem_prof_t;
+static mem_prof_t mem_prof[MAX_NUMNODES];
+
+static void __init mem_prof_init(void)
+{
+       unsigned long start_pfn, holes, free_pfn;
+       const unsigned long zone_alignment = 1UL << (MAX_ORDER - 1);
+       unsigned long ul;
+       mem_prof_t *mp;
+
+       /* Node#0 SDRAM */
+       mp = &mem_prof[0];
+       mp->start_pfn = PFN_UP(CONFIG_MEMORY_START);
+       mp->pages = PFN_DOWN(CONFIG_MEMORY_SIZE);
+       mp->holes = 0;
+       mp->free_pfn = PFN_UP(__pa(_end));
+
+       /* Node#1 internal SRAM */
+       mp = &mem_prof[1];
+       start_pfn = free_pfn = PFN_UP(CONFIG_IRAM_START);
+       holes = 0;
+       if (start_pfn & (zone_alignment - 1)) {
+               ul = zone_alignment;
+               while (start_pfn >= ul)
+                       ul += zone_alignment;
+
+               start_pfn = ul - zone_alignment;
+               holes = free_pfn - start_pfn;
+       }
+
+       mp->start_pfn = start_pfn;
+       mp->pages = PFN_DOWN(CONFIG_IRAM_SIZE) + holes;
+       mp->holes = holes;
+       mp->free_pfn = PFN_UP(CONFIG_IRAM_START);
+}
+
+unsigned long __init setup_memory(void)
+{
+       unsigned long bootmap_size;
+       unsigned long min_pfn;
+       int nid;
+       mem_prof_t *mp;
+
+       max_low_pfn = 0;
+       min_low_pfn = -1;
+
+       mem_prof_init();
+
+       for (nid = 0 ; nid < numnodes ; nid++) {
+               mp = &mem_prof[nid];
+               NODE_DATA(nid)=(pg_data_t *)&m32r_node_data[nid];
+               NODE_DATA(nid)->bdata = &node_bdata[nid];
+               min_pfn = mp->start_pfn;
+               max_pfn = mp->start_pfn + mp->pages;
+               bootmap_size = init_bootmem_node(NODE_DATA(nid), mp->free_pfn,
+                       mp->start_pfn, max_pfn);
+
+               free_bootmem_node(NODE_DATA(nid), PFN_PHYS(mp->start_pfn),
+                       PFN_PHYS(mp->pages));
+
+               reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(mp->start_pfn),
+                       PFN_PHYS(mp->free_pfn - mp->start_pfn) + bootmap_size);
+
+               if (max_low_pfn < max_pfn)
+                       max_low_pfn = max_pfn;
+
+               if (min_low_pfn > min_pfn)
+                       min_low_pfn = min_pfn;
+       }
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (LOADER_TYPE && INITRD_START) {
+               if (INITRD_START + INITRD_SIZE <= PFN_PHYS(max_low_pfn)) {
+                       reserve_bootmem_node(NODE_DATA(0), INITRD_START,
+                               INITRD_SIZE);
+                       initrd_start = INITRD_START ?
+                               INITRD_START + PAGE_OFFSET : 0;
+
+                       initrd_end = initrd_start + INITRD_SIZE;
+                       printk("initrd:start[%08lx],size[%08lx]\n",
+                               initrd_start, INITRD_SIZE);
+               } else {
+                       printk("initrd extends beyond end of memory "
+                               "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+                               INITRD_START + INITRD_SIZE,
+                               PFN_PHYS(max_low_pfn));
+
+                       initrd_start = 0;
+               }
+       }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+       return max_low_pfn;
+}
+
+#define START_PFN(nid) \
+       (NODE_DATA(nid)->bdata->node_boot_start >> PAGE_SHIFT)
+#define MAX_LOW_PFN(nid)       (NODE_DATA(nid)->bdata->node_low_pfn)
+
+unsigned long __init zone_sizes_init(void)
+{
+       unsigned long zones_size[MAX_NR_ZONES], zholes_size[MAX_NR_ZONES];
+       unsigned long low, start_pfn;
+       unsigned long holes = 0;
+       int nid, i;
+       mem_prof_t *mp;
+
+       pgdat_list = NULL;
+       for (nid = numnodes - 1 ; nid >= 0 ; nid--) {
+               NODE_DATA(nid)->pgdat_next = pgdat_list;
+               pgdat_list = NODE_DATA(nid);
+       }
+
+       for (nid = 0 ; nid < numnodes ; nid++) {
+               mp = &mem_prof[nid];
+               for (i = 0 ; i < MAX_NR_ZONES ; i++) {
+                       zones_size[i] = 0;
+                       zholes_size[i] = 0;
+               }
+               start_pfn = START_PFN(nid);
+               low = MAX_LOW_PFN(nid);
+               zones_size[ZONE_DMA] = low - start_pfn;
+               zholes_size[ZONE_DMA] = mp->holes;
+               holes += zholes_size[ZONE_DMA];
+
+               free_area_init_node(nid, NODE_DATA(nid), zones_size,
+                       start_pfn, zholes_size);
+       }
+
+       /*
+        * For test
+        *  Use all area of internal RAM.
+        *  see __alloc_pages()
+        */
+       NODE_DATA(1)->node_zones->pages_min = 0;
+       NODE_DATA(1)->node_zones->pages_low = 0;
+       NODE_DATA(1)->node_zones->pages_high = 0;
+
+       return holes;
+}
+
diff --git a/arch/m32r/mm/extable.c b/arch/m32r/mm/extable.c
new file mode 100644 (file)
index 0000000..9a97363
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * linux/arch/i386/mm/extable.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+       const struct exception_table_entry *fixup;
+
+       fixup = search_exception_tables(regs->bpc);
+       if (fixup) {
+               regs->bpc = fixup->fixup;
+               return 1;
+       }
+
+       return 0;
+}
+
diff --git a/arch/m32r/mm/fault-nommu.c b/arch/m32r/mm/fault-nommu.c
new file mode 100644 (file)
index 0000000..da267d8
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ *  linux/arch/m32r/mm/fault.c
+ *
+ *  Copyright (c) 2001, 2002  Hitoshi Yamamoto, and H. Kondo
+ *
+ *  Some code taken from i386 version.
+ *    Copyright (C) 1995  Linus Torvalds
+ */
+
+/* $Id: fault-nommu.c,v 1.1 2004/03/30 06:40:59 sakugawa Exp $ */
+
+#include <linux/config.h>
+#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/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+
+#include <asm/m32r.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+
+extern void die(const char *, struct pt_regs *, long);
+
+#ifndef CONFIG_SMP
+asmlinkage unsigned int tlb_entry_i_dat;
+asmlinkage unsigned int tlb_entry_d_dat;
+#define tlb_entry_i tlb_entry_i_dat
+#define tlb_entry_d tlb_entry_d_dat
+#else
+unsigned int tlb_entry_i_dat[NR_CPUS];
+unsigned int tlb_entry_d_dat[NR_CPUS];
+#define tlb_entry_i tlb_entry_i_dat[smp_processor_id()]
+#define tlb_entry_d tlb_entry_d_dat[smp_processor_id()]
+#endif
+
+/*
+ * Unlock any spinlocks which will prevent us from getting the
+ * message out
+ */
+void bust_spinlocks(int yes)
+{
+       int loglevel_save = console_loglevel;
+
+       if (yes) {
+               oops_in_progress = 1;
+               return;
+       }
+#ifdef CONFIG_VT
+       unblank_screen();
+#endif
+       oops_in_progress = 0;
+       /*
+        * OK, the message is on the console.  Now we call printk()
+        * without oops_in_progress set so that printk will give klogd
+        * a poke.  Hold onto your hats...
+        */
+       console_loglevel = 15;          /* NMI oopser may have shut the console up */
+       printk(" ");
+       console_loglevel = loglevel_save;
+}
+
+void do_BUG(const char *file, int line)
+{
+       bust_spinlocks(1);
+       printk("kernel BUG at %s:%d!\n", file, line);
+}
+
+/*======================================================================*
+ * do_page_fault()
+ *======================================================================*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * ARGUMENT:
+ *  regs       : M32R SP reg.
+ *  error_code : See below
+ *  address    : M32R MMU MDEVA reg. (Operand ACE)
+ *             : M32R BPC reg. (Instruction ACE)
+ *
+ * error_code :
+ *  bit 0 == 0 means no page found, 1 means protection fault
+ *  bit 1 == 0 means read, 1 means write
+ *  bit 2 == 0 means kernel, 1 means user-mode
+ *======================================================================*/
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
+  unsigned long address)
+{
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+
+       bust_spinlocks(1);
+
+       if (address < PAGE_SIZE)
+               printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+       else
+               printk(KERN_ALERT "Unable to handle kernel paging request");
+       printk(" at virtual address %08lx\n",address);
+       printk(" printing bpc:\n");
+       printk(KERN_ALERT "bpc = %08lx\n", regs->bpc);
+
+       die("Oops", regs, error_code);
+       bust_spinlocks(0);
+       do_exit(SIGKILL);
+}
+
+/*======================================================================*
+ * update_mmu_cache()
+ *======================================================================*/
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
+       pte_t pte)
+{
+       BUG();
+}
+
+/*======================================================================*
+ * flush_tlb_page() : flushes one page
+ *======================================================================*/
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+       BUG();
+}
+
+/*======================================================================*
+ * flush_tlb_range() : flushes a range of pages
+ *======================================================================*/
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+       unsigned long end)
+{
+       BUG();
+}
+
+/*======================================================================*
+ * flush_tlb_mm() : flushes the specified mm context TLB's
+ *======================================================================*/
+void local_flush_tlb_mm(struct mm_struct *mm)
+{
+       BUG();
+}
+
+/*======================================================================*
+ * flush_tlb_all() : flushes all processes TLBs
+ *======================================================================*/
+void local_flush_tlb_all(void)
+{
+       BUG();
+}
+
diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c
new file mode 100644 (file)
index 0000000..393ff03
--- /dev/null
@@ -0,0 +1,572 @@
+/*
+ *  linux/arch/m32r/mm/fault.c
+ *
+ *  Copyright (c) 2001, 2002  Hitoshi Yamamoto, and H. Kondo
+ *
+ *  Some code taken from i386 version.
+ *    Copyright (C) 1995  Linus Torvalds
+ */
+
+/* $Id$ */
+
+#include <linux/config.h>
+#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/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/vt_kern.h>             /* For unblank_screen() */
+#include <linux/highmem.h>
+#include <linux/module.h>
+
+#include <asm/m32r.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+
+extern void die(const char *, struct pt_regs *, long);
+
+#ifndef CONFIG_SMP
+asmlinkage unsigned int tlb_entry_i_dat;
+asmlinkage unsigned int tlb_entry_d_dat;
+#define tlb_entry_i tlb_entry_i_dat
+#define tlb_entry_d tlb_entry_d_dat
+#else
+unsigned int tlb_entry_i_dat[NR_CPUS];
+unsigned int tlb_entry_d_dat[NR_CPUS];
+#define tlb_entry_i tlb_entry_i_dat[smp_processor_id()]
+#define tlb_entry_d tlb_entry_d_dat[smp_processor_id()]
+#endif
+
+extern void init_tlb(void);
+
+/*
+ * Unlock any spinlocks which will prevent us from getting the
+ * message out
+ */
+void bust_spinlocks(int yes)
+{
+       int loglevel_save = console_loglevel;
+
+       if (yes) {
+               oops_in_progress = 1;
+               return;
+       }
+#ifdef CONFIG_VT
+       unblank_screen();
+#endif
+       oops_in_progress = 0;
+       /*
+        * OK, the message is on the console.  Now we call printk()
+        * without oops_in_progress set so that printk will give klogd
+        * a poke.  Hold onto your hats...
+        */
+       console_loglevel = 15;          /* NMI oopser may have shut the console up */
+       printk(" ");
+       console_loglevel = loglevel_save;
+}
+
+/*======================================================================*
+ * do_page_fault()
+ *======================================================================*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * ARGUMENT:
+ *  regs       : M32R SP reg.
+ *  error_code : See below
+ *  address    : M32R MMU MDEVA reg. (Operand ACE)
+ *             : M32R BPC reg. (Instruction ACE)
+ *
+ * error_code :
+ *  bit 0 == 0 means no page found, 1 means protection fault
+ *  bit 1 == 0 means read, 1 means write
+ *  bit 2 == 0 means kernel, 1 means user-mode
+ *  bit 3 == 0 means data, 1 means instruction
+ *======================================================================*/
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
+  unsigned long address)
+{
+       struct task_struct *tsk;
+       struct mm_struct *mm;
+       struct vm_area_struct * vma;
+       unsigned long page, addr;
+       int write;
+       siginfo_t info;
+
+       /*
+        * If BPSW IE bit enable --> set PSW IE bit
+        */
+       if (regs->psw & M32R_PSW_BIE)
+               local_irq_enable();
+
+       tsk = current;
+
+       info.si_code = SEGV_MAPERR;
+
+       /*
+        * We fault-in kernel-space virtual memory on-demand. The
+        * 'reference' page table is init_mm.pgd.
+        *
+        * NOTE! We MUST NOT take any locks for this case. We may
+        * be in an interrupt or a critical region, and should
+        * only copy the information from the master page table,
+        * nothing more.
+        *
+        * This verifies that the fault happens in kernel space
+        * (error_code & 4) == 0, and that the fault was not a
+        * protection error (error_code & 1) == 0.
+        */
+       if (address >= TASK_SIZE && !(error_code & 4))
+               goto vmalloc_fault;
+
+       mm = tsk->mm;
+
+       /*
+        * If we're in an interrupt or have no user context or are running in an
+        * atomic region then we must not take the fault..
+        */
+       if (in_atomic() || !mm)
+               goto bad_area_nosemaphore;
+
+       /* When running in the kernel we expect faults to occur only to
+        * addresses in user space.  All other faults represent errors in the
+        * kernel and should generate an OOPS.  Unfortunatly, in the case of an
+        * erroneous fault occuring in a code path which already holds mmap_sem
+        * we will deadlock attempting to validate the fault against the
+        * address space.  Luckily the kernel only validly references user
+        * space from well defined areas of code, which are listed in the
+        * exceptions table.
+        *
+        * As the vast majority of faults will be valid we will only perform
+        * the source reference check when there is a possibilty of a deadlock.
+        * Attempt to lock the address space, if we cannot we then validate the
+        * source.  If this is invalid we can skip the address space check,
+        * thus avoiding the deadlock.
+        */
+       if (!down_read_trylock(&mm->mmap_sem)) {
+               if ((error_code & 4) == 0 &&
+                   !search_exception_tables(regs->psw))
+                       goto bad_area_nosemaphore;
+               down_read(&mm->mmap_sem);
+       }
+
+       vma = find_vma(mm, address);
+       if (!vma)
+               goto bad_area;
+       if (vma->vm_start <= address)
+               goto good_area;
+       if (!(vma->vm_flags & VM_GROWSDOWN))
+               goto bad_area;
+#if 0
+       if (error_code & 4) {
+               /*
+                * accessing the stack below "spu" is always a bug.
+                * The "+ 4" is there due to the push instruction
+                * doing pre-decrement on the stack and that
+                * doesn't show up until later..
+                */
+               if (address + 4 < regs->spu)
+                       goto bad_area;
+       }
+#endif
+       if (expand_stack(vma, address))
+               goto bad_area;
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+       info.si_code = SEGV_ACCERR;
+       write = 0;
+       switch (error_code & 3) {
+               default:        /* 3: write, present */
+                       /* fall through */
+               case 2:         /* write, not present */
+                       if (!(vma->vm_flags & VM_WRITE))
+                               goto bad_area;
+                       write++;
+                       break;
+               case 1:         /* read, present */
+               case 0:         /* read, not present */
+                       if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+                               goto bad_area;
+       }
+
+survive:
+       /*
+        * If for any reason at all we couldn't handle the fault,
+        * make sure we exit gracefully rather than endlessly redo
+        * the fault.
+        */
+       addr = (address & PAGE_MASK) | (error_code & 8);
+       switch (handle_mm_fault(mm, vma, addr, write)) {
+               case VM_FAULT_MINOR:
+                       tsk->min_flt++;
+                       break;
+               case VM_FAULT_MAJOR:
+                       tsk->maj_flt++;
+                       break;
+               case VM_FAULT_SIGBUS:
+                       goto do_sigbus;
+               case VM_FAULT_OOM:
+                       goto out_of_memory;
+               default:
+                       BUG();
+       }
+
+       up_read(&mm->mmap_sem);
+       return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+       up_read(&mm->mmap_sem);
+
+bad_area_nosemaphore:
+       /* User mode accesses just cause a SIGSEGV */
+       if (error_code & 4) {
+               tsk->thread.address = address;
+               tsk->thread.error_code = error_code | (address >= TASK_SIZE);
+               tsk->thread.trap_no = 14;
+               info.si_signo = SIGSEGV;
+               info.si_errno = 0;
+               /* info.si_code has been set above */
+               info.si_addr = (void __user *)address;
+               force_sig_info(SIGSEGV, &info, tsk);
+               return;
+       }
+
+no_context:
+       /* Are we prepared to handle this kernel fault?  */
+       if (fixup_exception(regs))
+               return;
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+
+       bust_spinlocks(1);
+
+       if (address < PAGE_SIZE)
+               printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+       else
+               printk(KERN_ALERT "Unable to handle kernel paging request");
+       printk(" at virtual address %08lx\n",address);
+       printk(KERN_ALERT " printing bpc:\n");
+       printk("%08lx\n", regs->bpc);
+       page = *(unsigned long *)MPTB;
+       page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
+       printk(KERN_ALERT "*pde = %08lx\n", page);
+       if (page & _PAGE_PRESENT) {
+               page &= PAGE_MASK;
+               address &= 0x003ff000;
+               page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
+               printk(KERN_ALERT "*pte = %08lx\n", page);
+       }
+       die("Oops", regs, error_code);
+       bust_spinlocks(0);
+       do_exit(SIGKILL);
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+       up_read(&mm->mmap_sem);
+       if (tsk->pid == 1) {
+               yield();
+               down_read(&mm->mmap_sem);
+               goto survive;
+       }
+       printk("VM: killing process %s\n", tsk->comm);
+       if (error_code & 4)
+               do_exit(SIGKILL);
+       goto no_context;
+
+do_sigbus:
+       up_read(&mm->mmap_sem);
+
+       /* Kernel mode? Handle exception or die */
+       if (!(error_code & 4))
+               goto no_context;
+
+       tsk->thread.address = address;
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = 14;
+       info.si_signo = SIGBUS;
+       info.si_errno = 0;
+       info.si_code = BUS_ADRERR;
+       info.si_addr = (void __user *)address;
+       force_sig_info(SIGBUS, &info, tsk);
+       return;
+
+vmalloc_fault:
+       {
+               /*
+                * Synchronize this task's top level page-table
+                * with the 'reference' page table.
+                *
+                * Do _not_ use "tsk" here. We might be inside
+                * an interrupt in the middle of a task switch..
+                */
+               int offset = pgd_index(address);
+               pgd_t *pgd, *pgd_k;
+               pmd_t *pmd, *pmd_k;
+               pte_t *pte_k;
+
+               pgd = (pgd_t *)*(unsigned long *)MPTB;
+               pgd = offset + (pgd_t *)pgd;
+               pgd_k = init_mm.pgd + offset;
+
+               if (!pgd_present(*pgd_k))
+                       goto no_context;
+
+               /*
+                * set_pgd(pgd, *pgd_k); here would be useless on PAE
+                * and redundant with the set_pmd() on non-PAE.
+                */
+
+               pmd = pmd_offset(pgd, address);
+               pmd_k = pmd_offset(pgd_k, address);
+               if (!pmd_present(*pmd_k))
+                       goto no_context;
+               set_pmd(pmd, *pmd_k);
+
+               pte_k = pte_offset_kernel(pmd_k, address);
+               if (!pte_present(*pte_k))
+                       goto no_context;
+
+               addr = (address & PAGE_MASK) | (error_code & 8);
+               update_mmu_cache(NULL, addr, *pte_k);
+               return;
+       }
+}
+
+/*======================================================================*
+ * update_mmu_cache()
+ *======================================================================*/
+#define TLB_MASK       (NR_TLB_ENTRIES - 1)
+#define ITLB_END       (unsigned long *)(ITLB_BASE + (NR_TLB_ENTRIES * 8))
+#define DTLB_END       (unsigned long *)(DTLB_BASE + (NR_TLB_ENTRIES * 8))
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr,
+       pte_t pte)
+{
+       unsigned long *entry1, *entry2;
+       unsigned long pte_data, flags;
+       unsigned int *entry_dat;
+       int inst = vaddr & 8;
+       int i;
+
+       /* Ptrace may call this routine. */
+       if (vma && current->active_mm != vma->vm_mm)
+               return;
+
+       local_irq_save(flags);
+
+       vaddr = (vaddr & PAGE_MASK) | get_asid();
+
+#ifdef CONFIG_CHIP_OPSP
+       entry1 = (unsigned long *)ITLB_BASE;
+       for(i = 0 ; i < NR_TLB_ENTRIES; i++) {
+               if(*entry1++ == vaddr) {
+                       pte_data = pte_val(pte);
+                       set_tlb_data(entry1, pte_data);
+                       break;
+               }
+               entry1++;
+       }
+       entry2 = (unsigned long *)DTLB_BASE;
+       for(i = 0 ; i < NR_TLB_ENTRIES ; i++) {
+               if(*entry2++ == vaddr) {
+                       pte_data = pte_val(pte);
+                       set_tlb_data(entry2, pte_data);
+                       break;
+               }
+               entry2++;
+       }
+       local_irq_restore(flags);
+       return;
+#else
+       pte_data = pte_val(pte);
+
+       /*
+        * Update TLB entries
+        *  entry1: ITLB entry address
+        *  entry2: DTLB entry address
+        */
+       __asm__ __volatile__ (
+               "seth   %0, #high(%4)   \n\t"
+               "st     %2, @(%5, %0)   \n\t"
+               "ldi    %1, #1          \n\t"
+               "st     %1, @(%6, %0)   \n\t"
+               "add3   r4, %0, %7      \n\t"
+               ".fillinsn              \n"
+               "1:                     \n\t"
+               "ld     %1, @(%6, %0)   \n\t"
+               "bnez   %1, 1b          \n\t"
+               "ld     %0, @r4+        \n\t"
+               "ld     %1, @r4         \n\t"
+               "st     %3, @+%0        \n\t"
+               "st     %3, @+%1        \n\t"
+               : "=&r" (entry1), "=&r" (entry2)
+               : "r" (vaddr), "r" (pte_data), "i" (MMU_REG_BASE),
+               "i" (MSVA_offset), "i" (MTOP_offset), "i" (MIDXI_offset)
+               : "r4", "memory"
+       );
+
+       if ((!inst && entry2 >= DTLB_END) || (inst && entry1 >= ITLB_END))
+               goto notfound;
+
+found:
+       local_irq_restore(flags);
+
+       return;
+
+       /* Valid entry not found */
+notfound:
+       /*
+        * Update ITLB or DTLB entry
+        *  entry1: TLB entry address
+        *  entry2: TLB base address
+        */
+       if (!inst) {
+               entry2 = (unsigned long *)DTLB_BASE;
+               entry_dat = &tlb_entry_d;
+       } else {
+               entry2 = (unsigned long *)ITLB_BASE;
+               entry_dat = &tlb_entry_i;
+       }
+       entry1 = entry2 + (((*entry_dat - 1) & TLB_MASK) << 1);
+
+       for (i = 0 ; i < NR_TLB_ENTRIES ; i++) {
+               if (!(entry1[1] & 2))   /* Valid bit check */
+                       break;
+
+               if (entry1 != entry2)
+                       entry1 -= 2;
+               else
+                       entry1 += TLB_MASK << 1;
+       }
+
+       if (i >= NR_TLB_ENTRIES) {      /* Empty entry not found */
+               entry1 = entry2 + (*entry_dat << 1);
+               *entry_dat = (*entry_dat + 1) & TLB_MASK;
+       }
+       *entry1++ = vaddr;      /* Set TLB tag */
+       set_tlb_data(entry1, pte_data);
+
+       goto found;
+#endif
+}
+
+/*======================================================================*
+ * flush_tlb_page() : flushes one page
+ *======================================================================*/
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+       if (vma->vm_mm && mm_context(vma->vm_mm) != NO_CONTEXT) {
+               unsigned long flags;
+
+               local_irq_save(flags);
+               page &= PAGE_MASK;
+               page |= (mm_context(vma->vm_mm) & MMU_CONTEXT_ASID_MASK);
+               __flush_tlb_page(page);
+               local_irq_restore(flags);
+       }
+}
+
+/*======================================================================*
+ * flush_tlb_range() : flushes a range of pages
+ *======================================================================*/
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+       unsigned long end)
+{
+       struct mm_struct *mm;
+
+       mm = vma->vm_mm;
+       if (mm_context(mm) != NO_CONTEXT) {
+               unsigned long flags;
+               int size;
+
+               local_irq_save(flags);
+               size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+               if (size > (NR_TLB_ENTRIES / 4)) { /* Too many TLB to flush */
+                       mm_context(mm) = NO_CONTEXT;
+                       if (mm == current->mm)
+                               activate_context(mm);
+               } else {
+                       unsigned long asid;
+
+                       asid = mm_context(mm) & MMU_CONTEXT_ASID_MASK;
+                       start &= PAGE_MASK;
+                       end += (PAGE_SIZE - 1);
+                       end &= PAGE_MASK;
+
+                       start |= asid;
+                       end   |= asid;
+                       while (start < end) {
+                               __flush_tlb_page(start);
+                               start += PAGE_SIZE;
+                       }
+               }
+               local_irq_restore(flags);
+       }
+}
+
+/*======================================================================*
+ * flush_tlb_mm() : flushes the specified mm context TLB's
+ *======================================================================*/
+void local_flush_tlb_mm(struct mm_struct *mm)
+{
+       /* Invalidate all TLB of this process. */
+       /* Instead of invalidating each TLB, we get new MMU context. */
+       if (mm_context(mm) != NO_CONTEXT) {
+               unsigned long flags;
+
+               local_irq_save(flags);
+               mm_context(mm) = NO_CONTEXT;
+               if (mm == current->mm)
+                       activate_context(mm);
+               local_irq_restore(flags);
+       }
+}
+
+/*======================================================================*
+ * flush_tlb_all() : flushes all processes TLBs
+ *======================================================================*/
+void local_flush_tlb_all(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __flush_tlb_all();
+       local_irq_restore(flags);
+}
+
+/*======================================================================*
+ * init_mmu()
+ *======================================================================*/
+void __init init_mmu(void)
+{
+       tlb_entry_i = 0;
+       tlb_entry_d = 0;
+       mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
+       set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);
+       *(volatile unsigned long *)MPTB = (unsigned long)swapper_pg_dir;
+}
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
new file mode 100644 (file)
index 0000000..a290e37
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ *  linux/arch/m32r/mm/init.c
+ *
+ *  Copyright (c) 2001, 2002  Hitoshi Yamamoto
+ *
+ *  Some code taken from sh version.
+ *    Copyright (C) 1999  Niibe Yutaka
+ *    Based on linux/arch/i386/mm/init.c:
+ *      Copyright (C) 1995  Linus Torvalds
+ */
+
+/* $Id$ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
+#include <linux/swap.h>
+#include <linux/highmem.h>
+#include <asm/types.h>
+#include <asm/processor.h>
+#include <asm/bitops.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/setup.h>
+#include <asm/tlb.h>
+
+/* References to section boundaries */
+extern char _text, _etext, _edata;
+extern char __init_begin, __init_end;
+
+pgd_t swapper_pg_dir[1024];
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+void show_mem(void)
+{
+       int total = 0, reserved = 0;
+       int shared = 0, cached = 0;
+       int highmem = 0;
+       struct page *page;
+       pg_data_t *pgdat;
+       unsigned long i;
+
+       printk("Mem-info:\n");
+       show_free_areas();
+       printk("Free swap:       %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+       for_each_pgdat(pgdat) {
+               for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+                       page = pgdat->node_mem_map + i;
+                       total++;
+                       if (PageHighMem(page))
+                               highmem++;
+                       if (PageReserved(page))
+                               reserved++;
+                       else if (PageSwapCache(page))
+                               cached++;
+                       else if (page_count(page))
+                               shared += page_count(page) - 1;
+               }
+       }
+       printk("%d pages of RAM\n", total);
+       printk("%d pages of HIGHMEM\n",highmem);
+       printk("%d reserved pages\n",reserved);
+       printk("%d pages shared\n",shared);
+       printk("%d pages swap cached\n",cached);
+}
+
+/*
+ * Cache of MMU context last used.
+ */
+#ifndef CONFIG_SMP
+unsigned long mmu_context_cache_dat;
+#else
+unsigned long mmu_context_cache_dat[NR_CPUS];
+#endif
+static unsigned long hole_pages;
+
+/*
+ * function prototype
+ */
+void __init paging_init(void);
+void __init mem_init(void);
+void free_initmem(void);
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long, unsigned long);
+#endif
+
+/* It'd be good if these lines were in the standard header file. */
+#define START_PFN(nid) \
+       (NODE_DATA(nid)->bdata->node_boot_start >> PAGE_SHIFT)
+#define MAX_LOW_PFN(nid)       (NODE_DATA(nid)->bdata->node_low_pfn)
+
+#ifndef CONFIG_DISCONTIGMEM
+unsigned long __init zone_sizes_init(void)
+{
+       unsigned long  zones_size[MAX_NR_ZONES] = {0, 0, 0};
+       unsigned long  max_dma;
+       unsigned long  low;
+       unsigned long  start_pfn;
+
+#ifdef CONFIG_MMU
+       start_pfn = START_PFN(0);
+       max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+       low = MAX_LOW_PFN(0);
+
+       if (low < max_dma){
+               zones_size[ZONE_DMA] = low - start_pfn;
+               zones_size[ZONE_NORMAL] = 0;
+       } else {
+               zones_size[ZONE_DMA] = low - start_pfn;
+               zones_size[ZONE_NORMAL] = low - max_dma;
+       }
+#else
+       zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT;
+       zones_size[ZONE_NORMAL] = __MEMORY_SIZE >> PAGE_SHIFT;
+       start_pfn = __MEMORY_START >> PAGE_SHIFT;
+#endif /* CONFIG_MMU */
+
+       free_area_init_node(0, NODE_DATA(0), zones_size, start_pfn, 0);
+
+       mem_map = contig_page_data.node_mem_map;
+
+       return 0;
+}
+#else  /* CONFIG_DISCONTIGMEM */
+extern unsigned long zone_sizes_init(void);
+#endif /* CONFIG_DISCONTIGMEM */
+
+/*======================================================================*
+ * paging_init() : sets up the page tables
+ *======================================================================*/
+void __init paging_init(void)
+{
+#ifdef CONFIG_MMU
+       int  i;
+       pgd_t *pg_dir;
+
+       /* We don't need kernel mapping as hardware support that. */
+       pg_dir = swapper_pg_dir;
+
+       for (i = 0 ; i < USER_PTRS_PER_PGD * 2 ; i++)
+               pgd_val(pg_dir[i]) = 0;
+#endif /* CONFIG_MMU */
+       hole_pages = zone_sizes_init();
+}
+
+int __init reservedpages_count(void)
+{
+       int reservedpages, nid, i;
+
+       reservedpages = 0;
+       for (nid = 0 ; nid < numnodes ; nid++)
+               for (i = 0 ; i < MAX_LOW_PFN(nid) - START_PFN(nid) ; i++)
+                       if (PageReserved(NODE_DATA(nid)->node_mem_map + i))
+                               reservedpages++;
+
+       return reservedpages;
+}
+
+/*======================================================================*
+ * mem_init() :
+ * orig : arch/sh/mm/init.c
+ *======================================================================*/
+void __init mem_init(void)
+{
+       int codesize, reservedpages, datasize, initsize;
+       int nid;
+#ifndef CONFIG_MMU
+       extern unsigned long memory_end;
+#endif
+
+       num_physpages = 0;
+       for (nid = 0 ; nid < numnodes ; nid++)
+               num_physpages += MAX_LOW_PFN(nid) - START_PFN(nid) + 1;
+
+       num_physpages -= hole_pages;
+
+#ifndef CONFIG_DISCONTIGMEM
+       max_mapnr = num_physpages;
+#endif /* CONFIG_DISCONTIGMEM */
+
+#ifdef CONFIG_MMU
+       high_memory = (void *)__va(PFN_PHYS(MAX_LOW_PFN(0)));
+#else
+       high_memory = (void *)(memory_end & PAGE_MASK);
+#endif /* CONFIG_MMU */
+
+       /* clear the zero-page */
+       memset(empty_zero_page, 0, PAGE_SIZE);
+
+       /* this will put all low memory onto the freelists */
+       for (nid = 0 ; nid < numnodes ; nid++)
+               totalram_pages += free_all_bootmem_node(NODE_DATA(nid));
+
+       reservedpages = reservedpages_count() - hole_pages;
+       codesize = (unsigned long) &_etext - (unsigned long)&_text;
+       datasize = (unsigned long) &_edata - (unsigned long)&_etext;
+       initsize = (unsigned long) &__init_end - (unsigned long)&__init_begin;
+
+       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),
+               num_physpages << (PAGE_SHIFT-10),
+               codesize >> 10,
+               reservedpages << (PAGE_SHIFT-10),
+               datasize >> 10,
+               initsize >> 10);
+}
+
+/*======================================================================*
+ * free_initmem() :
+ * orig : arch/sh/mm/init.c
+ *======================================================================*/
+void free_initmem(void)
+{
+       unsigned long addr;
+
+       addr = (unsigned long)(&__init_begin);
+       for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+               ClearPageReserved(virt_to_page(addr));
+               set_page_count(virt_to_page(addr), 1);
+               free_page(addr);
+               totalram_pages++;
+       }
+       printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", \
+         (int)(&__init_end - &__init_begin) >> 10);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+/*======================================================================*
+ * free_initrd_mem() :
+ * orig : arch/sh/mm/init.c
+ *======================================================================*/
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+       unsigned long p;
+       for (p = start; p < end; p += PAGE_SIZE) {
+               ClearPageReserved(virt_to_page(p));
+               set_page_count(virt_to_page(p), 1);
+               free_page(p);
+               totalram_pages++;
+       }
+       printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+}
+#endif
+
diff --git a/arch/m32r/mm/ioremap-nommu.c b/arch/m32r/mm/ioremap-nommu.c
new file mode 100644 (file)
index 0000000..2759f2d
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  linux/arch/m32r/mm/ioremap-nommu.c
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo
+ *
+ *  Taken from mips version.
+ *    (C) Copyright 1995 1996 Linus Torvalds
+ *    (C) Copyright 2001 Ralf Baechle
+ */
+
+/*
+ * 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 <asm/addrspace.h>
+#include <asm/byteorder.h>
+
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+
+#define IS_LOW512(addr) (!((unsigned long)(addr) & ~0x1fffffffUL))
+
+void __iomem *
+__ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+       return (void *)phys_addr;
+}
+
+#define IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == KSEG1)
+
+void iounmap(volatile void __iomem *addr)
+{
+}
+
diff --git a/arch/m32r/mm/ioremap.c b/arch/m32r/mm/ioremap.c
new file mode 100644 (file)
index 0000000..70c5905
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ *  linux/arch/m32r/mm/ioremap.c
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo
+ *
+ *  Taken from mips version.
+ *    (C) Copyright 1995 1996 Linus Torvalds
+ *    (C) Copyright 2001 Ralf Baechle
+ */
+
+/*
+ * 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 <asm/addrspace.h>
+#include <asm/byteorder.h>
+
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+static inline void
+remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+              unsigned long phys_addr, unsigned long flags)
+{
+       unsigned long end;
+       unsigned long pfn;
+       pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_READ
+                                  | _PAGE_WRITE | flags);
+
+       address &= ~PMD_MASK;
+       end = address + size;
+       if (end > PMD_SIZE)
+               end = PMD_SIZE;
+       if (address >= end)
+               BUG();
+       pfn = phys_addr >> PAGE_SHIFT;
+       do {
+               if (!pte_none(*pte)) {
+                       printk("remap_area_pte: page already exists\n");
+                       BUG();
+               }
+               set_pte(pte, pfn_pte(pfn, pgprot));
+               address += PAGE_SIZE;
+               pfn++;
+               pte++;
+       } while (address && (address < end));
+}
+
+static inline int
+remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
+              unsigned long phys_addr, unsigned long flags)
+{
+       unsigned long end;
+
+       address &= ~PGDIR_MASK;
+       end = address + size;
+       if (end > PGDIR_SIZE)
+               end = PGDIR_SIZE;
+       phys_addr -= address;
+       if (address >= end)
+               BUG();
+       do {
+               pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+               if (!pte)
+                       return -ENOMEM;
+               remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+               address = (address + PMD_SIZE) & PMD_MASK;
+               pmd++;
+       } while (address && (address < end));
+       return 0;
+}
+
+static int
+remap_area_pages(unsigned long address, unsigned long phys_addr,
+                unsigned long size, unsigned long flags)
+{
+       int error;
+       pgd_t * dir;
+       unsigned long end = address + size;
+
+       phys_addr -= address;
+       dir = pgd_offset(&init_mm, address);
+       flush_cache_all();
+       if (address >= end)
+               BUG();
+       spin_lock(&init_mm.page_table_lock);
+       do {
+               pmd_t *pmd;
+               pmd = pmd_alloc(&init_mm, dir, address);
+               error = -ENOMEM;
+               if (!pmd)
+                       break;
+               if (remap_area_pmd(pmd, address, end - address,
+                                        phys_addr + address, flags))
+                       break;
+               error = 0;
+               address = (address + PGDIR_SIZE) & PGDIR_MASK;
+               dir++;
+       } while (address && (address < end));
+       spin_unlock(&init_mm.page_table_lock);
+       flush_tlb_all();
+       return error;
+}
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+
+#define IS_LOW512(addr) (!((unsigned long)(addr) & ~0x1fffffffUL))
+
+void __iomem *
+__ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+       void __iomem * addr;
+       struct vm_struct * area;
+       unsigned long offset, last_addr;
+
+       /* Don't allow wraparound or zero size */
+       last_addr = phys_addr + size - 1;
+       if (!size || last_addr < phys_addr)
+               return NULL;
+
+       /*
+        * Map objects in the low 512mb of address space using KSEG1, otherwise
+        * map using page tables.
+        */
+       if (IS_LOW512(phys_addr) && IS_LOW512(phys_addr + size - 1))
+               return (void *) KSEG1ADDR(phys_addr);
+
+       /*
+        * Don't allow anybody to remap normal RAM that we're using..
+        */
+       if (phys_addr < virt_to_phys(high_memory)) {
+               char *t_addr, *t_end;
+               struct page *page;
+
+               t_addr = __va(phys_addr);
+               t_end = t_addr + (size - 1);
+
+               for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
+                       if(!PageReserved(page))
+                               return NULL;
+       }
+
+       /*
+        * Mappings have to be page-aligned
+        */
+       offset = phys_addr & ~PAGE_MASK;
+       phys_addr &= PAGE_MASK;
+       size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+       /*
+        * 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 (remap_area_pages((unsigned long)addr, phys_addr, size, flags)) {
+               vunmap((void __force *) addr);
+               return NULL;
+       }
+
+       return (void __iomem *) (offset + (char __iomem *)addr);
+}
+
+#define IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == KSEG1)
+
+void iounmap(volatile void __iomem *addr)
+{
+       if (!IS_KSEG1(addr))
+               vfree((void *) (PAGE_MASK & (unsigned long) addr));
+}
+
diff --git a/arch/m32r/mm/mmu.S b/arch/m32r/mm/mmu.S
new file mode 100644 (file)
index 0000000..0c28f11
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ *  linux/arch/m32r/mm/mmu.S
+ *
+ *  Copyright (C) 2001 by Hiroyuki Kondo
+ */
+
+/* $Id: mmu.S,v 1.15 2004/03/16 02:56:27 takata Exp $ */
+
+#include <linux/config.h>      /* CONFIG_MMU */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/smp.h>
+
+       .text
+#ifdef CONFIG_MMU
+
+#include <asm/mmu_context.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/m32r.h>
+
+/*
+ * TLB Miss Exception handler
+ */
+       .balign 16
+ENTRY(tme_handler)
+       .global tlb_entry_i_dat
+       .global tlb_entry_d_dat
+
+       SWITCH_TO_KERNEL_STACK
+
+#if defined(CONFIG_ISA_M32R2)
+       st      r0, @-sp
+       st      r1, @-sp
+       st      r2, @-sp
+       st      r3, @-sp
+
+       seth    r3, #high(MMU_REG_BASE)
+       ld      r1, @(MESTS_offset, r3) ; r1: status     (MESTS reg.)
+       ld      r0, @(MDEVP_offset, r3) ; r0: PFN + ASID (MDEVP reg.)
+       st      r1, @(MESTS_offset, r3) ; clear status   (MESTS reg.)
+       and3    r1, r1, #(MESTS_IT)
+       bnez    r1, 1f                  ; instruction TLB miss?
+
+;; data TLB miss
+;;  input
+;;   r0: PFN + ASID (MDEVP reg.)
+;;   r1 - r3: free
+;;  output
+;;   r0: PFN + ASID
+;;   r1: TLB entry base address
+;;   r2: &tlb_entry_{i|d}_dat
+;;   r3: free
+
+#ifndef CONFIG_SMP
+       seth    r2, #high(tlb_entry_d_dat)
+       or3     r2, r2, #low(tlb_entry_d_dat)
+#else  /* CONFIG_SMP */
+       ldi     r1, #-8192
+       seth    r2, #high(tlb_entry_d_dat)
+       or3     r2, r2, #low(tlb_entry_d_dat)
+       and     r1, sp
+       ld      r1, @(16, r1)           ; current_thread_info->cpu
+       slli    r1, #2
+       add     r2, r1
+#endif /* !CONFIG_SMP */
+       seth    r1, #high(DTLB_BASE)
+       or3     r1, r1, #low(DTLB_BASE)
+       bra     2f
+
+       .balign 16
+       .fillinsn
+1:
+;; instrucntion TLB miss
+;;  input
+;;   r0: MDEVP reg. (included ASID)
+;;   r1 - r3: free
+;;  output
+;;   r0: PFN + ASID
+;;   r1: TLB entry base address
+;;   r2: &tlb_entry_{i|d}_dat
+;;   r3: free
+       ldi     r3, #-4096
+       and3    r0, r0, #(MMU_CONTEXT_ASID_MASK)
+       mvfc    r1, bpc
+       and     r1, r3
+       or      r0, r1                  ; r0: PFN + ASID
+#ifndef CONFIG_SMP
+       seth    r2, #high(tlb_entry_i_dat)
+       or3     r2, r2, #low(tlb_entry_i_dat)
+#else  /* CONFIG_SMP */
+       ldi     r1, #-8192
+       seth    r2, #high(tlb_entry_i_dat)
+       or3     r2, r2, #low(tlb_entry_i_dat)
+       and     r1, sp
+       ld      r1, @(16, r1)           ; current_thread_info->cpu
+       slli    r1, #2
+       add     r2, r1
+#endif /* !CONFIG_SMP */
+       seth    r1, #high(ITLB_BASE)
+       or3     r1, r1, #low(ITLB_BASE)
+
+       .fillinsn
+2:
+;; select TLB entry
+;;  input
+;;   r0: PFN + ASID
+;;   r1: TLB entry base address
+;;   r2: &tlb_entry_{i|d}_dat
+;;   r3: free
+;;  output
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2, r3: free
+#ifdef CONFIG_ISA_DUAL_ISSUE
+       ld      r3, @r2         ||      srli    r1, #3
+#else
+       ld      r3, @r2
+       srli    r1, #3
+#endif
+       add     r1, r3
+       ; tlb_entry_{d|i}_dat++;
+       addi    r3, #1
+       and3    r3, r3, #(NR_TLB_ENTRIES - 1)
+#ifdef CONFIG_ISA_DUAL_ISSUE
+       st      r3, @r2         ||      slli    r1, #3
+#else
+       st      r3, @r2
+       slli    r1, #3
+#endif
+
+;; load pte
+;;  input
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2, r3: free
+;;  output
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2: pte_data
+;;   r3: free
+       ; pgd = *(unsigned long *)MPTB;
+       ld24    r2, #(-MPTB - 1)
+       srl3    r3, r0, #22
+#ifdef CONFIG_ISA_DUAL_ISSUE
+       not     r2, r2              ||  slli    r3, #2  ; r3: pgd offset
+#else
+       not     r2, r2
+       slli    r3, #2
+#endif
+       ld      r2, @r2                 ; r2: pgd base addr (MPTB reg.)
+       or      r3, r2                  ; r3: pmd addr
+
+       ; pmd = pmd_offset(pgd, address);
+       ld      r3, @r3                 ; r3: pmd data
+       ldi     r2, #-4096
+       beqz    r3, 3f                  ; pmd_none(*pmd) ?
+
+       ; pte = pte_offset(pmd, address);
+       and     r2, r3                  ; r2: pte base addr
+       srl3    r3, r0, #10
+       and3    r3, r3, #0xffc          ; r3: pte offset
+       or      r3, r2
+       seth    r2, #0x8000
+       or      r3, r2                  ; r3: pte addr
+
+       ; pte_data = (unsigned long)pte_val(*pte);
+       ld      r2, @r3                 ; r2: pte data
+       or3     r2, r2, #2              ; _PAGE_PRESENT(=2)
+
+       .fillinsn
+5:
+;; set tlb
+;;  input
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2: pte_data
+;;   r3: free
+       st      r0, @r1                 ; set_tlb_tag(entry++, address);
+       st      r2, @+r1                ; set_tlb_data(entry, pte_data);
+
+       .fillinsn
+6:
+       ld      r3, @sp+
+       ld      r2, @sp+
+       ld      r1, @sp+
+       ld      r0, @sp+
+       rte
+
+       .fillinsn
+3:
+;; error
+;;  input
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2, r3: free
+;;  output
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2: pte_data
+;;   r3: free
+#ifdef CONFIG_ISA_DUAL_ISSUE
+       bra     5b                  ||  ldi     r2, #2
+#else
+       ldi     r2, #2          ; r2: pte_data = 0 | _PAGE_PRESENT(=2)
+       bra     5b
+#endif
+
+#elif defined (CONFIG_ISA_M32R)
+
+       st      sp, @-sp
+       st      r0, @-sp
+       st      r1, @-sp
+       st      r2, @-sp
+       st      r3, @-sp
+       st      r4, @-sp
+
+       seth    r3, #high(MMU_REG_BASE)
+       ld      r0, @(MDEVA_offset,r3)  ; r0: address  (MDEVA reg.)
+       mvfc    r2, bpc                 ; r2: bpc
+       ld      r1, @(MESTS_offset,r3)  ; r1: status   (MESTS reg.)
+       st      r1, @(MESTS_offset,r3)  ; clear status (MESTS reg.)
+       and3    r1, r1, #(MESTS_IT)
+       beqz    r1, 1f                  ; data TLB miss?
+
+;; instrucntion TLB miss
+       mv      r0, r2                  ; address = bpc;
+       ; entry = (unsigned long *)ITLB_BASE+tlb_entry_i*2;
+       seth    r3, #shigh(tlb_entry_i_dat)
+       ld      r4, @(low(tlb_entry_i_dat),r3)
+       sll3    r2, r4, #3
+       seth    r1, #high(ITLB_BASE)
+       or3     r1, r1, #low(ITLB_BASE)
+       add     r2, r1                  ; r2: entry
+       addi    r4, #1                  ; tlb_entry_i++;
+       and3    r4, r4, #(NR_TLB_ENTRIES-1)
+       st      r4, @(low(tlb_entry_i_dat),r3)
+       bra     2f
+       .fillinsn
+1:
+;; data TLB miss
+       ; entry = (unsigned long *)DTLB_BASE+tlb_entry_d*2;
+       seth    r3, #shigh(tlb_entry_d_dat)
+       ld      r4, @(low(tlb_entry_d_dat),r3)
+       sll3    r2, r4, #3
+       seth    r1, #high(DTLB_BASE)
+       or3     r1, r1, #low(DTLB_BASE)
+       add     r2, r1                  ; r2: entry
+       addi    r4, #1                  ; tlb_entry_d++;
+       and3    r4, r4, #(NR_TLB_ENTRIES-1)
+       st      r4, @(low(tlb_entry_d_dat),r3)
+       .fillinsn
+2:
+;; load pte
+; r0: address, r2: entry
+; r1,r3,r4: (free)
+       ; pgd = *(unsigned long *)MPTB;
+       ld24    r1, #(-MPTB-1)
+       not     r1, r1
+       ld      r1, @r1
+       srl3    r4, r0, #22
+       sll3    r3, r4, #2
+       add     r3, r1                  ; r3: pgd
+       ; pmd = pmd_offset(pgd, address);
+       ld      r1, @r3                 ; r1: pmd
+       beqz    r1, 3f                  ; pmd_none(*pmd) ?
+;
+       and3    r1, r1, #0xeff
+       ldi     r4, #611                ; _KERNPG_TABLE(=611)
+       beq     r1, r4, 4f              ; !pmd_bad(*pmd) ?
+       .fillinsn
+3:
+       ldi     r1, #0                  ; r1: pte_data = 0
+       bra     5f
+       .fillinsn
+4:
+       ; pte = pte_offset(pmd, address);
+       ld      r4, @r3                 ; r4: pte
+       ldi     r3, #-4096
+       and     r4, r3
+       srl3    r3, r0, #10
+       and3    r3, r3, #0xffc
+       add     r4, r3
+       seth    r3, #0x8000
+       add     r4, r3                  ; r4: pte
+       ; pte_data = (unsigned long)pte_val(*pte);
+       ld      r1, @r4                 ; r1: pte_data
+       .fillinsn
+
+;; set tlb
+; r0: address, r1: pte_data, r2: entry
+; r3,r4: (free)
+5:
+       ldi     r3, #-4096              ; set_tlb_tag(entry++, address);
+       and     r3, r0
+       seth    r4, #shigh(MASID)
+       ld      r4, @(low(MASID),r4)    ; r4: MASID
+       and3    r4, r4, #(MMU_CONTEXT_ASID_MASK)
+       or      r3, r4
+       st      r3, @r2
+       or3     r4, r1, #2              ; _PAGE_PRESENT(=2)
+       st      r4, @(4,r2)             ; set_tlb_data(entry, pte_data);
+
+       ld      r4, @sp+
+       ld      r3, @sp+
+       ld      r2, @sp+
+       ld      r1, @sp+
+       ld      r0, @sp+
+       ld      sp, @sp+
+       rte
+
+#else
+#error unknown isa configuration
+#endif
+
+ENTRY(init_tlb)
+;; Set MMU Register
+       seth    r0, #high(MMU_REG_BASE)  ; Set MMU_REG_BASE higher
+       or3     r0, r0, #low(MMU_REG_BASE)  ; Set MMU_REG_BASE lower
+       ldi     r1, #0
+       st      r1, @(MPSZ_offset,r0)   ; Set MPSZ Reg(Page size 4KB:0 16KB:1 64KB:2)
+       ldi     r1, #0
+       st      r1, @(MASID_offset,r0)  ; Set ASID Zero
+
+;; Set TLB
+       seth    r0, #high(ITLB_BASE)    ; Set ITLB_BASE higher
+       or3     r0, r0, #low(ITLB_BASE) ; Set ITLB_BASE lower
+       seth    r1, #high(DTLB_BASE)    ; Set DTLB_BASE higher
+       or3     r1, r1, #low(DTLB_BASE) ; Set DTLB_BASE lower
+       ldi     r2, #0
+       ldi     r3, #NR_TLB_ENTRIES
+       addi    r0, #-4
+       addi    r1, #-4
+clear_tlb:
+       st      r2, @+r0                ; VPA <- 0
+       st      r2, @+r0                ; PPA <- 0
+       st      r2, @+r1                ; VPA <- 0
+       st      r2, @+r1                ; PPA <- 0
+       addi    r3, #-1
+       bnez    r3, clear_tlb
+;;
+       jmp     r14
+
+ENTRY(m32r_itlb_entrys)
+ENTRY(m32r_otlb_entrys)
+
+#endif  /* CONFIG_MMU */
+
+.end
+
diff --git a/arch/m32r/mm/page.S b/arch/m32r/mm/page.S
new file mode 100644 (file)
index 0000000..a2e9367
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ *  linux/arch/m32r/mm/page.S
+ *
+ *  Clear/Copy page with CPU
+ *
+ *  Copyright (C) 2004  The Free Software Initiative of Japan
+ *
+ *  Written by Niibe Yutaka
+ *
+ * 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.
+ *
+ */
+       .text
+       .global copy_page
+       /*
+        * copy_page (to, from)
+        *
+        * PAGE_SIZE = 4096-byte
+        * Cache line = 16-byte
+        * 16 * 256
+        */
+       .align  4
+copy_page:
+       ldi     r2, #255
+       ld      r3, @r0         /* cache line allocate */
+       ld      r4, @r1+
+       ld      r5, @r1+
+       ld      r6, @r1+
+       ld      r7, @r1+
+       .fillinsn
+0:
+       st      r4, @r0
+       st      r5, @+r0
+       st      r6, @+r0
+       st      r7, @+r0
+       ld      r4, @r1+
+       addi    r0, #4
+       ld      r5, @r1+
+       ld      r6, @r1+
+       ld      r7, @r1+
+       ld      r3, @r0         /* cache line allocate */
+       addi    r2, #-1
+       bnez    r2, 0b
+
+       st      r4, @r0
+       st      r5, @+r0
+       st      r6, @+r0
+       st      r7, @+r0
+       jmp     r14
+
+       .text
+       .global clear_page
+       /*
+        * clear_page (to)
+        *
+        * PAGE_SIZE = 4096-byte
+        * Cache line = 16-byte
+        * 16 * 256
+        */
+       .align  4
+clear_page:
+       ldi     r2, #255
+       ldi     r4, #0
+       ld      r3, @r0         /* cache line allocate */
+       .fillinsn
+0:
+       st      r4, @r0
+       st      r4, @+r0
+       st      r4, @+r0
+       st      r4, @+r0
+       addi    r0, #4
+       ld      r3, @r0         /* cache line allocate */
+       addi    r2, #-1
+       bnez    r2, 0b
+
+       st      r4, @r0
+       st      r4, @+r0
+       st      r4, @+r0
+       st      r4, @+r0
+       jmp     r14
diff --git a/arch/m32r/oaks32r/defconfig.nommu b/arch/m32r/oaks32r/defconfig.nommu
new file mode 100644 (file)
index 0000000..816b53e
--- /dev/null
@@ -0,0 +1,521 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+CONFIG_PLAT_OAKS32R=y
+# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_CHIP_M32700 is not set
+CONFIG_CHIP_M32102=y
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_ISA_M32R=y
+CONFIG_BUS_CLOCK=33333333
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x01000000
+CONFIG_MEMORY_SIZE=0x00800000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+CONFIG_M32R_NE2000=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_NETDEVICES is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 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
+
+#
+# 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_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_PLDSIO is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/m32r/oaks32r/dot.gdbinit.nommu b/arch/m32r/oaks32r/dot.gdbinit.nommu
new file mode 100644 (file)
index 0000000..48420f7
--- /dev/null
@@ -0,0 +1,155 @@
+# .gdbinit file
+# $Id: dot.gdbinit.oaks32r,v 1.2 2004/04/15 02:33:14 takata Exp $
+#-----
+# NOTE: this file is generated by a script, "gen_gdbinit.pl".
+# (Please type "gen_gdbinit.pl --help" and check the help message).
+# $ Id: gen_gdbinit.pl,v 1.10 2004/04/15 02:10:45 takata Exp $
+#-----
+# target platform: oaks32r
+
+# setting
+set width 0d70
+set radix 0d16
+
+# clk xin:cpu:bus=16:66:33
+define clock_init
+  set *(unsigned long *)0x00ef4008 = 1
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4000 = 0x00020100
+end
+
+# Initialize programmable ports
+define port_init
+  set *(unsigned long *)0x00ef1000 = 0x1
+  set *(unsigned long *)0x00ef1060 = 0x01400001
+  set *(unsigned long *)0x00ef1064 = 0x00015555
+  set *(unsigned long *)0x00ef1068 = 0x55555050
+  set *(unsigned long *)0x00ef106c = 0x05150040
+end
+
+# Initialize SDRAM controller
+define sdram_init
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef602c = 0x00000010
+  set *(unsigned long *)0x00ef6028 = 0x00000300
+  set *(unsigned long *)0x00ef6048 = 0x00000001
+  set *(unsigned long *)0x00ef6020 = 0x01000041
+  set *(unsigned long *)0x00ef6004 = 0x00010117
+  set *(unsigned long *)0x00ef6010 = 0x00000001
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  SDRAM controller initialization
+  0x01000000 - 0x017fffff (8MB)
+end
+
+# Initialize LAN controller
+define lanc_init
+  set *(unsigned long *)0x00ef5008 = 0x03031303
+  #RST DRV (P64)
+  set *(unsigned char *)0x00ef1046 = 0x08
+  set *(unsigned char *)0x00ef1026 = 0xff
+  set *(unsigned char *)0x00ef1026 = 0x00
+  set *(unsigned short *)0x02000630 = 0xffff
+end
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set  = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+end
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+  clock_init
+  shell sleep 0.1
+  port_init
+  sdram_init
+  lanc_init
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x01002000
+  # INITRD_START
+  set *(unsigned long *)($param + 0x0010) = 0x00000000
+  # INITRD_SIZE
+  set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d66666667
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d33333333
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+#  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.busybox.flat nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $fp = 0
+  set $pc = 0x01001000
+  si
+  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x00000020
+  b *0x00000030
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  setup
+  load_modules
+  boot
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+setup
+#load_modules
+#set_breakpoints
+#boot
+
diff --git a/arch/m32r/oprofile/Kconfig b/arch/m32r/oprofile/Kconfig
new file mode 100644 (file)
index 0000000..19d3773
--- /dev/null
@@ -0,0 +1,23 @@
+
+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.
+
+endmenu
+
diff --git a/arch/m32r/oprofile/Makefile b/arch/m32r/oprofile/Makefile
new file mode 100644 (file)
index 0000000..06e7c81
--- /dev/null
@@ -0,0 +1,9 @@
+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) init.o
diff --git a/arch/m32r/oprofile/init.c b/arch/m32r/oprofile/init.c
new file mode 100644 (file)
index 0000000..f5843c8
--- /dev/null
@@ -0,0 +1,25 @@
+/**
+ * @file init.c
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@movementarian.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/oprofile.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+extern void timer_init(struct oprofile_operations ** ops);
+
+int __init oprofile_arch_init(struct oprofile_operations ** ops)
+{
+       return -ENODEV;
+}
+
+
+void oprofile_arch_exit(void)
+{
+}
diff --git a/arch/m32r/opsput/defconfig.opsput b/arch/m32r/opsput/defconfig.opsput
new file mode 100644 (file)
index 0000000..07eae96
--- /dev/null
@@ -0,0 +1,598 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+# CONFIG_IKCONFIG_PROC is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+CONFIG_PLAT_OPSPUT=y
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_CHIP_M32700 is not set
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+CONFIG_CHIP_OPSP=y
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=50000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+# CONFIG_M32R_CFC is not set
+CONFIG_M32R_SMC91111=y
+CONFIG_M32700UT_DS1302=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD 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_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+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 is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG 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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER 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_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_NETDEVICES is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 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
+
+#
+# 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_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_M32R_SIO is not set
+CONFIG_SERIAL_M32R_PLDSIO=y
+CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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 is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_V4 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_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 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
+
+#
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_IOVIRT is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/m32r/opsput/dot.gdbinit b/arch/m32r/opsput/dot.gdbinit
new file mode 100644 (file)
index 0000000..9883f00
--- /dev/null
@@ -0,0 +1,180 @@
+# .gdbinit file
+# $Id: dot.gdbinit,v 1.1 2004/07/27 06:54:20 sakugawa Exp $
+
+# setting
+set width 0d70
+set radix 0d16
+set height 0
+debug_chaos
+
+define tlb_init
+  set $tlbbase = 0xfe000000
+  set *(unsigned long *)($tlbbase + 0x04) = 0x0
+  set *(unsigned long *)($tlbbase + 0x0c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x14) = 0x0
+  set *(unsigned long *)($tlbbase + 0x1c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x24) = 0x0
+  set *(unsigned long *)($tlbbase + 0x2c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x34) = 0x0
+  set *(unsigned long *)($tlbbase + 0x3c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x44) = 0x0
+  set *(unsigned long *)($tlbbase + 0x4c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x54) = 0x0
+  set *(unsigned long *)($tlbbase + 0x5c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x64) = 0x0
+  set *(unsigned long *)($tlbbase + 0x6c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x74) = 0x0
+  set *(unsigned long *)($tlbbase + 0x7c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x84) = 0x0
+  set *(unsigned long *)($tlbbase + 0x8c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x94) = 0x0
+  set *(unsigned long *)($tlbbase + 0x9c) = 0x0
+  set *(unsigned long *)($tlbbase + 0xa4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xac) = 0x0
+  set *(unsigned long *)($tlbbase + 0xb4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xbc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xc4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xcc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xd4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xdc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xe4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xec) = 0x0
+  set *(unsigned long *)($tlbbase + 0xf4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xfc) = 0x0
+  set $tlbbase = 0xfe000800
+  set *(unsigned long *)($tlbbase + 0x04) = 0x0
+  set *(unsigned long *)($tlbbase + 0x0c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x14) = 0x0
+  set *(unsigned long *)($tlbbase + 0x1c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x24) = 0x0
+  set *(unsigned long *)($tlbbase + 0x2c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x34) = 0x0
+  set *(unsigned long *)($tlbbase + 0x3c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x44) = 0x0
+  set *(unsigned long *)($tlbbase + 0x4c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x54) = 0x0
+  set *(unsigned long *)($tlbbase + 0x5c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x64) = 0x0
+  set *(unsigned long *)($tlbbase + 0x6c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x74) = 0x0
+  set *(unsigned long *)($tlbbase + 0x7c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x84) = 0x0
+  set *(unsigned long *)($tlbbase + 0x8c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x94) = 0x0
+  set *(unsigned long *)($tlbbase + 0x9c) = 0x0
+  set *(unsigned long *)($tlbbase + 0xa4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xac) = 0x0
+  set *(unsigned long *)($tlbbase + 0xb4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xbc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xc4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xcc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xd4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xdc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xe4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xec) = 0x0
+  set *(unsigned long *)($tlbbase + 0xf4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xfc) = 0x0
+end
+
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x88002000
+  # INITRD_START
+#  set *(unsigned long *)($param + 0x0010) = 0x08300000
+  # INITRD_SIZE
+#  set *(unsigned long *)($param + 0x0014) = 0x00400000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d200000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d50000000
+#  set *(unsigned long *)($param + 0x001c) = 0d25000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x\
+  root=/dev/nfsroot \
+  nfsroot=192.168.0.1:/project/m32r-linux/export/root.2.6 \
+  nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \
+  mem=16m \0"
+end
+
+define boot
+  set_kernel_parameters
+  set $pc=0x88001000
+  set $fp=0
+  set $evb=0x88000000
+  # I/D-Cache ON
+
+# IPI
+#  set *(long *)0x00eff2f8 = 0x2
+  set $fp=0
+#  set *(unsigned long *)0xa0ef4000 = 0x100
+  si
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  use_mon_code
+  while ($i < 0d32 )
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+#  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb
+end
+
+define show_regs
+  printf " R0[%08lx]   R1[%08lx]   R2[%08lx]   R3[%08lx]\n",$r0,$r1,$r2,$r3
+  printf " R4[%08lx]   R5[%08lx]   R6[%08lx]   R7[%08lx]\n",$r4,$r5,$r6,$r7
+  printf " R8[%08lx]   R9[%08lx]  R10[%08lx]  R11[%08lx]\n",$r8,$r9,$r10,$r11
+  printf "R12[%08lx]   FP[%08lx]   LR[%08lx]   SP[%08lx]\n",$r12,$fp,$lr,$sp
+  printf "PSW[%08lx]  CBR[%08lx]  SPI[%08lx]  SPU[%08lx]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[%08lx]   PC[%08lx] ACCL[%08lx] ACCH[%08lx]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[%08lx]\n",$evb
+end
+
+define setup
+  debug_chaos
+  set *(unsigned long *)0xa0ef6004 = 0x0001053f
+  set *(unsigned long *)0xa0ef6028 = 0x00031102
+#  set *(unsigned long *)0xa0ef400c = 0x2
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+set $pc=0x0
+b *0x30000
+c
+setup
+tlb_init
+load_modules
+#set *(long *)0xa0ef4000=0x101
+#set *(long *)0xa0ef400c=0x002
+
+boot
+#b tme_handler
+b *0x88000020
+
+
+
+
diff --git a/arch/m68k/Kconfig.debug b/arch/m68k/Kconfig.debug
new file mode 100644 (file)
index 0000000..f53b6d5
--- /dev/null
@@ -0,0 +1,5 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+endmenu
index 081a674..458925c 100644 (file)
@@ -7,7 +7,7 @@ ifndef CONFIG_SUN3
 else
   extra-y := sun3-head.o
 endif
-extra-y        += vmlinux.lds.s
+extra-y        += vmlinux.lds
 
 obj-y          := entry.o process.o traps.o ints.o signal.o ptrace.o \
                        sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o
index b069b0c..fe837e3 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/checksum.h>
-#include <asm/hardirq.h>
 
 asmlinkage long long __ashldi3 (long long, int);
 asmlinkage long long __ashrdi3 (long long, int);
@@ -72,18 +71,18 @@ EXPORT_SYMBOL(vme_brdtype);
    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_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(__muldi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(__muldi3);
 
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
-EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_failed_interruptible);
+EXPORT_SYMBOL(__down_failed_trylock);
+EXPORT_SYMBOL(__up_wakeup);
 
 EXPORT_SYMBOL(get_wchan);
index d85616f..11d1229 100644 (file)
@@ -38,24 +38,6 @@ static inline int set_rtc_mmss(unsigned long nowtime)
   return -1;
 }
 
-static inline void do_profile (unsigned long pc)
-{
-       if (prof_buffer && current->pid) {
-               extern int _stext;
-               pc -= (unsigned long) &_stext;
-               pc >>= prof_shift;
-               if (pc < prof_len)
-                       ++prof_buffer[pc];
-               else
-               /*
-                * Don't ignore out-of-bounds PC values silently,
-                * put them into the last histogram slot, so if
-                * present, they will show up as a sharp peak.
-                */
-                       ++prof_buffer[prof_len-1];
-       }
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -63,9 +45,7 @@ static inline void do_profile (unsigned long pc)
 static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
 {
        do_timer(regs);
-
-       if (!user_mode(regs))
-               do_profile(regs->pc);
+       profile_tick(CPU_PROFILING, regs);
 
 #ifdef CONFIG_HEARTBEAT
        /* use power LED as a heartbeat instead -- much more useful
diff --git a/arch/m68knommu/Kconfig.debug b/arch/m68knommu/Kconfig.debug
new file mode 100644 (file)
index 0000000..763c9aa
--- /dev/null
@@ -0,0 +1,42 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config FULLDEBUG
+       bool "Full Symbolic/Source Debugging support"
+       help
+         Enable debuging symbols on kernel build.
+
+config HIGHPROFILE
+       bool "Use fast second timer for profiling"
+       depends on COLDFIRE
+       help
+         Use a fast secondary clock to produce profiling information.
+
+config BOOTPARAM
+       bool 'Compiled-in Kernel Boot Parameter'
+
+config BOOTPARAM_STRING
+       string 'Kernel Boot Parameter'
+       default 'console=ttyS0,19200'
+       depends on BOOTPARAM
+
+config DUMPTOFLASH
+       bool "Panic/Dump to FLASH"
+       depends on COLDFIRE
+       help
+         Dump any panic of trap output into a flash memory segment
+         for later analysis.
+
+config NO_KERNEL_MSG
+       bool "Suppress Kernel BUG Messages"
+       help
+         Do not output any debug BUG messages within the kernel.
+
+config BDM_DISABLE
+       bool "Disable BDM signals"
+       depends on (EXPERIMENTAL && COLDFIRE)
+       help
+         Disable the ColdFire CPU's BDM signals.
+
+endmenu
index 1a6a360..1c6cd1a 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for arch/m68knommu/kernel.
 #
 
-extra-y := vmlinux.lds.s
+extra-y := vmlinux.lds
 
 obj-y += dma.o entry.o init_task.o m68k_ksyms.o process.o ptrace.o semaphore.o \
         setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
index c803fe6..02c56f5 100644 (file)
@@ -12,9 +12,9 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
+#include <linux/hardirq.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 
 #define DEFINE(sym, val) \
         asm volatile("\n->" #sym " %0 " #val : : "i" (val))
index 3fb0d78..0d58915 100644 (file)
@@ -616,9 +616,7 @@ adjust_stack:
        return;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
        goto adjust_stack;
 }
 
@@ -685,9 +683,7 @@ adjust_stack:
        return;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
        goto adjust_stack;
 }
 
index 74308a5..e328f28 100644 (file)
@@ -41,24 +41,6 @@ static inline int set_rtc_mmss(unsigned long nowtime)
        return -1;
 }
 
-static inline void do_profile (unsigned long pc)
-{
-       if (prof_buffer && current->pid) {
-               extern int _stext;
-               pc -= (unsigned long) &_stext;
-               pc >>= prof_shift;
-               if (pc < prof_len)
-                       ++prof_buffer[pc];
-               else
-               /*
-                * Don't ignore out-of-bounds PC values silently,
-                * put them into the last histogram slot, so if
-                * present, they will show up as a sharp peak.
-                */
-                       ++prof_buffer[prof_len-1];
-       }
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -75,9 +57,8 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
        write_seqlock(&xtime_lock);
 
        do_timer(regs);
-
-       if (!user_mode(regs))
-               do_profile(regs->pc);
+       if (current->pid)
+               profile_tick(CPU_PROFILING, regs);
 
        /*
         * If we have an externally synchronized Linux clock, then update
index 4d8f716..87f3bc4 100644 (file)
@@ -284,9 +284,6 @@ SECTIONS {
                __setup_start = .;
                *(.init.setup)
                __setup_end = .;
-               __start___param = .;
-               *(__param)
-               __stop___param = .;
                __initcall_start = .;
                *(.initcall1.init)
                *(.initcall2.init)
index 99c7d99..ef49596 100644 (file)
@@ -110,17 +110,8 @@ void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs)
 {
        /* Reset ColdFire timer2 */
        mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-
-        if (!user_mode(regs)) {
-                if (prof_buffer && current->pid) {
-                        extern int _stext;
-                        unsigned long ip = instruction_pointer(regs);
-                        ip -= (unsigned long) &_stext;
-                        ip >>= prof_shift;
-                        if (ip < prof_len)
-                                prof_buffer[ip]++;
-                }
-        }
+       if (current->pid)
+               profile_tick(CPU_PROFILING, regs);
 }
 
 /***************************************************************************/
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
new file mode 100644 (file)
index 0000000..d3c5cc3
--- /dev/null
@@ -0,0 +1,76 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config CROSSCOMPILE
+       bool "Are you using a crosscompiler"
+       help
+         Say Y here if you are compiling the kernel on a different
+         architecture than the one it is intended to run on.
+
+config CMDLINE
+       string "Default kernel command string"
+       default ""
+       help
+          On some platforms, there is currently no way for the boot loader to
+          pass arguments to the kernel. For these platforms, you can supply
+          some command-line options at build time by entering them here.  In
+          other cases you can specify kernel args so that you don't have
+         to set them up in board prom initialization routines.
+
+config DEBUG_STACK_USAGE
+       bool "Enable stack utilization instrumentation"
+       depends on DEBUG_KERNEL
+       help
+         Enables the display of the minimum amount of free stack which each
+         task has ever had available in the sysrq-T and sysrq-P debug output.
+
+         This option will slow down process creation somewhat.
+
+config KGDB
+       bool "Remote GDB kernel debugging"
+       depends on DEBUG_KERNEL
+       select DEBUG_INFO
+       help
+         If you say Y here, it will be possible to remotely debug the MIPS
+         kernel using gdb. This enlarges your kernel image disk size by
+         several megabytes and requires a machine with more than 16 MB,
+         better 32 MB RAM to avoid excessive linking time. This is only
+         useful for kernel hackers. If unsure, say N.
+
+config GDB_CONSOLE
+       bool "Console output to GDB"
+       depends on KGDB
+       help
+         If you are using GDB for remote debugging over a serial port and
+         would like kernel messages to be formatted into GDB $O packets so
+         that GDB prints them as program output, say 'Y'.
+
+config SB1XXX_CORELIS
+       bool "Corelis Debugger"
+       depends on SIBYTE_SB1xxx_SOC
+       select DEBUG_INFO
+       help
+         Select compile flags that produce code that can be processed by the
+         Corelis mksym utility and UDB Emulator.
+
+config RUNTIME_DEBUG
+       bool "Enable run-time debugging"
+       depends on DEBUG_KERNEL
+       help
+         If you say Y here, some debugging macros will do run-time checking.
+         If you say N here, those macros will mostly turn to no-ops.  See
+         include/asm-mips/debug.h for debuging macros.
+         If unsure, say N.
+
+config MIPS_UNCACHED
+       bool "Run uncached"
+       depends on DEBUG_KERNEL && !SMP && !SGI_IP27
+       help
+         If you say Y here there kernel will disable all CPU caches.  This will
+         reduce the system's performance dramatically but can help finding
+         otherwise hard to track bugs.  It can also useful if you're doing
+         hardware debugging with a logic analyzer and need to see all traffic
+         on the bus.
+
+endmenu
index f58f454..a72de97 100644 (file)
 #include <linux/kernel_stat.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/hardirq.h>
 
 #include <asm/mipsregs.h>
 #include <asm/ptrace.h>
 #include <asm/time.h>
-#include <asm/hardirq.h>
 #include <asm/div64.h>
 #include <asm/mach-au1x00/au1000.h>
 
index 098cfaa..e70684e 100644 (file)
@@ -29,6 +29,7 @@ SECTIONS
   .text : {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
     *(.fixup)
     *(.gnu.warning)
   } =0
@@ -96,9 +97,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
 
   .early_initcall.init : {
   __earlyinitcall_start = .;
index 9348cd3..fe7fc17 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <asm/mipsregs.h>
 #include <asm/ptrace.h>
-#include <asm/hardirq.h>
 #include <asm/div64.h>
 #include <asm/cpu.h>
 #include <asm/time.h>
index 820c3af..ec8077c 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/module.h>
 
 #include <asm/branch.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
index 4cbef34..ae1930e 100644 (file)
@@ -60,13 +60,7 @@ static void atlas_saa9730_base_fixup (struct pci_dev *pdev)
        printk ("saa9730_base = %x\n", saa9730_base);
 }
 
-#endif
-
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
+       atlas_saa9730_base_fixup);
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-#ifdef CONFIG_KGDB
-       {PCI_FIXUP_HEADER, PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
-        atlas_saa9730_base_fixup},
 #endif
-       { 0 }
-};
index f72022a..84c7e98 100644 (file)
@@ -41,6 +41,9 @@ static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
        pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
+        qube_raq_via_bmIDE_fixup);
+
 static void qube_raq_galileo_fixup(struct pci_dev *dev)
 {
        unsigned short galileo_id;
@@ -73,13 +76,8 @@ static void qube_raq_galileo_fixup(struct pci_dev *dev)
        }
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-       {PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
-        qube_raq_via_bmIDE_fixup},
-       {PCI_FIXUP_HEADER, PCI_VENDOR_ID_GALILEO, PCI_ANY_ID,
-        qube_raq_galileo_fixup},
-       0
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GALILEO, PCI_ANY_ID,
+       qube_raq_galileo_fixup);
 
 static char irq_tab_cobalt[] __initdata = {
   [COBALT_PCICONF_CPU]     = 0,
index 025285f..785bc03 100644 (file)
@@ -17,8 +17,5 @@ static void ddb5074_fixup(struct pci_dev *dev)
        pci_write_config_byte(dev, 0x7e, t8);
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-       { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
-         ddb5074_fixup },
-       {0}
-};
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
+       ddb5074_fixup);
index 9854413..25bf493 100644 (file)
@@ -41,6 +41,11 @@ static void ddb5477_fixup(struct pci_dev *dev)
        pci_write_config_byte(dev, 0x41, old | 0xd0);
 }
 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
+         ddb5477_fixup);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535,
+         ddb5477_fixup);
+
 /*
  * Fixup baseboard AMD chip so that tx does not underflow.
  *      bcr_18 |= 0x0800
@@ -69,12 +74,5 @@ static void ddb5477_amd_lance_fixup(struct pci_dev *dev)
        outw(temp, ioaddr + PCNET32_WIO_BDP);
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-       { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
-         ddb5477_fixup },
-       { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535,
-         ddb5477_fixup },
-       { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
-         ddb5477_amd_lance_fixup },
-       {0}
-};
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
+          ddb5477_amd_lance_fixup);
index 90c67c3..f64529b 100644 (file)
@@ -44,7 +44,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
        return irq_tab_mace[slot][pin];
 }
-
-struct pci_fixup pcibios_fixups[] = {
-       {0}
-};
index 49d33ff..e2ab64a 100644 (file)
@@ -4,7 +4,3 @@
 void __init pcibios_fixup_irqs(void)
 {
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-    { 0 }
-};
index 3345e19..bcde09e 100644 (file)
@@ -79,6 +79,8 @@ static void __init malta_piix_func0_fixup(struct pci_dev *pdev)
        }
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
+        malta_piix_func0_fixup);
 
 static void __init malta_piix_func1_fixup(struct pci_dev *pdev)
 {
@@ -96,10 +98,5 @@ static void __init malta_piix_func1_fixup(struct pci_dev *pdev)
        }
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-       {PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
-        malta_piix_func0_fixup},
-       {PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
-        malta_piix_func1_fixup},
-       { 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
+       malta_piix_func1_fixup);
index 1320c42..8e5db12 100644 (file)
@@ -42,7 +42,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 
        return irq_tab_mpc30x[slot];
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-       {       .pass = 0,      },
-};
index 99067c7..563fb2c 100644 (file)
@@ -82,7 +82,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 
        return irq_tab_rm200[slot][pin];
 }
-
-struct pci_fixup pcibios_fixups[] = {
-       {0}
-};
index 3c4183d..b996766 100644 (file)
@@ -329,6 +329,9 @@ static void __init pci_fixup_ioc3(struct pci_dev *d)
        pci_disable_swapping(d);
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
+        pci_fixup_ioc3);
+
 static void __init pci_fixup_isp1020(struct pci_dev *d)
 {
        struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus);
@@ -353,6 +356,9 @@ static void __init pci_fixup_isp1020(struct pci_dev *d)
        pci_enable_swapping(d);
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020,
+        pci_fixup_isp1020);
+
 static void __init pci_fixup_isp2x00(struct pci_dev *d)
 {
        struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus);
@@ -427,14 +433,7 @@ static void __init pci_fixup_isp2x00(struct pci_dev *d)
        /*d->resource[1].flags |= 1; */
 }
 
-struct pci_fixup pcibios_fixups[] = {
-       {PCI_FIXUP_HEADER, PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
-        pci_fixup_ioc3},
-       {PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020,
-        pci_fixup_isp1020},
-       {PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100,
-        pci_fixup_isp2x00},
-       {PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200,
-        pci_fixup_isp2x00},
-       {0}
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100,
+        pci_fixup_isp2x00);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200,
+        pci_fixup_isp2x00);
index 18e06ec..8c7c385 100644 (file)
@@ -279,7 +279,3 @@ static int __init sb1250_pcibios_init(void)
        return 0;
 }
 arch_initcall(sb1250_pcibios_init);
-
-struct pci_fixup pcibios_fixups[] = {
-       {0}
-};
index b9a12e9..95bbfd0 100644 (file)
@@ -414,11 +414,6 @@ struct pci_ops titan_pci_ops = {
         titan_ht_config_write_dword
 };
 
-
-struct pci_fixup pcibios_fixups[] = {
-        {0}
-};
-
 void __init pcibios_fixup_bus(struct pci_bus *c)
 {
         titan_ht_pcibios_fixup_bus(c);
index 6c6df7b..e3cdb95 100644 (file)
@@ -225,7 +225,7 @@ void __init paging_init(void)
                pfn_t end_pfn = node_getmaxclick(node) + 1;
 
                zones_size[ZONE_DMA] = end_pfn - start_pfn;
-               free_area_init_node(node, NODE_DATA(node), NULL,
+               free_area_init_node(node, NODE_DATA(node),
                                zones_size, start_pfn, NULL);
 
                if (end_pfn > max_low_pfn)
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
new file mode 100644 (file)
index 0000000..8caaed1
--- /dev/null
@@ -0,0 +1,14 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_RWLOCK
+        bool "Read-write spinlock debugging"
+        depends on DEBUG_KERNEL && SMP
+        help
+          If you say Y here then read-write lock processing will count how many
+          times it has tried to get the lock and issue an error message after
+          too many attempts.  If you suspect a rwlock problem or a kernel
+          hacker asks for this option then say Y.  Otherwise say N.
+
+endmenu
index 937ab23..3cb08a4 100644 (file)
@@ -146,15 +146,6 @@ char *pcibios_setup(char *str)
        return str;
 }
 
-/* Used in drivers/pci/quirks.c */
-struct pci_fixup pcibios_fixups[] = { 
-#ifdef CONFIG_SUPERIO
-       { PCI_FIXUP_HEADER,     PCI_VENDOR_ID_NS,       PCI_DEVICE_ID_NS_87415, superio_fixup_pci },
-#endif
-       { 0 }
-};
-
-
 /*
  * Called by pci_set_master() - a driver interface.
  *
index 949998f..8f4ad0c 100644 (file)
@@ -47,44 +47,6 @@ static long halftick;
 extern void smp_do_timer(struct pt_regs *regs);
 #endif
 
-static inline void
-parisc_do_profile(struct pt_regs *regs)
-{
-       unsigned long pc = regs->iaoq[0];
-#if 0
-       extern unsigned long prof_cpu_mask;
-#endif
-       extern char _stext;
-
-       profile_hook(regs);
-
-       if (user_mode(regs))
-               return;
-
-       if (!prof_buffer)
-               return;
-
-#if 0
-       /* FIXME: when we have irq affinity to cpu, we need to
-        * only look at the cpus specified in this mask 
-        */
-
-       if (!((1 << smp_processor_id()) & prof_cpu_mask))
-               return;
-#endif
-
-       pc -= (unsigned long) &_stext;
-       pc >>= prof_shift;
-       /*
-        * Don't ignore out-of-bounds PC values silently,
-        * put them into the last histogram slot, so if
-        * present, they will show up as a sharp peak.
-        */
-       if (pc > prof_len - 1)
-               pc = prof_len - 1;
-       atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
-
 irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        long now;
@@ -92,7 +54,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        int nticks;
        int cpu = smp_processor_id();
 
-       parisc_do_profile(regs);
+       profile_tick(CPU_PROFILING, regs);
 
        now = mfctl(16);
        /* initialize next_tick to time at last clocktick */
index 7e79f1b..5166a93 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/hardirq.h>     /* in_interrupt() */
 #include <asm/system.h>
-#include <asm/hardirq.h>       /* in_interrupt() */
 
 #undef INIT_STUCK
 #define INIT_STUCK 1L << 30
diff --git a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug
new file mode 100644 (file)
index 0000000..0df2814
--- /dev/null
@@ -0,0 +1,84 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config KGDB
+       bool "Include kgdb kernel debugger"
+       depends on DEBUG_KERNEL && (BROKEN || PPC_GEN550 || 4xx)
+       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.
+
+choice
+       prompt "Serial Port"
+       depends on KGDB
+       default KGDB_TTYS1
+
+config KGDB_TTYS0
+       bool "ttyS0"
+
+config KGDB_TTYS1
+       bool "ttyS1"
+
+config KGDB_TTYS2
+       bool "ttyS2"
+
+config KGDB_TTYS3
+       bool "ttyS3"
+
+endchoice
+
+config KGDB_CONSOLE
+       bool "Enable serial console thru kgdb port"
+       depends on KGDB && 8xx || CPM2
+       help
+         If you enable this, all serial console messages will be sent
+         over the gdb stub.
+         If unsure, say N.
+
+config XMON
+       bool "Include xmon kernel debugger"
+       depends on DEBUG_KERNEL
+       help
+         Include in-kernel hooks for the xmon kernel monitor/debugger.
+         Unless you are intending to debug the kernel, say N here.
+
+config BDI_SWITCH
+       bool "Include BDI-2000 user context switcher"
+       depends on DEBUG_KERNEL
+       help
+         Include in-kernel support for the Abatron BDI2000 debugger.
+         Unless you are intending to debug the kernel with one of these
+         machines, say N here.
+
+config SCHEDSTATS
+       bool "Collect scheduler statistics"
+       depends on DEBUG_KERNEL && PROC_FS
+       help
+         If you say Y here, additional code will be inserted into the
+         scheduler and related routines to collect statistics about
+         scheduler behavior and provide them in /proc/schedstat.  These
+         stats may be useful for both tuning and debugging the scheduler
+         If you aren't debugging the scheduler or trying to tune a specific
+         application, you can say N to avoid the very slight overhead
+         this adds.
+
+config BOOTX_TEXT
+       bool "Support for early boot text console (BootX or OpenFirmware only)"
+       depends PPC_OF
+       help
+         Say Y here to see progress messages from the boot firmware in text
+         mode. Requires either BootX or Open Firmware.
+
+config SERIAL_TEXT_DEBUG
+       bool "Support for early boot texts over serial port"
+       depends on 4xx || GT64260 || LOPEC || PPLUS || PRPMC800 || PPC_GEN550 || PPC_MPC52xx
+
+config PPC_OCP
+       bool
+       depends on IBM_OCP || FSL_OCP
+       default y
+
+endmenu
index cc93c9e..af881d7 100644 (file)
@@ -423,9 +423,6 @@ void __init config_amiga(void)
   mach_floppy_setup    = amiga_floppy_setup;
 #endif
   mach_reset           = amiga_reset;
-#ifdef CONFIG_DUMMY_CONSOLE
-  conswitchp           = &dummy_con;
-#endif
 #ifdef CONFIG_HEARTBEAT
   mach_heartbeat = amiga_heartbeat;
 #endif
index 8eb07a6..9017c54 100644 (file)
@@ -5,14 +5,14 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/serial.h>
-#include <linux/serialP.h>
 #include <linux/serial_reg.h>
 #include <asm/serial.h>
 
+#include "nonstdio.h"
+#include "serial.h"
+
 #define SERIAL_BAUD    9600
 
-extern void outb(int port, unsigned char val);
-extern unsigned char inb(int port);
 extern unsigned long ISA_io;
 
 static struct serial_state rs_table[RS_TABLE_SIZE] = {
index 2dc176e..03dfaa0 100644 (file)
  * is" without any warranty of any kind, whether express or implied.
  */
 
-void __attribute__ ((weak))
-serial_fixups(void)
-{
-}
-
 unsigned long __attribute__ ((weak))
 serial_init(int chan, void *ignored)
 {
index 93771e2..7c4fb8f 100644 (file)
@@ -41,7 +41,7 @@ disable_6xx_mmu:
        /* Test for a 601 */
        mfpvr   r10
        srwi    r10,r10,16
-       cmp   0,r10,1         /* 601 ? */
+       cmpwi   0,r10,1         /* 601 ? */
        beq     .clearbats_601
 
        /* Clear BATs */
@@ -117,9 +117,9 @@ _setup_L2CR:
        /* Wait for the invalidation to complete */
        mfspr   r8,PVR
        srwi    r8,r8,16
-       cmpl  cr0,r8,0x8000                   /* 7450 */
-       cmpl  cr1,r8,0x8001                   /* 7455 */
-       cmpl  cr2,r8,0x8002                   /* 7457 */
+       cmplwi  cr0,r8,0x8000                   /* 7450 */
+       cmplwi  cr1,r8,0x8001                   /* 7455 */
+       cmplwi  cr2,r8,0x8002                   /* 7457 */
        cror    4*cr0+eq,4*cr0+eq,4*cr1+eq      /* Now test if any are true. */
        cror    4*cr0+eq,4*cr0+eq,4*cr2+eq
        bne     2f
@@ -190,7 +190,7 @@ timebase_period_ns:
 udelay:
        mfspr   r4,PVR
        srwi    r4,r4,16
-       cmp   0,r4,1          /* 601 ? */
+       cmpwi   0,r4,1          /* 601 ? */
        bne     .udelay_not_601
 00:    li      r0,86   /* Instructions / microsecond? */
        mtctr   r0
@@ -213,16 +213,16 @@ udelay:
 1:     mftbu   r5
        mftb    r6
        mftbu   r7
-       cmp     0,r5,r7
+       cmpw    0,r5,r7
        bne     1b              /* Get [synced] base time */
        addc    r9,r6,r4        /* Compute end time */
        addze   r8,r5
 2:     mftbu   r5
-       cmp     0,r5,r8
+       cmpw    0,r5,r8
        blt     2b
        bgt     3f
        mftb    r6
-       cmp     0,r6,r9
+       cmpw    0,r6,r9
        blt     2b
 3:     blr
 
index 7a0f027..f2b5526 100644 (file)
@@ -30,3 +30,5 @@ extern void puthex(unsigned long val);
 extern void puts(const char *);
 extern void udelay(long delay);
 extern unsigned char inb(int port);
+extern void board_isa_init(void);
+extern void ISA_init(unsigned long base);
diff --git a/arch/ppc/boot/include/serial.h b/arch/ppc/boot/include/serial.h
new file mode 100644 (file)
index 0000000..d710eab
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * A really private header file for the (dumb) serial driver in arch/ppc/boot
+ *
+ * Shamelessly taken from include/linux/serialP.h:
+ *
+ * Copyright (C) 1997 by Theodore Ts'o.
+ *
+ * Redistribution of this file is permitted under the terms of the GNU
+ * Public License (GPL)
+ */
+
+#ifndef _PPC_BOOT_SERIALP_H
+#define _PPC_BOOT_SERIALP_H
+
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * Given that this is how SERIAL_PORT_DFNS are done, and that we need
+ * to use a few of their fields, we need to have our own copy of it.
+ */
+struct serial_state {
+       int     magic;
+       int     baud_base;
+       unsigned long   port;
+       int     irq;
+       int     flags;
+       int     hub6;
+       int     type;
+       int     line;
+       int     revision;       /* Chip revision (950) */
+       int     xmit_fifo_size;
+       int     custom_divisor;
+       int     count;
+       u8      *iomem_base;
+       u16     iomem_reg_shift;
+       unsigned short  close_delay;
+       unsigned short  closing_wait; /* time to wait before closing */
+       unsigned long   icount;
+       int     io_type;
+       void    *info;
+       void    *dev;
+};
+#endif /* _PPC_BOOT_SERIAL_H */
index 97ef7d1..9d088a5 100644 (file)
@@ -4,5 +4,7 @@
 
 CFLAGS_kbd.o   += -Idrivers/char
 
-lib-y := zlib.o div64.o
+lib-y := $(addprefix ../../../../lib/zlib_inflate/, \
+           infblock.o infcodes.o inffast.o inflate.o inftrees.o infutil.o)
+lib-y += div64.o
 lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o
index 94c23c0..04ba9d5 100644 (file)
@@ -12,7 +12,6 @@
 
 #include "nonstdio.h"
 #include "of1275.h"
-#include "zlib.h"
 
 /* Passed from the linker */
 extern char __image_begin, __image_end;
index 7119506..9e69527 100644 (file)
@@ -7,10 +7,10 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include "zlib.h"
 #include "nonstdio.h"
 #include "of1275.h"
 #include <linux/string.h>
+#include <linux/zlib.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
 
@@ -30,12 +30,11 @@ struct memchunk {
 
 static struct memchunk *freechunks;
 
-static void *zalloc(void *x, unsigned items, unsigned size)
+static void *zalloc(unsigned size)
 {
     void *p;
     struct memchunk **mpp, *mp;
 
-    size *= items;
     size = (size + 7) & -8;
     heap_use += size;
     if (heap_use > heap_max)
@@ -57,74 +56,57 @@ static void *zalloc(void *x, unsigned items, unsigned size)
     return p;
 }
 
-static void zfree(void *x, void *addr, unsigned nb)
-{
-    struct memchunk *mp = addr;
-
-    nb = (nb + 7) & -8;
-    heap_use -= nb;
-    if (avail_ram == addr + nb) {
-       avail_ram = addr;
-       return;
-    }
-    mp->size = nb;
-    mp->next = freechunks;
-    freechunks = mp;
-}
-
 #define HEAD_CRC       2
 #define EXTRA_FIELD    4
 #define ORIG_NAME      8
 #define COMMENT                0x10
 #define RESERVED       0xe0
 
-#define DEFLATED       8
-
 void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
 {
-    z_stream s;
-    int r, i, flags;
-
-    /* skip header */
-    i = 10;
-    flags = src[3];
-    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
-       printf("bad gzipped data\n\r");
-       exit();
-    }
-    if ((flags & EXTRA_FIELD) != 0)
-       i = 12 + src[10] + (src[11] << 8);
-    if ((flags & ORIG_NAME) != 0)
-       while (src[i++] != 0)
-           ;
-    if ((flags & COMMENT) != 0)
-       while (src[i++] != 0)
-           ;
-    if ((flags & HEAD_CRC) != 0)
-       i += 2;
-    if (i >= *lenp) {
-       printf("gunzip: ran out of data in header\n\r");
-       exit();
-    }
+       z_stream s;
+       int r, i, flags;
+
+       /* skip header */
+       i = 10;
+       flags = src[3];
+       if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
+               printf("bad gzipped data\n\r");
+               exit();
+       }
+       if ((flags & EXTRA_FIELD) != 0)
+               i = 12 + src[10] + (src[11] << 8);
+       if ((flags & ORIG_NAME) != 0)
+               while (src[i++] != 0)
+                       ;
+       if ((flags & COMMENT) != 0)
+               while (src[i++] != 0)
+                       ;
+       if ((flags & HEAD_CRC) != 0)
+               i += 2;
+       if (i >= *lenp) {
+               printf("gunzip: ran out of data in header\n\r");
+               exit();
+       }
 
-    s.zalloc = zalloc;
-    s.zfree = zfree;
-    r = inflateInit2(&s, -MAX_WBITS);
-    if (r != Z_OK) {
-       printf("inflateInit2 returned %d\n\r", r);
-       exit();
-    }
-    s.next_in = src + i;
-    s.avail_in = *lenp - i;
-    s.next_out = dst;
-    s.avail_out = dstlen;
-    r = inflate(&s, Z_FINISH);
-    if (r != Z_OK && r != Z_STREAM_END) {
-       printf("inflate returned %d msg: %s\n\r", r, s.msg);
-       exit();
-    }
-    *lenp = s.next_out - (unsigned char *) dst;
-    inflateEnd(&s);
+       /* Initialize ourself. */
+       s.workspace = zalloc(zlib_inflate_workspacesize());
+       r = zlib_inflateInit2(&s, -MAX_WBITS);
+       if (r != Z_OK) {
+               printf("zlib_inflateInit2 returned %d\n\r", r);
+               exit();
+       }
+       s.next_in = src + i;
+       s.avail_in = *lenp - i;
+       s.next_out = dst;
+       s.avail_out = dstlen;
+       r = zlib_inflate(&s, Z_FINISH);
+       if (r != Z_OK && r != Z_STREAM_END) {
+               printf("inflate returned %d msg: %s\n\r", r, s.msg);
+               exit();
+       }
+       *lenp = s.next_out - (unsigned char *) dst;
+       zlib_inflateEnd(&s);
 }
 
 /* Make a bi_rec in OF.  We need to be passed a name for BI_BOOTLOADER_ID,
index 844c0bc..ab9e897 100644 (file)
@@ -16,7 +16,7 @@
 setup_bats:
        mfpvr   5
        rlwinm  5,5,16,16,31            /* r3 = 1 for 601, 4 for 604 */
-       cmp   0,5,1
+       cmpwi   0,5,1
        li      0,0
        bne     4f
        mtibatl 3,0                     /* invalidate BAT first */
diff --git a/arch/ppc/boot/simple/chrpmap.c b/arch/ppc/boot/simple/chrpmap.c
new file mode 100644 (file)
index 0000000..14d9e05
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 2004 (C) IBM. 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.
+ */
+
+#include <nonstdio.h>
+
+void board_isa_init(void)
+{
+       ISA_init(0xFE000000);
+}
index 58e2a92..8615d5f 100644 (file)
@@ -22,7 +22,6 @@
 #endif
 
 #include "nonstdio.h"
-#include "zlib.h"
 
 /* The linker tells us where the image is. */
 extern char __image_begin, __image_end;
@@ -72,6 +71,14 @@ extern void flush_instruction_cache(void);
 extern void gunzip(void *, int, unsigned char *, int *);
 extern void embed_config(bd_t **bp);
 
+/* Weak function for boards which don't need to build the
+ * board info struct because they are using PPCBoot/U-Boot.
+ */
+void __attribute__ ((weak))
+embed_config(bd_t **bdp)
+{
+}
+
 unsigned long
 load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp)
 {
index da29dec..75380ac 100644 (file)
@@ -88,6 +88,7 @@ load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
                ofinit(OFW_interface);
        }
 
+       board_isa_init();
 #if defined(CONFIG_VGA_CONSOLE)
        vga_init((unsigned char *)0xC0000000);
 #endif /* CONFIG_VGA_CONSOLE */
index fa181ff..d012c39 100644 (file)
@@ -26,7 +26,6 @@ extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
 /* Define some important locations of the Spruce. */
 #define SPRUCE_PCI_CONFIG_ADDR 0xfec00000
 #define SPRUCE_PCI_CONFIG_DATA 0xfec00004
-#define SPRUCE_ISA_IO_BASE     0xf8000000
 
 /* PCI configuration space access routines. */
 unsigned int *pci_config_address = (unsigned int *)SPRUCE_PCI_CONFIG_ADDR;
@@ -86,8 +85,6 @@ void cpc700_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
        out_le32((unsigned *)pci_config_data, val);
 }
 
-unsigned long isa_io_base = SPRUCE_ISA_IO_BASE;
-
 #define PCNET32_WIO_RDP                0x10
 #define PCNET32_WIO_RAP                0x12
 #define PCNET32_WIO_RESET      0x14
diff --git a/arch/ppc/boot/simple/pibs.c b/arch/ppc/boot/simple/pibs.c
new file mode 100644 (file)
index 0000000..9ce8847
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <asm/ppcboot.h>
+#include <platforms/4xx/ocotea.h>
+
+extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
+                                      unsigned long cksum);
+
+/* We need to make sure that this is before the images to ensure
+ * that it's in a mapped location. - Tom */
+bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
+bd_t *hold_residual = &hold_resid_buf;
+
+/* String functions lifted from lib/vsprintf.c and lib/ctype.c */
+unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C,                       /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,                /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C,                       /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C,                       /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,                   /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P,                       /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D,                       /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P,                       /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,     /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U,                       /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U,                       /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P,                       /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,     /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L,                       /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L,                       /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C,                       /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,               /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,               /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
+
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
+{
+       unsigned long long result = 0,value;
+
+       if (!base) {
+               base = 10;
+               if (*cp == '0') {
+                       base = 8;
+                       cp++;
+                       if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
+                               cp++;
+                               base = 16;
+                       }
+               }
+       } else if (base == 16) {
+               if (cp[0] == '0' && toupper(cp[1]) == 'X')
+                       cp += 2;
+       }
+       while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+           ? toupper(*cp) : *cp)-'A'+10) < base) {
+               result = result*base + value;
+               cp++;
+       }
+       if (endp)
+               *endp = (char *)cp;
+       return result;
+}
+
+void *
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+               void *ign1, void *ign2)
+{
+       unsigned long long mac64;
+
+       decompress_kernel(load_addr, num_words, cksum);
+
+       mac64 = simple_strtoull((char *)OCOTEA_PIBS_MAC_BASE, 0, 16);
+       memcpy(hold_residual->bi_enetaddr, (char *)&mac64+2, 6);
+       mac64 = simple_strtoull((char *)(OCOTEA_PIBS_MAC_BASE+OCOTEA_PIBS_MAC_OFFSET), 0, 16);
+       memcpy(hold_residual->bi_enet1addr, (char *)&mac64+2, 6);
+       mac64 = simple_strtoull((char *)(OCOTEA_PIBS_MAC_BASE+OCOTEA_PIBS_MAC_OFFSET*2), 0, 16);
+       memcpy(hold_residual->bi_enet2addr, (char *)&mac64+2, 6);
+       mac64 = simple_strtoull((char *)(OCOTEA_PIBS_MAC_BASE+OCOTEA_PIBS_MAC_OFFSET*3), 0, 16);
+       memcpy(hold_residual->bi_enet3addr, (char *)&mac64+2, 6);
+       return (void *)hold_residual;
+}
diff --git a/arch/ppc/boot/simple/prepmap.c b/arch/ppc/boot/simple/prepmap.c
new file mode 100644 (file)
index 0000000..c871a4d
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 2004 (C) IBM. 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.
+ */
+
+#include <nonstdio.h>
+
+void board_isa_init(void)
+{
+       ISA_init(0x80000000);
+}
index e57d967..555a216 100644 (file)
@@ -50,7 +50,7 @@ relocate:
         * Check if we need to relocate ourselves to the link addr or were
         * we loaded there to begin with.
         */
-       cmp     cr0,r3,r4
+       cmpw    cr0,r3,r4
        beq     start_ldr       /* If 0, we don't need to relocate */
 
        /* Move this code somewhere safe.  This is max(load + size, end)
@@ -122,7 +122,7 @@ do_relocate:
        GETSYM(r4, start)
        mr      r3,r8           /* Get the load addr */
 
-       cmp     cr0,r4,r3       /* If we need to copy from the end, do so */
+       cmpw    cr0,r4,r3       /* If we need to copy from the end, do so */
        bgt     do_relocate_from_end
 
 do_relocate_from_start:
@@ -165,7 +165,7 @@ start_ldr:
        subi    r4,r4,4
        li      r0,0
 50:    stwu    r0,4(r3)
-       cmp     cr0,r3,r4
+       cmpw    cr0,r3,r4
        bne     50b
 90:    mr      r9,r1           /* Save old stack pointer (in case it matters) */
        lis     r1,.stack@h
index 8158d8c..f6629a2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/ppc/pp3boot/mkbugboot.c
+ * arch/ppc/boot/utils/mkbugboot.c
  *
  * Makes a Motorola PPCBUG ROM bootable image which can be flashed
  * into one of the FLASH banks on a Motorola PowerPlus board.
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
 
 #ifdef __i386__
 #define cpu_to_be32(x) le32_to_cpu(x)
@@ -49,11 +54,6 @@ unsigned short le16_to_cpu(unsigned short x)
 /* size of read buffer */
 #define SIZE 0x1000
 
-/* typedef long int32_t; */
-typedef unsigned long uint32_t;
-typedef unsigned short uint16_t;
-typedef unsigned char uint8_t;
-
 /* PPCBUG ROM boot header */
 typedef struct bug_boot_header {
   uint8_t      magic_word[4];          /* "BOOT" */
index 7ef98c0..2be22e2 100644 (file)
 #include <sys/stat.h>
 #include <unistd.h>
 #include <netinet/in.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
 #include <stdint.h>
+#endif
 
 /* This gets tacked on the front of the image.  There are also a few
  * bytes allocated after the _start label used by the boot rom (see
index 6e1a38d..46776b9 100644 (file)
@@ -1,26 +1,48 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Wed Sep 22 09:53:26 2004
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_GENERIC_IOMAP=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -33,24 +55,26 @@ CONFIG_OBSOLETE_MODPARM=y
 CONFIG_KMOD=y
 
 #
-# Platform support
+# Processor
 #
-CONFIG_PPC=y
-CONFIG_PPC32=y
 CONFIG_6xx=y
 # CONFIG_40x is not set
+# CONFIG_44x is not set
 # CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
 # CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
 
 #
-# IBM 4xx options
+# Platform options
 #
-# CONFIG_8260 is not set
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PPC_STD_MMU=y
 # CONFIG_PPC_MULTIPLATFORM is not set
 # CONFIG_APUS is not set
-# CONFIG_WILLOW_2 is not set
+# CONFIG_WILLOW is not set
 # CONFIG_PCORE is not set
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
@@ -66,34 +90,30 @@ CONFIG_MVME5100=y
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_LITE5200 is not set
 # CONFIG_MVME5100_IPMC761_PRESENT is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
-CONFIG_ALTIVEC=y
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
 
 #
-# General setup
+# Bus options
 #
-# CONFIG_HIGHMEM is not set
+CONFIG_GENERIC_ISA_DMA=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
 # CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_NAMES is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-# CONFIG_PPC601_SYNC_FIX is not set
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="ip=on"
 
 #
 # Advanced setup
@@ -109,15 +129,29 @@ CONFIG_KERNEL_START=0xc0000000
 CONFIG_TASK_SIZE=0x80000000
 CONFIG_BOOT_LOAD=0x00800000
 
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
 #
 # 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
 
 #
 # Block devices
@@ -129,46 +163,46 @@ CONFIG_BOOT_LOAD=0x00800000
 # CONFIG_BLK_DEV_UMEM 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_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
 
 #
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
 CONFIG_BLK_DEV_IDE=y
 
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 # CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
 #
+CONFIG_IDE_GENERIC=y
 # CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
-# SCSI support
+# SCSI device support
 #
 CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
 
 #
 # SCSI support type (disk, tape, CD-ROM)
@@ -184,64 +218,70 @@ CONFIG_BLK_DEV_SR=y
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
 #
 # SCSI low-level drivers
 #
 # 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_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-CONFIG_SCSI_SYM53C8XX=y
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=20
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=32
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG 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 (EXPERIMENTAL)
+# IEEE 1394 (FireWire) support
 #
 # CONFIG_IEEE1394 is not set
 
@@ -250,6 +290,10 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
 #
 # CONFIG_I2O is not set
 
+#
+# Macintosh device drivers
+#
+
 #
 # Networking support
 #
@@ -261,86 +305,90 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 # CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
 # 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_ARPD is not set
-# CONFIG_INET_ECN 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_TUNNEL=m
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
 
 #
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_TFTP is not set
-# CONFIG_IP_NF_AMANDA is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_QUEUE is not set
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
+# CONFIG_IP_NF_MATCH_LIMIT is not set
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_MAC is not set
+# CONFIG_IP_NF_MATCH_PKTTYPE is not set
+# CONFIG_IP_NF_MATCH_MARK is not set
+# CONFIG_IP_NF_MATCH_MULTIPORT is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_DSCP is not set
+# CONFIG_IP_NF_MATCH_AH_ESP is not set
+# CONFIG_IP_NF_MATCH_LENGTH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_TCPMSS is not set
 CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_UNCLEAN=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
-# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_MATCH_STATE is not set
+# CONFIG_IP_NF_MATCH_CONNTRACK is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_FILTER is not set
 # CONFIG_IP_NF_TARGET_LOG is not set
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_TARGET_TCPMSS is not set
+# CONFIG_IP_NF_NAT is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
 # CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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_NET_DIVERT is not set
@@ -352,29 +400,33 @@ CONFIG_IPV6_SCTP__=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 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
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
@@ -382,17 +434,26 @@ CONFIG_MII=y
 #
 # Tulip family network device support
 #
-# CONFIG_NET_TULIP is not set
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 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=y
-# CONFIG_EEPRO100_PIO is not set
-# CONFIG_E100 is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
@@ -403,6 +464,7 @@ CONFIG_EEPRO100=y
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -421,52 +483,39 @@ CONFIG_EEPRO100=y
 # Ethernet (10000 Mbit)
 #
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+# CONFIG_S2IO is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Token Ring devices
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
 
 #
-# Token Ring devices (depends on LLC=y)
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
+# CONFIG_NET_RADIO is not set
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA 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
 
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
 
 #
-# Graphics support
+# Telephony Support
 #
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
+# CONFIG_PHONE is not set
 
 #
 # Input device support
@@ -483,18 +532,16 @@ CONFIG_EEPRO100=y
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 # CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
 
 #
 # Input Device Drivers
 #
 
-#
-# Macintosh device drivers
-#
-
 #
 # Character devices
 #
+# CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -502,6 +549,7 @@ CONFIG_SOUND_GAMEPORT=y
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -510,27 +558,8 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 
 #
 # IPMI
@@ -551,11 +580,23 @@ CONFIG_GEN_RTC=y
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
 
 #
 # Multimedia devices
@@ -567,6 +608,26 @@ CONFIG_GEN_RTC=y
 #
 # CONFIG_DVB is not set
 
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
 #
 # File systems
 #
@@ -592,17 +653,20 @@ CONFIG_EXT2_FS=y
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# 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_SYSFS=y
 # CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
 #
@@ -611,6 +675,7 @@ CONFIG_RAMFS=y
 # 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
@@ -625,19 +690,21 @@ CONFIG_RAMFS=y
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
 # CONFIG_NFS_V4 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_EXPORTFS is not set
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# 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_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -647,31 +714,26 @@ CONFIG_SUNRPC=y
 CONFIG_MSDOS_PARTITION=y
 
 #
-# Sound
+# Native Language Support
 #
-# CONFIG_SOUND is not set
+# CONFIG_NLS is not set
 
 #
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
+# Library routines
 #
-# CONFIG_BT is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 
 #
-# Library routines
+# Profiling support
 #
-# CONFIG_CRC32 is not set
+# CONFIG_PROFILING is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
 
 #
 # Security options
index ee0705c..e42049f 100644 (file)
@@ -172,9 +172,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
 setup_750cx:
        mfspr   r10, SPRN_HID1
        rlwinm  r10,r10,4,28,31
-       cmp   cr0,r10,7
-       cmp   cr1,r10,9
-       cmp   cr2,r10,11
+       cmpwi   cr0,r10,7
+       cmpwi   cr1,r10,9
+       cmpwi   cr2,r10,11
        cror    4*cr0+eq,4*cr0+eq,4*cr1+eq
        cror    4*cr0+eq,4*cr0+eq,4*cr2+eq
        bnelr
@@ -218,10 +218,10 @@ setup_745x_specifics:
 
        /* All of the bits we have to set.....
         */
-       ori     r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK
+       ori     r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK | HID0_BTIC
 BEGIN_FTR_SECTION
-       ori     r11,r11,HID0_BTIC
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_BTIC)
+       xori    r11,r11,HID0_BTIC
+END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC)
 BEGIN_FTR_SECTION
        oris    r11,r11,HID0_DPM@h      /* enable dynamic power mgmt */
 END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
@@ -287,12 +287,12 @@ _GLOBAL(__save_cpu_setup)
        /* Now deal with CPU type dependent registers */
        mfspr   r3,PVR
        srwi    r3,r3,16
-       cmpl  cr0,r3,0x8000   /* 7450 */
-       cmpl  cr1,r3,0x000c   /* 7400 */
-       cmpl  cr2,r3,0x800c   /* 7410 */
-       cmpl  cr3,r3,0x8001   /* 7455 */
-       cmpl  cr4,r3,0x8002   /* 7457 */
-       cmpl  cr5,r3,0x7000   /* 750FX */
+       cmplwi  cr0,r3,0x8000   /* 7450 */
+       cmplwi  cr1,r3,0x000c   /* 7400 */
+       cmplwi  cr2,r3,0x800c   /* 7410 */
+       cmplwi  cr3,r3,0x8001   /* 7455 */
+       cmplwi  cr4,r3,0x8002   /* 7457 */
+       cmplwi  cr5,r3,0x7000   /* 750FX */
        /* cr1 is 7400 || 7410 */
        cror    4*cr1+eq,4*cr1+eq,4*cr2+eq
        /* cr0 is 74xx */
@@ -323,7 +323,7 @@ _GLOBAL(__save_cpu_setup)
        /* If rev 2.x, backup HID2 */
        mfspr   r3,PVR
        andi.   r3,r3,0xff00
-       cmp   cr0,r3,0x0200
+       cmpwi   cr0,r3,0x0200
        bne     1f
        mfspr   r4,SPRN_HID2
        stw     r4,CS_HID2(r5)
@@ -354,12 +354,12 @@ _GLOBAL(__restore_cpu_setup)
        /* Now deal with CPU type dependent registers */
        mfspr   r3,PVR
        srwi    r3,r3,16
-       cmpl  cr0,r3,0x8000   /* 7450 */
-       cmpl  cr1,r3,0x000c   /* 7400 */
-       cmpl  cr2,r3,0x800c   /* 7410 */
-       cmpl  cr3,r3,0x8001   /* 7455 */
-       cmpl  cr4,r3,0x8002   /* 7457 */
-       cmpl  cr5,r3,0x7000   /* 750FX */
+       cmplwi  cr0,r3,0x8000   /* 7450 */
+       cmplwi  cr1,r3,0x000c   /* 7400 */
+       cmplwi  cr2,r3,0x800c   /* 7410 */
+       cmplwi  cr3,r3,0x8001   /* 7455 */
+       cmplwi  cr4,r3,0x8002   /* 7457 */
+       cmplwi  cr5,r3,0x7000   /* 750FX */
        /* cr1 is 7400 || 7410 */
        cror    4*cr1+eq,4*cr1+eq,4*cr2+eq
        /* cr0 is 74xx */
@@ -412,7 +412,7 @@ _GLOBAL(__restore_cpu_setup)
        /* If rev 2.x, restore HID2 with low voltage bit cleared */
        mfspr   r3,PVR
        andi.   r3,r3,0xff00
-       cmp   cr0,r3,0x0200
+       cmpwi   cr0,r3,0x0200
        bne     4f
        lwz     r4,CS_HID2(r5)
        rlwinm  r4,r4,0,19,17
@@ -426,7 +426,7 @@ _GLOBAL(__restore_cpu_setup)
        mftbl   r5
 3:     mftbl   r6
        sub     r6,r6,r5
-       cmpl  cr0,r6,10000
+       cmplwi  cr0,r6,10000
        ble     3b
        /* Setup final PLL */
        mtspr   SPRN_HID1,r4
index 6a6ee98..f2ea1a9 100644 (file)
@@ -112,7 +112,9 @@ _GLOBAL(__save_cpu_setup)
        /* We only deal with 970 for now */
        mfspr   r0,SPRN_PVR
        srwi    r0,r0,16
-       cmpwi   r0,0x39
+       cmpwi   cr0,r0,0x39
+       cmpwi   cr1,r0,0x3c
+       cror    4*cr0+eq,4*cr0+eq,4*cr1+eq
        bne     1f
 
        /* Save HID0,1,4 and 5 */
@@ -144,7 +146,9 @@ _GLOBAL(__restore_cpu_setup)
        /* We only deal with 970 for now */
        mfspr   r0,SPRN_PVR
        srwi    r0,r0,16
-       cmpwi   r0,0x39
+       cmpwi   cr0,r0,0x39
+       cmpwi   cr1,r0,0x3c
+       cror    4*cr0+eq,4*cr0+eq,4*cr1+eq
        bne     1f
 
        /* Clear interrupt prefix */
index 54f9a3e..334b8bf 100644 (file)
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #include <linux/dma-mapping.h>
+#include <linux/hardirq.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
@@ -381,6 +381,7 @@ void __dma_sync(void *vaddr, size_t size, int direction)
                break;
        }
 }
+EXPORT_SYMBOL(__dma_sync);
 
 #ifdef CONFIG_HIGHMEM
 /*
@@ -438,3 +439,4 @@ void __dma_sync_page(struct page *page, unsigned long offset,
        __dma_sync((void *)start, size, direction);
 #endif
 }
+EXPORT_SYMBOL(__dma_sync_page);
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
new file mode 100644 (file)
index 0000000..6f54039
--- /dev/null
@@ -0,0 +1,240 @@
+#ifndef __HEAD_BOOKE_H__
+#define __HEAD_BOOKE_H__
+
+/*
+ * Macros used for common Book-e exception handling
+ */
+
+#define SET_IVOR(vector_number, vector_label)          \
+               li      r26,vector_label@l;             \
+               mtspr   SPRN_IVOR##vector_number,r26;   \
+               sync
+
+#define NORMAL_EXCEPTION_PROLOG                                                     \
+       mtspr   SPRN_SPRG0,r10;         /* save two registers to work with */\
+       mtspr   SPRN_SPRG1,r11;                                              \
+       mtspr   SPRN_SPRG4W,r1;                                              \
+       mfcr    r10;                    /* save CR in r10 for now          */\
+       mfspr   r11,SPRN_SRR1;          /* check whether user or kernel    */\
+       andi.   r11,r11,MSR_PR;                                              \
+       beq     1f;                                                          \
+       mfspr   r1,SPRG3;               /* if from user, start at top of   */\
+       lwz     r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
+       addi    r1,r1,THREAD_SIZE;                                           \
+1:     subi    r1,r1,INT_FRAME_SIZE;   /* Allocate an exception frame     */\
+       tophys(r11,r1);                                                      \
+       stw     r10,_CCR(r11);          /* save various registers          */\
+       stw     r12,GPR12(r11);                                              \
+       stw     r9,GPR9(r11);                                                \
+       mfspr   r10,SPRG0;                                                   \
+       stw     r10,GPR10(r11);                                              \
+       mfspr   r12,SPRG1;                                                   \
+       stw     r12,GPR11(r11);                                              \
+       mflr    r10;                                                         \
+       stw     r10,_LINK(r11);                                              \
+       mfspr   r10,SPRG4R;                                                  \
+       mfspr   r12,SRR0;                                                    \
+       stw     r10,GPR1(r11);                                               \
+       mfspr   r9,SRR1;                                                     \
+       stw     r10,0(r11);                                                  \
+       rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
+       stw     r0,GPR0(r11);                                                \
+       SAVE_4GPRS(3, r11);                                                  \
+       SAVE_2GPRS(7, r11)
+
+/*
+ * Exception prolog for critical exceptions.  This is a little different
+ * from the normal exception prolog above since a critical exception
+ * can potentially occur at any point during normal exception processing.
+ * Thus we cannot use the same SPRG registers as the normal prolog above.
+ * Instead we use a couple of words of memory at low physical addresses.
+ * This is OK since we don't support SMP on these processors. For Book E
+ * processors, we also have a reserved register (SPRG2) that is only used
+ * in critical exceptions so we can free up a GPR to use as the base for
+ * indirect access to the critical exception save area.  This is necessary
+ * since the MMU is always on and the save area is offset from KERNELBASE.
+ */
+#define CRITICAL_EXCEPTION_PROLOG                                           \
+       mtspr   SPRG2,r8;               /* SPRG2 only used in criticals */   \
+       lis     r8,crit_save@ha;                                             \
+       stw     r10,crit_r10@l(r8);                                          \
+       stw     r11,crit_r11@l(r8);                                          \
+       mfspr   r10,SPRG0;                                                   \
+       stw     r10,crit_sprg0@l(r8);                                        \
+       mfspr   r10,SPRG1;                                                   \
+       stw     r10,crit_sprg1@l(r8);                                        \
+       mfspr   r10,SPRG4R;                                                  \
+       stw     r10,crit_sprg4@l(r8);                                        \
+       mfspr   r10,SPRG5R;                                                  \
+       stw     r10,crit_sprg5@l(r8);                                        \
+       mfspr   r10,SPRG7R;                                                  \
+       stw     r10,crit_sprg7@l(r8);                                        \
+       mfspr   r10,SPRN_PID;                                                \
+       stw     r10,crit_pid@l(r8);                                          \
+       mfspr   r10,SRR0;                                                    \
+       stw     r10,crit_srr0@l(r8);                                         \
+       mfspr   r10,SRR1;                                                    \
+       stw     r10,crit_srr1@l(r8);                                         \
+       mfspr   r8,SPRG2;               /* SPRG2 only used in criticals */   \
+       mfcr    r10;                    /* save CR in r10 for now          */\
+       mfspr   r11,SPRN_CSRR1;         /* check whether user or kernel    */\
+       andi.   r11,r11,MSR_PR;                                              \
+       lis     r11,critical_stack_top@h;                                    \
+       ori     r11,r11,critical_stack_top@l;                                \
+       beq     1f;                                                          \
+       /* COMING FROM USER MODE */                                          \
+       mfspr   r11,SPRG3;              /* if from user, start at top of   */\
+       lwz     r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
+       addi    r11,r11,THREAD_SIZE;                                         \
+1:     subi    r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame     */\
+       stw     r10,_CCR(r11);          /* save various registers          */\
+       stw     r12,GPR12(r11);                                              \
+       stw     r9,GPR9(r11);                                                \
+       mflr    r10;                                                         \
+       stw     r10,_LINK(r11);                                              \
+       mfspr   r12,SPRN_DEAR;          /* save DEAR and ESR in the frame  */\
+       stw     r12,_DEAR(r11);         /* since they may have had stuff   */\
+       mfspr   r9,SPRN_ESR;            /* in them at the point where the  */\
+       stw     r9,_ESR(r11);           /* exception was taken             */\
+       mfspr   r12,CSRR0;                                                   \
+       stw     r1,GPR1(r11);                                                \
+       mfspr   r9,CSRR1;                                                    \
+       stw     r1,0(r11);                                                   \
+       tovirt(r1,r11);                                                      \
+       rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
+       stw     r0,GPR0(r11);                                                \
+       SAVE_4GPRS(3, r11);                                                  \
+       SAVE_2GPRS(7, r11)
+
+/*
+ * Exception prolog for machine check exceptions.  This is similar to
+ * the critical exception prolog, except that machine check exceptions
+ * have their own save area.  For Book E processors, we also have a
+ * reserved register (SPRG6) that is only used in machine check exceptions
+ * so we can free up a GPR to use as the base for indirect access to the
+ * machine check exception save area.  This is necessary since the MMU
+ * is always on and the save area is offset from KERNELBASE.
+ */
+#define MCHECK_EXCEPTION_PROLOG                                             \
+       mtspr   SPRG6W,r8;              /* SPRG6 used in machine checks */   \
+       lis     r8,mcheck_save@ha;                                           \
+       stw     r10,mcheck_r10@l(r8);                                        \
+       stw     r11,mcheck_r11@l(r8);                                        \
+       mfspr   r10,SPRG0;                                                   \
+       stw     r10,mcheck_sprg0@l(r8);                                      \
+       mfspr   r10,SPRG1;                                                   \
+       stw     r10,mcheck_sprg1@l(r8);                                      \
+       mfspr   r10,SPRG4R;                                                  \
+       stw     r10,mcheck_sprg4@l(r8);                                      \
+       mfspr   r10,SPRG5R;                                                  \
+       stw     r10,mcheck_sprg5@l(r8);                                      \
+       mfspr   r10,SPRG7R;                                                  \
+       stw     r10,mcheck_sprg7@l(r8);                                      \
+       mfspr   r10,SPRN_PID;                                                \
+       stw     r10,mcheck_pid@l(r8);                                        \
+       mfspr   r10,SRR0;                                                    \
+       stw     r10,mcheck_srr0@l(r8);                                       \
+       mfspr   r10,SRR1;                                                    \
+       stw     r10,mcheck_srr1@l(r8);                                       \
+       mfspr   r10,CSRR0;                                                   \
+       stw     r10,mcheck_csrr0@l(r8);                                      \
+       mfspr   r10,CSRR1;                                                   \
+       stw     r10,mcheck_csrr1@l(r8);                                      \
+       mfspr   r8,SPRG6R;              /* SPRG6 used in machine checks */   \
+       mfcr    r10;                    /* save CR in r10 for now          */\
+       mfspr   r11,SPRN_MCSRR1;        /* check whether user or kernel    */\
+       andi.   r11,r11,MSR_PR;                                              \
+       lis     r11,mcheck_stack_top@h;                                      \
+       ori     r11,r11,mcheck_stack_top@l;                                  \
+       beq     1f;                                                          \
+       /* COMING FROM USER MODE */                                          \
+       mfspr   r11,SPRG3;              /* if from user, start at top of   */\
+       lwz     r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
+       addi    r11,r11,THREAD_SIZE;                                         \
+1:     subi    r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame     */\
+       stw     r10,_CCR(r11);          /* save various registers          */\
+       stw     r12,GPR12(r11);                                              \
+       stw     r9,GPR9(r11);                                                \
+       mflr    r10;                                                         \
+       stw     r10,_LINK(r11);                                              \
+       mfspr   r12,SPRN_DEAR;          /* save DEAR and ESR in the frame  */\
+       stw     r12,_DEAR(r11);         /* since they may have had stuff   */\
+       mfspr   r9,SPRN_ESR;            /* in them at the point where the  */\
+       stw     r9,_ESR(r11);           /* exception was taken             */\
+       mfspr   r12,MCSRR0;                                                  \
+       stw     r1,GPR1(r11);                                                \
+       mfspr   r9,MCSRR1;                                                   \
+       stw     r1,0(r11);                                                   \
+       tovirt(r1,r11);                                                      \
+       rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
+       stw     r0,GPR0(r11);                                                \
+       SAVE_4GPRS(3, r11);                                                  \
+       SAVE_2GPRS(7, r11)
+
+/*
+ * Exception vectors.
+ */
+#define        START_EXCEPTION(label)                                               \
+        .align 5;                                                                   \
+label:
+
+#define FINISH_EXCEPTION(func)                                 \
+       bl      transfer_to_handler_full;                       \
+       .long   func;                                           \
+       .long   ret_from_except_full
+
+#define EXCEPTION(n, label, hdlr, xfer)                                \
+       START_EXCEPTION(label);                                 \
+       NORMAL_EXCEPTION_PROLOG;                                \
+       addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
+       xfer(n, hdlr)
+
+#define CRITICAL_EXCEPTION(n, label, hdlr)                     \
+       START_EXCEPTION(label);                                 \
+       CRITICAL_EXCEPTION_PROLOG;                              \
+       addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
+       EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+                         NOCOPY, transfer_to_handler_full, \
+                         ret_from_except_full)
+
+#define MCHECK_EXCEPTION(n, label, hdlr)                       \
+       START_EXCEPTION(label);                                 \
+       MCHECK_EXCEPTION_PROLOG;                                \
+       mfspr   r5,SPRN_ESR;                                    \
+       stw     r5,_ESR(r11);                                   \
+       addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
+       EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+                         NOCOPY, mcheck_transfer_to_handler,   \
+                         ret_from_mcheck_exc)
+
+#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret)  \
+       li      r10,trap;                                       \
+       stw     r10,TRAP(r11);                                  \
+       lis     r10,msr@h;                                      \
+       ori     r10,r10,msr@l;                                  \
+       copyee(r10, r9);                                        \
+       bl      tfer;                                           \
+       .long   hdlr;                                           \
+       .long   ret
+
+#define COPY_EE(d, s)          rlwimi d,s,0,16,16
+#define NOCOPY(d, s)
+
+#define EXC_XFER_STD(n, hdlr)          \
+       EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
+                         ret_from_except_full)
+
+#define EXC_XFER_LITE(n, hdlr)         \
+       EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
+                         ret_from_except)
+
+#define EXC_XFER_EE(n, hdlr)           \
+       EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
+                         ret_from_except_full)
+
+#define EXC_XFER_EE_LITE(n, hdlr)      \
+       EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
+                         ret_from_except)
+
+
+#endif /* __HEAD_BOOKE_H__ */
index ceb51d3..cf96419 100644 (file)
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
 #include <asm/offsets.h>
-
-/*
- * Macros
- */
-
-#define SET_IVOR(vector_number, vector_label)          \
-               li      r26,vector_label@l;             \
-               mtspr   SPRN_IVOR##vector_number,r26;   \
-               sync
+#include "head_booke.h"
 
 /* As with the other PowerPC ports, it is expected that when code
  * execution begins here, the following registers contain valid, yet
@@ -371,232 +363,6 @@ skpinv:   addi    r6,r6,1                         /* Increment */
  * We align on a 32 byte cache line boundary for good measure.
  */
 
-#define NORMAL_EXCEPTION_PROLOG                                                     \
-       mtspr   SPRN_SPRG0,r10;         /* save two registers to work with */\
-       mtspr   SPRN_SPRG1,r11;                                              \
-       mtspr   SPRN_SPRG4W,r1;                                              \
-       mfcr    r10;                    /* save CR in r10 for now          */\
-       mfspr   r11,SPRN_SRR1;          /* check whether user or kernel    */\
-       andi.   r11,r11,MSR_PR;                                              \
-       beq     1f;                                                          \
-       mfspr   r1,SPRG3;               /* if from user, start at top of   */\
-       lwz     r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
-       addi    r1,r1,THREAD_SIZE;                                           \
-1:     subi    r1,r1,INT_FRAME_SIZE;   /* Allocate an exception frame     */\
-       tophys(r11,r1);                                                      \
-       stw     r10,_CCR(r11);          /* save various registers          */\
-       stw     r12,GPR12(r11);                                              \
-       stw     r9,GPR9(r11);                                                \
-       mfspr   r10,SPRG0;                                                   \
-       stw     r10,GPR10(r11);                                              \
-       mfspr   r12,SPRG1;                                                   \
-       stw     r12,GPR11(r11);                                              \
-       mflr    r10;                                                         \
-       stw     r10,_LINK(r11);                                              \
-       mfspr   r10,SPRG4R;                                                  \
-       mfspr   r12,SRR0;                                                    \
-       stw     r10,GPR1(r11);                                               \
-       mfspr   r9,SRR1;                                                     \
-       stw     r10,0(r11);                                                  \
-       rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
-       stw     r0,GPR0(r11);                                                \
-       SAVE_4GPRS(3, r11);                                                  \
-       SAVE_2GPRS(7, r11)
-
-/*
- * Exception prolog for critical exceptions.  This is a little different
- * from the normal exception prolog above since a critical exception
- * can potentially occur at any point during normal exception processing.
- * Thus we cannot use the same SPRG registers as the normal prolog above.
- * Instead we use a couple of words of memory at low physical addresses.
- * This is OK since we don't support SMP on these processors. For Book E
- * processors, we also have a reserved register (SPRG2) that is only used
- * in critical exceptions so we can free up a GPR to use as the base for
- * indirect access to the critical exception save area.  This is necessary
- * since the MMU is always on and the save area is offset from KERNELBASE.
- */
-#define CRITICAL_EXCEPTION_PROLOG                                           \
-       mtspr   SPRG2,r8;               /* SPRG2 only used in criticals */   \
-       lis     r8,crit_save@ha;                                             \
-       stw     r10,crit_r10@l(r8);                                          \
-       stw     r11,crit_r11@l(r8);                                          \
-       mfspr   r10,SPRG0;                                                   \
-       stw     r10,crit_sprg0@l(r8);                                        \
-       mfspr   r10,SPRG1;                                                   \
-       stw     r10,crit_sprg1@l(r8);                                        \
-       mfspr   r10,SPRG4R;                                                  \
-       stw     r10,crit_sprg4@l(r8);                                        \
-       mfspr   r10,SPRG5R;                                                  \
-       stw     r10,crit_sprg5@l(r8);                                        \
-       mfspr   r10,SPRG7R;                                                  \
-       stw     r10,crit_sprg7@l(r8);                                        \
-       mfspr   r10,SPRN_PID;                                                \
-       stw     r10,crit_pid@l(r8);                                          \
-       mfspr   r10,SRR0;                                                    \
-       stw     r10,crit_srr0@l(r8);                                         \
-       mfspr   r10,SRR1;                                                    \
-       stw     r10,crit_srr1@l(r8);                                         \
-       mfspr   r8,SPRG2;               /* SPRG2 only used in criticals */   \
-       mfcr    r10;                    /* save CR in r10 for now          */\
-       mfspr   r11,SPRN_CSRR1;         /* check whether user or kernel    */\
-       andi.   r11,r11,MSR_PR;                                              \
-       lis     r11,critical_stack_top@h;                                    \
-       ori     r11,r11,critical_stack_top@l;                                \
-       beq     1f;                                                          \
-       /* COMING FROM USER MODE */                                          \
-       mfspr   r11,SPRG3;              /* if from user, start at top of   */\
-       lwz     r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-       addi    r11,r11,THREAD_SIZE;                                         \
-1:     subi    r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame     */\
-       stw     r10,_CCR(r11);          /* save various registers          */\
-       stw     r12,GPR12(r11);                                              \
-       stw     r9,GPR9(r11);                                                \
-       mflr    r10;                                                         \
-       stw     r10,_LINK(r11);                                              \
-       mfspr   r12,SPRN_DEAR;          /* save DEAR and ESR in the frame  */\
-       stw     r12,_DEAR(r11);         /* since they may have had stuff   */\
-       mfspr   r9,SPRN_ESR;            /* in them at the point where the  */\
-       stw     r9,_ESR(r11);           /* exception was taken             */\
-       mfspr   r12,CSRR0;                                                   \
-       stw     r1,GPR1(r11);                                                \
-       mfspr   r9,CSRR1;                                                    \
-       stw     r1,0(r11);                                                   \
-       tovirt(r1,r11);                                                      \
-       rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
-       stw     r0,GPR0(r11);                                                \
-       SAVE_4GPRS(3, r11);                                                  \
-       SAVE_2GPRS(7, r11)
-
-/*
- * Exception prolog for machine check exceptions.  This is similar to
- * the critical exception prolog, except that machine check exceptions
- * have their own save area.  For Book E processors, we also have a
- * reserved register (SPRG6) that is only used in machine check exceptions
- * so we can free up a GPR to use as the base for indirect access to the
- * machine check exception save area.  This is necessary since the MMU
- * is always on and the save area is offset from KERNELBASE.
- */
-#define MCHECK_EXCEPTION_PROLOG                                             \
-       mtspr   SPRG6W,r8;              /* SPRG6 used in machine checks */   \
-       lis     r8,mcheck_save@ha;                                           \
-       stw     r10,mcheck_r10@l(r8);                                        \
-       stw     r11,mcheck_r11@l(r8);                                        \
-       mfspr   r10,SPRG0;                                                   \
-       stw     r10,mcheck_sprg0@l(r8);                                      \
-       mfspr   r10,SPRG1;                                                   \
-       stw     r10,mcheck_sprg1@l(r8);                                      \
-       mfspr   r10,SPRG4R;                                                  \
-       stw     r10,mcheck_sprg4@l(r8);                                      \
-       mfspr   r10,SPRG5R;                                                  \
-       stw     r10,mcheck_sprg5@l(r8);                                      \
-       mfspr   r10,SPRG7R;                                                  \
-       stw     r10,mcheck_sprg7@l(r8);                                      \
-       mfspr   r10,SPRN_PID;                                                \
-       stw     r10,mcheck_pid@l(r8);                                        \
-       mfspr   r10,SRR0;                                                    \
-       stw     r10,mcheck_srr0@l(r8);                                       \
-       mfspr   r10,SRR1;                                                    \
-       stw     r10,mcheck_srr1@l(r8);                                       \
-       mfspr   r10,CSRR0;                                                   \
-       stw     r10,mcheck_csrr0@l(r8);                                      \
-       mfspr   r10,CSRR1;                                                   \
-       stw     r10,mcheck_csrr1@l(r8);                                      \
-       mfspr   r8,SPRG6R;              /* SPRG6 used in machine checks */   \
-       mfcr    r10;                    /* save CR in r10 for now          */\
-       mfspr   r11,SPRN_MCSRR1;        /* check whether user or kernel    */\
-       andi.   r11,r11,MSR_PR;                                              \
-       lis     r11,mcheck_stack_top@h;                                      \
-       ori     r11,r11,mcheck_stack_top@l;                                  \
-       beq     1f;                                                          \
-       /* COMING FROM USER MODE */                                          \
-       mfspr   r11,SPRG3;              /* if from user, start at top of   */\
-       lwz     r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-       addi    r11,r11,THREAD_SIZE;                                         \
-1:     subi    r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame     */\
-       stw     r10,_CCR(r11);          /* save various registers          */\
-       stw     r12,GPR12(r11);                                              \
-       stw     r9,GPR9(r11);                                                \
-       mflr    r10;                                                         \
-       stw     r10,_LINK(r11);                                              \
-       mfspr   r12,SPRN_DEAR;          /* save DEAR and ESR in the frame  */\
-       stw     r12,_DEAR(r11);         /* since they may have had stuff   */\
-       mfspr   r9,SPRN_ESR;            /* in them at the point where the  */\
-       stw     r9,_ESR(r11);           /* exception was taken             */\
-       mfspr   r12,MCSRR0;                                                  \
-       stw     r1,GPR1(r11);                                                \
-       mfspr   r9,MCSRR1;                                                   \
-       stw     r1,0(r11);                                                   \
-       tovirt(r1,r11);                                                      \
-       rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
-       stw     r0,GPR0(r11);                                                \
-       SAVE_4GPRS(3, r11);                                                  \
-       SAVE_2GPRS(7, r11)
-
-/*
- * Exception vectors.
- */
-#define        START_EXCEPTION(label)                                               \
-        .align 5;                                                                   \
-label:
-
-#define FINISH_EXCEPTION(func)                                 \
-       bl      transfer_to_handler_full;                       \
-       .long   func;                                           \
-       .long   ret_from_except_full
-
-#define EXCEPTION(n, label, hdlr, xfer)                                \
-       START_EXCEPTION(label);                                 \
-       NORMAL_EXCEPTION_PROLOG;                                \
-       addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
-       xfer(n, hdlr)
-
-#define CRITICAL_EXCEPTION(n, label, hdlr)                     \
-       START_EXCEPTION(label);                                 \
-       CRITICAL_EXCEPTION_PROLOG;                              \
-       addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
-       EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-                         NOCOPY, transfer_to_handler_full, \
-                         ret_from_except_full)
-
-#define MCHECK_EXCEPTION(n, label, hdlr)                       \
-       START_EXCEPTION(label);                                 \
-       MCHECK_EXCEPTION_PROLOG;                                \
-       mfspr   r5,SPRN_ESR;                                    \
-       stw     r5,_ESR(r11);                                   \
-       addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
-       EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-                         NOCOPY, mcheck_transfer_to_handler,   \
-                         ret_from_mcheck_exc)
-
-#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret)  \
-       li      r10,trap;                                       \
-       stw     r10,TRAP(r11);                                  \
-       lis     r10,msr@h;                                      \
-       ori     r10,r10,msr@l;                                  \
-       copyee(r10, r9);                                        \
-       bl      tfer;                                           \
-       .long   hdlr;                                           \
-       .long   ret
-
-#define COPY_EE(d, s)          rlwimi d,s,0,16,16
-#define NOCOPY(d, s)
-
-#define EXC_XFER_STD(n, hdlr)          \
-       EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
-                         ret_from_except_full)
-
-#define EXC_XFER_LITE(n, hdlr)         \
-       EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
-                         ret_from_except)
-
-#define EXC_XFER_EE(n, hdlr)           \
-       EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
-                         ret_from_except_full)
-
-#define EXC_XFER_EE_LITE(n, hdlr)      \
-       EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
-                         ret_from_except)
-
 interrupt_base:
        /* Critical Input Interrupt */
        CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
index 5adb6be..6db80f6 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
+#include <linux/sysctl.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -65,3 +66,36 @@ int cpu_idle(void)
                        default_idle();
        return 0;
 }
+
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx)
+/*
+ * Register the sysctl to set/clear powersave_nap.
+ */
+extern unsigned long powersave_nap;
+
+static ctl_table powersave_nap_ctl_table[]={
+       {
+               .ctl_name       = KERN_PPC_POWERSAVE_NAP,
+               .procname       = "powersave-nap",
+               .data           = &powersave_nap,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+       { 0, },
+};
+static ctl_table powersave_nap_sysctl_root[] = {
+       { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
+       { 0,},
+};
+
+static int __init
+register_powersave_nap_sysctl(void)
+{
+       register_sysctl_table(powersave_nap_sysctl_root, 0);
+
+       return 0;
+}
+
+__initcall(register_powersave_nap_sysctl);
+#endif
index 608f71c..25d009c 100644 (file)
@@ -79,12 +79,12 @@ BEGIN_FTR_SECTION
        /* Now check if user or arch enabled NAP mode */
        lis     r4,powersave_nap@ha
        lwz     r4,powersave_nap@l(r4)
-       cmp   0,r4,0
+       cmpwi   0,r4,0
        beq     1f
        lis     r3,HID0_NAP@h
 1:     
 END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
-       cmp   0,r3,0
+       cmpwi   0,r3,0
        beqlr
 
        /* Clear MSR:EE */
@@ -133,7 +133,7 @@ BEGIN_FTR_SECTION
        /* Go to low speed mode on some 750FX */
        lis     r4,powersave_lowspeed@ha
        lwz     r4,powersave_lowspeed@l(r4)
-       cmp   0,r4,0
+       cmpwi   0,r4,0
        beq     1f
        mfspr   r4,SPRN_HID1
        oris    r4,r4,0x0001
index 538a044..73a58ff 100644 (file)
@@ -56,7 +56,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
        /* Now check if user or arch enabled NAP mode */
        lis     r4,powersave_nap@ha
        lwz     r4,powersave_nap@l(r4)
-       cmp   0,r4,0
+       cmpwi   0,r4,0
        beqlr
 
        /* Clear MSR:EE */
index 4145ff7..08cddde 100644 (file)
@@ -33,6 +33,7 @@
 unsigned long isa_io_base     = 0;
 unsigned long isa_mem_base    = 0;
 unsigned long pci_dram_offset = 0;
+int pcibios_assign_bus_offset = 1;
 
 void pcibios_make_OF_bus_map(void);
 
@@ -45,11 +46,6 @@ static void fixup_broken_pcnet32(struct pci_dev* dev);
 static int reparent_resources(struct resource *parent, struct resource *res);
 static void fixup_rev1_53c810(struct pci_dev* dev);
 static void fixup_cpc710_pci64(struct pci_dev* dev);
-#ifdef CONFIG_PPC_PMAC
-extern void pmac_pci_fixup_cardbus(struct pci_dev* dev);
-extern void pmac_pci_fixup_pciata(struct pci_dev* dev);
-extern void pmac_pci_fixup_k2_sata(struct pci_dev* dev);
-#endif
 #ifdef CONFIG_PPC_OF
 static u8* pci_to_OF_bus_map;
 #endif
@@ -64,20 +60,6 @@ struct pci_controller** hose_tail = &hose_head;
 
 static int pci_bus_count;
 
-struct pci_fixup pcibios_fixups[] = {
-       { PCI_FIXUP_HEADER,     PCI_VENDOR_ID_TRIDENT,  PCI_ANY_ID,                     fixup_broken_pcnet32 },
-       { PCI_FIXUP_HEADER,     PCI_VENDOR_ID_NCR,      PCI_DEVICE_ID_NCR_53C810,       fixup_rev1_53c810 },
-       { PCI_FIXUP_HEADER,     PCI_VENDOR_ID_IBM,      PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64},
-       { PCI_FIXUP_HEADER,     PCI_ANY_ID,             PCI_ANY_ID,                     pcibios_fixup_resources },
-#ifdef CONFIG_PPC_PMAC
-       /* We should add per-machine fixup support in xxx_setup.c or xxx_pci.c */
-       { PCI_FIXUP_FINAL,      PCI_VENDOR_ID_TI,       PCI_ANY_ID,                     pmac_pci_fixup_cardbus },
-       { PCI_FIXUP_FINAL,      PCI_ANY_ID,             PCI_ANY_ID,                     pmac_pci_fixup_pciata },
-       { PCI_FIXUP_HEADER,     PCI_VENDOR_ID_SERVERWORKS, 0x0240,                      pmac_pci_fixup_k2_sata },
-#endif /* CONFIG_PPC_PMAC */
-       { 0 }
-};
-
 static void
 fixup_rev1_53c810(struct pci_dev* dev)
 {
@@ -90,6 +72,7 @@ fixup_rev1_53c810(struct pci_dev* dev)
                dev->class = PCI_CLASS_STORAGE_SCSI;
        }
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR,    PCI_DEVICE_ID_NCR_53C810,       fixup_rev1_53c810);
 
 static void
 fixup_broken_pcnet32(struct pci_dev* dev)
@@ -100,6 +83,7 @@ fixup_broken_pcnet32(struct pci_dev* dev)
                pci_name_device(dev);
        }
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT,        PCI_ANY_ID,                     fixup_broken_pcnet32);
 
 static void
 fixup_cpc710_pci64(struct pci_dev* dev)
@@ -112,6 +96,7 @@ fixup_cpc710_pci64(struct pci_dev* dev)
        dev->resource[1].start = dev->resource[1].end = 0;
        dev->resource[1].flags = 0;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,    PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64);
 
 static void
 pcibios_fixup_resources(struct pci_dev *dev)
@@ -158,9 +143,9 @@ pcibios_fixup_resources(struct pci_dev *dev)
        if (ppc_md.pcibios_fixup_resources)
                ppc_md.pcibios_fixup_resources(dev);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID,           PCI_ANY_ID,                     pcibios_fixup_resources);
 
-void
-pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
                        struct resource *res)
 {
        unsigned long offset = 0;
@@ -173,6 +158,7 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
        region->start = res->start - offset;
        region->end = res->end - offset;
 }
+EXPORT_SYMBOL(pcibios_resource_to_bus);
 
 /*
  * We need to avoid collisions with `mirrored' VGA ports
@@ -187,8 +173,7 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
  * but we want to try to avoid allocating at 0x2900-0x2bff
  * which might have be mirrored at 0x0100-0x03ff..
  */
-void
-pcibios_align_resource(void *data, struct resource *res, unsigned long size,
+void pcibios_align_resource(void *data, struct resource *res, unsigned long size,
                       unsigned long align)
 {
        struct pci_dev *dev = data;
@@ -208,7 +193,7 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size,
                }
        }
 }
-
+EXPORT_SYMBOL(pcibios_align_resource);
 
 /*
  *  Handle resources of PCI devices.  If the world were perfect, we could
@@ -427,7 +412,7 @@ probe_resource(struct pci_bus *parent, struct resource *pr,
                        r = &dev->resource[i];
                        if (!r->flags || (r->flags & IORESOURCE_UNSET))
                                continue;
-                       if (pci_find_parent_resource(bus->self, r) != pr)
+                       if (pci_find_parent_resource(dev, r) != pr)
                                continue;
                        if (r->end >= res->start && res->end >= r->start) {
                                *conflict = r;
@@ -1279,7 +1264,7 @@ pcibios_init(void)
                bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
                hose->last_busno = bus->subordinate;
                if (pci_assign_all_busses || next_busno <= hose->last_busno)
-                       next_busno = hose->last_busno+1;
+                       next_busno = hose->last_busno + pcibios_assign_bus_offset;
        }
        pci_bus_count = next_busno;
 
@@ -1724,6 +1709,32 @@ pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
        res->child = NULL;
 }
 
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (!len)
+               return NULL;
+       if (max && len > max)
+               len = max;
+       if (flags & IORESOURCE_IO)
+               return ioport_map(start, len);
+       if (flags & IORESOURCE_MEM)
+               return (void __iomem *) start;
+       /* What? */
+       return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+       /* Nothing to do */
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
+
+
 /*
  * Null PCI config access functions, for the case when we can't
  * find a hose.
index 91592c0..d8e027f 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/threads.h>
 #include <linux/smp_lock.h>
 #include <linux/seq_file.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -34,9 +35,6 @@
 static int ppc_htab_show(struct seq_file *m, void *v);
 static ssize_t ppc_htab_write(struct file * file, const char __user * buffer,
                              size_t count, loff_t *ppos);
-int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos);
-
 extern PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 extern unsigned long _SDR1;
@@ -438,3 +436,32 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
        *ppos += *lenp;
        return 0;
 }
+
+#ifdef CONFIG_SYSCTL
+/*
+ * Register our sysctl.
+ */
+static ctl_table htab_ctl_table[]={
+       {
+               .ctl_name       = KERN_PPC_L2CR,
+               .procname       = "l2cr",
+               .mode           = 0644,
+               .proc_handler   = &proc_dol2crvec,
+       },
+       { 0, },
+};
+static ctl_table htab_sysctl_root[] = {
+       { 1, "kernel", NULL, 0, 0755, htab_ctl_table, },
+       { 0,},
+};
+
+static int __init
+register_ppc_htab_sysctl(void)
+{
+       register_sysctl_table(htab_sysctl_root, 0);
+
+       return 0;
+}
+
+__initcall(register_ppc_htab_sysctl);
+#endif
index d8fe6b5..82a2134 100644 (file)
@@ -106,7 +106,7 @@ vmaddfp:
 1:     lfsx    fr0,r4,r7
        lfsx    fr1,r5,r7
        lfsx    fr2,r6,r7
-       fmadds  fr0,fr0,fr1,fr2
+       fmadds  fr0,fr0,fr2,fr1
        stfsx   fr0,r3,r7
        addi    r7,r7,4
        bdnz    1b
@@ -133,7 +133,7 @@ vnmsubfp:
 1:     lfsx    fr0,r4,r7
        lfsx    fr1,r5,r7
        lfsx    fr2,r6,r7
-       fnmsubs fr0,fr0,fr1,fr2
+       fnmsubs fr0,fr0,fr2,fr1
        stfsx   fr0,r3,r7
        addi    r7,r7,4
        bdnz    1b
index 74928a7..7874e8a 100644 (file)
@@ -80,13 +80,13 @@ _GLOBAL(csum_partial)
        adde    r0,r0,r5        /* be unnecessary to unroll this loop */
        bdnz    2b
        andi.   r4,r4,3
-3:     cmp   0,r4,2
+3:     cmpwi   0,r4,2
        blt+    4f
        lhz     r5,4(r3)
        addi    r3,r3,2
        subi    r4,r4,2
        adde    r0,r0,r5
-4:     cmp   0,r4,1
+4:     cmpwi   0,r4,1
        bne+    5f
        lbz     r5,4(r3)
        slwi    r5,r5,8         /* Upper byte of word */
@@ -143,7 +143,7 @@ _GLOBAL(csum_partial_copy_generic)
        adde    r0,r0,r9
        bdnz    82b
 13:    andi.   r5,r5,3
-3:     cmp   0,r5,2
+3:     cmpwi   0,r5,2
        blt+    4f
 83:    lhz     r6,4(r3)
        addi    r3,r3,2
@@ -151,7 +151,7 @@ _GLOBAL(csum_partial_copy_generic)
 93:    sth     r6,4(r4)
        addi    r4,r4,2
        adde    r0,r0,r6
-4:     cmp   0,r5,1
+4:     cmpwi   0,r5,1
        bne+    5f
 84:    lbz     r6,4(r3)
 94:    stb     r6,4(r4)
@@ -188,7 +188,7 @@ src_error_3:
 97:    stbu    r6,1(r4)
        bdnz    97b
 src_error:
-       cmp   0,r7,0
+       cmpwi   0,r7,0
        beq     1f
        li      r6,-EFAULT
        stw     r6,0(r7)
@@ -196,7 +196,7 @@ src_error:
        blr
 
 dst_error:
-       cmp   0,r8,0
+       cmpwi   0,r8,0
        beq     1f
        li      r6,-EFAULT
        stw     r6,0(r8)
index 1037656..9991c48 100644 (file)
@@ -216,7 +216,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
 
        /* Grow the after block backwards */
        if (before == NULL && after != NULL) {
-               (int8_t *) after->start -= size;
+               after->start = (int8_t *)after->start - size;
                after->size += size;
                return;
        }
@@ -407,7 +407,7 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
        /* blk still in free list, with updated start and/or size */
        if (bs == s || be == e) {
                if (bs == s)
-                       (int8_t *) blk->start += size;
+                       blk->start = (int8_t *)blk->start + size;
                blk->size -= size;
 
        } else {
@@ -471,7 +471,7 @@ void *rh_alloc(rh_info_t * info, int size, const char *owner)
        newblk->owner = owner;
 
        /* blk still in free list, with updated start, size */
-       (int8_t *) blk->start += size;
+       blk->start = (int8_t *)blk->start + size;
        blk->size -= size;
 
        start = newblk->start;
@@ -535,7 +535,7 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
        /* blk still in free list, with updated start and/or size */
        if (bs == s || be == e) {
                if (bs == s)
-                       (int8_t *) blk->start += size;
+                       blk->start = (int8_t *)blk->start + size;
                blk->size -= size;
 
        } else {
index aeaa1cd..afb82b6 100644 (file)
@@ -82,7 +82,6 @@ do {                                                                  \
        if (X##_e <= _FP_WFRACBITS_##fs)                        \
          {                                                     \
            _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);    \
-           __ret |= _FP_ROUND(wc, X);                          \
            _FP_FRAC_SLL_##wc(X, 1);                            \
            if (_FP_FRAC_OVERP_##wc(fs, X))                     \
              {                                                 \
index 1d79838..a2ab8b0 100644 (file)
@@ -72,7 +72,7 @@ unsigned int tlb_44x_hwater = 62;
 static void __init
 ppc44x_pin_tlb(int slot, unsigned int virt, unsigned int phys)
 {
-       unsigned long attrib;
+       unsigned long attrib = 0;
 
        __asm__ __volatile__("\
        clrrwi  %2,%2,10\n\
index 6066ff3..a7f6161 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/setup.h>
 #include "mmu_decl.h"
 
+extern int __map_without_ltlbs;
 /*
  * MMU_init_hw does the chip-specific initialization of the MMU hardware.
  */
@@ -102,6 +103,10 @@ unsigned long __init mmu_mapin_ram(void)
        p = PPC_MEMSTART;
        s = 0;
 
+       if (__map_without_ltlbs) {
+               return s;
+       }
+
        while (s <= (total_lowmem - LARGE_PAGE_SIZE_16M)) {
                pmd_t *pmdp;
                unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE;
index aada7e4..686dd6d 100644 (file)
@@ -120,10 +120,6 @@ mpc8540ads_setup_arch(void)
        mpc85xx_setup_hose();
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-       conswitchp = &dummy_con;
-#endif
-
 #ifdef CONFIG_SERIAL_8250
        mpc85xx_early_serial_map();
 #endif
index c7e53e3..5eb6e42 100644 (file)
@@ -307,7 +307,7 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
 {
        if (bus == 0 && PCI_SLOT(devfn) == 0)
                return PCIBIOS_DEVICE_NOT_FOUND;
-#if CONFIG_85xx_PCI2
+#ifdef CONFIG_85xx_PCI2
        /* With the current code we know PCI2 will be bus 2, however this may
         * not be guarnteed */
        if (bus == 2 && PCI_SLOT(devfn) == 0)
@@ -358,10 +358,6 @@ mpc85xx_cds_setup_arch(void)
         mpc85xx_setup_hose();
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-        conswitchp = &dummy_con;
-#endif
-
 #ifdef CONFIG_SERIAL_8250
         mpc85xx_early_serial_map();
 #endif
index a4a91aa..50cc50a 100644 (file)
@@ -144,9 +144,6 @@ sbc8560_setup_arch(void)
        /* setup PCI host bridges */
        mpc85xx_setup_hose();
 #endif
-#ifdef CONFIG_DUMMY_CONSOLE
-       conswitchp = &dummy_con;
-#endif
 #ifdef CONFIG_SERIAL_8250
        sbc8560_early_serial_map();
 #endif
index 56be78e..3514bb9 100644 (file)
@@ -250,13 +250,6 @@ chrp_setup_arch(void)
         */
        sio_init();
 
-       /*
-        *  Setup the console operations
-        */
-#ifdef CONFIG_DUMMY_CONSOLE
-       conswitchp = &dummy_con;
-#endif
-
        /* Get the event scan rate for the rtas so we know how
         * often it expects a heartbeat. -- Cort
         */
@@ -382,7 +375,7 @@ void __init chrp_init_IRQ(void)
 {
        struct device_node *np;
        int i;
-       unsigned long chrp_int_ack;
+       unsigned long chrp_int_ack = 0;
        unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
        struct device_node *kbd;
index 71f62a0..863d1e3 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/sections.h>
 #include <asm/io.h>
 #include <asm/prom.h>
index 4e2e18a..8a60203 100644 (file)
@@ -464,10 +464,6 @@ static void __init k2_setup_arch(void)
                ROOT_DEV = Root_HDC1;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-       conswitchp = &dummy_con;
-#endif
-
        /* Identify the system */
        printk(KERN_INFO "System Identification: SBS K2 - PowerPC 750 @ "
                        "%d Mhz\n", k2_get_cpu_speed() / 1000000);
index 043040d..db6ea44 100644 (file)
@@ -36,6 +36,8 @@
 #include <asm/mpc52xx.h>
 
 
+extern int powersave_nap;
+
 /* Board data given by U-Boot */
 bd_t __res;
 EXPORT_SYMBOL(__res);  /* For modules */
@@ -64,25 +66,55 @@ struct ocp_def board_ocp[] = {
                .vendor         = OCP_VENDOR_INVALID
        }
 };
-       
+
 
 /* ======================================================================== */
 /* Platform specific code                                                   */
 /* ======================================================================== */
 
 static int
-icecube_show_cpuinfo(struct seq_file *m)
+lite5200_show_cpuinfo(struct seq_file *m)
 {
        seq_printf(m, "machine\t\t: Freescale LITE5200\n");
        return 0;
 }
 
 static void __init
-icecube_setup_arch(void)
+lite5200_setup_cpu(void)
 {
+       struct mpc52xx_intr *intr;
+
+       u32 intr_ctrl;
+
+       /* Map zones */
+       intr = (struct mpc52xx_intr *)
+               ioremap(MPC52xx_INTR,sizeof(struct mpc52xx_intr));
+
+       if (!intr) {
+               printk("lite5200.c: Error while mapping INTR during lite5200_setup_cpu\n");
+               goto unmap_regs;
+       }
+
+       /* IRQ[0-3] setup : IRQ0     - Level Active Low  */
+       /*                  IRQ[1-3] - Level Active High */
+       intr_ctrl = in_be32(&intr->ctrl);
+       intr_ctrl &= ~0x00ff0000;
+       intr_ctrl |=  0x00c00000;
+       out_be32(&intr->ctrl, intr_ctrl);
+
+       /* Unmap reg zone */
+unmap_regs:
+       if (intr) iounmap(intr);
+}
 
+static void __init
+lite5200_setup_arch(void)
+{
        /* Add board OCP definitions */
        mpc52xx_add_board_devices(board_ocp);
+
+       /* CPU & Port mux setup */
+       lite5200_setup_cpu();
 }
 
 void __init
@@ -110,7 +142,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                        initrd_end = r5 + KERNELBASE;
                }
 #endif
-       
+
                /* Load the command line */
                if (r6) {
                        *(char *)(r7+KERNELBASE) = 0;
@@ -120,14 +152,17 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 
        /* BAT setup */
        mpc52xx_set_bat();
-       
+
        /* No ISA bus AFAIK */
        isa_io_base             = 0;
        isa_mem_base            = 0;
 
+       /* Powersave */
+       powersave_nap = 1;      /* We allow this platform to NAP */
+
        /* Setup the ppc_md struct */
-       ppc_md.setup_arch       = icecube_setup_arch;
-       ppc_md.show_cpuinfo     = icecube_show_cpuinfo;
+       ppc_md.setup_arch       = lite5200_setup_arch;
+       ppc_md.show_cpuinfo     = lite5200_show_cpuinfo;
        ppc_md.show_percpuinfo  = NULL;
        ppc_md.init_IRQ         = mpc52xx_init_irq;
        ppc_md.get_irq          = mpc52xx_get_irq;
@@ -138,12 +173,12 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
        ppc_md.restart          = mpc52xx_restart;
        ppc_md.power_off        = mpc52xx_power_off;
        ppc_md.halt             = mpc52xx_halt;
-       
-               /* No time keeper on the IceCube */
+
+               /* No time keeper on the LITE5200 */
        ppc_md.time_init        = NULL;
        ppc_md.get_rtc_time     = NULL;
        ppc_md.set_rtc_time     = NULL;
-       
+
        ppc_md.calibrate_decr   = mpc52xx_calibrate_decr;
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
        ppc_md.progress         = mpc52xx_progress;
diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c
new file mode 100644 (file)
index 0000000..0037f5c
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * arch/ppc/platforms/lopec.c
+ *
+ * Setup routines for the Motorola LoPEC.
+ *
+ * Author: Dan Cox
+ * Maintainer: Tom Rini <trini@kernel.crashing.org>
+ *
+ * 2001-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.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pci_ids.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/root_dev.h>
+#include <linux/pci.h>
+
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/io.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/hw_irq.h>
+#include <asm/prep_nvram.h>
+#include <asm/kgdb.h>
+
+/*
+ * Define all of the IRQ senses and polarities.  Taken from the
+ * LoPEC Programmer's Reference Guide.
+ */
+static u_char lopec_openpic_initsenses[16] __initdata = {
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* IRQ 0 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* IRQ 1 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* IRQ 2 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* IRQ 3 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* IRQ 4 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* IRQ 5 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* IRQ 6 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* IRQ 7 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* IRQ 8 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* IRQ 9 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* IRQ 10 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* IRQ 11 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* IRQ 12 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* IRQ 13 */
+       (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE),       /* IRQ 14 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE)       /* IRQ 15 */
+};
+
+static inline int __init
+lopec_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+       int irq;
+       static char pci_irq_table[][4] = {
+               {16, 0, 0, 0}, /* ID 11 - Winbond */
+               {22, 0, 0, 0}, /* ID 12 - SCSI */
+               {0, 0, 0, 0}, /* ID 13 - nothing */
+               {17, 0, 0, 0}, /* ID 14 - 82559 Ethernet */
+               {27, 0, 0, 0}, /* ID 15 - USB */
+               {23, 0, 0, 0}, /* ID 16 - PMC slot 1 */
+               {24, 0, 0, 0}, /* ID 17 - PMC slot 2 */
+               {25, 0, 0, 0}, /* ID 18 - PCI slot */
+               {0, 0, 0, 0}, /* ID 19 - nothing */
+               {0, 0, 0, 0}, /* ID 20 - nothing */
+               {0, 0, 0, 0}, /* ID 21 - nothing */
+               {0, 0, 0, 0}, /* ID 22 - nothing */
+               {0, 0, 0, 0}, /* ID 23 - nothing */
+               {0, 0, 0, 0}, /* ID 24 - PMC slot 1b */
+               {0, 0, 0, 0}, /* ID 25 - nothing */
+               {0, 0, 0, 0}  /* ID 26 - PMC Slot 2b */
+       };
+       const long min_idsel = 11, max_idsel = 26, irqs_per_slot = 4;
+
+       irq = PCI_IRQ_TABLE_LOOKUP;
+       if (!irq)
+               return 0;
+
+       return irq;
+}
+
+static void __init
+lopec_setup_winbond_83553(struct pci_controller *hose)
+{
+       int devfn;
+
+       devfn = PCI_DEVFN(11,0);
+
+       /* IDE interrupt routing (primary 14, secondary 15) */
+       early_write_config_byte(hose, 0, devfn, 0x43, 0xef);
+       /* PCI interrupt routing */
+       early_write_config_word(hose, 0, devfn, 0x44, 0x0000);
+
+       /* ISA-PCI address decoder */
+       early_write_config_byte(hose, 0, devfn, 0x48, 0xf0);
+
+       /* RTC, kb, not used in PPC */
+       early_write_config_byte(hose, 0, devfn, 0x4d, 0x00);
+       early_write_config_byte(hose, 0, devfn, 0x4e, 0x04);
+       devfn = PCI_DEVFN(11, 1);
+       early_write_config_byte(hose, 0, devfn, 0x09, 0x8f);
+       early_write_config_dword(hose, 0, devfn, 0x40, 0x00ff0011);
+}
+
+static void __init
+lopec_find_bridges(void)
+{
+       struct pci_controller *hose;
+
+       hose = pcibios_alloc_controller();
+       if (!hose)
+               return;
+
+       hose->first_busno = 0;
+       hose->last_busno = 0xff;
+
+       if (mpc10x_bridge_init(hose, MPC10X_MEM_MAP_B, MPC10X_MEM_MAP_B,
+                               MPC10X_MAPB_EUMB_BASE) == 0) {
+
+               hose->mem_resources[0].end = 0xffffffff;
+               lopec_setup_winbond_83553(hose);
+               hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+               ppc_md.pci_swizzle = common_swizzle;
+               ppc_md.pci_map_irq = lopec_map_irq;
+       }
+}
+
+static int
+lopec_show_cpuinfo(struct seq_file *m)
+{
+       seq_printf(m, "machine\t\t: Motorola LoPEC\n");
+       return 0;
+}
+
+static u32
+lopec_irq_canonicalize(u32 irq)
+{
+       if (irq == 2)
+               return 9;
+       else
+               return irq;
+}
+
+static void
+lopec_restart(char *cmd)
+{
+#define LOPEC_SYSSTAT1 0xffe00000
+       /* force a hard reset, if possible */
+       unsigned char reg = *((unsigned char *) LOPEC_SYSSTAT1);
+       reg |= 0x80;
+       *((unsigned char *) LOPEC_SYSSTAT1) = reg;
+
+       local_irq_disable();
+       while(1);
+#undef LOPEC_SYSSTAT1
+}
+
+static void
+lopec_halt(void)
+{
+       local_irq_disable();
+       while(1);
+}
+
+static void
+lopec_power_off(void)
+{
+       lopec_halt();
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+int lopec_ide_ports_known = 0;
+static unsigned long lopec_ide_regbase[MAX_HWIFS];
+static unsigned long lopec_ide_ctl_regbase[MAX_HWIFS];
+static unsigned long lopec_idedma_regbase;
+
+static void
+lopec_ide_probe(void)
+{
+       struct pci_dev *dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
+                                             PCI_DEVICE_ID_WINBOND_82C105,
+                                             NULL);
+       lopec_ide_ports_known = 1;
+
+       if (dev) {
+               lopec_ide_regbase[0] = dev->resource[0].start;
+               lopec_ide_regbase[1] = dev->resource[2].start;
+               lopec_ide_ctl_regbase[0] = dev->resource[1].start;
+               lopec_ide_ctl_regbase[1] = dev->resource[3].start;
+               lopec_idedma_regbase = dev->resource[4].start;
+       }
+}
+
+static int
+lopec_ide_default_irq(unsigned long base)
+{
+       if (lopec_ide_ports_known == 0)
+               lopec_ide_probe();
+
+       if (base == lopec_ide_regbase[0])
+               return 14;
+       else if (base == lopec_ide_regbase[1])
+               return 15;
+       else
+               return 0;
+}
+
+static unsigned long
+lopec_ide_default_io_base(int index)
+{
+       if (lopec_ide_ports_known == 0)
+               lopec_ide_probe();
+       return lopec_ide_regbase[index];
+}
+
+static void __init
+lopec_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data,
+                         unsigned long ctl, int *irq)
+{
+       unsigned long reg = data;
+       uint alt_status_base;
+       int i;
+
+       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+               hw->io_ports[i] = reg++;
+
+       if (data == lopec_ide_regbase[0]) {
+               alt_status_base = lopec_ide_ctl_regbase[0] + 2;
+               hw->irq = 14;
+       } else if (data == lopec_ide_regbase[1]) {
+               alt_status_base = lopec_ide_ctl_regbase[1] + 2;
+               hw->irq = 15;
+       } else {
+               alt_status_base = 0;
+               hw->irq = 0;
+       }
+
+       if (ctl)
+               hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
+       else
+               hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+
+       if (irq != NULL)
+               *irq = hw->irq;
+
+}
+#endif /* BLK_DEV_IDE */
+
+static void __init
+lopec_init_IRQ(void)
+{
+       int i;
+
+       /*
+        * Provide the open_pic code with the correct table of interrupts.
+        */
+       OpenPIC_InitSenses = lopec_openpic_initsenses;
+       OpenPIC_NumInitSenses = sizeof(lopec_openpic_initsenses);
+
+       mpc10x_set_openpic();
+
+       /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+       openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+                       &i8259_irq);
+
+       /* Map i8259 interrupts */
+       for(i = 0; i < NUM_8259_INTERRUPTS; i++)
+               irq_desc[i].handler = &i8259_pic;
+
+       /*
+        * The EPIC allows for a read in the range of 0xFEF00000 ->
+        * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
+        */
+       i8259_init(0xfef00000);
+}
+
+static int __init
+lopec_request_io(void)
+{
+       outb(0x00, 0x4d0);
+       outb(0xc0, 0x4d1);
+
+       request_region(0x00, 0x20, "dma1");
+       request_region(0x20, 0x20, "pic1");
+       request_region(0x40, 0x20, "timer");
+       request_region(0x80, 0x10, "dma page reg");
+       request_region(0xa0, 0x20, "pic2");
+       request_region(0xc0, 0x20, "dma2");
+
+       return 0;
+}
+
+device_initcall(lopec_request_io);
+
+static void __init
+lopec_map_io(void)
+{
+       io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+       io_block_mapping(0xb0000000, 0xb0000000, 0x10000000, _PAGE_IO);
+}
+
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+lopec_set_bat(void)
+{
+       mb();
+       mtspr(DBAT1U, 0xf8000ffe);
+       mtspr(DBAT1L, 0xf800002a);
+       mb();
+}
+
+TODC_ALLOC();
+
+static void __init
+lopec_setup_arch(void)
+{
+
+       TODC_INIT(TODC_TYPE_MK48T37, 0, 0,
+                 ioremap(0xffe80000, 0x8000), 8);
+
+       loops_per_jiffy = 100000000/HZ;
+
+       lopec_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (initrd_start)
+               ROOT_DEV = Root_RAM0;
+       else
+#elif defined(CONFIG_ROOT_NFS)
+               ROOT_DEV = Root_NFS;
+#elif defined(CONFIG_BLK_DEV_IDEDISK)
+               ROOT_DEV = Root_HDA1;
+#else
+               ROOT_DEV = Root_SDA1;
+#endif
+
+#ifdef CONFIG_PPCBUG_NVRAM
+       /* Read in NVRAM data */
+       init_prep_nvram();
+
+       /* if no bootargs, look in NVRAM */
+       if ( cmd_line[0] == '\0' ) {
+               char *bootargs;
+                bootargs = prep_nvram_get_var("bootargs");
+                if (bootargs != NULL) {
+                        strcpy(cmd_line, bootargs);
+                        /* again.. */
+                        strcpy(saved_command_line, cmd_line);
+               }
+       }
+#endif
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+             unsigned long r6, unsigned long r7)
+{
+       parse_bootinfo(find_bootinfo());
+       lopec_set_bat();
+
+       isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+       isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+       pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+       ISA_DMA_THRESHOLD = 0x00ffffff;
+       DMA_MODE_READ = 0x44;
+       DMA_MODE_WRITE = 0x48;
+
+       ppc_md.setup_arch = lopec_setup_arch;
+       ppc_md.show_cpuinfo = lopec_show_cpuinfo;
+       ppc_md.irq_canonicalize = lopec_irq_canonicalize;
+       ppc_md.init_IRQ = lopec_init_IRQ;
+       ppc_md.get_irq = openpic_get_irq;
+
+       ppc_md.restart = lopec_restart;
+       ppc_md.power_off = lopec_power_off;
+       ppc_md.halt = lopec_halt;
+
+       ppc_md.setup_io_mappings = lopec_map_io;
+
+       ppc_md.time_init = todc_time_init;
+       ppc_md.set_rtc_time = todc_set_rtc_time;
+       ppc_md.get_rtc_time = todc_get_rtc_time;
+       ppc_md.calibrate_decr = todc_calibrate_decr;
+
+       ppc_md.nvram_read_val = todc_direct_read_val;
+       ppc_md.nvram_write_val = todc_direct_write_val;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+       ppc_ide_md.default_irq = lopec_ide_default_irq;
+       ppc_ide_md.default_io_base = lopec_ide_default_io_base;
+       ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports;
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+       ppc_md.progress = gen550_progress;
+#endif
+}
diff --git a/arch/ppc/platforms/lopec.h b/arch/ppc/platforms/lopec.h
new file mode 100644 (file)
index 0000000..5490edb
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * include/asm-ppc/lopec_serial.h
+ *
+ * Definitions for Motorola LoPEC board.
+ *
+ * Author: Dan Cox
+ *         danc@mvista.com (or, alternately, source@mvista.com)
+ *
+ * 2001 (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 __H_LOPEC_SERIAL
+#define __H_LOPEC_SERIAL
+
+#define RS_TABLE_SIZE 3
+
+#define BASE_BAUD (1843200 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+#define SERIAL_PORT_DFNS \
+         { 0, BASE_BAUD, 0xffe10000, 29, STD_COM_FLAGS, \
+           iomem_base: (u8 *) 0xffe10000, \
+           io_type: SERIAL_IO_MEM }, \
+         { 0, BASE_BAUD, 0xffe11000, 20, STD_COM_FLAGS, \
+           iomem_base: (u8 *) 0xffe11000, \
+           io_type: SERIAL_IO_MEM }, \
+         { 0, BASE_BAUD, 0xffe12000, 21, STD_COM_FLAGS, \
+           iomem_base: (u8 *) 0xffe12000, \
+           io_type: SERIAL_IO_MEM }
+
+#endif
index 06ed938..348118b 100644 (file)
@@ -58,8 +58,6 @@
 #include <asm/kgdb.h>
 
 #include "mcpn765.h"
-#include "mcpn765_serial.h"
-
 
 static u_char mcpn765_openpic_initsenses[] __initdata = {
        (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),/* 16: i8259 cascade */
@@ -324,10 +322,6 @@ mcpn765_setup_arch(void)
                ROOT_DEV = Root_SDA2;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-       conswitchp = &dummy_con;
-#endif
-
        if ( ppc_md.progress )
                ppc_md.progress("mcpn765_setup_arch: find_bridges", 0);
 
index 8723383..4d35eca 100644 (file)
@@ -6,7 +6,7 @@
  * Author: Mark A. Greer
  *         mgreer@mvista.com
  *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
+ * 2001-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.
@@ -25,6 +25,7 @@
 
 #ifndef __PPC_PLATFORMS_MCPN765_H
 #define __PPC_PLATFORMS_MCPN765_H
+#include <linux/config.h>
 
 /* PCI Memory space mapping info */
 #define        MCPN765_PCI_MEM_SIZE            0x40000000U
 #define        MCPN765_BOARD_EXT_FEATURE_REG   0xfef880f0U
 #define        MCPN765_BOARD_LAST_RESET_REG    0xfef880f8U
 
-/* UART base addresses are defined in <asm-ppc/platforms/mcpn765_serial.h> */
+/* Defines for UART */
+
+/* Define the UART base addresses */
+#define        MCPN765_SERIAL_1                0xfef88000
+#define        MCPN765_SERIAL_2                0xfef88200
+#define        MCPN765_SERIAL_3                0xfef88400
+#define        MCPN765_SERIAL_4                0xfef88600
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  4
+#endif
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD      ( 1843200 / 16 )
+#define UART_CLK       1843200
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+/* All UART IRQ's are wire-OR'd to IRQ 17 */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, MCPN765_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */\
+               iomem_base: (u8 *)MCPN765_SERIAL_1,                     \
+               iomem_reg_shift: 4,                                     \
+               io_type: SERIAL_IO_MEM },                               \
+        { 0, BASE_BAUD, MCPN765_SERIAL_2, 17, STD_COM_FLAGS, /* ttyS1 */\
+               iomem_base: (u8 *)MCPN765_SERIAL_2,                     \
+               iomem_reg_shift: 4,                                     \
+               io_type: SERIAL_IO_MEM },                               \
+        { 0, BASE_BAUD, MCPN765_SERIAL_3, 17, STD_COM_FLAGS, /* ttyS2 */\
+               iomem_base: (u8 *)MCPN765_SERIAL_3,                     \
+               iomem_reg_shift: 4,                                     \
+               io_type: SERIAL_IO_MEM },                               \
+        { 0, BASE_BAUD, MCPN765_SERIAL_4, 17, STD_COM_FLAGS, /* ttyS3 */\
+               iomem_base: (u8 *)MCPN765_SERIAL_4,                     \
+               iomem_reg_shift: 4,                                     \
+               io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
 
 /* Define the NVRAM/RTC address strobe & data registers */
 #define MCPN765_PHYS_NVRAM_AS0          0xfef880c8U
 #define MCPN765_PHYS_NVRAM_AS1          0xfef880d0U
 #define MCPN765_PHYS_NVRAM_DATA         0xfef880d8U
 
-
 extern void mcpn765_find_bridges(void);
 
 #endif /* __PPC_PLATFORMS_MCPN765_H */
index 30b6936..dce7225 100644 (file)
 #include <asm/ocp.h>
 #include <asm/mpc52xx.h>
 
+
+struct ocp_fs_i2c_data mpc5200_i2c_def = {
+        .flags  = FS_I2C_CLOCK_5200,
+};
+
+
 /* Here is the core_ocp struct.
  * With all the devices common to all board. Even if port multiplexing is
  * not setup for them (if the user don't want them, just don't select the
  * board specific file.
  */
 struct ocp_def core_ocp[] = {
+       {
+               .vendor         = OCP_VENDOR_FREESCALE,
+               .function       = OCP_FUNC_IIC,
+               .index          = 0,
+               .paddr          = MPC52xx_I2C1,
+               .irq            = OCP_IRQ_NA,   /* MPC52xx_IRQ_I2C1 - Buggy */
+               .pm             = OCP_CPM_NA,
+               .additions      = &mpc5200_i2c_def,
+       },
+       {
+               .vendor         = OCP_VENDOR_FREESCALE,
+               .function       = OCP_FUNC_IIC,
+               .index          = 1,
+               .paddr          = MPC52xx_I2C2,
+               .irq            = OCP_IRQ_NA,   /* MPC52xx_IRQ_I2C2 - Buggy */
+               .pm             = OCP_CPM_NA,
+               .additions      = &mpc5200_i2c_def,
+       },
        {       /* Terminating entry */
                .vendor         = OCP_VENDOR_INVALID
        }
diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c
new file mode 100644 (file)
index 0000000..b08be24
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * arch/ppc/platforms/mvme5100.c
+ *
+ * Board setup routines for the Motorola MVME5100.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001-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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/pci-bridge.h>
+#include <asm/bootinfo.h>
+#include <asm/hawk.h>
+
+#include <platforms/pplus.h>
+#include <platforms/mvme5100.h>
+
+static u_char mvme5100_openpic_initsenses[16] __initdata = {
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* i8259 cascade */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* TL16C550 UART 1,2 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet1 front panel or P2 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Hawk Watchdog 1,2 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* DS1621 thermal alarm */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT0# */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT1# */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT2# */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT3# */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTA#, PMC2 INTB# */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTB#, PMC2 INTC# */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTC#, PMC2 INTD# */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTD#, PMC2 INTA# */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet 2 (front panel) */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Abort Switch */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* RTC Alarm */
+};
+
+static inline int
+mvme5100_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+       int irq;
+
+       static char pci_irq_table[][4] =
+       /*
+        *      PCI IDSEL/INTPIN->INTLINE
+        *         A   B   C   D
+        */
+       {
+               {  0,  0,  0,  0 },     /* IDSEL 11 - Winbond */
+               {  0,  0,  0,  0 },     /* IDSEL 12 - unused */
+               { 21, 22, 23, 24 },     /* IDSEL 13 - Universe II */
+               { 18,  0,  0,  0 },     /* IDSEL 14 - Enet 1 */
+               {  0,  0,  0,  0 },     /* IDSEL 15 - unused */
+               { 25, 26, 27, 28 },     /* IDSEL 16 - PMC Slot 1 */
+               { 28, 25, 26, 27 },     /* IDSEL 17 - PMC Slot 2 */
+               {  0,  0,  0,  0 },     /* IDSEL 18 - unused */
+               { 29,  0,  0,  0 },     /* IDSEL 19 - Enet 2 */
+               {  0,  0,  0,  0 },     /* IDSEL 20 - PMCSPAN */
+       };
+
+       const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4;
+       irq = PCI_IRQ_TABLE_LOOKUP;
+       /* If lookup is zero, always return 0 */
+       if (!irq)
+               return 0;
+       else
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+       /* If IPMC761 present, return table value */
+       return irq;
+#else
+       /* If IPMC761 not present, we don't have an i8259 so adjust */
+       return (irq - NUM_8259_INTERRUPTS);
+#endif
+}
+
+static void
+mvme5100_pcibios_fixup_resources(struct pci_dev *dev)
+{
+       int i;
+
+       if ((dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
+                       (dev->device == PCI_DEVICE_ID_MOTOROLA_HAWK))
+               for (i=0; i<DEVICE_COUNT_RESOURCE; i++)
+               {
+                       dev->resource[i].start = 0;
+                       dev->resource[i].end = 0;
+               }
+}
+
+static void __init
+mvme5100_setup_bridge(void)
+{
+       struct pci_controller*  hose;
+
+       hose = pcibios_alloc_controller();
+
+       if (!hose)
+               return;
+
+       hose->first_busno = 0;
+       hose->last_busno = 0xff;
+       hose->pci_mem_offset = MVME5100_PCI_MEM_OFFSET;
+
+       pci_init_resource(&hose->io_resource, MVME5100_PCI_LOWER_IO,
+                       MVME5100_PCI_UPPER_IO, IORESOURCE_IO,
+                       "PCI host bridge");
+
+       pci_init_resource(&hose->mem_resources[0], MVME5100_PCI_LOWER_MEM,
+                       MVME5100_PCI_UPPER_MEM, IORESOURCE_MEM,
+                       "PCI host bridge");
+
+       hose->io_space.start = MVME5100_PCI_LOWER_IO;
+       hose->io_space.end = MVME5100_PCI_UPPER_IO;
+       hose->mem_space.start = MVME5100_PCI_LOWER_MEM;
+       hose->mem_space.end = MVME5100_PCI_UPPER_MEM;
+       hose->io_base_virt = (void *)MVME5100_ISA_IO_BASE;
+
+       /* Use indirect method of Hawk */
+       setup_indirect_pci(hose, MVME5100_PCI_CONFIG_ADDR,
+                       MVME5100_PCI_CONFIG_DATA);
+
+       hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+       ppc_md.pcibios_fixup_resources = mvme5100_pcibios_fixup_resources;
+       ppc_md.pci_swizzle = common_swizzle;
+       ppc_md.pci_map_irq = mvme5100_map_irq;
+}
+
+static void __init
+mvme5100_setup_arch(void)
+{
+       if ( ppc_md.progress )
+               ppc_md.progress("mvme5100_setup_arch: enter", 0);
+
+       loops_per_jiffy = 50000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (initrd_start)
+               ROOT_DEV = Root_RAM0;
+       else
+#endif
+#ifdef CONFIG_ROOT_NFS
+               ROOT_DEV = Root_NFS;
+#else
+               ROOT_DEV = Root_SDA2;
+#endif
+
+       if ( ppc_md.progress )
+               ppc_md.progress("mvme5100_setup_arch: find_bridges", 0);
+
+       /* Setup PCI host bridge */
+       mvme5100_setup_bridge();
+
+       /* Find and map our OpenPIC */
+       hawk_mpic_init(MVME5100_PCI_MEM_OFFSET);
+       OpenPIC_InitSenses = mvme5100_openpic_initsenses;
+       OpenPIC_NumInitSenses = sizeof(mvme5100_openpic_initsenses);
+
+       printk("MVME5100 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
+
+       if ( ppc_md.progress )
+               ppc_md.progress("mvme5100_setup_arch: exit", 0);
+
+       return;
+}
+
+static void __init
+mvme5100_init2(void)
+{
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+               request_region(0x00,0x20,"dma1");
+               request_region(0x20,0x20,"pic1");
+               request_region(0x40,0x20,"timer");
+               request_region(0x80,0x10,"dma page reg");
+               request_region(0xa0,0x20,"pic2");
+               request_region(0xc0,0x20,"dma2");
+#endif
+       return;
+}
+
+/*
+ * Interrupt setup and service.
+ * Have MPIC on HAWK and cascaded 8259s on Winbond cascaded to MPIC.
+ */
+static void __init
+mvme5100_init_IRQ(void)
+{
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+       int i;
+#endif
+
+       if ( ppc_md.progress )
+               ppc_md.progress("init_irq: enter", 0);
+
+       openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+       openpic_init(NUM_8259_INTERRUPTS);
+       openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+                       &i8259_irq);
+
+       /* Map i8259 interrupts. */
+       for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+               irq_desc[i].handler = &i8259_pic;
+
+       i8259_init(NULL);
+#else
+       openpic_init(0);
+#endif
+
+       if ( ppc_md.progress )
+               ppc_md.progress("init_irq: exit", 0);
+
+       return;
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void
+mvme5100_set_bat(void)
+{
+       mb();
+       mtspr(DBAT1U, 0xf0001ffe);
+       mtspr(DBAT1L, 0xf000002a);
+       mb();
+}
+
+static unsigned long __init
+mvme5100_find_end_of_memory(void)
+{
+       return hawk_get_mem_size(MVME5100_HAWK_SMC_BASE);
+}
+
+static void __init
+mvme5100_map_io(void)
+{
+       io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+       ioremap_base = 0xfe000000;
+}
+
+static void
+mvme5100_reset_board(void)
+{
+       local_irq_disable();
+
+       /* Set exception prefix high - to the firmware */
+       _nmask_and_or_msr(0, MSR_IP);
+
+       out_8((u_char *)MVME5100_BOARD_MODRST_REG, 0x01);
+
+       return;
+}
+
+static void
+mvme5100_restart(char *cmd)
+{
+       volatile ulong i = 10000000;
+
+       mvme5100_reset_board();
+
+       while (i-- > 0);
+       panic("restart failed\n");
+}
+
+static void
+mvme5100_halt(void)
+{
+       local_irq_disable();
+       while (1);
+}
+
+static void
+mvme5100_power_off(void)
+{
+       mvme5100_halt();
+}
+
+static int
+mvme5100_show_cpuinfo(struct seq_file *m)
+{
+       seq_printf(m, "vendor\t\t: Motorola\n");
+       seq_printf(m, "machine\t\t: MVME5100\n");
+
+       return 0;
+}
+
+TODC_ALLOC();
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+             unsigned long r6, unsigned long r7)
+{
+       parse_bootinfo(find_bootinfo());
+       mvme5100_set_bat();
+
+       isa_io_base = MVME5100_ISA_IO_BASE;
+       isa_mem_base = MVME5100_ISA_MEM_BASE;
+       pci_dram_offset = MVME5100_PCI_DRAM_OFFSET;
+
+       ppc_md.setup_arch = mvme5100_setup_arch;
+       ppc_md.show_cpuinfo = mvme5100_show_cpuinfo;
+       ppc_md.init_IRQ = mvme5100_init_IRQ;
+       ppc_md.get_irq = openpic_get_irq;
+       ppc_md.init = mvme5100_init2;
+
+       ppc_md.restart = mvme5100_restart;
+       ppc_md.power_off = mvme5100_power_off;
+       ppc_md.halt = mvme5100_halt;
+
+       ppc_md.find_end_of_memory = mvme5100_find_end_of_memory;
+       ppc_md.setup_io_mappings = mvme5100_map_io;
+
+       TODC_INIT(TODC_TYPE_MK48T37, MVME5100_NVRAM_AS0, MVME5100_NVRAM_AS1,
+                       MVME5100_NVRAM_DATA, 8);
+
+       ppc_md.time_init = todc_time_init;
+       ppc_md.set_rtc_time = todc_set_rtc_time;
+       ppc_md.get_rtc_time = todc_get_rtc_time;
+       ppc_md.calibrate_decr = todc_calibrate_decr;
+
+       ppc_md.nvram_read_val = todc_m48txx_read_val;
+       ppc_md.nvram_write_val = todc_m48txx_write_val;
+}
index 5cc61d1..edd4794 100644 (file)
 #define MVME5100_SERIAL_IRQ            1
 #endif
 
-#define MVME5100_WINBOND_DEVFN         0x58
-#define MVME5100_WINBOND_VIDDID                0x056510ad
+#define RS_TABLE_SIZE  4
 
-extern void mvme5100_setup_bridge(void);
+#define BASE_BAUD ( MVME5100_BASE_BAUD / 16 )
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+/* All UART IRQ's are wire-OR'd to one MPIC IRQ */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, MVME5100_SERIAL_1, \
+               MVME5100_SERIAL_IRQ, \
+               STD_COM_FLAGS, /* ttyS0 */ \
+               iomem_base: (unsigned char *)MVME5100_SERIAL_1,         \
+               iomem_reg_shift: 4,                                     \
+               io_type: SERIAL_IO_MEM },                               \
+        { 0, BASE_BAUD, MVME5100_SERIAL_2, \
+               MVME5100_SERIAL_IRQ, \
+               STD_COM_FLAGS, /* ttyS1 */ \
+               iomem_base: (unsigned char *)MVME5100_SERIAL_2,         \
+               iomem_reg_shift: 4,                                     \
+               io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
 
 #endif /* __ASM_MVME5100_H__ */
 #endif /* __KERNEL__ */
index 9c42872..da022ec 100644 (file)
@@ -228,10 +228,6 @@ pcore_setup_arch(void)
                ROOT_DEV = Root_SDA2;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-       conswitchp = &dummy_con;
-#endif
-
        printk(KERN_INFO "Force PowerCore ");
        if (board_type == PCORE_TYPE_6750)
                printk("6750\n");
index 9dcc4e2..4e53bea 100644 (file)
@@ -50,6 +50,7 @@ static struct pci_controller *u3_agp;
 #endif /* CONFIG_POWER4 */
 
 extern u8 pci_cache_line_size;
+extern int pcibios_assign_bus_offset;
 
 struct pci_dev *k2_skiplist[2];
 
@@ -315,6 +316,10 @@ u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
        unsigned int addr;
        int i;
 
+       struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
+       if (np == NULL)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
        /*
         * When a device in K2 is powered down, we die on config
         * cycle accesses. Fix that here.
@@ -362,6 +367,9 @@ u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
        unsigned int addr;
        int i;
 
+       struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
+       if (np == NULL)
+               return PCIBIOS_DEVICE_NOT_FOUND;
        /*
         * When a device in K2 is powered down, we die on config
         * cycle accesses. Fix that here.
@@ -565,6 +573,14 @@ pmac_find_bridges(void)
 
        init_p2pbridge();
        fixup_nec_usb2();
+       
+       /* We are still having some issues with the Xserve G4, enabling
+        * some offset between bus number and domains for now when we
+        * assign all busses should help for now
+        */
+       if (pci_assign_all_busses)
+               pcibios_assign_bus_offset = 0x10;
+
 #ifdef CONFIG_POWER4 
        /* There is something wrong with DMA on U3/HT. I haven't figured out
         * the details yet, but if I set the cache line size to 128 bytes like
@@ -707,7 +723,7 @@ setup_u3_ht(struct pci_controller* hose, struct reg_property *addr)
         * properties or figuring out the U3 address space decoding logic and
         * then read its configuration register (if any).
         */
-       hose->io_base_phys = 0xf4000000 + 0x00400000;
+       hose->io_base_phys = 0xf4000000;
        hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);
        isa_io_base = (unsigned long) hose->io_base_virt;
        hose->io_resource.name = np->full_name;
@@ -1034,6 +1050,8 @@ void pmac_pci_fixup_cardbus(struct pci_dev* dev)
        }
 }
 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus);
+
 void pmac_pci_fixup_pciata(struct pci_dev* dev)
 {
        u8 progif = 0;
@@ -1074,6 +1092,8 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev)
                        printk(KERN_ERR "Rewrite of PROGIF failed !\n");
        }
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
+
 
 /*
  * Disable second function on K2-SATA, it's broken
@@ -1104,3 +1124,4 @@ void __pmac pmac_pci_fixup_k2_sata(struct pci_dev* dev)
                }
        }
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata);
index 7047422..1a300ff 100644 (file)
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/sections.h>
 #include <asm/io.h>
 #include <asm/prom.h>
index cd8e3e7..0963654 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/pmu.h>
+#include <linux/hardirq.h>
 
 #include <asm/sections.h>
 #include <asm/prom.h>
@@ -26,7 +27,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
-#include <asm/hardirq.h>
 #include <asm/time.h>
 #include <asm/nvram.h>
 
index b834e17..41a6dc8 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Borrowed heavily from prpmc750.h by Matt Porter <mporter@mvista.com>
  *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
+ * 2001-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.
@@ -16,8 +16,6 @@
 #ifndef __ASMPPC_POWERPMC250_H
 #define __ASMPPC_POWERPMC250_H
 
-#include <linux/serial_reg.h>
-
 #define POWERPMC250_PCI_CONFIG_ADDR    0x80000cf8
 #define POWERPMC250_PCI_CONFIG_DATA    0x80000cfc
 
 #define POWERPMC250_SERIAL             0xff000000
 #define POWERPMC250_SERIAL_IRQ         20
 
+/* UART Defines. */
+#define RS_TABLE_SIZE  1
+
+#define BASE_BAUD  (POWERPMC250_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+#define SERIAL_PORT_DFNS \
+       { 0, BASE_BAUD, POWERPMC250_SERIAL, POWERPMC250_SERIAL_IRQ,     \
+               STD_COM_FLAGS,                          /* ttyS0 */     \
+               iomem_base: (u8 *)POWERPMC250_SERIAL,                   \
+               iomem_reg_shift: 0,                                     \
+               io_type: SERIAL_IO_MEM }
+
 #endif /* __ASMPPC_POWERPMC250_H */
diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c
new file mode 100644 (file)
index 0000000..cecaba6
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * arch/ppc/platforms/pq2ads.c
+ *
+ * PQ2ADS platform support
+ *
+ * Author: Kumar Gala <kumar.gala@freescale.com>
+ * Derived from: est8260_setup.c by Allen Curtis
+ *
+ * Copyright 2004 Freescale Semiconductor, 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.
+ */
+
+#include <linux/init.h>
+
+#include <asm/mpc8260.h>
+
+void __init
+m82xx_board_init(void)
+{
+       /* Enable the 2nd UART port */
+        *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2;
+}
index 1bee6ca..0c17a0c 100644 (file)
 
 #define BOOTROM_RESTART_ADDR   ((uint)0xff000104)
 
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR         "Motorola"
+#define CPUINFO_MACHINE                "PQ2 ADS PowerPC"
+
 /* The ADS8260 has 16, 32-bit wide control/status registers, accessed
  * only on word boundaries.
  * Not all are used (yet), or are interesting to us (yet).
index 58775fc..a528562 100644 (file)
@@ -836,52 +836,59 @@ struct mot_info {
 void __init
 ibm_prep_init(void)
 {
-#ifdef CONFIG_PREP_RESIDUAL
-       u32 addr, real_addr, len;
-       PPC_DEVICE *mpic;
-       PnP_TAG_PACKET *pkt;
-
-       /* Use the PReP residual data to determine if an OpenPIC is
-        * present.  If so, get the large vendor packet which will
-        * tell us the base address and length in memory.
-        * If we are successful, ioremap the memory area and set
-        * OpenPIC_Addr (this indicates that the OpenPIC was found).
-        */
-       mpic = residual_find_device(-1, NULL, SystemPeripheral,
-                           ProgrammableInterruptController, MPIC, 0);
-       if (!mpic)
-               return;
+       if (have_residual_data) {
+               u32 addr, real_addr, len, offset;
+               PPC_DEVICE *mpic;
+               PnP_TAG_PACKET *pkt;
+
+               /* Use the PReP residual data to determine if an OpenPIC is
+                * present.  If so, get the large vendor packet which will
+                * tell us the base address and length in memory.
+                * If we are successful, ioremap the memory area and set
+                * OpenPIC_Addr (this indicates that the OpenPIC was found).
+                */
+               mpic = residual_find_device(-1, NULL, SystemPeripheral,
+                                   ProgrammableInterruptController, MPIC, 0);
+               if (!mpic)
+                       return;
 
-       pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
-                       mpic->AllocatedOffset, 9, 0);
+               pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+                               mpic->AllocatedOffset, 9, 0);
 
-       if (!pkt)
-               return;
+               if (!pkt)
+                       return;
 
 #define p pkt->L4_Pack.L4_Data.L4_PPCPack
-       if (!((p.PPCData[0] == 2) && (p.PPCData[1] == 32)))
-               return; /* not a 32-bit memory address */
+               if (p.PPCData[1] == 32) {
+                       switch (p.PPCData[0]) {
+                               case 1:  offset = PREP_ISA_IO_BASE;  break;
+                               case 2:  offset = PREP_ISA_MEM_BASE; break;
+                               default: return; /* Not I/O or memory?? */
+                       }
+               }
+               else
+                       return; /* Not a 32-bit address */
 
-       real_addr = ld_le32((unsigned int *) (p.PPCData + 4));
-       if (real_addr == 0xffffffff)
-               return;
+               real_addr = ld_le32((unsigned int *) (p.PPCData + 4));
+               if (real_addr == 0xffffffff)
+                       return;
 
-       /* Adjust address to be as seen by CPU */
-       addr = real_addr + PREP_ISA_MEM_BASE;
+               /* Adjust address to be as seen by CPU */
+               addr = real_addr + offset;
 
-       len = ld_le32((unsigned int *) (p.PPCData + 12));
-       if (!len)
-               return;
+               len = ld_le32((unsigned int *) (p.PPCData + 12));
+               if (!len)
+                       return;
 #undef p
-       OpenPIC_Addr = ioremap(addr, len);
-       ppc_md.get_irq = openpic_get_irq;
+               OpenPIC_Addr = ioremap(addr, len);
+               ppc_md.get_irq = openpic_get_irq;
 
-       OpenPIC_InitSenses = prep_openpic_initsenses;
-       OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
+               OpenPIC_InitSenses = prep_openpic_initsenses;
+               OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
 
-       printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x "
-              "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr);
-#endif
+               printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x "
+                      "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr);
+       }
 }
 
 static void __init
@@ -900,6 +907,17 @@ ibm43p_pci_map_non0(struct pci_dev *dev)
        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 }
 
+void __init
+prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+       if (have_residual_data) {
+               Motherboard_map_name = res->VitalProductData.PrintableModel;
+               Motherboard_map = NULL;
+               Motherboard_routes = NULL;
+               residual_irq_mask(irq_edge_mask_lo, irq_edge_mask_hi);
+       }
+}
+
 void __init
 prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
 {
@@ -1011,21 +1029,31 @@ prep_route_pci_interrupts(void)
                }
        } else if ( _prep_type == _PREP_IBM ) {
                unsigned char irq_edge_mask_lo, irq_edge_mask_hi;
+               unsigned short irq_edge_mask;
+               int i;
 
                setup_ibm_pci(&irq_edge_mask_lo, &irq_edge_mask_hi);
 
                outb(inb(0x04d0)|irq_edge_mask_lo, 0x4d0); /* primary 8259 */
                outb(inb(0x04d1)|irq_edge_mask_hi, 0x4d1); /* cascaded 8259 */
+
+               irq_edge_mask = (irq_edge_mask_hi << 8) | irq_edge_mask_lo;
+               for (i = 0; i < 16; ++i, irq_edge_mask >>= 1)
+                       if (irq_edge_mask & 1)
+                               irq_desc[i].status |= IRQ_LEVEL;
        } else {
                printk("No known machine pci routing!\n");
                return;
        }
 
        /* Set up mapping from slots */
-       for (i = 1;  i <= 4;  i++)
-               ibc_pirq[i-1] = Motherboard_routes[i];
-       /* Enable PCI interrupts */
-       *ibc_pcicon |= 0x20;
+       if (Motherboard_routes) {
+               for (i = 1;  i <= 4;  i++)
+                       ibc_pirq[i-1] = Motherboard_routes[i];
+
+               /* Enable PCI interrupts */
+               *ibc_pcicon |= 0x20;
+       }
 }
 
 void __init
@@ -1171,38 +1199,52 @@ void __init
 prep_pcibios_fixup(void)
 {
         struct pci_dev *dev = NULL;
+       int irq;
+       int have_openpic = (OpenPIC_Addr != NULL);
 
        prep_route_pci_interrupts();
 
        printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
-       if (OpenPIC_Addr) {
-               /* PCI interrupts are controlled by the OpenPIC */
-               while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-                       if (dev->bus->number == 0) {
-                                       dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
-                               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-                       } else {
-                               if (Motherboard_non0 != NULL)
-                                       Motherboard_non0(dev);
-                       }
-               }
-
-               /* Setup the Winbond or Via PIB */
-               prep_pib_init();
-
-               return;
-       }
 
-       dev = NULL;
+       /* Iterate through all the PCI devices, setting the IRQ */
        while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
                /*
-                * Use our old hard-coded kludge to figure out what
-                * irq this device uses.  This is necessary on things
-                * without residual data. -- Cort
+                * If we have residual data, then this is easy: query the
+                * residual data for the IRQ line allocated to the device.
+                * This works the same whether we have an OpenPic or not.
+                */
+               if (have_residual_data) {
+                       irq = residual_pcidev_irq(dev);
+                       dev->irq = have_openpic ? openpic_to_irq(irq) : irq;
+               }
+               /*
+                * If we don't have residual data, then we need to use
+                * tables to determine the IRQ.  The table organisation
+                * is different depending on whether there is an OpenPIC
+                * or not.  The tables are only used for bus 0, so check
+                * this first.
                 */
-               unsigned char d = PCI_SLOT(dev->devfn);
-               dev->irq = Motherboard_routes[Motherboard_map[d]];
+               else if (dev->bus->number == 0) {
+                       irq = Motherboard_map[PCI_SLOT(dev->devfn)];
+                       dev->irq = have_openpic ? openpic_to_irq(irq)
+                                               : Motherboard_routes[irq];
+               }
+               /*
+                * Finally, if we don't have residual data and the bus is
+                * non-zero, use the callback (if provided)
+                */
+               else {
+                       if (Motherboard_non0 != NULL)
+                               Motherboard_non0(dev);
+
+                       continue;
+               }
+
+               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
        }
+
+       /* Setup the Winbond or Via PIB */
+       prep_pib_init();
 }
 
 static void __init
@@ -1262,14 +1304,15 @@ prep_find_bridges(void)
                           PREP_ISA_IO_BASE + 0xcfc);
 
        printk("PReP architecture\n");
-#ifdef CONFIG_PREP_RESIDUAL
-       {
+
+       if (have_residual_data) {
                PPC_DEVICE *hostbridge;
 
                hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
                        BridgeController, PCIBridge, -1, 0);
                if (hostbridge &&
-                       hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
+                       ((hostbridge->DeviceId.Interface == PCIBridgeIndirect) ||
+                        (hostbridge->DeviceId.Interface == PCIBridgeRS6K))) {
                        PnP_TAG_PACKET * pkt;
                        pkt = PnP_find_large_vendor_packet(
                                res->DevicePnPHeap+hostbridge->AllocatedOffset,
@@ -1284,7 +1327,6 @@ prep_find_bridges(void)
                                setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc);
                }
        }
-#endif /* CONFIG_PREP_RESIDUAL */
 
        ppc_md.pcibios_fixup = prep_pcibios_fixup;
        ppc_md.pcibios_after_init = prep_pcibios_after_init;
index e0ab8e3..a75553c 100644 (file)
@@ -193,10 +193,6 @@ static void __init prpmc750_setup_arch(void)
                ROOT_DEV = Root_SDA2;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-       conswitchp = &dummy_con;
-#endif
-
        OpenPIC_InitSenses = prpmc750_openpic_initsenses;
        OpenPIC_NumInitSenses = sizeof(prpmc750_openpic_initsenses);
 
index 23ed941..015b4f5 100644 (file)
@@ -5,20 +5,16 @@
  *
  * Author: Matt Porter <mporter@mvista.com>
  *
- * Copyright 2001 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 as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * 2001-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.
  */
 
 #ifdef __KERNEL__
 #ifndef __ASM_PRPMC750_H__
 #define __ASM_PRPMC750_H__
 
-#include <linux/serial_reg.h>
-
 /*
  * Due to limiations imposed by legacy hardware (primaryily IDE controllers),
  * the PrPMC750 carrier board operates using a PReP address map.
 #define PRPMC750_TBEN_REG              0xfef880c0
 #define PRPMC750_TBEN_MASK             0x01
 
+/* UART Defines. */
+#define RS_TABLE_SIZE  4
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD  (PRPMC750_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+#define SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, PRPMC750_SERIAL_0, 1, STD_COM_FLAGS, \
+               iomem_base: (unsigned char *)PRPMC750_SERIAL_0, \
+               iomem_reg_shift: 4, \
+               io_type: SERIAL_IO_MEM } /* ttyS0 */
+
 #endif                         /* __ASM_PRPMC750_H__ */
 #endif                         /* __KERNEL__ */
index 0ffcfdf..0e99f8b 100644 (file)
@@ -309,10 +309,6 @@ static void __init prpmc800_setup_arch(void)
                ROOT_DEV = Root_SDA2;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-       conswitchp = &dummy_con;
-#endif
-
        printk(KERN_INFO "Port by MontaVista Software, Inc. "
                         "(source@mvista.com)\n");
 }
index 4af2f2c..e53ec9b 100644 (file)
@@ -5,12 +5,10 @@
  *
  * Author: Dale Farnsworth <dale.farnsworth@mvista.com>
  *
- * Copyright 2001 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 as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * 2001-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.
  */
  /*
   * From Processor to PCI:
 #define PRPMC800_INT_IRQ                       16
 #define PRPMC800_INT_PRI                       15
 
+/* UART Defines. */
+#define RS_TABLE_SIZE  4
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD (PRPMC800_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+/* UARTS are at IRQ 16 */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, PRPMC800_SERIAL_1, 16, STD_COM_FLAGS, /* ttyS0 */\
+               iomem_base: (unsigned char *)PRPMC800_SERIAL_1,         \
+               iomem_reg_shift: 0,                                     \
+               io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
+
 #endif                         /* __ASMPPC_PRPMC800_H */
index b094e27..0f84ca6 100644 (file)
@@ -504,7 +504,7 @@ void __init print_residual_device_info(void)
 #define did dev->DeviceId
 
        /* make sure we have residual data first */
-       if ( res->ResidualLength == 0 )
+       if (!have_residual_data)
                return;
 
        printk("Residual: %ld devices\n", res->ActualNumDevices);
@@ -639,7 +639,7 @@ void print_residual_device_info(void)
 #define did dev->DeviceId
 
        /* make sure we have residual data first */
-       if ( res->ResidualLength == 0 )
+       if (!have_residual_data)
                return;
        printk("Residual: %ld devices\n", res->ActualNumDevices);
        for ( i = 0;
@@ -790,7 +790,7 @@ PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
                         int n)
 {
        int i;
-       if ( !res->ResidualLength ) return NULL;
+       if (!have_residual_data) return NULL;
        for (i=0; i<res->ActualNumDevices; i++) {
 #define Dev res->Devices[i].DeviceId
                if ( (Dev.BusId&BusMask)                                  &&
@@ -813,7 +813,7 @@ PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
                         int n)
 {
        int i;
-       if ( !res->ResidualLength ) return NULL;
+       if (!have_residual_data) return NULL;
        for (i=0; i<res->ActualNumDevices; i++) {
 #define Dev res->Devices[i].DeviceId
                if ( (Dev.BusId&BusMask)                                  &&
@@ -827,6 +827,129 @@ PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
        return NULL;
 }
 
+static int __init
+residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev)
+{
+       int irq = -1;
+
+#define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData
+       if (dev->bus->number == data[16]) {
+               int i, size;
+
+               size = 3 + ld_le16((u_short *) (&pkt->L4_Pack.Count0));
+               for (i = 20; i < size - 4; i += 12) {
+                       unsigned char pin;
+                       int line_irq;
+
+                       if (dev->devfn != data[i + 1])
+                               continue;
+
+                       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+                       if (pin) {
+                               line_irq = ld_le16((unsigned short *)
+                                               (&data[i + 4 + 2 * (pin - 1)]));
+                               irq = (line_irq == 0xffff) ? 0
+                                                          : line_irq & 0x7fff;
+                       } else
+                               irq = 0;
+
+                       break;
+               }
+       }
+#undef data
+
+       return irq;
+}
+
+int __init
+residual_pcidev_irq(struct pci_dev *dev)
+{
+       int i = 0;
+       int irq = -1;
+       PPC_DEVICE *bridge;
+
+       while ((bridge = residual_find_device
+              (-1, NULL, BridgeController, PCIBridge, -1, i++))) {
+
+               PnP_TAG_PACKET *pkt;
+               if (bridge->AllocatedOffset) {
+                       pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+                                          bridge->AllocatedOffset, 3, 0);
+                       if (!pkt)
+                               continue;
+
+                       irq = residual_scan_pcibridge(pkt, dev);
+                       if (irq != -1)
+                               break;
+               }
+       }
+
+       return (irq < 0) ? 0 : irq;
+}
+
+void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+       PPC_DEVICE *dev;
+       int i = 0;
+       unsigned short irq_mask = 0x000; /* default to edge */
+
+       while ((dev = residual_find_device(-1, NULL, -1, -1, -1, i++))) {
+               PnP_TAG_PACKET *pkt;
+               unsigned short mask;
+               int size;
+               int offset = dev->AllocatedOffset;
+
+               if (!offset)
+                       continue;
+
+               pkt = PnP_find_packet(res->DevicePnPHeap + offset,
+                                             IRQFormat, 0);
+               if (!pkt)
+                       continue;
+
+               size = tag_small_count(pkt->S1_Pack.Tag) + 1;
+               mask = ld_le16((unsigned short *)pkt->S4_Pack.IRQMask);
+               if (size > 3 && (pkt->S4_Pack.IRQInfo & 0x0c))
+                       irq_mask |= mask;
+       }
+
+       *irq_edge_mask_lo = irq_mask & 0xff;
+       *irq_edge_mask_hi = irq_mask >> 8;
+}
+
+unsigned int __init residual_isapic_addr(void)
+{
+       PPC_DEVICE *isapic;
+       PnP_TAG_PACKET *pkt;
+       unsigned int addr;
+
+       isapic = residual_find_device(~0, NULL, SystemPeripheral,
+                                     ProgrammableInterruptController,
+                                     ISA_PIC, 0);
+       if (!isapic)
+               goto unknown;
+
+       pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+                                               isapic->AllocatedOffset, 9, 0);
+       if (!pkt)
+               goto unknown;
+
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+       /* Must be 32-bit system address */
+       if (!((p.PPCData[0] == 3) && (p.PPCData[1] == 32)))
+               goto unknown;
+
+       /* It doesn't seem to work where length != 1 (what can I say? :-/ ) */
+       if (ld_le32((unsigned int *)(p.PPCData + 12)) != 1)
+               goto unknown;
+
+       addr = ld_le32((unsigned int *) (p.PPCData + 4));
+#undef p
+       return addr;
+unknown:
+       return 0;
+}
+
 PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
                                unsigned packet_tag,
                                int n)
@@ -901,7 +1024,7 @@ static int proc_prep_residual_read(char * buf, char ** start, off_t off,
 int __init
 proc_prep_residual_init(void)
 {
-       if (res->ResidualLength)
+       if (have_residual_data)
                create_proc_read_entry("residual", S_IRUGO, NULL,
                                        proc_prep_residual_read, NULL);
        return 0;
index ad67102..74be324 100644 (file)
@@ -228,11 +228,6 @@ spruce_setup_arch(void)
                ROOT_DEV = Root_SDA1;
 #endif
 
-#ifdef CONFIG_VT
-       conswitchp = &dummy_con;
-#endif
-
-
        /* Identify the system */
        printk(KERN_INFO "System Identification: IBM Spruce\n");
        printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
index 43eac41..bd8335b 100644 (file)
@@ -1,12 +1,3 @@
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <asm/irq.h>
-#include <asm/immap_cpm2.h>
-#include <asm/mpc8260.h>
-#include "cpm2_pic.h"
-
 /* The CPM2 internal interrupt controller.  It is usually
  * the only interrupt controller.
  * There are two 32-bit registers (high/low) for up to 64
@@ -18,6 +9,18 @@
  * We create two tables, indexed by vector number, to indicate
  * which register to use and which bit in the register to use.
  */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/irq.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+
+#include "cpm2_pic.h"
+
 static u_char  irq_to_siureg[] = {
        1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1,
@@ -123,9 +126,5 @@ cpm2_get_irq(struct pt_regs *regs)
 
        if (irq == 0)
                return(-1);
-#if 0
-        irq += ppc8260_pic.irq_offset;
-#endif
        return irq;
 }
-
index a9da441..d05003b 100644 (file)
@@ -1,13 +1,7 @@
 #ifndef _PPC_KERNEL_CPM2_H
 #define _PPC_KERNEL_CPM2_H
 
-#include <linux/irq.h>
-
 extern struct hw_interrupt_type cpm2_pic;
-
-void cpm2_pic_init(void);
-void cpm2_do_IRQ(struct pt_regs *regs,
-                 int            cpu);
-int cpm2_get_irq(struct pt_regs *regs);
+extern int cpm2_get_irq(struct pt_regs *regs);
 
 #endif /* _PPC_KERNEL_CPM2_H */
index 9c2e150..a9911dc 100644 (file)
@@ -285,3 +285,35 @@ hawk_get_mem_size(uint smc_base)
 
        return total;
 }
+
+int __init
+hawk_mpic_init(unsigned int pci_mem_offset)
+{
+       unsigned short  devid;
+       unsigned int    pci_membase;
+
+       /* Check the first PCI device to see if it is a Raven or Hawk. */
+       early_read_config_word(0, 0, 0, PCI_DEVICE_ID, &devid);
+
+       switch (devid) {
+       case PCI_DEVICE_ID_MOTOROLA_RAVEN:
+       case PCI_DEVICE_ID_MOTOROLA_HAWK:
+               break;
+       default:
+               OpenPIC_Addr = NULL;
+               return 1;
+       }
+
+       /* Read the memory base register. */
+       early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+
+       if (pci_membase == 0) {
+               OpenPIC_Addr = NULL;
+               return 1;
+       }
+
+       /* Map the MPIC registers to virtual memory. */
+       OpenPIC_Addr = ioremap(pci_membase + pci_mem_offset, 0x22000);
+
+       return 0;
+}
index a0cefdc..76d18d3 100644 (file)
@@ -6,6 +6,9 @@
  * Matt Porter <mporter@mvista.com>
  * Copyright 2002-2003 MontaVista Software Inc.
  *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
  * This program is free software; you can redistribute  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
  */
 #include <linux/config.h>
 #include <linux/types.h>
+#include <linux/serial.h>
+
+#include <asm/param.h>
 #include <asm/ibm44x.h>
 #include <asm/mmu.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/ppc4xx_pic.h>
 
 phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size)
 {
@@ -35,3 +44,159 @@ phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size)
 
        return (page_4gb | addr);
 };
+
+void __init ibm44x_calibrate_decr(unsigned int freq)
+{
+       tb_ticks_per_jiffy = freq / HZ;
+       tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+       /* Set the time base to zero */
+       mtspr(SPRN_TBWL, 0);
+       mtspr(SPRN_TBWU, 0);
+
+       /* Clear any pending timer interrupts */
+       mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+
+       /* Enable decrementer interrupt */
+       mtspr(SPRN_TCR, TCR_DIE);
+}
+
+extern void abort(void);
+
+static void ibm44x_restart(char *cmd)
+{
+       local_irq_disable();
+       abort();
+}
+
+static void ibm44x_power_off(void)
+{
+       local_irq_disable();
+       for(;;);
+}
+
+static void ibm44x_halt(void)
+{
+       local_irq_disable();
+       for(;;);
+}
+
+/*
+ * Read the 44x memory controller to get size of system memory.
+ */
+static unsigned long __init ibm44x_find_end_of_memory(void)
+{
+       u32 i, bank_config;
+       u32 mem_size = 0;
+
+       for (i=0; i<4; i++)
+       {
+               switch (i)
+               {
+                       case 0:
+                               mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR);
+                               break;
+                       case 1:
+                               mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR);
+                               break;
+                       case 2:
+                               mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR);
+                               break;
+                       case 3:
+                               mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR);
+                               break;
+               }
+
+               bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
+
+               if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE))
+                       continue;
+               switch (SDRAM_CONFIG_BANK_SIZE(bank_config))
+               {
+                       case SDRAM_CONFIG_SIZE_8M:
+                               mem_size += PPC44x_MEM_SIZE_8M;
+                               break;
+                       case SDRAM_CONFIG_SIZE_16M:
+                               mem_size += PPC44x_MEM_SIZE_16M;
+                               break;
+                       case SDRAM_CONFIG_SIZE_32M:
+                               mem_size += PPC44x_MEM_SIZE_32M;
+                               break;
+                       case SDRAM_CONFIG_SIZE_64M:
+                               mem_size += PPC44x_MEM_SIZE_64M;
+                               break;
+                       case SDRAM_CONFIG_SIZE_128M:
+                               mem_size += PPC44x_MEM_SIZE_128M;
+                               break;
+                       case SDRAM_CONFIG_SIZE_256M:
+                               mem_size += PPC44x_MEM_SIZE_256M;
+                               break;
+                       case SDRAM_CONFIG_SIZE_512M:
+                               mem_size += PPC44x_MEM_SIZE_512M;
+                               break;
+               }
+       }
+       return mem_size;
+}
+
+static void __init ibm44x_init_irq(void)
+{
+       int i;
+
+       ppc4xx_pic_init();
+
+       for (i = 0; i < NR_IRQS; i++)
+               irq_desc[i].handler = ppc4xx_pic;
+}
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <asm/serial.h>
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+       SERIAL_PORT_DFNS        /* Defined in <asm/serial.h> */
+};
+
+static void ibm44x_progress(char *s, unsigned short hex)
+{
+       volatile char c;
+       volatile unsigned long com_port;
+       u16 shift;
+
+       com_port = (unsigned long)rs_table[0].iomem_base;
+       shift = rs_table[0].iomem_reg_shift;
+
+       while ((c = *s++) != 0) {
+               while ((*((volatile unsigned char *)com_port +
+                               (UART_LSR << shift)) & UART_LSR_THRE) == 0)
+                       ;
+               *(volatile unsigned char *)com_port = c;
+
+       }
+
+       /* Send LF/CR to pretty up output */
+       while ((*((volatile unsigned char *)com_port +
+               (UART_LSR << shift)) & UART_LSR_THRE) == 0)
+               ;
+       *(volatile unsigned char *)com_port = '\r';
+       while ((*((volatile unsigned char *)com_port +
+               (UART_LSR << shift)) & UART_LSR_THRE) == 0)
+               ;
+       *(volatile unsigned char *)com_port = '\n';
+}
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+
+void __init ibm44x_platform_init(void)
+{
+       ppc_md.init_IRQ = ibm44x_init_irq;
+       ppc_md.find_end_of_memory = ibm44x_find_end_of_memory;
+       ppc_md.restart = ibm44x_restart;
+       ppc_md.power_off = ibm44x_power_off;
+       ppc_md.halt = ibm44x_halt;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+       ppc_md.progress = ibm44x_progress;
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+}
+
index ee1053a..b14eb60 100644 (file)
@@ -4,7 +4,7 @@
  * PPC44x system library
  *
  * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2003 Zultys Technologies
+ * Copyright (c) 2003, 2004 Zultys Technologies
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -31,6 +31,12 @@ struct ibm44x_clocks {
        unsigned int uart1;
 };
 
+/* common 44x platform init */
+void ibm44x_platform_init(void) __init;
+
+/* initialize decrementer and tick-related variables */
+void ibm44x_calibrate_decr(unsigned int freq) __init;
+
 #endif /* __ASSEMBLY__ */
 #endif /* __PPC_SYSLIB_IBM44x_COMMON_H */
 #endif /* __KERNEL__ */
index 4e2ce7f..d135212 100644 (file)
@@ -66,6 +66,7 @@
 #endif
 
 #ifdef CONFIG_8260_PCI9
+struct pci_controller;
 extern void setup_m8260_indirect_pci(struct pci_controller* hose,
                                     u32 cfg_addr, u32 cfg_data);
 #else
diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c
new file mode 100644 (file)
index 0000000..7838a44
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * m8xx_wdt.c - MPC8xx watchdog driver
+ *
+ * Author: Florian Schirmer <jolt@tuxbox.org>
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> 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.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/8xx_immap.h>
+#include <syslib/m8xx_wdt.h>
+
+static int wdt_timeout;
+
+void m8xx_wdt_reset(void)
+{
+       volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+
+       imap->im_siu_conf.sc_swsr = 0x556c;     /* write magic1 */
+       imap->im_siu_conf.sc_swsr = 0xaa39;     /* write magic2 */
+}
+
+static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+       volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+
+       m8xx_wdt_reset();
+
+       imap->im_sit.sit_piscr |= PISCR_PS;     /* clear irq */
+
+       return IRQ_HANDLED;
+}
+
+void __init m8xx_wdt_handler_install(bd_t * binfo)
+{
+       volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+       u32 pitc;
+       u32 sypcr;
+       u32 pitrtclk;
+
+       sypcr = imap->im_siu_conf.sc_sypcr;
+
+       if (!(sypcr & 0x04)) {
+               printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n",
+                      sypcr);
+               return;
+       }
+
+       m8xx_wdt_reset();
+
+       printk(KERN_NOTICE
+              "m8xx_wdt: active wdt found (SWTC: 0x%04X, SWP: 0x%01X)\n",
+              (sypcr >> 16), sypcr & 0x01);
+
+       wdt_timeout = (sypcr >> 16) & 0xFFFF;
+
+       if (!wdt_timeout)
+               wdt_timeout = 0xFFFF;
+
+       if (sypcr & 0x01)
+               wdt_timeout *= 2048;
+
+       /*
+        * Fire trigger if half of the wdt ticked down 
+        */
+
+       if (imap->im_sit.sit_rtcsc & RTCSC_38K)
+               pitrtclk = 9600;
+       else
+               pitrtclk = 8192;
+
+       if ((wdt_timeout) > (UINT_MAX / pitrtclk))
+               pitc = wdt_timeout / binfo->bi_intfreq * pitrtclk / 2;
+       else
+               pitc = pitrtclk * wdt_timeout / binfo->bi_intfreq / 2;
+
+       imap->im_sit.sit_pitc = pitc << 16;
+       imap->im_sit.sit_piscr =
+           (mk_int_int_mask(PIT_INTERRUPT) << 8) | PISCR_PIE | PISCR_PTE;
+
+       if (request_irq(PIT_INTERRUPT, m8xx_wdt_interrupt, 0, "watchdog", NULL))
+               panic("m8xx_wdt: could not allocate watchdog irq!");
+
+       printk(KERN_NOTICE
+              "m8xx_wdt: keep-alive trigger installed (PITC: 0x%04X)\n", pitc);
+
+       wdt_timeout /= binfo->bi_intfreq;
+}
+
+int m8xx_wdt_get_timeout(void)
+{
+       return wdt_timeout;
+}
diff --git a/arch/ppc/syslib/m8xx_wdt.h b/arch/ppc/syslib/m8xx_wdt.h
new file mode 100644 (file)
index 0000000..0d81a9f
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Author: Florian Schirmer <jolt@tuxbox.org>
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> 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 _PPC_SYSLIB_M8XX_WDT_H
+#define _PPC_SYSLIB_M8XX_WDT_H
+
+extern void m8xx_wdt_handler_install(bd_t * binfo);
+extern int m8xx_wdt_get_timeout(void);
+extern void m8xx_wdt_reset(void);
+
+#endif                         /* _PPC_SYSLIB_M8XX_WDT_H */
index 0f88e63..4de79d3 100644 (file)
@@ -114,7 +114,7 @@ mpc52xx_ic_ack(unsigned int irq)
        /*
         * Only some irqs are reset here, others in interrupting hardware.
         */
-                       
+
        switch (irq) {
        case MPC52xx_IRQ0:
                val = in_be32(&intr->ctrl);
@@ -180,13 +180,14 @@ void __init
 mpc52xx_init_irq(void)
 {
        int i;
+       u32 intr_ctrl;
 
        /* Remap the necessary zones */
        intr = (struct mpc52xx_intr *)
                ioremap(MPC52xx_INTR, sizeof(struct mpc52xx_intr));
        sdma = (struct mpc52xx_sdma *)
                ioremap(MPC52xx_SDMA, sizeof(struct mpc52xx_sdma));
-       
+
        if ((intr==NULL) || (sdma==NULL))
                panic("Can't ioremap PIC/SDMA register for init_irq !");
 
@@ -195,12 +196,13 @@ mpc52xx_init_irq(void)
        out_be32(&sdma->IntMask, 0xffffffff);   /* 1 means disabled */
        out_be32(&intr->per_mask, 0x7ffffc00);  /* 1 means disabled */
        out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
-       out_be32(&intr->ctrl,
-                       0x0f000000 |    /* clear IRQ 0-3 */
-                       0x00c00000 |    /* IRQ0: level-sensitive, active low */
+       intr_ctrl = in_be32(&intr->ctrl);
+       intr_ctrl &=    0x00ff0000;     /* Keeps IRQ[0-3] config */
+       intr_ctrl |=    0x0f000000 |    /* clear IRQ 0-3 */
                        0x00001000 |    /* MEE master external enable */
                        0x00000000 |    /* 0 means disable IRQ 0-3 */
-                       0x00000001);    /* CEb route critical normally */
+                       0x00000001;     /* CEb route critical normally */
+       out_be32(&intr->ctrl, intr_ctrl);
 
        /* Zero a bunch of the priority settings.  */
        out_be32(&intr->per_pri1, 0);
@@ -214,6 +216,14 @@ mpc52xx_init_irq(void)
                irq_desc[i].handler = &mpc52xx_ic;
                irq_desc[i].status = IRQ_LEVEL;
        }
+
+       #define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
+       for (i=0 ; i<4 ; i++) {
+               int mode;
+               mode = IRQn_MODE(intr_ctrl,i);
+               if ((mode == 0x1) || (mode == 0x2))
+                       irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 0;
+       }
 }
 
 int
index 631cea3..d73e6fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/ppc/syslib/mpc52xx_common.c
+ * arch/ppc/syslib/mpc52xx_setup.c
  *
  * Common code for the boards based on Freescale MPC52xx embedded CPU.
  *
@@ -23,6 +23,7 @@
 #include <asm/mpc52xx.h>
 #include <asm/mpc52xx_psc.h>
 #include <asm/ocp.h>
+#include <asm/pgtable.h>
 #include <asm/ppcboot.h>
 
 extern bd_t __res;
@@ -38,9 +39,9 @@ void
 mpc52xx_restart(char *cmd)
 {
        struct mpc52xx_gpt* gpt0 = (struct mpc52xx_gpt*) MPC52xx_GPTx(0);
-       
+
        local_irq_disable();
-       
+
        /* Turn on the watchdog and wait for it to expire. It effectively
          does a reset */
        if (gpt0 != NULL) {
@@ -99,24 +100,28 @@ mpc52xx_map_io(void)
 #error "mpc52xx PSC for console not selected"
 #endif
 
+static void
+mpc52xx_psc_putc(struct mpc52xx_psc * psc, unsigned char c)
+{
+       while (!(in_be16(&psc->mpc52xx_psc_status) &
+                MPC52xx_PSC_SR_TXRDY));
+       out_8(&psc->mpc52xx_psc_buffer_8, c);
+}
+
 void
 mpc52xx_progress(char *s, unsigned short hex)
 {
        struct mpc52xx_psc *psc = (struct mpc52xx_psc *)MPC52xx_CONSOLE;
        char c;
 
-               /* Don't we need to disable serial interrupts ? */
-       
        while ((c = *s++) != 0) {
-               if (c == '\n') {
-                       while (!(in_be16(&psc->mpc52xx_psc_status) &
-                                MPC52xx_PSC_SR_TXRDY)) ;
-                       out_8(&psc->mpc52xx_psc_buffer_8, '\r');
-               }
-               while (!(in_be16(&psc->mpc52xx_psc_status) &
-                        MPC52xx_PSC_SR_TXRDY)) ;
-               out_8(&psc->mpc52xx_psc_buffer_8, c);
+               if (c == '\n')
+                       mpc52xx_psc_putc(psc, '\r');
+               mpc52xx_psc_putc(psc, c);
        }
+
+       mpc52xx_psc_putc(psc, '\r');
+       mpc52xx_psc_putc(psc, '\n');
 }
 
 #endif  /* CONFIG_SERIAL_TEXT_DEBUG */
@@ -137,7 +142,7 @@ mpc52xx_find_end_of_memory(void)
 
                /* Temp BAT2 mapping active when this is called ! */
                mmap_ctl = (struct mpc52xx_mmap_ctl*) MPC52xx_MMAP_CTL;
-                       
+
                sdram_config_0 = in_be32(&mmap_ctl->sdram0);
                sdram_config_1 = in_be32(&mmap_ctl->sdram1);
 
@@ -147,10 +152,8 @@ mpc52xx_find_end_of_memory(void)
                if (((sdram_config_1 & 0x1f) >= 0x13) &&
                                ((sdram_config_1 & 0xfff00000) == ramsize))
                        ramsize += 1 << ((sdram_config_1 & 0xf) + 17);
-
-               iounmap(mmap_ctl);
        }
-       
+
        return ramsize;
 }
 
@@ -167,7 +170,7 @@ mpc52xx_calibrate_decr(void)
                /* Get RTC & Clock manager modules */
                struct mpc52xx_rtc *rtc;
                struct mpc52xx_cdm *cdm;
-               
+
                rtc = (struct mpc52xx_rtc*)
                        ioremap(MPC52xx_RTC, sizeof(struct mpc52xx_rtc));
                cdm = (struct mpc52xx_cdm*)
@@ -206,7 +209,7 @@ mpc52xx_calibrate_decr(void)
                __res.bi_intfreq = cpufreq;
                __res.bi_ipbfreq = ipbfreq;
                __res.bi_pcifreq = pcifreq;
-       
+
                /* Release mapping */
                iounmap((void*)rtc);
                iounmap((void*)cdm);
index 52cb4a4..191e5af 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/sysdev.h>
+#include <linux/errno.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 #include <asm/io.h>
@@ -28,7 +29,6 @@
 #include <asm/sections.h>
 #include <asm/open_pic.h>
 #include <asm/i8259.h>
-#include <asm/hardirq.h>
 
 #include "open_pic_defs.h"
 
index f745882..735f3ae 100644 (file)
@@ -61,10 +61,6 @@ ppc4xx_setup_arch(void)
 #ifdef CONFIG_PCI
        ppc4xx_find_bridges();
 #endif
-
-#if defined(CONFIG_FB)
-       conswitchp = &dummy_con;
-#endif
 }
 
 /*
index 6ceea97..d4e6515 100644 (file)
@@ -277,7 +277,7 @@ mpc85xx_setup_hose(void)
        hose_a->io_space.start = MPC85XX_PCI1_LOWER_IO;
        hose_a->io_space.end = MPC85XX_PCI1_UPPER_IO;
        hose_a->io_base_phys = MPC85XX_PCI1_IO_BASE;
-#if CONFIG_85xx_PCI2
+#ifdef CONFIG_85xx_PCI2
        isa_io_base =
                (unsigned long) ioremap(MPC85XX_PCI1_IO_BASE,
                                        MPC85XX_PCI1_IO_SIZE +
@@ -304,7 +304,7 @@ mpc85xx_setup_hose(void)
 
        hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
 
-#if CONFIG_85xx_PCI2
+#ifdef CONFIG_85xx_PCI2
        hose_b = pcibios_alloc_controller();
 
        if (!hose_b)
index c1eb1f4..1dc7e0b 100644 (file)
@@ -277,9 +277,9 @@ todc_time_init(void)
 ulong
 todc_get_rtc_time(void)
 {
-       uint    year, mon, day, hour, min, sec;
+       uint    year = 0, mon = 0, day = 0, hour = 0, min = 0, sec = 0;
        uint    limit, i;
-       u_char  save_control, uip;
+       u_char  save_control, uip = 0;
 
        spin_lock(&rtc_lock);
        save_control = todc_read_val(todc_info->control_a);
@@ -361,7 +361,7 @@ int
 todc_set_rtc_time(unsigned long nowtime)
 {
        struct rtc_time tm;
-       u_char          save_control, save_freq_select;
+       u_char          save_control, save_freq_select = 0;
 
        spin_lock(&rtc_lock);
        to_tm(nowtime, &tm);
@@ -416,7 +416,7 @@ todc_set_rtc_time(unsigned long nowtime)
  */
 static unsigned char __init todc_read_timereg(int addr)
 {
-       unsigned char save_control, val;
+       unsigned char save_control = 0, val;
 
        switch (todc_info->rtc_type) {
                case TODC_TYPE_DS1557:
diff --git a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug
new file mode 100644 (file)
index 0000000..c3cd4c7
--- /dev/null
@@ -0,0 +1,59 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_STACKOVERFLOW
+       bool "Check for stack overflows"
+       depends on DEBUG_KERNEL
+
+config DEBUG_STACK_USAGE
+       bool "Stack utilization instrumentation"
+       depends on DEBUG_KERNEL
+       help
+         Enables the display of the minimum amount of free stack which each
+         task has ever had available in the sysrq-T and sysrq-P debug output.
+
+         This option will slow down process creation somewhat.
+
+config DEBUGGER
+       bool "Enable debugger hooks"
+       depends on DEBUG_KERNEL
+       help
+         Include in-kernel hooks for kernel debuggers. Unless you are
+         intending to debug the kernel, say N here.
+
+config XMON
+       bool "Include xmon kernel debugger"
+       depends on DEBUGGER
+       help
+         Include in-kernel hooks for the xmon kernel monitor/debugger.
+         Unless you are intending to debug the kernel, say N here.
+
+config XMON_DEFAULT
+       bool "Enable xmon by default"
+       depends on XMON
+
+config PPCDBG
+       bool "Include PPCDBG realtime debugging"
+       depends on DEBUG_KERNEL
+
+config IRQSTACKS
+       bool "Use separate kernel stacks when processing interrupts"
+       help
+         If you say Y here the kernel will use separate kernel stacks
+         for handling hard and soft interrupts.  This can help avoid
+         overflowing the process kernel stacks.
+
+config SCHEDSTATS
+       bool "Collect scheduler statistics"
+       depends on DEBUG_KERNEL && PROC_FS
+       help
+         If you say Y here, additional code will be inserted into the
+         scheduler and related routines to collect statistics about
+         scheduler behavior and provide them in /proc/schedstat.  These
+         stats may be useful for both tuning and debugging the scheduler
+         If you aren't debugging the scheduler or trying to tune a specific
+         application, you can say N to avoid the very slight overhead
+         this adds.
+
+endmenu
index 9d6431d..8f99c9d 100644 (file)
@@ -25,11 +25,11 @@ CROSS32_COMPILE ?=
 
 BOOTCC         := $(CROSS32_COMPILE)gcc
 HOSTCC         := gcc
-BOOTCFLAGS     := $(HOSTCFLAGS) -Iinclude -fno-builtin 
+BOOTCFLAGS     := $(HOSTCFLAGS) $(LINUXINCLUDE) -fno-builtin 
 BOOTAS         := $(CROSS32_COMPILE)as
 BOOTAFLAGS     := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional
 BOOTLD         := $(CROSS32_COMPILE)ld
-BOOTLFLAGS     := -Ttext 0x00400000 -e _start -T $(obj)/zImage.lds
+BOOTLFLAGS     := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds
 BOOTOBJCOPY    := $(CROSS32_COMPILE)objcopy
 OBJCOPYFLAGS    := contents,alloc,load,readonly,data
 
@@ -51,36 +51,31 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S
 #-----------------------------------------------------------
 # ELF sections within the zImage bootloader/wrapper
 #-----------------------------------------------------------
-required := vmlinux .config System.map
+required := vmlinux.strip
 initrd   := initrd
 
 obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section)))
 src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section)))
 gz-sec  = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
 
-host-progs             := piggy addnote addSystemMap addRamDisk
+hostprogs-y            := piggy addnote addRamDisk
 targets                += zImage zImage.initrd imagesize.c \
                           $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
                           $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
                           $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
-                          vmlinux.sm vmlinux.initrd vmlinux.sminitrd
-extra-y                        := sysmap.o initrd.o
-
-quiet_cmd_sysmap = SYSMAP   $@
-      cmd_sysmap = $(obj)/addSystemMap System.map $< $@
-$(obj)/vmlinux.sm: vmlinux $(obj)/addSystemMap System.map FORCE
-       $(call if_changed,sysmap)
+                          vmlinux.initrd
+extra-y                        := initrd.o
 
 quiet_cmd_ramdisk = RAMDISK $@
-      cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map $< $@
-$(obj)/vmlinux.initrd: vmlinux $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map FORCE
-       $(call if_changed,ramdisk)
+      cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz $< $@
 
-$(obj)/vmlinux.sminitrd: $(obj)/vmlinux.sm $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
-       $(call if_changed,ramdisk)
+quiet_cmd_stripvm = STRIP $@
+      cmd_stripvm = $(STRIP) -s $< -o $@
 
-$(obj)/sysmap.o: System.map $(obj)/piggyback FORCE
-       $(call if_changed,piggy)
+vmlinux.strip: vmlinux FORCE
+       $(call if_changed,stripvm)
+$(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
+       $(call if_changed,ramdisk)
 
 addsection = $(BOOTOBJCOPY) $(1) \
                --add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(patsubst %.o,%.gz, $(1)) \
@@ -113,9 +108,9 @@ $(obj)/zImage.initrd: obj-boot += $(call obj-sec, $(required) $(initrd))
 $(obj)/zImage.initrd: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(obj)/addnote FORCE
        $(call if_changed,addnote)
 
-$(obj)/imagesize.c: vmlinux
+$(obj)/imagesize.c: vmlinux.strip
        @echo Generating $@
-       ls -l vmlinux | \
+       ls -l vmlinux.strip | \
        awk '{printf "/* generated -- do not edit! */\n" \
                "unsigned long vmlinux_filesize = %d;\n", $$5}' > $(obj)/imagesize.c
        $(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \
@@ -123,6 +118,6 @@ $(obj)/imagesize.c: vmlinux
                >> $(obj)/imagesize.c
 
 install: $(CONFIGURE) $(obj)/$(BOOTIMAGE)
-       sh -x $(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(TOPDIR)/System.map" "$(INSTALL_PATH)"
+       sh -x $(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(INSTALL_PATH)"
 
-clean-files := $(patsubst $(obj)/%,%, $(obj-boot))
+clean-files := $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip)
index f5a9718..6cf7802 100644 (file)
@@ -31,13 +31,9 @@ unsigned long strlen(const char *s);
 void *memmove(void *dest, const void *src, unsigned long n);
 void *memcpy(void *dest, const void *src, unsigned long n);
 
-static struct bi_record *make_bi_recs(unsigned long);
-
-#define RAM_START      0x00000000
-#define RAM_END                (64<<20)
-
 /* Value picked to match that used by yaboot */
 #define PROG_START     0x01400000
+#define RAM_END                (256<<20) // Fixme: use OF */
 
 char *avail_ram;
 char *begin_avail, *end_avail;
@@ -48,8 +44,6 @@ unsigned int heap_max;
 extern char _start[];
 extern char _vmlinux_start[];
 extern char _vmlinux_end[];
-extern char _sysmap_start[];
-extern char _sysmap_end[];
 extern char _initrd_start[];
 extern char _initrd_end[];
 extern unsigned long vmlinux_filesize;
@@ -62,7 +56,6 @@ struct addr_range {
 };
 struct addr_range vmlinux = {0, 0, 0};
 struct addr_range vmlinuz = {0, 0, 0};
-struct addr_range sysmap  = {0, 0, 0};
 struct addr_range initrd  = {0, 0, 0};
 
 static char scratch[128<<10];  /* 128kB of scratch space for gunzip */
@@ -70,7 +63,7 @@ static char scratch[128<<10]; /* 128kB of scratch space for gunzip */
 typedef void (*kernel_entry_t)( unsigned long,
                                 unsigned long,
                                 void *,
-                               struct bi_record *);
+                               void *);
 
 
 int (*prom)(void *);
@@ -80,12 +73,31 @@ void *stdin;
 void *stdout;
 void *stderr;
 
+#define DEBUG
+
+static unsigned long claim_base = PROG_START;
+
+static unsigned long try_claim(unsigned long size)
+{
+       unsigned long addr = 0;
+
+       for(; claim_base < RAM_END; claim_base += 0x100000) {
+#ifdef DEBUG
+               printf("    trying: 0x%08lx\n\r", claim_base);
+#endif
+               addr = (unsigned long)claim(claim_base, size, 0);
+               if ((void *)addr != (void *)-1)
+                       break;
+       }
+       if (addr == 0)
+               return 0;
+       claim_base = PAGE_ALIGN(claim_base + size);
+       return addr;
+}
 
-void
-start(unsigned long a1, unsigned long a2, void *promptr)
+void start(unsigned long a1, unsigned long a2, void *promptr)
 {
-       unsigned long i, claim_addr, claim_size;
-       struct bi_record *bi_recs;
+       unsigned long i;
        kernel_entry_t kernel_entry;
        Elf64_Ehdr *elf64;
        Elf64_Phdr *elf64ph;
@@ -102,61 +114,59 @@ start(unsigned long a1, unsigned long a2, void *promptr)
 
        printf("zImage starting: loaded at 0x%x\n\r", (unsigned)_start);
 
-#if 0
-       sysmap.size = (unsigned long)(_sysmap_end - _sysmap_start);
-       sysmap.memsize = sysmap.size;
-       if ( sysmap.size > 0 ) {
-               sysmap.addr = (RAM_END - sysmap.size) & ~0xFFF;
-               claim(sysmap.addr, RAM_END - sysmap.addr, 0);
-               printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
-                      sysmap.addr, (unsigned long)_sysmap_start, sysmap.size);
-               memcpy((void *)sysmap.addr, (void *)_sysmap_start, sysmap.size);
+       /*
+        * Now we try to claim some memory for the kernel itself
+        * our "vmlinux_memsize" is the memory footprint in RAM, _HOWEVER_, what
+        * our Makefile stuffs in is an image containing all sort of junk including
+        * an ELF header. We need to do some calculations here to find the right
+        * size... In practice we add 1Mb, that is enough, but we should really
+        * consider fixing the Makefile to put a _raw_ kernel in there !
+        */
+       vmlinux_memsize += 0x100000;
+       printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize);
+       vmlinux.addr = try_claim(vmlinux_memsize);
+       if (vmlinux.addr == 0) {
+               printf("Can't allocate memory for kernel image !\n\r");
+               exit();
        }
-#endif
+       vmlinuz.addr = (unsigned long)_vmlinux_start;
+       vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
+       vmlinux.size = PAGE_ALIGN(vmlinux_filesize);
+       vmlinux.memsize = vmlinux_memsize;
 
+       /*
+        * Now we try to claim memory for the initrd (and copy it there)
+        */
        initrd.size = (unsigned long)(_initrd_end - _initrd_start);
        initrd.memsize = initrd.size;
        if ( initrd.size > 0 ) {
-               initrd.addr = (RAM_END - initrd.size) & ~0xFFF;
-               a1 = a2 = 0;
-               claim(initrd.addr, RAM_END - initrd.addr, 0);
+               printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
+               initrd.addr = try_claim(initrd.size);
+               if (initrd.addr == 0) {
+                       printf("Can't allocate memory for initial ramdisk !\n\r");
+                       exit();
+               }
+               a1 = initrd.addr;
+               a2 = initrd.size;
                printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
                       initrd.addr, (unsigned long)_initrd_start, initrd.size);
-               memcpy((void *)initrd.addr, (void *)_initrd_start, initrd.size);
-       }
-
-       vmlinuz.addr = (unsigned long)_vmlinux_start;
-       vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
-       vmlinux.addr = (unsigned long)(void *)-1;
-       vmlinux.size = PAGE_ALIGN(vmlinux_filesize);
-       vmlinux.memsize = vmlinux_memsize;
-
-       claim_size = vmlinux.memsize /* PPPBBB: + fudge for bi_recs */;
-       for(claim_addr = PROG_START; 
-           claim_addr <= PROG_START * 8; 
-           claim_addr += 0x100000) {
-#ifdef DEBUG
-               printf("    trying: 0x%08lx\n\r", claim_addr);
-#endif
-               vmlinux.addr = (unsigned long)claim(claim_addr, claim_size, 0);
-               if ((void *)vmlinux.addr != (void *)-1) break;
-       }
-       if ((void *)vmlinux.addr == (void *)-1) {
-               printf("claim error, can't allocate kernel memory\n\r");
-               exit();
+               memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
+               printf("initrd head: 0x%lx\n", *((u32 *)initrd.addr));
        }
 
-       /* PPPBBB: should kernel always be gziped? */
+       /* Eventually gunzip the kernel */
        if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
+               int len;
                avail_ram = scratch;
                begin_avail = avail_high = avail_ram;
                end_avail = scratch + sizeof(scratch);
                printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...",
                       vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size);
+               len = vmlinuz.size;
                gunzip((void *)vmlinux.addr, vmlinux.size,
-                       (unsigned char *)vmlinuz.addr, (int *)&vmlinuz.size);
-               printf("done %lu bytes\n\r", vmlinuz.size);
-               printf("%u bytes of heap consumed, max in use %u\n\r",
+                       (unsigned char *)vmlinuz.addr, &len);
+               printf("done 0x%lx bytes\n\r", len);
+               printf("0x%x bytes of heap consumed, max in use 0x%\n\r",
                       (unsigned)(avail_high - begin_avail), heap_max);
        } else {
                memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
@@ -192,7 +202,8 @@ start(unsigned long a1, unsigned long a2, void *promptr)
 
        flush_cache((void *)vmlinux.addr, vmlinux.memsize);
 
-       bi_recs = make_bi_recs(vmlinux.addr + vmlinux.memsize);
+       if (a1)
+               printf("initrd head: 0x%lx\n\r", *((u32 *)initrd.addr));
 
        kernel_entry = (kernel_entry_t)vmlinux.addr;
 #ifdef DEBUG
@@ -203,65 +214,16 @@ start(unsigned long a1, unsigned long a2, void *promptr)
                "        prom       = 0x%lx,\n\r"
                "        bi_recs    = 0x%lx,\n\r",
                (unsigned long)kernel_entry, a1, a2,
-               (unsigned long)prom, (unsigned long)bi_recs);
+               (unsigned long)prom, NULL);
 #endif
 
-       kernel_entry( a1, a2, prom, bi_recs );
+       kernel_entry( a1, a2, prom, NULL );
 
        printf("Error: Linux kernel returned to zImage bootloader!\n\r");
 
        exit();
 }
 
-static struct bi_record *
-make_bi_recs(unsigned long addr)
-{
-       struct bi_record *bi_recs;
-       struct bi_record *rec;
-
-       bi_recs = rec = bi_rec_init(addr);
-
-       rec = bi_rec_alloc(rec, 2);
-       rec->tag = BI_FIRST;
-       /* rec->data[0] = ...;  # Written below before return */
-       /* rec->data[1] = ...;  # Written below before return */
-
-       rec = bi_rec_alloc_bytes(rec, strlen("chrpboot")+1);
-       rec->tag = BI_BOOTLOADER_ID;
-       sprintf( (char *)rec->data, "chrpboot");
-
-       rec = bi_rec_alloc(rec, 2);
-       rec->tag = BI_MACHTYPE;
-       rec->data[0] = PLATFORM_PSERIES;
-       rec->data[1] = 1;
-
-       if ( initrd.size > 0 ) {
-               rec = bi_rec_alloc(rec, 2);
-               rec->tag = BI_INITRD;
-               rec->data[0] = initrd.addr;
-               rec->data[1] = initrd.size;
-       }
-
-       if ( sysmap.size > 0 ) {
-               rec = bi_rec_alloc(rec, 2);
-               rec->tag = BI_SYSMAP;
-               rec->data[0] = (unsigned long)sysmap.addr;
-               rec->data[1] = (unsigned long)sysmap.size;
-       }
-
-       rec = bi_rec_alloc(rec, 1);
-       rec->tag = BI_LAST;
-       rec->data[0] = (bi_rec_field)bi_recs;
-
-       /* Save the _end_ address of the bi_rec's in the first bi_rec
-        * data field for easy access by the kernel.
-        */
-       bi_recs->data[0] = (bi_rec_field)rec;
-       bi_recs->data[1] = (bi_rec_field)rec + rec->size - (bi_rec_field)bi_recs;
-
-       return bi_recs;
-}
-
 struct memchunk {
        unsigned int size;
        unsigned int pad;
index 7070cd2..941ade3 100644 (file)
@@ -61,19 +61,9 @@ SECTIONS
 
   . = ALIGN(4096);
   _vmlinux_start =  .;
-  .kernel:vmlinux : { *(.kernel:vmlinux) }
+  .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) }
   _vmlinux_end =  .;
 
-  . = ALIGN(4096);
-  _dotconfig_start =  .;
-  .kernel:.config : { *(.kernel:.config) }
-  _dotconfig_end =  .;
-
-  . = ALIGN(4096);
-  _sysmap_start =  .;
-  .kernel:System.map : { *(.kernel:System.map) }
-  _sysmap_end =  .;
-
   . = ALIGN(4096);
   _initrd_start =  .;
   .kernel:initrd : { *(.kernel:initrd) }
index 0485eed..9cc01b5 100644 (file)
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc3
+# Thu Oct  7 15:18:38 2004
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -16,11 +18,11 @@ CONFIG_FORCE_MAX_ZONEORDER=13
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
@@ -32,6 +34,8 @@ CONFIG_HOTPLUG=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
@@ -39,6 +43,8 @@ CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -50,18 +56,20 @@ CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_KMOD is not set
 CONFIG_STOP_MACHINE=y
+CONFIG_SYSVIPC_COMPAT=y
 
 #
 # Platform support
 #
 # CONFIG_PPC_ISERIES is not set
-CONFIG_PPC_PSERIES=y
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_PSERIES is not set
+CONFIG_PPC_PMAC=y
 CONFIG_PPC=y
 CONFIG_PPC64=y
 CONFIG_PPC_OF=y
 CONFIG_ALTIVEC=y
-CONFIG_PPC_PMAC=y
-CONFIG_PMAC_DART=y
+CONFIG_U3_DART=y
 CONFIG_PPC_PMAC64=y
 CONFIG_BOOTX_TEXT=y
 CONFIG_POWER4_ONLY=y
@@ -69,8 +77,8 @@ CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_NR_CPUS=2
-# CONFIG_HMT is not set
-# CONFIG_DISCONTIGMEM is not set
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_LPARCFG is not set
 
@@ -104,6 +112,8 @@ CONFIG_PROC_DEVICETREE=y
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 
@@ -132,7 +142,8 @@ CONFIG_FW_LOADER=y
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_INITRD=y
@@ -146,9 +157,9 @@ CONFIG_BLK_DEV_IDE=y
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_IDETAPE=y
 CONFIG_BLK_DEV_IDEFLOPPY=y
@@ -170,7 +181,6 @@ 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_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
@@ -196,6 +206,7 @@ CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
 # CONFIG_BLK_DEV_IDE_PMAC_BLINK is not set
 CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
@@ -221,7 +232,6 @@ CONFIG_CHR_DEV_SG=y
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_REPORT_LUNS=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
@@ -235,23 +245,25 @@ CONFIG_SCSI_SPI_ATTRS=y
 # SCSI low-level drivers
 #
 # 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_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_SVW=y
 # CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_SX4 is not set
 # CONFIG_SCSI_SATA_SIL is not set
 # CONFIG_SCSI_SATA_SIS is not set
 # CONFIG_SCSI_SATA_VIA is not set
 # CONFIG_SCSI_SATA_VITESSE is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
@@ -264,6 +276,7 @@ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -277,7 +290,6 @@ CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
 # CONFIG_SCSI_MAC53C94 is not set
 
 #
@@ -288,11 +300,15 @@ CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=y
 # CONFIG_MD_RAID6 is not set
 # CONFIG_MD_MULTIPATH is not set
 CONFIG_BLK_DEV_DM=y
 # CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
 
 #
 # Fusion MPT device support
@@ -332,6 +348,7 @@ CONFIG_IEEE1394_RAWIO=y
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Macintosh device drivers
@@ -340,7 +357,6 @@ CONFIG_ADB=y
 CONFIG_ADB_PMU=y
 # CONFIG_PMAC_PBOOK is not set
 # CONFIG_PMAC_BACKLIGHT is not set
-# CONFIG_MAC_SERIAL is not set
 # CONFIG_INPUT_ADBHID is not set
 CONFIG_THERM_PM72=y
 
@@ -369,14 +385,13 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=y
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -384,6 +399,8 @@ CONFIG_NETFILTER=y
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=y
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
 # CONFIG_IP_NF_FTP is not set
 # CONFIG_IP_NF_IRC is not set
 # CONFIG_IP_NF_TFTP is not set
@@ -408,8 +425,15 @@ CONFIG_IP_NF_MATCH_HELPER=y
 CONFIG_IP_NF_MATCH_STATE=y
 CONFIG_IP_NF_MATCH_CONNTRACK=y
 CONFIG_IP_NF_MATCH_OWNER=y
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_COMMENT is not set
 CONFIG_IP_NF_FILTER=y
 CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_IP_NF_TARGET_ULOG=y
+CONFIG_IP_NF_TARGET_TCPMSS=y
 CONFIG_IP_NF_NAT=y
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=y
@@ -424,9 +448,7 @@ CONFIG_IP_NF_TARGET_ECN=y
 CONFIG_IP_NF_TARGET_DSCP=y
 CONFIG_IP_NF_TARGET_MARK=y
 CONFIG_IP_NF_TARGET_CLASSIFY=y
-CONFIG_IP_NF_TARGET_LOG=y
-CONFIG_IP_NF_TARGET_ULOG=y
-CONFIG_IP_NF_TARGET_TCPMSS=y
+# CONFIG_IP_NF_RAW is not set
 CONFIG_IP_NF_ARPTABLES=y
 CONFIG_IP_NF_ARPFILTER=y
 CONFIG_IP_NF_ARP_MANGLE=y
@@ -438,7 +460,9 @@ CONFIG_XFRM=y
 #
 # CONFIG_IP_SCTP 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_LLC=y
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
@@ -454,30 +478,33 @@ CONFIG_LLC=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
 CONFIG_SUNGEM=y
 # CONFIG_NET_VENDOR_3COM is not set
@@ -509,57 +536,38 @@ CONFIG_TIGON3=m
 #
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_IBMVETH is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
 
 #
 # Token Ring devices
 #
 CONFIG_TR=y
 CONFIG_IBMOL=y
-# CONFIG_IBMLS is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
 
 #
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# Bluetooth support
+# Wan interfaces
 #
-# CONFIG_BT is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ISDN subsystem
@@ -598,6 +606,7 @@ CONFIG_SERIO=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -636,8 +645,6 @@ CONFIG_HW_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_HVC_CONSOLE=y
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -673,6 +680,7 @@ CONFIG_I2C_CHARDEV=y
 #
 CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
 
 #
 # I2C Hardware Bus support
@@ -697,23 +705,29 @@ CONFIG_I2C_KEYWEST=y
 # 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
 
 #
 # Hardware Sensors Chip support
 #
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
@@ -725,11 +739,17 @@ CONFIG_I2C_KEYWEST=y
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
 
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
 #
 # Misc devices
 #
@@ -748,6 +768,8 @@ CONFIG_I2C_KEYWEST=y
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
@@ -755,10 +777,12 @@ CONFIG_FB_OF=y
 # CONFIG_FB_PLATINUM is not set
 # CONFIG_FB_VALKYRIE is not set
 # CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
 CONFIG_FB_RIVA=y
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
@@ -778,10 +802,8 @@ CONFIG_FB_RADEON_I2C=y
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -811,6 +833,7 @@ CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
 
 #
 # USB Host Controller Drivers
@@ -829,6 +852,7 @@ CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=y
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
 CONFIG_USB_STORAGE_DATAFAB=y
 CONFIG_USB_STORAGE_FREECOM=y
 CONFIG_USB_STORAGE_ISD200=y
@@ -853,6 +877,7 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 
@@ -959,6 +984,7 @@ CONFIG_USB_EZUSB=y
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -997,6 +1023,7 @@ CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
 CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -1004,6 +1031,8 @@ CONFIG_UDF_FS=m
 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
 
 #
@@ -1016,8 +1045,8 @@ CONFIG_SYSFS=y
 CONFIG_DEVPTS_FS_XATTR=y
 # CONFIG_DEVPTS_FS_SECURITY is not set
 CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
 
 #
@@ -1030,7 +1059,7 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -1054,11 +1083,14 @@ CONFIG_EXPORTFS=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=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_POSIX is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -1076,7 +1108,6 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
@@ -1110,6 +1141,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # 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
@@ -1135,13 +1167,16 @@ CONFIG_OPROFILE=y
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUGGER is not set
 # CONFIG_PPCDBG is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_IRQSTACKS=y
+# CONFIG_SCHEDSTATS is not set
 
 #
 # Security options
@@ -1159,6 +1194,7 @@ CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -1166,14 +1202,19 @@ CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
 CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
 CONFIG_CRYPTO_TEST=m
 
 #
 # Library routines
 #
+CONFIG_CRC_CCITT=m
 CONFIG_CRC32=y
-CONFIG_ZLIB_INFLATE=m
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
index f550387..7398114 100644 (file)
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Thu Sep 23 16:45:05 2004
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -16,27 +18,35 @@ CONFIG_FORCE_MAX_ZONEORDER=13
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -48,25 +58,31 @@ CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_KMOD is not set
 CONFIG_STOP_MACHINE=y
+CONFIG_SYSVIPC_COMPAT=y
 
 #
 # Platform support
 #
 # CONFIG_PPC_ISERIES is not set
+CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_PPC_PSERIES=y
+# CONFIG_PPC_PMAC is not set
 CONFIG_PPC=y
 CONFIG_PPC64=y
 CONFIG_PPC_OF=y
 CONFIG_ALTIVEC=y
-# CONFIG_PPC_PMAC is not set
+CONFIG_PPC_SPLPAR=y
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_POWER4_ONLY is not set
-# CONFIG_IOMMU_VMERGE is not set
+CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
 CONFIG_IRQ_ALL_CPUS=y
-CONFIG_NR_CPUS=32
+CONFIG_NR_CPUS=128
 # CONFIG_HMT is not set
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_NUMA=y
+CONFIG_SCHED_SMT=y
+# CONFIG_PREEMPT is not set
 CONFIG_PPC_RTAS=y
 CONFIG_RTAS_FLASH=m
 CONFIG_SCANLOG=m
@@ -81,6 +97,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+CONFIG_HOTPLUG_CPU=y
 
 #
 # PCMCIA/CardBus support
@@ -107,7 +124,9 @@ CONFIG_PROC_DEVICETREE=y
 #
 # Generic Driver Options
 #
-CONFIG_FW_LOADER=m
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -127,7 +146,7 @@ CONFIG_FW_LOADER=m
 #
 # Block devices
 #
-CONFIG_BLK_DEV_FD=y
+CONFIG_BLK_DEV_FD=m
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -135,7 +154,8 @@ CONFIG_BLK_DEV_FD=y
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -149,9 +169,9 @@ CONFIG_BLK_DEV_IDE=y
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -173,7 +193,6 @@ 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_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 CONFIG_BLK_DEV_AMD74XX=y
@@ -194,6 +213,7 @@ CONFIG_BLK_DEV_AMD74XX=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
@@ -219,7 +239,6 @@ CONFIG_CHR_DEV_SG=y
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_REPORT_LUNS=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
@@ -233,28 +252,32 @@ CONFIG_SCSI_FC_ATTRS=y
 # SCSI low-level drivers
 #
 # 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_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
+CONFIG_SCSI_IBMVSCSI=m
 # CONFIG_SCSI_INIA100 is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_IPR=y
+# CONFIG_SCSI_IPR_TRACE is not set
+# CONFIG_SCSI_IPR_DUMP is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -277,11 +300,15 @@ CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
-# CONFIG_MD_MULTIPATH is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
 
 #
 # Fusion MPT device support
@@ -296,6 +323,7 @@ CONFIG_DM_CRYPT=m
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Macintosh device drivers
@@ -322,19 +350,17 @@ CONFIG_NET_IPIP=y
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
-CONFIG_INET_ECN=y
 CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=y
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -342,6 +368,8 @@ CONFIG_NETFILTER=y
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
 CONFIG_IP_NF_TFTP=m
@@ -366,8 +394,14 @@ CONFIG_IP_NF_MATCH_HELPER=m
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -386,9 +420,8 @@ CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_MARK=m
 CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
@@ -400,10 +433,11 @@ CONFIG_XFRM_USER=m
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP 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_LLC=y
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
@@ -419,28 +453,35 @@ CONFIG_LLC=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_RX=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 CONFIG_NET_VENDOR_3COM=y
@@ -452,6 +493,7 @@ CONFIG_VORTEX=y
 #
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
+CONFIG_IBMVETH=m
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
 # CONFIG_AMD8111_ETH is not set
@@ -471,6 +513,7 @@ CONFIG_E100=y
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -484,7 +527,6 @@ CONFIG_E1000=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 CONFIG_TIGON3=y
 
@@ -493,59 +535,40 @@ CONFIG_TIGON3=y
 #
 CONFIG_IXGB=m
 # CONFIG_IXGB_NAPI is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_IBMVETH=m
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+CONFIG_S2IO=m
+# CONFIG_S2IO_NAPI is not set
 
 #
 # Token Ring devices
 #
 CONFIG_TR=y
 CONFIG_IBMOL=y
-# CONFIG_IBMLS is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-CONFIG_NETCONSOLE=y
 
 #
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# Bluetooth support
+# Wan interfaces
 #
-# CONFIG_BT is not set
-CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
 
 #
 # ISDN subsystem
@@ -584,6 +607,7 @@ CONFIG_SERIO_I8042=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -591,15 +615,17 @@ CONFIG_SERIO_I8042=y
 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_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 CONFIG_INPUT_MISC=y
-CONFIG_INPUT_PCSPKR=y
+# CONFIG_INPUT_PCSPKR is not set
 # CONFIG_INPUT_UINPUT is not set
 
 #
@@ -624,16 +650,12 @@ CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_PMACZILOG is not set
+CONFIG_SERIAL_ICOM=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 CONFIG_HVC_CONSOLE=y
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+CONFIG_HVCS=m
 
 #
 # IPMI
@@ -656,7 +678,7 @@ CONFIG_HVC_CONSOLE=y
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
-CONFIG_MAX_RAW_DEVS=256
+CONFIG_MAX_RAW_DEVS=1024
 
 #
 # I2C support
@@ -669,11 +691,13 @@ CONFIG_I2C=y
 #
 CONFIG_I2C_ALGOBIT=y
 # 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
@@ -691,29 +715,51 @@ CONFIG_I2C_ALGOBIT=y
 # 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
 
 #
-# I2C Hardware Sensors Chip support
+# Hardware Sensors Chip support
 #
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
 
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
 #
 # Misc devices
 #
@@ -732,12 +778,14 @@ CONFIG_I2C_ALGOBIT=y
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
 # CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
 # CONFIG_FB_RIVA is not set
 CONFIG_FB_MATROX=y
@@ -765,10 +813,8 @@ CONFIG_FB_RADEON_I2C=y
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -798,11 +844,14 @@ CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
 
 #
 # USB Host Controller Drivers
 #
 CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_UHCI_HCD is not set
 
@@ -814,6 +863,7 @@ CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_PRINTER is not set
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -834,7 +884,10 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
 # CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
 
 #
 # USB Imaging devices
@@ -881,6 +934,8 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -905,7 +960,10 @@ CONFIG_FS_MBCACHE=y
 CONFIG_REISERFS_FS=y
 # CONFIG_REISERFS_CHECK is not set
 # CONFIG_REISERFS_PROC_INFO is not set
-CONFIG_JFS_FS=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
@@ -928,6 +986,7 @@ CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
 CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -935,6 +994,8 @@ CONFIG_UDF_FS=m
 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
 
 #
@@ -942,6 +1003,7 @@ CONFIG_VFAT_FS=y
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 CONFIG_DEVPTS_FS_XATTR=y
 # CONFIG_DEVPTS_FS_SECURITY is not set
@@ -974,18 +1036,22 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
+CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=m
-CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1001,7 +1067,7 @@ CONFIG_MSDOS_PARTITION=y
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+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
@@ -1024,7 +1090,8 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ASCII=y
+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
@@ -1049,15 +1116,18 @@ CONFIG_OPROFILE=y
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
 # CONFIG_PPCDBG is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_IRQSTACKS=y
+# CONFIG_SCHEDSTATS is not set
 
 #
 # Security options
@@ -1071,24 +1141,31 @@ CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_WHIRLPOOL=m
+CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=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_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_TEST=m
 
 #
 # Library routines
 #
+CONFIG_CRC_CCITT=m
 CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
index 33e1086..c53f079 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/version.h>
 
 #include <asm/sections.h>
-#include <asm/bootx.h>
+#include <asm/prom.h>
 #include <asm/btext.h>
 #include <asm/prom.h>
 #include <asm/page.h>
@@ -36,6 +36,11 @@ static int g_loc_Y;
 static int g_max_loc_X;
 static int g_max_loc_Y;
 
+static int dispDeviceRowBytes;
+static int dispDeviceDepth;
+static int dispDeviceRect[4];
+static unsigned char *dispDeviceBase, *logicalDisplayBase;
+
 unsigned long disp_BAT[2] __initdata = {0, 0};
 
 #define cmapsz (16*256)
@@ -45,30 +50,6 @@ static unsigned char vga_font[cmapsz];
 int boot_text_mapped;
 int force_printk_to_btext = 0;
 
-boot_infos_t disp_bi;
-
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
- */
-void __init btext_setup_display(int width, int height, int depth, int pitch,
-                   unsigned long address)
-{
-       unsigned long offset = reloc_offset();
-       boot_infos_t* bi = PTRRELOC(&disp_bi);
-
-       RELOC(g_loc_X) = 0;
-       RELOC(g_loc_Y) = 0;
-       RELOC(g_max_loc_X) = width / 8;
-       RELOC(g_max_loc_Y) = height / 16;
-       bi->logicalDisplayBase = (unsigned char *)address;
-       bi->dispDeviceBase = (unsigned char *)address;
-       bi->dispDeviceRowBytes = pitch;
-       bi->dispDeviceDepth = depth;
-       bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
-       bi->dispDeviceRect[2] = width;
-       bi->dispDeviceRect[3] = height;
-       RELOC(boot_text_mapped) = 1;
-}
 
 /* Here's a small text engine to use during early boot
  * or for debugging purposes
@@ -84,34 +65,84 @@ void __init btext_setup_display(int width, int height, int depth, int pitch,
 void map_boot_text(void)
 {
        unsigned long base, offset, size;
-       boot_infos_t *bi = &disp_bi;
        unsigned char *vbase;
 
        /* By default, we are no longer mapped */
        boot_text_mapped = 0;
-       if (bi->dispDeviceBase == 0)
+       if (dispDeviceBase == 0)
                return;
-       base = ((unsigned long) bi->dispDeviceBase) & 0xFFFFF000UL;
-       offset = ((unsigned long) bi->dispDeviceBase) - base;
-       size = bi->dispDeviceRowBytes * bi->dispDeviceRect[3] + offset
-               + bi->dispDeviceRect[0];
+       base = ((unsigned long) dispDeviceBase) & 0xFFFFF000UL;
+       offset = ((unsigned long) dispDeviceBase) - base;
+       size = dispDeviceRowBytes * dispDeviceRect[3] + offset
+               + dispDeviceRect[0];
        vbase = __ioremap(base, size, _PAGE_NO_CACHE);
        if (vbase == 0)
                return;
-       bi->logicalDisplayBase = vbase + offset;
+       logicalDisplayBase = vbase + offset;
        boot_text_mapped = 1;
 }
 
+int btext_initialize(struct device_node *np)
+{
+       unsigned int width, height, depth, pitch;
+       unsigned long address = 0;
+       u32 *prop;
+
+       prop = (u32 *)get_property(np, "width", NULL);
+       if (prop == NULL)
+               return -EINVAL;
+       width = *prop;
+       prop = (u32 *)get_property(np, "height", NULL);
+       if (prop == NULL)
+               return -EINVAL;
+       height = *prop;
+       prop = (u32 *)get_property(np, "depth", NULL);
+       if (prop == NULL)
+               return -EINVAL;
+       depth = *prop;
+       pitch = width * ((depth + 7) / 8);
+       prop = (u32 *)get_property(np, "linebytes", NULL);
+       if (prop)
+               pitch = *prop;
+       if (pitch == 1)
+               pitch = 0x1000;
+       prop = (u32 *)get_property(np, "address", NULL);
+       if (prop)
+               address = *prop;
+
+       /* FIXME: Add support for PCI reg properties */
+
+       if (address == 0)
+               return -EINVAL;
+
+       g_loc_X = 0;
+       g_loc_Y = 0;
+       g_max_loc_X = width / 8;
+       g_max_loc_Y = height / 16;
+       logicalDisplayBase = (unsigned char *)address;
+       dispDeviceBase = (unsigned char *)address;
+       dispDeviceRowBytes = pitch;
+       dispDeviceDepth = depth;
+       dispDeviceRect[0] = dispDeviceRect[1] = 0;
+       dispDeviceRect[2] = width;
+       dispDeviceRect[3] = height;
+
+       map_boot_text();
+
+       return 0;
+}
+
+
 /* Calc the base address of a given point (x,y) */
-static unsigned char * calc_base(boot_infos_t *bi, int x, int y)
+static unsigned char * calc_base(int x, int y)
 {
        unsigned char *base;
 
-       base = bi->logicalDisplayBase;
+       base = logicalDisplayBase;
        if (base == 0)
-               base = bi->dispDeviceBase;
-       base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3);
-       base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes;
+               base = dispDeviceBase;
+       base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3);
+       base += (y + dispDeviceRect[1]) * dispDeviceRowBytes;
        return base;
 }
 
@@ -119,24 +150,22 @@ static unsigned char * calc_base(boot_infos_t *bi, int x, int y)
 void btext_update_display(unsigned long phys, int width, int height,
                          int depth, int pitch)
 {
-       boot_infos_t *bi = &disp_bi;
-
-       if (bi->dispDeviceBase == 0)
+       if (dispDeviceBase == 0)
                return;
 
        /* check it's the same frame buffer (within 256MB) */
-       if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000)
+       if ((phys ^ (unsigned long)dispDeviceBase) & 0xf0000000)
                return;
 
-       bi->dispDeviceBase = (__u8 *) phys;
-       bi->dispDeviceRect[0] = 0;
-       bi->dispDeviceRect[1] = 0;
-       bi->dispDeviceRect[2] = width;
-       bi->dispDeviceRect[3] = height;
-       bi->dispDeviceDepth = depth;
-       bi->dispDeviceRowBytes = pitch;
+       dispDeviceBase = (__u8 *) phys;
+       dispDeviceRect[0] = 0;
+       dispDeviceRect[1] = 0;
+       dispDeviceRect[2] = width;
+       dispDeviceRect[3] = height;
+       dispDeviceDepth = depth;
+       dispDeviceRowBytes = pitch;
        if (boot_text_mapped) {
-               iounmap(bi->logicalDisplayBase);
+               iounmap(logicalDisplayBase);
                boot_text_mapped = 0;
        }
        map_boot_text();
@@ -148,108 +177,101 @@ void btext_update_display(unsigned long phys, int width, int height,
 
 void btext_clearscreen(void)
 {
-       unsigned long offset = reloc_offset();
-       boot_infos_t* bi        = PTRRELOC(&disp_bi);
-       unsigned long *base     = (unsigned long *)calc_base(bi, 0, 0);
-       unsigned long width     = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
-                                       (bi->dispDeviceDepth >> 3)) >> 3;
+       unsigned long *base     = (unsigned long *)calc_base(0, 0);
+       unsigned long width     = ((dispDeviceRect[2] - dispDeviceRect[0]) *
+                                       (dispDeviceDepth >> 3)) >> 3;
        int i,j;
 
-       for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++)
+       for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
        {
                unsigned long *ptr = base;
                for(j=width; j; --j)
                        *(ptr++) = 0;
-               base += (bi->dispDeviceRowBytes >> 3);
+               base += (dispDeviceRowBytes >> 3);
        }
 }
 
 #ifndef NO_SCROLL
 static void scrollscreen(void)
 {
-       unsigned long offset    = reloc_offset();
-       boot_infos_t* bi        = PTRRELOC(&disp_bi);
-       unsigned long *src      = (unsigned long *)calc_base(bi,0,16);
-       unsigned long *dst      = (unsigned long *)calc_base(bi,0,0);
-       unsigned long width     = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
-                                  (bi->dispDeviceDepth >> 3)) >> 3;
+       unsigned long *src      = (unsigned long *)calc_base(0,16);
+       unsigned long *dst      = (unsigned long *)calc_base(0,0);
+       unsigned long width     = ((dispDeviceRect[2] - dispDeviceRect[0]) *
+                                  (dispDeviceDepth >> 3)) >> 3;
        int i,j;
 
-       for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++)
+       for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
        {
                unsigned long *src_ptr = src;
                unsigned long *dst_ptr = dst;
                for(j=width; j; --j)
                        *(dst_ptr++) = *(src_ptr++);
-               src += (bi->dispDeviceRowBytes >> 3);
-               dst += (bi->dispDeviceRowBytes >> 3);
+               src += (dispDeviceRowBytes >> 3);
+               dst += (dispDeviceRowBytes >> 3);
        }
        for (i=0; i<16; i++)
        {
                unsigned long *dst_ptr = dst;
                for(j=width; j; --j)
                        *(dst_ptr++) = 0;
-               dst += (bi->dispDeviceRowBytes >> 3);
+               dst += (dispDeviceRowBytes >> 3);
        }
 }
 #endif /* ndef NO_SCROLL */
 
 void btext_drawchar(char c)
 {
-       unsigned long offset = reloc_offset();
        int cline = 0;
 #ifdef NO_SCROLL
        int x;
 #endif
-       if (!RELOC(boot_text_mapped))
+       if (!boot_text_mapped)
                return;
 
        switch (c) {
        case '\b':
-               if (RELOC(g_loc_X) > 0)
-                       --RELOC(g_loc_X);
+               if (g_loc_X > 0)
+                       --g_loc_X;
                break;
        case '\t':
-               RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8;
+               g_loc_X = (g_loc_X & -8) + 8;
                break;
        case '\r':
-               RELOC(g_loc_X) = 0;
+               g_loc_X = 0;
                break;
        case '\n':
-               RELOC(g_loc_X) = 0;
-               RELOC(g_loc_Y)++;
+               g_loc_X = 0;
+               g_loc_Y++;
                cline = 1;
                break;
        default:
-               draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y));
+               draw_byte(c, g_loc_X++, g_loc_Y);
        }
-       if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) {
-               RELOC(g_loc_X) = 0;
-               RELOC(g_loc_Y)++;
+       if (g_loc_X >= g_max_loc_X) {
+               g_loc_X = 0;
+               g_loc_Y++;
                cline = 1;
        }
 #ifndef NO_SCROLL
-       while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) {
+       while (g_loc_Y >= g_max_loc_Y) {
                scrollscreen();
-               RELOC(g_loc_Y)--;
+               g_loc_Y--;
        }
 #else
        /* wrap around from bottom to top of screen so we don't
           waste time scrolling each line.  -- paulus. */
-       if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y))
-               RELOC(g_loc_Y) = 0;
+       if (g_loc_Y >= g_max_loc_Y)
+               g_loc_Y = 0;
        if (cline) {
-               for (x = 0; x < RELOC(g_max_loc_X); ++x)
-                       draw_byte(' ', x, RELOC(g_loc_Y));
+               for (x = 0; x < g_max_loc_X; ++x)
+                       draw_byte(' ', x, g_loc_Y);
        }
 #endif
 }
 
 void btext_drawstring(const char *c)
 {
-       unsigned long offset = reloc_offset();
-
-       if (!RELOC(boot_text_mapped))
+       if (!boot_text_mapped)
                return;
        while (*c)
                btext_drawchar(*c++);
@@ -257,10 +279,9 @@ void btext_drawstring(const char *c)
 
 void btext_drawhex(unsigned long v)
 {
-       unsigned long offset = reloc_offset();
-       char *hex_table = RELOC("0123456789abcdef");
+       char *hex_table = "0123456789abcdef";
 
-       if (!RELOC(boot_text_mapped))
+       if (!boot_text_mapped)
                return;
        btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]);
        btext_drawchar(hex_table[(v >> 56) & 0x0000000FUL]);
@@ -283,14 +304,11 @@ void btext_drawhex(unsigned long v)
 
 static void draw_byte(unsigned char c, long locX, long locY)
 {
-       unsigned long offset    = reloc_offset();
-       boot_infos_t* bi        = PTRRELOC(&disp_bi);
-       unsigned char *base     = calc_base(bi, locX << 3, locY << 4);
-       unsigned char *font     = PTRRELOC(&vga_font[((unsigned int)c) * 16]);
-       int rb                  = bi->dispDeviceRowBytes;
-
-#if 0
-       switch(bi->dispDeviceDepth) {
+       unsigned char *base     = calc_base(locX << 3, locY << 4);
+       unsigned char *font     = &vga_font[((unsigned int)c) * 16];
+       int rb                  = dispDeviceRowBytes;
+
+       switch(dispDeviceDepth) {
        case 24:
        case 32:
                draw_byte_32(font, (unsigned int *)base, rb);
@@ -303,17 +321,6 @@ static void draw_byte(unsigned char c, long locX, long locY)
                draw_byte_8(font, (unsigned int *)base, rb);
                break;
        }
-#else
-       if(bi->dispDeviceDepth == 24 ||
-          bi->dispDeviceDepth == 32) {
-               draw_byte_32(font, (unsigned int *)base, rb);
-       } else if(bi->dispDeviceDepth == 15 ||
-          bi->dispDeviceDepth == 16) {
-               draw_byte_16(font, (unsigned int *)base, rb);
-       } else if(bi->dispDeviceDepth == 8) {
-               draw_byte_8(font, (unsigned int *)base, rb);
-       } 
-#endif
 }
 
 static unsigned int expand_bits_8[16] = {
@@ -369,8 +376,7 @@ static void draw_byte_16(unsigned char *font, unsigned int *base, int rb)
        int l, bits;
        int fg = 0xFFFFFFFFUL;
        int bg = 0x00000000UL;
-       unsigned long offset = reloc_offset();
-       unsigned int *eb = PTRRELOC((int *)expand_bits_16);
+       unsigned int *eb = (int *)expand_bits_16;
 
        for (l = 0; l < 16; ++l)
        {
@@ -388,8 +394,7 @@ static void draw_byte_8(unsigned char *font, unsigned int *base, int rb)
        int l, bits;
        int fg = 0x0F0F0F0FUL;
        int bg = 0x00000000UL;
-       unsigned long offset = reloc_offset();
-       unsigned int *eb = PTRRELOC((int *)expand_bits_8);
+       unsigned int *eb = (int *)expand_bits_8;
 
        for (l = 0; l < 16; ++l)
        {
index dedefb3..c72fb8f 100644 (file)
@@ -1,6 +1,10 @@
 /*
  * hvconsole.c
  * Copyright (C) 2004 Hollis Blanchard, IBM Corporation
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Additional Author(s):
+ *  Ryan S. Arnold <rsa@us.ibm.com>
  *
  * LPAR console support.
  * 
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <asm/hvcall.h>
-#include <asm/prom.h>
 #include <asm/hvconsole.h>
+#include <asm/prom.h>
 
-int hvc_get_chars(int index, char *buf, int count)
+/**
+ * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper
+ * @vtermno: The vtermno or unit_address of the adapter from which to fetch the
+ *     data.
+ * @buf: The character buffer into which to put the character data fetched from
+ *     firmware.
+ * @count: not used?
+ */
+int hvc_get_chars(uint32_t vtermno, char *buf, int count)
 {
        unsigned long got;
 
-       if (plpar_hcall(H_GET_TERM_CHAR, index, 0, 0, 0, &got,
+       if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
                (unsigned long *)buf, (unsigned long *)buf+1) == H_Success) {
                /*
                 * Work around a HV bug where it gives us a null
@@ -53,40 +65,56 @@ int hvc_get_chars(int index, char *buf, int count)
 
 EXPORT_SYMBOL(hvc_get_chars);
 
-int hvc_put_chars(int index, const char *buf, int count)
+/**
+ * hvc_put_chars: send characters to firmware for denoted vterm adapter
+ * @vtermno: The vtermno or unit_address of the adapter from which the data
+ *     originated.
+ * @buf: The character buffer that contains the character data to send to
+ *     firmware.
+ * @count: Send this number of characters.
+ */
+int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
 {
        unsigned long *lbuf = (unsigned long *) buf;
        long ret;
 
-       ret = plpar_hcall_norets(H_PUT_TERM_CHAR, index, count, lbuf[0],
+       ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0],
                                 lbuf[1]);
        if (ret == H_Success)
                return count;
        if (ret == H_Busy)
                return 0;
-       return -1;
+       return -EIO;
 }
 
 EXPORT_SYMBOL(hvc_put_chars);
 
-/* return the number of client vterms present */
-/* XXX this requires an interface change to handle multiple discontiguous
- * vterms */
-int hvc_count(int *start_termno)
+/*
+ * We hope/assume that the first vty found corresponds to the first console
+ * device.
+ */
+int hvc_find_vtys(void)
 {
        struct device_node *vty;
        int num_found = 0;
 
-       /* consider only the first vty node.
-        * we should _always_ be able to find one. */
-       vty = of_find_node_by_name(NULL, "vty");
-       if (vty && device_is_compatible(vty, "hvterm1")) {
-               u32 *termno = (u32 *)get_property(vty, "reg", NULL);
+       for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
+                       vty = of_find_node_by_name(vty, "vty")) {
+               uint32_t *vtermno;
+
+               /* We have statically defined space for only a certain number of
+                * console adapters. */
+               if (num_found >= MAX_NR_HVC_CONSOLES)
+                       break;
 
-               if (termno && start_termno)
-                       *start_termno = *termno;
-               num_found = 1;
-               of_node_put(vty);
+               vtermno = (uint32_t *)get_property(vty, "reg", NULL);
+               if (!vtermno)
+                       continue;
+
+               if (device_is_compatible(vty, "hvterm1")) {
+                       hvc_instantiate(*vtermno, num_found);
+                       ++num_found;
+               }
        }
 
        return num_found;
index fbe445e..bde8f42 100644 (file)
@@ -61,14 +61,21 @@ int hvcs_convert(long to_convert)
        }
 }
 
+/**
+ * hvcs_free_partner_info - free pi allocated by hvcs_get_partner_info
+ * @head: list_head pointer for an allocated list of partner info structs to
+ *     free.
+ *
+ * This function is used to free the partner info list that was returned by
+ * calling hvcs_get_partner_info().
+ */
 int hvcs_free_partner_info(struct list_head *head)
 {
        struct hvcs_partner_info *pi;
        struct list_head *element;
 
-       if (!head) {
+       if (!head)
                return -EINVAL;
-       }
 
        while (!list_empty(head)) {
                element = head->next;
@@ -82,7 +89,7 @@ int hvcs_free_partner_info(struct list_head *head)
 EXPORT_SYMBOL(hvcs_free_partner_info);
 
 /* Helper function for hvcs_get_partner_info */
-int hvcs_next_partner(unsigned int unit_address,
+int hvcs_next_partner(uint32_t unit_address,
                unsigned long last_p_partition_ID,
                unsigned long last_p_unit_address, unsigned long *pi_buff)
 
@@ -94,25 +101,37 @@ int hvcs_next_partner(unsigned int unit_address,
        return hvcs_convert(retval);
 }
 
-/*
- * The unit_address parameter is the unit address of the vty-server vdevice
- * in whose partner information the caller is interested.  This function
- * uses a pointer to a list_head instance in which to store the partner info.
+/**
+ * hvcs_get_partner_info - Get all of the partner info for a vty-server adapter
+ * @unit_address: The unit_address of the vty-server adapter for which this
+ *     function is fetching partner info.
+ * @head: An initialized list_head pointer to an empty list to use to return the
+ *     list of partner info fetched from the hypervisor to the caller.
+ * @pi_buff: A page sized buffer pre-allocated prior to calling this function
+ *     that is to be used to be used by firmware as an iterator to keep track
+ *     of the partner info retrieval.
+ *
  * This function returns non-zero on success, or if there is no partner info.
  *
+ * The pi_buff is pre-allocated prior to calling this function because this
+ * function may be called with a spin_lock held and kmalloc of a page is not
+ * recommended as GFP_ATOMIC.
+ *
+ * The first long of this buffer is used to store a partner unit address.  The
+ * second long is used to store a partner partition ID and starting at
+ * pi_buff[2] is the 79 character Converged Location Code (diff size than the
+ * unsigned longs, hence the casting mumbo jumbo you see later).
+ *
  * Invocation of this function should always be followed by an invocation of
  * hvcs_free_partner_info() using a pointer to the SAME list head instance
- * that was used to store the partner_info list.
+ * that was passed as a parameter to this function.
  */
-int hvcs_get_partner_info(unsigned int unit_address, struct list_head *head,
+int hvcs_get_partner_info(uint32_t unit_address, struct list_head *head,
                unsigned long *pi_buff)
 {
        /*
-        * This is a page sized buffer to be passed to hvcall per invocation.
-        * NOTE: the first long returned is unit_address.  The second long
-        * returned is the partition ID and starting with pi_buff[2] are
-        * HVCS_CLC_LENGTH characters, which are diff size than the unsigned
-        * long, hence the casting mumbojumbo you see later.
+        * Dealt with as longs because of the hcall interface even though the
+        * values are uint32_t.
         */
        unsigned long   last_p_partition_ID;
        unsigned long   last_p_unit_address;
@@ -122,15 +141,12 @@ int hvcs_get_partner_info(unsigned int unit_address, struct list_head *head,
 
        memset(pi_buff, 0x00, PAGE_SIZE);
        /* invalid parameters */
-       if (!head)
+       if (!head || !pi_buff)
                return -EINVAL;
 
        last_p_partition_ID = last_p_unit_address = ~0UL;
        INIT_LIST_HEAD(head);
 
-       if (!pi_buff)
-               return -ENOMEM;
-
        do {
                retval = hvcs_next_partner(unit_address, last_p_partition_ID,
                                last_p_unit_address, pi_buff);
@@ -183,21 +199,29 @@ int hvcs_get_partner_info(unsigned int unit_address, struct list_head *head,
 }
 EXPORT_SYMBOL(hvcs_get_partner_info);
 
-/*
+/**
+ * hvcs_register_connection - establish a connection between this vty-server and
+ *     a vty.
+ * @unit_address: The unit address of the vty-server adapter that is to be
+ *     establish a connection.
+ * @p_partition_ID: The partition ID of the vty adapter that is to be connected.
+ * @p_unit_address: The unit address of the vty adapter to which the vty-server
+ *     is to be connected.
+ *
  * If this function is called once and -EINVAL is returned it may
  * indicate that the partner info needs to be refreshed for the
  * target unit address at which point the caller must invoke
  * hvcs_get_partner_info() and then call this function again.  If,
  * for a second time, -EINVAL is returned then it indicates that
  * there is probably already a partner connection registered to a
- * different vty-server@ vdevice.  It is also possible that a second
+ * different vty-server adapter.  It is also possible that a second
  * -EINVAL may indicate that one of the parms is not valid, for
- * instance if the link was removed between the vty-server@ vdevice
- * and the vty@ vdevice that you are trying to open.  Don't shoot the
+ * instance if the link was removed between the vty-server adapter
+ * and the vty adapter that you are trying to open.  Don't shoot the
  * messenger.  Firmware implemented it this way.
  */
-int hvcs_register_connection( unsigned int unit_address,
-               unsigned int p_partition_ID, unsigned int p_unit_address)
+int hvcs_register_connection( uint32_t unit_address,
+               uint32_t p_partition_ID, uint32_t p_unit_address)
 {
        long retval;
        retval = plpar_hcall_norets(H_REGISTER_VTERM, unit_address,
@@ -206,11 +230,17 @@ int hvcs_register_connection( unsigned int unit_address,
 }
 EXPORT_SYMBOL(hvcs_register_connection);
 
-/*
- * If -EBUSY is returned continue to call this function
- * until 0 is returned.
+/**
+ * hvcs_free_connection - free the connection between a vty-server and vty
+ * @unit_address: The unit address of the vty-server that is to have its
+ *     connection severed.
+ *
+ * This function is used to free the partner connection between a vty-server
+ * adapter and a vty adapter.
+ *
+ * If -EBUSY is returned continue to call this function until 0 is returned.
  */
-int hvcs_free_connection(unsigned int unit_address)
+int hvcs_free_connection(uint32_t unit_address)
 {
        long retval;
        retval = plpar_hcall_norets(H_FREE_VTERM, unit_address);
index 2456227..b1177b4 100644 (file)
@@ -233,4 +233,6 @@ void hpte_init_iSeries(void)
        ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
        ppc_md.hpte_insert      = iSeries_hpte_insert;
        ppc_md.hpte_remove      = iSeries_hpte_remove;
+
+       htab_finish_init();
 }
index 3472d18..d3715a1 100644 (file)
@@ -419,46 +419,39 @@ static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus,
  * I/0 Memory copy MUST use mmio commands on iSeries
  * To do; For performance, include the hv call directly
  */
-void *iSeries_memset_io(void *dest, char c, size_t Count)
+void iSeries_memset_io(volatile void __iomem *dest, char c, size_t Count)
 {
        u8 ByteValue = c;
        long NumberOfBytes = Count;
-       char *IoBuffer = dest;
 
        while (NumberOfBytes > 0) {
-               iSeries_Write_Byte(ByteValue, (void *)IoBuffer);
-               ++IoBuffer;
+               iSeries_Write_Byte(ByteValue, dest++);
                -- NumberOfBytes;
        }
-       return dest;
 }
 EXPORT_SYMBOL(iSeries_memset_io);
 
-void *iSeries_memcpy_toio(void *dest, void *source, size_t count)
+void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t count)
 {
-       char *dst = dest;
        char *src = source;
        long NumberOfBytes = count;
 
        while (NumberOfBytes > 0) {
-               iSeries_Write_Byte(*src++, (void *)dst++);
+               iSeries_Write_Byte(*src++, dest++);
                -- NumberOfBytes;
        }
-       return dest;
 }
 EXPORT_SYMBOL(iSeries_memcpy_toio);
 
-void *iSeries_memcpy_fromio(void *dest, void *source, size_t count)
+void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *src, size_t count)
 {
        char *dst = dest;
-       char *src = source;
        long NumberOfBytes = count;
 
        while (NumberOfBytes > 0) {
-               *dst++ = iSeries_Read_Byte((void *)src++);
+               *dst++ = iSeries_Read_Byte(src++);
                -- NumberOfBytes;
        }
-       return dest;
 }
 EXPORT_SYMBOL(iSeries_memcpy_fromio);
 
@@ -612,17 +605,19 @@ static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode,
  * Note: Make sure the passed variable end up on the stack to avoid
  * the exposure of being device global.
  */
-static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress,
+static inline struct iSeries_Device_Node *xlateIoMmAddress(const volatile void __iomem *IoAddress,
                 u64 *dsaptr, u64 *BarOffsetPtr)
 {
+       unsigned long OrigIoAddr;
        unsigned long BaseIoAddr;
        unsigned long TableIndex;
        struct iSeries_Device_Node *DevNode;
 
-       if (((unsigned long)IoAddress < iSeries_Base_Io_Memory) ||
-                       ((unsigned long)IoAddress >= iSeries_Max_Io_Memory))
+       OrigIoAddr = (unsigned long __force)IoAddress;
+       if ((OrigIoAddr < iSeries_Base_Io_Memory) ||
+                       (OrigIoAddr >= iSeries_Max_Io_Memory))
                return NULL;
-       BaseIoAddr = (unsigned long)IoAddress - iSeries_Base_Io_Memory;
+       BaseIoAddr = OrigIoAddr - iSeries_Base_Io_Memory;
        TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size;
        DevNode = iSeries_IoMmTable[TableIndex];
 
@@ -644,7 +639,7 @@ static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress,
  * iSeries_Read_Word = Read Word  (16 bit)
  * iSeries_Read_Long = Read Long  (32 bit)
  */
-u8 iSeries_Read_Byte(void *IoAddress)
+u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
@@ -673,7 +668,7 @@ u8 iSeries_Read_Byte(void *IoAddress)
 }
 EXPORT_SYMBOL(iSeries_Read_Byte);
 
-u16 iSeries_Read_Word(void *IoAddress)
+u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
@@ -703,7 +698,7 @@ u16 iSeries_Read_Word(void *IoAddress)
 }
 EXPORT_SYMBOL(iSeries_Read_Word);
 
-u32 iSeries_Read_Long(void *IoAddress)
+u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
@@ -740,7 +735,7 @@ EXPORT_SYMBOL(iSeries_Read_Long);
  * iSeries_Write_Word = Write Word(16 bit)
  * iSeries_Write_Long = Write Long(32 bit)
  */
-void iSeries_Write_Byte(u8 data, void *IoAddress)
+void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
@@ -767,7 +762,7 @@ void iSeries_Write_Byte(u8 data, void *IoAddress)
 }
 EXPORT_SYMBOL(iSeries_Write_Byte);
 
-void iSeries_Write_Word(u16 data, void *IoAddress)
+void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
@@ -794,7 +789,7 @@ void iSeries_Write_Word(u16 data, void *IoAddress)
 }
 EXPORT_SYMBOL(iSeries_Write_Word);
 
-void iSeries_Write_Long(u32 data, void *IoAddress)
+void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
@@ -820,7 +815,3 @@ void iSeries_Write_Long(u32 data, void *IoAddress)
        } while (CheckReturnCode("WWL", DevNode, rc) != 0);
 }
 EXPORT_SYMBOL(iSeries_Write_Long);
-
-void pcibios_name_device(struct pci_dev *dev)
-{
-}
index e1e48c3..8848ece 100644 (file)
@@ -65,7 +65,8 @@ int iSeries_Device_ToggleReset(struct pci_dev *PciDev, int AssertTime,
                AssertDelay = (5 * HZ) / 10;
        else
                AssertDelay = (AssertTime * HZ) / 10;
-       if (WaitDelay == 0)
+
+       if (DelayTime == 0)
                WaitDelay = (30 * HZ) / 10;
        else
                WaitDelay = (DelayTime * HZ) / 10;
index 240dad4..098041b 100644 (file)
 #ifndef        __ISERIES_SETUP_H__
 #define        __ISERIES_SETUP_H__
 
-extern void iSeries_init_early(void);
-extern void iSeries_init(unsigned long r3, unsigned long ird_start,
-               unsigned long ird_end, unsigned long cline_start,
-               unsigned long cline_end);
 extern void iSeries_setup_arch(void);
 extern void iSeries_setup_residual(struct seq_file *m, int cpu_id);
 extern void iSeries_get_cpuinfo(struct seq_file *m);
index fb98306..97e4a26 100644 (file)
@@ -46,7 +46,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
        /* Now check if user or arch enabled NAP mode */
        LOADBASE(r3,powersave_nap)
        lwz     r4,powersave_nap@l(r3)
-       cmp   0,r4,0
+       cmpwi   0,r4,0
        beqlr
 
        /* Clear MSR:EE */
diff --git a/arch/ppc64/kernel/iomap.c b/arch/ppc64/kernel/iomap.c
new file mode 100644 (file)
index 0000000..b70a924
--- /dev/null
@@ -0,0 +1,119 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+
+/*
+ * Here comes the ppc64 implementation of the IOMAP 
+ * interfaces.
+ */
+unsigned int fastcall ioread8(void __iomem *addr)
+{
+       return readb(addr);
+}
+unsigned int fastcall ioread16(void __iomem *addr)
+{
+       return readw(addr);
+}
+unsigned int fastcall ioread32(void __iomem *addr)
+{
+       return readl(addr);
+}
+EXPORT_SYMBOL(ioread8);
+EXPORT_SYMBOL(ioread16);
+EXPORT_SYMBOL(ioread32);
+
+void fastcall iowrite8(u8 val, void __iomem *addr)
+{
+       writeb(val, addr);
+}
+void fastcall iowrite16(u16 val, void __iomem *addr)
+{
+       writew(val, addr);
+}
+void fastcall iowrite32(u32 val, void __iomem *addr)
+{
+       writel(val, addr);
+}
+EXPORT_SYMBOL(iowrite8);
+EXPORT_SYMBOL(iowrite16);
+EXPORT_SYMBOL(iowrite32);
+
+/*
+ * These are the "repeat read/write" functions. Note the
+ * non-CPU byte order. We do things in "IO byteorder"
+ * here.
+ *
+ * FIXME! We could make these do EEH handling if we really
+ * wanted. Not clear if we do.
+ */
+void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+       _insb((u8 __force *) addr, dst, count);
+}
+void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+       _insw_ns((u16 __force *) addr, dst, count);
+}
+void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+       _insl_ns((u32 __force *) addr, dst, count);
+}
+EXPORT_SYMBOL(ioread8_rep);
+EXPORT_SYMBOL(ioread16_rep);
+EXPORT_SYMBOL(ioread32_rep);
+
+void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+       _outsb((u8 __force *) addr, src, count);
+}
+void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+       _outsw_ns((u16 __force *) addr, src, count);
+}
+void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+       _outsl_ns((u32 __force *) addr, src, count);
+}
+EXPORT_SYMBOL(iowrite8_rep);
+EXPORT_SYMBOL(iowrite16_rep);
+EXPORT_SYMBOL(iowrite32_rep);
+
+void __iomem *ioport_map(unsigned long port, unsigned int len)
+{
+       if (!_IO_IS_VALID(port))
+               return NULL;
+       return (void __iomem *) (port+pci_io_base);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+       /* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (!len)
+               return NULL;
+       if (max && len > max)
+               len = max;
+       if (flags & IORESOURCE_IO)
+               return ioport_map(start, len);
+       if (flags & IORESOURCE_MEM)
+               return (void __iomem *) start;
+       /* What? */
+       return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+       /* Nothing to do */
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
index c2e3206..56a26ee 100644 (file)
 #include <asm/abs_addr.h>
 #include <asm/bitops.h>
 
-struct lmb lmb __initdata;
+struct lmb lmb;
+
+#undef DEBUG
+
+void lmb_dump_all(void)
+{
+#ifdef DEBUG
+       unsigned long i;
+       struct lmb *_lmb  = &lmb;
+
+       udbg_printf("lmb_dump_all:\n");
+       udbg_printf("    memory.cnt               = 0x%lx\n",
+                   _lmb->memory.cnt);
+       udbg_printf("    memory.size              = 0x%lx\n",
+                   _lmb->memory.size);
+       for (i=0; i < _lmb->memory.cnt ;i++) {
+               udbg_printf("    memory.region[0x%x].base       = 0x%lx\n",
+                           i, _lmb->memory.region[i].base);
+               udbg_printf("                 .physbase = 0x%lx\n",
+                           _lmb->memory.region[i].physbase);
+               udbg_printf("                 .size     = 0x%lx\n",
+                           _lmb->memory.region[i].size);
+       }
+
+       udbg_printf("\n    reserved.cnt   = 0x%lx\n",
+                   _lmb->reserved.cnt);
+       udbg_printf("    reserved.size    = 0x%lx\n",
+                   _lmb->reserved.size);
+       for (i=0; i < _lmb->reserved.cnt ;i++) {
+               udbg_printf("    reserved.region[0x%x].base       = 0x%lx\n",
+                           i, _lmb->reserved.region[i].base);
+               udbg_printf("                 .physbase = 0x%lx\n",
+                           _lmb->reserved.region[i].physbase);
+               udbg_printf("                 .size     = 0x%lx\n",
+                           _lmb->reserved.region[i].size);
+       }
+#endif /* DEBUG */
+}
 
 static unsigned long __init
 lmb_addrs_overlap(unsigned long base1, unsigned long size1,
@@ -71,8 +108,7 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
 void __init
 lmb_init(void)
 {
-       unsigned long offset = reloc_offset();
-       struct lmb *_lmb = PTRRELOC(&lmb);
+       struct lmb *_lmb = &lmb;
 
        /* Create a dummy zero size LMB which will get coalesced away later.
         * This simplifies the lmb_add() code below...
@@ -94,8 +130,7 @@ lmb_analyze(void)
        unsigned long i;
        unsigned long mem_size = 0;
        unsigned long size_mask = 0;
-       unsigned long offset = reloc_offset();
-       struct lmb *_lmb = PTRRELOC(&lmb);
+       struct lmb *_lmb = &lmb;
 #ifdef CONFIG_MSCHUNKS
        unsigned long physbase = 0;
 #endif
@@ -178,8 +213,7 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
 long __init
 lmb_add(unsigned long base, unsigned long size)
 {
-       unsigned long offset = reloc_offset();
-       struct lmb *_lmb = PTRRELOC(&lmb);
+       struct lmb *_lmb = &lmb;
        struct lmb_region *_rgn = &(_lmb->memory);
 
        /* On pSeries LPAR systems, the first LMB is our RMO region. */
@@ -193,8 +227,7 @@ lmb_add(unsigned long base, unsigned long size)
 long __init
 lmb_reserve(unsigned long base, unsigned long size)
 {
-       unsigned long offset = reloc_offset();
-       struct lmb *_lmb = PTRRELOC(&lmb);
+       struct lmb *_lmb = &lmb;
        struct lmb_region *_rgn = &(_lmb->reserved);
 
        return lmb_add_region(_rgn, base, size);
@@ -227,8 +260,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
 {
        long i, j;
        unsigned long base = 0;
-       unsigned long offset = reloc_offset();
-       struct lmb *_lmb = PTRRELOC(&lmb);
+       struct lmb *_lmb = &lmb;
        struct lmb_region *_mem = &(_lmb->memory);
        struct lmb_region *_rsv = &(_lmb->reserved);
 
@@ -263,8 +295,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
 unsigned long __init
 lmb_phys_mem_size(void)
 {
-       unsigned long offset = reloc_offset();
-       struct lmb *_lmb = PTRRELOC(&lmb);
+       struct lmb *_lmb = &lmb;
 #ifdef CONFIG_MSCHUNKS
        return _lmb->memory.size;
 #else
@@ -282,8 +313,7 @@ lmb_phys_mem_size(void)
 unsigned long __init
 lmb_end_of_DRAM(void)
 {
-       unsigned long offset = reloc_offset();
-       struct lmb *_lmb = PTRRELOC(&lmb);
+       struct lmb *_lmb = &lmb;
        struct lmb_region *_mem = &(_lmb->memory);
        int idx = _mem->cnt - 1;
 
@@ -300,8 +330,7 @@ unsigned long __init
 lmb_abs_to_phys(unsigned long aa)
 {
        unsigned long i, pa = aa;
-       unsigned long offset = reloc_offset();
-       struct lmb *_lmb = PTRRELOC(&lmb);
+       struct lmb *_lmb = &lmb;
        struct lmb_region *_mem = &(_lmb->memory);
 
        for (i=0; i < _mem->cnt; i++) {
index 89d6a0a..49ddf5e 100644 (file)
@@ -340,7 +340,7 @@ static int nvram_create_os_partition(void)
        struct list_head * p;
        struct nvram_partition * part;
        struct nvram_partition * new_part = NULL;
-       struct nvram_partition * free_part;
+       struct nvram_partition * free_part = NULL;
        int seq_init[2] = { 0, 0 };
        loff_t tmp_index;
        long size = 0;
@@ -603,6 +603,7 @@ void __exit nvram_cleanup(void)
 }
 
 
+#ifdef CONFIG_PPC_PSERIES
 
 /* nvram_write_error_log
  *
@@ -727,6 +728,7 @@ int nvram_clear_error_log()
        return 0;
 }
 
+#endif /* CONFIG_PPC_PSERIES */
 
 module_init(nvram_init);
 module_exit(nvram_cleanup);
index 4f9832a..4237675 100644 (file)
@@ -344,5 +344,5 @@ void __init openpic2_init(int offset)
        openpic2_set_priority(0);
        openpic2_disable_8259_pass_through();
 
-       ppc64_boot_msg(0x25, "OpenPic2 Done");
+       ppc64_boot_msg(0x25, "OpenPic U3 Done");
 }
index 9174917..abbbe28 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
+#include <asm/plpar_wrappers.h>
 #include "pci.h"
 
 
@@ -88,9 +89,153 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
 }
 
 
+static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
+                               long npages, unsigned long uaddr,
+                               enum dma_data_direction direction)
+{
+       u64 rc;
+       union tce_entry tce;
+
+       tce.te_word = 0;
+       tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+       tce.te_rdwr = 1;
+       if (direction != DMA_TO_DEVICE)
+               tce.te_pciwr = 1;
+
+       while (npages--) {
+               rc = plpar_tce_put((u64)tbl->it_index, 
+                                  (u64)tcenum << 12, 
+                                  tce.te_word );
+               
+               if (rc && printk_ratelimit()) {
+                       printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+                       printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+                       printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
+                       printk("\ttce val = 0x%lx\n", tce.te_word );
+                       show_stack(current, (unsigned long *)__get_SP());
+               }
+                       
+               tcenum++;
+               tce.te_rpn++;
+       }
+}
+
+DEFINE_PER_CPU(void *, tce_page) = NULL;
+
+static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
+                                    long npages, unsigned long uaddr,
+                                    enum dma_data_direction direction)
+{
+       u64 rc;
+       union tce_entry tce, *tcep;
+       long l, limit;
+
+       if (npages == 1)
+               return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
+                                          direction);
+
+       tcep = __get_cpu_var(tce_page);
+
+       /* This is safe to do since interrupts are off when we're called
+        * from iommu_alloc{,_sg}()
+        */
+       if (!tcep) {
+               tcep = (void *)__get_free_page(GFP_ATOMIC);
+               /* If allocation fails, fall back to the loop implementation */
+               if (!tcep)
+                       return tce_build_pSeriesLP(tbl, tcenum, npages,
+                                                  uaddr, direction);
+               __get_cpu_var(tce_page) = tcep;
+       }
+
+       tce.te_word = 0;
+       tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+       tce.te_rdwr = 1;
+       if (direction != DMA_TO_DEVICE)
+               tce.te_pciwr = 1;
+
+       /* We can map max one pageful of TCEs at a time */
+       do {
+               /*
+                * Set up the page with TCE data, looping through and setting
+                * the values.
+                */
+               limit = min_t(long, npages, PAGE_SIZE/sizeof(union tce_entry));
+
+               for (l = 0; l < limit; l++) {
+                       tcep[l] = tce;
+                       tce.te_rpn++;
+               }
+
+               rc = plpar_tce_put_indirect((u64)tbl->it_index,
+                                           (u64)tcenum << 12,
+                                           (u64)virt_to_abs(tcep),
+                                           limit);
+
+               npages -= limit;
+               tcenum += limit;
+       } while (npages > 0 && !rc);
+
+       if (rc && printk_ratelimit()) {
+               printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+               printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+               printk("\tnpages  = 0x%lx\n", (u64)npages);
+               printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word);
+               show_stack(current, (unsigned long *)__get_SP());
+       }
+}
+
+static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
+{
+       u64 rc;
+       union tce_entry tce;
+
+       tce.te_word = 0;
+
+       while (npages--) {
+               rc = plpar_tce_put((u64)tbl->it_index,
+                                  (u64)tcenum << 12,
+                                  tce.te_word);
+
+               if (rc && printk_ratelimit()) {
+                       printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+                       printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+                       printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
+                       printk("\ttce val = 0x%lx\n", tce.te_word );
+                       show_stack(current, (unsigned long *)__get_SP());
+               }
+
+               tcenum++;
+       }
+}
+
+
+static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
+{
+       u64 rc;
+       union tce_entry tce;
+
+       tce.te_word = 0;
+
+       rc = plpar_tce_stuff((u64)tbl->it_index,
+                          (u64)tcenum << 12,
+                          tce.te_word,
+                          npages);
+
+       if (rc && printk_ratelimit()) {
+               printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
+               printk("\trc      = %ld\n", rc);
+               printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+               printk("\tnpages  = 0x%lx\n", (u64)npages);
+               printk("\ttce val = 0x%lx\n", tce.te_word );
+               show_stack(current, (unsigned long *)__get_SP());
+       }
+}
+
+
 static void iommu_buses_init(void)
 {
-       struct pci_controller* phb;
+       struct pci_controller *phb, *tmp;
        struct device_node *dn, *first_dn;
        int num_slots, num_slots_ilog2;
        int first_phb = 1;
@@ -106,10 +251,10 @@ static void iommu_buses_init(void)
        else
                tcetable_ilog2 = 22;
 
-       /* XXX Should we be using pci_root_buses instead?  -ojn 
+       /* XXX Should we be using pci_root_buses instead?  -ojn
         */
 
-       for (phb=hose_head; phb; phb=phb->next) {
+       list_for_each_entry_safe(phb, tmp, &hose_list, list_node) {
                first_dn = ((struct device_node *)phb->arch_data)->child;
 
                /* Carve 2GB into the largest dma_window_size possible */
@@ -166,24 +311,25 @@ static void iommu_table_setparms(struct pci_controller *phb,
                                 struct device_node *dn,
                                 struct iommu_table *tbl) 
 {
-       phandle node;
-       unsigned long i;
-       struct of_tce_table *oft;
-
-       node = ((struct device_node *)(phb->arch_data))->node;
+       struct device_node *node;
+       unsigned long *basep;
+       unsigned int *sizep;
 
-       oft = NULL;
+       node = (struct device_node *)phb->arch_data;
 
-       for (i=0; of_tce_table[i].node; i++)
-               if(of_tce_table[i].node == node) {
-                       oft = &of_tce_table[i];
-                       break;
-               }
-
-       if (!oft)
-               panic("PCI_DMA: iommu_table_setparms: Can't find phb named '%s' in of_tce_table\n", dn->full_name);
-
-       memset((void *)oft->base, 0, oft->size);
+       if (get_property(node, "linux,has-tce-table", NULL) == NULL) {
+               printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has no tce table !\n",
+                     dn->full_name);
+               return;
+       }
+       basep = (unsigned long *)get_property(node, "linux,tce-base", NULL);
+       sizep = (unsigned int *)get_property(node, "linux,tce-size", NULL);
+       if (basep == NULL || sizep == NULL) {
+               printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has missing tce"
+                      " entries !\n", dn->full_name);
+               return;
+       }
+       memset((void *)(*basep), 0, *sizep);
 
        tbl->it_busno = phb->bus->number;
        
@@ -207,10 +353,11 @@ static void iommu_table_setparms(struct pci_controller *phb,
        if (phb->dma_window_base_cur > (1 << 19))
                panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 
        
-       tbl->it_base = oft->base;
+       tbl->it_base = *basep;
        tbl->it_index = 0;
        tbl->it_entrysize = sizeof(union tce_entry);
        tbl->it_blocksize = 16;
+       tbl->it_type = TCE_PCI;
 }
 
 /*
@@ -246,6 +393,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
        tbl->it_index  = dma_window[0];
        tbl->it_entrysize = sizeof(union tce_entry);
        tbl->it_blocksize  = 16;
+       tbl->it_type = TCE_PCI;
 }
 
 
@@ -293,8 +441,16 @@ void iommu_setup_pSeries(void)
 /* These are called very early. */
 void tce_init_pSeries(void)
 {
-       ppc_md.tce_build = tce_build_pSeries;
-       ppc_md.tce_free  = tce_free_pSeries;
+       if (!(systemcfg->platform & PLATFORM_LPAR)) {
+               ppc_md.tce_build = tce_build_pSeries;
+               ppc_md.tce_free  = tce_free_pSeries;
+       } else if (cur_cpu_spec->firmware_features & FW_FEATURE_MULTITCE) {
+               ppc_md.tce_build = tce_buildmulti_pSeriesLP;
+               ppc_md.tce_free  = tce_freemulti_pSeriesLP;
+       } else {
+               ppc_md.tce_build = tce_build_pSeriesLP;
+               ppc_md.tce_free  = tce_free_pSeriesLP;
+       }
 
        pci_iommu_init();
 }
index a44c332..68eeb7a 100644 (file)
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#define DEBUG
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/dma-mapping.h>
 #include <asm/naca.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
-#include <asm/hvcall.h>
 #include <asm/prom.h>
 #include <asm/abs_addr.h>
 #include <asm/cputable.h>
+#include <asm/plpar_wrappers.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
 
 /* in pSeries_hvCall.S */
 EXPORT_SYMBOL(plpar_hcall);
@@ -45,146 +53,9 @@ EXPORT_SYMBOL(plpar_hcall_4out);
 EXPORT_SYMBOL(plpar_hcall_norets);
 EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
 
-long poll_pending(void)
-{
-       unsigned long dummy;
-       return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0,
-                          &dummy, &dummy, &dummy);
-}
-
-long prod_processor(void)
-{
-       plpar_hcall_norets(H_PROD);
-       return(0); 
-}
-
-long cede_processor(void)
-{
-       plpar_hcall_norets(H_CEDE);
-       return(0); 
-}
-
-long register_vpa(unsigned long flags, unsigned long proc, unsigned long vpa)
-{
-       plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa);
-       return(0); 
-}
-
-long plpar_pte_remove(unsigned long flags,
-                     unsigned long ptex,
-                     unsigned long avpn,
-                     unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
-{
-       unsigned long dummy;
-       return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0,
-                          old_pteh_ret, old_ptel_ret, &dummy);
-}
-
-long plpar_pte_read(unsigned long flags,
-                   unsigned long ptex,
-                   unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
-{
-       unsigned long dummy;
-       return plpar_hcall(H_READ, flags, ptex, 0, 0,
-                          old_pteh_ret, old_ptel_ret, &dummy);
-}
-
-long plpar_pte_protect(unsigned long flags,
-                      unsigned long ptex,
-                      unsigned long avpn)
-{
-       return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn);
-}
-
-long plpar_tce_get(unsigned long liobn,
-                  unsigned long ioba,
-                  unsigned long *tce_ret)
-{
-       unsigned long dummy;
-       return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0,
-                          tce_ret, &dummy, &dummy);
-}
-
-long plpar_tce_put(unsigned long liobn,
-                  unsigned long ioba,
-                  unsigned long tceval)
-{
-       return plpar_hcall_norets(H_PUT_TCE, liobn, ioba, tceval);
-}
+extern void fw_feature_init(void);
+extern void pSeries_find_serial_port(void);
 
-long plpar_get_term_char(unsigned long termno,
-                        unsigned long *len_ret,
-                        char *buf_ret)
-{
-       unsigned long *lbuf = (unsigned long *)buf_ret;  /* ToDo: alignment? */
-       return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0,
-                          len_ret, lbuf+0, lbuf+1);
-}
-
-long plpar_put_term_char(unsigned long termno,
-                        unsigned long len,
-                        const char *buffer)
-{
-       unsigned long *lbuf = (unsigned long *)buffer;  /* ToDo: alignment? */
-       return plpar_hcall_norets(H_PUT_TERM_CHAR, termno, len, lbuf[0],
-                                 lbuf[1]);
-}
-
-static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
-               long npages, unsigned long uaddr,
-               enum dma_data_direction direction)
-{
-       u64 rc;
-       union tce_entry tce;
-
-       tce.te_word = 0;
-       tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
-       tce.te_rdwr = 1;
-       if (direction != DMA_TO_DEVICE)
-               tce.te_pciwr = 1;
-
-       while (npages--) {
-               rc = plpar_tce_put((u64)tbl->it_index, 
-                                  (u64)tcenum << 12, 
-                                  tce.te_word );
-               
-               if (rc && printk_ratelimit()) {
-                       printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
-                       printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
-                       printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-                       printk("\ttce val = 0x%lx\n", tce.te_word );
-                       show_stack(current, (unsigned long *)__get_SP());
-               }
-                       
-               tcenum++;
-               tce.te_rpn++;
-       }
-}
-
-static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
-{
-       u64 rc;
-       union tce_entry tce;
-
-       tce.te_word = 0;
-
-       while (npages--) {
-               rc = plpar_tce_put((u64)tbl->it_index, 
-                                  (u64)tcenum << 12,
-                                  tce.te_word );
-               
-               if (rc && printk_ratelimit()) {
-                       printk("tce_free_pSeriesLP: plpar_tce_put failed\n");
-                       printk("\trc      = %ld\n", rc);
-                       printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
-                       printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-                       printk("\ttce val = 0x%lx\n", tce.te_word );
-                       show_stack(current, (unsigned long *)__get_SP());
-               }
-               
-               tcenum++;
-       }
-}
 
 int vtermno;   /* virtual terminal# for udbg  */
 
@@ -249,8 +120,19 @@ static unsigned char udbg_getcLP(void)
        }
 }
 
+/* call this from early_init() for a working debug console on
+ * vterm capable LPAR machines
+ */
+void udbg_init_debug_lpar(void)
+{
+       vtermno = 0;
+       ppc_md.udbg_putc = udbg_putcLP;
+       ppc_md.udbg_getc = udbg_getcLP;
+       ppc_md.udbg_getc_poll = udbg_getc_pollLP;
+}
+
 /* returns 0 if couldn't find or use /chosen/stdout as console */
-static int find_udbg_vterm(void)
+int find_udbg_vterm(void)
 {
        struct device_node *stdout_node;
        u32 *termno;
@@ -258,15 +140,14 @@ static int find_udbg_vterm(void)
        int found = 0;
 
        /* find the boot console from /chosen/stdout */
-       if (!of_stdout_device) {
-               printk(KERN_WARNING "couldn't get path from /chosen/stdout!\n");
-               return found;
-       }
-       stdout_node = of_find_node_by_path(of_stdout_device);
-       if (!stdout_node) {
-               printk(KERN_WARNING "couldn't find node from /chosen/stdout\n");
-               return found;
-       }
+       if (!of_chosen)
+               return 0;
+       name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+       if (name == NULL)
+               return 0;
+       stdout_node = of_find_node_by_path(name);
+       if (!stdout_node)
+               return 0;
 
        /* now we have the stdout node; figure out what type of device it is. */
        name = (char *)get_property(stdout_node, "name", NULL);
@@ -288,15 +169,17 @@ static int find_udbg_vterm(void)
                } else {
                        /* XXX implement udbg_putcLP_vtty for hvterm-protocol1 case */
                        printk(KERN_WARNING "%s doesn't speak hvterm1; "
-                                       "can't print udbg messages\n", of_stdout_device);
+                                       "can't print udbg messages\n",
+                              stdout_node->full_name);
                }
        } else if (strncmp(name, "serial", 6)) {
                /* XXX fix ISA serial console */
                printk(KERN_WARNING "serial stdout on LPAR ('%s')! "
-                               "can't print udbg messages\n", of_stdout_device);
+                               "can't print udbg messages\n",
+                      stdout_node->full_name);
        } else {
                printk(KERN_WARNING "don't know how to print to stdout '%s'\n",
-                               of_stdout_device);
+                      stdout_node->full_name);
        }
 
 out:
@@ -304,35 +187,6 @@ out:
        return found;
 }
 
-void pSeries_lpar_mm_init(void);
-
-/* This is called early in setup.c.
- * Use it to setup page table ppc_md stuff as well as udbg.
- */
-void pSeriesLP_init_early(void)
-{
-       pSeries_lpar_mm_init();
-
-       tce_init_pSeries();
-
-       ppc_md.tce_build = tce_build_pSeriesLP;
-       ppc_md.tce_free  = tce_free_pSeriesLP;
-
-       pci_iommu_init();
-
-#ifdef CONFIG_SMP
-       smp_init_pSeries();
-#endif
-
-       /* The keyboard is not useful in the LPAR environment.
-        * Leave all the ppc_md keyboard interfaces NULL.
-        */
-
-       if (0 == find_udbg_vterm()) {
-               printk(KERN_WARNING
-                       "can't use stdout; can't print early debug messages.\n");
-       }
-}
 
 long pSeries_lpar_hpte_insert(unsigned long hpte_group,
                              unsigned long va, unsigned long prpn,
@@ -377,7 +231,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
        lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, lhpte.dw0.dword0,
                              lhpte.dw1.dword1, &slot, &dummy0, &dummy1);
 
-       if (lpar_rc == H_PTEG_Full)
+       if (unlikely(lpar_rc == H_PTEG_Full))
                return -1;
 
        /*
@@ -385,7 +239,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
         * will fail. However we must catch the failure in hash_page
         * or we will loop forever, so return -2 in this case.
         */
-       if (lpar_rc != H_Success)
+       if (unlikely(lpar_rc != H_Success))
                return -2;
 
        /* Because of iSeries, we have to pass down the secondary
@@ -415,9 +269,7 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
                if (lpar_rc == H_Success)
                        return i;
 
-               if (lpar_rc != H_Not_Found)
-                       panic("Bad return code from pte remove rc = %lx\n",
-                             lpar_rc);
+               BUG_ON(lpar_rc != H_Not_Found);
 
                slot_offset++;
                slot_offset &= 0x7;
@@ -426,6 +278,18 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
        return -1;
 }
 
+static void pSeries_lpar_hptab_clear(void)
+{
+       unsigned long size_bytes = 1UL << naca->pftSize;
+       unsigned long hpte_count = size_bytes >> 4;
+       unsigned long dummy1, dummy2;
+       int i;
+
+       /* TODO: Use bulk call */
+       for (i = 0; i < hpte_count; i++)
+               plpar_pte_remove(0, i, 0, &dummy1, &dummy2);
+}
+
 /*
  * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
  * the low 3 bits of flags happen to line up.  So no transform is needed.
@@ -447,8 +311,7 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp,
        if (lpar_rc == H_Not_Found)
                return -1;
 
-       if (lpar_rc != H_Success)
-               panic("bad return code from pte protect rc = %lx\n", lpar_rc);
+       BUG_ON(lpar_rc != H_Success);
 
        return 0;
 }
@@ -464,11 +327,10 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
        /* Do not need RPN to logical page translation */
        /* No cross CEC PFT access                     */
        flags = 0;
-       
+
        lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
 
-       if (lpar_rc != H_Success)
-               panic("Error on pte read in get_hpte0 rc = %lx\n", lpar_rc);
+       BUG_ON(lpar_rc != H_Success);
 
        return dword0;
 }
@@ -519,15 +381,12 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
        vpn = va >> PAGE_SHIFT;
 
        slot = pSeries_lpar_hpte_find(vpn);
-       if (slot == -1)
-               panic("updateboltedpp: Could not find page to bolt\n");
+       BUG_ON(slot == -1);
 
        flags = newpp & 3;
        lpar_rc = plpar_pte_protect(flags, slot, 0);
 
-       if (lpar_rc != H_Success)
-               panic("Bad return code from pte bolted protect rc = %lx\n",
-                     lpar_rc); 
+       BUG_ON(lpar_rc != H_Success);
 }
 
 static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
@@ -546,8 +405,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
        if (lpar_rc == H_Not_Found)
                return;
 
-       if (lpar_rc != H_Success)
-               panic("Bad return code from invalidate rc = %lx\n", lpar_rc);
+       BUG_ON(lpar_rc != H_Success);
 }
 
 /*
@@ -560,18 +418,19 @@ void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number,
        int i;
        unsigned long flags;
        struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
+       int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
 
-       if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
+       if (lock_tlbie)
                spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
 
        for (i = 0; i < number; i++)
                flush_hash_page(context, batch->addr[i], batch->pte[i], local);
 
-       if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
+       if (lock_tlbie)
                spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
 }
 
-void pSeries_lpar_mm_init(void)
+void hpte_init_lpar(void)
 {
        ppc_md.hpte_invalidate  = pSeries_lpar_hpte_invalidate;
        ppc_md.hpte_updatepp    = pSeries_lpar_hpte_updatepp;
@@ -579,4 +438,7 @@ void pSeries_lpar_mm_init(void)
        ppc_md.hpte_insert      = pSeries_lpar_hpte_insert;
        ppc_md.hpte_remove      = pSeries_lpar_hpte_remove;
        ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
+       ppc_md.hpte_clear_all   = pSeries_lpar_hptab_clear;
+
+       htab_finish_init();
 }
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
new file mode 100644 (file)
index 0000000..80e0289
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+ *  linux/arch/ppc/kernel/setup.c
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *  Modified by PPC64 Team, IBM Corp
+ *
+ * This program is free software; you can redistribute 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.
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/console.h>
+#include <linux/pci.h>
+#include <linux/version.h>
+#include <linux/adb.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+#include <asm/pci-bridge.h>
+#include <asm/iommu.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/naca.h>
+#include <asm/time.h>
+#include <asm/nvram.h>
+
+#include "i8259.h"
+#include "open_pic.h"
+#include <asm/xics.h>
+#include <asm/ppcdebug.h>
+#include <asm/cputable.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+extern void pSeries_init_openpic(void);
+
+extern void find_and_init_phbs(void);
+extern void pSeries_final_fixup(void);
+
+extern void pSeries_get_boot_time(struct rtc_time *rtc_time);
+extern void pSeries_get_rtc_time(struct rtc_time *rtc_time);
+extern int  pSeries_set_rtc_time(struct rtc_time *rtc_time);
+extern void find_udbg_vterm(void);
+extern void SystemReset_FWNMI(void), MachineCheck_FWNMI(void); /* from head.S */
+int fwnmi_active;  /* TRUE if an FWNMI handler is present */
+
+unsigned long  virtPython0Facilities = 0;  // python0 facility area (memory mapped io) (64-bit format) VIRTUAL address.
+
+extern unsigned long loops_per_jiffy;
+
+extern unsigned long ppc_proc_freq;
+extern unsigned long ppc_tb_freq;
+
+void pSeries_get_cpuinfo(struct seq_file *m)
+{
+       struct device_node *root;
+       const char *model = "";
+
+       root = of_find_node_by_path("/");
+       if (root)
+               model = get_property(root, "model", NULL);
+       seq_printf(m, "machine\t\t: CHRP %s\n", model);
+       of_node_put(root);
+}
+
+/* Initialize firmware assisted non-maskable interrupts if
+ * the firmware supports this feature.
+ *
+ */
+static void __init fwnmi_init(void)
+{
+       int ret;
+       int ibm_nmi_register = rtas_token("ibm,nmi-register");
+       if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE)
+               return;
+       ret = rtas_call(ibm_nmi_register, 2, 1, NULL,
+                       __pa((unsigned long)SystemReset_FWNMI),
+                       __pa((unsigned long)MachineCheck_FWNMI));
+       if (ret == 0)
+               fwnmi_active = 1;
+}
+
+static void __init pSeries_setup_arch(void)
+{
+       struct device_node *root;
+       unsigned int *opprop;
+
+       /* Fixup ppc_md depending on the type of interrupt controller */
+       if (naca->interrupt_controller == IC_OPEN_PIC) {
+               ppc_md.init_IRQ       = pSeries_init_openpic; 
+               ppc_md.get_irq        = openpic_get_irq;
+       } else {
+               ppc_md.init_IRQ       = xics_init_IRQ;
+               ppc_md.get_irq        = xics_get_irq;
+       }
+
+#ifdef CONFIG_SMP
+       smp_init_pSeries();
+#endif
+       /* openpic global configuration register (64-bit format). */
+       /* openpic Interrupt Source Unit pointer (64-bit format). */
+       /* python0 facility area (mmio) (64-bit format) REAL address. */
+
+       /* init to some ~sane value until calibrate_delay() runs */
+       loops_per_jiffy = 50000000;
+
+       if (ROOT_DEV == 0) {
+               printk("No ramdisk, default root is /dev/sda2\n");
+               ROOT_DEV = Root_SDA2;
+       }
+
+       fwnmi_init();
+
+       /* Find and initialize PCI host bridges */
+       /* iSeries needs to be done much later. */
+       eeh_init();
+       find_and_init_phbs();
+
+       /* Find the Open PIC if present */
+       root = of_find_node_by_path("/");
+       opprop = (unsigned int *) get_property(root,
+                               "platform-open-pic", NULL);
+       if (opprop != 0) {
+               int n = prom_n_addr_cells(root);
+               unsigned long openpic;
+
+               for (openpic = 0; n > 0; --n)
+                       openpic = (openpic << 32) + *opprop++;
+               printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic);
+               OpenPIC_Addr = __ioremap(openpic, 0x40000, _PAGE_NO_CACHE);
+       }
+       of_node_put(root);
+
+#ifdef CONFIG_DUMMY_CONSOLE
+       conswitchp = &dummy_con;
+#endif
+
+       pSeries_nvram_init();
+}
+
+static int __init pSeries_init_panel(void)
+{
+       /* Manually leave the kernel version on the panel. */
+       ppc_md.progress("Linux ppc64\n", 0);
+       ppc_md.progress(UTS_RELEASE, 0);
+
+       return 0;
+}
+arch_initcall(pSeries_init_panel);
+
+
+
+void __init pSeries_find_serial_port(void)
+{
+       struct device_node *np;
+       unsigned long encode_phys_size = 32;
+       u32 *sizeprop;
+
+       struct isa_reg_property {
+               u32 space;
+               u32 address;
+               u32 size;
+       };
+       struct pci_reg_property {
+               struct pci_address addr;
+               u32 size_hi;
+               u32 size_lo;
+       };                                                                        
+
+       DBG(" -> pSeries_find_serial_port()\n");
+
+       naca->serialPortAddr = 0;
+
+       np = of_find_node_by_path("/");
+       if (!np)
+               return;
+       sizeprop = (u32 *)get_property(np, "#size-cells", NULL);
+       if (sizeprop != NULL)
+               encode_phys_size = (*sizeprop) << 5;
+       
+       for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
+               struct device_node *isa, *pci;
+               struct isa_reg_property *reg;
+               union pci_range *rangesp;
+               char *typep;
+
+               typep = (char *)get_property(np, "ibm,aix-loc", NULL);
+               if ((typep == NULL) || (typep && strcmp(typep, "S1")))
+                       continue;
+
+               reg = (struct isa_reg_property *)get_property(np, "reg", NULL); 
+
+               isa = of_get_parent(np);
+               if (!isa) {
+                       DBG("no isa parent found\n");
+                       break;
+               }
+               pci = of_get_parent(isa);
+               if (!pci) {
+                       DBG("no pci parent found\n");
+                       break;
+               }
+
+               rangesp = (union pci_range *)get_property(pci, "ranges", NULL);
+
+               if ( encode_phys_size == 32 )
+                       naca->serialPortAddr = rangesp->pci32.phys+reg->address;
+               else {
+                       naca->serialPortAddr =
+                               ((((unsigned long)rangesp->pci64.phys_hi) << 32)
+                               |
+                       (rangesp->pci64.phys_lo)) + reg->address;
+               }
+               break;
+       }
+
+       DBG(" <- pSeries_find_serial_port()\n");
+}
+
+
+/* Build up the firmware_features bitmask field
+ * using contents of device-tree/ibm,hypertas-functions.
+ * Ultimately this functionality may be moved into prom.c prom_init().
+ */
+void __init fw_feature_init(void)
+{
+       struct device_node * dn;
+       char * hypertas;
+       unsigned int len;
+
+       DBG(" -> fw_feature_init()\n");
+
+       cur_cpu_spec->firmware_features = 0;
+       dn = of_find_node_by_path("/rtas");
+       if (dn == NULL) {
+               printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n");
+               goto no_rtas;
+       }
+
+       hypertas = get_property(dn, "ibm,hypertas-functions", &len);
+       if (hypertas) {
+               while (len > 0){
+                       int i, hypertas_len;
+                       /* check value against table of strings */
+                       for(i=0; i < FIRMWARE_MAX_FEATURES ;i++) {
+                               if ((firmware_features_table[i].name) &&
+                                   (strcmp(firmware_features_table[i].name,hypertas))==0) {
+                                       /* we have a match */
+                                       cur_cpu_spec->firmware_features |= 
+                                               (firmware_features_table[i].val);
+                                       break;
+                               } 
+                       }
+                       hypertas_len = strlen(hypertas);
+                       len -= hypertas_len +1;
+                       hypertas+= hypertas_len +1;
+               }
+       }
+
+       of_node_put(dn);
+ no_rtas:
+       printk(KERN_INFO "firmware_features = 0x%lx\n", 
+              cur_cpu_spec->firmware_features);
+
+       DBG(" <- fw_feature_init()\n");
+}
+
+
+static  void __init pSeries_discover_pic(void)
+{
+       struct device_node *np;
+       char *typep;
+
+       /*
+        * Setup interrupt mapping options that are needed for finish_device_tree
+        * to properly parse the OF interrupt tree & do the virtual irq mapping
+        */
+       __irq_offset_value = NUM_ISA_INTERRUPTS;
+       naca->interrupt_controller = IC_INVALID;
+       for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) {
+               typep = (char *)get_property(np, "compatible", NULL);
+               if (strstr(typep, "open-pic"))
+                       naca->interrupt_controller = IC_OPEN_PIC;
+               else if (strstr(typep, "ppc-xicp"))
+                       naca->interrupt_controller = IC_PPC_XIC;
+               else
+                       printk("initialize_naca: failed to recognize"
+                              " interrupt-controller\n");
+               break;
+       }
+}
+
+/*
+ * Early initialization.  Relocation is on but do not reference unbolted pages
+ */
+static void __init pSeries_init_early(void)
+{
+       void *comport;
+       int iommu_off = 0;
+
+       DBG(" -> pSeries_init_early()\n");
+
+       fw_feature_init();
+       
+       if (systemcfg->platform & PLATFORM_LPAR)
+               hpte_init_lpar();
+       else {
+               hpte_init_native();
+               iommu_off = (of_chosen &&
+                            get_property(of_chosen, "linux,iommu-off", NULL));
+       }
+
+       pSeries_find_serial_port();
+
+       if (systemcfg->platform & PLATFORM_LPAR)
+               find_udbg_vterm();
+       else if (naca->serialPortAddr) {
+               /* Map the uart for udbg. */
+               comport = (void *)__ioremap(naca->serialPortAddr, 16, _PAGE_NO_CACHE);
+               udbg_init_uart(comport);
+
+               ppc_md.udbg_putc = udbg_putc;
+               ppc_md.udbg_getc = udbg_getc;
+               ppc_md.udbg_getc_poll = udbg_getc_poll;
+               DBG("Hello World !\n");
+       }
+
+
+       if (iommu_off)
+               pci_dma_init_direct();
+       else
+               tce_init_pSeries();
+
+       pSeries_discover_pic();
+
+       DBG(" <- pSeries_init_early()\n");
+}
+
+
+static void pSeries_progress(char *s, unsigned short hex)
+{
+       struct device_node *root;
+       int width, *p;
+       char *os;
+       static int display_character, set_indicator;
+       static int max_width;
+       static spinlock_t progress_lock = SPIN_LOCK_UNLOCKED;
+       static int pending_newline = 0;  /* did last write end with unprinted newline? */
+
+       if (!rtas.base)
+               return;
+
+       if (max_width == 0) {
+               if ((root = find_path_device("/rtas")) &&
+                    (p = (unsigned int *)get_property(root,
+                                                      "ibm,display-line-length",
+                                                      NULL)))
+                       max_width = *p;
+               else
+                       max_width = 0x10;
+               display_character = rtas_token("display-character");
+               set_indicator = rtas_token("set-indicator");
+       }
+
+       if (display_character == RTAS_UNKNOWN_SERVICE) {
+               /* use hex display if available */
+               if (set_indicator != RTAS_UNKNOWN_SERVICE)
+                       rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
+               return;
+       }
+
+       spin_lock(&progress_lock);
+
+       /*
+        * Last write ended with newline, but we didn't print it since
+        * it would just clear the bottom line of output. Print it now
+        * instead.
+        *
+        * If no newline is pending, print a CR to start output at the
+        * beginning of the line.
+        */
+       if (pending_newline) {
+               rtas_call(display_character, 1, 1, NULL, '\r');
+               rtas_call(display_character, 1, 1, NULL, '\n');
+               pending_newline = 0;
+       } else {
+               rtas_call(display_character, 1, 1, NULL, '\r');
+       }
+       width = max_width;
+       os = s;
+       while (*os) {
+               if (*os == '\n' || *os == '\r') {
+                       /* Blank to end of line. */
+                       while (width-- > 0)
+                               rtas_call(display_character, 1, 1, NULL, ' ');
+                       /* If newline is the last character, save it
+                        * until next call to avoid bumping up the
+                        * display output.
+                        */
+                       if (*os == '\n' && !os[1]) {
+                               pending_newline = 1;
+                               spin_unlock(&progress_lock);
+                               return;
+                       }
+                       /* RTAS wants CR-LF, not just LF */
+                       if (*os == '\n') {
+                               rtas_call(display_character, 1, 1, NULL, '\r');
+                               rtas_call(display_character, 1, 1, NULL, '\n');
+                       } else {
+                               /* CR might be used to re-draw a line, so we'll
+                                * leave it alone and not add LF.
+                                */
+                               rtas_call(display_character, 1, 1, NULL, *os);
+                       }
+                       width = max_width;
+               } else {
+                       width--;
+                       rtas_call(display_character, 1, 1, NULL, *os);
+               }
+               os++;
+               /* if we overwrite the screen length */
+               if (width <= 0)
+                       while ((*os != 0) && (*os != '\n') && (*os != '\r'))
+                               os++;
+       }
+       /* Blank to end of line. */
+       while (width-- > 0)
+               rtas_call(display_character, 1, 1, NULL, ' ');
+
+       spin_unlock(&progress_lock);
+}
+
+extern void setup_default_decr(void);
+
+/* Some sane defaults: 125 MHz timebase, 1GHz processor */
+#define DEFAULT_TB_FREQ                125000000UL
+#define DEFAULT_PROC_FREQ      (DEFAULT_TB_FREQ * 8)
+
+static void __init pSeries_calibrate_decr(void)
+{
+       struct device_node *cpu;
+       struct div_result divres;
+       unsigned int *fp;
+       int node_found;
+
+       /*
+        * The cpu node should have a timebase-frequency property
+        * to tell us the rate at which the decrementer counts.
+        */
+       cpu = of_find_node_by_type(NULL, "cpu");
+
+       ppc_tb_freq = DEFAULT_TB_FREQ;          /* hardcoded default */
+       node_found = 0;
+       if (cpu != 0) {
+               fp = (unsigned int *)get_property(cpu, "timebase-frequency",
+                                                 NULL);
+               if (fp != 0) {
+                       node_found = 1;
+                       ppc_tb_freq = *fp;
+               }
+       }
+       if (!node_found)
+               printk(KERN_ERR "WARNING: Estimating decrementer frequency "
+                               "(not found)\n");
+
+       ppc_proc_freq = DEFAULT_PROC_FREQ;
+       node_found = 0;
+       if (cpu != 0) {
+               fp = (unsigned int *)get_property(cpu, "clock-frequency",
+                                                 NULL);
+               if (fp != 0) {
+                       node_found = 1;
+                       ppc_proc_freq = *fp;
+               }
+       }
+       if (!node_found)
+               printk(KERN_ERR "WARNING: Estimating processor frequency "
+                               "(not found)\n");
+
+       of_node_put(cpu);
+
+       printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+              ppc_tb_freq/1000000, ppc_tb_freq%1000000);
+       printk(KERN_INFO "time_init: processor frequency   = %lu.%.6lu MHz\n",
+              ppc_proc_freq/1000000, ppc_proc_freq%1000000);
+
+       tb_ticks_per_jiffy = ppc_tb_freq / HZ;
+       tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
+       tb_ticks_per_usec = ppc_tb_freq / 1000000;
+       tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
+       div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
+       tb_to_xs = divres.result_low;
+
+       setup_default_decr();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+extern struct machdep_calls pSeries_md;
+
+static int __init pSeries_probe(int platform)
+{
+       if (platform != PLATFORM_PSERIES &&
+           platform != PLATFORM_PSERIES_LPAR)
+               return 0;
+
+       /* if we have some ppc_md fixups for LPAR to do, do
+        * it here ...
+        */
+
+       return 1;
+}
+
+struct machdep_calls __initdata pSeries_md = {
+       .probe                  = pSeries_probe,
+       .setup_arch             = pSeries_setup_arch,
+       .init_early             = pSeries_init_early,
+       .get_cpuinfo            = pSeries_get_cpuinfo,
+       .log_error              = pSeries_log_error,
+       .pcibios_fixup          = pSeries_final_fixup,
+       .restart                = rtas_restart,
+       .power_off              = rtas_power_off,
+       .halt                   = rtas_halt,
+       .panic                  = rtas_os_term,
+       .get_boot_time          = pSeries_get_boot_time,
+       .get_rtc_time           = pSeries_get_rtc_time,
+       .set_rtc_time           = pSeries_set_rtc_time,
+       .calibrate_decr         = pSeries_calibrate_decr,
+       .progress               = pSeries_progress,
+};
index 30e5002..751071a 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/list.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
 unsigned long pci_probe_only = 1;
 unsigned long pci_assign_all_buses = 0;
 
+/* legal IO pages under MAX_ISA_PORT.  This is to ensure we don't touch
+   devices we don't have access to. */
+unsigned long io_page_mask;
+
+EXPORT_SYMBOL(io_page_mask);
+
+
 unsigned int pcibios_assign_all_busses(void)
 {
        return pci_assign_all_buses;
@@ -55,16 +63,9 @@ unsigned int pcibios_assign_all_busses(void)
 unsigned long isa_io_base;     /* NULL if no ISA bus */
 unsigned long pci_io_base;
 
-void pcibios_name_device(struct pci_dev* dev);
-void pcibios_final_fixup(void);
-static void fixup_broken_pcnet32(struct pci_dev* dev);
-static void fixup_windbond_82c105(struct pci_dev* dev);
-extern void fixup_k2_sata(struct pci_dev* dev);
-
 void iSeries_pcibios_init(void);
 
-struct pci_controller *hose_head;
-struct pci_controller **hose_tail = &hose_head;
+LIST_HEAD(hose_list);
 
 struct pci_dma_ops pci_dma_ops;
 EXPORT_SYMBOL(pci_dma_ops);
@@ -74,20 +75,6 @@ int global_phb_number;               /* Global phb counter */
 /* Cached ISA bridge dev. */
 struct pci_dev *ppc64_isabridge_dev = NULL;
 
-struct pci_fixup pcibios_fixups[] = {
-       { PCI_FIXUP_HEADER,     PCI_VENDOR_ID_TRIDENT,          PCI_ANY_ID,
-         fixup_broken_pcnet32 },
-       { PCI_FIXUP_HEADER,     PCI_VENDOR_ID_WINBOND,          PCI_DEVICE_ID_WINBOND_82C105,
-         fixup_windbond_82c105 },
-       { PCI_FIXUP_HEADER,     PCI_ANY_ID,                     PCI_ANY_ID,
-         pcibios_name_device },
-#ifdef CONFIG_PPC_PMAC
-       { PCI_FIXUP_HEADER,     PCI_VENDOR_ID_SERVERWORKS,      0x0240,
-         fixup_k2_sata },
-#endif
-       { 0 }
-};
-
 static void fixup_broken_pcnet32(struct pci_dev* dev)
 {
        if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
@@ -96,6 +83,7 @@ static void fixup_broken_pcnet32(struct pci_dev* dev)
                pci_name_device(dev);
        }
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
 
 static void fixup_windbond_82c105(struct pci_dev* dev)
 {
@@ -118,6 +106,7 @@ static void fixup_windbond_82c105(struct pci_dev* dev)
                        dev->resource[i].flags &= ~IORESOURCE_IO;
        }
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, fixup_windbond_82c105);
 
 void 
 pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
@@ -239,9 +228,9 @@ pci_alloc_pci_controller(enum phb_types controller_type)
                memcpy(hose->what,model,7);
         hose->type = controller_type;
         hose->global_number = global_phb_number++;
-        
-        *hose_tail = hose;
-        hose_tail = &hose->next;
+
+       list_add_tail(&hose->list_node, &hose_list);
+
         return hose;
 }
 
@@ -281,18 +270,17 @@ static void __init pcibios_claim_of_setup(void)
 
 static int __init pcibios_init(void)
 {
-       struct pci_controller *hose;
+       struct pci_controller *hose, *tmp;
        struct pci_bus *bus;
 
 #ifdef CONFIG_PPC_ISERIES
        iSeries_pcibios_init(); 
 #endif
 
-       //ppc64_boot_msg(0x40, "PCI Probe");
        printk("PCI: Probing PCI hardware\n");
 
        /* Scan all of the recorded PCI controllers.  */
-       for (hose = hose_head; hose; hose = hose->next) {
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
                hose->last_busno = 0xff;
                bus = pci_scan_bus(hose->first_busno, hose->ops,
                                   hose->arch_data);
@@ -308,7 +296,7 @@ static int __init pcibios_init(void)
                   pci_assign_unassigned_resources() is able to work
                   correctly with [partially] allocated PCI tree. */
                pci_assign_unassigned_resources();
-#endif
+#endif /* !CONFIG_PPC_ISERIES */
 
        /* Call machine dependent final fixup */
        if (ppc_md.pcibios_fixup)
@@ -320,11 +308,6 @@ static int __init pcibios_init(void)
                printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
 
        printk("PCI: Probing PCI hardware done\n");
-       //ppc64_boot_msg(0x41, "PCI Done");
-
-#ifdef CONFIG_PPC_PSERIES
-       pci_addr_cache_build();
-#endif
 
        return 0;
 }
@@ -524,7 +507,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
        return ret;
 }
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 static ssize_t pci_show_devspec(struct device *dev, char *buf)
 {
        struct pci_dev *pdev;
@@ -537,11 +520,329 @@ static ssize_t pci_show_devspec(struct device *dev, char *buf)
        return sprintf(buf, "%s", np->full_name);
 }
 static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 void pcibios_add_platform_entries(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
        device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+}
+
+#ifdef CONFIG_PPC_MULTIPLATFORM
+
+#define ISA_SPACE_MASK 0x1
+#define ISA_SPACE_IO 0x1
+
+static void pci_process_ISA_OF_ranges(struct device_node *isa_node,
+                                     unsigned long phb_io_base_phys,
+                                     void * phb_io_base_virt)
+{
+       struct isa_range *range;
+       unsigned long pci_addr;
+       unsigned int isa_addr;
+       unsigned int size;
+       int rlen = 0;
+
+       range = (struct isa_range *) get_property(isa_node, "ranges", &rlen);
+       if (rlen < sizeof(struct isa_range)) {
+               printk(KERN_ERR "unexpected isa range size: %s\n", 
+                               __FUNCTION__);
+               return; 
+       }
+       
+       /* From "ISA Binding to 1275"
+        * The ranges property is laid out as an array of elements,
+        * each of which comprises:
+        *   cells 0 - 1:       an ISA address
+        *   cells 2 - 4:       a PCI address 
+        *                      (size depending on dev->n_addr_cells)
+        *   cell 5:            the size of the range
+        */
+       if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) {
+               isa_addr = range->isa_addr.a_lo;
+               pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | 
+                       range->pci_addr.a_lo;
+
+               /* Assume these are both zero */
+               if ((pci_addr != 0) || (isa_addr != 0)) {
+                       printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
+                                       __FUNCTION__);
+                       return;
+               }
+               
+               size = PAGE_ALIGN(range->size);
+
+               __ioremap_explicit(phb_io_base_phys, 
+                                  (unsigned long) phb_io_base_virt, 
+                                  size, _PAGE_NO_CACHE);
+       }
+}
+
+void __init pci_process_bridge_OF_ranges(struct pci_controller *hose,
+                                        struct device_node *dev, int primary)
+{
+       unsigned int *ranges;
+       unsigned long size;
+       int rlen = 0;
+       int memno = 0;
+       struct resource *res;
+       int np, na = prom_n_addr_cells(dev);
+       unsigned long pci_addr, cpu_phys_addr;
+       struct device_node *isa_dn;
+
+       np = na + 5;
+
+       /* From "PCI Binding to 1275"
+        * The ranges property is laid out as an array of elements,
+        * each of which comprises:
+        *   cells 0 - 2:       a PCI address
+        *   cells 3 or 3+4:    a CPU physical address
+        *                      (size depending on dev->n_addr_cells)
+        *   cells 4+5 or 5+6:  the size of the range
+        */
+       rlen = 0;
+       hose->io_base_phys = 0;
+       ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+       while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+               res = NULL;
+               pci_addr = (unsigned long)ranges[1] << 32 | ranges[2];
+
+               cpu_phys_addr = ranges[3];
+               if (na == 2)
+                       cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
+
+               size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
+
+               switch (ranges[0] >> 24) {
+               case 1:         /* I/O space */
+                       hose->io_base_phys = cpu_phys_addr;
+                       hose->io_base_virt = reserve_phb_iospace(size);
+                       PPCDBG(PPCDBG_PHBINIT, 
+                              "phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", 
+                              hose->global_number, hose->io_base_phys, 
+                              (unsigned long) hose->io_base_virt);
+
+                       if (primary) {
+                               pci_io_base = (unsigned long)hose->io_base_virt;
+                               isa_dn = of_find_node_by_type(NULL, "isa");
+                               if (isa_dn) {
+                                       isa_io_base = pci_io_base;
+                                       pci_process_ISA_OF_ranges(isa_dn,
+                                               hose->io_base_phys,
+                                               hose->io_base_virt);
+                                       of_node_put(isa_dn);
+                                        /* Allow all IO */
+                                        io_page_mask = -1;
+                               }
+                       }
+
+                       res = &hose->io_resource;
+                       res->flags = IORESOURCE_IO;
+                       res->start = pci_addr;
+                       res->start += (unsigned long)hose->io_base_virt -
+                               pci_io_base;
+                       break;
+               case 2:         /* memory space */
+                       memno = 0;
+                       while (memno < 3 && hose->mem_resources[memno].flags)
+                               ++memno;
+
+                       if (memno == 0)
+                               hose->pci_mem_offset = cpu_phys_addr - pci_addr;
+                       if (memno < 3) {
+                               res = &hose->mem_resources[memno];
+                               res->flags = IORESOURCE_MEM;
+                               res->start = cpu_phys_addr;
+                       }
+                       break;
+               }
+               if (res != NULL) {
+                       res->name = dev->full_name;
+                       res->end = res->start + size - 1;
+                       res->parent = NULL;
+                       res->sibling = NULL;
+                       res->child = NULL;
+               }
+               ranges += np;
+       }
+}
+
+/*********************************************************************** 
+ * pci_find_hose_for_OF_device
+ *
+ * This function finds the PHB that matching device_node in the 
+ * OpenFirmware by scanning all the pci_controllers.
+ * 
+ ***********************************************************************/
+struct pci_controller* pci_find_hose_for_OF_device(struct device_node *node)
+{
+       while (node) {
+               struct pci_controller *hose, *tmp;
+               list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+                       if (hose->arch_data == node)
+                               return hose;
+               node=node->parent;
+       }
+       return NULL;
+}
+
+/*
+ * ppc64 can have multifunction devices that do not respond to function 0.
+ * In this case we must scan all functions.
+ */
+int pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
+{
+       struct device_node *busdn, *dn;
+
+       if (bus->self)
+               busdn = pci_device_to_OF_node(bus->self);
+       else
+               busdn = bus->sysdata;   /* must be a phb */
+
+       /*
+        * Check to see if there is any of the 8 functions are in the
+        * device tree.  If they are then we need to scan all the
+        * functions of this slot.
+        */
+       for (dn = busdn->child; dn; dn = dn->sibling)
+               if ((dn->devfn >> 3) == (devfn >> 3))
+                       return 1;
+
+       return 0;
+}
+
+
+void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
+                                          struct pci_bus *bus)
+{
+       /* Update device resources.  */
+       struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+       int i;
+
+       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+               if (dev->resource[i].flags & IORESOURCE_IO) {
+                       unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
+                        unsigned long start, end, mask;
+
+                        start = dev->resource[i].start += offset;
+                        end = dev->resource[i].end += offset;
+
+                        /* Need to allow IO access to pages that are in the
+                           ISA range */
+                        if (start < MAX_ISA_PORT) {
+                                if (end > MAX_ISA_PORT)
+                                        end = MAX_ISA_PORT;
+
+                                start >>= PAGE_SHIFT;
+                                end >>= PAGE_SHIFT;
+
+                                /* get the range of pages for the map */
+                                mask = ((1 << (end+1))-1) ^ ((1 << start)-1);
+                                io_page_mask |= mask;
+                        }
+               }
+                else if (dev->resource[i].flags & IORESOURCE_MEM) {
+                       dev->resource[i].start += hose->pci_mem_offset;
+                       dev->resource[i].end += hose->pci_mem_offset;
+               }
+        }
+}
+EXPORT_SYMBOL(pcibios_fixup_device_resources);
+
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+       struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+       struct list_head *ln;
+
+       /* XXX or bus->parent? */
+       struct pci_dev *dev = bus->self;
+       struct resource *res;
+       int i;
+
+       if (!dev) {
+               /* Root bus. */
+
+               hose->bus = bus;
+               bus->resource[0] = res = &hose->io_resource;
+               if (!res->flags)
+                       BUG();  /* No I/O resource for this PHB? */
+
+               if (request_resource(&ioport_resource, res))
+                       printk(KERN_ERR "Failed to request IO on "
+                                       "PCI domain %d\n", pci_domain_nr(bus));
+
+
+               for (i = 0; i < 3; ++i) {
+                       res = &hose->mem_resources[i];
+                       if (!res->flags && i == 0)
+                               BUG();  /* No memory resource for this PHB? */
+                       bus->resource[i+1] = res;
+                       if (res->flags && request_resource(&iomem_resource, res))
+                               printk(KERN_ERR "Failed to request MEM on "
+                                               "PCI domain %d\n",
+                                               pci_domain_nr(bus));
+               }
+       } else if (pci_probe_only &&
+                  (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+               /* This is a subordinate bridge */
+
+               pci_read_bridge_bases(bus);
+               pcibios_fixup_device_resources(dev, bus);
+       }
+
+       /* XXX Need to check why Alpha doesnt do this - Anton */
+       if (!pci_probe_only)
+               return;
+
+       for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+               struct pci_dev *dev = pci_dev_b(ln);
+               if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+                       pcibios_fixup_device_resources(dev, bus);
+       }
+}
+EXPORT_SYMBOL(pcibios_fixup_bus);
+
+/******************************************************************
+ * pci_read_irq_line
+ *
+ * Reads the Interrupt Pin to determine if interrupt is use by card.
+ * If the interrupt is used, then gets the interrupt line from the 
+ * openfirmware and sets it in the pci_dev and pci_config line.
+ *
+ ******************************************************************/
+int pci_read_irq_line(struct pci_dev *pci_dev)
+{
+       u8 intpin;
+       struct device_node *node;
+
+       pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin);
+
+       if (intpin == 0) {
+               PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n",
+                      pci_name(pci_dev));
+               return 0;       
+       }
+
+       node = pci_device_to_OF_node(pci_dev);
+       if (node == NULL) { 
+               PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",
+                      pci_name(pci_dev));
+               return -1;      
+       }
+       if (node->n_intrs == 0)         {
+               PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n",
+                      pci_name(pci_dev));
+               return -1;      
+       }
+       pci_dev->irq = node->intrs[0].line;
+
+       pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq);
+       
+       PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",
+              pci_name(pci_dev), pci_dev->irq);
+       return 0;
 }
+EXPORT_SYMBOL(pci_read_irq_line);
+
+#endif /* CONFIG_PPC_MULTIPLATFORM */
index c771bdc..2ef21d7 100644 (file)
@@ -129,10 +129,10 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
  */
 static void *traverse_all_pci_devices(traverse_func pre)
 {
-       struct pci_controller *phb;
+       struct pci_controller *phb, *tmp;
        void *ret;
 
-       for (phb = hose_head; phb; phb = phb->next)
+       list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
                if ((ret = traverse_pci_devices(phb->arch_data, pre, phb))
                                != NULL)
                        return ret;
index 4d99851..951831f 100644 (file)
@@ -54,9 +54,9 @@ static inline struct iommu_table *devnode_table(struct pci_dev *dev)
        return ISERIES_DEVNODE(dev)->iommu_table;
 #endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
        return PCI_GET_DN(dev)->iommu_table;
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 }
 
 
index c059a76..c45ecbd 100644 (file)
@@ -44,9 +44,9 @@
 #undef DEBUG_FEATURE
 
 #ifdef DEBUG_FEATURE
-#define DBG(fmt,...) printk(KERN_DEBUG fmt)
+#define DBG(fmt...) printk(KERN_DEBUG fmt)
 #else
-#define DBG(fmt,...)
+#define DBG(fmt...)
 #endif
 
 /*
@@ -343,6 +343,10 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
                PMAC_TYPE_POWERMAC_G5,          g5_features,
                0,
        },
+       {       "PowerMac7,3",                  "PowerMac G5",
+               PMAC_TYPE_POWERMAC_G5,          g5_features,
+               0,
+       },
        {       "RackMac3,1",                   "XServe G5",
                PMAC_TYPE_POWERMAC_G5,          g5_features,
                0,
@@ -611,7 +615,7 @@ int __init pmac_feature_late_init(void)
 
 device_initcall(pmac_feature_late_init);
 
-
+#if 0
 static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
 {
        int     freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 };
@@ -625,6 +629,7 @@ static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
                       name, freqs[freq],
                       bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);
 }
+#endif
 
 void __init pmac_check_ht_link(void)
 {
index d07579f..52da757 100644 (file)
@@ -50,7 +50,7 @@ struct low_i2c_host
        struct device_node      *np;            /* OF device node */
        struct semaphore        mutex;          /* Access mutex for use by i2c-keywest */
        low_i2c_func_t          func;           /* Access function */
-       int                     is_open : 1;    /* Poor man's access control */
+       unsigned                is_open : 1;    /* Poor man's access control */
        int                     mode;           /* Current mode */
        int                     channel;        /* Current channel */
        int                     num_channels;   /* Number of channels */
index 1691957..9e1a069 100644 (file)
@@ -271,7 +271,7 @@ static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
                                    int offset, int len, u32 *val)
 {
        struct pci_controller *hose;
-       struct device_node *busdn;
+       struct device_node *busdn, *dn;
        unsigned long addr;
 
        if (bus->self)
@@ -284,6 +284,16 @@ static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
        if (hose == NULL)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
+       /* We only allow config cycles to devices that are in OF device-tree
+        * as we are apparently having some weird things going on with some
+        * revs of K2 on recent G5s
+        */
+       for (dn = busdn->child; dn; dn = dn->sibling)
+               if (dn->devfn == devfn)
+                       break;
+       if (dn == NULL)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
        addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
        if (!addr)
                return PCIBIOS_DEVICE_NOT_FOUND;
@@ -419,7 +429,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
         * properties or figuring out the U3 address space decoding logic and
         * then read it's configuration register (if any).
         */
-       hose->io_base_phys = 0xf4000000 + 0x00400000;
+       hose->io_base_phys = 0xf4000000;
        hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);
        isa_io_base = pci_io_base = (unsigned long) hose->io_base_virt;
        hose->io_resource.name = np->full_name;
@@ -664,17 +674,15 @@ void __init pmac_pcibios_fixup(void)
 
        pci_fix_bus_sysdata();
 
-#ifdef CONFIG_PMAC_DART
-       iommu_setup_pmac();
-#endif /* CONFIG_PMAC_DART */
+       iommu_setup_u3();
 
 }
 
 static void __init pmac_fixup_phb_resources(void)
 {
-       struct pci_controller *hose;
+       struct pci_controller *hose, *tmp;
        
-       for (hose = hose_head; hose; hose = hose->next) {
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
                unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
                hose->io_resource.start += offset;
                hose->io_resource.end += offset;
@@ -746,6 +754,9 @@ void __init pmac_pci_init(void)
         * the exception of U3/AGP (hook into pci_set_mwi)
         */
        pci_cache_line_size = 16; /* 64 bytes */
+
+       /* Allow all IO */
+       io_page_mask = -1;
 }
 
 /*
@@ -777,3 +788,4 @@ void fixup_k2_sata(struct pci_dev* dev)
                }
        }
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, fixup_k2_sata);
index 58e8b39..3d1de0f 100644 (file)
@@ -23,6 +23,8 @@
  * bootup setup stuff..
  */
 
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/errno.h>
@@ -63,7 +65,6 @@
 #include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/dma.h>
-#include <asm/bootx.h>
 #include <asm/btext.h>
 #include <asm/cputable.h>
 #include <asm/pmac_feature.h>
 
 #include "pmac.h"
 
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+
 static int current_root_goodness = -1;
 #define DEFAULT_ROOT_DEVICE Root_SDA1  /* sda1 - slightly silly choice */
 
@@ -81,10 +89,6 @@ int sccdbg;
 
 extern void udbg_init_scc(struct device_node *np);
 
-#ifdef CONFIG_BOOTX_TEXT
-void pmac_progress(char *s, unsigned short hex);
-#endif
-
 void __pmac pmac_show_cpuinfo(struct seq_file *m)
 {
        struct device_node *np;
@@ -134,28 +138,20 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m)
 
 void __init pmac_setup_arch(void)
 {
-       struct device_node *cpu;
-       int *fp;
-       unsigned long pvr;
-
-       pvr = PVR_VER(mfspr(PVR));
-
-       /* Set loops_per_jiffy to a half-way reasonable value,
-          for use until calibrate_delay gets called. */
-       cpu = find_type_devices("cpu");
-       if (cpu != 0) {
-               fp = (int *) get_property(cpu, "clock-frequency", NULL);
-               if (fp != 0) {
-                       if (pvr == 4 || pvr >= 8)
-                               /* 604, G3, G4 etc. */
-                               loops_per_jiffy = *fp / HZ;
-                       else
-                               /* 601, 603, etc. */
-                               loops_per_jiffy = *fp / (2*HZ);
-               } else
-                       loops_per_jiffy = 50000000 / HZ;
+       /* init to some ~sane value until calibrate_delay() runs */
+       loops_per_jiffy = 50000000;
+
+       /* Probe motherboard chipset */
+       pmac_feature_init();
+#if 0
+       /* Lock-enable the SCC channel used for debug */
+       if (sccdbg) {
+               np = of_find_node_by_name(NULL, "escc");
+               if (np)
+                       pmac_call_feature(PMAC_FTR_SCC_ENABLE, np,
+                                         PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
        }
-       
+#endif
        /* We can NAP */
        powersave_nap = 1;
 
@@ -183,67 +179,13 @@ void __init pmac_setup_arch(void)
 #endif
 }
 
-extern char *bootpath;
-extern char *bootdevice;
-void *boot_host;
-int boot_target;
-int boot_part;
-extern dev_t boot_dev;
-
 #ifdef CONFIG_SCSI
-void __init note_scsi_host(struct device_node *node, void *host)
+void note_scsi_host(struct device_node *node, void *host)
 {
-       int l;
-       char *p;
-
-       l = strlen(node->full_name);
-       if (bootpath != NULL && bootdevice != NULL
-           && strncmp(node->full_name, bootdevice, l) == 0
-           && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
-               boot_host = host;
-               /*
-                * There's a bug in OF 1.0.5.  (Why am I not surprised.)
-                * If you pass a path like scsi/sd@1:0 to canon, it returns
-                * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
-                * That is, the scsi target number doesn't get preserved.
-                * So we pick the target number out of bootpath and use that.
-                */
-               p = strstr(bootpath, "/sd@");
-               if (p != NULL) {
-                       p += 4;
-                       boot_target = simple_strtoul(p, NULL, 10);
-                       p = strchr(p, ':');
-                       if (p != NULL)
-                               boot_part = simple_strtoul(p + 1, NULL, 10);
-               }
-       }
+       /* Obsolete */
 }
 #endif
 
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-static dev_t __init find_ide_boot(void)
-{
-       char *p;
-       int n;
-       dev_t __init pmac_find_ide_boot(char *bootdevice, int n);
-
-       if (bootdevice == NULL)
-               return 0;
-       p = strrchr(bootdevice, '/');
-       if (p == NULL)
-               return 0;
-       n = p - bootdevice;
-
-       return pmac_find_ide_boot(bootdevice, n);
-}
-#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
-
-void __init find_boot_device(void)
-{
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-       boot_dev = find_ide_boot();
-#endif
-}
 
 static int initializing = 1;
 
@@ -258,7 +200,7 @@ late_initcall(pmac_late_init);
 /* can't be __init - can be called whenever a disk is first accessed */
 void __pmac note_bootable_part(dev_t dev, int part, int goodness)
 {
-       static int found_boot = 0;
+       extern dev_t boot_dev;
        char *p;
 
        if (!initializing)
@@ -270,10 +212,6 @@ void __pmac note_bootable_part(dev_t dev, int part, int goodness)
        if (p != NULL && (p == saved_command_line || p[-1] == ' '))
                return;
 
-       if (!found_boot) {
-               find_boot_device();
-               found_boot = 1;
-       }
        if (!boot_dev || dev == boot_dev) {
                ROOT_DEV = dev + part;
                boot_dev = 0;
@@ -313,21 +251,73 @@ static void btext_putc(unsigned char c)
 }
 #endif /* CONFIG_BOOTX_TEXT */
 
+static void __init init_boot_display(void)
+{
+       char *name;
+       struct device_node *np = NULL; 
+       int rc = -ENODEV;
+
+       printk("trying to initialize btext ...\n");
+
+       name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+       if (name != NULL) {
+               np = of_find_node_by_path(name);
+               if (np != NULL) {
+                       if (strcmp(np->type, "display") != 0) {
+                               printk("boot stdout isn't a display !\n");
+                               of_node_put(np);
+                               np = NULL;
+                       }
+               }
+       }
+       if (np)
+               rc = btext_initialize(np);
+       if (rc == 0)
+               return;
+
+       for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
+               if (get_property(np, "linux,opened", NULL)) {
+                       printk("trying %s ...\n", np->full_name);
+                       rc = btext_initialize(np);
+                       printk("result: %d\n", rc);
+               }
+               if (rc == 0)
+                       return;
+       }
+}
+
 /* 
  * Early initialization.
- * Relocation is on but do not reference unbolted pages
- * Also, device-tree hasn't been "finished", so don't muck with
- * it too much
  */
 void __init pmac_init_early(void)
 {
-       hpte_init_pSeries();
+       DBG(" -> pmac_init_early\n");
+
+       /* Initialize hash table, from now on, we can take hash faults
+        * and call ioremap
+        */
+       hpte_init_native();
 
+       /* Init SCC */
+               if (strstr(cmd_line, "sccdbg")) {
+               sccdbg = 1;
+                       udbg_init_scc(NULL);
+               }
+
+       else {
 #ifdef CONFIG_BOOTX_TEXT
-       ppc_md.udbg_putc = btext_putc;
-       ppc_md.udbg_getc = dummy_getc;
-       ppc_md.udbg_getc_poll = dummy_getc_poll;
+               init_boot_display();
+
+               ppc_md.udbg_putc = btext_putc;
+               ppc_md.udbg_getc = dummy_getc;
+               ppc_md.udbg_getc_poll = dummy_getc_poll;
 #endif /* CONFIG_BOOTX_TEXT */
+       }
+
+       /* Setup interrupt mapping options */
+       naca->interrupt_controller = IC_OPEN_PIC;
+
+       DBG(" <- pmac_init_early\n");
 }
 
 extern void* OpenPIC_Addr;
@@ -417,60 +407,19 @@ static int __init pmac_irq_cascade_init(void)
 
 core_initcall(pmac_irq_cascade_init);
 
-void __init pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
-                     unsigned long r6, unsigned long r7)
-{
-       /* Probe motherboard chipset */
-       pmac_feature_init();
-
-       /* Init SCC */
-       if (strstr(cmd_line, "sccdbg")) {
-               sccdbg = 1;
-               udbg_init_scc(NULL);
-       }
-
-       /* Fill up the machine description */
-       ppc_md.setup_arch     = pmac_setup_arch;
-               ppc_md.get_cpuinfo    = pmac_show_cpuinfo;
-
-       ppc_md.init_IRQ       = pmac_init_IRQ;
-       ppc_md.get_irq        = openpic_get_irq;
-
-       ppc_md.pcibios_fixup  = pmac_pcibios_fixup;
-
-       ppc_md.restart        = pmac_restart;
-       ppc_md.power_off      = pmac_power_off;
-       ppc_md.halt           = pmac_halt;
-
-               ppc_md.get_boot_time  = pmac_get_boot_time;
-               ppc_md.set_rtc_time   = pmac_set_rtc_time;
-               ppc_md.get_rtc_time   = pmac_get_rtc_time;
-       ppc_md.calibrate_decr = pmac_calibrate_decr;
-
-       ppc_md.feature_call   = pmac_do_feature_call;
-
-
-#ifdef CONFIG_BOOTX_TEXT
-       ppc_md.progress       = pmac_progress;
-#endif /* CONFIG_BOOTX_TEXT */
-
-       if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
-
-}
-
-#ifdef CONFIG_BOOTX_TEXT
-void __init pmac_progress(char *s, unsigned short hex)
+static void __init pmac_progress(char *s, unsigned short hex)
 {
        if (sccdbg) {
                udbg_puts(s);
-               udbg_putc('\n');
+               udbg_puts("\n");
        }
+#ifdef CONFIG_BOOTX_TEXT
        else if (boot_text_mapped) {
                btext_drawstring(s);
-               btext_drawchar('\n');
+               btext_drawstring("\n");
        }
-}
 #endif /* CONFIG_BOOTX_TEXT */
+}
 
 static int __init pmac_declare_of_platform_devices(void)
 {
@@ -489,3 +438,41 @@ static int __init pmac_declare_of_platform_devices(void)
 }
 
 device_initcall(pmac_declare_of_platform_devices);
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init pmac_probe(int platform)
+{
+       if (platform != PLATFORM_POWERMAC)
+               return 0;
+
+       /*
+        * On U3, the DART (iommu) must be allocated now since it
+        * has an impact on htab_initialize (due to the large page it
+        * occupies having to be broken up so the DART itself is not
+        * part of the cacheable linar mapping
+        */
+       alloc_u3_dart_table();
+
+       return 1;
+}
+
+struct machdep_calls __initdata pmac_md = {
+       .probe                  = pmac_probe,
+       .setup_arch             = pmac_setup_arch,
+       .init_early             = pmac_init_early,
+               .get_cpuinfo            = pmac_show_cpuinfo,
+       .init_IRQ               = pmac_init_IRQ,
+       .get_irq                = openpic_get_irq,
+       .pcibios_fixup          = pmac_pcibios_fixup,
+       .restart                = pmac_restart,
+       .power_off              = pmac_power_off,
+       .halt                   = pmac_halt,
+               .get_boot_time          = pmac_get_boot_time,
+               .set_rtc_time           = pmac_set_rtc_time,
+               .get_rtc_time           = pmac_get_rtc_time,
+       .calibrate_decr         = pmac_calibrate_decr,
+       .feature_call           = pmac_do_feature_call,
+       .progress               = pmac_progress,
+};
index aea28b9..06f3798 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/time.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
+#include <linux/interrupt.h>
 
 #include <asm/sections.h>
 #include <asm/prom.h>
@@ -25,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
-#include <asm/hardirq.h>
 #include <asm/time.h>
 #include <asm/nvram.h>
 
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
new file mode 100644 (file)
index 0000000..f62bda7
--- /dev/null
@@ -0,0 +1,1714 @@
+/*
+ * 
+ *
+ * Procedures for interfacing to Open Firmware.
+ *
+ * Paul Mackerras      August 1996.
+ * Copyright (C) 1996 Paul Mackerras.
+ * 
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@us.ibm.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.
+ */
+
+#undef DEBUG_PROM
+
+#include <stdarg.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/stringify.h>
+#include <linux/delay.h>
+#include <linux/initrd.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+#include <asm/abs_addr.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/bitops.h>
+#include <asm/naca.h>
+#include <asm/pci.h>
+#include <asm/iommu.h>
+#include <asm/bootinfo.h>
+#include <asm/ppcdebug.h>
+#include <asm/btext.h>
+#include <asm/sections.h>
+#include <asm/machdep.h>
+#include "open_pic.h"
+
+#ifdef CONFIG_LOGO_LINUX_CLUT224
+#include <linux/linux_logo.h>
+extern const struct linux_logo logo_linux_clut224;
+#endif
+
+/*
+ * Properties whose value is longer than this get excluded from our
+ * copy of the device tree. This value does need to be big enough to
+ * ensure that we don't lose things like the interrupt-map property
+ * on a PCI-PCI bridge.
+ */
+#define MAX_PROPERTY_LENGTH    (1UL * 1024 * 1024)
+
+/*
+ * Eventually bump that one up
+ */
+#define DEVTREE_CHUNK_SIZE     0x100000
+
+/*
+ * This is the size of the local memory reserve map that gets copied
+ * into the boot params passed to the kernel. That size is totally
+ * flexible as the kernel just reads the list until it encounters an
+ * entry with size 0, so it can be changed without breaking binary
+ * compatibility
+ */
+#define MEM_RESERVE_MAP_SIZE   8
+
+/*
+ * prom_init() is called very early on, before the kernel text
+ * and data have been mapped to KERNELBASE.  At this point the code
+ * is running at whatever address it has been loaded at, so
+ * references to extern and static variables must be relocated
+ * explicitly.  The procedure reloc_offset() returns the address
+ * we're currently running at minus the address we were linked at.
+ * (Note that strings count as static variables.)
+ *
+ * Because OF may have mapped I/O devices into the area starting at
+ * KERNELBASE, particularly on CHRP machines, we can't safely call
+ * OF once the kernel has been mapped to KERNELBASE.  Therefore all
+ * OF calls should be done within prom_init(), and prom_init()
+ * and all routines called within it must be careful to relocate
+ * references as necessary.
+ *
+ * Note that the bss is cleared *after* prom_init runs, so we have
+ * to make sure that any static or extern variables it accesses
+ * are put in the data segment.
+ */
+
+
+#define PROM_BUG() do {                                                \
+        prom_printf("kernel BUG at %s line 0x%x!\n",           \
+                   RELOC(__FILE__), __LINE__);                 \
+        __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR);      \
+} while (0)
+
+#ifdef DEBUG_PROM
+#define prom_debug(x...)       prom_printf(x)
+#else
+#define prom_debug(x...)
+#endif
+
+
+typedef u32 prom_arg_t;
+
+struct prom_args {
+        u32 service;
+        u32 nargs;
+        u32 nret;
+        prom_arg_t args[10];
+        prom_arg_t *rets;     /* Pointer to return values in args[16]. */
+};
+
+struct prom_t {
+       unsigned long entry;
+       ihandle root;
+       ihandle chosen;
+       int cpu;
+       ihandle stdout;
+       ihandle disp_node;
+       struct prom_args args;
+       unsigned long version;
+       unsigned long root_size_cells;
+       unsigned long root_addr_cells;
+};
+
+struct pci_reg_property {
+       struct pci_address addr;
+       u32 size_hi;
+       u32 size_lo;
+};
+
+struct mem_map_entry {
+       u64     base;
+       u64     size;
+};
+
+typedef u32 cell_t;
+
+extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
+
+extern unsigned long reloc_offset(void);
+extern void enter_prom(struct prom_args *args, unsigned long entry);
+extern void copy_and_flush(unsigned long dest, unsigned long src,
+                          unsigned long size, unsigned long offset);
+
+extern unsigned long klimit;
+
+//int global_width = 640, global_height = 480, global_depth = 8, global_pitch;
+//unsigned global_address;
+/* prom structure */
+static struct prom_t __initdata prom;
+
+#define PROM_SCRATCH_SIZE 256
+
+static char __initdata of_stdout_device[256];
+static char __initdata prom_scratch[PROM_SCRATCH_SIZE];
+
+static unsigned long __initdata dt_header_start;
+static unsigned long __initdata dt_struct_start, dt_struct_end;
+static unsigned long __initdata dt_string_start, dt_string_end;
+
+static unsigned long __initdata prom_initrd_start, prom_initrd_end;
+
+static int __initdata iommu_force_on;
+static int __initdata ppc64_iommu_off;
+static int __initdata of_platform;
+
+static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
+
+static unsigned long __initdata alloc_top;
+static unsigned long __initdata alloc_top_high;
+static unsigned long __initdata alloc_bottom;
+static unsigned long __initdata rmo_top;
+static unsigned long __initdata ram_top;
+
+static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
+static int __initdata mem_reserve_cnt;
+
+static cell_t __initdata regbuf[1024];
+
+
+#define MAX_CPU_THREADS 2
+
+/* TO GO */
+#ifdef CONFIG_HMT
+struct {
+       unsigned int pir;
+       unsigned int threadid;
+} hmt_thread_data[NR_CPUS];
+#endif /* CONFIG_HMT */
+
+/*
+ * This are used in calls to call_prom.  The 4th and following
+ * arguments to call_prom should be 32-bit values.  64 bit values
+ * are truncated to 32 bits (and fortunately don't get interpreted
+ * as two arguments).
+ */
+#define ADDR(x)                (u32) ((unsigned long)(x) - offset)
+
+/* This is the one and *ONLY* place where we actually call open
+ * firmware from, since we need to make sure we're running in 32b
+ * mode when we do.  We switch back to 64b mode upon return.
+ */
+
+#define PROM_ERROR     (-1)
+
+static int __init call_prom(const char *service, int nargs, int nret, ...)
+{
+       int i;
+       unsigned long offset = reloc_offset();
+       struct prom_t *_prom = PTRRELOC(&prom);
+       va_list list;
+
+       _prom->args.service = ADDR(service);
+       _prom->args.nargs = nargs;
+       _prom->args.nret = nret;
+       _prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]);
+
+       va_start(list, nret);
+       for (i=0; i < nargs; i++)
+               _prom->args.args[i] = va_arg(list, prom_arg_t);
+       va_end(list);
+
+       for (i=0; i < nret ;i++)
+               _prom->args.rets[i] = 0;
+
+       enter_prom(&_prom->args, _prom->entry);
+
+       return (nret > 0) ? _prom->args.rets[0] : 0;
+}
+
+
+static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
+                               unsigned long align)
+{
+       return (unsigned int)call_prom("claim", 3, 1,
+                                      (prom_arg_t)virt, (prom_arg_t)size,
+                                      (prom_arg_t)align);
+}
+
+static void __init prom_print(const char *msg)
+{
+       const char *p, *q;
+       unsigned long offset = reloc_offset();
+       struct prom_t *_prom = PTRRELOC(&prom);
+
+       if (_prom->stdout == 0)
+               return;
+
+       for (p = msg; *p != 0; p = q) {
+               for (q = p; *q != 0 && *q != '\n'; ++q)
+                       ;
+               if (q > p)
+                       call_prom("write", 3, 1, _prom->stdout, p, q - p);
+               if (*q == 0)
+                       break;
+               ++q;
+               call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2);
+       }
+}
+
+
+static void __init prom_print_hex(unsigned long val)
+{
+       unsigned long offset = reloc_offset();
+       int i, nibbles = sizeof(val)*2;
+       char buf[sizeof(val)*2+1];
+       struct prom_t *_prom = PTRRELOC(&prom);
+
+       for (i = nibbles-1;  i >= 0;  i--) {
+               buf[i] = (val & 0xf) + '0';
+               if (buf[i] > '9')
+                       buf[i] += ('a'-'0'-10);
+               val >>= 4;
+       }
+       buf[nibbles] = '\0';
+       call_prom("write", 3, 1, _prom->stdout, buf, nibbles);
+}
+
+
+static void __init prom_printf(const char *format, ...)
+{
+       unsigned long offset = reloc_offset();
+       const char *p, *q, *s;
+       va_list args;
+       unsigned long v;
+       struct prom_t *_prom = PTRRELOC(&prom);
+
+       va_start(args, format);
+       for (p = PTRRELOC(format); *p != 0; p = q) {
+               for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
+                       ;
+               if (q > p)
+                       call_prom("write", 3, 1, _prom->stdout, p, q - p);
+               if (*q == 0)
+                       break;
+               if (*q == '\n') {
+                       ++q;
+                       call_prom("write", 3, 1, _prom->stdout,
+                                 ADDR("\r\n"), 2);
+                       continue;
+               }
+               ++q;
+               if (*q == 0)
+                       break;
+               switch (*q) {
+               case 's':
+                       ++q;
+                       s = va_arg(args, const char *);
+                       prom_print(s);
+                       break;
+               case 'x':
+                       ++q;
+                       v = va_arg(args, unsigned long);
+                       prom_print_hex(v);
+                       break;
+               }
+       }
+}
+
+
+static void __init __attribute__((noreturn)) prom_panic(const char *reason)
+{
+       unsigned long offset = reloc_offset();
+
+       prom_print(PTRRELOC(reason));
+       /* ToDo: should put up an SRC here */
+       call_prom("exit", 0, 0);
+
+       for (;;)                        /* should never get here */
+               ;
+}
+
+
+static int __init prom_next_node(phandle *nodep)
+{
+       phandle node;
+
+       if ((node = *nodep) != 0
+           && (*nodep = call_prom("child", 1, 1, node)) != 0)
+               return 1;
+       if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
+               return 1;
+       for (;;) {
+               if ((node = call_prom("parent", 1, 1, node)) == 0)
+                       return 0;
+               if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
+                       return 1;
+       }
+}
+
+static int __init prom_getprop(phandle node, const char *pname,
+                              void *value, size_t valuelen)
+{
+       unsigned long offset = reloc_offset();
+
+       return call_prom("getprop", 4, 1, node, ADDR(pname),
+                        (u32)(unsigned long) value, (u32) valuelen);
+}
+
+static int __init prom_getproplen(phandle node, const char *pname)
+{
+       unsigned long offset = reloc_offset();
+
+       return call_prom("getproplen", 2, 1, node, ADDR(pname));
+}
+
+static int __init prom_setprop(phandle node, const char *pname,
+                              void *value, size_t valuelen)
+{
+       unsigned long offset = reloc_offset();
+
+       return call_prom("setprop", 4, 1, node, ADDR(pname),
+                        (u32)(unsigned long) value, (u32) valuelen);
+}
+
+
+/*
+ * Early parsing of the command line passed to the kernel, used for
+ * the options that affect the iommu
+ */
+static void __init early_cmdline_parse(void)
+{
+       unsigned long offset = reloc_offset();
+       struct prom_t *_prom = PTRRELOC(&prom);
+       char *opt, *p;
+       int l = 0;
+
+       RELOC(prom_cmd_line[0]) = 0;
+       p = RELOC(prom_cmd_line);
+       if ((long)_prom->chosen > 0)
+               l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
+#ifdef CONFIG_CMDLINE
+       if (l == 0) /* dbl check */
+               strlcpy(RELOC(prom_cmd_line),
+                       RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line));
+#endif /* CONFIG_CMDLINE */
+       prom_printf("command line: %s\n", RELOC(prom_cmd_line));
+
+       opt = strstr(RELOC(prom_cmd_line), RELOC("iommu="));
+       if (opt) {
+               prom_printf("iommu opt is: %s\n", opt);
+               opt += 6;
+               while (*opt && *opt == ' ')
+                       opt++;
+               if (!strncmp(opt, RELOC("off"), 3))
+                       RELOC(ppc64_iommu_off) = 1;
+               else if (!strncmp(opt, RELOC("force"), 5))
+                       RELOC(iommu_force_on) = 1;
+       }
+}
+
+/*
+ * Memory allocation strategy... our layout is normally:
+ *
+ *  at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, initrd
+ *  might end up beeing before the kernel though. We assume this won't override
+ *  the final kernel at 0, we have no provision to handle that in this version,
+ *  but it should hopefully never happen.
+ *
+ *  alloc_top is set to the top of RMO, eventually shrink down if the TCEs overlap
+ *  alloc_bottom is set to the top of kernel/initrd
+ *
+ *  from there, allocations are done that way : rtas is allocated topmost, and
+ *  the device-tree is allocated from the bottom. We try to grow the device-tree
+ *  allocation as we progress. If we can't, then we fail, we don't currently have
+ *  a facility to restart elsewhere, but that shouldn't be necessary neither
+ *
+ *  Note that calls to reserve_mem have to be done explicitely, memory allocated
+ *  with either alloc_up or alloc_down isn't automatically reserved.
+ */
+
+
+/*
+ * Allocates memory in the RMO upward from the kernel/initrd
+ *
+ * When align is 0, this is a special case, it means to allocate in place
+ * at the current location of alloc_bottom or fail (that is basically
+ * extending the previous allocation). Used for the device-tree flattening
+ */
+static unsigned long __init alloc_up(unsigned long size, unsigned long align)
+{
+       unsigned long offset = reloc_offset();
+       unsigned long base = _ALIGN_UP(RELOC(alloc_bottom), align);
+       unsigned long addr = 0;
+
+       prom_debug("alloc_up(%x, %x)\n", size, align);
+       if (RELOC(ram_top) == 0)
+               prom_panic("alloc_up() called with mem not initialized\n");
+
+       if (align)
+               base = _ALIGN_UP(RELOC(alloc_bottom), align);
+       else
+               base = RELOC(alloc_bottom);
+
+       for(; (base + size) <= RELOC(alloc_top); 
+           base = _ALIGN_UP(base + 0x100000, align)) {
+               prom_debug("    trying: 0x%x\n\r", base);
+               addr = (unsigned long)prom_claim(base, size, 0);
+               if ((int)addr != PROM_ERROR)
+                       break;
+               addr = 0;
+               if (align == 0)
+                       break;
+       }
+       if (addr == 0)
+               return 0;
+       RELOC(alloc_bottom) = addr;
+
+       prom_debug(" -> %x\n", addr);
+       prom_debug("  alloc_bottom : %x\n", RELOC(alloc_bottom));
+       prom_debug("  alloc_top    : %x\n", RELOC(alloc_top));
+       prom_debug("  alloc_top_hi : %x\n", RELOC(alloc_top_high));
+       prom_debug("  rmo_top      : %x\n", RELOC(rmo_top));
+       prom_debug("  ram_top      : %x\n", RELOC(ram_top));
+
+       return addr;
+}
+
+/*
+ * Allocates memory downard, either from top of RMO, or if highmem
+ * is set, from the top of RAM. Note that this one doesn't handle
+ * failures. In does claim memory if highmem is not set.
+ */
+static unsigned long __init alloc_down(unsigned long size, unsigned long align,
+                                      int highmem)
+{
+       unsigned long offset = reloc_offset();
+       unsigned long base, addr = 0;
+
+       prom_debug("alloc_down(%x, %x, %s)\n", size, align,
+                  highmem ? RELOC("(high)") : RELOC("(low)"));
+       if (RELOC(ram_top) == 0)
+               prom_panic("alloc_down() called with mem not initialized\n");
+
+       if (highmem) {
+               /* Carve out storage for the TCE table. */
+               addr = _ALIGN_DOWN(RELOC(alloc_top_high) - size, align);
+               if (addr <= RELOC(alloc_bottom))
+                       return 0;
+               else {
+                       /* Will we bump into the RMO ? If yes, check out that we
+                        * didn't overlap existing allocations there, if we did,
+                        * we are dead, we must be the first in town !
+                        */
+                       if (addr < RELOC(rmo_top)) {
+                               /* Good, we are first */
+                               if (RELOC(alloc_top) == RELOC(rmo_top))
+                                       RELOC(alloc_top) = RELOC(rmo_top) = addr;
+                               else
+                                       return 0;
+                       }
+                       RELOC(alloc_top_high) = addr;
+               }
+               goto bail;
+       }
+
+       base = _ALIGN_DOWN(RELOC(alloc_top) - size, align);
+       for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align))  {
+               prom_debug("    trying: 0x%x\n\r", base);
+               addr = (unsigned long)prom_claim(base, size, 0);
+               if ((int)addr != PROM_ERROR)
+                       break;
+               addr = 0;
+       }
+       if (addr == 0)
+               return 0;
+       RELOC(alloc_top) = addr;
+
+ bail:
+       prom_debug(" -> %x\n", addr);
+       prom_debug("  alloc_bottom : %x\n", RELOC(alloc_bottom));
+       prom_debug("  alloc_top    : %x\n", RELOC(alloc_top));
+       prom_debug("  alloc_top_hi : %x\n", RELOC(alloc_top_high));
+       prom_debug("  rmo_top      : %x\n", RELOC(rmo_top));
+       prom_debug("  ram_top      : %x\n", RELOC(ram_top));
+
+       return addr;
+}
+
+/*
+ * Parse a "reg" cell
+ */
+static unsigned long __init prom_next_cell(int s, cell_t **cellp)
+{
+       cell_t *p = *cellp;
+       unsigned long r = 0;
+
+       /* Ignore more than 2 cells */
+       while (s > 2) {
+               p++;
+               s--;
+       }
+       while (s) {
+               r <<= 32;
+               r |= *(p++);
+               s--;
+       }
+
+       *cellp = p;
+       return r;
+}
+
+/*
+ * Very dumb function for adding to the memory reserve list, but
+ * we don't need anything smarter at this point
+ *
+ * XXX Eventually check for collisions. They should NEVER happen
+ * if problems seem to show up, it would be a good start to track
+ * them down.
+ */
+static void reserve_mem(unsigned long base, unsigned long size)
+{
+       unsigned long offset = reloc_offset();
+       unsigned long top = base + size;
+       unsigned long cnt = RELOC(mem_reserve_cnt);
+
+       if (size == 0)
+               return;
+
+       /* We need to always keep one empty entry so that we
+        * have our terminator with "size" set to 0 since we are
+        * dumb and just copy this entire array to the boot params
+        */
+       base = _ALIGN_DOWN(base, PAGE_SIZE);
+       top = _ALIGN_UP(top, PAGE_SIZE);
+       size = top - base;
+
+       if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
+               prom_panic("Memory reserve map exhausted !\n");
+       RELOC(mem_reserve_map)[cnt].base = base;
+       RELOC(mem_reserve_map)[cnt].size = size;
+       RELOC(mem_reserve_cnt) = cnt + 1;
+}
+
+/*
+ * Initialize memory allocation mecanism, parse "memory" nodes and
+ * obtain that way the top of memory and RMO to setup out local allocator
+ */
+static void __init prom_init_mem(void)
+{
+       phandle node;
+       char *path, type[64];
+       unsigned int plen;
+       cell_t *p, *endp;
+       unsigned long offset = reloc_offset();
+       struct prom_t *_prom = PTRRELOC(&prom);
+
+       /*
+        * We iterate the memory nodes to find
+        * 1) top of RMO (first node)
+        * 2) top of memory
+        */
+       prom_debug("root_addr_cells: %x\n", (long)_prom->root_addr_cells);
+       prom_debug("root_size_cells: %x\n", (long)_prom->root_size_cells);
+
+       prom_debug("scanning memory:\n");
+       path = RELOC(prom_scratch);
+
+       for (node = 0; prom_next_node(&node); ) {
+               type[0] = 0;
+               prom_getprop(node, "device_type", type, sizeof(type));
+
+               if (strcmp(type, RELOC("memory")))
+                       continue;
+       
+               plen = prom_getprop(node, "reg", RELOC(regbuf), sizeof(regbuf));
+               if (plen > sizeof(regbuf)) {
+                       prom_printf("memory node too large for buffer !\n");
+                       plen = sizeof(regbuf);
+               }
+               p = RELOC(regbuf);
+               endp = p + (plen / sizeof(cell_t));
+
+#ifdef DEBUG_PROM
+               memset(path, 0, PROM_SCRATCH_SIZE);
+               call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
+               prom_debug("  node %s :\n", path);
+#endif /* DEBUG_PROM */
+
+               while ((endp - p) >= (_prom->root_addr_cells + _prom->root_size_cells)) {
+                       unsigned long base, size;
+
+                       base = prom_next_cell(_prom->root_addr_cells, &p);
+                       size = prom_next_cell(_prom->root_size_cells, &p);
+
+                       if (size == 0)
+                               continue;
+                       prom_debug("    %x %x\n", base, size);
+                       if (base == 0)
+                               RELOC(rmo_top) = size;
+                       if ((base + size) > RELOC(ram_top))
+                               RELOC(ram_top) = base + size;
+               }
+       }
+
+       /* Setup our top/bottom alloc points, that is top of RMO or top of
+        * segment 0 when running non-LPAR
+        */
+       if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
+               RELOC(alloc_top) = RELOC(rmo_top);
+       else
+               RELOC(alloc_top) = min(0x40000000ul, RELOC(ram_top));
+       RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(klimit) - offset + 0x4000);
+       RELOC(alloc_top_high) = RELOC(ram_top);
+
+       /* Check if we have an initrd after the kernel, if we do move our bottom
+        * point to after it
+        */
+       if (RELOC(prom_initrd_start)) {
+               if ((RELOC(prom_initrd_start) + RELOC(prom_initrd_end))
+                   > RELOC(alloc_bottom))
+                       RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end));
+       }
+
+       prom_printf("memory layout at init:\n");
+       prom_printf("  alloc_bottom : %x\n", RELOC(alloc_bottom));
+       prom_printf("  alloc_top    : %x\n", RELOC(alloc_top));
+       prom_printf("  alloc_top_hi : %x\n", RELOC(alloc_top_high));
+       prom_printf("  rmo_top      : %x\n", RELOC(rmo_top));
+       prom_printf("  ram_top      : %x\n", RELOC(ram_top));
+}
+
+
+/*
+ * Allocate room for and instanciate RTAS
+ */
+static void __init prom_instantiate_rtas(void)
+{
+       unsigned long offset = reloc_offset();
+       struct prom_t *_prom = PTRRELOC(&prom);
+       phandle prom_rtas;
+       u64 base, entry = 0;
+        u32 size;
+
+       prom_debug("prom_instantiate_rtas: start...\n");
+
+       prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
+       if (prom_rtas != (phandle) -1) {
+               prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
+               if (size != 0) {
+                       base = alloc_down(size, PAGE_SIZE, 0);
+                       if (base == 0) {
+                               prom_printf("RTAS allocation failed !\n");
+                               return;
+                       }
+                       prom_printf("instantiating rtas at 0x%x", base);
+
+                       prom_rtas = call_prom("open", 1, 1, ADDR("/rtas"));
+                       prom_printf("...");
+
+                       if (call_prom("call-method", 3, 2,
+                                     ADDR("instantiate-rtas"),
+                                     prom_rtas, base) != PROM_ERROR) {
+                               entry = (long)_prom->args.rets[1];
+                       }
+                       if (entry == 0) {
+                               prom_printf(" failed\n");
+                               return;
+                       }
+                       prom_printf(" done\n");
+
+                       reserve_mem(base, size);
+               }
+
+               prom_setprop(_prom->chosen, "linux,rtas-base", &base, sizeof(base));
+               prom_setprop(_prom->chosen, "linux,rtas-entry", &entry, sizeof(entry));
+               prom_setprop(_prom->chosen, "linux,rtas-size", &size, sizeof(size));
+
+               prom_debug("rtas base     = 0x%x\n", base);
+               prom_debug("rtas entry    = 0x%x\n", entry);
+               prom_debug("rtas size     = 0x%x\n", (long)size);
+       }
+       prom_debug("prom_instantiate_rtas: end...\n");
+}
+
+
+/*
+ * Allocate room for and initialize TCE tables
+ */
+static void __init prom_initialize_tce_table(void)
+{
+       phandle node;
+       ihandle phb_node;
+       unsigned long offset = reloc_offset();
+       char compatible[64], type[64], model[64];
+       char *path = RELOC(prom_scratch);
+       u64 base, vbase, align;
+       u32 minalign, minsize;
+       u64 tce_entry, *tce_entryp;
+       u64 local_alloc_top, local_alloc_bottom;
+       u64 i;
+
+       if (RELOC(ppc64_iommu_off))
+               return;
+
+       prom_debug("starting prom_initialize_tce_table\n");
+
+       /* Cache current top of allocs so we reserve a single block */
+       local_alloc_top = RELOC(alloc_top_high);
+       local_alloc_bottom = local_alloc_top;
+
+       /* Search all nodes looking for PHBs. */
+       for (node = 0; prom_next_node(&node); ) {
+               compatible[0] = 0;
+               type[0] = 0;
+               model[0] = 0;
+               prom_getprop(node, "compatible",
+                            compatible, sizeof(compatible));
+               prom_getprop(node, "device_type", type, sizeof(type));
+               prom_getprop(node, "model", model, sizeof(model));
+
+               if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL))
+                       continue;
+
+               /* Keep the old logic in tack to avoid regression. */
+               if (compatible[0] != 0) {
+                       if ((strstr(compatible, RELOC("python")) == NULL) &&
+                           (strstr(compatible, RELOC("Speedwagon")) == NULL) &&
+                           (strstr(compatible, RELOC("Winnipeg")) == NULL))
+                               continue;
+               } else if (model[0] != 0) {
+                       if ((strstr(model, RELOC("ython")) == NULL) &&
+                           (strstr(model, RELOC("peedwagon")) == NULL) &&
+                           (strstr(model, RELOC("innipeg")) == NULL))
+                               continue;
+               }
+
+               if (prom_getprop(node, "tce-table-minalign", &minalign,
+                                sizeof(minalign)) == PROM_ERROR)
+                       minalign = 0;
+               if (prom_getprop(node, "tce-table-minsize", &minsize,
+                                sizeof(minsize)) == PROM_ERROR)
+                       minsize = 4UL << 20;
+
+               /*
+                * Even though we read what OF wants, we just set the table
+                * size to 4 MB.  This is enough to map 2GB of PCI DMA space.
+                * By doing this, we avoid the pitfalls of trying to DMA to
+                * MMIO space and the DMA alias hole.
+                *
+                * On POWER4, firmware sets the TCE region by assuming
+                * each TCE table is 8MB. Using this memory for anything
+                * else will impact performance, so we always allocate 8MB.
+                * Anton
+                */
+               if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))
+                       minsize = 8UL << 20;
+               else
+                       minsize = 4UL << 20;
+
+               /* Align to the greater of the align or size */
+               align = max(minalign, minsize);
+               base = alloc_down(minsize, align, 1);
+               if (base == 0)
+                       prom_panic("ERROR, cannot find space for TCE table.\n");
+               if (base < local_alloc_bottom)
+                       local_alloc_bottom = base;
+
+               vbase = (unsigned long)abs_to_virt(base);
+
+               /* Save away the TCE table attributes for later use. */
+               prom_setprop(node, "linux,tce-base", &vbase, sizeof(vbase));
+               prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize));
+               prom_setprop(node, "linux,has-tce-table", NULL, 0);
+
+               /* It seems OF doesn't null-terminate the path :-( */
+               memset(path, 0, sizeof(path));
+               /* Call OF to setup the TCE hardware */
+               if (call_prom("package-to-path", 3, 1, node,
+                             path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
+                       prom_printf("package-to-path failed\n");
+               }
+
+               prom_debug("TCE table: %s\n", path);
+               prom_debug("\tnode = 0x%x\n", node);
+               prom_debug("\tbase = 0x%x\n", vbase);
+               prom_debug("\tsize = 0x%x\n", minsize);
+
+               /* Initialize the table to have a one-to-one mapping
+                * over the allocated size.
+                */
+               tce_entryp = (unsigned long *)base;
+               for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
+                       tce_entry = (i << PAGE_SHIFT);
+                       tce_entry |= 0x3;
+                       *tce_entryp = tce_entry;
+               }
+
+               prom_printf("opening PHB %s", path);
+               phb_node = call_prom("open", 1, 1, path);
+               if ( (long)phb_node <= 0)
+                       prom_printf("... failed\n");
+               else
+                       prom_printf("... done\n");
+
+               call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
+                         phb_node, -1, minsize,
+                         (u32) base, (u32) (base >> 32));
+               call_prom("close", 1, 0, phb_node);
+       }
+
+       reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
+
+       /* Flag the first invalid entry */
+       prom_debug("ending prom_initialize_tce_table\n");
+}
+
+/*
+ * With CHRP SMP we need to use the OF to start the other
+ * processors so we can't wait until smp_boot_cpus (the OF is
+ * trashed by then) so we have to put the processors into
+ * a holding pattern controlled by the kernel (not OF) before
+ * we destroy the OF.
+ *
+ * This uses a chunk of low memory, puts some holding pattern
+ * code there and sends the other processors off to there until
+ * smp_boot_cpus tells them to do something.  The holding pattern
+ * checks that address until its cpu # is there, when it is that
+ * cpu jumps to __secondary_start().  smp_boot_cpus() takes care
+ * of setting those values.
+ *
+ * We also use physical address 0x4 here to tell when a cpu
+ * is in its holding pattern code.
+ *
+ * Fixup comment... DRENG / PPPBBB - Peter
+ *
+ * -- Cort
+ */
+static void __init prom_hold_cpus(void)
+{
+       unsigned long i;
+       unsigned int reg;
+       phandle node;
+       unsigned long offset = reloc_offset();
+       char type[64];
+       int cpuid = 0;
+       unsigned int interrupt_server[MAX_CPU_THREADS];
+       unsigned int cpu_threads, hw_cpu_num;
+       int propsize;
+       extern void __secondary_hold(void);
+       extern unsigned long __secondary_hold_spinloop;
+       extern unsigned long __secondary_hold_acknowledge;
+       unsigned long *spinloop
+               = (void *)virt_to_abs(&__secondary_hold_spinloop);
+       unsigned long *acknowledge
+               = (void *)virt_to_abs(&__secondary_hold_acknowledge);
+       unsigned long secondary_hold
+               = virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold));
+       struct prom_t *_prom = PTRRELOC(&prom);
+
+       prom_debug("prom_hold_cpus: start...\n");
+       prom_debug("    1) spinloop       = 0x%x\n", (unsigned long)spinloop);
+       prom_debug("    1) *spinloop      = 0x%x\n", *spinloop);
+       prom_debug("    1) acknowledge    = 0x%x\n",
+                  (unsigned long)acknowledge);
+       prom_debug("    1) *acknowledge   = 0x%x\n", *acknowledge);
+       prom_debug("    1) secondary_hold = 0x%x\n", secondary_hold);
+
+       /* Set the common spinloop variable, so all of the secondary cpus
+        * will block when they are awakened from their OF spinloop.
+        * This must occur for both SMP and non SMP kernels, since OF will
+        * be trashed when we move the kernel.
+        */
+       *spinloop = 0;
+
+#ifdef CONFIG_HMT
+       for (i=0; i < NR_CPUS; i++) {
+               RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
+       }
+#endif
+       /* look for cpus */
+       for (node = 0; prom_next_node(&node); ) {
+               type[0] = 0;
+               prom_getprop(node, "device_type", type, sizeof(type));
+               if (strcmp(type, RELOC("cpu")) != 0)
+                       continue;
+
+               /* Skip non-configured cpus. */
+               prom_getprop(node, "status", type, sizeof(type));
+               if (strcmp(type, RELOC("okay")) != 0)
+                       continue;
+
+               reg = -1;
+               prom_getprop(node, "reg", &reg, sizeof(reg));
+
+               prom_debug("\ncpuid        = 0x%x\n", cpuid);
+               prom_debug("cpu hw idx   = 0x%x\n", reg);
+
+               /* Init the acknowledge var which will be reset by
+                * the secondary cpu when it awakens from its OF
+                * spinloop.
+                */
+               *acknowledge = (unsigned long)-1;
+
+               propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s",
+                                       &interrupt_server,
+                                       sizeof(interrupt_server));
+               if (propsize < 0) {
+                       /* no property.  old hardware has no SMT */
+                       cpu_threads = 1;
+                       interrupt_server[0] = reg; /* fake it with phys id */
+               } else {
+                       /* We have a threaded processor */
+                       cpu_threads = propsize / sizeof(u32);
+                       if (cpu_threads > MAX_CPU_THREADS) {
+                               prom_printf("SMT: too many threads!\n"
+                                           "SMT: found %x, max is %x\n",
+                                           cpu_threads, MAX_CPU_THREADS);
+                               cpu_threads = 1; /* ToDo: panic? */
+                       }
+               }
+
+               hw_cpu_num = interrupt_server[0];
+               if (hw_cpu_num != _prom->cpu) {
+                       /* Primary Thread of non-boot cpu */
+                       prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg);
+                       call_prom("start-cpu", 3, 0, node,
+                                 secondary_hold, cpuid);
+
+                       for ( i = 0 ; (i < 100000000) && 
+                             (*acknowledge == ((unsigned long)-1)); i++ ) ;
+
+                       if (*acknowledge == cpuid) {
+                               prom_printf("done\n");
+                               /* We have to get every CPU out of OF,
+                                * even if we never start it. */
+                               if (cpuid >= NR_CPUS)
+                                       goto next;
+                       } else {
+                               prom_printf("failed: %x\n", *acknowledge);
+                       }
+               }
+#ifdef CONFIG_SMP
+               else
+                       prom_printf("%x : boot cpu     %x\n", cpuid, reg);
+#endif
+next:
+#ifdef CONFIG_SMP
+               /* Init paca for secondary threads.   They start later. */
+               for (i=1; i < cpu_threads; i++) {
+                       cpuid++;
+                       if (cpuid >= NR_CPUS)
+                               continue;
+               }
+#endif /* CONFIG_SMP */
+               cpuid++;
+       }
+#ifdef CONFIG_HMT
+       /* Only enable HMT on processors that provide support. */
+       if (__is_processor(PV_PULSAR) || 
+           __is_processor(PV_ICESTAR) ||
+           __is_processor(PV_SSTAR)) {
+               prom_printf("    starting secondary threads\n");
+
+               for (i = 0; i < NR_CPUS; i += 2) {
+                       if (!cpu_online(i))
+                               continue;
+
+                       if (i == 0) {
+                               unsigned long pir = mfspr(SPRN_PIR);
+                               if (__is_processor(PV_PULSAR)) {
+                                       RELOC(hmt_thread_data)[i].pir = 
+                                               pir & 0x1f;
+                               } else {
+                                       RELOC(hmt_thread_data)[i].pir = 
+                                               pir & 0x3ff;
+                               }
+                       }
+               }
+       } else {
+               prom_printf("Processor is not HMT capable\n");
+       }
+#endif
+
+       if (cpuid > NR_CPUS)
+               prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS)
+                           ") exceeded: ignoring extras\n");
+
+       prom_debug("prom_hold_cpus: end...\n");
+}
+
+
+static void __init prom_init_client_services(unsigned long pp)
+{
+       unsigned long offset = reloc_offset();
+       struct prom_t *_prom = PTRRELOC(&prom);
+
+       /* Get a handle to the prom entry point before anything else */
+       _prom->entry = pp;
+
+       /* Init default value for phys size */
+       _prom->root_size_cells = 1;
+       _prom->root_addr_cells = 2;
+
+       /* get a handle for the stdout device */
+       _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
+       if ((long)_prom->chosen <= 0)
+               prom_panic("cannot find chosen"); /* msg won't be printed :( */
+
+       /* get device tree root */
+       _prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
+       if ((long)_prom->root <= 0)
+               prom_panic("cannot find device tree root"); /* msg won't be printed :( */
+}
+
+static void __init prom_init_stdout(void)
+{
+       unsigned long offset = reloc_offset();
+       struct prom_t *_prom = PTRRELOC(&prom);
+       char *path = RELOC(of_stdout_device);
+       char type[16];
+       u32 val;
+
+       if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0)
+               prom_panic("cannot find stdout");
+
+       _prom->stdout = val;
+
+       /* Get the full OF pathname of the stdout device */
+       memset(path, 0, 256);
+       call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255);
+       val = call_prom("instance-to-package", 1, 1, _prom->stdout);
+       prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val));
+       prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device));
+       prom_setprop(_prom->chosen, "linux,stdout-path",
+                    RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1);
+
+       /* If it's a display, note it */
+       memset(type, 0, sizeof(type));
+       prom_getprop(val, "device_type", type, sizeof(type));
+       if (strcmp(type, RELOC("display")) == 0) {
+               _prom->disp_node = val;
+               prom_setprop(val, "linux,boot-display", NULL, 0);
+       }
+}
+
+static int __init prom_find_machine_type(void)
+{
+       unsigned long offset = reloc_offset();
+       struct prom_t *_prom = PTRRELOC(&prom);
+       char compat[256];
+       int len, i = 0;
+       phandle rtas;
+
+       len = prom_getprop(_prom->root, "compatible",
+                          compat, sizeof(compat)-1);
+       if (len > 0) {
+               compat[len] = 0;
+               while (i < len) {
+                       char *p = &compat[i];
+                       int sl = strlen(p);
+                       if (sl == 0)
+                               break;
+                       if (strstr(p, RELOC("Power Macintosh")) ||
+                           strstr(p, RELOC("MacRISC4")))
+                               return PLATFORM_POWERMAC;
+                       i += sl + 1;
+               }
+       }
+       /* Default to pSeries. We need to know if we are running LPAR */
+       rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
+       if (rtas != (phandle) -1) {
+               unsigned long x;
+               x = prom_getproplen(rtas, "ibm,hypertas-functions");
+               if (x != PROM_ERROR) {
+                       prom_printf("Hypertas detected, assuming LPAR !\n");
+                       return PLATFORM_PSERIES_LPAR;
+               }
+       }
+       return PLATFORM_PSERIES;
+}
+
+static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
+{
+       unsigned long offset = reloc_offset();
+
+       return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
+}
+
+/*
+ * If we have a display that we don't know how to drive,
+ * we will want to try to execute OF's open method for it
+ * later.  However, OF will probably fall over if we do that
+ * we've taken over the MMU.
+ * So we check whether we will need to open the display,
+ * and if so, open it now.
+ */
+static unsigned long __init prom_check_displays(void)
+{
+       unsigned long offset = reloc_offset();
+       struct prom_t *_prom = PTRRELOC(&prom);
+       char type[16], *path;
+       phandle node;
+       ihandle ih;
+       int i;
+
+       static unsigned char default_colors[] = {
+               0x00, 0x00, 0x00,
+               0x00, 0x00, 0xaa,
+               0x00, 0xaa, 0x00,
+               0x00, 0xaa, 0xaa,
+               0xaa, 0x00, 0x00,
+               0xaa, 0x00, 0xaa,
+               0xaa, 0xaa, 0x00,
+               0xaa, 0xaa, 0xaa,
+               0x55, 0x55, 0x55,
+               0x55, 0x55, 0xff,
+               0x55, 0xff, 0x55,
+               0x55, 0xff, 0xff,
+               0xff, 0x55, 0x55,
+               0xff, 0x55, 0xff,
+               0xff, 0xff, 0x55,
+               0xff, 0xff, 0xff
+       };
+       const unsigned char *clut;
+
+       prom_printf("Looking for displays\n");
+       for (node = 0; prom_next_node(&node); ) {
+               memset(type, 0, sizeof(type));
+               prom_getprop(node, "device_type", type, sizeof(type));
+               if (strcmp(type, RELOC("display")) != 0)
+                       continue;
+
+               /* It seems OF doesn't null-terminate the path :-( */
+               path = RELOC(prom_scratch);
+               memset(path, 0, PROM_SCRATCH_SIZE);
+
+               /*
+                * leave some room at the end of the path for appending extra
+                * arguments
+                */
+               if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0)
+                       continue;
+               prom_printf("found display   : %s, opening ... ", path);
+               
+               ih = call_prom("open", 1, 1, path);
+               if (ih == (ihandle)0 || ih == (ihandle)-1) {
+                       prom_printf("failed\n");
+                       continue;
+               }
+
+               /* Success */
+               prom_printf("done\n");
+               prom_setprop(node, "linux,opened", NULL, 0);
+
+               /*
+                * stdout wasn't a display node, pick the first we can find
+                * for btext
+                */
+               if (_prom->disp_node == 0)
+                       _prom->disp_node = node;
+
+               /* Setup a useable color table when the appropriate
+                * method is available. Should update this to set-colors */
+               clut = RELOC(default_colors);
+               for (i = 0; i < 32; i++, clut += 3)
+                       if (prom_set_color(ih, i, clut[0], clut[1],
+                                          clut[2]) != 0)
+                               break;
+
+#ifdef CONFIG_LOGO_LINUX_CLUT224
+               clut = PTRRELOC(RELOC(logo_linux_clut224.clut));
+               for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3)
+                       if (prom_set_color(ih, i + 32, clut[0], clut[1],
+                                          clut[2]) != 0)
+                               break;
+#endif /* CONFIG_LOGO_LINUX_CLUT224 */
+       }
+}
+
+
+/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
+static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
+                             unsigned long needed, unsigned long align)
+{
+       unsigned long offset = reloc_offset();
+       void *ret;
+
+       *mem_start = _ALIGN(*mem_start, align);
+       while ((*mem_start + needed) > *mem_end) {
+               unsigned long room, chunk;
+
+               prom_debug("Chunk exhausted, claiming more at %x...\n",
+                          RELOC(alloc_bottom));
+               room = RELOC(alloc_top) - RELOC(alloc_bottom);
+               if (room > DEVTREE_CHUNK_SIZE)
+                       room = DEVTREE_CHUNK_SIZE;
+               if (room < PAGE_SIZE)
+                       prom_panic("No memory for flatten_device_tree (no room)");
+               chunk = alloc_up(room, 0);
+               if (chunk == 0)
+                       prom_panic("No memory for flatten_device_tree (claim failed)");
+               *mem_end = RELOC(alloc_top);
+       }
+
+       ret = (void *)*mem_start;
+       *mem_start += needed;
+
+       return ret;
+}
+
+#define dt_push_token(token, mem_start, mem_end) \
+       do { *((u32 *)make_room(mem_start, mem_end, 4, 4)) = token; } while(0)
+
+static unsigned long __init dt_find_string(char *str)
+{
+       unsigned long offset = reloc_offset();
+       char *s, *os;
+
+       s = os = (char *)RELOC(dt_string_start);
+       s += 4;
+       while (s <  (char *)RELOC(dt_string_end)) {
+               if (strcmp(s, str) == 0)
+                       return s - os;
+               s += strlen(s) + 1;
+       }
+       return 0;
+}
+
+static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
+                                        unsigned long *mem_end)
+{
+       unsigned long offset = reloc_offset();
+       char *prev_name, *namep, *sstart;
+       unsigned long soff;
+       phandle child;
+
+       sstart =  (char *)RELOC(dt_string_start);
+
+       /* get and store all property names */
+       prev_name = RELOC("");
+       for (;;) {
+               
+               /* 32 is max len of name including nul. */
+               namep = make_room(mem_start, mem_end, 32, 1);
+               if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) {
+                       /* No more nodes: unwind alloc */
+                       *mem_start = (unsigned long)namep;
+                       break;
+               }
+               soff = dt_find_string(namep);
+               if (soff != 0) {
+                       *mem_start = (unsigned long)namep;
+                       namep = sstart + soff;
+               } else {
+                       /* Trim off some if we can */
+                       *mem_start = (unsigned long)namep + strlen(namep) + 1;
+                       RELOC(dt_string_end) = *mem_start;
+               }
+               prev_name = namep;
+       }
+
+       /* do all our children */
+       child = call_prom("child", 1, 1, node);
+       while (child != (phandle)0) {
+               scan_dt_build_strings(child, mem_start, mem_end);
+               child = call_prom("peer", 1, 1, child);
+       }
+}
+
+static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
+                                       unsigned long *mem_end)
+{
+       int l, align;
+       phandle child;
+       char *namep, *prev_name, *sstart;
+       unsigned long soff;
+       unsigned char *valp;
+       unsigned long offset = reloc_offset();
+       char pname[32];
+       char *path;
+
+       path = RELOC(prom_scratch);
+
+       dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
+
+       /* get the node's full name */
+       namep = (char *)*mem_start;
+       l = call_prom("package-to-path", 3, 1, node,
+                     namep, *mem_end - *mem_start);
+       if (l >= 0) {
+               /* Didn't fit?  Get more room. */
+               if (l+1 > *mem_end - *mem_start) {
+                       namep = make_room(mem_start, mem_end, l+1, 1);
+                       call_prom("package-to-path", 3, 1, node, namep, l);
+               }
+               namep[l] = '\0';
+               *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
+       }
+
+       /* get it again for debugging */
+       memset(path, 0, PROM_SCRATCH_SIZE);
+       call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
+
+       /* get and store all properties */
+       prev_name = RELOC("");
+       sstart = (char *)RELOC(dt_string_start);
+       for (;;) {
+               if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0)
+                       break;
+
+               /* find string offset */
+               soff = dt_find_string(pname);
+               if (soff == 0) {
+                       prom_printf("WARNING: Can't find string index for <%s>, node %s\n",
+                                   pname, path);
+                       break;
+               }
+               prev_name = sstart + soff;
+
+               /* get length */
+               l = call_prom("getproplen", 2, 1, node, pname);
+
+               /* sanity checks */
+               if (l < 0)
+                       continue;
+               if (l > MAX_PROPERTY_LENGTH) {
+                       prom_printf("WARNING: ignoring large property ");
+                       /* It seems OF doesn't null-terminate the path :-( */
+                       prom_printf("[%s] ", path);
+                       prom_printf("%s length 0x%x\n", pname, l);
+                       continue;
+               }
+
+               /* push property head */
+               dt_push_token(OF_DT_PROP, mem_start, mem_end);
+               dt_push_token(l, mem_start, mem_end);
+               dt_push_token(soff, mem_start, mem_end);
+
+               /* push property content */
+               align = (l >= 8) ? 8 : 4;
+               valp = make_room(mem_start, mem_end, l, align);
+               call_prom("getprop", 4, 1, node, pname, valp, l);
+               *mem_start = _ALIGN(*mem_start, 4);
+       }
+
+       /* Add a "linux,phandle" property. */
+       soff = dt_find_string(RELOC("linux,phandle"));
+       if (soff == 0)
+               prom_printf("WARNING: Can't find string index for <linux-phandle>"
+                           " node %s\n", path);
+       else {
+               dt_push_token(OF_DT_PROP, mem_start, mem_end);
+               dt_push_token(4, mem_start, mem_end);
+               dt_push_token(soff, mem_start, mem_end);
+               valp = make_room(mem_start, mem_end, 4, 4);
+               *(u32 *)valp = node;
+       }
+
+       /* do all our children */
+       child = call_prom("child", 1, 1, node);
+       while (child != (phandle)0) {
+               scan_dt_build_struct(child, mem_start, mem_end);
+               child = call_prom("peer", 1, 1, child);
+       }
+
+       dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
+}
+
+static void __init flatten_device_tree(void)
+{
+       phandle root;
+       unsigned long offset = reloc_offset();
+       unsigned long mem_start, mem_end, room;
+       struct boot_param_header *hdr;
+       char *namep;
+       u64 *rsvmap;
+
+       /*
+        * Check how much room we have between alloc top & bottom (+/- a
+        * few pages), crop to 4Mb, as this is our "chuck" size
+        */
+       room = RELOC(alloc_top) - RELOC(alloc_bottom) - 0x4000;
+       if (room > DEVTREE_CHUNK_SIZE)
+               room = DEVTREE_CHUNK_SIZE;
+       prom_debug("starting device tree allocs at %x\n", RELOC(alloc_bottom));
+
+       /* Now try to claim that */
+       mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
+       if (mem_start == 0)
+               prom_panic("Can't allocate initial device-tree chunk\n");
+       mem_end = RELOC(alloc_top);
+
+       /* Get root of tree */
+       root = call_prom("peer", 1, 1, (phandle)0);
+       if (root == (phandle)0)
+               prom_panic ("couldn't get device tree root\n");
+
+       /* Build header and make room for mem rsv map */ 
+       mem_start = _ALIGN(mem_start, 4);
+       hdr = make_room(&mem_start, &mem_end, sizeof(struct boot_param_header), 4);
+       RELOC(dt_header_start) = (unsigned long)hdr;
+       rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
+
+       /* Start of strings */
+       mem_start = PAGE_ALIGN(mem_start);
+       RELOC(dt_string_start) = mem_start;
+       mem_start += 4; /* hole */
+
+       /* Add "linux,phandle" in there, we'll need it */
+       namep = make_room(&mem_start, &mem_end, 16, 1);
+       strcpy(namep, RELOC("linux,phandle"));
+       mem_start = (unsigned long)namep + strlen(namep) + 1;
+       RELOC(dt_string_end) = mem_start;
+
+       /* Build string array */
+       prom_printf("Building dt strings...\n"); 
+       scan_dt_build_strings(root, &mem_start, &mem_end);
+
+       /* Build structure */
+       mem_start = PAGE_ALIGN(mem_start);
+       RELOC(dt_struct_start) = mem_start;
+       prom_printf("Building dt structure...\n"); 
+       scan_dt_build_struct(root, &mem_start, &mem_end);
+       dt_push_token(OF_DT_END, &mem_start, &mem_end);
+       RELOC(dt_struct_end) = PAGE_ALIGN(mem_start);
+
+       /* Finish header */
+       hdr->magic = OF_DT_HEADER;
+       hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
+       hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
+       hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);
+       hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);
+       hdr->version = OF_DT_VERSION;
+       hdr->last_comp_version = 1;
+
+       /* Reserve the whole thing and copy the reserve map in, we
+        * also bump mem_reserve_cnt to cause further reservations to
+        * fail since it's too late.
+        */
+       reserve_mem(RELOC(dt_header_start), hdr->totalsize);
+       memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map));
+
+#ifdef DEBUG_PROM
+       {
+               int i;
+               prom_printf("reserved memory map:\n");
+               for (i = 0; i < RELOC(mem_reserve_cnt); i++)
+                       prom_printf("  %x - %x\n", RELOC(mem_reserve_map)[i].base,
+                                   RELOC(mem_reserve_map)[i].size);
+       }
+#endif
+       RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE;
+
+       prom_printf("Device tree strings 0x%x -> 0x%x\n",
+                   RELOC(dt_string_start), RELOC(dt_string_end)); 
+       prom_printf("Device tree struct  0x%x -> 0x%x\n",
+                   RELOC(dt_struct_start), RELOC(dt_struct_end));
+
+ }
+
+static void __init prom_find_boot_cpu(void)
+{
+       unsigned long offset = reloc_offset();
+               struct prom_t *_prom = PTRRELOC(&prom);
+       u32 getprop_rval;
+       ihandle prom_cpu;
+       phandle cpu_pkg;
+
+       if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0)
+               prom_panic("cannot find boot cpu");
+
+       cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
+
+       prom_setprop(cpu_pkg, "linux,boot-cpu", NULL, 0);
+       prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));
+       _prom->cpu = getprop_rval;
+
+       prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);
+}
+
+static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+       unsigned long offset = reloc_offset();
+               struct prom_t *_prom = PTRRELOC(&prom);
+
+       if ( r3 && r4 && r4 != 0xdeadbeef) {
+               u64 val;
+
+               RELOC(prom_initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
+               RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
+
+               val = (u64)RELOC(prom_initrd_start);
+               prom_setprop(_prom->chosen, "linux,initrd-start", &val, sizeof(val));
+               val = (u64)RELOC(prom_initrd_end);
+               prom_setprop(_prom->chosen, "linux,initrd-end", &val, sizeof(val));
+
+               reserve_mem(RELOC(prom_initrd_start),
+                           RELOC(prom_initrd_end) - RELOC(prom_initrd_start));
+
+               prom_debug("initrd_start=0x%x\n", RELOC(prom_initrd_start));
+               prom_debug("initrd_end=0x%x\n", RELOC(prom_initrd_end));
+       }
+#endif /* CONFIG_BLK_DEV_INITRD */
+}
+
+/*
+ * We enter here early on, when the Open Firmware prom is still
+ * handling exceptions and the MMU hash table for us.
+ */
+
+unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
+                              unsigned long r6, unsigned long r7)
+{      
+       unsigned long offset = reloc_offset();
+               struct prom_t *_prom = PTRRELOC(&prom);
+       unsigned long phys = KERNELBASE - offset;
+       u32 getprop_rval;
+       
+       /*
+        * First zero the BSS
+        */
+       memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start);
+
+       /*
+        * Init interface to Open Firmware, get some node references,
+        * like /chosen
+        */
+       prom_init_client_services(pp);
+
+       /*
+        * Init prom stdout device
+        */
+       prom_init_stdout();
+       prom_debug("klimit=0x%x\n", RELOC(klimit));
+       prom_debug("offset=0x%x\n", offset);
+
+       /*
+        * Reserve kernel in reserve map
+        */
+       reserve_mem(0, __pa(RELOC(klimit)));
+
+       /*
+        * Check for an initrd
+        */
+       prom_check_initrd(r3, r4);
+
+       /*
+        * Get default machine type. At this point, we do not differenciate
+        * between pSeries SMP and pSeries LPAR
+        */
+       RELOC(of_platform) = prom_find_machine_type();
+       getprop_rval = RELOC(of_platform);
+       prom_setprop(_prom->chosen, "linux,platform",
+                    &getprop_rval, sizeof(getprop_rval));
+
+       /*
+        * On pSeries, copy the CPU hold code
+        */
+               if (RELOC(of_platform) & PLATFORM_PSERIES)
+                       copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
+
+       /*
+        * Get memory cells format
+        */
+       getprop_rval = 1;
+       prom_getprop(_prom->root, "#size-cells",
+                    &getprop_rval, sizeof(getprop_rval));
+       _prom->root_size_cells = getprop_rval;
+       getprop_rval = 2;
+       prom_getprop(_prom->root, "#address-cells",
+                    &getprop_rval, sizeof(getprop_rval));
+       _prom->root_addr_cells = getprop_rval;
+
+       /*
+        * Do early parsing of command line
+        */
+       early_cmdline_parse();
+
+       /*
+        * Initialize memory management within prom_init
+        */
+       prom_init_mem();
+
+       /*
+        * Determine which cpu is actually running right _now_
+        */
+       prom_find_boot_cpu();
+
+       /* 
+        * Initialize display devices
+        */
+       prom_check_displays();
+
+       /*
+        * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
+        * that uses the allocator, we need to make sure we get the top of memory
+        * available for us here...
+        */
+       if (RELOC(of_platform) == PLATFORM_PSERIES)
+               prom_initialize_tce_table();
+
+       /*
+        * On non-powermacs, try to instantiate RTAS and puts all CPUs
+        * in spin-loops. PowerMacs don't have a working RTAS and use
+        * a different way to spin CPUs
+        */
+       if (RELOC(of_platform) != PLATFORM_POWERMAC) {
+               prom_instantiate_rtas();
+               prom_hold_cpus();
+       }
+
+       /*
+        * Fill in some infos for use by the kernel later on
+        */
+       if (RELOC(ppc64_iommu_off))
+               prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0);
+       if (RELOC(iommu_force_on))
+               prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0);
+
+       /*
+        * Now finally create the flattened device-tree
+        */
+               prom_printf("copying OF device tree ...\n");
+               flatten_device_tree();
+
+       /*
+        * Call OF "quiesce" method to shut down pending DMA's from
+        * devices etc...
+        */
+       prom_printf("Calling quiesce ...\n");
+       call_prom("quiesce", 0, 0);
+
+       /*
+        * And finally, call the kernel passing it the flattened device
+        * tree and NULL as r5, thus triggering the new entry point which
+        * is common to us and kexec
+        */
+       prom_printf("returning from prom_init\n");
+       prom_debug("->dt_header_start=0x%x\n", RELOC(dt_header_start));
+       prom_debug("->phys=0x%x\n", phys);
+
+       __start(RELOC(dt_header_start), phys, 0);
+
+       return 0;
+}
+
diff --git a/arch/ppc64/kernel/u3_iommu.c b/arch/ppc64/kernel/u3_iommu.c
new file mode 100644 (file)
index 0000000..2bb0b39
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * arch/ppc64/kernel/u3_iommu.c
+ *
+ * Copyright (C) 2004 Olof Johansson <olof@austin.ibm.com>, IBM Corporation
+ *
+ * Based on pSeries_iommu.c:
+ * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
+ * Copyright (C) 2004 Olof Johansson <olof@austin.ibm.com>, IBM Corporation
+ *
+ * Dynamic DMA mapping support, Apple U3 & IBM CPC925 "DART" iommu.
+ *
+ * 
+ * This program is free software; you can redistribute 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/config.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/ppcdebug.h>
+#include <asm/iommu.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/abs_addr.h>
+#include <asm/cacheflush.h>
+#include <asm/lmb.h>
+
+#include "pci.h"
+
+extern int iommu_force_on;
+
+/* physical base of DART registers */
+#define DART_BASE        0xf8033000UL
+
+/* Offset from base to control register */
+#define DARTCNTL   0
+/* Offset from base to exception register */
+#define DARTEXCP   0x10
+/* Offset from base to TLB tag registers */
+#define DARTTAG    0x1000
+
+
+/* Control Register fields */
+
+/* base address of table (pfn) */
+#define DARTCNTL_BASE_MASK    0xfffff
+#define DARTCNTL_BASE_SHIFT   12
+
+#define DARTCNTL_FLUSHTLB     0x400
+#define DARTCNTL_ENABLE       0x200
+
+/* size of table in pages */
+#define DARTCNTL_SIZE_MASK    0x1ff
+#define DARTCNTL_SIZE_SHIFT   0
+
+/* DART table fields */
+#define DARTMAP_VALID   0x80000000
+#define DARTMAP_RPNMASK 0x00ffffff
+
+/* Physical base address and size of the DART table */
+unsigned long dart_tablebase; /* exported to htab_initialize */
+static unsigned long dart_tablesize;
+
+/* Virtual base address of the DART table */
+static u32 *dart_vbase;
+
+/* Mapped base address for the dart */
+static unsigned int *dart; 
+
+/* Dummy val that entries are set to when unused */
+static unsigned int dart_emptyval;
+
+static struct iommu_table iommu_table_u3;
+static int dart_dirty;
+
+#define DBG(...)
+
+static inline void dart_tlb_invalidate_all(void)
+{
+       unsigned long l = 0;
+       unsigned int reg;
+       unsigned long limit;
+
+       DBG("dart: flush\n");
+
+       /* To invalidate the DART, set the DARTCNTL_FLUSHTLB bit in the
+        * control register and wait for it to clear.
+        *
+        * Gotcha: Sometimes, the DART won't detect that the bit gets
+        * set. If so, clear it and set it again.
+        */ 
+
+       limit = 0;
+
+retry:
+       reg = in_be32((unsigned int *)dart+DARTCNTL);
+       reg |= DARTCNTL_FLUSHTLB;
+       out_be32((unsigned int *)dart+DARTCNTL, reg);
+
+       l = 0;
+       while ((in_be32((unsigned int *)dart+DARTCNTL) & DARTCNTL_FLUSHTLB) &&
+               l < (1L<<limit)) {
+               l++;
+       }
+       if (l == (1L<<limit)) {
+               if (limit < 4) {
+                       limit++;
+                       reg = in_be32((unsigned int *)dart+DARTCNTL);
+                       reg &= ~DARTCNTL_FLUSHTLB;
+                       out_be32((unsigned int *)dart+DARTCNTL, reg);
+                       goto retry;
+               } else
+                       panic("U3-DART: TLB did not flush after waiting a long "
+                             "time. Buggy U3 ?");
+       }
+}
+
+static void dart_flush(struct iommu_table *tbl)
+{
+       if (dart_dirty)
+               dart_tlb_invalidate_all();
+       dart_dirty = 0;
+}
+
+static void dart_build(struct iommu_table *tbl, long index, 
+                      long npages, unsigned long uaddr,
+                      enum dma_data_direction direction)
+{
+       unsigned int *dp;
+       unsigned int rpn;
+
+       DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
+
+       dp = ((unsigned int*)tbl->it_base) + index;
+       
+       /* On U3, all memory is contigous, so we can move this
+        * out of the loop.
+        */
+       while (npages--) {
+               rpn = virt_to_abs(uaddr) >> PAGE_SHIFT;
+
+               *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
+
+               rpn++;
+               uaddr += PAGE_SIZE;
+       }
+
+       dart_dirty = 1;
+}
+
+
+static void dart_free(struct iommu_table *tbl, long index, long npages)
+{
+       unsigned int *dp;
+       
+       /* We don't worry about flushing the TLB cache. The only drawback of
+        * not doing it is that we won't catch buggy device drivers doing
+        * bad DMAs, but then no 32-bit architecture ever does either.
+        */
+
+       DBG("dart: free at: %lx, %lx\n", index, npages);
+
+       dp  = ((unsigned int *)tbl->it_base) + index;
+               
+       while (npages--)
+               *(dp++) = dart_emptyval;
+}
+
+
+static int dart_init(struct device_node *dart_node)
+{
+       unsigned int regword;
+       unsigned int i;
+       unsigned long tmp;
+       struct page *p;
+
+       if (dart_tablebase == 0 || dart_tablesize == 0) {
+               printk(KERN_INFO "U3-DART: table not allocated, using direct DMA\n");
+               return -ENODEV;
+       }
+
+       /* Make sure nothing from the DART range remains in the CPU cache
+        * from a previous mapping that existed before the kernel took
+        * over
+        */
+       flush_dcache_phys_range(dart_tablebase, dart_tablebase + dart_tablesize);
+
+       /* Allocate a spare page to map all invalid DART pages. We need to do
+        * that to work around what looks like a problem with the HT bridge
+        * prefetching into invalid pages and corrupting data
+        */
+       tmp = __get_free_pages(GFP_ATOMIC, 1);
+       if (tmp == 0)
+               panic("U3-DART: Cannot allocate spare page !");
+       dart_emptyval = DARTMAP_VALID |
+               ((virt_to_abs(tmp) >> PAGE_SHIFT) & DARTMAP_RPNMASK);
+
+       /* Map in DART registers. FIXME: Use device node to get base address */
+       dart = ioremap(DART_BASE, 0x7000);
+       if (dart == NULL)
+               panic("U3-DART: Cannot map registers !");
+
+       /* Set initial control register contents: table base, 
+        * table size and enable bit
+        */
+       regword = DARTCNTL_ENABLE | 
+               ((dart_tablebase >> PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) |
+               (((dart_tablesize >> PAGE_SHIFT) & DARTCNTL_SIZE_MASK)
+                                << DARTCNTL_SIZE_SHIFT);
+       p = virt_to_page(dart_tablebase);
+       dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
+
+       /* Fill initial table */
+       for (i = 0; i < dart_tablesize/4; i++)
+               dart_vbase[i] = dart_emptyval;
+
+       /* Initialize DART with table base and enable it. */
+       out_be32((unsigned int *)dart, regword);
+
+       /* Invalidate DART to get rid of possible stale TLBs */
+       dart_tlb_invalidate_all();
+
+       iommu_table_u3.it_busno = 0;
+       
+       /* Units of tce entries */
+       iommu_table_u3.it_offset = 0;
+       
+       /* Set the tce table size - measured in pages */
+       iommu_table_u3.it_size = dart_tablesize >> PAGE_SHIFT;
+
+       /* Initialize the common IOMMU code */
+       iommu_table_u3.it_base = (unsigned long)dart_vbase;
+       iommu_table_u3.it_index = 0;
+       iommu_table_u3.it_blocksize = 1;
+       iommu_table_u3.it_entrysize = sizeof(u32);
+       iommu_init_table(&iommu_table_u3);
+
+       /* Reserve the last page of the DART to avoid possible prefetch
+        * past the DART mapped area
+        */
+       set_bit(iommu_table_u3.it_mapsize - 1, iommu_table_u3.it_map);
+
+       printk(KERN_INFO "U3/CPC925 DART IOMMU initialized\n");
+
+       return 0;
+}
+
+void iommu_setup_u3(void)
+{
+       struct pci_dev *dev = NULL;
+       struct device_node *dn;
+
+       /* Find the DART in the device-tree */
+       dn = of_find_compatible_node(NULL, "dart", "u3-dart");
+       if (dn == NULL)
+               return;
+
+       /* Setup low level TCE operations for the core IOMMU code */
+       ppc_md.tce_build = dart_build;
+       ppc_md.tce_free  = dart_free;
+       ppc_md.tce_flush = dart_flush;
+
+       /* Initialize the DART HW */
+       if (dart_init(dn))
+               return;
+
+       /* Setup pci_dma ops */
+       pci_iommu_init();
+
+       /* We only have one iommu table on the mac for now, which makes
+        * things simple. Setup all PCI devices to point to this table
+        */
+       while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+               /* We must use pci_device_to_OF_node() to make sure that
+                * we get the real "final" pointer to the device in the
+                * pci_dev sysdata and not the temporary PHB one
+                */
+               struct device_node *dn = pci_device_to_OF_node(dev);
+               if (dn)
+                       dn->iommu_table = &iommu_table_u3;
+       }
+}
+
+void __init alloc_u3_dart_table(void)
+{
+       /* Only reserve DART space if machine has more than 2GB of RAM
+        * or if requested with iommu=on on cmdline.
+        */
+       if (lmb_end_of_DRAM() <= 0x80000000ull && !iommu_force_on)
+               return;
+
+       /* 512 pages (2MB) is max DART tablesize. */
+       dart_tablesize = 1UL << 21;
+       /* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we
+        * will blow up an entire large page anyway in the kernel mapping
+        */
+       dart_tablebase = (unsigned long)
+               abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
+
+       printk(KERN_INFO "U3-DART allocated at: %lx\n", dart_tablebase);
+}
index 940cd72..b79d33e 100644 (file)
@@ -89,7 +89,7 @@ _GLOBAL(vmaddfp)
 1:     lfsx    fr0,r4,r7
        lfsx    fr1,r5,r7
        lfsx    fr2,r6,r7
-       fmadds  fr0,fr0,fr1,fr2
+       fmadds  fr0,fr0,fr2,fr1
        stfsx   fr0,r3,r7
        addi    r7,r7,4
        bdnz    1b
@@ -109,7 +109,7 @@ _GLOBAL(vnmsubfp)
 1:     lfsx    fr0,r4,r7
        lfsx    fr1,r5,r7
        lfsx    fr2,r6,r7
-       fnmsubs fr0,fr0,fr1,fr2
+       fnmsubs fr0,fr0,fr2,fr1
        stfsx   fr0,r3,r7
        addi    r7,r7,4
        bdnz    1b
index 1d9b611..4103cc1 100644 (file)
@@ -14,6 +14,7 @@ SECTIONS
   .text : {
        *(.text .text.*)
        SCHED_TEXT
+       LOCK_TEXT
        *(.fixup)
        . = ALIGN(4096);
        _etext = .;
@@ -61,12 +62,6 @@ SECTIONS
        __setup_end = .;
        }
 
-  __param : {
-       __start___param = .;
-       *(__param)
-       __stop___param = .;
-       }
-
   .initcall.init : {
        __initcall_start = .;
        *(.initcall1.init)
@@ -122,10 +117,13 @@ SECTIONS
 
   .data : {
        *(.data .data.rel* .toc1)
-       *(.opd)
        *(.branch_lt)
        }
 
+  .opd : {
+       *(.opd)
+       }
+
   .got : {
        __toc_start = .;
        *(.got)
index 4ac6a63..ef96c6c 100644 (file)
@@ -92,19 +92,19 @@ _GLOBAL(csum_partial)
         adde    r5,r5,r6
         bdnz    2b
         andi.  r4,r4,7         /* compute bytes left to sum after doublewords */
-3:     cmp   0,r4,4          /* is at least a full word left? */
+3:     cmpwi   0,r4,4          /* is at least a full word left? */
        blt     4f
        lwz     r6,8(r3)        /* sum this word */
        addi    r3,r3,4
        subi    r4,r4,4
        adde    r5,r5,r6
-4:      cmpi    0,r4,2         /* is at least a halfword left? */
+4:     cmpwi   0,r4,2          /* is at least a halfword left? */
         blt+   5f
         lhz     r6,8(r3)        /* sum this halfword */
         addi    r3,r3,2
         subi    r4,r4,2
         adde    r5,r5,r6
-5:      cmpi    0,r4,1         /* is at least a byte left? */
+5:     cmpwi   0,r4,1          /* is at least a byte left? */
         bne+    6f
         lbz     r6,8(r3)        /* sum this byte */
         slwi    r6,r6,8         /* this byte is assumed to be the upper byte of a halfword */
@@ -150,7 +150,7 @@ _GLOBAL(csum_partial_copy_generic)
        adde    r0,r0,r6
        bdnz    82b
        andi.   r5,r5,3
-3:     cmp   0,r5,2
+3:     cmpwi   0,r5,2
        blt+    4f
 83:    lhz     r6,4(r3)
        addi    r3,r3,2
@@ -158,7 +158,7 @@ _GLOBAL(csum_partial_copy_generic)
 93:    sth     r6,4(r4)
        addi    r4,r4,2
        adde    r0,r0,r6
-4:     cmp   0,r5,1
+4:     cmpwi   0,r5,1
        bne+    5f
 84:    lbz     r6,4(r3)
 94:    stb     r6,4(r4)
@@ -198,7 +198,7 @@ src_error_3:
        bdnz    97b
        .globl src_error
 src_error:
-       cmp   0,r7,0
+       cmpdi   0,r7,0
        beq     1f
        li      r6,-EFAULT
        stw     r6,0(r7)
@@ -207,7 +207,7 @@ src_error:
 
        .globl dst_error
 dst_error:
-       cmp   0,r8,0
+       cmpdi   0,r8,0
        beq     1f
        li      r6,-EFAULT
        stw     r6,0(r8)
index 58e973c..72d642d 100644 (file)
 #include <asm/hvcall.h>
 #include <asm/iSeries/HvCall.h>
 
-#ifndef CONFIG_SPINLINE
-
-/*
- * On a system with shared processors (that is, where a physical
- * processor is multiplexed between several virtual processors),
- * there is no point spinning on a lock if the holder of the lock
- * isn't currently scheduled on a physical processor.  Instead
- * we detect this situation and ask the hypervisor to give the
- * rest of our timeslice to the lock holder.
- *
- * So that we can tell which virtual processor is holding a lock,
- * we put 0x80000000 | smp_processor_id() in the lock when it is
- * held.  Conveniently, we have a word in the paca that holds this
- * value.
- */
-
 /* waiting for a spinlock... */
 #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
 
-/* We only yield to the hypervisor if we are in shared processor mode */
-#define SHARED_PROCESSOR (get_paca()->lppaca.xSharedProc)
-
 void __spin_yield(spinlock_t *lock)
 {
        unsigned int lock_value, holder_cpu, yield_count;
@@ -63,100 +44,16 @@ void __spin_yield(spinlock_t *lock)
        HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
                ((u64)holder_cpu << 32) | yield_count);
 #else
-       plpar_hcall_norets(H_CONFER, holder_cpu, yield_count);
+       plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
+                          yield_count);
 #endif
 }
 
-#else /* SPLPAR || ISERIES */
-#define __spin_yield(x)        barrier()
-#define SHARED_PROCESSOR       0
-#endif
-
-/*
- * This returns the old value in the lock, so we succeeded
- * in getting the lock if the return value is 0.
- */
-static __inline__ unsigned long __spin_trylock(spinlock_t *lock)
-{
-       unsigned long tmp, tmp2;
-
-       __asm__ __volatile__(
-"      lwz             %1,%3(13)               # __spin_trylock\n\
-1:     lwarx           %0,0,%2\n\
-       cmpwi           0,%0,0\n\
-       bne-            2f\n\
-       stwcx.          %1,0,%2\n\
-       bne-            1b\n\
-       isync\n\
-2:"    : "=&r" (tmp), "=&r" (tmp2)
-       : "r" (&lock->lock), "i" (offsetof(struct paca_struct, lock_token))
-       : "cr0", "memory");
-
-       return tmp;
-}
-
-int _raw_spin_trylock(spinlock_t *lock)
-{
-       return __spin_trylock(lock) == 0;
-}
-
-EXPORT_SYMBOL(_raw_spin_trylock);
-
-void _raw_spin_lock(spinlock_t *lock)
-{
-       while (1) {
-               if (likely(__spin_trylock(lock) == 0))
-                       break;
-               do {
-                       HMT_low();
-                       if (SHARED_PROCESSOR)
-                               __spin_yield(lock);
-               } while (likely(lock->lock != 0));
-               HMT_medium();
-       }
-}
-
-EXPORT_SYMBOL(_raw_spin_lock);
-
-void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
-{
-       unsigned long flags_dis;
-
-       while (1) {
-               if (likely(__spin_trylock(lock) == 0))
-                       break;
-               local_save_flags(flags_dis);
-               local_irq_restore(flags);
-               do {
-                       HMT_low();
-                       if (SHARED_PROCESSOR)
-                               __spin_yield(lock);
-               } while (likely(lock->lock != 0));
-               HMT_medium();
-               local_irq_restore(flags_dis);
-       }
-}
-
-EXPORT_SYMBOL(_raw_spin_lock_flags);
-
-void spin_unlock_wait(spinlock_t *lock)
-{
-       while (lock->lock) {
-               HMT_low();
-               if (SHARED_PROCESSOR)
-                       __spin_yield(lock);
-       }
-       HMT_medium();
-}
-
-EXPORT_SYMBOL(spin_unlock_wait);
-
 /*
  * Waiting for a read lock or a write lock on a rwlock...
  * This turns out to be the same for read and write locks, since
  * we only know the holder if it is write-locked.
  */
-#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
 void __rw_yield(rwlock_t *rw)
 {
        int lock_value;
@@ -179,121 +76,20 @@ void __rw_yield(rwlock_t *rw)
        HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
                ((u64)holder_cpu << 32) | yield_count);
 #else
-       plpar_hcall_norets(H_CONFER, holder_cpu, yield_count);
+       plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
+                          yield_count);
 #endif
 }
-
-#else /* SPLPAR || ISERIES */
-#define __rw_yield(x)  barrier()
 #endif
 
-/*
- * This returns the old value in the lock + 1,
- * so we got a read lock if the return value is > 0.
- */
-static __inline__ long __read_trylock(rwlock_t *rw)
-{
-       long tmp;
-
-       __asm__ __volatile__(
-"1:    lwarx           %0,0,%1         # read_trylock\n\
-       extsw           %0,%0\n\
-       addic.          %0,%0,1\n\
-       ble-            2f\n\
-       stwcx.          %0,0,%1\n\
-       bne-            1b\n\
-       isync\n\
-2:"    : "=&r" (tmp)
-       : "r" (&rw->lock)
-       : "cr0", "xer", "memory");
-
-       return tmp;
-}
-
-int _raw_read_trylock(rwlock_t *rw)
-{
-       return __read_trylock(rw) > 0;
-}
-
-EXPORT_SYMBOL(_raw_read_trylock);
-
-void _raw_read_lock(rwlock_t *rw)
-{
-       while (1) {
-               if (likely(__read_trylock(rw) > 0))
-                       break;
-               do {
-                       HMT_low();
-                       if (SHARED_PROCESSOR)
-                               __rw_yield(rw);
-               } while (likely(rw->lock < 0));
-               HMT_medium();
-       }
-}
-
-EXPORT_SYMBOL(_raw_read_lock);
-
-void _raw_read_unlock(rwlock_t *rw)
-{
-       long tmp;
-
-       __asm__ __volatile__(
-       "eieio                          # read_unlock\n\
-1:     lwarx           %0,0,%1\n\
-       addic           %0,%0,-1\n\
-       stwcx.          %0,0,%1\n\
-       bne-            1b"
-       : "=&r"(tmp)
-       : "r"(&rw->lock)
-       : "cr0", "memory");
-}
-
-EXPORT_SYMBOL(_raw_read_unlock);
-
-/*
- * This returns the old value in the lock,
- * so we got the write lock if the return value is 0.
- */
-static __inline__ long __write_trylock(rwlock_t *rw)
-{
-       long tmp, tmp2;
-
-       __asm__ __volatile__(
-"      lwz             %1,%3(13)       # write_trylock\n\
-1:     lwarx           %0,0,%2\n\
-       cmpwi           0,%0,0\n\
-       bne-            2f\n\
-       stwcx.          %1,0,%2\n\
-       bne-            1b\n\
-       isync\n\
-2:"    : "=&r" (tmp), "=&r" (tmp2)
-       : "r" (&rw->lock), "i" (offsetof(struct paca_struct, lock_token))
-       : "cr0", "memory");
-
-       return tmp;
-}
-
-int _raw_write_trylock(rwlock_t *rw)
-{
-       return __write_trylock(rw) == 0;
-}
-
-EXPORT_SYMBOL(_raw_write_trylock);
-
-void _raw_write_lock(rwlock_t *rw)
+void spin_unlock_wait(spinlock_t *lock)
 {
-       while (1) {
-               if (likely(__write_trylock(rw) == 0))
-                       break;
-               do {
-                       HMT_low();
-                       if (SHARED_PROCESSOR)
-                               __rw_yield(rw);
-               } while (likely(rw->lock != 0));
-               HMT_medium();
+       while (lock->lock) {
+               HMT_low();
+               if (SHARED_PROCESSOR)
+                       __spin_yield(lock);
        }
+       HMT_medium();
 }
 
-EXPORT_SYMBOL(_raw_write_lock);
-
-#endif /* CONFIG_SPINLINE */
+EXPORT_SYMBOL(spin_unlock_wait);
index 0d6b5c2..68dd4b9 100644 (file)
@@ -172,9 +172,9 @@ htab_insert_pte:
        li      r9,0
 _GLOBAL(htab_call_hpte_insert1)
        bl      .                       /* Will be patched by htab_finish_init() */
-       cmp   0,r3,0
+       cmpdi   0,r3,0
        bge     htab_pte_insert_ok      /* Insertion successful */
-       cmp   0,r3,-2                 /* Critical failure */
+       cmpdi   0,r3,-2                 /* Critical failure */
        beq-    htab_pte_insert_failure
 
        /* Now try secondary slot */
@@ -194,9 +194,9 @@ _GLOBAL(htab_call_hpte_insert1)
        li      r9,0
 _GLOBAL(htab_call_hpte_insert2)
        bl      .                       /* Will be patched by htab_finish_init() */
-       cmp   0,r3,0
+       cmpdi   0,r3,0
        bge+    htab_pte_insert_ok      /* Insertion successful */
-       cmp   0,r3,-2                 /* Critical failure */
+       cmpdi   0,r3,-2                 /* Critical failure */
        beq-    htab_pte_insert_failure
 
        /* Both are full, we need to evict something */
@@ -263,7 +263,7 @@ _GLOBAL(htab_call_hpte_updatepp)
        /* if we failed because typically the HPTE wasn't really here
         * we try an insertion. 
         */
-       cmp   0,r3,-1
+       cmpdi   0,r3,-1
        beq-    htab_insert_pte
 
        /* Clear the BUSY bit and Write out the PTE */
@@ -278,6 +278,10 @@ htab_wrong_access:
        b       bail
 
 htab_pte_insert_failure:
-       b       .htab_insert_failure
+       /* Bail out restoring old PTE */
+       ld      r6,STK_PARM(r6)(r1)
+       std     r31,0(r6)
+       li      r3,-1
+       b       bail
 
 
diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
new file mode 100644 (file)
index 0000000..0d8c8ab
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * native hashtable management.
+ *
+ * SMP scalability work:
+ *    Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
+ * 
+ * This program is free software; you can redistribute 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/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/threads.h>
+#include <linux/smp.h>
+
+#include <asm/abs_addr.h>
+#include <asm/machdep.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+#include <asm/tlb.h>
+#include <asm/cputable.h>
+
+#define HPTE_LOCK_BIT 3
+
+static spinlock_t native_tlbie_lock = SPIN_LOCK_UNLOCKED;
+
+static inline void native_lock_hpte(HPTE *hptep)
+{
+       unsigned long *word = &hptep->dw0.dword0;
+
+       while (1) {
+               if (!test_and_set_bit(HPTE_LOCK_BIT, word))
+                       break;
+               while(test_bit(HPTE_LOCK_BIT, word))
+                       cpu_relax();
+       }
+}
+
+static inline void native_unlock_hpte(HPTE *hptep)
+{
+       unsigned long *word = &hptep->dw0.dword0;
+
+       asm volatile("lwsync":::"memory");
+       clear_bit(HPTE_LOCK_BIT, word);
+}
+
+long native_hpte_insert(unsigned long hpte_group, unsigned long va,
+                       unsigned long prpn, int secondary,
+                       unsigned long hpteflags, int bolted, int large)
+{
+       unsigned long arpn = physRpn_to_absRpn(prpn);
+       HPTE *hptep = htab_data.htab + hpte_group;
+       Hpte_dword0 dw0;
+       HPTE lhpte;
+       int i;
+
+       for (i = 0; i < HPTES_PER_GROUP; i++) {
+               dw0 = hptep->dw0.dw0;
+
+               if (!dw0.v) {
+                       /* retry with lock held */
+                       native_lock_hpte(hptep);
+                       dw0 = hptep->dw0.dw0;
+                       if (!dw0.v)
+                               break;
+                       native_unlock_hpte(hptep);
+               }
+
+               hptep++;
+       }
+
+       if (i == HPTES_PER_GROUP)
+               return -1;
+
+       lhpte.dw1.dword1      = 0;
+       lhpte.dw1.dw1.rpn     = arpn;
+       lhpte.dw1.flags.flags = hpteflags;
+
+       lhpte.dw0.dword0      = 0;
+       lhpte.dw0.dw0.avpn    = va >> 23;
+       lhpte.dw0.dw0.h       = secondary;
+       lhpte.dw0.dw0.bolted  = bolted;
+       lhpte.dw0.dw0.v       = 1;
+
+       if (large) {
+               lhpte.dw0.dw0.l = 1;
+               lhpte.dw0.dw0.avpn &= ~0x1UL;
+       }
+
+       hptep->dw1.dword1 = lhpte.dw1.dword1;
+
+       /* Guarantee the second dword is visible before the valid bit */
+       __asm__ __volatile__ ("eieio" : : : "memory");
+
+       /*
+        * Now set the first dword including the valid bit
+        * NOTE: this also unlocks the hpte
+        */
+       hptep->dw0.dword0 = lhpte.dw0.dword0;
+
+       __asm__ __volatile__ ("ptesync" : : : "memory");
+
+       return i | (secondary << 3);
+}
+
+static long native_hpte_remove(unsigned long hpte_group)
+{
+       HPTE *hptep;
+       Hpte_dword0 dw0;
+       int i;
+       int slot_offset;
+
+       /* pick a random entry to start at */
+       slot_offset = mftb() & 0x7;
+
+       for (i = 0; i < HPTES_PER_GROUP; i++) {
+               hptep = htab_data.htab + hpte_group + slot_offset;
+               dw0 = hptep->dw0.dw0;
+
+               if (dw0.v && !dw0.bolted) {
+                       /* retry with lock held */
+                       native_lock_hpte(hptep);
+                       dw0 = hptep->dw0.dw0;
+                       if (dw0.v && !dw0.bolted)
+                               break;
+                       native_unlock_hpte(hptep);
+               }
+
+               slot_offset++;
+               slot_offset &= 0x7;
+       }
+
+       if (i == HPTES_PER_GROUP)
+               return -1;
+
+       /* Invalidate the hpte. NOTE: this also unlocks it */
+       hptep->dw0.dword0 = 0;
+
+       return i;
+}
+
+static inline void set_pp_bit(unsigned long pp, HPTE *addr)
+{
+       unsigned long old;
+       unsigned long *p = &addr->dw1.dword1;
+
+       __asm__ __volatile__(
+       "1:     ldarx   %0,0,%3\n\
+               rldimi  %0,%2,0,61\n\
+               stdcx.  %0,0,%3\n\
+               bne     1b"
+       : "=&r" (old), "=m" (*p)
+       : "r" (pp), "r" (p), "m" (*p)
+       : "cc");
+}
+
+/*
+ * Only works on small pages. Yes its ugly to have to check each slot in
+ * the group but we only use this during bootup.
+ */
+static long native_hpte_find(unsigned long vpn)
+{
+       HPTE *hptep;
+       unsigned long hash;
+       unsigned long i, j;
+       long slot;
+       Hpte_dword0 dw0;
+
+       hash = hpt_hash(vpn, 0);
+
+       for (j = 0; j < 2; j++) {
+               slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+               for (i = 0; i < HPTES_PER_GROUP; i++) {
+                       hptep = htab_data.htab + slot;
+                       dw0 = hptep->dw0.dw0;
+
+                       if ((dw0.avpn == (vpn >> 11)) && dw0.v &&
+                           (dw0.h == j)) {
+                               /* HPTE matches */
+                               if (j)
+                                       slot = -slot;
+                               return slot;
+                       }
+                       ++slot;
+               }
+               hash = ~hash;
+       }
+
+       return -1;
+}
+
+static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
+                                unsigned long va, int large, int local)
+{
+       HPTE *hptep = htab_data.htab + slot;
+       Hpte_dword0 dw0;
+       unsigned long avpn = va >> 23;
+       int ret = 0;
+
+       if (large)
+               avpn &= ~0x1UL;
+
+       native_lock_hpte(hptep);
+
+       dw0 = hptep->dw0.dw0;
+
+       /* Even if we miss, we need to invalidate the TLB */
+       if ((dw0.avpn != avpn) || !dw0.v) {
+               native_unlock_hpte(hptep);
+               ret = -1;
+       } else {
+               set_pp_bit(newpp, hptep);
+               native_unlock_hpte(hptep);
+       }
+
+       /* Ensure it is out of the tlb too */
+       if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+               tlbiel(va);
+       } else {
+               int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+
+               if (lock_tlbie)
+                       spin_lock(&native_tlbie_lock);
+               tlbie(va, large);
+               if (lock_tlbie)
+                       spin_unlock(&native_tlbie_lock);
+       }
+
+       return ret;
+}
+
+/*
+ * Update the page protection bits. Intended to be used to create
+ * guard pages for kernel data structures on pages which are bolted
+ * in the HPT. Assumes pages being operated on will not be stolen.
+ * Does not work on large pages.
+ *
+ * No need to lock here because we should be the only user.
+ */
+static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
+{
+       unsigned long vsid, va, vpn, flags;
+       long slot;
+       HPTE *hptep;
+       int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+
+       vsid = get_kernel_vsid(ea);
+       va = (vsid << 28) | (ea & 0x0fffffff);
+       vpn = va >> PAGE_SHIFT;
+
+       slot = native_hpte_find(vpn);
+       if (slot == -1)
+               panic("could not find page to bolt\n");
+       hptep = htab_data.htab + slot;
+
+       set_pp_bit(newpp, hptep);
+
+       /* Ensure it is out of the tlb too */
+       if (lock_tlbie)
+               spin_lock_irqsave(&native_tlbie_lock, flags);
+       tlbie(va, 0);
+       if (lock_tlbie)
+               spin_unlock_irqrestore(&native_tlbie_lock, flags);
+}
+
+static void native_hpte_invalidate(unsigned long slot, unsigned long va,
+                                   int large, int local)
+{
+       HPTE *hptep = htab_data.htab + slot;
+       Hpte_dword0 dw0;
+       unsigned long avpn = va >> 23;
+       unsigned long flags;
+       int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+
+       if (large)
+               avpn &= ~0x1UL;
+
+       local_irq_save(flags);
+       native_lock_hpte(hptep);
+
+       dw0 = hptep->dw0.dw0;
+
+       /* Even if we miss, we need to invalidate the TLB */
+       if ((dw0.avpn != avpn) || !dw0.v) {
+               native_unlock_hpte(hptep);
+       } else {
+               /* Invalidate the hpte. NOTE: this also unlocks it */
+               hptep->dw0.dword0 = 0;
+       }
+
+       /* Invalidate the tlb */
+       if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+               tlbiel(va);
+       } else {
+               if (lock_tlbie)
+                       spin_lock(&native_tlbie_lock);
+               tlbie(va, large);
+               if (lock_tlbie)
+                       spin_unlock(&native_tlbie_lock);
+       }
+       local_irq_restore(flags);
+}
+
+static void native_flush_hash_range(unsigned long context,
+                                   unsigned long number, int local)
+{
+       unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn;
+       int i, j;
+       HPTE *hptep;
+       Hpte_dword0 dw0;
+       struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
+
+       /* XXX fix for large ptes */
+       unsigned long large = 0;
+
+       local_irq_save(flags);
+
+       j = 0;
+       for (i = 0; i < number; i++) {
+               if ((batch->addr[i] >= USER_START) &&
+                   (batch->addr[i] <= USER_END))
+                       vsid = get_vsid(context, batch->addr[i]);
+               else
+                       vsid = get_kernel_vsid(batch->addr[i]);
+
+               va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
+               batch->vaddr[j] = va;
+               if (large)
+                       vpn = va >> HPAGE_SHIFT;
+               else
+                       vpn = va >> PAGE_SHIFT;
+               hash = hpt_hash(vpn, large);
+               secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15;
+               if (secondary)
+                       hash = ~hash;
+               slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+               slot += (pte_val(batch->pte[i]) & _PAGE_GROUP_IX) >> 12;
+
+               hptep = htab_data.htab + slot;
+
+               avpn = va >> 23;
+               if (large)
+                       avpn &= ~0x1UL;
+
+               native_lock_hpte(hptep);
+
+               dw0 = hptep->dw0.dw0;
+
+               /* Even if we miss, we need to invalidate the TLB */
+               if ((dw0.avpn != avpn) || !dw0.v) {
+                       native_unlock_hpte(hptep);
+               } else {
+                       /* Invalidate the hpte. NOTE: this also unlocks it */
+                       hptep->dw0.dword0 = 0;
+               }
+
+               j++;
+       }
+
+       if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+               asm volatile("ptesync":::"memory");
+
+               for (i = 0; i < j; i++)
+                       __tlbiel(batch->vaddr[i]);
+
+               asm volatile("ptesync":::"memory");
+       } else {
+               int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+
+               if (lock_tlbie)
+                       spin_lock(&native_tlbie_lock);
+
+               asm volatile("ptesync":::"memory");
+
+               for (i = 0; i < j; i++)
+                       __tlbie(batch->vaddr[i], 0);
+
+               asm volatile("eieio; tlbsync; ptesync":::"memory");
+
+               if (lock_tlbie)
+                       spin_unlock(&native_tlbie_lock);
+       }
+
+       local_irq_restore(flags);
+}
+
+void hpte_init_native(void)
+{
+#ifdef CONFIG_PPC_PSERIES
+       struct device_node *root;
+       const char *model;
+#endif /* CONFIG_PPC_PSERIES */
+
+       ppc_md.hpte_invalidate  = native_hpte_invalidate;
+       ppc_md.hpte_updatepp    = native_hpte_updatepp;
+       ppc_md.hpte_updateboltedpp = native_hpte_updateboltedpp;
+       ppc_md.hpte_insert      = native_hpte_insert;
+       ppc_md.hpte_remove      = native_hpte_remove;
+
+#ifdef CONFIG_PPC_PSERIES
+       /* Disable TLB batching on nighthawk */
+       root = of_find_node_by_path("/");
+       if (root) {
+               model = get_property(root, "model", NULL);
+               if (!strcmp(model, "CHRP IBM,9076-N81")) {
+                       of_node_put(root);
+                       goto bail;
+               }
+               of_node_put(root);
+       }
+#endif /* CONFIG_PPC_PSERIES */
+
+       ppc_md.flush_hash_range = native_flush_hash_range;
+ bail:
+       htab_finish_init();
+}
index 2399f3f..9d92b0d 100644 (file)
@@ -37,33 +37,51 @@ static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
        return 0;
 }
 
+/* Return whether the region described by v_addr and size is a subset
+ * of the region described by parent
+ */
+static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
+                       struct vm_struct *parent)
+{
+       return (int) (v_addr >= (unsigned long) parent->addr &&
+                     v_addr < (unsigned long) parent->addr + parent->size &&
+                     size < parent->size);
+}
+
+/* Return whether the region described by v_addr and size is a superset
+ * of the region described by child
+ */
+static int im_region_is_superset(unsigned long v_addr, unsigned long size,
+               struct vm_struct *child)
+{
+       struct vm_struct parent;
+
+       parent.addr = (void *) v_addr;
+       parent.size = size;
+
+       return im_region_is_subset((unsigned long) child->addr, child->size,
+                       &parent);
+}
+
 /* Return whether the region described by v_addr and size overlaps
- * the region described by vm.  Overlapping regions meet the 
+ * the region described by vm.  Overlapping regions meet the
  * following conditions:
  * 1) The regions share some part of the address space
  * 2) The regions aren't identical
- * 3) The first region is not a subset of the second
+ * 3) Neither region is a subset of the other
  */
-static inline int im_region_overlaps(unsigned long v_addr, unsigned long size,
+static int im_region_overlaps(unsigned long v_addr, unsigned long size,
                     struct vm_struct *vm)
 {
+       if (im_region_is_superset(v_addr, size, vm))
+               return 0;
+
        return (v_addr + size > (unsigned long) vm->addr + vm->size &&
                v_addr < (unsigned long) vm->addr + vm->size) ||
               (v_addr < (unsigned long) vm->addr &&
                v_addr + size > (unsigned long) vm->addr);
 }
 
-/* Return whether the region described by v_addr and size is a subset
- * of the region described by vm
- */
-static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
-                       struct vm_struct *vm)
-{
-       return (int) (v_addr >= (unsigned long) vm->addr && 
-                     v_addr < (unsigned long) vm->addr + vm->size &&
-                     size < vm->size);
-}
-
 /* Determine imalloc status of region described by v_addr and size.
  * Can return one of the following:
  * IM_REGION_UNUSED   -  Entire region is unallocated in imalloc space.
@@ -73,28 +91,37 @@ static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
  * IM_REGION_EXISTS -    Exact region already allocated in imalloc space.
  *                       vm will be assigned to a ptr to the existing imlist
  *                       member.
- * IM_REGION_OVERLAPS -  A portion of the region is already allocated in 
- *                       imalloc space.
+ * IM_REGION_OVERLAPS -  Region overlaps an allocated region in imalloc space.
+ * IM_REGION_SUPERSET -  Region is a superset of a region that is already
+ *                       allocated in imalloc space.
  */
-static int im_region_status(unsigned long v_addr, unsigned long size, 
+static int im_region_status(unsigned long v_addr, unsigned long size,
                    struct vm_struct **vm)
 {
        struct vm_struct *tmp;
 
-       for (tmp = imlist; tmp; tmp = tmp->next) 
-               if (v_addr < (unsigned long) tmp->addr + tmp->size) 
+       for (tmp = imlist; tmp; tmp = tmp->next)
+               if (v_addr < (unsigned long) tmp->addr + tmp->size)
                        break;
-                                       
+
        if (tmp) {
                if (im_region_overlaps(v_addr, size, tmp))
                        return IM_REGION_OVERLAP;
 
                *vm = tmp;
-               if (im_region_is_subset(v_addr, size, tmp))
+               if (im_region_is_subset(v_addr, size, tmp)) {
+                       /* Return with tmp pointing to superset */
                        return IM_REGION_SUBSET;
-               else if (v_addr == (unsigned long) tmp->addr && 
-                        size == tmp->size) 
+               }
+               if (im_region_is_superset(v_addr, size, tmp)) {
+                       /* Return with tmp pointing to first subset */
+                       return IM_REGION_SUPERSET;
+               }
+               else if (v_addr == (unsigned long) tmp->addr &&
+                        size == tmp->size) {
+                       /* Return with tmp pointing to exact region */
                        return IM_REGION_EXISTS;
+               }
        }
 
        *vm = NULL;
@@ -208,6 +235,10 @@ static struct vm_struct * __im_get_area(unsigned long req_addr,
                tmp = split_im_region(req_addr, size, tmp);
                break;
        case IM_REGION_EXISTS:
+               /* Return requested region */
+               break;
+       case IM_REGION_SUPERSET:
+               /* Return first existing subset of requested region */
                break;
        default:
                printk(KERN_ERR "%s() unexpected imalloc region status\n",
index 5ebf686..f90dd1f 100644 (file)
@@ -54,13 +54,13 @@ static inline int mmap_is_legacy(void)
         */
        if (!test_thread_flag(TIF_32BIT))
                return 1;
-               
-       if (current->personality & ADDR_COMPAT_LAYOUT) 
+
+       if (current->personality & ADDR_COMPAT_LAYOUT)
                return 1;
-       
+
        if (current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY)
                return 1;
-               
+
        return sysctl_legacy_va_layout;
 }
 
@@ -81,7 +81,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
        } else {
                mm->mmap_base = mmap_base();
                mm->get_unmapped_area = arch_get_unmapped_area_topdown;
-               mm->get_unmapped_exec_area = arch_get_unmapped_exec_area;
                mm->unmap_area = arch_unmap_area_topdown;
        }
 }
index bc61258..7424d8d 100644 (file)
 
 extern void slb_allocate(unsigned long ea);
 
+static inline unsigned long mk_esid_data(unsigned long ea, unsigned long slot)
+{
+       return (ea & ESID_MASK) | SLB_ESID_V | slot;
+}
+
+static inline unsigned long mk_vsid_data(unsigned long ea, unsigned long flags)
+{
+       return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags;
+}
+
 static inline void create_slbe(unsigned long ea, unsigned long vsid,
                               unsigned long flags, unsigned long entry)
 {
-       ea = (ea & ESID_MASK) | SLB_ESID_V | entry;
-       vsid = (vsid << SLB_VSID_SHIFT) | flags;
        asm volatile("slbmte  %0,%1" :
-                    : "r" (vsid), "r" (ea)
+                    : "r" (mk_vsid_data(ea, flags)),
+                      "r" (mk_esid_data(ea, entry))
                     : "memory" );
 }
 
-static void slb_add_bolted(void)
+static void slb_flush_and_rebolt(void)
 {
-#ifndef CONFIG_PPC_ISERIES
-       WARN_ON(!irqs_disabled());
-
        /* If you change this make sure you change SLB_NUM_BOLTED
-        * appropriately too */
+        * appropriately too. */
+       unsigned long ksp_flags = SLB_VSID_KERNEL;
+       unsigned long ksp_esid_data;
 
-       /* Slot 1 - first VMALLOC segment
-         *     Since modules end up there it gets hit very heavily.
-         */
-       create_slbe(VMALLOCBASE, get_kernel_vsid(VMALLOCBASE),
-                   SLB_VSID_KERNEL, 1);
+       WARN_ON(!irqs_disabled());
 
-       asm volatile("isync":::"memory");
-#endif
+       if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+               ksp_flags |= SLB_VSID_L;
+
+       ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
+       if ((ksp_esid_data & ESID_MASK) == KERNELBASE)
+               ksp_esid_data &= ~SLB_ESID_V;
+
+       /* We need to do this all in asm, so we're sure we don't touch
+        * the stack between the slbia and rebolting it. */
+       asm volatile("isync\n"
+                    "slbia\n"
+                    /* Slot 1 - first VMALLOC segment */
+                    "slbmte    %0,%1\n"
+                    /* Slot 2 - kernel stack */
+                    "slbmte    %2,%3\n"
+                    "isync"
+                    :: "r"(mk_vsid_data(VMALLOCBASE, SLB_VSID_KERNEL)),
+                       "r"(mk_esid_data(VMALLOCBASE, 1)),
+                       "r"(mk_vsid_data(ksp_esid_data, ksp_flags)),
+                       "r"(ksp_esid_data)
+                    : "memory");
 }
 
 /* Flush all user entries from the segment table of the current processor. */
@@ -71,8 +94,7 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
                }
                asm volatile("isync" : : : "memory");
        } else {
-               asm volatile("isync; slbia; isync" : : : "memory");
-               slb_add_bolted();
+               slb_flush_and_rebolt();
        }
 
        /* Workaround POWER5 < DD2.1 issue */
@@ -115,22 +137,27 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
 
 void slb_initialize(void)
 {
-#ifdef CONFIG_PPC_ISERIES
-       asm volatile("isync; slbia; isync":::"memory");
-#else
+       /* On iSeries the bolted entries have already been set up by
+        * the hypervisor from the lparMap data in head.S */
+#ifndef CONFIG_PPC_ISERIES
        unsigned long flags = SLB_VSID_KERNEL;
 
-       /* Invalidate the entire SLB (even slot 0) & all the ERATS */
-       if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
-               flags |= SLB_VSID_L;
+       /* Invalidate the entire SLB (even slot 0) & all the ERATS */
+       if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+               flags |= SLB_VSID_L;
 
-       asm volatile("isync":::"memory");
-       asm volatile("slbmte  %0,%0"::"r" (0) : "memory");
+       asm volatile("isync":::"memory");
+       asm volatile("slbmte  %0,%0"::"r" (0) : "memory");
        asm volatile("isync; slbia; isync":::"memory");
-       create_slbe(KERNELBASE, get_kernel_vsid(KERNELBASE),
-                   flags, 0);
-
+       create_slbe(KERNELBASE, get_kernel_vsid(KERNELBASE), flags, 0);
+       create_slbe(VMALLOCBASE, get_kernel_vsid(KERNELBASE),
+                   SLB_VSID_KERNEL, 1);
+       /* We don't bolt the stack for the time being - we're in boot,
+        * so the stack is in the bolted segment.  By the time it goes
+        * elsewhere, we'll call _switch() which will bolt in the new
+        * one. */
+       asm volatile("isync":::"memory");
 #endif
-       slb_add_bolted();
+
        get_paca()->stab_rr = SLB_NUM_BOLTED;
 }
index 4b3dfe0..8379d67 100644 (file)
@@ -37,8 +37,21 @@ _GLOBAL(slb_allocate)
         * a free slot first but that took too long. Unfortunately we
         * dont have any LRU information to help us choose a slot.
         */
+#ifdef CONFIG_PPC_ISERIES
+       /*
+        * On iSeries, the "bolted" stack segment can be cast out on
+        * shared processor switch so we need to check for a miss on
+        * it and restore it to the right slot.
+        */
+       ld      r9,PACAKSAVE(r13)
+       clrrdi  r9,r9,28
+       clrrdi  r11,r3,28
+       li      r10,SLB_NUM_BOLTED-1    /* Stack goes in last bolted slot */
+       cmpld   r9,r11
+       beq     3f
+#endif /* CONFIG_PPC_ISERIES */
+
        ld      r10,PACASTABRR(r13)
-3:
        addi    r10,r10,1
        /* use a cpu feature mask if we ever change our slb size */
        cmpldi  r10,SLB_NUM_ENTRIES
@@ -46,55 +59,28 @@ _GLOBAL(slb_allocate)
        blt+    4f
        li      r10,SLB_NUM_BOLTED
 
-       /*
-        * Never cast out the segment for our kernel stack. Since we
-        * dont invalidate the ERAT we could have a valid translation
-        * for the kernel stack during the first part of exception exit
-        * which gets invalidated due to a tlbie from another cpu at a
-        * non recoverable point (after setting srr0/1) - Anton
-        */
-4:     slbmfee r11,r10
-       srdi    r11,r11,27
-       /*
-        * Use paca->ksave as the value of the kernel stack pointer,
-        * because this is valid at all times.
-        * The >> 27 (rather than >> 28) is so that the LSB is the
-        * valid bit - this way we check valid and ESID in one compare.
-        * In order to completely close the tiny race in the context
-        * switch (between updating r1 and updating paca->ksave),
-        * we check against both r1 and paca->ksave.
-        */
-       srdi    r9,r1,27
-       ori     r9,r9,1                 /* mangle SP for later compare */
-       cmpd    r11,r9
-       beq-    3b
-       ld      r9,PACAKSAVE(r13)
-       srdi    r9,r9,27
-       ori     r9,r9,1
-       cmpd    r11,r9
-       beq-    3b
-
+4:
        std     r10,PACASTABRR(r13)
-
+3:
        /* r3 = faulting address, r10 = entry */
 
        srdi    r9,r3,60                /* get region */
        srdi    r3,r3,28                /* get esid */
        cmpldi  cr7,r9,0xc              /* cmp KERNELBASE for later use */
 
-       /* r9 = region, r3 = esid, cr7 = <>KERNELBASE */
-
-       rldicr. r11,r3,32,16
-       bne-    8f                      /* invalid ea bits set */
-       addi    r11,r9,-1
-       cmpldi  r11,0xb
-       blt-    8f                      /* invalid region */
+       rldimi  r10,r3,28,0             /* r10= ESID<<28 | entry */
+       oris    r10,r10,SLB_ESID_V@h    /* r10 |= SLB_ESID_V */
 
-       /* r9 = region, r3 = esid, r10 = entry, cr7 = <>KERNELBASE */
+       /* r3 = esid, r10 = esid_data, cr7 = <>KERNELBASE */
 
        blt     cr7,0f                  /* user or kernel? */
 
-       /* kernel address */
+       /* kernel address: proto-VSID = ESID */
+       /* WARNING - MAGIC: we don't use the VSID 0xfffffffff, but
+        * this code will generate the protoVSID 0xfffffffff for the
+        * top segment.  That's ok, the scramble below will translate
+        * it to VSID 0, which is reserved as a bad VSID - one which
+        * will never have any pages in it.  */
        li      r11,SLB_VSID_KERNEL
 BEGIN_FTR_SECTION
        bne     cr7,9f
@@ -102,8 +88,12 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
        b       9f
 
-0:     /* user address */
+0:     /* user address: proto-VSID = context<<15 | ESID */
        li      r11,SLB_VSID_USER
+
+       srdi.   r9,r3,13
+       bne-    8f                      /* invalid ea bits set */
+
 #ifdef CONFIG_HUGETLB_PAGE
 BEGIN_FTR_SECTION
        /* check against the hugepage ranges */
@@ -125,33 +115,18 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
 #endif /* CONFIG_HUGETLB_PAGE */
 
 6:     ld      r9,PACACONTEXTID(r13)
+       rldimi  r3,r9,USER_ESID_BITS,0
 
-9:     /* r9 = "context", r3 = esid, r11 = flags, r10 = entry */
-
-       rldimi  r9,r3,15,0              /* r9= VSID ordinal */
-
-7:     rldimi  r10,r3,28,0             /* r10= ESID<<28 | entry */
-       oris    r10,r10,SLB_ESID_V@h    /* r10 |= SLB_ESID_V */
-
-       /* r9 = ordinal, r3 = esid, r11 = flags, r10 = esid_data */
-
-       li      r3,VSID_RANDOMIZER@higher
-       sldi    r3,r3,32
-       oris    r3,r3,VSID_RANDOMIZER@h
-       ori     r3,r3,VSID_RANDOMIZER@l
-
-       mulld   r9,r3,r9                /* r9 = ordinal * VSID_RANDOMIZER */
-       clrldi  r9,r9,28                /* r9 &= VSID_MASK */
-       sldi    r9,r9,SLB_VSID_SHIFT    /* r9 <<= SLB_VSID_SHIFT */
-       or      r9,r9,r11               /* r9 |= flags */
+9:     /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */
+       ASM_VSID_SCRAMBLE(r3,r9)
 
-       /* r9 = vsid_data, r10 = esid_data, cr7 = <>KERNELBASE */
+       rldimi  r11,r3,SLB_VSID_SHIFT,16        /* combine VSID and flags */
 
        /*
         * No need for an isync before or after this slbmte. The exception
         * we enter with and the rfid we exit with are context synchronizing.
         */
-       slbmte  r9,r10
+       slbmte  r11,r10
 
        bgelr   cr7                     /* we're done for kernel addresses */
 
@@ -174,6 +149,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
        blr
 
 8:     /* invalid EA */
-       li      r9,0                    /* 0 VSID ordinal -> BAD_VSID */
+       li      r3,0                    /* BAD_VSID */
        li      r11,SLB_VSID_USER       /* flags don't much matter */
-       b       7b
+       b       9b
diff --git a/arch/ppc64/mm/stab.c b/arch/ppc64/mm/stab.c
new file mode 100644 (file)
index 0000000..9b4fe8a
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * PowerPC64 Segment Translation Support.
+ *
+ * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
+ *    Copyright (c) 2001 Dave Engebretsen
+ *
+ * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM
+ *
+ *      This program is free software; you can redistribute 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/config.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+#include <asm/paca.h>
+#include <asm/naca.h>
+#include <asm/cputable.h>
+
+/* Both the segment table and SLB code uses the following cache */
+#define NR_STAB_CACHE_ENTRIES 8
+DEFINE_PER_CPU(long, stab_cache_ptr);
+DEFINE_PER_CPU(long, stab_cache[NR_STAB_CACHE_ENTRIES]);
+
+/*
+ * Create a segment table entry for the given esid/vsid pair.
+ */
+static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
+{
+       unsigned long esid_data, vsid_data;
+       unsigned long entry, group, old_esid, castout_entry, i;
+       unsigned int global_entry;
+       struct stab_entry *ste, *castout_ste;
+       unsigned long kernel_segment = (esid << SID_SHIFT) >= KERNELBASE;
+
+       vsid_data = vsid << STE_VSID_SHIFT;
+       esid_data = esid << SID_SHIFT | STE_ESID_KP | STE_ESID_V;
+       if (! kernel_segment)
+               esid_data |= STE_ESID_KS;
+
+       /* Search the primary group first. */
+       global_entry = (esid & 0x1f) << 3;
+       ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
+
+       /* Find an empty entry, if one exists. */
+       for (group = 0; group < 2; group++) {
+               for (entry = 0; entry < 8; entry++, ste++) {
+                       if (!(ste->esid_data & STE_ESID_V)) {
+                               ste->vsid_data = vsid_data;
+                               asm volatile("eieio":::"memory");
+                               ste->esid_data = esid_data;
+                               return (global_entry | entry);
+                       }
+               }
+               /* Now search the secondary group. */
+               global_entry = ((~esid) & 0x1f) << 3;
+               ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
+       }
+
+       /*
+        * Could not find empty entry, pick one with a round robin selection.
+        * Search all entries in the two groups.
+        */
+       castout_entry = get_paca()->stab_rr;
+       for (i = 0; i < 16; i++) {
+               if (castout_entry < 8) {
+                       global_entry = (esid & 0x1f) << 3;
+                       ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
+                       castout_ste = ste + castout_entry;
+               } else {
+                       global_entry = ((~esid) & 0x1f) << 3;
+                       ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
+                       castout_ste = ste + (castout_entry - 8);
+               }
+
+               /* Dont cast out the first kernel segment */
+               if ((castout_ste->esid_data & ESID_MASK) != KERNELBASE)
+                       break;
+
+               castout_entry = (castout_entry + 1) & 0xf;
+       }
+
+       get_paca()->stab_rr = (castout_entry + 1) & 0xf;
+
+       /* Modify the old entry to the new value. */
+
+       /* Force previous translations to complete. DRENG */
+       asm volatile("isync" : : : "memory");
+
+       old_esid = castout_ste->esid_data >> SID_SHIFT;
+       castout_ste->esid_data = 0;             /* Invalidate old entry */
+
+       asm volatile("sync" : : : "memory");    /* Order update */
+
+       castout_ste->vsid_data = vsid_data;
+       asm volatile("eieio" : : : "memory");   /* Order update */
+       castout_ste->esid_data = esid_data;
+
+       asm volatile("slbie  %0" : : "r" (old_esid << SID_SHIFT));
+       /* Ensure completion of slbie */
+       asm volatile("sync" : : : "memory");
+
+       return (global_entry | (castout_entry & 0x7));
+}
+
+/*
+ * Allocate a segment table entry for the given ea and mm
+ */
+static int __ste_allocate(unsigned long ea, struct mm_struct *mm)
+{
+       unsigned long vsid;
+       unsigned char stab_entry;
+       unsigned long offset;
+
+       /* Kernel or user address? */
+       if (ea >= KERNELBASE) {
+               vsid = get_kernel_vsid(ea);
+       } else {
+               if ((ea >= TASK_SIZE_USER64) || (! mm))
+                       return 1;
+
+               vsid = get_vsid(mm->context.id, ea);
+       }
+
+       stab_entry = make_ste(get_paca()->stab_addr, GET_ESID(ea), vsid);
+
+       if (ea < KERNELBASE) {
+               offset = __get_cpu_var(stab_cache_ptr);
+               if (offset < NR_STAB_CACHE_ENTRIES)
+                       __get_cpu_var(stab_cache[offset++]) = stab_entry;
+               else
+                       offset = NR_STAB_CACHE_ENTRIES+1;
+               __get_cpu_var(stab_cache_ptr) = offset;
+
+               /* Order update */
+               asm volatile("sync":::"memory");
+       }
+
+       return 0;
+}
+
+int ste_allocate(unsigned long ea)
+{
+       return __ste_allocate(ea, current->mm);
+}
+
+/*
+ * Do the segment table work for a context switch: flush all user
+ * entries from the table, then preload some probably useful entries
+ * for the new task
+ */
+void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
+{
+       struct stab_entry *stab = (struct stab_entry *) get_paca()->stab_addr;
+       struct stab_entry *ste;
+       unsigned long offset = __get_cpu_var(stab_cache_ptr);
+       unsigned long pc = KSTK_EIP(tsk);
+       unsigned long stack = KSTK_ESP(tsk);
+       unsigned long unmapped_base;
+
+       /* Force previous translations to complete. DRENG */
+       asm volatile("isync" : : : "memory");
+
+       if (offset <= NR_STAB_CACHE_ENTRIES) {
+               int i;
+
+               for (i = 0; i < offset; i++) {
+                       ste = stab + __get_cpu_var(stab_cache[i]);
+                       ste->esid_data = 0; /* invalidate entry */
+               }
+       } else {
+               unsigned long entry;
+
+               /* Invalidate all entries. */
+               ste = stab;
+
+               /* Never flush the first entry. */
+               ste += 1;
+               for (entry = 1;
+                    entry < (PAGE_SIZE / sizeof(struct stab_entry));
+                    entry++, ste++) {
+                       unsigned long ea;
+                       ea = ste->esid_data & ESID_MASK;
+                       if (ea < KERNELBASE) {
+                               ste->esid_data = 0;
+                       }
+               }
+       }
+
+       asm volatile("sync; slbia; sync":::"memory");
+
+       __get_cpu_var(stab_cache_ptr) = 0;
+
+       /* Now preload some entries for the new task */
+       if (test_tsk_thread_flag(tsk, TIF_32BIT))
+               unmapped_base = TASK_UNMAPPED_BASE_USER32;
+       else
+               unmapped_base = TASK_UNMAPPED_BASE_USER64;
+
+       __ste_allocate(pc, mm);
+
+       if (GET_ESID(pc) == GET_ESID(stack))
+               return;
+
+       __ste_allocate(stack, mm);
+
+       if ((GET_ESID(pc) == GET_ESID(unmapped_base))
+           || (GET_ESID(stack) == GET_ESID(unmapped_base)))
+               return;
+
+       __ste_allocate(unmapped_base, mm);
+
+       /* Order update */
+       asm volatile("sync" : : : "memory");
+}
+
+extern void slb_initialize(void);
+
+/*
+ * Build an entry for the base kernel segment and put it into
+ * the segment table or SLB.  All other segment table or SLB
+ * entries are faulted in.
+ */
+void stab_initialize(unsigned long stab)
+{
+       unsigned long vsid = get_kernel_vsid(KERNELBASE);
+
+       if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {
+               slb_initialize();
+       } else {
+               asm volatile("isync; slbia; isync":::"memory");
+               make_ste(stab, GET_ESID(KERNELBASE), vsid);
+
+               /* Order update */
+               asm volatile("sync":::"memory");
+       }
+}
index aa9c8af..c936c5c 100644 (file)
 /* freeze counters. set to 1 on a perfmon exception */
 #define MMCR0_FC       (1UL << (31 - 0))
 
+/* freeze in supervisor state */
+#define MMCR0_KERNEL_DISABLE (1UL << (31 - 1))
+
+/* freeze in problem state */
+#define MMCR0_PROBLEM_DISABLE (1UL << (31 - 2))
+
 /* freeze counters while MSR mark = 1 */
 #define MMCR0_FCM1     (1UL << (31 - 3))
 
 /* freeze counters on enabled condition or event */
 #define MMCR0_FCECE    (1UL << (31 - 6))
 
-/* performance monitor alert has occurred, set to 0 after handling exception */
-#define MMCR0_PMAO     (1UL << (31 - 24))
-
 /* PMC1 count enable*/
 #define MMCR0_PMC1INTCONTROL   (1UL << (31 - 16))
 
 /* PMCn count enable*/
 #define MMCR0_PMCNINTCONTROL   (1UL << (31 - 17))
 
+/* performance monitor alert has occurred, set to 0 after handling exception */
+#define MMCR0_PMAO     (1UL << (31 - 24))
+
 /* state of MSR HV when SIAR set */
 #define MMCRA_SIHV     (1UL << (63 - 35))
 
@@ -60,6 +66,9 @@ struct op_counter_config {
 
 /* System-wide configuration as set via oprofilefs.  */
 struct op_system_config {
+       unsigned long mmcr0;
+       unsigned long mmcr1;
+       unsigned long mmcra;
        unsigned long enable_kernel;
        unsigned long enable_user;
 };
index 21ceb0b..251fdef 100644 (file)
 #include <asm/processor.h>
 #include <asm/cputable.h>
 
-#define dbg(args...) printk(args)
+#define dbg(args...)
 
 #include "op_impl.h"
 
 static void ctrl_write(unsigned int i, unsigned int val)
 {
-       unsigned int tmp;
-       unsigned long shift, mask;
+       unsigned int tmp = 0;
+       unsigned long shift = 0, mask = 0;
 
        dbg("ctrl_write %d %x\n", i, val);
 
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
new file mode 100644 (file)
index 0000000..f53b6d5
--- /dev/null
@@ -0,0 +1,5 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+endmenu
index a21e308..462ee9a 100644 (file)
@@ -102,8 +102,12 @@ static inline void appldata_debug_print(struct appldata_mem_data *mem_data)
  */
 static void appldata_get_mem_data(void *data)
 {
-       struct sysinfo val;
-       struct page_state ps;
+       /*
+        * don't put large structures on the stack, we are
+        * serialized through the appldata_ops_lock and can use static
+        */
+       static struct sysinfo val;
+       static struct page_state ps;
        struct appldata_mem_data *mem_data;
 
        mem_data = data;
index ce2b035..7537972 100644 (file)
@@ -39,5 +39,9 @@ int main(void)
        DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc),);
        DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap),);
        DEFINE(__PT_SIZE, sizeof(struct pt_regs),);
+       BLANK();
+       DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain),);
+       DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs),);
+       DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1),);
        return 0;
 }
index 52d5a78..bb0f973 100644 (file)
@@ -391,10 +391,10 @@ __u8 _ebc_toupper[256] =
        0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
 };
 
-EXPORT_SYMBOL_NOVERS(_ascebc_500);
-EXPORT_SYMBOL_NOVERS(_ebcasc_500);
-EXPORT_SYMBOL_NOVERS(_ascebc);
-EXPORT_SYMBOL_NOVERS(_ebcasc);
-EXPORT_SYMBOL_NOVERS(_ebc_tolower);
-EXPORT_SYMBOL_NOVERS(_ebc_toupper);
+EXPORT_SYMBOL(_ascebc_500);
+EXPORT_SYMBOL(_ebcasc_500);
+EXPORT_SYMBOL(_ascebc);
+EXPORT_SYMBOL(_ebcasc);
+EXPORT_SYMBOL(_ebc_tolower);
+EXPORT_SYMBOL(_ebc_toupper);
 
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
new file mode 100644 (file)
index 0000000..79a4222
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *  arch/s390/kernel/irq.c
+ *
+ *  S390 version
+ *    Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *
+ * This file contains interrupt related functions.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
+#include <linux/seq_file.h>
+#include <linux/cpu.h>
+
+/*
+ * show_interrupts is needed by /proc/interrupts.
+ */
+int show_interrupts(struct seq_file *p, void *v)
+{
+       static const char *intrclass_names[] = { "EXT", "I/O", };
+       int i = *(loff_t *) v, j;
+
+       if (i == 0) {
+               seq_puts(p, "           ");
+               for (j=0; j<NR_CPUS; j++)
+                       if (cpu_online(j))
+                               seq_printf(p, "CPU%d       ",j);
+               seq_putc(p, '\n');
+       }
+
+       if (i < NR_IRQS) {
+               seq_printf(p, "%s: ", intrclass_names[i]);
+#ifndef CONFIG_SMP
+               seq_printf(p, "%10u ", kstat_irqs(i));
+#else
+               for (j = 0; j < NR_CPUS; j++)
+                       if (cpu_online(j))
+                               seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#endif
+                seq_putc(p, '\n');
+
+        }
+
+        return 0;
+}
+
+/*
+ * For compatibilty only. S/390 specific setup of interrupts et al. is done
+ * much later in init_channel_subsystem().
+ */
+void __init
+init_IRQ(void)
+{
+       /* nothing... */
+}
+
+/*
+ * Switch to the asynchronous interrupt stack for softirq execution.
+ */
+extern void __do_softirq(void);
+
+asmlinkage void do_softirq(void)
+{
+       unsigned long flags, old, new;
+
+       if (in_interrupt())
+               return;
+
+       local_irq_save(flags);
+
+       if (local_softirq_pending()) {
+               /* Get current stack pointer. */
+               asm volatile("la %0,0(15)" : "=a" (old));
+               /* Check against async. stack address range. */
+               new = S390_lowcore.async_stack;
+               if (((new - old) >> (PAGE_SHIFT + THREAD_ORDER)) != 0) {
+                       /* Need to switch to the async. stack. */
+                       new -= STACK_FRAME_OVERHEAD;
+                       ((struct stack_frame *) new)->back_chain = old;
+
+                       asm volatile("   la    15,0(%0)\n"
+                                    "   basr  14,%2\n"
+                                    "   la    15,0(%1)\n"
+                                    : : "a" (new), "a" (old),
+                                        "a" (__do_softirq)
+                                    : "0", "1", "2", "3", "4", "5",
+                                      "cc", "memory" );
+               } else
+                       /* We are already on the async stack. */
+                       __do_softirq();
+       }
+
+       local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(do_softirq);
index f219748..7ba777e 100644 (file)
@@ -6,52 +6,15 @@
  *
  */
 #include <linux/proc_fs.h>
+#include <linux/profile.h>
 
 static struct proc_dir_entry * root_irq_dir;
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-                                       int count, int *eof, void *data)
-{
-       int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-       if (count - len < 2)
-               return -EINVAL;
-       len += sprintf(page + len, "\n");
-       return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file,
-                                       const char __user *buffer,
-                                       unsigned long count, void *data)
-{
-       cpumask_t *mask = (cpumask_t *)data;
-       unsigned long full_count = count, err;
-       cpumask_t new_value;
-
-       err = cpumask_parse(buffer, count, new_value);
-       if (err)
-               return err;
-
-       *mask = new_value;
-       return full_count;
-}
-
-cpumask_t prof_cpu_mask = CPU_MASK_ALL;
-
 void init_irq_proc(void)
 {
-       struct proc_dir_entry *entry;
-
        /* create /proc/irq */
        root_irq_dir = proc_mkdir("irq", 0);
 
        /* create /proc/irq/prof_cpu_mask */
-       entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-       if (!entry)
-               return;
-
-       entry->nlink = 1;
-       entry->data = (void *)&prof_cpu_mask;
-       entry->read_proc = prof_cpu_mask_read_proc;
-       entry->write_proc = prof_cpu_mask_write_proc;
+       create_prof_cpu_mask(root_irq_dir);
 }
index c00e5e3..b61490b 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
 
 #include <asm/lowcore.h>
 #include <asm/s390_ext.h>
index b4534b2..89fdb38 100644 (file)
@@ -24,6 +24,7 @@ SECTIONS
   .text : {
        *(.text)
        SCHED_TEXT
+       LOCK_TEXT
        *(.fixup)
        *(.gnu.warning)
        } = 0x0700
@@ -78,9 +79,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
        *(.initcall1.init) 
index d9ccdbd..02d2179 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/s390_ext.h>
 #include <asm/timer.h>
 
-#define VTIMER_MAGIC (0x4b87ad6e + 1)
+#define VTIMER_MAGIC (TIMER_MAGIC + 1)
 static ext_int_info_t ext_int_info_timer;
 DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
 
index 966af7c..9cf22aa 100644 (file)
@@ -46,7 +46,7 @@ size_t strlen(const char *s)
 {
        return __strend(s) - s;
 }
-EXPORT_SYMBOL_NOVERS(strlen);
+EXPORT_SYMBOL(strlen);
 
 /**
  * strnlen - Find the length of a length-limited string
@@ -59,7 +59,7 @@ size_t strnlen(const char * s, size_t n)
 {
        return __strnend(s, n) - s;
 }
-EXPORT_SYMBOL_NOVERS(strnlen);
+EXPORT_SYMBOL(strnlen);
 
 /**
  * strcpy - Copy a %NUL terminated string
@@ -79,7 +79,7 @@ char *strcpy(char *dest, const char *src)
                      : "cc", "memory" );
        return ret;
 }
-EXPORT_SYMBOL_NOVERS(strcpy);
+EXPORT_SYMBOL(strcpy);
 
 /**
  * strlcpy - Copy a %NUL terminated string into a sized buffer
@@ -103,7 +103,7 @@ size_t strlcpy(char *dest, const char *src, size_t size)
        }
        return ret;
 }
-EXPORT_SYMBOL_NOVERS(strlcpy);
+EXPORT_SYMBOL(strlcpy);
 
 /**
  * strncpy - Copy a length-limited, %NUL-terminated string
@@ -121,7 +121,7 @@ char *strncpy(char *dest, const char *src, size_t n)
        __builtin_memcpy(dest, src, len);
        return dest;
 }
-EXPORT_SYMBOL_NOVERS(strncpy);
+EXPORT_SYMBOL(strncpy);
 
 /**
  * strcat - Append one %NUL-terminated string to another
@@ -144,7 +144,7 @@ char *strcat(char *dest, const char *src)
                      : "d" (r0), "0" (0UL) : "cc", "memory" );
        return ret;
 }
-EXPORT_SYMBOL_NOVERS(strcat);
+EXPORT_SYMBOL(strcat);
 
 /**
  * strlcat - Append a length-limited, %NUL-terminated string to another
@@ -168,7 +168,7 @@ size_t strlcat(char *dest, const char *src, size_t n)
        }
        return res;
 }
-EXPORT_SYMBOL_NOVERS(strlcat);
+EXPORT_SYMBOL(strlcat);
 
 /**
  * strncat - Append a length-limited, %NUL-terminated string to another
@@ -190,7 +190,7 @@ char *strncat(char *dest, const char *src, size_t n)
        __builtin_memcpy(p, src, len);
        return dest;
 }
-EXPORT_SYMBOL_NOVERS(strncat);
+EXPORT_SYMBOL(strncat);
 
 /**
  * strcmp - Compare two strings
@@ -217,7 +217,7 @@ int strcmp(const char *cs, const char *ct)
                      : : "cc" );
        return ret;
 }
-EXPORT_SYMBOL_NOVERS(strcmp);
+EXPORT_SYMBOL(strcmp);
 
 /**
  * strrchr - Find the last occurrence of a character in a string
@@ -235,7 +235,7 @@ char * strrchr(const char * s, int c)
               } while (--len > 0);
        return 0;
 }
-EXPORT_SYMBOL_NOVERS(strrchr);
+EXPORT_SYMBOL(strrchr);
 
 /**
  * strstr - Find the first substring in a %NUL terminated string
@@ -269,7 +269,7 @@ char * strstr(const char * s1,const char * s2)
        }
        return 0;
 }
-EXPORT_SYMBOL_NOVERS(strstr);
+EXPORT_SYMBOL(strstr);
 
 /**
  * memchr - Find a character in an area of memory.
@@ -293,7 +293,7 @@ void *memchr(const void *s, int c, size_t n)
                      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
        return (void *) ret;
 }
-EXPORT_SYMBOL_NOVERS(memchr);
+EXPORT_SYMBOL(memchr);
 
 /**
  * memcmp - Compare two areas of memory
@@ -319,7 +319,7 @@ int memcmp(const void *cs, const void *ct, size_t n)
                ret = *(char *) r2 - *(char *) r4;
        return ret;
 }
-EXPORT_SYMBOL_NOVERS(memcmp);
+EXPORT_SYMBOL(memcmp);
 
 /**
  * memscan - Find a character in an area of memory.
@@ -340,7 +340,7 @@ void *memscan(void *s, int c, size_t n)
                      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
        return (void *) ret;
 }
-EXPORT_SYMBOL_NOVERS(memscan);
+EXPORT_SYMBOL(memscan);
 
 /**
  * memcpy - Copy one area of memory to another
@@ -354,7 +354,7 @@ void *memcpy(void *dest, const void *src, size_t n)
 {
        return __builtin_memcpy(dest, src, n);
 }
-EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL(memcpy);
 
 /**
  * bcopy - Copy one area of memory to another
@@ -369,7 +369,7 @@ void bcopy(const void *srcp, void *destp, size_t n)
 {
        __builtin_memcpy(destp, srcp, n);
 }
-EXPORT_SYMBOL_NOVERS(bcopy);
+EXPORT_SYMBOL(bcopy);
 
 /**
  * memset - Fill a region of memory with the given value
@@ -393,4 +393,4 @@ void *memset(void *s, int c, size_t n)
                } while (--n > 0);
        return s;
 }
-EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL(memset);
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
new file mode 100644 (file)
index 0000000..3fab181
--- /dev/null
@@ -0,0 +1,124 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config SH_STANDARD_BIOS
+       bool "Use LinuxSH standard BIOS"
+       help
+         Say Y here if your target has the gdb-sh-stub
+         package from www.m17n.org (or any conforming standard LinuxSH BIOS)
+         in FLASH or EPROM.  The kernel will use standard BIOS calls during
+         boot for various housekeeping tasks (including calls to read and
+         write characters to a system console, get a MAC address from an
+         on-board Ethernet interface, and shut down the hardware).  Note this
+         does not work with machines with an existing operating system in
+         mask ROM and no flash (WindowsCE machines fall in this category).
+         If unsure, say N.
+
+config EARLY_SCIF_CONSOLE
+       bool "Use early SCIF console"
+       depends on CPU_SH4
+
+config EARLY_PRINTK
+       bool "Early printk support"
+       depends on SH_STANDARD_BIOS || EARLY_SCIF_CONSOLE
+       help
+         Say Y here to redirect kernel printk messages to the serial port
+         used by the SH-IPL bootloader, starting very early in the boot
+         process and ending when the kernel's serial console is initialised.
+         This option is only useful porting the kernel to a new machine,
+         when the kernel may crash or hang before the serial console is
+         initialised. If unsure, say N.
+
+config KGDB
+       bool "Include KGDB kernel debugger"
+       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
+
+config MORE_COMPILE_OPTIONS
+       bool "Add any additional compile options"
+       help
+         If you want to add additional CFLAGS to the kernel build, enable this
+         option and then enter what you would like to add in the next question.
+         Note however that -g is already appended with the selection of KGDB.
+
+config COMPILE_OPTIONS
+       string "Additional compile arguments"
+       depends on MORE_COMPILE_OPTIONS
+
+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"
+       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
+       int "Port number (ttySCn)"
+       default "1"
+
+config KGDB_DEFBAUD
+       int "Baud rate"
+       default "115200"
+
+choice
+       prompt "Parity"
+       depends on KGDB
+       default KGDB_DEFPARITY_N
+
+config KGDB_DEFPARITY_N
+       bool "None"
+
+config KGDB_DEFPARITY_E
+       bool "Even"
+
+config KGDB_DEFPARITY_O
+       bool "Odd"
+
+endchoice
+
+choice
+       prompt "Data bits"
+       depends on KGDB
+       default KGDB_DEFBITS_8
+
+config KGDB_DEFBITS_8
+       bool "8"
+
+config KGDB_DEFBITS_7
+       bool "7"
+
+endchoice
+
+endmenu
+
+config FRAME_POINTER
+       bool "Compile the kernel with frame pointers"
+       default y if KGDB
+       help
+         If you say Y here the resulting kernel image will be slightly larger
+         and slower, but it will give very useful debugging information.
+         If you don't debug the kernel, you can say N, but we may not be able
+         to solve problems without frame pointers.
+
+endmenu
index c9bbd72..ba3a654 100644 (file)
@@ -176,14 +176,7 @@ static void __devinit quirk_ali_ide_ports(struct pci_dev *dev)
        dev->resource[4].end   = 0xf00f;
        dev->resource[4].flags = IORESOURCE_IO;
 }
-
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-       { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL,
-         PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports },
-       { 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports);
 
 char * __devinit pcibios_setup(char *str)
 {
index 54020eb..276fa11 100644 (file)
@@ -455,13 +455,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
                }
        }
 }
-
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-       { PCI_FIXUP_HEADER,     PCI_ANY_ID,     PCI_ANY_ID,     pci_fixup_ide_bases },
-       { 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 void __init pcibios_init(void)
 {
index aa5e24a..d07572b 100644 (file)
@@ -47,11 +47,7 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev)
        }
 }
 
-struct pci_fixup pcibios_fixups[] = {
-       { PCI_FIXUP_HEADER, PCI_ANY_ID,
-         PCI_ANY_ID, gapspci_fixup_resources },
-       { 0, }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
 
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
index 29e7bf6..4be02f6 100644 (file)
@@ -160,13 +160,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
                }
        }
 }
-
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-       { PCI_FIXUP_HEADER,     PCI_ANY_ID,     PCI_ANY_ID,     pci_fixup_ide_bases },
-       { 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 int __init st40pci_init(unsigned memStart, unsigned memSize)
 {
index ccee2ec..fc5ef99 100644 (file)
@@ -413,9 +413,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
        return;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -490,9 +488,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        return;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
 }
 
 /*
index e757b2c..34d4e0c 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
index 43a9e26..7abba21 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 #include <asm/kgdb.h>
index 4b7a0bc..115b1b6 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
index 0ac5d41..551ba9a 100644 (file)
@@ -263,58 +263,10 @@ source "fs/Kconfig"
 
 source "arch/sh64/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config MAGIC_SYSRQ
-       bool "Magic SysRq key"
-       help
-         If you say Y here, you will have some control over the system even
-         if the system crashes for example during kernel debugging (e.g., you
-         will be able to flush the buffer cache to disk, reboot the system
-         immediately or dump some status information). This is accomplished
-         by pressing various keys while holding SysRq (Alt+PrintScreen). It
-         also works on a serial console (on PC hardware at least), if you
-         send a BREAK and then within 5 seconds a command keypress. The
-         keys are documented in Documentation/sysrq.txt. Don't say Y unless
-         you really know what this hack does.
-
-config EARLY_PRINTK
-       bool "Early SCIF console support"
-
-config DEBUG_KERNEL_WITH_GDB_STUB
-       bool "GDB Stub kernel debug"
-
-config SH64_PROC_TLB
-       bool "Debug: report TLB fill/purge activity through /proc/tlb"
-       depends on PROC_FS
-
-config SH64_PROC_ASIDS
-       bool "Debug: report ASIDs through /proc/asids"
-       depends on PROC_FS
-
-config SH64_SR_WATCH
-       bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
-
-config SH_ALPHANUMERIC
-       bool "Enable debug outputs to on-board alphanumeric display"
-
-config SH_NO_BSS_INIT
-       bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)"
-
-config FRAME_POINTER
-       bool "Compile the kernel with frame pointers"
-       default y if KGDB
-       help
-         If you say Y here the resulting kernel image will be slightly larger
-         and slower, but it will give very useful debugging information.
-         If you don't debug the kernel, you can say N, but we may not be able
-         to solve problems without frame pointers.
-
-endmenu
+source "arch/sh64/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/sh64/Kconfig.debug b/arch/sh64/Kconfig.debug
new file mode 100644 (file)
index 0000000..530b3c6
--- /dev/null
@@ -0,0 +1,37 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config EARLY_PRINTK
+       bool "Early SCIF console support"
+
+config DEBUG_KERNEL_WITH_GDB_STUB
+       bool "GDB Stub kernel debug"
+
+config SH64_PROC_TLB
+       bool "Debug: report TLB fill/purge activity through /proc/tlb"
+       depends on PROC_FS
+
+config SH64_PROC_ASIDS
+       bool "Debug: report ASIDs through /proc/asids"
+       depends on PROC_FS
+
+config SH64_SR_WATCH
+       bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
+
+config SH_ALPHANUMERIC
+       bool "Enable debug outputs to on-board alphanumeric display"
+
+config SH_NO_BSS_INIT
+       bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)"
+
+config FRAME_POINTER
+       bool "Compile the kernel with frame pointers"
+       default y if KGDB
+       help
+         If you say Y here the resulting kernel image will be slightly larger
+         and slower, but it will give very useful debugging information.
+         If you don't debug the kernel, you can say N, but we may not be able
+         to solve problems without frame pointers.
+
+endmenu
index bcf6385..7d0f422 100644 (file)
@@ -148,6 +148,7 @@ asmlinkage void do_NMI(unsigned long vector_num, struct pt_regs * regs)
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
        int status;
+       int ret;
 
        status = 1;     /* Force the "do bottom halves" bit */
 
@@ -155,8 +156,9 @@ int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction *
                 local_irq_enable();
 
        do {
-               status |= action->flags;
-               action->handler(irq, action->dev_id, regs);
+               ret = action->handler(irq, action->dev_id, regs);
+               if (ret == IRQ_HANDLED)
+                       status |= action->flags;
                action = action->next;
        } while (action);
        if (status & SA_SAMPLE_RANDOM)
index c2b4f00..842a243 100644 (file)
@@ -48,12 +48,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
                }
        }
 }
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-       { PCI_FIXUP_HEADER,     PCI_ANY_ID,     PCI_ANY_ID,     pci_fixup_ide_bases },
-       { 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 char * __init pcibios_setup(char *str)
 {
index f9e8227..13cec35 100644 (file)
@@ -820,7 +820,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
 {
        if (!newsp)
                newsp = pregs->regs[15];
-       return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, pregs, 0, 0, 0);
+       return do_fork(clone_flags, newsp, pregs, 0, 0, 0);
 }
 
 /*
@@ -901,7 +901,7 @@ unsigned long get_wchan(struct task_struct *p)
         */
        pc = thread_saved_pc(p);
 
-#if CONFIG_FRAME_POINTER
+#ifdef CONFIG_FRAME_POINTER
        if (in_sh64_switch_to(pc)) {
                sh64_switch_to_fp = (long) p->thread.sp;
                /* r14 is saved at offset 4 in the sh64_switch_to frame */
index 887e89a..c48bc4a 100644 (file)
@@ -311,11 +311,8 @@ asmlinkage void syscall_trace(void)
        if (!(tsk->ptrace & PT_PTRACED))
                return;
 
-       tsk->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-                                   ? 0x80 : 0);
-       tsk->state = TASK_STOPPED;
-       notify_parent(tsk, SIGCHLD);
-       schedule();
+       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
index 80712f1..36cd5de 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 
@@ -59,17 +58,17 @@ EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(screen_info);
 #endif
 
-EXPORT_SYMBOL_NOVERS(__down);
-EXPORT_SYMBOL_NOVERS(__down_trylock);
-EXPORT_SYMBOL_NOVERS(__up);
-EXPORT_SYMBOL_NOVERS(__put_user_asm_l);
-EXPORT_SYMBOL_NOVERS(__get_user_asm_l);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(strchr);
-EXPORT_SYMBOL_NOVERS(strlen);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_trylock);
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__put_user_asm_l);
+EXPORT_SYMBOL(__get_user_asm_l);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strlen);
 
 EXPORT_SYMBOL(flush_dcache_page);
 
@@ -78,7 +77,7 @@ EXPORT_SYMBOL(flush_dcache_page);
 extern void __sdivsi3(void);
 extern void __muldi3(void);
 extern void __udivsi3(void);
-EXPORT_SYMBOL_NOVERS(__sdivsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
+EXPORT_SYMBOL(__sdivsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__udivsi3);
 
index 376b899..a848fbd 100644 (file)
@@ -520,9 +520,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
        return;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -628,9 +626,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        return;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
 }
 
 /*
index 128bd22..b3738ed 100644 (file)
@@ -298,37 +298,6 @@ static int set_rtc_time(unsigned long nowtime)
 /* last time the RTC clock got updated */
 static long last_rtc_update = 0;
 
-static inline void sh64_do_profile(struct pt_regs *regs)
-{
-       extern int _stext;
-       unsigned long pc;
-
-       profile_hook(regs);
-
-       if (user_mode(regs))
-               return;
-
-       /* Don't profile cpu_idle..  */
-       if (!prof_buffer || !current->pid)
-               return;
-
-       pc = instruction_pointer(regs);
-       pc -= (unsigned long) &_stext;
-       pc >>= prof_shift;
-
-       /*
-        * Don't ignore out-of-bounds PC values silently, put them into the
-        * last histogram slot, so if present, they will show up as a sharp
-        * peak.
-        */
-       if (pc > prof_len - 1)
-               pc = prof_len - 1;
-
-       /* We could just be sloppy and not lock against a re-entry on this
-          increment, but the profiling code won't always be linked in anyway. */
-       atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -340,8 +309,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
        ctc_last_interrupt = (unsigned long) current_ctc;
 
        do_timer(regs);
-
-       sh64_do_profile(regs);
+       profile_tick(CPU_PROFILING, regs);
 
 #ifdef CONFIG_HEARTBEAT
        {
index a3fba81..7d9f7a6 100644 (file)
@@ -59,6 +59,7 @@ SECTIONS
        *(.text64)
         *(.text..SHmedia32)
        SCHED_TEXT
+       LOCK_TEXT
        *(.fixup)
        *(.gnu.warning)
 #ifdef CONFIG_LITTLE_ENDIAN
@@ -106,9 +107,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : C_PHYS(.init.setup) { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : C_PHYS(__param) { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : C_PHYS(.initcall.init) {
        *(.initcall1.init)
index b5ab4a8..d1190b4 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/tlb.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/registers.h>             /* required by inline asm statements */
 
index 17cdeb4..09cd9c8 100644 (file)
@@ -122,8 +122,8 @@ void __init paging_init(void)
         * All memory is good as ZONE_NORMAL (fall-through) and ZONE_DMA.
          */
        zones_size[ZONE_DMA] = MAX_LOW_PFN - START_PFN;
-
-       free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
+       NODE_DATA(0)->node_mem_map = NULL;
+       free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
 
        /* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/
        mem_map = NODE_DATA(0)->node_mem_map;
diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug
new file mode 100644 (file)
index 0000000..120f6b5
--- /dev/null
@@ -0,0 +1,14 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_STACK_USAGE
+       bool "Enable stack utilization instrumentation"
+       depends on DEBUG_KERNEL
+       help
+         Enables the display of the minimum amount of free stack which each
+         task has ever had available in the sysrq-T and sysrq-P debug output.
+
+         This option will slow down process creation somewhat.
+
+endmenu
index b19cc86..b365084 100644 (file)
@@ -7,28 +7,52 @@
 ROOT_IMG       := /usr/src/root.img
 ELFTOAOUT      := elftoaout
 
-host-progs     := piggyback btfixupprep
-targets                := tftpboot.img btfix.o btfix.s image
+hostprogs-y    := piggyback btfixupprep
+targets                := tftpboot.img btfix.o btfix.S image
 
 quiet_cmd_elftoaout    = ELFTOAOUT $@
       cmd_elftoaout    = $(ELFTOAOUT) $(obj)/image -o $@
-quiet_cmd_piggy                = PIGGY $@
+quiet_cmd_piggy                = PIGGY   $@
       cmd_piggy                = $(obj)/piggyback $@ $(obj)/System.map $(ROOT_IMG)
-quiet_cmd_btfix                = BTFIX $@
+quiet_cmd_btfix                = BTFIX   $@
       cmd_btfix                = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@
+quiet_cmd_sysmap        = SYSMAP  $(obj)/System.map
+      cmd_sysmap        = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
+quiet_cmd_image = LD      $@
+      cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@
+
+define rule_image
+       $(if $($(quiet)cmd_image),               \
+         echo '  $($(quiet)cmd_image)' &&)      \
+         $(cmd_image);                          \
+       $(if $($(quiet)cmd_sysmap),              \
+         echo '  $($(quiet)cmd_sysmap)' &&)  \
+       $(cmd_sysmap) $@ $(obj)/System.map;      \
+       if [ $$? -ne 0 ]; then                   \
+               rm -f $@;                        \
+               /bin/false;                      \
+       fi;                                      \
+       echo 'cmd_$@ := $(cmd_image)' > $(@D)/.$(@F).cmd
+endef
 
 BTOBJS := $(HEAD_Y) $(INIT_Y)
 BTLIBS := $(CORE_Y) $(LIBS_Y) $(DRIVERS_Y) $(NET_Y)
-LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds.s $(BTOBJS) --start-group $(BTLIBS) --end-group $(kallsyms.o)
+LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds $(BTOBJS) \
+                  --start-group $(BTLIBS) --end-group \
+                  $(kallsyms.o) $(obj)/btfix.o
 
-# Actual linking
+# Link the final image including btfixup'ed symbols.
+# This is a replacement for the link done in the top-level Makefile.
+# Note: No dependency on the prerequisite files since that would require
+# make to try check if they are updated - and due to changes
+# in gcc options (path for example) this would result in
+# these files being recompiled for each build.
 $(obj)/image: $(obj)/btfix.o FORCE
-       $(call if_changed,ld)
-       $(NM) $@ | grep -v  '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > $(obj)/System.map
+       $(call if_changed_rule,image)
 
 $(obj)/tftpboot.img: $(obj)/piggyback $(obj)/System.map $(obj)/image FORCE
        $(call if_changed,elftoaout)
        $(call if_changed,piggy)
 
-$(obj)/btfix.s: $(obj)/btfixupprep vmlinux FORCE
+$(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE
        $(call if_changed,btfix)
index fcf149e..3d22ba2 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y                := head.o init_task.o vmlinux.lds.s
+extra-y                := head.o init_task.o vmlinux.lds
 
 EXTRA_AFLAGS   := -ansi
 
index 14a4b95..624e2a6 100644 (file)
@@ -858,7 +858,7 @@ vac_hwflush_patch1_on:              addcc   %l7, -PAGE_SIZE, %l7
 vac_hwflush_patch2_on:         sta     %g0, [%l3 + %l7] ASI_HWFLUSHSEG
 
        .globl  invalid_segment_patch1, invalid_segment_patch2
-       .globl  num_context_patch1, num_context_patch2
+       .globl  num_context_patch1
        .globl  vac_linesize_patch, vac_hwflush_patch1
        .globl  vac_hwflush_patch2
 
index bc52cd4..c982473 100644 (file)
 #include <asm/uaccess.h>
 
 
-struct pci_fixup pcibios_fixups[] = {
-       { 0 }
-};
-
 unsigned int pcic_pin_to_irq(unsigned int pin, char *name);
 
 /*
index 9f659c2..1de4c8a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
+#include <linux/profile.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -29,7 +30,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/hardirq.h>
 #include <asm/sbus.h>
 #include <asm/sbi.h>
 #include <asm/tlbflush.h>
@@ -201,18 +201,9 @@ void __init smp4d_boot_cpus(void)
                        int no;
 
                        /* Cook up an idler for this guy. */
-                       kernel_thread(start_secondary, NULL, CLONE_IDLETASK);
-
+                       p = fork_idle(i);
                        cpucount++;
-
-                       p = prev_task(&init_task);
-
-                       init_idle(p, i);
-
                        current_set[i] = p->thread_info;
-
-                       unhash_process(p);
-
                        for (no = 0; !cpu_find_by_instance(no, NULL, &mid)
                                     && mid != i; no++) ;
 
@@ -418,8 +409,6 @@ void smp4d_message_pass(int target, int msg, unsigned long data, int wait)
        panic("Bogon SMP message pass.");
 }
 
-extern void sparc_do_profile(unsigned long pc, unsigned long o7);
-
 void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
 {
        int cpu = hard_smp4d_processor_id();
@@ -437,8 +426,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
                show_leds(cpu);
        }
 
-       if(!user_mode(regs))
-               sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+       profile_tick(CPU_PROFILING, regs);
 
        if(!--prof_counter(cpu)) {
                int user = user_mode(regs);
index 8d4bbfa..38938d2 100644 (file)
@@ -13,6 +13,7 @@ SECTIONS
   {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
     *(.gnu.warning)
   } =0
   _etext = .;
@@ -46,9 +47,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
        *(.initcall1.init) 
index c18475e..d5593b5 100644 (file)
@@ -1341,7 +1341,7 @@ void __init srmmu_paging_init(void)
                zones_size[ZONE_HIGHMEM] = npages;
                zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
-               free_area_init_node(0, &contig_page_data, NULL, zones_size,
+               free_area_init_node(0, &contig_page_data, zones_size,
                                    pfn_base, zholes_size);
                mem_map = contig_page_data.node_mem_map;
        }
diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug
new file mode 100644 (file)
index 0000000..cd8d39f
--- /dev/null
@@ -0,0 +1,54 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_STACK_USAGE
+       bool "Enable stack utilization instrumentation"
+       depends on DEBUG_KERNEL
+       help
+         Enables the display of the minimum amount of free stack which each
+         task has ever had available in the sysrq-T and sysrq-P debug output.
+
+         This option will slow down process creation somewhat.
+
+config KPROBES
+       bool "Kprobes"
+       depends on DEBUG_KERNEL
+       help
+         Kprobes allows you to trap at almost any kernel address and
+         execute a callback function.  register_kprobe() establishes
+         a probepoint and specifies the callback.  Kprobes is useful
+         for kernel debugging, non-intrusive instrumentation and testing.
+         If in doubt, say "N".
+
+config DEBUG_DCFLUSH
+       bool "D-cache flush debugging"
+       depends on DEBUG_KERNEL
+
+config STACK_DEBUG
+       depends on DEBUG_KERNEL
+       bool "Stack Overflow Detection Support"
+
+config DEBUG_BOOTMEM
+       depends on DEBUG_KERNEL
+       bool "Debug BOOTMEM initialization"
+
+# We have a custom atomic_dec_and_lock() implementation but it's not
+# compatible with spinlock debugging so we need to fall back on
+# the generic version in that case.
+config HAVE_DEC_LOCK
+       bool
+       depends on SMP && !DEBUG_SPINLOCK
+       default y
+
+config MCOUNT
+       bool
+       depends on STACK_DEBUG
+       default y
+
+config FRAME_POINTER
+       bool
+       depends on MCOUNT
+       default y
+
+endmenu
index 5eb14ff..6968a6d 100644 (file)
@@ -7,7 +7,7 @@
 ROOT_IMG       := /usr/src/root.img
 ELFTOAOUT      := elftoaout
 
-host-progs     := piggyback
+hostprogs-y    := piggyback
 targets                := image tftpboot.img vmlinux.aout
 
 quiet_cmd_elftoaout = ELF2AOUT $@
index 2caca47..093281b 100644 (file)
@@ -5,7 +5,7 @@
 EXTRA_AFLAGS := -ansi
 EXTRA_CFLAGS := -Werror
 
-extra-y                := head.o init_task.o vmlinux.lds.s
+extra-y                := head.o init_task.o vmlinux.lds
 
 obj-y          := process.o setup.o cpu.o idprom.o \
                   traps.o devices.o auxio.o \
@@ -22,6 +22,7 @@ obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
 obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o
+obj-$(CONFIG_KPROBES) += kprobes.o
 
 ifdef CONFIG_SUNOS_EMUL
   obj-y += sys_sunos32.o sunos_ioctl32.o
index a280462..fb3e3b7 100644 (file)
@@ -27,12 +27,12 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 #define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs)      \
 do {   unsigned int *dest = &(__elf_regs[0]);          \
        struct pt_regs *src = (__pt_regs);              \
-       unsigned int *sp;                               \
+       unsigned int __user *sp;                        \
        int i;                                          \
        for(i = 0; i < 16; i++)                         \
                dest[i] = (unsigned int) src->u_regs[i];\
        /* Don't try this at home kids... */            \
-       sp = (unsigned int *) (src->u_regs[14] &        \
+       sp = (unsigned int __user *) (src->u_regs[14] & \
                0x00000000fffffffc);                    \
        for(i = 0; i < 16; i++)                         \
                __get_user(dest[i+16], &sp[i]);         \
index 2296525..97cf912 100644 (file)
@@ -72,7 +72,7 @@ struct mctrl_info {
        struct obp_mem_layout   layout_prop;
        int                     layout_size;
 
-       void                    *regs;
+       void __iomem            *regs;
 
        u64                     timing_control1;
        u64                     timing_control2;
index 9468eac..d50b755 100644 (file)
@@ -17,7 +17,8 @@
 
 #define                TASK_REGOFF             (THREAD_SIZE-TRACEREG_SZ-STACKFRAME_SZ)
 #define                ETRAP_PSTATE1           (PSTATE_RMO | PSTATE_PRIV)
-#define                ETRAP_PSTATE2           (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE)
+#define                ETRAP_PSTATE2           \
+               (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE)
 
 /*
  * On entry, %g7 is return address - 0x4.
                .text           
                .align  64
                .globl  etrap, etrap_irq, etraptl1
-etrap:         rdpr    %pil, %g2                                               ! Single        Group
+etrap:         rdpr    %pil, %g2
 etrap_irq:
-               rdpr    %tstate, %g1                                            ! Single        Group
-               sllx    %g2, 20, %g3                                            ! IEU0          Group
-               andcc   %g1, TSTATE_PRIV, %g0                                   ! IEU1
-               or      %g1, %g3, %g1                                           ! IEU0          Group
-               bne,pn  %xcc, 1f                                                ! CTI
-                sub    %sp, STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS, %g2          ! IEU1
-               wrpr    %g0, 7, %cleanwin                                       ! Single        Group+4bubbles
-
-               sethi   %hi(TASK_REGOFF), %g2                                   ! IEU0          Group           
-               sethi   %hi(TSTATE_PEF), %g3                                    ! IEU1
-               or      %g2, %lo(TASK_REGOFF), %g2                              ! IEU0          Group
-               and     %g1, %g3, %g3                                           ! IEU1
-               brnz,pn %g3, 1f                                                 ! CTI+IEU1      Group
-                add    %g6, %g2, %g2                                           ! IEU0
-               wr      %g0, 0, %fprs                                           ! Single        Group+4bubbles
-1:             rdpr    %tpc, %g3                                               ! Single        Group
-
-               stx     %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]               ! Store         Group
-               rdpr    %tnpc, %g1                                              ! Single        Group
-               stx     %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]                  ! Store         Group
-               rd      %y, %g3                                                 ! Single        Group+4bubbles
-               stx     %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]                 ! Store         Group
-               st      %g3, [%g2 + STACKFRAME_SZ + PT_V9_Y]                    ! Store         Group
-               save    %g2, -STACK_BIAS, %sp   ! Ordering here is critical     ! Single        Group
-               mov     %g6, %l6                                                ! IEU0          Group
-
-               bne,pn  %xcc, 3f                                                ! CTI           
-                mov    PRIMARY_CONTEXT, %l4                                    ! IEU1
-               rdpr    %canrestore, %g3                                        ! Single        Group+4bubbles
-               rdpr    %wstate, %g2                                            ! Single        Group+4bubbles
-               wrpr    %g0, 0, %canrestore                                     ! Single        Group+4bubbles
-               sll     %g2, 3, %g2                                             ! IEU0          Group
-               mov     1, %l5                                                  ! IEU1
-               stb     %l5, [%l6 + TI_FPDEPTH]                                 ! Store
-
-               wrpr    %g3, 0, %otherwin                                       ! Single        Group+4bubbles
-               wrpr    %g2, 0, %wstate                                         ! Single        Group+4bubbles
-               stxa    %g0, [%l4] ASI_DMMU                                     ! Store         Group
-               flush   %l6                                                     ! Single        Group+9bubbles
-               wr      %g0, ASI_AIUS, %asi                                     ! Single        Group+4bubbles
-2:             wrpr    %g0, 0x0, %tl                                           ! Single        Group+4bubbles
-               mov     %g4, %l4                                                ! IEU1
-               mov     %g5, %l5                                                ! IEU0          Group
-
-               mov     %g7, %l2                                                ! IEU1
-               wrpr    %g0, ETRAP_PSTATE1, %pstate                             ! Single        Group+4bubbles
-               stx     %g1, [%sp + PTREGS_OFF + PT_V9_G1]                      ! Store         Group
-               stx     %g2, [%sp + PTREGS_OFF + PT_V9_G2]                      ! Store         Group
-               stx     %g3, [%sp + PTREGS_OFF + PT_V9_G3]                      ! Store         Group
-               stx     %g4, [%sp + PTREGS_OFF + PT_V9_G4]                      ! Store         Group
-               stx     %g5, [%sp + PTREGS_OFF + PT_V9_G5]                      ! Store         Group
-               stx     %g6, [%sp + PTREGS_OFF + PT_V9_G6]                      ! Store         Group
-
-               stx     %g7, [%sp + PTREGS_OFF + PT_V9_G7]                      ! Store         Group
-               stx     %i0, [%sp + PTREGS_OFF + PT_V9_I0]                      ! Store         Group
-               stx     %i1, [%sp + PTREGS_OFF + PT_V9_I1]                      ! Store         Group
-               stx     %i2, [%sp + PTREGS_OFF + PT_V9_I2]                      ! Store         Group
-               stx     %i3, [%sp + PTREGS_OFF + PT_V9_I3]                      ! Store         Group
-               stx     %i4, [%sp + PTREGS_OFF + PT_V9_I4]                      ! Store         Group
-               stx     %i5, [%sp + PTREGS_OFF + PT_V9_I5]                      ! Store         Group
-
-               stx     %i6, [%sp + PTREGS_OFF + PT_V9_I6]                      ! Store         Group
-               stx     %i7, [%sp + PTREGS_OFF + PT_V9_I7]                      ! Store         Group
-               wrpr    %g0, ETRAP_PSTATE2, %pstate                             ! Single        Group+4bubbles
-               mov     %l6, %g6                                                ! IEU0
-               jmpl    %l2 + 0x4, %g0                                          ! CTI           Group
-                ldx    [%g6 + TI_TASK], %g4                                    ! Load
+               rdpr    %tstate, %g1
+               sllx    %g2, 20, %g3
+               andcc   %g1, TSTATE_PRIV, %g0
+               or      %g1, %g3, %g1
+               bne,pn  %xcc, 1f
+                sub    %sp, STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS, %g2
+               wrpr    %g0, 7, %cleanwin
+
+               sethi   %hi(TASK_REGOFF), %g2
+               sethi   %hi(TSTATE_PEF), %g3
+               or      %g2, %lo(TASK_REGOFF), %g2
+               and     %g1, %g3, %g3
+               brnz,pn %g3, 1f
+                add    %g6, %g2, %g2
+               wr      %g0, 0, %fprs
+1:             rdpr    %tpc, %g3
+
+               stx     %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]
+               rdpr    %tnpc, %g1
+               stx     %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]
+               rd      %y, %g3
+               stx     %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
+               st      %g3, [%g2 + STACKFRAME_SZ + PT_V9_Y]
+               save    %g2, -STACK_BIAS, %sp   ! Ordering here is critical
+               mov     %g6, %l6
+
+               bne,pn  %xcc, 3f
+                mov    PRIMARY_CONTEXT, %l4
+               rdpr    %canrestore, %g3
+               rdpr    %wstate, %g2
+               wrpr    %g0, 0, %canrestore
+               sll     %g2, 3, %g2
+               mov     1, %l5
+               stb     %l5, [%l6 + TI_FPDEPTH]
+
+               wrpr    %g3, 0, %otherwin
+               wrpr    %g2, 0, %wstate
+               stxa    %g0, [%l4] ASI_DMMU
+               flush   %l6
+               wr      %g0, ASI_AIUS, %asi
+2:             wrpr    %g0, 0x0, %tl
+               mov     %g4, %l4
+               mov     %g5, %l5
+
+               mov     %g7, %l2
+               wrpr    %g0, ETRAP_PSTATE1, %pstate
+               stx     %g1, [%sp + PTREGS_OFF + PT_V9_G1]
+               stx     %g2, [%sp + PTREGS_OFF + PT_V9_G2]
+               stx     %g3, [%sp + PTREGS_OFF + PT_V9_G3]
+               stx     %g4, [%sp + PTREGS_OFF + PT_V9_G4]
+               stx     %g5, [%sp + PTREGS_OFF + PT_V9_G5]
+               stx     %g6, [%sp + PTREGS_OFF + PT_V9_G6]
+
+               stx     %g7, [%sp + PTREGS_OFF + PT_V9_G7]
+               stx     %i0, [%sp + PTREGS_OFF + PT_V9_I0]
+               stx     %i1, [%sp + PTREGS_OFF + PT_V9_I1]
+               stx     %i2, [%sp + PTREGS_OFF + PT_V9_I2]
+               stx     %i3, [%sp + PTREGS_OFF + PT_V9_I3]
+               stx     %i4, [%sp + PTREGS_OFF + PT_V9_I4]
+               stx     %i5, [%sp + PTREGS_OFF + PT_V9_I5]
+
+               stx     %i6, [%sp + PTREGS_OFF + PT_V9_I6]
+               stx     %i7, [%sp + PTREGS_OFF + PT_V9_I7]
+               wrpr    %g0, ETRAP_PSTATE2, %pstate
+               mov     %l6, %g6
+               jmpl    %l2 + 0x4, %g0
+                ldx    [%g6 + TI_TASK], %g4
                nop
                nop
                nop
 
-3:             ldub    [%l6 + TI_FPDEPTH], %l5                                 ! Load          Group
-               add     %l6, TI_FPSAVED + 1, %l4                                ! IEU0
-               srl     %l5, 1, %l3                                             ! IEU0          Group
-               add     %l5, 2, %l5                                             ! IEU1
-               stb     %l5, [%l6 + TI_FPDEPTH]                                 ! Store
-               ba,pt   %xcc, 2b                                                ! CTI
-                stb    %g0, [%l4 + %l3]                                        ! Store         Group
+3:             ldub    [%l6 + TI_FPDEPTH], %l5
+               add     %l6, TI_FPSAVED + 1, %l4
+               srl     %l5, 1, %l3
+               add     %l5, 2, %l5
+               stb     %l5, [%l6 + TI_FPDEPTH]
+               ba,pt   %xcc, 2b
+                stb    %g0, [%l4 + %l3]
                nop
 
 etraptl1:      /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
-                * We place this right after pt_regs on the trap stack.  The layout
-                * is:
+                * We place this right after pt_regs on the trap stack.
+                * The layout is:
                 *      0x00    TL1's TSTATE
                 *      0x08    TL1's TPC
                 *      0x10    TL1's TNPC
@@ -166,81 +167,81 @@ etraptl1: /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
                wrpr    %g1, %tl
                stx     %g1, [%g2 + STACK_BIAS + 0x80]
 
-               rdpr    %tstate, %g1                                            ! Single        Group+4bubbles
-               sub     %g2, STACKFRAME_SZ + TRACEREG_SZ - STACK_BIAS, %g2      ! IEU1
-               ba,pt   %xcc, 1b                                                ! CTI           Group
-                andcc  %g1, TSTATE_PRIV, %g0                                   ! IEU0
+               rdpr    %tstate, %g1
+               sub     %g2, STACKFRAME_SZ + TRACEREG_SZ - STACK_BIAS, %g2
+               ba,pt   %xcc, 1b
+                andcc  %g1, TSTATE_PRIV, %g0
 
                .align  64
                .globl  scetrap
-scetrap:       rdpr    %pil, %g2                                               ! Single        Group
-               rdpr    %tstate, %g1                                            ! Single        Group
-               sllx    %g2, 20, %g3                                            ! IEU0          Group
-               andcc   %g1, TSTATE_PRIV, %g0                                   ! IEU1
-               or      %g1, %g3, %g1                                           ! IEU0          Group
-               bne,pn  %xcc, 1f                                                ! CTI
-                sub    %sp, (STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS), %g2        ! IEU1
-               wrpr    %g0, 7, %cleanwin                                       ! Single        Group+4bubbles
-
-               sllx    %g1, 51, %g3                                            ! IEU0          Group
-               sethi   %hi(TASK_REGOFF), %g2                                   ! IEU1
-               or      %g2, %lo(TASK_REGOFF), %g2                              ! IEU0          Group
-               brlz,pn %g3, 1f                                                 ! CTI+IEU1
-                add    %g6, %g2, %g2                                           ! IEU0          Group
-               wr      %g0, 0, %fprs                                           ! Single        Group+4bubbles
-1:             rdpr    %tpc, %g3                                               ! Single        Group
-               stx     %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]               ! Store         Group
-
-               rdpr    %tnpc, %g1                                              ! Single        Group
-               stx     %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]                  ! Store         Group
-               stx     %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]                 ! Store         Group
-               save    %g2, -STACK_BIAS, %sp   ! Ordering here is critical     ! Single        Group
-               mov     %g6, %l6                                                ! IEU0          Group
-               bne,pn  %xcc, 2f                                                ! CTI           
-                mov    ASI_P, %l7                                              ! IEU1
-               rdpr    %canrestore, %g3                                        ! Single        Group+4bubbles
-
-               rdpr    %wstate, %g2                                            ! Single        Group+4bubbles
-               wrpr    %g0, 0, %canrestore                                     ! Single        Group+4bubbles
-               sll     %g2, 3, %g2                                             ! IEU0          Group
-               mov     PRIMARY_CONTEXT, %l4                                    ! IEU1
-               wrpr    %g3, 0, %otherwin                                       ! Single        Group+4bubbles
-               wrpr    %g2, 0, %wstate                                         ! Single        Group+4bubbles
-               stxa    %g0, [%l4] ASI_DMMU                                     ! Store
-               flush   %l6                                                     ! Single        Group+9bubbles
-
-               mov     ASI_AIUS, %l7                                           ! IEU0          Group
-2:             mov     %g4, %l4                                                ! IEU1
-               mov     %g5, %l5                                                ! IEU0          Group
-               add     %g7, 0x4, %l2                                           ! IEU1
-               wrpr    %g0, ETRAP_PSTATE1, %pstate                             ! Single        Group+4bubbles
-               stx     %g1, [%sp + PTREGS_OFF + PT_V9_G1]                      ! Store         Group
-               stx     %g2, [%sp + PTREGS_OFF + PT_V9_G2]                      ! Store         Group
-               sllx    %l7, 24, %l7                                            ! IEU0
-
-               stx     %g3, [%sp + PTREGS_OFF + PT_V9_G3]                      ! Store         Group
-               rdpr    %cwp, %l0                                               ! Single        Group
-               stx     %g4, [%sp + PTREGS_OFF + PT_V9_G4]                      ! Store         Group
-               stx     %g5, [%sp + PTREGS_OFF + PT_V9_G5]                      ! Store         Group
-               stx     %g6, [%sp + PTREGS_OFF + PT_V9_G6]                      ! Store         Group
-               stx     %g7, [%sp + PTREGS_OFF + PT_V9_G7]                      ! Store         Group
-               or      %l7, %l0, %l7                                           ! IEU0
-               sethi   %hi(TSTATE_RMO | TSTATE_PEF), %l0                       ! IEU1
-
-               or      %l7, %l0, %l7                                           ! IEU0          Group
-               wrpr    %l2, %tnpc                                              ! Single        Group+4bubbles
-               wrpr    %l7, (TSTATE_PRIV | TSTATE_IE), %tstate                 ! Single        Group+4bubbles
-               stx     %i0, [%sp + PTREGS_OFF + PT_V9_I0]                      ! Store         Group
-               stx     %i1, [%sp + PTREGS_OFF + PT_V9_I1]                      ! Store         Group
-               stx     %i2, [%sp + PTREGS_OFF + PT_V9_I2]                      ! Store         Group
-               stx     %i3, [%sp + PTREGS_OFF + PT_V9_I3]                      ! Store         Group
-               stx     %i4, [%sp + PTREGS_OFF + PT_V9_I4]                      ! Store         Group
-
-               stx     %i5, [%sp + PTREGS_OFF + PT_V9_I5]                      ! Store         Group
-               stx     %i6, [%sp + PTREGS_OFF + PT_V9_I6]                      ! Store         Group
-               mov     %l6, %g6                                                ! IEU1
-               stx     %i7, [%sp + PTREGS_OFF + PT_V9_I7]                      ! Store         Group
-               ldx     [%g6 + TI_TASK], %g4                                    ! Load          Group
+scetrap:       rdpr    %pil, %g2
+               rdpr    %tstate, %g1
+               sllx    %g2, 20, %g3
+               andcc   %g1, TSTATE_PRIV, %g0
+               or      %g1, %g3, %g1
+               bne,pn  %xcc, 1f
+                sub    %sp, (STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS), %g2
+               wrpr    %g0, 7, %cleanwin
+
+               sllx    %g1, 51, %g3
+               sethi   %hi(TASK_REGOFF), %g2
+               or      %g2, %lo(TASK_REGOFF), %g2
+               brlz,pn %g3, 1f
+                add    %g6, %g2, %g2
+               wr      %g0, 0, %fprs
+1:             rdpr    %tpc, %g3
+               stx     %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]
+
+               rdpr    %tnpc, %g1
+               stx     %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]
+               stx     %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
+               save    %g2, -STACK_BIAS, %sp   ! Ordering here is critical
+               mov     %g6, %l6
+               bne,pn  %xcc, 2f
+                mov    ASI_P, %l7
+               rdpr    %canrestore, %g3
+
+               rdpr    %wstate, %g2
+               wrpr    %g0, 0, %canrestore
+               sll     %g2, 3, %g2
+               mov     PRIMARY_CONTEXT, %l4
+               wrpr    %g3, 0, %otherwin
+               wrpr    %g2, 0, %wstate
+               stxa    %g0, [%l4] ASI_DMMU
+               flush   %l6
+
+               mov     ASI_AIUS, %l7
+2:             mov     %g4, %l4
+               mov     %g5, %l5
+               add     %g7, 0x4, %l2
+               wrpr    %g0, ETRAP_PSTATE1, %pstate
+               stx     %g1, [%sp + PTREGS_OFF + PT_V9_G1]
+               stx     %g2, [%sp + PTREGS_OFF + PT_V9_G2]
+               sllx    %l7, 24, %l7
+
+               stx     %g3, [%sp + PTREGS_OFF + PT_V9_G3]
+               rdpr    %cwp, %l0
+               stx     %g4, [%sp + PTREGS_OFF + PT_V9_G4]
+               stx     %g5, [%sp + PTREGS_OFF + PT_V9_G5]
+               stx     %g6, [%sp + PTREGS_OFF + PT_V9_G6]
+               stx     %g7, [%sp + PTREGS_OFF + PT_V9_G7]
+               or      %l7, %l0, %l7
+               sethi   %hi(TSTATE_RMO | TSTATE_PEF), %l0
+
+               or      %l7, %l0, %l7
+               wrpr    %l2, %tnpc
+               wrpr    %l7, (TSTATE_PRIV | TSTATE_IE), %tstate
+               stx     %i0, [%sp + PTREGS_OFF + PT_V9_I0]
+               stx     %i1, [%sp + PTREGS_OFF + PT_V9_I1]
+               stx     %i2, [%sp + PTREGS_OFF + PT_V9_I2]
+               stx     %i3, [%sp + PTREGS_OFF + PT_V9_I3]
+               stx     %i4, [%sp + PTREGS_OFF + PT_V9_I4]
+
+               stx     %i5, [%sp + PTREGS_OFF + PT_V9_I5]
+               stx     %i6, [%sp + PTREGS_OFF + PT_V9_I6]
+               mov     %l6, %g6
+               stx     %i7, [%sp + PTREGS_OFF + PT_V9_I7]
+               ldx     [%g6 + TI_TASK], %g4
                done
                nop
                nop
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
new file mode 100644 (file)
index 0000000..bc5cc1d
--- /dev/null
@@ -0,0 +1,373 @@
+/* arch/sparc64/kernel/kprobes.c
+ *
+ * Copyright (C) 2004 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+
+#include <asm/kdebug.h>
+#include <asm/signal.h>
+
+/* We do not have hardware single-stepping on sparc64.
+ * So we implement software single-stepping with breakpoint
+ * traps.  The top-level scheme is similar to that used
+ * in the x86 kprobes implementation.
+ *
+ * In the kprobe->insn[] array we store the original
+ * instruction at index zero and a break instruction at
+ * index one.
+ *
+ * When we hit a kprobe we:
+ * - Run the pre-handler
+ * - Remember "regs->tnpc" and interrupt level stored in
+ *   "regs->tstate" so we can restore them later
+ * - Disable PIL interrupts
+ * - Set regs->tpc to point to kprobe->insn[0]
+ * - Set regs->tnpc to point to kprobe->insn[1]
+ * - Mark that we are actively in a kprobe
+ *
+ * At this point we wait for the second breakpoint at
+ * kprobe->insn[1] to hit.  When it does we:
+ * - Run the post-handler
+ * - Set regs->tpc to "remembered" regs->tnpc stored above,
+ *   restore the PIL interrupt level in "regs->tstate" as well
+ * - Make any adjustments necessary to regs->tnpc in order
+ *   to handle relative branches correctly.  See below.
+ * - Mark that we are no longer actively in a kprobe.
+ */
+
+void arch_prepare_kprobe(struct kprobe *p)
+{
+       p->insn[0] = *p->addr;
+       p->insn[1] = BREAKPOINT_INSTRUCTION_2;
+}
+
+/* kprobe_status settings */
+#define KPROBE_HIT_ACTIVE      0x00000001
+#define KPROBE_HIT_SS          0x00000002
+
+static struct kprobe *current_kprobe;
+static unsigned long current_kprobe_orig_tnpc;
+static unsigned long current_kprobe_orig_tstate_pil;
+static unsigned int kprobe_status;
+
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+       current_kprobe_orig_tnpc = regs->tnpc;
+       current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
+       regs->tstate |= TSTATE_PIL;
+
+       regs->tpc = (unsigned long) &p->insn[0];
+       regs->tnpc = (unsigned long) &p->insn[1];
+}
+
+static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
+{
+       *p->addr = p->opcode;
+       flushi(p->addr);
+
+       regs->tpc = (unsigned long) p->addr;
+       regs->tnpc = current_kprobe_orig_tnpc;
+       regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
+                       current_kprobe_orig_tstate_pil);
+}
+
+static int kprobe_handler(struct pt_regs *regs)
+{
+       struct kprobe *p;
+       void *addr = (void *) regs->tpc;
+       int ret = 0;
+
+       preempt_disable();
+
+       if (kprobe_running()) {
+               /* We *are* holding lock here, so this is safe.
+                * Disarm the probe we just hit, and ignore it.
+                */
+               p = get_kprobe(addr);
+               if (p) {
+                       disarm_kprobe(p, regs);
+                       ret = 1;
+               } else {
+                       p = current_kprobe;
+                       if (p->break_handler && p->break_handler(p, regs))
+                               goto ss_probe;
+               }
+               /* If it's not ours, can't be delete race, (we hold lock). */
+               goto no_kprobe;
+       }
+
+       lock_kprobes();
+       p = get_kprobe(addr);
+       if (!p) {
+               unlock_kprobes();
+               if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) {
+                       /*
+                        * The breakpoint instruction was removed right
+                        * after we hit it.  Another cpu has removed
+                        * either a probepoint or a debugger breakpoint
+                        * at this address.  In either case, no further
+                        * handling of this interrupt is appropriate.
+                        */
+                       ret = 1;
+               }
+               /* Not one of ours: let kernel handle it */
+               goto no_kprobe;
+       }
+
+       kprobe_status = KPROBE_HIT_ACTIVE;
+       current_kprobe = p;
+       if (p->pre_handler(p, regs))
+               return 1;
+
+ss_probe:
+       prepare_singlestep(p, regs);
+       kprobe_status = KPROBE_HIT_SS;
+       return 1;
+
+no_kprobe:
+       preempt_enable_no_resched();
+       return ret;
+}
+
+/* If INSN is a relative control transfer instruction,
+ * return the corrected branch destination value.
+ *
+ * The original INSN location was REAL_PC, it actually
+ * executed at PC and produced destination address NPC.
+ */
+static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc,
+                                    unsigned long pc, unsigned long npc)
+{
+       /* Branch not taken, no mods necessary.  */
+       if (npc == pc + 0x4UL)
+               return real_pc + 0x4UL;
+
+       /* The three cases are call, branch w/prediction,
+        * and traditional branch.
+        */
+       if ((insn & 0xc0000000) == 0x40000000 ||
+           (insn & 0xc1c00000) == 0x00400000 ||
+           (insn & 0xc1c00000) == 0x00800000) {
+               /* The instruction did all the work for us
+                * already, just apply the offset to the correct
+                * instruction location.
+                */
+               return (real_pc + (npc - pc));
+       }
+
+       return real_pc + 0x4UL;
+}
+
+/* If INSN is an instruction which writes it's PC location
+ * into a destination register, fix that up.
+ */
+static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc)
+{
+       unsigned long *slot = NULL;
+
+       /* Simplest cast is call, which always uses %o7 */
+       if ((insn & 0xc0000000) == 0x40000000) {
+               slot = &regs->u_regs[UREG_I7];
+       }
+
+       /* Jmpl encodes the register inside of the opcode */
+       if ((insn & 0xc1f80000) == 0x81c00000) {
+               unsigned long rd = ((insn >> 25) & 0x1f);
+
+               if (rd <= 15) {
+                       slot = &regs->u_regs[rd];
+               } else {
+                       /* Hard case, it goes onto the stack. */
+                       flushw_all();
+
+                       rd -= 16;
+                       slot = (unsigned long *)
+                               (regs->u_regs[UREG_FP] + STACK_BIAS);
+                       slot += rd;
+               }
+       }
+       if (slot != NULL)
+               *slot = real_pc;
+}
+
+/*
+ * Called after single-stepping.  p->addr is the address of the
+ * instruction whose first byte has been replaced by the breakpoint
+ * instruction.  To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction.  The address of this
+ * copy is p->insn.
+ *
+ * This function prepares to return from the post-single-step
+ * breakpoint trap.
+ */
+static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+       u32 insn = p->insn[0];
+
+       regs->tpc = current_kprobe_orig_tnpc;
+       regs->tnpc = relbranch_fixup(insn,
+                                    (unsigned long) p->addr,
+                                    (unsigned long) &p->insn[0],
+                                    regs->tnpc);
+       retpc_fixup(regs, insn, (unsigned long) p->addr);
+
+       regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
+                       current_kprobe_orig_tstate_pil);
+}
+
+static inline int post_kprobe_handler(struct pt_regs *regs)
+{
+       if (!kprobe_running())
+               return 0;
+
+       if (current_kprobe->post_handler)
+               current_kprobe->post_handler(current_kprobe, regs, 0);
+
+       resume_execution(current_kprobe, regs);
+
+       unlock_kprobes();
+       preempt_enable_no_resched();
+
+       return 1;
+}
+
+/* Interrupts disabled, kprobe_lock held. */
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+       if (current_kprobe->fault_handler
+           && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+               return 1;
+
+       if (kprobe_status & KPROBE_HIT_SS) {
+               resume_execution(current_kprobe, regs);
+
+               unlock_kprobes();
+               preempt_enable_no_resched();
+       }
+       return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
+                            void *data)
+{
+       struct die_args *args = (struct die_args *)data;
+       switch (val) {
+       case DIE_DEBUG:
+               if (kprobe_handler(args->regs))
+                       return NOTIFY_STOP;
+               break;
+       case DIE_DEBUG_2:
+               if (post_kprobe_handler(args->regs))
+                       return NOTIFY_STOP;
+               break;
+       case DIE_GPF:
+               if (kprobe_running() &&
+                   kprobe_fault_handler(args->regs, args->trapnr))
+                       return NOTIFY_STOP;
+               break;
+       case DIE_PAGE_FAULT:
+               if (kprobe_running() &&
+                   kprobe_fault_handler(args->regs, args->trapnr))
+                       return NOTIFY_STOP;
+               break;
+       default:
+               break;
+       }
+       return NOTIFY_DONE;
+}
+
+asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs)
+{
+       BUG_ON(trap_level != 0x170 && trap_level != 0x171);
+
+       if (user_mode(regs)) {
+               local_irq_enable();
+               bad_trap(regs, trap_level);
+               return;
+       }
+
+       /* trap_level == 0x170 --> ta 0x70
+        * trap_level == 0x171 --> ta 0x71
+        */
+       if (notify_die((trap_level == 0x170) ? DIE_DEBUG : DIE_DEBUG_2,
+                      (trap_level == 0x170) ? "debug" : "debug_2",
+                      regs, 0, trap_level, SIGTRAP) != NOTIFY_STOP)
+               bad_trap(regs, trap_level);
+}
+
+/* Jprobes support.  */
+static struct pt_regs jprobe_saved_regs;
+static struct pt_regs *jprobe_saved_regs_location;
+static struct sparc_stackf jprobe_saved_stack;
+
+int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       struct jprobe *jp = container_of(p, struct jprobe, kp);
+
+       jprobe_saved_regs_location = regs;
+       memcpy(&jprobe_saved_regs, regs, sizeof(*regs));
+
+       /* Save a whole stack frame, this gets arguments
+        * pushed onto the stack after using up all the
+        * arg registers.
+        */
+       memcpy(&jprobe_saved_stack,
+              (char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
+              sizeof(jprobe_saved_stack));
+
+       regs->tpc  = (unsigned long) jp->entry;
+       regs->tnpc = ((unsigned long) jp->entry) + 0x4UL;
+       regs->tstate |= TSTATE_PIL;
+
+       return 1;
+}
+
+void jprobe_return(void)
+{
+       preempt_enable_no_resched();
+       __asm__ __volatile__(
+               ".globl jprobe_return_trap_instruction\n"
+"jprobe_return_trap_instruction:\n\t"
+               "ta 0x70");
+}
+
+extern void jprobe_return_trap_instruction(void);
+
+extern void __show_regs(struct pt_regs * regs);
+
+int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       u32 *addr = (u32 *) regs->tpc;
+
+       if (addr == (u32 *) jprobe_return_trap_instruction) {
+               if (jprobe_saved_regs_location != regs) {
+                       printk("JPROBE: Current regs (%p) does not match "
+                              "saved regs (%p).\n",
+                              regs, jprobe_saved_regs_location);
+                       printk("JPROBE: Saved registers\n");
+                       __show_regs(jprobe_saved_regs_location);
+                       printk("JPROBE: Current registers\n");
+                       __show_regs(regs);
+                       BUG();
+               }
+               /* Restore old register state.  Do pt_regs
+                * first so that UREG_FP is the original one for
+                * the stack frame restore.
+                */
+               memcpy(regs, &jprobe_saved_regs, sizeof(*regs));
+
+               memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
+                      &jprobe_saved_stack,
+                      sizeof(jprobe_saved_stack));
+
+               return 1;
+       }
+       return 0;
+}
index fda6524..58310aa 100644 (file)
  */
 void __init pci_fixup_host_bridge_self(struct pci_bus *pbus)
 {
-       struct list_head *walk = &pbus->devices;
-
-       walk = walk->next;
-       while (walk != &pbus->devices) {
-               struct pci_dev *pdev = pci_dev_b(walk);
+       struct pci_dev *pdev;
 
+       list_for_each_entry(pdev, &pbus->devices, bus_list) {
                if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) {
                        pbus->self = pdev;
                        return;
                }
-
-               walk = walk->next;
        }
 
        prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n");
@@ -217,31 +212,18 @@ void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus,
                                    struct pci_pbm_info *pbm,
                                    int prom_node)
 {
-       struct list_head *walk = &pbus->devices;
-
-       /* This loop is coded like this because the cookie
-        * fillin routine can delete devices from the tree.
-        */
-       walk = walk->next;
-       while (walk != &pbus->devices) {
-               struct pci_dev *pdev = pci_dev_b(walk);
-               struct list_head *walk_next = walk->next;
+       struct pci_dev *pdev, *pdev_next;
+       struct pci_bus *this_pbus, *pbus_next;
 
+       /* This must be _safe because the cookie fillin
+          routine can delete devices from the tree.  */
+       list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list)
                pdev_cookie_fillin(pbm, pdev, prom_node);
 
-               walk = walk_next;
-       }
-
-       walk = &pbus->children;
-       walk = walk->next;
-       while (walk != &pbus->children) {
-               struct pci_bus *this_pbus = pci_bus_b(walk);
+       list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) {
                struct pcidev_cookie *pcp = this_pbus->self->sysdata;
-               struct list_head *walk_next = walk->next;
 
                pci_fill_in_pbm_cookies(this_pbus, pbm, pcp->prom_node);
-
-               walk = walk_next;
        }
 }
 
@@ -431,14 +413,14 @@ static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
 void __init pci_record_assignments(struct pci_pbm_info *pbm,
                                   struct pci_bus *pbus)
 {
-       struct list_head *walk = &pbus->devices;
+       struct pci_dev *dev;
+       struct pci_bus *bus;
 
-       for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-               pdev_record_assignments(pbm, pci_dev_b(walk));
+       list_for_each_entry(dev, &pbus->devices, bus_list)
+               pdev_record_assignments(pbm, dev);
 
-       walk = &pbus->children;
-       for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-               pci_record_assignments(pbm, pci_bus_b(walk));
+       list_for_each_entry(bus, &pbus->children, node)
+               pci_record_assignments(pbm, bus);
 }
 
 /* Return non-zero if PDEV has implicit I/O resources even
@@ -549,14 +531,14 @@ static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm,
 void __init pci_assign_unassigned(struct pci_pbm_info *pbm,
                                  struct pci_bus *pbus)
 {
-       struct list_head *walk = &pbus->devices;
+       struct pci_dev *dev;
+       struct pci_bus *bus;
 
-       for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-               pdev_assign_unassigned(pbm, pci_dev_b(walk));
+       list_for_each_entry(dev, &pbus->devices, bus_list)
+               pdev_assign_unassigned(pbm, dev);
 
-       walk = &pbus->children;
-       for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-               pci_assign_unassigned(pbm, pci_bus_b(walk));
+       list_for_each_entry(bus, &pbus->children, node)
+               pci_assign_unassigned(pbm, bus);
 }
 
 static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt)
@@ -797,14 +779,14 @@ have_irq:
 void __init pci_fixup_irq(struct pci_pbm_info *pbm,
                          struct pci_bus *pbus)
 {
-       struct list_head *walk = &pbus->devices;
+       struct pci_dev *dev;
+       struct pci_bus *bus;
 
-       for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-               pdev_fixup_irq(pci_dev_b(walk));
+       list_for_each_entry(dev, &pbus->devices, bus_list)
+               pdev_fixup_irq(dev);
 
-       walk = &pbus->children;
-       for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-               pci_fixup_irq(pbm, pci_bus_b(walk));
+       list_for_each_entry(bus, &pbus->children, node)
+               pci_fixup_irq(pbm, bus);
 }
 
 static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz)
@@ -897,7 +879,7 @@ static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz)
 void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm,
                                     struct pci_bus *pbus)
 {
-       struct list_head *walk;
+       struct pci_dev *pdev;
        int all_are_66mhz;
        u16 status;
 
@@ -906,11 +888,8 @@ void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm,
                goto out;
        }
 
-       walk = &pbus->devices;
        all_are_66mhz = 1;
-       for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-               struct pci_dev *pdev = pci_dev_b(walk);
-
+       list_for_each_entry(pdev, &pbus->devices, bus_list) {
                pci_read_config_word(pdev, PCI_STATUS, &status);
                if (!(status & PCI_STATUS_66MHZ)) {
                        all_are_66mhz = 0;
@@ -929,17 +908,17 @@ out:
 void pci_setup_busmastering(struct pci_pbm_info *pbm,
                            struct pci_bus *pbus)
 {
-       struct list_head *walk = &pbus->devices;
+       struct pci_dev *dev;
+       struct pci_bus *bus;
        int is_66mhz;
 
        is_66mhz = pbm->is_66mhz_capable && pbm->all_devs_66mhz;
 
-       for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-               pdev_setup_busmastering(pci_dev_b(walk), is_66mhz);
+       list_for_each_entry(dev, &pbus->devices, bus_list)
+               pdev_setup_busmastering(dev, is_66mhz);
 
-       walk = &pbus->children;
-       for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-               pci_setup_busmastering(pbm, pci_bus_b(walk));
+       list_for_each_entry(bus, &pbus->children, node)
+               pci_setup_busmastering(pbm, bus);
 }
 
 void pci_register_legacy_regions(struct resource *io_res,
@@ -987,10 +966,10 @@ void pci_scan_for_target_abort(struct pci_controller_info *p,
                               struct pci_pbm_info *pbm,
                               struct pci_bus *pbus)
 {
-       struct list_head *walk = &pbus->devices;
+       struct pci_dev *pdev;
+       struct pci_bus *bus;
 
-       for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-               struct pci_dev *pdev = pci_dev_b(walk);
+       list_for_each_entry(pdev, &pbus->devices, bus_list) {
                u16 status, error_bits;
 
                pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -1005,19 +984,18 @@ void pci_scan_for_target_abort(struct pci_controller_info *p,
                }
        }
 
-       walk = &pbus->children;
-       for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-               pci_scan_for_target_abort(p, pbm, pci_bus_b(walk));
+       list_for_each_entry(bus, &pbus->children, node)
+               pci_scan_for_target_abort(p, pbm, bus);
 }
 
 void pci_scan_for_master_abort(struct pci_controller_info *p,
                               struct pci_pbm_info *pbm,
                               struct pci_bus *pbus)
 {
-       struct list_head *walk = &pbus->devices;
+       struct pci_dev *pdev;
+       struct pci_bus *bus;
 
-       for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-               struct pci_dev *pdev = pci_dev_b(walk);
+       list_for_each_entry(pdev, &pbus->devices, bus_list) {
                u16 status, error_bits;
 
                pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -1031,19 +1009,18 @@ void pci_scan_for_master_abort(struct pci_controller_info *p,
                }
        }
 
-       walk = &pbus->children;
-       for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-               pci_scan_for_master_abort(p, pbm, pci_bus_b(walk));
+       list_for_each_entry(bus, &pbus->children, node)
+               pci_scan_for_master_abort(p, pbm, bus);
 }
 
 void pci_scan_for_parity_error(struct pci_controller_info *p,
                               struct pci_pbm_info *pbm,
                               struct pci_bus *pbus)
 {
-       struct list_head *walk = &pbus->devices;
+       struct pci_dev *pdev;
+       struct pci_bus *bus;
 
-       for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-               struct pci_dev *pdev = pci_dev_b(walk);
+       list_for_each_entry(pdev, &pbus->devices, bus_list) {
                u16 status, error_bits;
 
                pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -1058,7 +1035,6 @@ void pci_scan_for_parity_error(struct pci_controller_info *p,
                }
        }
 
-       walk = &pbus->children;
-       for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-               pci_scan_for_parity_error(p, pbm, pci_bus_b(walk));
+       list_for_each_entry(bus, &pbus->children, node)
+               pci_scan_for_parity_error(p, pbm, bus);
 }
index 302a0a2..6c32059 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/spinlock.h>
 #include <asm/io.h>
 
-extern spinlock_t pci_controller_lock;
 extern struct pci_controller_info *pci_controller_root;
 
 extern int pci_num_controllers;
index cca82a1..94a5298 100644 (file)
@@ -56,6 +56,39 @@ static void __iommu_flushall(struct pci_iommu *iommu)
        }
 }
 
+#define IOPTE_CONSISTENT(CTX) \
+       (IOPTE_VALID | IOPTE_CACHE | \
+        (((CTX) << 47) & IOPTE_CONTEXT))
+
+#define IOPTE_STREAMING(CTX) \
+       (IOPTE_CONSISTENT(CTX) | IOPTE_STBUF)
+
+/* Existing mappings are never marked invalid, instead they
+ * are pointed to a dummy page.
+ */
+#define IOPTE_IS_DUMMY(iommu, iopte)   \
+       ((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa)
+
+static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte)
+{
+       unsigned long val = iopte_val(*iopte);
+
+       val &= ~IOPTE_PAGE;
+       val |= iommu->dummy_page_pa;
+
+       iopte_val(*iopte) = val;
+}
+
+void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize)
+{
+       int i;
+
+       tsbsize /= sizeof(iopte_t);
+
+       for (i = 0; i < tsbsize; i++)
+               iopte_make_dummy(iommu, &iommu->page_table[i]);
+}
+
 static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages)
 {
        iopte_t *iopte, *limit, *first;
@@ -79,7 +112,7 @@ static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long n
        
        first = iopte;
        for (;;) {
-               if (iopte_val(*iopte) == 0UL) {
+               if (IOPTE_IS_DUMMY(iommu, iopte)) {
                        if ((iopte + (1 << cnum)) >= limit)
                                ent = 0;
                        else
@@ -142,12 +175,12 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long
        iopte = iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS));
        while (iopte > iommu->page_table) {
                iopte--;
-               if (!(iopte_val(*iopte) & IOPTE_VALID)) {
+               if (IOPTE_IS_DUMMY(iommu, iopte)) {
                        unsigned long tmp = npages;
 
                        while (--tmp) {
                                iopte--;
-                               if (iopte_val(*iopte) & IOPTE_VALID)
+                               if (!IOPTE_IS_DUMMY(iommu, iopte))
                                        break;
                        }
                        if (tmp == 0) {
@@ -162,15 +195,6 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long
        return NULL;
 }
 
-#define IOPTE_CONSISTENT(CTX) \
-       (IOPTE_VALID | IOPTE_CACHE | \
-        (((CTX) << 47) & IOPTE_CONTEXT))
-
-#define IOPTE_STREAMING(CTX) \
-       (IOPTE_CONSISTENT(CTX) | IOPTE_STBUF)
-
-#define IOPTE_INVALID  0UL
-
 /* Allocate and map kernel buffer of size SIZE using consistent mode
  * DMA for PCI device PDEV.  Return non-NULL cpu-side address if
  * successful and set *DMA_ADDRP to the PCI side dma address.
@@ -261,7 +285,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
                limit = (iommu->page_table +
                         (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
                while (walk < limit) {
-                       if (iopte_val(*walk) != IOPTE_INVALID)
+                       if (!IOPTE_IS_DUMMY(iommu, walk))
                                break;
                        walk++;
                }
@@ -280,7 +304,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
                ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
 
        for (i = 0; i < npages; i++, iopte++)
-               iopte_val(*iopte) = IOPTE_INVALID;
+               iopte_make_dummy(iommu, iopte);
 
        if (iommu->iommu_ctxflush) {
                pci_iommu_write(iommu->iommu_ctxflush, ctx);
@@ -376,7 +400,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
        base = iommu->page_table +
                ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 #ifdef DEBUG_PCI_IOMMU
-       if (iopte_val(*base) == IOPTE_INVALID)
+       if (IOPTE_IS_DUMMY(iommu, base))
                printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n",
                       bus_addr, sz, __builtin_return_address(0));
 #endif
@@ -415,7 +439,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
        }
 
        /* Step 2: Clear out first TSB entry. */
-       iopte_val(*base) = IOPTE_INVALID;
+       iopte_make_dummy(iommu, base);
 
        free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
                               npages, ctx);
@@ -611,7 +635,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
                ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
 #ifdef DEBUG_PCI_IOMMU
-       if (iopte_val(*base) == IOPTE_INVALID)
+       if (IOPTE_IS_DUMMY(iommu, base))
                printk("pci_unmap_sg called on non-mapped region %016lx,%d from %016lx\n", sglist->dma_address, nelems, __builtin_return_address(0));
 #endif
 
@@ -648,7 +672,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
        }
 
        /* Step 2: Clear out first TSB entry. */
-       iopte_val(*base) = IOPTE_INVALID;
+       iopte_make_dummy(iommu, base);
 
        free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
                               npages, ctx);
index 6a266a7..2bf2477 100644 (file)
@@ -1113,10 +1113,9 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
 
 static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
 {
-       struct list_head *walk = &sabre_bus->devices;
+       struct pci_dev *pdev;
 
-       for (walk = walk->next; walk != &sabre_bus->devices; walk = walk->next) {
-               struct pci_dev *pdev = pci_dev_b(walk);
+       list_for_each_entry(pdev, &sabre_bus->devices, bus_list) {
 
                if (pdev->vendor == PCI_VENDOR_ID_SUN &&
                    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
@@ -1178,10 +1177,9 @@ static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm)
 static void __init sabre_scan_bus(struct pci_controller_info *p)
 {
        static int once;
-       struct pci_bus *sabre_bus;
+       struct pci_bus *sabre_bus, *pbus;
        struct pci_pbm_info *pbm;
        struct pcidev_cookie *cookie;
-       struct list_head *walk;
        int sabres_scanned;
 
        /* The APB bridge speaks to the Sabre host PCI bridge
@@ -1217,9 +1215,7 @@ static void __init sabre_scan_bus(struct pci_controller_info *p)
 
        sabres_scanned = 0;
 
-       walk = &sabre_bus->children;
-       for (walk = walk->next; walk != &sabre_bus->children; walk = walk->next) {
-               struct pci_bus *pbus = pci_bus_b(walk);
+       list_for_each_entry(pbus, &sabre_bus->children, node) {
 
                if (pbus->number == p->pbm_A.pci_first_busno) {
                        pbm = &p->pbm_A;
@@ -1293,6 +1289,14 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
         * in pci_iommu.c
         */
 
+       iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
+       if (!iommu->dummy_page) {
+               prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
+               prom_halt();
+       }
+       memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+       iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+
        tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8));
        if (!tsbbase) {
                prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n");
@@ -1301,7 +1305,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
        iommu->page_table = (iopte_t *)tsbbase;
        iommu->page_table_map_base = dvma_offset;
        iommu->dma_addr_mask = dma_mask;
-       memset((char *)tsbbase, 0, PAGE_SIZE << order);
+       pci_iommu_table_init(iommu, PAGE_SIZE << order);
 
        sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
 
@@ -1546,7 +1550,6 @@ void __init sabre_init(int pnode, char *model_name)
        struct linux_prom64_registers pr_regs[2];
        struct pci_controller_info *p;
        struct pci_iommu *iommu;
-       unsigned long flags;
        int tsbsize, err;
        u32 busrange[2];
        u32 vdma[2];
@@ -1594,10 +1597,8 @@ void __init sabre_init(int pnode, char *model_name)
 
        upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);
 
-       spin_lock_irqsave(&pci_controller_lock, flags);
        p->next = pci_controller_root;
        pci_controller_root = p;
-       spin_unlock_irqrestore(&pci_controller_lock, flags);
 
        p->pbm_A.portid = upa_portid;
        p->pbm_B.portid = upa_portid;
index 40f7919..491bb36 100644 (file)
@@ -158,7 +158,7 @@ tl0_resv164:        BTRAP(0x164) BTRAP(0x165) BTRAP(0x166) BTRAP(0x167) BTRAP(0x168)
 tl0_resv169:   BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c)
 tl0_linux64:   LINUX_64BIT_SYSCALL_TRAP
 tl0_gsctx:     TRAP(sparc64_get_context) TRAP(sparc64_set_context)
-tl0_resv170:   BTRAP(0x170) BTRAP(0x171) BTRAP(0x172)
+tl0_resv170:   KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) BTRAP(0x172)
 tl0_resv173:   BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
 tl0_resv178:   BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c)
 tl0_resv17d:   BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f)
index 8faeee0..a710d38 100644 (file)
@@ -16,6 +16,7 @@ SECTIONS
   {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
     *(.gnu.warning)
   } =0
   _etext = .;
@@ -52,9 +53,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
        *(.initcall1.init) 
index b64aee9..3008d53 100644 (file)
@@ -7,7 +7,7 @@
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
-void outsb(unsigned long addr, const void *src, unsigned long count)
+void outsb(void __iomem *addr, const void *src, unsigned long count)
 {
        const u8 *p = src;
 
@@ -15,7 +15,7 @@ void outsb(unsigned long addr, const void *src, unsigned long count)
                outb(*p++, addr);
 }
 
-void outsw(unsigned long addr, const void *src, unsigned long count)
+void outsw(void __iomem *addr, const void *src, unsigned long count)
 {
        if(count) {
                u16 *ps = (u16 *)src;
@@ -44,7 +44,7 @@ void outsw(unsigned long addr, const void *src, unsigned long count)
        }
 }
 
-void outsl(unsigned long addr, const void *src, unsigned long count)
+void outsl(void __iomem *addr, const void *src, unsigned long count)
 {
        if(count) {
                if((((u64)src) & 0x3) == 0) {
@@ -119,7 +119,7 @@ void outsl(unsigned long addr, const void *src, unsigned long count)
        }
 }
 
-void insb(unsigned long addr, void *dst, unsigned long count)
+void insb(void __iomem *addr, void *dst, unsigned long count)
 {
        if(count) {
                u32 *pi;
@@ -144,7 +144,7 @@ void insb(unsigned long addr, void *dst, unsigned long count)
        }
 }
 
-void insw(unsigned long addr, void *dst, unsigned long count)
+void insw(void __iomem *addr, void *dst, unsigned long count)
 {
        if(count) {
                u16 *ps = dst;
@@ -169,7 +169,7 @@ void insw(unsigned long addr, void *dst, unsigned long count)
        }
 }
 
-void insl(unsigned long addr, void *dst, unsigned long count)
+void insl(void __iomem *addr, void *dst, unsigned long count)
 {
        if(count) {
                if((((unsigned long)dst) & 0x3) == 0) {
diff --git a/arch/sparc64/lib/U1copy_from_user.S b/arch/sparc64/lib/U1copy_from_user.S
new file mode 100644 (file)
index 0000000..93146a8
--- /dev/null
@@ -0,0 +1,33 @@
+/* U1copy_from_user.S: UltraSparc-I/II/IIi/IIe optimized copy from userspace.
+ *
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
+ */
+
+#define EX_LD(x)               \
+98:    x;                      \
+       .section .fixup;        \
+       .align 4;               \
+99:    retl;                   \
+        mov    1, %o0;         \
+       .section __ex_table;    \
+       .align 4;               \
+       .word 98b, 99b;         \
+       .text;                  \
+       .align 4;
+
+#define FUNC_NAME              ___copy_from_user
+#define LOAD(type,addr,dest)   type##a [addr] %asi, dest
+#define LOAD_BLK(addr,dest)    ldda [addr] ASI_BLK_AIUS, dest
+#define EX_RETVAL(x)           0
+
+       /* Writing to %asi is _expensive_ so we hardcode it.
+        * Reading %asi to check for KERNEL_DS is comparatively
+        * cheap.
+        */
+#define PREAMBLE                                       \
+       rd              %asi, %g1;                      \
+       cmp             %g1, ASI_AIUS;                  \
+       bne,pn          %icc, memcpy_user_stub;         \
+        nop;                                           \
+
+#include "U1memcpy.S"
diff --git a/arch/sparc64/lib/U1copy_to_user.S b/arch/sparc64/lib/U1copy_to_user.S
new file mode 100644 (file)
index 0000000..1fccc52
--- /dev/null
@@ -0,0 +1,33 @@
+/* U1copy_to_user.S: UltraSparc-I/II/IIi/IIe optimized copy to userspace.
+ *
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
+ */
+
+#define EX_ST(x)               \
+98:    x;                      \
+       .section .fixup;        \
+       .align 4;               \
+99:    retl;                   \
+        mov    1, %o0;         \
+       .section __ex_table;    \
+       .align 4;               \
+       .word 98b, 99b;         \
+       .text;                  \
+       .align 4;
+
+#define FUNC_NAME              ___copy_to_user
+#define STORE(type,src,addr)   type##a src, [addr] ASI_AIUS
+#define STORE_BLK(src,addr)    stda src, [addr] ASI_BLK_AIUS
+#define EX_RETVAL(x)           0
+
+       /* Writing to %asi is _expensive_ so we hardcode it.
+        * Reading %asi to check for KERNEL_DS is comparatively
+        * cheap.
+        */
+#define PREAMBLE                                       \
+       rd              %asi, %g1;                      \
+       cmp             %g1, ASI_AIUS;                  \
+       bne,pn          %icc, memcpy_user_stub;         \
+        nop;                                           \
+
+#include "U1memcpy.S"
diff --git a/arch/sparc64/lib/U1memcpy.S b/arch/sparc64/lib/U1memcpy.S
new file mode 100644 (file)
index 0000000..06a5bd2
--- /dev/null
@@ -0,0 +1,555 @@
+/* U1memcpy.S: UltraSPARC-I/II/IIi/IIe optimized memcpy.
+ *
+ * Copyright (C) 1997, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#ifdef __KERNEL__
+#include <asm/visasm.h>
+#include <asm/asi.h>
+#else
+#define ASI_BLK_P 0xf0
+#define FPRS_FEF  0x04
+#ifdef MEMCPY_DEBUG
+#define VISEntry rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \
+                clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0;
+#define VISExit and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#else
+#define VISEntry rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
+#define VISExit and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#endif
+#endif
+
+#ifndef EX_LD
+#define EX_LD(x)       x
+#endif
+
+#ifndef EX_ST
+#define EX_ST(x)       x
+#endif
+
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)   x
+#endif
+
+#ifndef LOAD
+#define LOAD(type,addr,dest)   type [addr], dest
+#endif
+
+#ifndef LOAD_BLK
+#define LOAD_BLK(addr,dest)    ldda [addr] ASI_BLK_P, dest
+#endif
+
+#ifndef STORE
+#define STORE(type,src,addr)   type src, [addr]
+#endif
+
+#ifndef STORE_BLK
+#define STORE_BLK(src,addr)    stda src, [addr] ASI_BLK_P
+#endif
+
+#ifndef FUNC_NAME
+#define FUNC_NAME      memcpy
+#endif
+
+#ifndef PREAMBLE
+#define PREAMBLE
+#endif
+
+#ifndef XCC
+#define XCC xcc
+#endif
+
+#define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9)          \
+       faligndata              %f1, %f2, %f48;                 \
+       faligndata              %f2, %f3, %f50;                 \
+       faligndata              %f3, %f4, %f52;                 \
+       faligndata              %f4, %f5, %f54;                 \
+       faligndata              %f5, %f6, %f56;                 \
+       faligndata              %f6, %f7, %f58;                 \
+       faligndata              %f7, %f8, %f60;                 \
+       faligndata              %f8, %f9, %f62;
+
+#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt)   \
+       EX_LD(LOAD_BLK(%src, %fdest));                          \
+       EX_ST(STORE_BLK(%fsrc, %dest));                         \
+       add                     %src, 0x40, %src;               \
+       subcc                   %len, 0x40, %len;               \
+       be,pn                   %xcc, jmptgt;                   \
+        add                    %dest, 0x40, %dest;             \
+
+#define LOOP_CHUNK1(src, dest, len, branch_dest)               \
+       MAIN_LOOP_CHUNK(src, dest, f0,  f48, len, branch_dest)
+#define LOOP_CHUNK2(src, dest, len, branch_dest)               \
+       MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest)
+#define LOOP_CHUNK3(src, dest, len, branch_dest)               \
+       MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest)
+
+#define STORE_SYNC(dest, fsrc)                         \
+       EX_ST(STORE_BLK(%fsrc, %dest));                 \
+       add                     %dest, 0x40, %dest;
+
+#define STORE_JUMP(dest, fsrc, target)                 \
+       EX_ST(STORE_BLK(%fsrc, %dest));                 \
+       add                     %dest, 0x40, %dest;     \
+       ba,pt                   %xcc, target;
+
+#define FINISH_VISCHUNK(dest, f0, f1, left)    \
+       subcc                   %left, 8, %left;\
+       bl,pn                   %xcc, 95f;      \
+        faligndata             %f0, %f1, %f48; \
+       EX_ST(STORE(std, %f48, %dest));         \
+       add                     %dest, 8, %dest;
+
+#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)       \
+       subcc                   %left, 8, %left;        \
+       bl,pn                   %xcc, 95f;              \
+        fsrc1                  %f0, %f1;
+
+#define UNEVEN_VISCHUNK(dest, f0, f1, left)            \
+       UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)        \
+       ba,a,pt                 %xcc, 93f;
+
+       .register       %g2,#scratch
+       .register       %g3,#scratch
+
+       .text
+       .align          64
+
+       .globl          FUNC_NAME
+       .type           FUNC_NAME,#function
+FUNC_NAME:             /* %o0=dst, %o1=src, %o2=len */
+       PREAMBLE
+       mov             %o0, %g5
+       cmp             %o2, 0
+       be,pn           %XCC, 85f
+        or             %o0, %o1, %o3
+       cmp             %o2, 16
+       blu,a,pn        %XCC, 80f
+        or             %o3, %o2, %o3
+
+       cmp             %o2, (5 * 64)
+       blu,pt          %XCC, 70f
+        andcc          %o3, 0x7, %g0
+
+       /* Clobbers o5/g1/g2/g3/g7/icc/xcc.  */
+       VISEntry
+
+       /* Is 'dst' already aligned on an 64-byte boundary? */
+       andcc           %o0, 0x3f, %g2
+       be,pt           %XCC, 2f
+
+       /* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
+        * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
+        * subtract this from 'len'.
+        */
+        sub            %o0, %o1, %o4
+       sub             %g2, 0x40, %g2
+       sub             %g0, %g2, %g2
+       sub             %o2, %g2, %o2
+       andcc           %g2, 0x7, %g1
+       be,pt           %icc, 2f
+        and            %g2, 0x38, %g2
+
+1:     subcc           %g1, 0x1, %g1
+       EX_LD(LOAD(ldub, %o1 + 0x00, %o3))
+       EX_ST(STORE(stb, %o3, %o1 + %o4))
+       bgu,pt          %XCC, 1b
+        add            %o1, 0x1, %o1
+
+       add             %o1, %o4, %o0
+
+2:     cmp             %g2, 0x0
+       and             %o1, 0x7, %g1
+       be,pt           %icc, 3f
+        alignaddr      %o1, %g0, %o1
+
+       EX_LD(LOAD(ldd, %o1, %f4))
+1:     EX_LD(LOAD(ldd, %o1 + 0x8, %f6))
+       add             %o1, 0x8, %o1
+       subcc           %g2, 0x8, %g2
+       faligndata      %f4, %f6, %f0
+       EX_ST(STORE(std, %f0, %o0))
+       be,pn           %icc, 3f
+        add            %o0, 0x8, %o0
+
+       EX_LD(LOAD(ldd, %o1 + 0x8, %f4))
+       add             %o1, 0x8, %o1
+       subcc           %g2, 0x8, %g2
+       faligndata      %f6, %f4, %f0
+       EX_ST(STORE(std, %f0, %o0))
+       bne,pt          %icc, 1b
+        add            %o0, 0x8, %o0
+
+       /* Destination is 64-byte aligned.  */
+3:     
+       membar            #LoadStore | #StoreStore | #StoreLoad
+
+       subcc           %o2, 0x40, %o4
+       add             %o1, %g1, %g1
+       andncc          %o4, (0x40 - 1), %o4
+       srl             %g1, 3, %g2
+       sub             %o2, %o4, %g3
+       andn            %o1, (0x40 - 1), %o1
+       and             %g2, 7, %g2
+       andncc          %g3, 0x7, %g3
+       fmovd           %f0, %f2
+       sub             %g3, 0x8, %g3
+       sub             %o2, %o4, %o2
+
+       add             %g1, %o4, %g1
+       subcc           %o2, %g3, %o2
+
+       EX_LD(LOAD_BLK(%o1, %f0))
+       add             %o1, 0x40, %o1
+       add             %g1, %g3, %g1
+       EX_LD(LOAD_BLK(%o1, %f16))
+       add             %o1, 0x40, %o1
+       sub             %o4, 0x80, %o4
+       EX_LD(LOAD_BLK(%o1, %f32))
+       add             %o1, 0x40, %o1
+
+       /* There are 8 instances of the unrolled loop,
+        * one for each possible alignment of the
+        * source buffer.  Each loop instance is 452
+        * bytes.
+        */
+       sll             %g2, 3, %o3
+       sub             %o3, %g2, %o3
+       sllx            %o3, 4, %o3
+       add             %o3, %g2, %o3
+       sllx            %o3, 2, %g2
+1:     rd              %pc, %o3
+       add             %o3, %lo(1f - 1b), %o3
+       jmpl            %o3 + %g2, %g0
+        nop
+
+       .align          64
+1:     FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
+       LOOP_CHUNK1(o1, o0, o4, 1f)
+       FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
+       LOOP_CHUNK2(o1, o0, o4, 2f)
+       FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
+       LOOP_CHUNK3(o1, o0, o4, 3f)
+       ba,pt           %xcc, 1b+4
+        faligndata     %f0, %f2, %f48
+1:     FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
+       STORE_JUMP(o0, f48, 40f) membar #Sync
+2:     FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
+       STORE_JUMP(o0, f48, 48f) membar #Sync
+3:     FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
+       STORE_JUMP(o0, f48, 56f) membar #Sync
+
+1:     FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
+       LOOP_CHUNK1(o1, o0, o4, 1f)
+       FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
+       LOOP_CHUNK2(o1, o0, o4, 2f)
+       FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
+       LOOP_CHUNK3(o1, o0, o4, 3f)
+       ba,pt           %xcc, 1b+4
+        faligndata     %f2, %f4, %f48
+1:     FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
+       STORE_JUMP(o0, f48, 41f) membar #Sync
+2:     FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
+       STORE_JUMP(o0, f48, 49f) membar #Sync
+3:     FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
+       STORE_JUMP(o0, f48, 57f) membar #Sync
+
+1:     FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
+       LOOP_CHUNK1(o1, o0, o4, 1f)
+       FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
+       LOOP_CHUNK2(o1, o0, o4, 2f)
+       FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
+       LOOP_CHUNK3(o1, o0, o4, 3f)
+       ba,pt           %xcc, 1b+4
+        faligndata     %f4, %f6, %f48
+1:     FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
+       STORE_JUMP(o0, f48, 42f) membar #Sync
+2:     FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
+       STORE_JUMP(o0, f48, 50f) membar #Sync
+3:     FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
+       STORE_JUMP(o0, f48, 58f) membar #Sync
+
+1:     FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
+       LOOP_CHUNK1(o1, o0, o4, 1f)
+       FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
+       LOOP_CHUNK2(o1, o0, o4, 2f)
+       FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) 
+       LOOP_CHUNK3(o1, o0, o4, 3f)
+       ba,pt           %xcc, 1b+4
+        faligndata     %f6, %f8, %f48
+1:     FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)
+       STORE_JUMP(o0, f48, 43f) membar #Sync
+2:     FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
+       STORE_JUMP(o0, f48, 51f) membar #Sync
+3:     FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
+       STORE_JUMP(o0, f48, 59f) membar #Sync
+
+1:     FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
+       LOOP_CHUNK1(o1, o0, o4, 1f)
+       FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
+       LOOP_CHUNK2(o1, o0, o4, 2f)
+       FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
+       LOOP_CHUNK3(o1, o0, o4, 3f)
+       ba,pt           %xcc, 1b+4
+        faligndata     %f8, %f10, %f48
+1:     FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
+       STORE_JUMP(o0, f48, 44f) membar #Sync
+2:     FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
+       STORE_JUMP(o0, f48, 52f) membar #Sync
+3:     FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
+       STORE_JUMP(o0, f48, 60f) membar #Sync
+
+1:     FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
+       LOOP_CHUNK1(o1, o0, o4, 1f)
+       FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
+       LOOP_CHUNK2(o1, o0, o4, 2f)
+       FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
+       LOOP_CHUNK3(o1, o0, o4, 3f)
+       ba,pt           %xcc, 1b+4
+        faligndata     %f10, %f12, %f48
+1:     FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
+       STORE_JUMP(o0, f48, 45f) membar #Sync
+2:     FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
+       STORE_JUMP(o0, f48, 53f) membar #Sync
+3:     FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
+       STORE_JUMP(o0, f48, 61f) membar #Sync
+
+1:     FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
+       LOOP_CHUNK1(o1, o0, o4, 1f)
+       FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
+       LOOP_CHUNK2(o1, o0, o4, 2f)
+       FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
+       LOOP_CHUNK3(o1, o0, o4, 3f)
+       ba,pt           %xcc, 1b+4
+        faligndata     %f12, %f14, %f48
+1:     FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
+       STORE_JUMP(o0, f48, 46f) membar #Sync
+2:     FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
+       STORE_JUMP(o0, f48, 54f) membar #Sync
+3:     FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
+       STORE_JUMP(o0, f48, 62f) membar #Sync
+
+1:     FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
+       LOOP_CHUNK1(o1, o0, o4, 1f)
+       FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
+       LOOP_CHUNK2(o1, o0, o4, 2f)
+       FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
+       LOOP_CHUNK3(o1, o0, o4, 3f)
+       ba,pt           %xcc, 1b+4
+        faligndata     %f14, %f16, %f48
+1:     FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
+       STORE_JUMP(o0, f48, 47f) membar #Sync
+2:     FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
+       STORE_JUMP(o0, f48, 55f) membar #Sync
+3:     FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
+       STORE_SYNC(o0, f48) membar #Sync
+       FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
+       STORE_JUMP(o0, f48, 63f) membar #Sync
+
+40:    FINISH_VISCHUNK(o0, f0,  f2,  g3)
+41:    FINISH_VISCHUNK(o0, f2,  f4,  g3)
+42:    FINISH_VISCHUNK(o0, f4,  f6,  g3)
+43:    FINISH_VISCHUNK(o0, f6,  f8,  g3)
+44:    FINISH_VISCHUNK(o0, f8,  f10, g3)
+45:    FINISH_VISCHUNK(o0, f10, f12, g3)
+46:    FINISH_VISCHUNK(o0, f12, f14, g3)
+47:    UNEVEN_VISCHUNK(o0, f14, f0,  g3)
+48:    FINISH_VISCHUNK(o0, f16, f18, g3)
+49:    FINISH_VISCHUNK(o0, f18, f20, g3)
+50:    FINISH_VISCHUNK(o0, f20, f22, g3)
+51:    FINISH_VISCHUNK(o0, f22, f24, g3)
+52:    FINISH_VISCHUNK(o0, f24, f26, g3)
+53:    FINISH_VISCHUNK(o0, f26, f28, g3)
+54:    FINISH_VISCHUNK(o0, f28, f30, g3)
+55:    UNEVEN_VISCHUNK(o0, f30, f0,  g3)
+56:    FINISH_VISCHUNK(o0, f32, f34, g3)
+57:    FINISH_VISCHUNK(o0, f34, f36, g3)
+58:    FINISH_VISCHUNK(o0, f36, f38, g3)
+59:    FINISH_VISCHUNK(o0, f38, f40, g3)
+60:    FINISH_VISCHUNK(o0, f40, f42, g3)
+61:    FINISH_VISCHUNK(o0, f42, f44, g3)
+62:    FINISH_VISCHUNK(o0, f44, f46, g3)
+63:    UNEVEN_VISCHUNK_LAST(o0, f46, f0,  g3)
+
+93:    EX_LD(LOAD(ldd, %o1, %f2))
+       add             %o1, 8, %o1
+       subcc           %g3, 8, %g3
+       faligndata      %f0, %f2, %f8
+       EX_ST(STORE(std, %f8, %o0))
+       bl,pn           %xcc, 95f
+        add            %o0, 8, %o0
+       EX_LD(LOAD(ldd, %o1, %f0))
+       add             %o1, 8, %o1
+       subcc           %g3, 8, %g3
+       faligndata      %f2, %f0, %f8
+       EX_ST(STORE(std, %f8, %o0))
+       bge,pt          %xcc, 93b
+        add            %o0, 8, %o0
+
+95:    brz,pt          %o2, 2f
+        mov            %g1, %o1
+
+1:     EX_LD(LOAD(ldub, %o1, %o3))
+       add             %o1, 1, %o1
+       subcc           %o2, 1, %o2
+       EX_ST(STORE(stb, %o3, %o0))
+       bne,pt          %xcc, 1b
+        add            %o0, 1, %o0
+
+2:     membar          #StoreLoad | #StoreStore
+       VISExit
+       retl
+        mov            EX_RETVAL(%g5), %o0
+
+       .align          64
+70:    /* 16 < len <= (5 * 64) */
+       bne,pn          %XCC, 75f
+        sub            %o0, %o1, %o3
+
+72:    andn            %o2, 0xf, %o4
+       and             %o2, 0xf, %o2
+1:     EX_LD(LOAD(ldx, %o1 + 0x00, %o5))
+       EX_LD(LOAD(ldx, %o1 + 0x08, %g1))
+       subcc           %o4, 0x10, %o4
+       EX_ST(STORE(stx, %o5, %o1 + %o3))
+       add             %o1, 0x8, %o1
+       EX_ST(STORE(stx, %g1, %o1 + %o3))
+       bgu,pt          %XCC, 1b
+        add            %o1, 0x8, %o1
+73:    andcc           %o2, 0x8, %g0
+       be,pt           %XCC, 1f
+        nop
+       EX_LD(LOAD(ldx, %o1, %o5))
+       sub             %o2, 0x8, %o2
+       EX_ST(STORE(stx, %o5, %o1 + %o3))
+       add             %o1, 0x8, %o1
+1:     andcc           %o2, 0x4, %g0
+       be,pt           %XCC, 1f
+        nop
+       EX_LD(LOAD(lduw, %o1, %o5))
+       sub             %o2, 0x4, %o2
+       EX_ST(STORE(stw, %o5, %o1 + %o3))
+       add             %o1, 0x4, %o1
+1:     cmp             %o2, 0
+       be,pt           %XCC, 85f
+        nop
+       ba,pt           %xcc, 90f
+        nop
+
+75:    andcc           %o0, 0x7, %g1
+       sub             %g1, 0x8, %g1
+       be,pn           %icc, 2f
+        sub            %g0, %g1, %g1
+       sub             %o2, %g1, %o2
+
+1:     EX_LD(LOAD(ldub, %o1, %o5))
+       subcc           %g1, 1, %g1
+       EX_ST(STORE(stb, %o5, %o1 + %o3))
+       bgu,pt          %icc, 1b
+        add            %o1, 1, %o1
+
+2:     add             %o1, %o3, %o0
+       andcc           %o1, 0x7, %g1
+       bne,pt          %icc, 8f
+        sll            %g1, 3, %g1
+
+       cmp             %o2, 16
+       bgeu,pt         %icc, 72b
+        nop
+       ba,a,pt         %xcc, 73b
+
+8:     mov             64, %o3
+       andn            %o1, 0x7, %o1
+       EX_LD(LOAD(ldx, %o1, %g2))
+       sub             %o3, %g1, %o3
+       andn            %o2, 0x7, %o4
+       sllx            %g2, %g1, %g2
+1:     EX_LD(LOAD(ldx, %o1 + 0x8, %g3))
+       subcc           %o4, 0x8, %o4
+       add             %o1, 0x8, %o1
+       srlx            %g3, %o3, %o5
+       or              %o5, %g2, %o5
+       EX_ST(STORE(stx, %o5, %o0))
+       add             %o0, 0x8, %o0
+       bgu,pt          %icc, 1b
+        sllx           %g3, %g1, %g2
+
+       srl             %g1, 3, %g1
+       andcc           %o2, 0x7, %o2
+       be,pn           %icc, 85f
+        add            %o1, %g1, %o1
+       ba,pt           %xcc, 90f
+        sub            %o0, %o1, %o3
+
+       .align          64
+80:    /* 0 < len <= 16 */
+       andcc           %o3, 0x3, %g0
+       bne,pn          %XCC, 90f
+        sub            %o0, %o1, %o3
+
+1:     EX_LD(LOAD(lduw, %o1, %g1))
+       subcc           %o2, 4, %o2
+       EX_ST(STORE(stw, %g1, %o1 + %o3))
+       bgu,pt          %XCC, 1b
+        add            %o1, 4, %o1
+
+85:    retl
+        mov            EX_RETVAL(%g5), %o0
+
+       .align          32
+90:    EX_LD(LOAD(ldub, %o1, %g1))
+       subcc           %o2, 1, %o2
+       EX_ST(STORE(stb, %g1, %o1 + %o3))
+       bgu,pt          %XCC, 90b
+        add            %o1, 1, %o1
+       retl
+        mov            EX_RETVAL(%g5), %o0
+
+       .size           FUNC_NAME, .-FUNC_NAME
index 46b446b..df600b6 100644 (file)
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#include <asm/visasm.h>
-#include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
-
-#define XCC xcc
-
-#define EXNV_RAW(x,y,a,b)              \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    ba U3cfu_fixup;                 \
-        a, b, %o1;                     \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EXNV(x,y,a,b)                  \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    add %o1, %o3, %o0;              \
-       ba U3cfu_fixup;                 \
-        a, b, %o1;                     \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EXNV4(x,y,a,b)                 \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    add %o1, %o3, %o0;              \
-       a, b, %o1;                      \
-       ba U3cfu_fixup;                 \
-        add %o1, 4, %o1;               \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EXNV8(x,y,a,b)                 \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    add %o1, %o3, %o0;              \
-       a, b, %o1;                      \
-       ba U3cfu_fixup;                 \
-        add %o1, 8, %o1;               \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EX(x,y,a,b)                    \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    VISExitHalf;                    \
-       ba U3cfu_fixup;                 \
-        a, b, %o1;                     \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EX2(x,y)                       \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    VISExitHalf;                    \
-       and %o2, (0x40 - 1), %o1;       \
-       add %o1, %o4, %o1;              \
-       ba U3cfu_fixup;                 \
-        add %o1, 0x1c0, %o1;           \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EX3(x,y)                       \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    VISExitHalf;                    \
-       and %o2, (0x40 - 1), %o1;       \
-       sll %g3, 6, %g3;                \
-       add %o1, 0x80, %o1;             \
-       ba U3cfu_fixup;                 \
-        add %o1, %g3, %o1;             \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EX4(x,y)                       \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    VISExitHalf;                    \
-       and %o2, (0x40 - 1), %o1;       \
-       add %o1, 0x40, %o1;             \
-       ba U3cfu_fixup;                 \
-        add %o1, %g3, %o1;             \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-
-       .register       %g2,#scratch
-       .register       %g3,#scratch
-
-       /* Special/non-trivial issues of this code:
-        *
-        * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
-        * 2) Only low 32 FPU registers are used so that only the
-        *    lower half of the FPU register set is dirtied by this
-        *    code.  This is especially important in the kernel.
-        * 3) This code never prefetches cachelines past the end
-        *    of the source buffer.
-        */
-
-       .text
-       .align  32
-
-       /* The cheetah's flexible spine, oversized liver, enlarged heart,
-        * slender muscular body, and claws make it the swiftest hunter
-        * in Africa and the fastest animal on land.  Can reach speeds
-        * of up to 2.4GB per second.
-        */
-
-       .globl  U3copy_from_user
-U3copy_from_user:      /* %o0=dst, %o1=src, %o2=len */
-       cmp             %o2, 0
-       be,pn           %XCC, 85f
-        or             %o0, %o1, %o3
-       cmp             %o2, 16
-       bleu,a,pn       %XCC, 80f
-        or             %o3, %o2, %o3
-
-       cmp             %o2, 256
-       blu,pt          %XCC, 70f
-        andcc          %o3, 0x7, %g0
-
-       ba,pt           %xcc, 1f
-        andcc          %o0, 0x3f, %g2
-
-       /* Here len >= 256 and condition codes reflect execution
-        * of "andcc %o0, 0x7, %g2", done by caller.
-        */
-       .align          64
-1:
-       /* Is 'dst' already aligned on an 64-byte boundary? */
-       be,pt           %XCC, 2f
-
-       /* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
-        * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
-        * subtract this from 'len'.
-        */
-        sub            %g2, 0x40, %g2
-       sub             %g0, %g2, %g2
-       sub             %o2, %g2, %o2
-
-       /* Copy %g2 bytes from src to dst, one byte at a time. */
-1:     EXNV_RAW(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)
-       add             %o1, 0x1, %o1
-       add             %o0, 0x1, %o0
-       subcc           %g2, 0x1, %g2
-
-       bg,pt           %XCC, 1b
-        stb            %o3, [%o0 + -1]
-
-2:     VISEntryHalf
-       and             %o1, 0x7, %g1
-       ba,pt           %xcc, 1f
-        alignaddr      %o1, %g0, %o1
-
-       .align          64
-1:
-       membar          #StoreLoad | #StoreStore | #LoadStore
-       prefetcha       [%o1 + 0x000] %asi, #one_read
-       prefetcha       [%o1 + 0x040] %asi, #one_read
-       andn            %o2, (0x40 - 1), %o4
-       prefetcha       [%o1 + 0x080] %asi, #one_read
-       prefetcha       [%o1 + 0x0c0] %asi, #one_read
-       EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0)
-       prefetcha       [%o1 + 0x100] %asi, #one_read
-       EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0)
-       prefetcha       [%o1 + 0x140] %asi, #one_read
-       EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0)
-       prefetcha       [%o1 + 0x180] %asi, #one_read
-       faligndata      %f0, %f2, %f16
-       EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0)
-       faligndata      %f2, %f4, %f18
-       EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0)
-       faligndata      %f4, %f6, %f20
-       EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0)
-       faligndata      %f6, %f8, %f22
-
-       EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0)
-       faligndata      %f8, %f10, %f24
-       EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0)
-       faligndata      %f10, %f12, %f26
-       EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0)
-
-       sub             %o4, 0x80, %o4
-       add             %o1, 0x40, %o1
-       ba,pt           %xcc, 1f
-        srl            %o4, 6, %o3
-
-       .align          64
-1:
-       EX3(ldda [%o1 + 0x008] %asi, %f2)
-       faligndata      %f12, %f14, %f28
-       EX3(ldda [%o1 + 0x010] %asi, %f4)
-       faligndata      %f14, %f0, %f30
-       stda            %f16, [%o0] ASI_BLK_P
-       EX3(ldda [%o1 + 0x018] %asi, %f6)
-       faligndata      %f0, %f2, %f16
-
-       EX3(ldda [%o1 + 0x020] %asi, %f8)
-       faligndata      %f2, %f4, %f18
-       EX3(ldda [%o1 + 0x028] %asi, %f10)
-       faligndata      %f4, %f6, %f20
-       EX3(ldda [%o1 + 0x030] %asi, %f12)
-       faligndata      %f6, %f8, %f22
-       EX3(ldda [%o1 + 0x038] %asi, %f14)
-       faligndata      %f8, %f10, %f24
-
-       EX3(ldda [%o1 + 0x040] %asi, %f0)
-       prefetcha       [%o1 + 0x180] %asi, #one_read
-       faligndata      %f10, %f12, %f26
-       subcc           %o3, 0x01, %o3
-       add             %o1, 0x40, %o1
-       bg,pt           %XCC, 1b
-        add            %o0, 0x40, %o0
-
-       /* Finally we copy the last full 64-byte block. */
-       EX3(ldda [%o1 + 0x008] %asi, %f2)
-       faligndata      %f12, %f14, %f28
-       EX3(ldda [%o1 + 0x010] %asi, %f4)
-       faligndata      %f14, %f0, %f30
-       stda            %f16, [%o0] ASI_BLK_P
-       EX3(ldda [%o1 + 0x018] %asi, %f6)
-       faligndata      %f0, %f2, %f16
-       EX3(ldda [%o1 + 0x020] %asi, %f8)
-       faligndata      %f2, %f4, %f18
-       EX3(ldda [%o1 + 0x028] %asi, %f10)
-       faligndata      %f4, %f6, %f20
-       EX3(ldda [%o1 + 0x030] %asi, %f12)
-       faligndata      %f6, %f8, %f22
-       EX3(ldda [%o1 + 0x038] %asi, %f14)
-       faligndata      %f8, %f10, %f24
-       cmp             %g1, 0
-       be,pt           %XCC, 1f
-        add            %o0, 0x40, %o0
-       EX4(ldda [%o1 + 0x040] %asi, %f0)
-1:     faligndata      %f10, %f12, %f26
-       faligndata      %f12, %f14, %f28
-       faligndata      %f14, %f0, %f30
-       stda            %f16, [%o0] ASI_BLK_P
-       add             %o0, 0x40, %o0
-       add             %o1, 0x40, %o1
-
-       membar          #Sync
-
-       /* Now we copy the (len modulo 64) bytes at the end.
-        * Note how we borrow the %f0 loaded above.
-        *
-        * Also notice how this code is careful not to perform a
-        * load past the end of the src buffer.
-        */
-       and             %o2, 0x3f, %o2
-       andcc           %o2, 0x38, %g2
-       be,pn           %XCC, 10f
-        subcc          %g2, 0x8, %g2
-       be,pn           %XCC, 10f
-        cmp            %g1, 0
-
-       be,a,pt         %XCC, 1f
-        EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0)
-
-1:     EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0)
-       add             %o1, 0x8, %o1
-       sub             %o2, 0x8, %o2
-       subcc           %g2, 0x8, %g2
-       faligndata      %f0, %f2, %f8
-       std             %f8, [%o0 + 0x00]
-       be,pn           %XCC, 10f
-        add            %o0, 0x8, %o0
-       EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0)
-       add             %o1, 0x8, %o1
-       sub             %o2, 0x8, %o2
-       subcc           %g2, 0x8, %g2
-       faligndata      %f2, %f0, %f8
-       std             %f8, [%o0 + 0x00]
-       bne,pn          %XCC, 1b
-        add            %o0, 0x8, %o0
-
-       /* If anything is left, we copy it one byte at a time.
-        * Note that %g1 is (src & 0x3) saved above before the
-        * alignaddr was performed.
-        */
-10:
-       cmp             %o2, 0
-       add             %o1, %g1, %o1
-       VISExitHalf
-       be,pn           %XCC, 85f
-        sub            %o0, %o1, %o3
-
-       andcc           %g1, 0x7, %g0
-       bne,pn          %icc, 90f
-        andcc          %o2, 0x8, %g0
-       be,pt           %icc, 1f
-        nop
-       EXNV(ldxa [%o1] %asi, %o5, add %o2, %g0)
-       stx             %o5, [%o1 + %o3]
-       add             %o1, 0x8, %o1
-
-1:     andcc           %o2, 0x4, %g0
-       be,pt           %icc, 1f
-        nop
-       EXNV(lduwa [%o1] %asi, %o5, and %o2, 0x7)
-       stw             %o5, [%o1 + %o3]
-       add             %o1, 0x4, %o1
-
-1:     andcc           %o2, 0x2, %g0
-       be,pt           %icc, 1f
-        nop
-       EXNV(lduha [%o1] %asi, %o5, and %o2, 0x3)
-       sth             %o5, [%o1 + %o3]
-       add             %o1, 0x2, %o1
-
-1:     andcc           %o2, 0x1, %g0
-       be,pt           %icc, 85f
-        nop
-       EXNV(lduba [%o1] %asi, %o5, and %o2, 0x1)
-       ba,pt           %xcc, 85f
-        stb            %o5, [%o1 + %o3]
-
-70: /* 16 < len <= 64 */
-       bne,pn          %XCC, 90f
-        sub            %o0, %o1, %o3
-
-       andn            %o2, 0x7, %o4
-       and             %o2, 0x7, %o2
-1:     subcc           %o4, 0x8, %o4
-       EXNV8(ldxa [%o1] %asi, %o5, add %o2, %o4)
-       stx             %o5, [%o1 + %o3]
-       bgu,pt          %XCC, 1b
-        add            %o1, 0x8, %o1
-       andcc           %o2, 0x4, %g0
-       be,pt           %XCC, 1f
-        nop
-       sub             %o2, 0x4, %o2
-       EXNV4(lduwa [%o1] %asi, %o5, add %o2, %g0)
-       stw             %o5, [%o1 + %o3]
-       add             %o1, 0x4, %o1
-1:     cmp             %o2, 0
-       be,pt           %XCC, 85f
-        nop
-       ba,pt           %xcc, 90f
-        nop
-
-80: /* 0 < len <= 16 */
-       andcc           %o3, 0x3, %g0
-       bne,pn          %XCC, 90f
-        sub            %o0, %o1, %o3
-
-1:
-       subcc           %o2, 4, %o2
-       EXNV(lduwa [%o1] %asi, %g1, add %o2, %g0)
-       stw             %g1, [%o1 + %o3]
-       bgu,pt          %XCC, 1b
-        add            %o1, 4, %o1
-
-85:    retl
-        clr            %o0
-
-       .align  32
-90:
-       subcc           %o2, 1, %o2
-       EXNV(lduba [%o1] %asi, %g1, add %o2, %g0)
-       stb             %g1, [%o1 + %o3]
-       bgu,pt          %XCC, 90b
-        add            %o1, 1, %o1
-       retl
-        clr            %o0
-
-U3cfu_fixup:
-       /* Since this is copy_from_user(), zero out the rest of the
-        * kernel buffer.
-        */
-       cmp             %o1, 0
-       ble,pn          %icc, 2f
-        mov            %o1, %g2
-
-1:     subcc           %g2, 1, %g2
-       stb             %g0, [%o0]
-       bne,pt          %icc, 1b
-        add            %o0, 1, %o0
-
-2:     retl
-        mov            %o1, %o0
+#define EX_LD(x)               \
+98:    x;                      \
+       .section .fixup;        \
+       .align 4;               \
+99:    retl;                   \
+        mov    1, %o0;         \
+       .section __ex_table;    \
+       .align 4;               \
+       .word 98b, 99b;         \
+       .text;                  \
+       .align 4;
+
+#define FUNC_NAME              U3copy_from_user
+#define LOAD(type,addr,dest)   type##a [addr] %asi, dest
+#define EX_RETVAL(x)           0
+
+#include "U3memcpy.S"
index 7152271..f337f22 100644 (file)
-/* U3copy_to_user.S: UltraSparc-III optimized memcpy.
+/* U3copy_to_user.S: UltraSparc-III optimized copy to userspace.
  *
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#include <asm/visasm.h>
-#include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
-
-#define XCC xcc
-
-#define EXNV(x,y,a,b)  \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    retl;                           \
-        a, b, %o0;                     \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EXNV2(x,y,a,b) \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    a, b, %o0;                      \
-       retl;                           \
-        add %o0, 1, %o0;               \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EXNV3(x,y,a,b) \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    a, b, %o0;                      \
-       retl;                           \
-        add %o0, 4, %o0;               \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EXNV4(x,y,a,b) \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    a, b, %o0;                      \
-       retl;                           \
-        add %o0, 8, %o0;               \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EX(x,y,a,b)                    \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    VISExitHalf;                    \
-       retl;                           \
-        a, b, %o0;                     \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
+#define EX_ST(x)               \
+98:    x;                      \
+       .section .fixup;        \
+       .align 4;               \
+99:    retl;                   \
+        mov    1, %o0;         \
+       .section __ex_table;    \
+       .align 4;               \
+       .word 98b, 99b;         \
+       .text;                  \
        .align 4;
-#define EXBLK1(x,y)                    \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    VISExitHalf;                    \
-       add %o4, 0x1c0, %o1;            \
-       and %o2, (0x40 - 1), %o2;       \
-       retl;                           \
-        add %o1, %o2, %o0;             \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EXBLK2(x,y)                    \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    VISExitHalf;                    \
-       sll %o3, 6, %o3;                \
-       and %o2, (0x40 - 1), %o2;       \
-       add %o3, 0x80, %o1;             \
-       retl;                           \
-        add %o1, %o2, %o0;             \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EXBLK3(x,y)                    \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    VISExitHalf;                    \
-       and %o2, (0x40 - 1), %o2;       \
-       retl;                           \
-        add %o2, 0x80, %o0;            \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-#define EXBLK4(x,y)                    \
-98:    x,y;                            \
-       .section .fixup;                \
-       .align 4;                       \
-99:    VISExitHalf;                    \
-       and %o2, (0x40 - 1), %o2;       \
-       retl;                           \
-        add %o2, 0x40, %o0;            \
-       .section __ex_table;            \
-       .align 4;                       \
-       .word 98b, 99b;                 \
-       .text;                          \
-       .align 4;
-
-       .register       %g2,#scratch
-       .register       %g3,#scratch
-
-       /* Special/non-trivial issues of this code:
-        *
-        * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
-        * 2) Only low 32 FPU registers are used so that only the
-        *    lower half of the FPU register set is dirtied by this
-        *    code.  This is especially important in the kernel.
-        * 3) This code never prefetches cachelines past the end
-        *    of the source buffer.
-        */
-
-       .text
-       .align  32
 
-       /* The cheetah's flexible spine, oversized liver, enlarged heart,
-        * slender muscular body, and claws make it the swiftest hunter
-        * in Africa and the fastest animal on land.  Can reach speeds
-        * of up to 2.4GB per second.
-        */
+#define FUNC_NAME              U3copy_to_user
+#define STORE(type,src,addr)   type##a src, [addr] ASI_AIUS
+#define STORE_BLK(src,addr)    stda src, [addr] ASI_BLK_AIUS
+#define EX_RETVAL(x)           0
 
-       .globl  U3copy_to_user
-U3copy_to_user:        /* %o0=dst, %o1=src, %o2=len */
        /* Writing to %asi is _expensive_ so we hardcode it.
         * Reading %asi to check for KERNEL_DS is comparatively
         * cheap.
         */
-       rd              %asi, %g1
-       cmp             %g1, ASI_AIUS
-       bne,pn          %icc, U3memcpy_user_stub
-        nop
-
-       cmp             %o2, 0
-       be,pn           %XCC, 85f
-        or             %o0, %o1, %o3
-       cmp             %o2, 16
-       bleu,a,pn       %XCC, 80f
-        or             %o3, %o2, %o3
-
-       cmp             %o2, 256
-       blu,pt          %XCC, 70f
-        andcc          %o3, 0x7, %g0
-
-       ba,pt           %xcc, 1f
-        andcc          %o0, 0x3f, %g2
-
-       /* Here len >= 256 and condition codes reflect execution
-        * of "andcc %o0, 0x7, %g2", done by caller.
-        */
-       .align          64
-1:
-       /* Is 'dst' already aligned on an 64-byte boundary? */
-       be,pt           %XCC, 2f
-
-       /* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
-        * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
-        * subtract this from 'len'.
-        */
-        sub            %g2, 0x40, %g2
-       sub             %g0, %g2, %g2
-       sub             %o2, %g2, %o2
-
-       /* Copy %g2 bytes from src to dst, one byte at a time. */
-1:     ldub            [%o1 + 0x00], %o3
-       add             %o1, 0x1, %o1
-       add             %o0, 0x1, %o0
-       subcc           %g2, 0x1, %g2
-
-       bg,pt           %XCC, 1b
-        EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2)
-
-2:     VISEntryHalf
-       and             %o1, 0x7, %g1
-       ba,pt           %xcc, 1f
-        alignaddr      %o1, %g0, %o1
-
-       .align          64
-1:
-       membar          #StoreLoad | #StoreStore | #LoadStore
-       prefetch        [%o1 + 0x000], #one_read
-       prefetch        [%o1 + 0x040], #one_read
-       andn            %o2, (0x40 - 1), %o4
-       prefetch        [%o1 + 0x080], #one_read
-       prefetch        [%o1 + 0x0c0], #one_read
-       ldd             [%o1 + 0x000], %f0
-       prefetch        [%o1 + 0x100], #one_read
-       ldd             [%o1 + 0x008], %f2
-       prefetch        [%o1 + 0x140], #one_read
-       ldd             [%o1 + 0x010], %f4
-       prefetch        [%o1 + 0x180], #one_read
-       faligndata      %f0, %f2, %f16
-       ldd             [%o1 + 0x018], %f6
-       faligndata      %f2, %f4, %f18
-       ldd             [%o1 + 0x020], %f8
-       faligndata      %f4, %f6, %f20
-       ldd             [%o1 + 0x028], %f10
-       faligndata      %f6, %f8, %f22
-
-       ldd             [%o1 + 0x030], %f12
-       faligndata      %f8, %f10, %f24
-       ldd             [%o1 + 0x038], %f14
-       faligndata      %f10, %f12, %f26
-       ldd             [%o1 + 0x040], %f0
-
-       sub             %o4, 0x80, %o4
-       add             %o1, 0x40, %o1
-       ba,pt           %xcc, 1f
-        srl            %o4, 6, %o3
-
-       .align          64
-1:
-       ldd             [%o1 + 0x008], %f2
-       faligndata      %f12, %f14, %f28
-       ldd             [%o1 + 0x010], %f4
-       faligndata      %f14, %f0, %f30
-       EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS)
-       ldd             [%o1 + 0x018], %f6
-       faligndata      %f0, %f2, %f16
-
-       ldd             [%o1 + 0x020], %f8
-       faligndata      %f2, %f4, %f18
-       ldd             [%o1 + 0x028], %f10
-       faligndata      %f4, %f6, %f20
-       ldd             [%o1 + 0x030], %f12
-       faligndata      %f6, %f8, %f22
-       ldd             [%o1 + 0x038], %f14
-       faligndata      %f8, %f10, %f24
-
-       ldd             [%o1 + 0x040], %f0
-       prefetch        [%o1 + 0x180], #one_read
-       faligndata      %f10, %f12, %f26
-       subcc           %o3, 0x01, %o3
-       add             %o1, 0x40, %o1
-       bg,pt           %XCC, 1b
-        add            %o0, 0x40, %o0
-
-       /* Finally we copy the last full 64-byte block. */
-       ldd             [%o1 + 0x008], %f2
-       faligndata      %f12, %f14, %f28
-       ldd             [%o1 + 0x010], %f4
-       faligndata      %f14, %f0, %f30
-       EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS)
-       ldd             [%o1 + 0x018], %f6
-       faligndata      %f0, %f2, %f16
-       ldd             [%o1 + 0x020], %f8
-       faligndata      %f2, %f4, %f18
-       ldd             [%o1 + 0x028], %f10
-       faligndata      %f4, %f6, %f20
-       ldd             [%o1 + 0x030], %f12
-       faligndata      %f6, %f8, %f22
-       ldd             [%o1 + 0x038], %f14
-       faligndata      %f8, %f10, %f24
-       cmp             %g1, 0
-       be,pt           %XCC, 1f
-        add            %o0, 0x40, %o0
-       ldd             [%o1 + 0x040], %f0
-1:     faligndata      %f10, %f12, %f26
-       faligndata      %f12, %f14, %f28
-       faligndata      %f14, %f0, %f30
-       EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS)
-       add             %o0, 0x40, %o0
-       add             %o1, 0x40, %o1
-
-       membar          #Sync
-
-       /* Now we copy the (len modulo 64) bytes at the end.
-        * Note how we borrow the %f0 loaded above.
-        *
-        * Also notice how this code is careful not to perform a
-        * load past the end of the src buffer.
-        */
-       and             %o2, 0x3f, %o2
-       andcc           %o2, 0x38, %g2
-       be,pn           %XCC, 2f
-        subcc          %g2, 0x8, %g2
-       be,pn           %XCC, 2f
-        cmp            %g1, 0
-
-       be,a,pt         %XCC, 1f
-        ldd            [%o1 + 0x00], %f0
-
-1:     ldd             [%o1 + 0x08], %f2
-       add             %o1, 0x8, %o1
-       sub             %o2, 0x8, %o2
-       subcc           %g2, 0x8, %g2
-       faligndata      %f0, %f2, %f8
-       EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)
-       be,pn           %XCC, 2f
-        add            %o0, 0x8, %o0
-       ldd             [%o1 + 0x08], %f0
-       add             %o1, 0x8, %o1
-       sub             %o2, 0x8, %o2
-       subcc           %g2, 0x8, %g2
-       faligndata      %f2, %f0, %f8
-       EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)
-       bne,pn          %XCC, 1b
-        add            %o0, 0x8, %o0
-
-       /* If anything is left, we copy it one byte at a time.
-        * Note that %g1 is (src & 0x3) saved above before the
-        * alignaddr was performed.
-        */
-2:
-       cmp             %o2, 0
-       add             %o1, %g1, %o1
-       VISExitHalf
-       be,pn           %XCC, 85f
-        sub            %o0, %o1, %o3
-
-       andcc           %g1, 0x7, %g0
-       bne,pn          %icc, 90f
-        andcc          %o2, 0x8, %g0
-       be,pt           %icc, 1f
-        nop
-       ldx             [%o1], %o5
-       EXNV(stxa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-       add             %o1, 0x8, %o1
-
-1:     andcc           %o2, 0x4, %g0
-       be,pt           %icc, 1f
-        nop
-       lduw            [%o1], %o5
-       EXNV(stwa %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x7)
-       add             %o1, 0x4, %o1
-
-1:     andcc           %o2, 0x2, %g0
-       be,pt           %icc, 1f
-        nop
-       lduh            [%o1], %o5
-       EXNV(stha %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x3)
-       add             %o1, 0x2, %o1
-
-1:     andcc           %o2, 0x1, %g0
-       be,pt           %icc, 85f
-        nop
-       ldub            [%o1], %o5
-       ba,pt           %xcc, 85f
-        EXNV(stba %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x1)
-
-70: /* 16 < len <= 64 */
-       bne,pn          %XCC, 90f
-        sub            %o0, %o1, %o3
-
-       andn            %o2, 0x7, %o4
-       and             %o2, 0x7, %o2
-1:     subcc           %o4, 0x8, %o4
-       ldx             [%o1], %o5
-       EXNV4(stxa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %o4)
-       bgu,pt          %XCC, 1b
-        add            %o1, 0x8, %o1
-       andcc           %o2, 0x4, %g0
-       be,pt           %XCC, 1f
-        nop
-       sub             %o2, 0x4, %o2
-       lduw            [%o1], %o5
-       EXNV3(stwa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-       add             %o1, 0x4, %o1
-1:     cmp             %o2, 0
-       be,pt           %XCC, 85f
-        nop
-       ba,pt           %xcc, 90f
-        nop
-
-80: /* 0 < len <= 16 */
-       andcc           %o3, 0x3, %g0
-       bne,pn          %XCC, 90f
-        sub            %o0, %o1, %o3
-
-1:
-       subcc           %o2, 4, %o2
-       lduw            [%o1], %g1
-       EXNV3(stwa %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-       bgu,pt          %XCC, 1b
-        add            %o1, 4, %o1
-
-85:    retl
-        clr            %o0
+#define PREAMBLE                                       \
+       rd              %asi, %g1;                      \
+       cmp             %g1, ASI_AIUS;                  \
+       bne,pn          %icc, memcpy_user_stub;         \
+        nop;                                           \
 
-       .align  32
-90:
-       subcc           %o2, 1, %o2
-       ldub            [%o1], %g1
-       EXNV2(stba %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-       bgu,pt          %XCC, 90b
-        add            %o1, 1, %o1
-       retl
-        clr            %o0
+#include "U3memcpy.S"
index e9982de..5cde954 100644 (file)
@@ -6,14 +6,50 @@
 #ifdef __KERNEL__
 #include <asm/visasm.h>
 #include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
 #else
 #define ASI_BLK_P 0xf0
 #define FPRS_FEF  0x04
+#ifdef MEMCPY_DEBUG
+#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \
+                    clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0;
+#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#else
 #define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
 #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
 #endif
+#endif
+
+#ifndef EX_LD
+#define EX_LD(x)       x
+#endif
+
+#ifndef EX_ST
+#define EX_ST(x)       x
+#endif
+
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)   x
+#endif
+
+#ifndef LOAD
+#define LOAD(type,addr,dest)   type [addr], dest
+#endif
+
+#ifndef STORE
+#define STORE(type,src,addr)   type src, [addr]
+#endif
+
+#ifndef STORE_BLK
+#define STORE_BLK(src,addr)    stda src, [addr] ASI_BLK_P
+#endif
+
+#ifndef FUNC_NAME
+#define FUNC_NAME      U3memcpy
+#endif
+
+#ifndef PREAMBLE
+#define PREAMBLE
+#endif
 
 #ifndef XCC
 #define XCC xcc
@@ -33,7 +69,7 @@
         */
 
        .text
-       .align  32
+       .align          64
 
        /* The cheetah's flexible spine, oversized liver, enlarged heart,
         * slender muscular body, and claws make it the swiftest hunter
         * of up to 2.4GB per second.
         */
 
-       .globl  U3memcpy
-U3memcpy:      /* %o0=dst, %o1=src, %o2=len */
+       .globl  FUNC_NAME
+       .type   FUNC_NAME,#function
+FUNC_NAME:     /* %o0=dst, %o1=src, %o2=len */
+       PREAMBLE
        mov             %o0, %g5
        cmp             %o2, 0
        be,pn           %XCC, 85f
         or             %o0, %o1, %o3
        cmp             %o2, 16
-       bleu,a,pn       %XCC, 70f
+       blu,a,pn        %XCC, 80f
         or             %o3, %o2, %o3
 
-       cmp             %o2, 256
-       blu,pt          %XCC, 80f
+       cmp             %o2, (3 * 64)
+       blu,pt          %XCC, 70f
         andcc          %o3, 0x7, %g0
 
-       ba,pt           %xcc, 1f
-        andcc          %o0, 0x3f, %g2
-
-       /* Here len >= 256 and condition codes reflect execution
-        * of "andcc %o0, 0x7, %g2", done by caller.
+       /* Clobbers o5/g1/g2/g3/g7/icc/xcc.  We must preserve
+        * o5 from here until we hit VISExitHalf.
         */
-       .align          64
-1:
+       VISEntryHalf
+
        /* Is 'dst' already aligned on an 64-byte boundary? */
+       andcc           %o0, 0x3f, %g2
        be,pt           %XCC, 2f
 
        /* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
         * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
         * subtract this from 'len'.
         */
-        sub            %g2, 0x40, %g2
+        sub            %o0, %o1, %o4
+       sub             %g2, 0x40, %g2
        sub             %g0, %g2, %g2
        sub             %o2, %g2, %o2
+       andcc           %g2, 0x7, %g1
+       be,pt           %icc, 2f
+        and            %g2, 0x38, %g2
 
-       /* Copy %g2 bytes from src to dst, one byte at a time. */
-1:     ldub            [%o1 + 0x00], %o3
-       add             %o1, 0x1, %o1
-       add             %o0, 0x1, %o0
-       subcc           %g2, 0x1, %g2
+1:     subcc           %g1, 0x1, %g1
+       EX_LD(LOAD(ldub, %o1 + 0x00, %o3))
+       EX_ST(STORE(stb, %o3, %o1 + %o4))
+       bgu,pt          %XCC, 1b
+        add            %o1, 0x1, %o1
 
-       bg,pt           %XCC, 1b
-        stb            %o3, [%o0 + -1]
+       add             %o1, %o4, %o0
 
-2:     VISEntryHalf
+2:     cmp             %g2, 0x0
        and             %o1, 0x7, %g1
-       ba,pt           %xcc, 1f
+       be,pt           %icc, 3f
         alignaddr      %o1, %g0, %o1
 
-       .align          64
-1:
-       membar          #StoreLoad | #StoreStore | #LoadStore
-       prefetch        [%o1 + 0x000], #one_read
-       prefetch        [%o1 + 0x040], #one_read
+       EX_LD(LOAD(ldd, %o1, %f4))
+1:     EX_LD(LOAD(ldd, %o1 + 0x8, %f6))
+       add             %o1, 0x8, %o1
+       subcc           %g2, 0x8, %g2
+       faligndata      %f4, %f6, %f0
+       EX_ST(STORE(std, %f0, %o0))
+       be,pn           %icc, 3f
+        add            %o0, 0x8, %o0
+
+       EX_LD(LOAD(ldd, %o1 + 0x8, %f4))
+       add             %o1, 0x8, %o1
+       subcc           %g2, 0x8, %g2
+       faligndata      %f6, %f4, %f2
+       EX_ST(STORE(std, %f2, %o0))
+       bne,pt          %icc, 1b
+        add            %o0, 0x8, %o0
+
+3:     LOAD(prefetch, %o1 + 0x000, #one_read)
+       LOAD(prefetch, %o1 + 0x040, #one_read)
        andn            %o2, (0x40 - 1), %o4
-       prefetch        [%o1 + 0x080], #one_read
-       prefetch        [%o1 + 0x0c0], #one_read
-       ldd             [%o1 + 0x000], %f0
-       prefetch        [%o1 + 0x100], #one_read
-       ldd             [%o1 + 0x008], %f2
-       prefetch        [%o1 + 0x140], #one_read
-       ldd             [%o1 + 0x010], %f4
-       prefetch        [%o1 + 0x180], #one_read
+       LOAD(prefetch, %o1 + 0x080, #one_read)
+       LOAD(prefetch, %o1 + 0x0c0, #one_read)
+       LOAD(prefetch, %o1 + 0x100, #one_read)
+       EX_LD(LOAD(ldd, %o1 + 0x000, %f0))
+       LOAD(prefetch, %o1 + 0x140, #one_read)
+       EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
+       LOAD(prefetch, %o1 + 0x180, #one_read)
+       EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
+       LOAD(prefetch, %o1 + 0x1c0, #one_read)
        faligndata      %f0, %f2, %f16
-       ldd             [%o1 + 0x018], %f6
+       EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
        faligndata      %f2, %f4, %f18
-       ldd             [%o1 + 0x020], %f8
+       EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
        faligndata      %f4, %f6, %f20
-       ldd             [%o1 + 0x028], %f10
+       EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
        faligndata      %f6, %f8, %f22
 
-       ldd             [%o1 + 0x030], %f12
+       EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
        faligndata      %f8, %f10, %f24
-       ldd             [%o1 + 0x038], %f14
+       EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
        faligndata      %f10, %f12, %f26
-       ldd             [%o1 + 0x040], %f0
+       EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
 
-       sub             %o4, 0x80, %o4
+       subcc           %o4, 0x80, %o4
        add             %o1, 0x40, %o1
-       ba,pt           %xcc, 1f
+       bgu,pt          %XCC, 1f
         srl            %o4, 6, %o3
+       ba,pt           %xcc, 2f
+        nop
 
        .align          64
 1:
-       ldd             [%o1 + 0x008], %f2
+       EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
        faligndata      %f12, %f14, %f28
-       ldd             [%o1 + 0x010], %f4
+       EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
        faligndata      %f14, %f0, %f30
-       stda            %f16, [%o0] ASI_BLK_P
-       ldd             [%o1 + 0x018], %f6
+       EX_ST(STORE_BLK(%f16, %o0))
+       EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
        faligndata      %f0, %f2, %f16
+       add             %o0, 0x40, %o0
 
-       ldd             [%o1 + 0x020], %f8
+       EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
        faligndata      %f2, %f4, %f18
-       ldd             [%o1 + 0x028], %f10
+       EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
        faligndata      %f4, %f6, %f20
-       ldd             [%o1 + 0x030], %f12
+       EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
+       subcc           %o3, 0x01, %o3
        faligndata      %f6, %f8, %f22
-       ldd             [%o1 + 0x038], %f14
-       faligndata      %f8, %f10, %f24
+       EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
 
-       ldd             [%o1 + 0x040], %f0
-       prefetch        [%o1 + 0x180], #one_read
+       faligndata      %f8, %f10, %f24
+       EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
+       LOAD(prefetch, %o1 + 0x1c0, #one_read)
        faligndata      %f10, %f12, %f26
-       subcc           %o3, 0x01, %o3
-       add             %o1, 0x40, %o1
        bg,pt           %XCC, 1b
-        add            %o0, 0x40, %o0
+        add            %o1, 0x40, %o1
 
        /* Finally we copy the last full 64-byte block. */
-       ldd             [%o1 + 0x008], %f2
+2:
+       EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
        faligndata      %f12, %f14, %f28
-       ldd             [%o1 + 0x010], %f4
+       EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
        faligndata      %f14, %f0, %f30
-       stda            %f16, [%o0] ASI_BLK_P
-       ldd             [%o1 + 0x018], %f6
+       EX_ST(STORE_BLK(%f16, %o0))
+       EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
        faligndata      %f0, %f2, %f16
-       ldd             [%o1 + 0x020], %f8
+       EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
        faligndata      %f2, %f4, %f18
-       ldd             [%o1 + 0x028], %f10
+       EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
        faligndata      %f4, %f6, %f20
-       ldd             [%o1 + 0x030], %f12
+       EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
        faligndata      %f6, %f8, %f22
-       ldd             [%o1 + 0x038], %f14
+       EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
        faligndata      %f8, %f10, %f24
        cmp             %g1, 0
        be,pt           %XCC, 1f
         add            %o0, 0x40, %o0
-       ldd             [%o1 + 0x040], %f0
+       EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
 1:     faligndata      %f10, %f12, %f26
        faligndata      %f12, %f14, %f28
        faligndata      %f14, %f0, %f30
-       stda            %f16, [%o0] ASI_BLK_P
+       EX_ST(STORE_BLK(%f16, %o0))
        add             %o0, 0x40, %o0
        add             %o1, 0x40, %o1
        membar          #Sync
@@ -189,23 +246,22 @@ U3memcpy: /* %o0=dst, %o1=src, %o2=len */
        be,pn           %XCC, 2f
         cmp            %g1, 0
 
+       sub             %o2, %g2, %o2
        be,a,pt         %XCC, 1f
-        ldd            [%o1 + 0x00], %f0
+        EX_LD(LOAD(ldd, %o1 + 0x00, %f0))
 
-1:     ldd             [%o1 + 0x08], %f2
+1:     EX_LD(LOAD(ldd, %o1 + 0x08, %f2))
        add             %o1, 0x8, %o1
-       sub             %o2, 0x8, %o2
        subcc           %g2, 0x8, %g2
        faligndata      %f0, %f2, %f8
-       std             %f8, [%o0 + 0x00]
+       EX_ST(STORE(std, %f8, %o0))
        be,pn           %XCC, 2f
         add            %o0, 0x8, %o0
-       ldd             [%o1 + 0x08], %f0
+       EX_LD(LOAD(ldd, %o1 + 0x08, %f0))
        add             %o1, 0x8, %o1
-       sub             %o2, 0x8, %o2
        subcc           %g2, 0x8, %g2
        faligndata      %f2, %f0, %f8
-       std             %f8, [%o0 + 0x00]
+       EX_ST(STORE(std, %f8, %o0))
        bne,pn          %XCC, 1b
         add            %o0, 0x8, %o0
 
@@ -225,48 +281,60 @@ U3memcpy: /* %o0=dst, %o1=src, %o2=len */
         andcc          %o2, 0x8, %g0
        be,pt           %icc, 1f
         nop
-       ldx             [%o1], %o5
-       stx             %o5, [%o1 + %o3]
+       EX_LD(LOAD(ldx, %o1, %o5))
+       EX_ST(STORE(stx, %o5, %o1 + %o3))
        add             %o1, 0x8, %o1
 
 1:     andcc           %o2, 0x4, %g0
        be,pt           %icc, 1f
         nop
-       lduw            [%o1], %o5
-       stw             %o5, [%o1 + %o3]
+       EX_LD(LOAD(lduw, %o1, %o5))
+       EX_ST(STORE(stw, %o5, %o1 + %o3))
        add             %o1, 0x4, %o1
 
 1:     andcc           %o2, 0x2, %g0
        be,pt           %icc, 1f
         nop
-       lduh            [%o1], %o5
-       sth             %o5, [%o1 + %o3]
+       EX_LD(LOAD(lduh, %o1, %o5))
+       EX_ST(STORE(sth, %o5, %o1 + %o3))
        add             %o1, 0x2, %o1
 
 1:     andcc           %o2, 0x1, %g0
        be,pt           %icc, 85f
         nop
-       ldub            [%o1], %o5
+       EX_LD(LOAD(ldub, %o1, %o5))
        ba,pt           %xcc, 85f
-        stb            %o5, [%o1 + %o3]
+        EX_ST(STORE(stb, %o5, %o1 + %o3))
 
+       .align          64
 70: /* 16 < len <= 64 */
-       bne,pn          %XCC, 90f
+       bne,pn          %XCC, 75f
         sub            %o0, %o1, %o3
 
-       andn            %o2, 0x7, %o4
-       and             %o2, 0x7, %o2
-1:     subcc           %o4, 0x8, %o4
-       ldx             [%o1], %o5
-       stx             %o5, [%o1 + %o3]
+72:
+       andn            %o2, 0xf, %o4
+       and             %o2, 0xf, %o2
+1:     subcc           %o4, 0x10, %o4
+       EX_LD(LOAD(ldx, %o1 + 0x00, %o5))
+       EX_LD(LOAD(ldx, %o1 + 0x08, %g1))
+       EX_ST(STORE(stx, %o5, %o1 + %o3))
+       add             %o1, 0x8, %o1
+       EX_ST(STORE(stx, %g1, %o1 + %o3))
        bgu,pt          %XCC, 1b
         add            %o1, 0x8, %o1
-       andcc           %o2, 0x4, %g0
+73:    andcc           %o2, 0x8, %g0
+       be,pt           %XCC, 1f
+        nop
+       sub             %o2, 0x8, %o2
+       EX_LD(LOAD(ldx, %o1, %o5))
+       EX_ST(STORE(stx, %o5, %o1 + %o3))
+       add             %o1, 0x8, %o1
+1:     andcc           %o2, 0x4, %g0
        be,pt           %XCC, 1f
         nop
        sub             %o2, 0x4, %o2
-       lduw            [%o1], %o5
-       stw             %o5, [%o1 + %o3]
+       EX_LD(LOAD(lduw, %o1, %o5))
+       EX_ST(STORE(stw, %o5, %o1 + %o3))
        add             %o1, 0x4, %o1
 1:     cmp             %o2, 0
        be,pt           %XCC, 85f
@@ -274,6 +342,53 @@ U3memcpy:  /* %o0=dst, %o1=src, %o2=len */
        ba,pt           %xcc, 90f
         nop
 
+75:
+       andcc           %o0, 0x7, %g1
+       sub             %g1, 0x8, %g1
+       be,pn           %icc, 2f
+        sub            %g0, %g1, %g1
+       sub             %o2, %g1, %o2
+
+1:     subcc           %g1, 1, %g1
+       EX_LD(LOAD(ldub, %o1, %o5))
+       EX_ST(STORE(stb, %o5, %o1 + %o3))
+       bgu,pt          %icc, 1b
+        add            %o1, 1, %o1
+
+2:     add             %o1, %o3, %o0
+       andcc           %o1, 0x7, %g1
+       bne,pt          %icc, 8f
+        sll            %g1, 3, %g1
+
+       cmp             %o2, 16
+       bgeu,pt         %icc, 72b
+        nop
+       ba,a,pt         %xcc, 73b
+
+8:     mov             64, %o3
+       andn            %o1, 0x7, %o1
+       EX_LD(LOAD(ldx, %o1, %g2))
+       sub             %o3, %g1, %o3
+       andn            %o2, 0x7, %o4
+       sllx            %g2, %g1, %g2
+1:     EX_LD(LOAD(ldx, %o1 + 0x8, %g3))
+       subcc           %o4, 0x8, %o4
+       add             %o1, 0x8, %o1
+       srlx            %g3, %o3, %o5
+       or              %o5, %g2, %o5
+       EX_ST(STORE(stx, %o5, %o0))
+       add             %o0, 0x8, %o0
+       bgu,pt          %icc, 1b
+        sllx           %g3, %g1, %g2
+
+       srl             %g1, 3, %g1
+       andcc           %o2, 0x7, %o2
+       be,pn           %icc, 85f
+        add            %o1, %g1, %o1
+       ba,pt           %xcc, 90f
+        sub            %o0, %o1, %o3
+
+       .align          64
 80: /* 0 < len <= 16 */
        andcc           %o3, 0x3, %g0
        bne,pn          %XCC, 90f
@@ -281,34 +396,22 @@ U3memcpy: /* %o0=dst, %o1=src, %o2=len */
 
 1:
        subcc           %o2, 4, %o2
-       lduw            [%o1], %g1
-       stw             %g1, [%o1 + %o3]
+       EX_LD(LOAD(lduw, %o1, %g1))
+       EX_ST(STORE(stw, %g1, %o1 + %o3))
        bgu,pt          %XCC, 1b
         add            %o1, 4, %o1
 
 85:    retl
-        mov            %g5, %o0
+        mov            EX_RETVAL(%g5), %o0
 
-       .align  32
+       .align          32
 90:
        subcc           %o2, 1, %o2
-       ldub            [%o1], %g1
-       stb             %g1, [%o1 + %o3]
+       EX_LD(LOAD(ldub, %o1, %g1))
+       EX_ST(STORE(stb, %g1, %o1 + %o3))
        bgu,pt          %XCC, 90b
         add            %o1, 1, %o1
        retl
-        mov            %g5, %o0
+        mov            EX_RETVAL(%g5), %o0
 
-       /* Act like copy_{to,in}_user(), ie. return zero instead
-        * of original destination pointer.  This is invoked when
-        * copy_{to,in}_user() finds that %asi is kernel space.
-        */
-       .globl  U3memcpy_user_stub
-U3memcpy_user_stub:
-       save            %sp, -192, %sp
-       mov             %i0, %o0
-       mov             %i1, %o1
-       call            U3memcpy
-        mov            %i2, %o2
-       ret
-        restore        %g0, %g0, %o0
+       .size           FUNC_NAME, .-FUNC_NAME
diff --git a/arch/sparc64/lib/U3patch.S b/arch/sparc64/lib/U3patch.S
new file mode 100644 (file)
index 0000000..e2b6c5e
--- /dev/null
@@ -0,0 +1,32 @@
+/* U3patch.S: Patch Ultra-I routines with Ultra-III variant.
+ *
+ * Copyright (C) 2004 David S. Miller <davem@redhat.com>
+ */
+
+#define BRANCH_ALWAYS  0x10680000
+#define NOP            0x01000000
+#define ULTRA3_DO_PATCH(OLD, NEW)      \
+       sethi   %hi(NEW), %g1; \
+       or      %g1, %lo(NEW), %g1; \
+       sethi   %hi(OLD), %g2; \
+       or      %g2, %lo(OLD), %g2; \
+       sub     %g1, %g2, %g1; \
+       sethi   %hi(BRANCH_ALWAYS), %g3; \
+       srl     %g1, 2, %g1; \
+       or      %g3, %lo(BRANCH_ALWAYS), %g3; \
+       or      %g3, %g1, %g3; \
+       stw     %g3, [%g2]; \
+       sethi   %hi(NOP), %g3; \
+       or      %g3, %lo(NOP), %g3; \
+       stw     %g3, [%g2 + 0x4]; \
+       flush   %g2;
+
+       .globl  cheetah_patch_copyops
+       .type   cheetah_patch_copyops,#function
+cheetah_patch_copyops:
+       ULTRA3_DO_PATCH(memcpy, U3memcpy)
+       ULTRA3_DO_PATCH(___copy_from_user, U3copy_from_user)
+       ULTRA3_DO_PATCH(___copy_to_user, U3copy_to_user)
+       retl
+        nop
+       .size   cheetah_patch_copyops,.-cheetah_patch_copyops
index a0d6d8a..26463d8 100644 (file)
@@ -10,6 +10,7 @@
        .align  64
 
        .globl  __atomic_add
+       .type   __atomic_add,#function
 __atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
        lduw    [%o1], %g5
        add     %g5, %o0, %g7
@@ -19,8 +20,10 @@ __atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
         membar #StoreLoad | #StoreStore
        retl
         add    %g7, %o0, %o0
+       .size   __atomic_add, .-__atomic_add
 
        .globl  __atomic_sub
+       .type   __atomic_sub,#function
 __atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */
        lduw    [%o1], %g5
        sub     %g5, %o0, %g7
@@ -30,8 +33,10 @@ __atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */
         membar #StoreLoad | #StoreStore
        retl
         sub    %g7, %o0, %o0
+       .size   __atomic_sub, .-__atomic_sub
 
        .globl  __atomic64_add
+       .type   __atomic64_add,#function
 __atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
        ldx     [%o1], %g5
        add     %g5, %o0, %g7
@@ -41,8 +46,10 @@ __atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
         membar #StoreLoad | #StoreStore
        retl
         add    %g7, %o0, %o0
+       .size   __atomic64_add, .-__atomic64_add
 
        .globl  __atomic64_sub
+       .type   __atomic64_sub,#function
 __atomic64_sub: /* %o0 = increment, %o1 = atomic_ptr */
        ldx     [%o1], %g5
        sub     %g5, %o0, %g7
@@ -52,4 +59,4 @@ __atomic64_sub: /* %o0 = increment, %o1 = atomic_ptr */
         membar #StoreLoad | #StoreStore
        retl
         sub    %g7, %o0, %o0
-
+       .size   __atomic64_sub, .-__atomic64_sub
index 0c2aacc..c1e3700 100644 (file)
@@ -9,6 +9,7 @@
        .text
        .align  64
        .globl  ___test_and_set_bit
+       .type   ___test_and_set_bit,#function
 ___test_and_set_bit:   /* %o0=nr, %o1=addr */
        srlx    %o0, 6, %g1
        mov     1, %g5
@@ -26,8 +27,10 @@ ___test_and_set_bit: /* %o0=nr, %o1=addr */
         ldx    [%o1], %g7
 2:     retl
         membar #StoreLoad | #StoreStore
+       .size   ___test_and_set_bit, .-___test_and_set_bit
 
        .globl  ___test_and_clear_bit
+       .type   ___test_and_clear_bit,#function
 ___test_and_clear_bit: /* %o0=nr, %o1=addr */
        srlx    %o0, 6, %g1
        mov     1, %g5
@@ -45,8 +48,10 @@ ___test_and_clear_bit:       /* %o0=nr, %o1=addr */
         ldx    [%o1], %g7
 2:     retl
         membar #StoreLoad | #StoreStore
+       .size   ___test_and_clear_bit, .-___test_and_clear_bit
 
        .globl  ___test_and_change_bit
+       .type   ___test_and_change_bit,#function
 ___test_and_change_bit:        /* %o0=nr, %o1=addr */
        srlx    %o0, 6, %g1
        mov     1, %g5
@@ -64,41 +69,4 @@ ___test_and_change_bit:      /* %o0=nr, %o1=addr */
 2:     retl
         membar #StoreLoad | #StoreStore
        nop
-
-       .globl  ___test_and_set_le_bit
-___test_and_set_le_bit:        /* %o0=nr, %o1=addr */
-       srlx    %o0, 5, %g1
-       mov     1, %g5
-       sllx    %g1, 2, %g3
-       and     %o0, 31, %g2
-       sllx    %g5, %g2, %g5
-       add     %o1, %g3, %o1
-       lduwa   [%o1] ASI_PL, %g7
-1:     andcc   %g7, %g5, %o0
-       bne,pn  %icc, 2f
-        xor    %g7, %g5, %g1
-       casa    [%o1] ASI_PL, %g7, %g1
-       cmp     %g7, %g1
-       bne,a,pn %icc, 1b
-        lduwa  [%o1] ASI_PL, %g7
-2:     retl
-        membar #StoreLoad | #StoreStore
-
-       .globl  ___test_and_clear_le_bit
-___test_and_clear_le_bit:      /* %o0=nr, %o1=addr */
-       srlx    %o0, 5, %g1
-       mov     1, %g5
-       sllx    %g1, 2, %g3
-       and     %o0, 31, %g2
-       sllx    %g5, %g2, %g5
-       add     %o1, %g3, %o1
-       lduwa   [%o1] ASI_PL, %g7
-1:     andcc   %g7, %g5, %o0
-       be,pn   %icc, 2f
-        xor    %g7, %g5, %g1
-       casa    [%o1] ASI_PL, %g7, %g1
-       cmp     %g7, %g1
-       bne,a,pn %icc, 1b
-        lduwa  [%o1] ASI_PL, %g7
-2:     retl
-        membar #StoreLoad | #StoreStore
+       .size   ___test_and_change_bit, .-___test_and_change_bit
diff --git a/arch/sparc64/lib/copy_in_user.S b/arch/sparc64/lib/copy_in_user.S
new file mode 100644 (file)
index 0000000..816076c
--- /dev/null
@@ -0,0 +1,119 @@
+/* copy_in_user.S: Copy from userspace to userspace.
+ *
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
+ */
+
+#include <asm/asi.h>
+
+#define XCC xcc
+
+#define EX(x,y)                        \
+98:    x,y;                    \
+       .section .fixup;        \
+       .align 4;               \
+99:    retl;                   \
+        mov 1, %o0;            \
+       .section __ex_table;    \
+       .align 4;               \
+       .word 98b, 99b;         \
+       .text;                  \
+       .align 4;
+
+       .register       %g2,#scratch
+       .register       %g3,#scratch
+
+       .text
+       .align  32
+
+       /* Don't try to get too fancy here, just nice and
+        * simple.  This is predominantly used for well aligned
+        * small copies in the compat layer.  It is also used
+        * to copy register windows around during thread cloning.
+        */
+
+       .globl          ___copy_in_user
+       .type           ___copy_in_user,#function
+___copy_in_user:       /* %o0=dst, %o1=src, %o2=len */
+       /* Writing to %asi is _expensive_ so we hardcode it.
+        * Reading %asi to check for KERNEL_DS is comparatively
+        * cheap.
+        */
+       rd              %asi, %g1
+       cmp             %g1, ASI_AIUS
+       bne,pn          %icc, memcpy_user_stub
+        nop
+
+       cmp             %o2, 0
+       be,pn           %XCC, 85f
+        or             %o0, %o1, %o3
+       cmp             %o2, 16
+       bleu,a,pn       %XCC, 80f
+        or             %o3, %o2, %o3
+
+       /* 16 < len <= 64 */
+       andcc           %o3, 0x7, %g0
+       bne,pn          %XCC, 90f
+        sub            %o0, %o1, %o3
+
+       andn            %o2, 0x7, %o4
+       and             %o2, 0x7, %o2
+1:     subcc           %o4, 0x8, %o4
+       EX(ldxa [%o1] %asi, %o5)
+       EX(stxa %o5, [%o1 + %o3] ASI_AIUS)
+       bgu,pt          %XCC, 1b
+        add            %o1, 0x8, %o1
+       andcc           %o2, 0x4, %g0
+       be,pt           %XCC, 1f
+        nop
+       sub             %o2, 0x4, %o2
+       EX(lduwa [%o1] %asi, %o5)
+       EX(stwa %o5, [%o1 + %o3] ASI_AIUS)
+       add             %o1, 0x4, %o1
+1:     cmp             %o2, 0
+       be,pt           %XCC, 85f
+        nop
+       ba,pt           %xcc, 90f
+        nop
+
+80:    /* 0 < len <= 16 */
+       andcc           %o3, 0x3, %g0
+       bne,pn          %XCC, 90f
+        sub            %o0, %o1, %o3
+
+82:
+       subcc           %o2, 4, %o2
+       EX(lduwa [%o1] %asi, %g1)
+       EX(stwa %g1, [%o1 + %o3] ASI_AIUS)
+       bgu,pt          %XCC, 82b
+        add            %o1, 4, %o1
+
+85:    retl
+        clr            %o0
+
+       .align  32
+90:
+       subcc           %o2, 1, %o2
+       EX(lduba [%o1] %asi, %g1)
+       EX(stba %g1, [%o1 + %o3] ASI_AIUS)
+       bgu,pt          %XCC, 90b
+        add            %o1, 1, %o1
+       retl
+        clr            %o0
+
+       .size           ___copy_in_user, .-___copy_in_user
+
+       /* Act like copy_{to,in}_user(), ie. return zero instead
+        * of original destination pointer.  This is invoked when
+        * copy_{to,in}_user() finds that %asi is kernel space.
+        */
+       .globl          memcpy_user_stub
+       .type           memcpy_user_stub,#function
+memcpy_user_stub:
+       save            %sp, -192, %sp
+       mov             %i0, %o0
+       mov             %i1, %o1
+       call            memcpy
+        mov            %i2, %o2
+       ret
+        restore        %g0, %g0, %o0
+       .size           memcpy_user_stub, .-memcpy_user_stub
index 862eefb..23ebf2c 100644 (file)
@@ -45,6 +45,7 @@
 
        .align          32
        .globl          copy_user_page
+       .type           copy_user_page,#function
 copy_user_page:                /* %o0=dest, %o1=src, %o2=vaddr */
        lduw            [%g6 + TI_PRE_COUNT], %o4
        sethi           %uhi(PAGE_OFFSET), %g2
@@ -237,3 +238,5 @@ copy_user_page:             /* %o0=dest, %o1=src, %o2=vaddr */
 
        retl
         stw            %o4, [%g6 + TI_PRE_COUNT]
+
+       .size           copy_user_page, .-copy_user_page
diff --git a/arch/sparc64/lib/delay.c b/arch/sparc64/lib/delay.c
new file mode 100644 (file)
index 0000000..f55f528
--- /dev/null
@@ -0,0 +1,49 @@
+/* delay.c: Delay loops for sparc64
+ *
+ * Copyright (C) 2004 David S. Miller <davem@redhat.com>
+ *
+ * Based heavily upon x86 variant which is:
+ *     Copyright (C) 1993 Linus Torvalds
+ *     Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <linux/delay.h>
+
+void __delay(unsigned long loops)
+{
+       __asm__ __volatile__(
+"      b,pt    %%xcc, 1f\n"
+"       cmp    %0, 0\n"
+"      .align  32\n"
+"1:\n"
+"      bne,pt  %%xcc, 1b\n"
+"       subcc  %0, 1, %0\n"
+       : "=&r" (loops)
+       : "0" (loops)
+       : "cc");
+}
+
+/* We used to multiply by HZ after shifting down by 32 bits
+ * but that runs into problems for higher values of HZ and
+ * slow cpus.
+ */
+void __const_udelay(unsigned long n)
+{
+       n *= 4;
+
+       n *= (cpu_data(smp_processor_id()).udelay_val * (HZ/4));
+       n >>= 32;
+
+       __delay(n + 1);
+}
+
+void __udelay(unsigned long n)
+{
+       __const_udelay(n * 0x10c7UL);
+}
+
+
+void __ndelay(unsigned long n)
+{
+       __const_udelay(n * 0x5UL);
+}
diff --git a/arch/sparc64/lib/iomap.c b/arch/sparc64/lib/iomap.c
new file mode 100644 (file)
index 0000000..ac556db
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Implement the sparc64 iomap interfaces
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+/* Create a virtual mapping cookie for an IO port range */
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+       return (void __iomem *) (unsigned long) port;
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+       /* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (!len || !start)
+               return NULL;
+       if (maxlen && len > maxlen)
+               len = maxlen;
+       if (flags & IORESOURCE_IO)
+               return ioport_map(start, len);
+       if (flags & IORESOURCE_MEM) {
+               if (flags & IORESOURCE_CACHEABLE)
+                       return ioremap(start, len);
+               return ioremap_nocache(start, len);
+       }
+       /* What? */
+       return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+       /* nothing to do */
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
index e7d349f..58ca5b9 100644 (file)
@@ -1,6 +1,7 @@
        .text
-       .align          32
-       .globl          ip_fast_csum
+       .align  32
+       .globl  ip_fast_csum
+       .type   ip_fast_csum,#function
 ip_fast_csum:  /* %o0 = iph, %o1 = ihl */
        sub     %o1, 4, %g7
        lduw    [%o0 + 0x00], %o2
@@ -30,3 +31,4 @@ ip_fast_csum: /* %o0 = iph, %o1 = ihl */
        set     0xffff, %o1
        retl
         and    %o2, %o1, %o0
+       .size   ip_fast_csum, .-ip_fast_csum
diff --git a/arch/sparc64/lib/memmove.S b/arch/sparc64/lib/memmove.S
new file mode 100644 (file)
index 0000000..ca8781d
--- /dev/null
@@ -0,0 +1,33 @@
+/* memmove.S: Simple memmove implementation.
+ *
+ * Copyright (C) 1997, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+       .text
+       .align          32
+       .globl          memmove
+       .type           memmove,#function
+memmove:
+       mov             %o0, %g1
+       cmp             %o0, %o1
+       blu,pt          %xcc, memcpy
+        sub            %o0, %o1, %g5
+       add             %o1, %o2, %g3
+       cmp             %g3, %o0
+       bleu,pt         %xcc, memcpy
+        add            %o1, %o2, %g5
+       add             %o0, %o2, %o5
+
+       sub             %g5, 1, %o1
+       sub             %o5, 1, %o0
+1:     ldub            [%o1], %g5
+       subcc           %o2, 1, %o2
+       sub             %o1, 1, %o1
+       stb             %g5, [%o0]
+       bne,pt          %icc, 1b
+        sub            %o0, 1, %o0
+
+       retl
+        mov            %g1, %o0
+       .size           memmove, .-memmove
index 55527f6..066ec1e 100644 (file)
@@ -9,9 +9,9 @@
 #define HI_MAGIC 0x80808080
 
        .align  32
-       .global strlen, __strlen
+       .globl  strlen
+       .type   strlen,#function
 strlen:
-__strlen:
        mov     %o0, %o1
        andcc   %o0, 3, %g0
        be,pt   %icc, 9f
@@ -76,3 +76,5 @@ __strlen:
 13:
        retl
         mov    2, %o0
+
+       .size   strlen, .-strlen
index 474ba72..6f14f53 100644 (file)
@@ -7,9 +7,9 @@
 #include <asm/asi.h>
 
        .text
-       .align 4
-       .global __strncmp, strncmp
-__strncmp:
+       .align  32
+       .glob strncmp
+       .type   strncmp,#function
 strncmp:
        brlez,pn %o2, 3f
         lduba  [%o0] (ASI_PNF), %o3
@@ -29,3 +29,4 @@ strncmp:
 3:
        retl
         clr    %o0
+       .size   strncmp, .-strncmp
index 9abb371..93d600a 100644 (file)
@@ -12,7 +12,7 @@
 0:     .xword  0x0101010101010101
 
        .text
-       .align  4
+       .align  32
 
        /* Must return:
         *
@@ -31,6 +31,7 @@
         */
 
        .globl  __strncpy_from_user
+       .type   __strncpy_from_user,#function
 __strncpy_from_user:
        /* %o0=dest, %o1=src, %o2=count */
        sethi   %hi(0b), %o5            ! IEU0  Group
@@ -122,6 +123,7 @@ __strncpy_from_user:
         mov    %o2, %o0
 2:     retl
         add    %o2, %o3, %o0
+       .size   __strncpy_from_user, .-__strncpy_from_user
 
        .section .fixup,#alloc,#execinstr
        .align  4
diff --git a/arch/sparc64/lib/user_fixup.c b/arch/sparc64/lib/user_fixup.c
new file mode 100644 (file)
index 0000000..58ec560
--- /dev/null
@@ -0,0 +1,68 @@
+/* user_fixup.c: Fix up user copy faults.
+ *
+ * Copyright (C) 2004 David S. Miller <davem@redhat.com>
+ */
+
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+/* Calculating the exact fault address when using
+ * block loads and stores can be very complicated.
+ * Instead of trying to be clever and handling all
+ * of the cases, just fix things up simply here.
+ */
+
+unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size)
+{
+       char *dst = to;
+       const char __user *src = from;
+
+       while (size--) {
+               if (__get_user(*dst, src))
+                       break;
+               dst++;
+               src++;
+       }
+
+       if (size)
+               memset(dst, 0, size);
+
+       return size;
+}
+
+unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size)
+{
+       char __user *dst = to;
+       const char *src = from;
+
+       while (size--) {
+               if (__put_user(*src, dst))
+                       break;
+               dst++;
+               src++;
+       }
+
+       return size;
+}
+
+unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size)
+{
+       char __user *dst = to;
+       char __user *src = from;
+
+       while (size--) {
+               char tmp;
+
+               if (__get_user(tmp, src))
+                       break;
+               if (__put_user(tmp, dst))
+                       break;
+               dst++;
+               src++;
+       }
+
+       return size;
+}
index 8eeba35..f748fd6 100644 (file)
@@ -18,8 +18,9 @@
  *     !(len & 127) && len >= 256
  */
        .text
-       .globl xor_vis_2
-       .type xor_vis_2,@function
+       .align  32
+       .globl  xor_vis_2
+       .type   xor_vis_2,#function
 xor_vis_2:
        rd      %fprs, %o5
        andcc   %o5, FPRS_FEF|FPRS_DU, %g0
@@ -87,11 +88,10 @@ xor_vis_2:
        wr      %g1, %g0, %asi
        retl
          wr    %g0, 0, %fprs
-       .size xor_vis_2, .-xor_vis_2
+       .size   xor_vis_2, .-xor_vis_2
 
-
-       .globl xor_vis_3
-       .type xor_vis_3,@function
+       .globl  xor_vis_3
+       .type   xor_vis_3,#function
 xor_vis_3:
        rd      %fprs, %o5
        andcc   %o5, FPRS_FEF|FPRS_DU, %g0
@@ -156,11 +156,10 @@ xor_vis_3:
        wr      %g1, %g0, %asi
        retl
         wr     %g0, 0, %fprs
-       .size xor_vis_3, .-xor_vis_3
-
+       .size   xor_vis_3, .-xor_vis_3
 
-       .globl xor_vis_4
-       .type xor_vis_4,@function
+       .globl  xor_vis_4
+       .type   xor_vis_4,#function
 xor_vis_4:
        rd      %fprs, %o5
        andcc   %o5, FPRS_FEF|FPRS_DU, %g0
@@ -244,11 +243,10 @@ xor_vis_4:
        wr      %g1, %g0, %asi
        retl
         wr     %g0, 0, %fprs
-       .size xor_vis_4, .-xor_vis_4
-
+       .size   xor_vis_4, .-xor_vis_4
 
-       .globl xor_vis_5
-       .type xor_vis_5,@function
+       .globl  xor_vis_5
+       .type   xor_vis_5,#function
 xor_vis_5:
        mov     %o5, %g5
        rd      %fprs, %o5
@@ -353,4 +351,4 @@ xor_vis_5:
        wr      %g1, %g0, %asi
        retl
         wr     %g0, 0, %fprs
-       .size xor_vis_5, .-xor_vis_5
+       .size   xor_vis_5, .-xor_vis_5
index 4a3db02..15b4cfe 100644 (file)
@@ -137,21 +137,34 @@ asmlinkage int solaris_brk(u32 brk)
        return sunos_brk(brk);
 }
 
-#define set_utsfield(to, from, dotchop, countfrom) {                   \
-       char *p;                                                        \
-       int i, len = (countfrom) ?                                      \
-               ((sizeof(to) > sizeof(from) ?                           \
-                       sizeof(from) : sizeof(to))) : sizeof(to);       \
-       if (copy_to_user(to, from, len))                                \
-               return -EFAULT;                                         \
-       if (dotchop)                                                    \
-               for (p=from,i=0; *p && *p != '.' && --len; p++,i++);    \
-       else                                                            \
-               i = len - 1;                                            \
-       if (__put_user('\0', (char __user *)((to)+i)))                  \
-               return -EFAULT;                                         \
+static int __set_utsfield(char __user *to, int to_size,
+                         const char *from, int from_size,
+                         int dotchop, int countfrom)
+{
+       int len = countfrom ? (to_size > from_size ?
+                              from_size : to_size) : to_size;
+       int off;
+
+       if (copy_to_user(to, from, len))
+               return -EFAULT;
+
+       off = len < to_size? len: len - 1;
+       if (dotchop) {
+               const char *p = strnchr(from, len, '.');
+               if (p) off = p - from;
+       }
+
+       if (__put_user('\0', to + off))
+               return -EFAULT;
+
+       return 0;
 }
 
+#define set_utsfield(to, from, dotchop, countfrom) \
+       __set_utsfield((to), sizeof(to), \
+                      (from), sizeof(from), \
+                      (dotchop), (countfrom))
+
 struct sol_uname {
        char sysname[9];
        char nodename[9];
@@ -219,17 +232,20 @@ static char *serial(char *buffer)
 asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
 {
        struct sol_uname __user *v = A(buf);
+       int err;
+
        switch (which) {
        case 0: /* old uname */
                /* Let's cheat */
-               set_utsfield(v->sysname, "SunOS", 1, 0);
+               err  = set_utsfield(v->sysname, "SunOS", 1, 0);
                down_read(&uts_sem);
-               set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
+               err |= set_utsfield(v->nodename, system_utsname.nodename,
+                                   1, 1);
                up_read(&uts_sem);
-               set_utsfield(v->release, "2.6", 0, 0);
-               set_utsfield(v->version, "Generic", 0, 0);
-               set_utsfield(v->machine, machine(), 0, 0);
-               return 0;
+               err |= set_utsfield(v->release, "2.6", 0, 0);
+               err |= set_utsfield(v->version, "Generic", 0, 0);
+               err |= set_utsfield(v->machine, machine(), 0, 0);
+               return (err ? -EFAULT : 0);
        case 2: /* ustat */
                return -ENOSYS;
        case 3: /* fusers */
@@ -242,15 +258,18 @@ asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
 asmlinkage int solaris_utsname(u32 buf)
 {
        struct sol_utsname __user *v = A(buf);
+       int err;
+
        /* Why should we not lie a bit? */
        down_read(&uts_sem);
-       set_utsfield(v->sysname, "SunOS", 0, 0);
-       set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
-       set_utsfield(v->release, "5.6", 0, 0);
-       set_utsfield(v->version, "Generic", 0, 0);
-       set_utsfield(v->machine, machine(), 0, 0);
+       err  = set_utsfield(v->sysname, "SunOS", 0, 0);
+       err |= set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
+       err |= set_utsfield(v->release, "5.6", 0, 0);
+       err |= set_utsfield(v->version, "Generic", 0, 0);
+       err |= set_utsfield(v->machine, machine(), 0, 0);
        up_read(&uts_sem);
-       return 0;
+
+       return (err ? -EFAULT : 0);
 }
 
 #define SI_SYSNAME             1       /* return name of operating system */
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
new file mode 100644 (file)
index 0000000..a2d5830
--- /dev/null
@@ -0,0 +1,43 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config FRAME_POINTER
+       bool
+       default y if DEBUG_INFO
+
+config PT_PROXY
+       bool "Enable ptrace proxy"
+       depends on XTERM_CHAN && DEBUG_INFO
+       help
+       This option enables a debugging interface which allows gdb to debug
+       the kernel without needing to actually attach to kernel threads.
+       If you want to do kernel debugging, say Y here; otherwise say N.
+
+config GPROF
+       bool "Enable gprof support"
+       depends on DEBUG_INFO
+       help
+        This allows profiling of a User-Mode Linux kernel with the gprof
+        utility.
+
+        See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+        details.
+
+        If you're involved in UML kernel development and want to use gprof,
+        say Y.  If you're unsure, say N.
+
+config GCOV
+       bool "Enable gcov support"
+       depends on DEBUG_INFO
+       help
+        This option allows developers to retrieve coverage data from a UML
+        session.
+
+        See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+        details.
+
+        If you're involved in UML kernel development and want to use gcov,
+        say Y.  If you're unsure, say N.
+
+endmenu
index 8d58a30..eed367d 100644 (file)
@@ -3,5 +3,4 @@
 # Licensed under the GPL
 #
 
-MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/tt/include
-
+MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/kernel/tt/include
index d875d04..1951731 100644 (file)
 #error "__BYTE_ORDER not defined"
 #endif
 
-extern int init_cow_file(int fd, char *cow_file, char *backing_file, 
-                        int sectorsize, int alignment, int *bitmap_offset_out, 
+extern int init_cow_file(int fd, char *cow_file, char *backing_file,
+                        int sectorsize, int alignment, int *bitmap_offset_out,
                         unsigned long *bitmap_len_out, int *data_offset_out);
 
 extern int file_reader(__u64 offset, char *buf, int len, void *arg);
-extern int read_cow_header(int (*reader)(__u64, char *, int, void *), 
-                          void *arg, __u32 *version_out, 
-                          char **backing_file_out, time_t *mtime_out, 
-                          __u64 *size_out, int *sectorsize_out, 
+extern int read_cow_header(int (*reader)(__u64, char *, int, void *),
+                          void *arg, __u32 *version_out,
+                          char **backing_file_out, time_t *mtime_out,
+                          __u64 *size_out, int *sectorsize_out,
                           __u32 *align_out, int *bitmap_offset_out);
 
-extern int write_cow_header(char *cow_file, int fd, char *backing_file, 
+extern int write_cow_header(char *cow_file, int fd, char *backing_file,
                            int sectorsize, int alignment, long long *size);
 
 extern void cow_sizes(int version, __u64 size, int sectorsize, int align,
-                     int bitmap_offset, unsigned long *bitmap_len_out, 
+                     int bitmap_offset, unsigned long *bitmap_len_out,
                      int *data_offset_out);
 
 #endif
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
new file mode 100644 (file)
index 0000000..ce251f0
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __COW_SYS_H__
+#define __COW_SYS_H__
+
+#include "kern_util.h"
+#include "user_util.h"
+#include "os.h"
+#include "user.h"
+
+static inline void *cow_malloc(int size)
+{
+       return(um_kmalloc(size));
+}
+
+static inline void cow_free(void *ptr)
+{
+       kfree(ptr);
+}
+
+#define cow_printf printk
+
+static inline char *cow_strdup(char *str)
+{
+       return(uml_strdup(str));
+}
+
+static inline int cow_seek_file(int fd, __u64 offset)
+{
+       return(os_seek_file(fd, offset));
+}
+
+static inline int cow_file_size(char *file, __u64 *size_out)
+{
+       return(os_file_size(file, size_out));
+}
+
+static inline int cow_write_file(int fd, char *buf, int size)
+{
+       return(os_write_file(fd, buf, size));
+}
+
+#endif
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
index 014c2c8..d3fad24 100644 (file)
@@ -27,20 +27,20 @@ struct cow_header_v1 {
 #define PATH_LEN_V2 MAXPATHLEN
 
 struct cow_header_v2 {
-       unsigned long magic;
-       unsigned long version;
+       __u32 magic;
+       __u32 version;
        char backing_file[PATH_LEN_V2];
        time_t mtime;
        __u64 size;
        int sectorsize;
 };
 
-/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in 
+/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
  * case other systems have different values for MAXPATHLEN
  */
 #define PATH_LEN_V3 4096
 
-/* Changes from V2 - 
+/* Changes from V2 -
  *     PATH_LEN_V3 as described above
  *     Explicitly specify field bit lengths for systems with different
  *             lengths for the usual C types.  Not sure whether char or
@@ -90,15 +90,15 @@ union cow_header {
 #define DIV_ROUND(x, len) (((x) + (len) - 1) / (len))
 #define ROUND_UP(x, align) DIV_ROUND(x, align) * (align)
 
-void cow_sizes(int version, __u64 size, int sectorsize, int align, 
-              int bitmap_offset, unsigned long *bitmap_len_out, 
+void cow_sizes(int version, __u64 size, int sectorsize, int align,
+              int bitmap_offset, unsigned long *bitmap_len_out,
               int *data_offset_out)
 {
        if(version < 3){
                *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
 
                *data_offset_out = bitmap_offset + *bitmap_len_out;
-               *data_offset_out = (*data_offset_out + sectorsize - 1) / 
+               *data_offset_out = (*data_offset_out + sectorsize - 1) /
                        sectorsize;
                *data_offset_out *= sectorsize;
        }
@@ -117,7 +117,7 @@ static int absolutize(char *to, int size, char *from)
        int remaining;
 
        if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
-               cow_printf("absolutize : unable to get cwd - errno = %d\n", 
+               cow_printf("absolutize : unable to get cwd - errno = %d\n",
                           errno);
                return(-1);
        }
@@ -126,7 +126,7 @@ static int absolutize(char *to, int size, char *from)
                *slash = '\0';
                if(chdir(from)){
                        *slash = '/';
-                       cow_printf("absolutize : Can't cd to '%s' - " 
+                       cow_printf("absolutize : Can't cd to '%s' - "
                                   "errno = %d\n", from, errno);
                        return(-1);
                }
@@ -158,7 +158,7 @@ static int absolutize(char *to, int size, char *from)
        return(0);
 }
 
-int write_cow_header(char *cow_file, int fd, char *backing_file, 
+int write_cow_header(char *cow_file, int fd, char *backing_file,
                     int sectorsize, int alignment, long long *size)
 {
        struct cow_header_v3 *header;
@@ -183,12 +183,12 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
        err = -EINVAL;
        if(strlen(backing_file) > sizeof(header->backing_file) - 1){
                cow_printf("Backing file name \"%s\" is too long - names are "
-                          "limited to %d characters\n", backing_file, 
+                          "limited to %d characters\n", backing_file,
                           sizeof(header->backing_file) - 1);
                goto out_free;
        }
 
-       if(absolutize(header->backing_file, sizeof(header->backing_file), 
+       if(absolutize(header->backing_file, sizeof(header->backing_file),
                      backing_file))
                goto out_free;
 
@@ -234,10 +234,10 @@ int file_reader(__u64 offset, char *buf, int len, void *arg)
 
 /* XXX Need to sanity-check the values read from the header */
 
-int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, 
-                   __u32 *version_out, char **backing_file_out, 
-                   time_t *mtime_out, __u64 *size_out, 
-                   int *sectorsize_out, __u32 *align_out, 
+int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
+                   __u32 *version_out, char **backing_file_out,
+                   time_t *mtime_out, __u64 *size_out,
+                   int *sectorsize_out, __u32 *align_out,
                    int *bitmap_offset_out)
 {
        union cow_header *header;
@@ -310,7 +310,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
        }
        else {
                cow_printf("read_cow_header - invalid COW version\n");
-               goto out;               
+               goto out;
        }
        err = -ENOMEM;
        *backing_file_out = cow_strdup(file);
@@ -326,18 +326,18 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
 }
 
 int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
-                 int alignment, int *bitmap_offset_out, 
+                 int alignment, int *bitmap_offset_out,
                  unsigned long *bitmap_len_out, int *data_offset_out)
 {
        __u64 size, offset;
        char zero = 0;
        int err;
 
-       err = write_cow_header(cow_file, fd, backing_file, sectorsize, 
+       err = write_cow_header(cow_file, fd, backing_file, sectorsize,
                               alignment, &size);
-       if(err) 
+       if(err)
                goto out;
-       
+
        *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment);
        cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out,
                  bitmap_len_out, data_offset_out);
@@ -349,9 +349,9 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
                goto out;
        }
 
-       /* does not really matter how much we write it is just to set EOF 
+       /* does not really matter how much we write it is just to set EOF
         * this also sets the entire COW bitmap
-        * to zero without having to allocate it 
+        * to zero without having to allocate it
         */
        err = cow_write_file(fd, &zero, sizeof(zero));
        if(err != sizeof(zero)){
index 4bcb829..3af52a6 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -9,7 +9,7 @@
 #include "linux/interrupt.h"
 
 extern int um_request_irq(unsigned int irq, int fd, int type,
-                         irqreturn_t (*handler)(int, void *, 
+                         irqreturn_t (*handler)(int, void *,
                                                 struct pt_regs *),
                          unsigned long irqflags,  const char * devname,
                          void *dev_id);
index b39f03d..cb7e196 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
new file mode 100644 (file)
index 0000000..ee16421
--- /dev/null
@@ -0,0 +1,171 @@
+#include <asm-generic/vmlinux.lds.h>
+
+OUTPUT_FORMAT(ELF_FORMAT)
+OUTPUT_ARCH(ELF_ARCH)
+ENTRY(_start)
+jiffies = jiffies_64;
+
+SECTIONS
+{
+  . = START + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  __binary_start = .;
+  . = ALIGN(4096);             /* Init code and data */
+  _stext = .;
+  __init_begin = .;
+  .init.text : {
+       _sinittext = .;
+       *(.init.text)
+       _einittext = .;
+  }
+
+  . = ALIGN(4096);
+
+  /* Read-only sections, merged into text segment: */
+  .hash           : { *(.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rel.init       : { *(.rel.init) }
+  .rela.init      : { *(.rela.init) }
+  .rel.text       : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
+  .rela.text      : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
+  .rel.fini       : { *(.rel.fini) }
+  .rela.fini      : { *(.rela.fini) }
+  .rel.rodata     : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
+  .rela.rodata    : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
+  .rel.data       : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
+  .rela.data      : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
+  .rel.tdata     : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
+  .rela.tdata    : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
+  .rel.tbss      : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
+  .rela.tbss     : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
+  .rel.ctors      : { *(.rel.ctors) }
+  .rela.ctors     : { *(.rela.ctors) }
+  .rel.dtors      : { *(.rel.dtors) }
+  .rela.dtors     : { *(.rela.dtors) }
+  .rel.got        : { *(.rel.got) }
+  .rela.got       : { *(.rela.got) }
+  .rel.bss        : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
+  .rela.bss       : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
+  .rel.plt        : { *(.rel.plt) }
+  .rela.plt       : { *(.rela.plt) }
+  .init           : {
+    KEEP (*(.init))
+  } =0x90909090
+  .plt            : { *(.plt) }
+  .text           : {
+    *(.text)
+    SCHED_TEXT
+    *(.stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0x90909090
+  .fini           : {
+    KEEP (*(.fini))
+  } =0x90909090
+
+  .kstrtab : { *(.kstrtab) }
+
+  #include "asm/common.lds.S"
+
+  init.data : { *(.init.data) }
+
+  /* Ensure the __preinit_array_start label is properly aligned.  We
+     could instead move the label definition inside the section, but
+     the linker would then create the section even if it turns out to
+     be empty, which isn't pretty.  */
+  . = ALIGN(32 / 8);
+  .preinit_array     : { *(.preinit_array) }
+  .init_array     : { *(.init_array) }
+  .fini_array     : { *(.fini_array) }
+  .data           : {
+    . = ALIGN(KERNEL_STACK_SIZE);              /* init_task */
+    *(.data.init_task)
+    *(.data .data.* .gnu.linkonce.d.*)
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  .tdata         : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss                  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .eh_frame       : { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : { *(.gcc_except_table) }
+  .dynamic        : { *(.dynamic) }
+  .ctors          : {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    /* We don't want to include the .ctor section from
+       from the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          : {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .got            : { *(.got.plt) *(.got) }
+  _edata = .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  .bss            : {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(32 / 8);
+  . = ALIGN(32 / 8);
+  }
+  _end = .;
+  PROVIDE (end = .);
+   /* 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 sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .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) }
+}
diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c
new file mode 100644 (file)
index 0000000..e1fd2c5
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/resource.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+#include <asm/page.h>
+#include "user_util.h"
+#include "kern_util.h"
+#include "mem_user.h"
+#include "signal_user.h"
+#include "user.h"
+#include "init.h"
+#include "mode.h"
+#include "choose-mode.h"
+#include "uml-config.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 */
+char *linux_prog;
+
+#define PGD_BOUND (4 * 1024 * 1024)
+#define STACKSIZE (8 * 1024 * 1024)
+#define THREAD_NAME_LEN (256)
+
+static void set_stklim(void)
+{
+       struct rlimit lim;
+
+       if(getrlimit(RLIMIT_STACK, &lim) < 0){
+               perror("getrlimit");
+               exit(1);
+       }
+       if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){
+               lim.rlim_cur = STACKSIZE;
+               if(setrlimit(RLIMIT_STACK, &lim) < 0){
+                       perror("setrlimit");
+                       exit(1);
+               }
+       }
+       stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1);
+}
+
+static __init void do_uml_initcalls(void)
+{
+       initcall_t *call;
+
+       call = &__uml_initcall_start;
+       while (call < &__uml_initcall_end){;
+               (*call)();
+               call++;
+       }
+}
+
+static void last_ditch_exit(int sig)
+{
+       CHOOSE_MODE(kmalloc_ok = 0, (void) 0);
+       signal(SIGINT, SIG_DFL);
+       signal(SIGTERM, SIG_DFL);
+       signal(SIGHUP, SIG_DFL);
+       uml_cleanup();
+       exit(1);
+}
+
+extern int uml_exitcode;
+
+int main(int argc, char **argv, char **envp)
+{
+       char **new_argv;
+       sigset_t mask;
+       int ret, i;
+
+       /* Enable all signals except SIGIO - in some environments, we can
+        * enter with some signals blocked
+        */
+
+       sigemptyset(&mask);
+       sigaddset(&mask, SIGIO);
+       if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
+               perror("sigprocmask");
+               exit(1);
+       }
+
+#ifdef UML_CONFIG_MODE_TT
+       /* Allocate memory for thread command lines */
+       if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
+
+               char padding[THREAD_NAME_LEN] = {
+                       [ 0 ...  THREAD_NAME_LEN - 2] = ' ', '\0'
+               };
+
+               new_argv = malloc((argc + 2) * sizeof(char*));
+               if(!new_argv) {
+                       perror("Allocating extended argv");
+                       exit(1);
+               }
+
+               new_argv[0] = argv[0];
+               new_argv[1] = padding;
+
+               for(i = 2; i <= argc; i++)
+                       new_argv[i] = argv[i - 1];
+               new_argv[argc + 1] = NULL;
+
+               execvp(new_argv[0], new_argv);
+               perror("execing with extended args");
+               exit(1);
+       }
+#endif
+
+       linux_prog = argv[0];
+
+       set_stklim();
+
+       new_argv = malloc((argc + 1) * sizeof(char *));
+       if(new_argv == NULL){
+               perror("Mallocing argv");
+               exit(1);
+       }
+       for(i=0;i<argc;i++){
+               new_argv[i] = strdup(argv[i]);
+               if(new_argv[i] == NULL){
+                       perror("Mallocing an arg");
+                       exit(1);
+               }
+       }
+       new_argv[argc] = NULL;
+
+       set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+       set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+       set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+
+       do_uml_initcalls();
+       ret = linux_main(argc, argv);
+
+       /* Reboot */
+       if(ret){
+               int err;
+
+               printf("\n");
+
+               /* Let any pending signals fire, then disable them.  This
+                * ensures that they won't be delivered after the exec, when
+                * they are definitely not expected.
+                */
+               unblock_signals();
+               disable_timer();
+               err = deactivate_all_fds();
+               if(err)
+                       printf("deactivate_all_fds failed, errno = %d\n",
+                              -err);
+
+               execvp(new_argv[0], new_argv);
+               perror("Failed to exec kernel");
+               ret = 1;
+       }
+       printf("\n");
+       return(uml_exitcode);
+}
+
+#define CAN_KMALLOC() \
+       (kmalloc_ok && CHOOSE_MODE((getpid() != tracing_pid), 1))
+
+extern void *__real_malloc(int);
+
+void *__wrap_malloc(int size)
+{
+       void *ret;
+
+       if(!CAN_KMALLOC())
+               return(__real_malloc(size));
+       else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/
+               ret = um_kmalloc(size);
+       else ret = um_vmalloc(size);
+
+       /* glibc people insist that if malloc fails, errno should be
+        * set by malloc as well. So we do.
+        */
+       if(ret == NULL)
+               errno = ENOMEM;
+
+       return(ret);
+}
+
+void *__wrap_calloc(int n, int size)
+{
+       void *ptr = __wrap_malloc(n * size);
+
+       if(ptr == NULL) return(NULL);
+       memset(ptr, 0, n * size);
+       return(ptr);
+}
+
+extern void __real_free(void *);
+
+extern unsigned long high_physmem;
+
+void __wrap_free(void *ptr)
+{
+       unsigned long addr = (unsigned long) ptr;
+
+       /* We need to know how the allocation happened, so it can be correctly
+        * freed.  This is done by seeing what region of memory the pointer is
+        * in -
+        *      physical memory - kmalloc/kfree
+        *      kernel virtual memory - vmalloc/vfree
+        *      anywhere else - malloc/free
+        * If kmalloc is not yet possible, then the kernel memory regions
+        * may not be set up yet, and the variables not initialized.  So,
+        * free is called.
+        *
+        * CAN_KMALLOC is checked because it would be bad to free a buffer
+        * with kmalloc/vmalloc after they have been turned off during
+        * shutdown.
+        */
+
+       if((addr >= uml_physmem) && (addr < high_physmem)){
+               if(CAN_KMALLOC())
+                       kfree(ptr);
+       }
+       else if((addr >= start_vm) && (addr < end_vm)){
+               if(CAN_KMALLOC())
+                       vfree(ptr);
+       }
+       else __real_free(ptr);
+}
+
+/*
+ * 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 d0e0f50..3253bc0 100644 (file)
@@ -1,13 +1,14 @@
-/* 
+/*
  * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
 #include "linux/mm.h"
-#include "linux/ghash.h"
+#include "linux/rbtree.h"
 #include "linux/slab.h"
 #include "linux/vmalloc.h"
 #include "linux/bootmem.h"
+#include "linux/module.h"
 #include "asm/types.h"
 #include "asm/pgtable.h"
 #include "kern_util.h"
 #include "kern.h"
 #include "init.h"
 
-#if 0
-static pgd_t physmem_pgd[PTRS_PER_PGD];
-
-static struct phys_desc *lookup_mapping(void *addr)
-{
-       pgd = &physmem_pgd[pgd_index(addr)];
-       if(pgd_none(pgd))
-               return(NULL);
-
-       pmd = pmd_offset(pgd, addr);
-       if(pmd_none(pmd))
-               return(NULL);
-
-       pte = pte_offset_kernel(pmd, addr);
-       return((struct phys_desc *) pte_val(pte));
-}
-
-static struct add_mapping(void *addr, struct phys_desc *new)
-{
-}
-#endif
-
-#define PHYS_HASHSIZE (8192)
-
-struct phys_desc;
-
-DEF_HASH_STRUCTS(virtmem, PHYS_HASHSIZE, struct phys_desc);
-
 struct phys_desc {
-       struct virtmem_ptrs virt_ptrs;
+       struct rb_node rb;
        int fd;
        __u64 offset;
        void *virt;
@@ -56,21 +29,48 @@ struct phys_desc {
        struct list_head list;
 };
 
-struct virtmem_table virtmem_hash;
+static struct rb_root phys_mappings = RB_ROOT;
 
-static int virt_cmp(void *virt1, void *virt2)
+static struct rb_node **find_rb(void *virt)
 {
-       return(virt1 != virt2);
+       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 int virt_hash(void *virt)
+static struct phys_desc *find_phys_mapping(void *virt)
 {
-       unsigned long addr = ((unsigned long) virt) >> PAGE_SHIFT;
-       return(addr % PHYS_HASHSIZE);
+       struct rb_node **n = find_rb(virt);
+
+       if(*n == NULL)
+               return(NULL);
+
+       return(rb_entry(*n, struct phys_desc, rb));
 }
 
-DEF_HASH(static, virtmem, struct phys_desc, virt_ptrs, void *, virt, virt_cmp, 
-        virt_hash);
+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, (*n)->rb_parent, n);
+       rb_insert_color(&desc->rb, &phys_mappings);
+}
 
 LIST_HEAD(descriptor_mappings);
 
@@ -106,7 +106,7 @@ static struct desc_mapping *descriptor_mapping(int fd)
        if(desc == NULL)
                return(NULL);
 
-       *desc = ((struct desc_mapping) 
+       *desc = ((struct desc_mapping)
                { .fd =         fd,
                  .list =       LIST_HEAD_INIT(desc->list),
                  .pages =      LIST_HEAD_INIT(desc->pages) });
@@ -127,7 +127,8 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
                return(-ENOMEM);
 
        phys = __pa(virt);
-       if(find_virtmem_hash(&virtmem_hash, virt) != NULL)
+       desc = find_phys_mapping(virt);
+       if(desc != NULL)
                panic("Address 0x%p is already substituted\n", virt);
 
        err = -ENOMEM;
@@ -135,14 +136,13 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
        if(desc == NULL)
                goto out;
 
-       *desc = ((struct phys_desc) 
-               { .virt_ptrs =  { NULL, NULL },
-                 .fd =         fd,
+       *desc = ((struct phys_desc)
+               { .fd =                 fd,
                  .offset =             offset,
                  .virt =               virt,
                  .phys =               __pa(virt),
                  .list =               LIST_HEAD_INIT(desc->list) });
-       insert_virtmem_hash(&virtmem_hash, desc);
+       insert_phys_mapping(desc);
 
        list_add(&desc->list, &fd_maps->pages);
 
@@ -151,7 +151,7 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
        if(!err)
                goto out;
 
-       remove_virtmem_hash(&virtmem_hash, desc);
+       rb_erase(&desc->rb, &phys_mappings);
        kfree(desc);
  out:
        return(err);
@@ -164,7 +164,7 @@ static void remove_mapping(struct phys_desc *desc)
        void *virt = desc->virt;
        int err;
 
-       remove_virtmem_hash(&virtmem_hash, desc);
+       rb_erase(&desc->rb, &phys_mappings);
        list_del(&desc->list);
        kfree(desc);
 
@@ -179,7 +179,7 @@ int physmem_remove_mapping(void *virt)
        struct phys_desc *desc;
 
        virt = (void *) ((unsigned long) virt & PAGE_MASK);
-       desc = find_virtmem_hash(&virtmem_hash, virt);
+       desc = find_phys_mapping(virt);
        if(desc == NULL)
                return(0);
 
@@ -221,6 +221,10 @@ void physmem_forget_descriptor(int fd)
        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;
@@ -234,7 +238,9 @@ void arch_free_page(struct page *page, int order)
 
 int is_remapped(void *virt)
 {
-       return(find_virtmem_hash(&virtmem_hash, virt) != NULL);
+       struct phys_desc *desc = find_phys_mapping(virt);
+
+       return(desc != NULL);
 }
 
 /* Changed during early boot */
@@ -273,7 +279,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
 
        if(kmalloc_ok){
                map = kmalloc(total_len, GFP_KERNEL);
-               if(map == NULL) 
+               if(map == NULL)
                        map = vmalloc(total_len);
        }
        else map = alloc_bootmem_low_pages(total_len);
@@ -322,12 +328,12 @@ static unsigned long kmem_top = 0;
 
 unsigned long get_kmem_end(void)
 {
-       if(kmem_top == 0) 
+       if(kmem_top == 0)
                kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
        return(kmem_top);
 }
 
-void map_memory(unsigned long virt, unsigned long phys, unsigned long len, 
+void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
                int r, int w, int x)
 {
        __u64 offset;
@@ -335,9 +341,14 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
 
        fd = phys_mapping(phys, &offset);
        err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
-       if(err)
+       if(err) {
+               if(err == -ENOMEM)
+                       printk("try increasing the host's "
+                              "/proc/sys/vm/max_map_count to <physical "
+                              "memory size>/4096\n");
                panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
                      "err = %d\n", virt, fd, offset, len, r, w, x, err);
+       }
 }
 
 #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
@@ -353,7 +364,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
        physmem_fd = create_mem_file(len + highmem);
 
        offset = uml_reserved - uml_physmem;
-       err = os_map_memory((void *) uml_reserved, physmem_fd, offset, 
+       err = os_map_memory((void *) uml_reserved, physmem_fd, offset,
                            len - offset, 1, 1, 0);
        if(err < 0){
                os_print_error(err, "Mapping memory");
@@ -367,8 +378,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
 
 int phys_mapping(unsigned long phys, __u64 *offset_out)
 {
-       struct phys_desc *desc = find_virtmem_hash(&virtmem_hash, 
-                                                  __va(phys & PAGE_MASK));
+       struct phys_desc *desc = find_phys_mapping(__va(phys & PAGE_MASK));
        int fd = -1;
 
        if(desc != NULL){
@@ -381,9 +391,9 @@ int phys_mapping(unsigned long phys, __u64 *offset_out)
        }
        else if(phys < __pa(end_iomem)){
                struct iomem_region *region = iomem_regions;
-       
+
                while(region != NULL){
-                       if((phys >= region->phys) && 
+                       if((phys >= region->phys) &&
                           (phys < region->phys + region->size)){
                                fd = region->fd;
                                *offset_out = phys - region->phys;
@@ -419,7 +429,7 @@ __uml_setup("mem=", uml_mem_setup,
 unsigned long find_iomem(char *driver, unsigned long *len_out)
 {
        struct iomem_region *region = iomem_regions;
-       
+
        while(region != NULL){
                if(!strcmp(region->driver, driver)){
                        *len_out = region->size;
@@ -437,7 +447,7 @@ int setup_iomem(void)
        int err;
 
        while(region != NULL){
-               err = os_map_memory((void *) iomem_start, region->fd, 0, 
+               err = os_map_memory((void *) iomem_start, region->fd, 0,
                                    region->size, 1, 1, 0);
                if(err)
                        printk("Mapping iomem region for driver '%s' failed, "
index 52cfd60..74a69e4 100644 (file)
@@ -80,6 +80,12 @@ void unblock_signals(void)
        change_signals(SIG_UNBLOCK);
 }
 
+/* These are the asynchronous signals.  SIGVTALRM and SIGARLM are handled
+ * together under SIGVTALRM_BIT.  SIGPROF is excluded because we want to
+ * be able to profile all of UML, not just the non-critical sections.  If
+ * profiling is not thread-safe, then that is not my problem.  We can disable
+ * profiling when SMP is enabled in that case.
+ */
 #define SIGIO_BIT 0
 #define SIGVTALRM_BIT 1
 
@@ -114,6 +120,11 @@ int set_signals(int enable)
                sigaddset(&mask, SIGVTALRM);
                sigaddset(&mask, SIGALRM);
        }
+
+       /* This is safe - sigprocmask is guaranteed to copy locally the
+        * value of new_set, do his work and then, at the end, write to
+        * old_set.
+        */
        if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
                panic("Failed to enable signals");
        ret = enable_mask(&mask);
index ed3d6bc..02e3e06 100644 (file)
@@ -77,7 +77,7 @@ void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end)
        int updated = 0, err;
 
        mm = &init_mm;
-       for(addr = start_vm; addr < end_vm;){
+       for(addr = start; addr < end;){
                pgd = pgd_offset(mm, addr);
                pmd = pmd_offset(pgd, addr);
                if(pmd_present(*pmd)){
index ea82f19..77048cd 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
@@ -12,8 +12,9 @@
 #include "asm/pgtable.h"
 #include "asm/uaccess.h"
 #include "kern_util.h"
+#include "user_util.h"
 
-extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 
+extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
                             pte_t *pte_out);
 
 static unsigned long maybe_map(unsigned long virt, int is_write)
@@ -25,7 +26,7 @@ static unsigned long maybe_map(unsigned long virt, int is_write)
        int dummy_code;
 
        if(IS_ERR(phys) || (is_write && !pte_write(pte))){
-               err = handle_page_fault(virt, 0, is_write, 0, &dummy_code);
+               err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
                if(err)
                        return(0);
                phys = um_virt_to_phys(current, virt, NULL);
@@ -33,7 +34,7 @@ static unsigned long maybe_map(unsigned long virt, int is_write)
        return((unsigned long) phys);
 }
 
-static int do_op(unsigned long addr, int len, int is_write, 
+static int do_op(unsigned long addr, int len, int is_write,
                 int (*op)(unsigned long addr, int len, void *arg), void *arg)
 {
        struct page *page;
@@ -51,37 +52,67 @@ static int do_op(unsigned long addr, int len, int is_write,
        return(n);
 }
 
-static int buffer_op(unsigned long addr, int len, int is_write,
-                    int (*op)(unsigned long addr, int len, void *arg),
-                    void *arg)
+static void do_buffer_op(void *jmpbuf, void *arg_ptr)
 {
+       va_list args = *((va_list *) arg_ptr);
+       unsigned long addr = va_arg(args, unsigned long);
+       int len = va_arg(args, int);
+       int is_write = va_arg(args, int);
+       int (*op)(unsigned long, int, void *) = va_arg(args, void *);
+       void *arg = va_arg(args, void *);
+       int *res = va_arg(args, int *);
        int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
        int remain = len, n;
 
+       current->thread.fault_catcher = jmpbuf;
        n = do_op(addr, size, is_write, op, arg);
-       if(n != 0)
-               return(n < 0 ? remain : 0);
+       if(n != 0){
+               *res = (n < 0 ? remain : 0);
+               goto out;
+       }
 
        addr += size;
        remain -= size;
-       if(remain == 0) 
-               return(0);
+       if(remain == 0){
+               *res = 0;
+               goto out;
+       }
 
        while(addr < ((addr + remain) & PAGE_MASK)){
                n = do_op(addr, PAGE_SIZE, is_write, op, arg);
-               if(n != 0)
-                       return(n < 0 ? remain : 0);
+               if(n != 0){
+                       *res = (n < 0 ? remain : 0);
+                       goto out;
+               }
 
                addr += PAGE_SIZE;
                remain -= PAGE_SIZE;
        }
-       if(remain == 0)
-               return(0);
+       if(remain == 0){
+               *res = 0;
+               goto out;
+       }
 
        n = do_op(addr, remain, is_write, op, arg);
        if(n != 0)
-               return(n < 0 ? remain : 0);
-       return(0);
+               *res = (n < 0 ? remain : 0);
+       else *res = 0;
+ out:
+       current->thread.fault_catcher = NULL;
+}
+
+static int buffer_op(unsigned long addr, int len, int is_write,
+                    int (*op)(unsigned long addr, int len, void *arg),
+                    void *arg)
+{
+       int faulted, res;
+
+       faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
+                                &res);
+       if(!faulted)
+               return(res);
+
+       return(addr + len - (unsigned long) current->thread.fault_addr);
 }
 
 static int copy_chunk_from_user(unsigned long from, int len, void *arg)
@@ -135,7 +166,7 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
        n = strnlen(to, len);
        *to_ptr += n;
 
-       if(n < len) 
+       if(n < len)
                return(1);
        return(0);
 }
@@ -153,7 +184,7 @@ int strncpy_from_user_skas(char *dst, const char *src, int count)
        if(!access_ok_skas(VERIFY_READ, src, 1))
                return(-EFAULT);
 
-       n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, 
+       n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user,
                      &ptr);
        if(n != 0)
                return(-EFAULT);
@@ -178,7 +209,7 @@ int clear_user_skas(void *mem, int len)
                return(0);
        }
 
-       return(access_ok_skas(VERIFY_WRITE, mem, len) ? 
+       return(access_ok_skas(VERIFY_WRITE, mem, len) ?
               buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len);
 }
 
index 9c84011..0409718 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
@@ -8,7 +8,7 @@
 
 int copy_from_user_tt(void *to, const void *from, int n)
 {
-       if(!access_ok_tt(VERIFY_READ, from, n)) 
+       if(!access_ok_tt(VERIFY_READ, from, n))
                return(n);
 
        return(__do_copy_from_user(to, from, n, &current->thread.fault_addr,
@@ -19,7 +19,7 @@ int copy_to_user_tt(void *to, const void *from, int n)
 {
        if(!access_ok_tt(VERIFY_WRITE, to, n))
                return(n);
-               
+
        return(__do_copy_to_user(to, from, n, &current->thread.fault_addr,
                                 &current->thread.fault_catcher));
 }
@@ -28,10 +28,10 @@ int strncpy_from_user_tt(char *dst, const char *src, int count)
 {
        int n;
 
-       if(!access_ok_tt(VERIFY_READ, src, 1)) 
+       if(!access_ok_tt(VERIFY_READ, src, 1))
                return(-EFAULT);
 
-       n = __do_strncpy_from_user(dst, src, count, 
+       n = __do_strncpy_from_user(dst, src, count,
                                   &current->thread.fault_addr,
                                   &current->thread.fault_catcher);
        if(n < 0) return(-EFAULT);
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
new file mode 100644 (file)
index 0000000..89ed329
--- /dev/null
@@ -0,0 +1,96 @@
+#include <asm-generic/vmlinux.lds.h>
+
+OUTPUT_FORMAT(ELF_FORMAT)
+OUTPUT_ARCH(ELF_ARCH)
+ENTRY(_start)
+jiffies = jiffies_64;
+
+SECTIONS
+{
+  . = START + SIZEOF_HEADERS;
+
+  __binary_start = .;
+#ifdef MODE_TT
+  .thread_private : {
+    __start_thread_private = .;
+    errno = .;
+    . += 4;
+    arch/um/kernel/tt/unmap_fin.o (.data)
+    __end_thread_private = .;
+  }
+  . = ALIGN(4096);
+  .remap : { arch/um/kernel/tt/unmap_fin.o (.text) }
+#endif
+
+  . = ALIGN(4096);             /* Init code and data */
+  _stext = .;
+  __init_begin = .;
+  .init.text : {
+       _sinittext = .;
+       *(.init.text)
+       _einittext = .;
+  }
+  . = ALIGN(4096);
+  .text      :
+  {
+    *(.text)
+    SCHED_TEXT
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+    *(.gnu.linkonce.t*)
+  }
+
+  #include "asm/common.lds.S"
+
+  init.data : { *(init.data) }
+  .data    :
+  {
+    . = ALIGN(KERNEL_STACK_SIZE);              /* init_task */
+    *(.data.init_task)
+    *(.data)
+    *(.gnu.linkonce.d*)
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  .ctors         :
+  {
+    *(.ctors)
+  }
+  .dtors         :
+  {
+    *(.dtors)
+  }
+
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  _edata  =  .;
+  PROVIDE (edata = .);
+  . = ALIGN(0x1000);
+  .sbss      :
+  {
+   __bss_start = .;
+   PROVIDE(_bss_start = .);
+   *(.sbss)
+   *(.scommon)
+  }
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  _end = . ;
+  PROVIDE (end = .);
+  /* 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) }
+}
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
new file mode 100644 (file)
index 0000000..cf30a39
--- /dev/null
@@ -0,0 +1,21 @@
+#include <stdlib.h>
+#include <sys/time.h>
+
+unsigned long long os_usecs(void)
+{
+       struct timeval tv;
+
+       gettimeofday(&tv, NULL);
+       return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec);
+}
+
+/*
+ * 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 ef0fb71..2433c9e 100644 (file)
 
 extern size_t strlen(const char *);
 extern void *memcpy(void *, const void *, size_t);
+extern void *memmove(void *, const void *, size_t);
 extern void *memset(void *, int, size_t);
 extern int printf(const char *, ...);
 
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(printf);
 
 EXPORT_SYMBOL(strstr);
 
 /* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
- * However, the modules will use the CRC defined *here*, no matter if it is 
+ * However, the modules will use the CRC defined *here*, no matter if it is
  * good; so the versions of these symbols will always match
  */
 #define EXPORT_SYMBOL_PROTO(sym)       \
index 751549b..6ad3174 100644 (file)
@@ -3,6 +3,7 @@
  * Licensed under the GPL
  */
 
+#include "linux/sched.h"
 #include "asm/mman.h"
 #include "asm/uaccess.h"
 #include "asm/unistd.h"
@@ -56,6 +57,27 @@ int old_select(struct sel_arg_struct *arg)
        return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
 }
 
+/* The i386 version skips reading from %esi, the fourth argument. So we must do
+ * this, too.
+ */
+int sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tid,
+             int unused, int *child_tid)
+{
+       long ret;
+
+       /* XXX: normal arch do here this pass, and also pass the regs to
+        * do_fork, instead of NULL. Currently the arch-independent code
+        * ignores these values, while the UML code (actually it's
+        * copy_thread) does the right thing. But this should change,
+        probably. */
+       /*if (!newsp)
+               newsp = UPT_SP(current->thread.regs);*/
+       current->thread.forking = 1;
+       ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
+       current->thread.forking = 0;
+       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
diff --git a/arch/v850/Kconfig.debug b/arch/v850/Kconfig.debug
new file mode 100644 (file)
index 0000000..4acfb9c
--- /dev/null
@@ -0,0 +1,10 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config NO_KERNEL_MSG
+       bool "Suppress Kernel BUG Messages"
+       help
+         Do not output any debug BUG messages within the kernel.
+
+endmenu
index 117bcaa..3930482 100644 (file)
@@ -9,7 +9,7 @@
 # for more details.
 #
 
-extra-y := head.o init_task.o vmlinux.lds.s
+extra-y := head.o init_task.o vmlinux.lds
 
 obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \
         signal.o irq.o mach.o ptrace.o bug.o
index 666930d..24f2913 100644 (file)
@@ -12,8 +12,8 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
+#include <linux/hardirq.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/errno.h>
 
 #define DEFINE(sym, val) \
index da39beb..551c41b 100644 (file)
@@ -322,8 +322,6 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
 \f
 /* Stubs for things we don't use.  */
 
-struct pci_fixup pcibios_fixups[] = { { 0 } };
-
 /* Called after each bus is probed, but before its children are examined. */
 void pcibios_fixup_bus(struct pci_bus *b)
 {
index caa9e3a..60098e4 100644 (file)
@@ -344,9 +344,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
        return;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -421,9 +419,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        return;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
 }
 
 /*
index 2336da4..0ca6490 100644 (file)
@@ -14,7 +14,6 @@
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/checksum.h>
-#include <asm/hardirq.h>
 #include <asm/current.h>
 
 
@@ -37,29 +36,29 @@ EXPORT_SYMBOL (ip_compute_csum);
 EXPORT_SYMBOL (ip_fast_csum);
 
 /* string / mem functions */
-EXPORT_SYMBOL_NOVERS (strcpy);
-EXPORT_SYMBOL_NOVERS (strncpy);
-EXPORT_SYMBOL_NOVERS (strcat);
-EXPORT_SYMBOL_NOVERS (strncat);
-EXPORT_SYMBOL_NOVERS (strcmp);
-EXPORT_SYMBOL_NOVERS (strncmp);
-EXPORT_SYMBOL_NOVERS (strchr);
-EXPORT_SYMBOL_NOVERS (strlen);
-EXPORT_SYMBOL_NOVERS (strnlen);
-EXPORT_SYMBOL_NOVERS (strpbrk);
-EXPORT_SYMBOL_NOVERS (strrchr);
-EXPORT_SYMBOL_NOVERS (strstr);
-EXPORT_SYMBOL_NOVERS (memset);
-EXPORT_SYMBOL_NOVERS (memcpy);
-EXPORT_SYMBOL_NOVERS (memmove);
-EXPORT_SYMBOL_NOVERS (memcmp);
-EXPORT_SYMBOL_NOVERS (memscan);
+EXPORT_SYMBOL (strcpy);
+EXPORT_SYMBOL (strncpy);
+EXPORT_SYMBOL (strcat);
+EXPORT_SYMBOL (strncat);
+EXPORT_SYMBOL (strcmp);
+EXPORT_SYMBOL (strncmp);
+EXPORT_SYMBOL (strchr);
+EXPORT_SYMBOL (strlen);
+EXPORT_SYMBOL (strnlen);
+EXPORT_SYMBOL (strpbrk);
+EXPORT_SYMBOL (strrchr);
+EXPORT_SYMBOL (strstr);
+EXPORT_SYMBOL (memset);
+EXPORT_SYMBOL (memcpy);
+EXPORT_SYMBOL (memmove);
+EXPORT_SYMBOL (memcmp);
+EXPORT_SYMBOL (memscan);
 
 /* semaphores */
-EXPORT_SYMBOL_NOVERS (__down);
-EXPORT_SYMBOL_NOVERS (__down_interruptible);
-EXPORT_SYMBOL_NOVERS (__down_trylock);
-EXPORT_SYMBOL_NOVERS (__up);
+EXPORT_SYMBOL (__down);
+EXPORT_SYMBOL (__down_interruptible);
+EXPORT_SYMBOL (__down_trylock);
+EXPORT_SYMBOL (__up);
 
 /*
  * libgcc functions - functions that are used internally by the
@@ -72,8 +71,8 @@ extern void __lshrdi3 (void);
 extern void __muldi3 (void);
 extern void __negdi2 (void);
 
-EXPORT_SYMBOL_NOVERS (__ashldi3);
-EXPORT_SYMBOL_NOVERS (__ashrdi3);
-EXPORT_SYMBOL_NOVERS (__lshrdi3);
-EXPORT_SYMBOL_NOVERS (__muldi3);
-EXPORT_SYMBOL_NOVERS (__negdi2);
+EXPORT_SYMBOL (__ashldi3);
+EXPORT_SYMBOL (__ashrdi3);
+EXPORT_SYMBOL (__lshrdi3);
+EXPORT_SYMBOL (__muldi3);
+EXPORT_SYMBOL (__negdi2);
diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
new file mode 100644 (file)
index 0000000..2ba7f5a
--- /dev/null
@@ -0,0 +1,59 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+# !SMP for now because the context switch early causes GPF in segment reloading
+# and the GS base checking does the wrong thing then, causing a hang.
+config CHECKING
+       bool "Additional run-time checks"
+       depends on DEBUG_KERNEL && !SMP
+       help
+         Enables some internal consistency checks for kernel debugging.
+         You should normally say N.
+
+config INIT_DEBUG
+       bool "Debug __init statements"
+       depends on DEBUG_KERNEL
+       help
+         Fill __init and __initdata at the end of boot. This helps debugging
+         illegal uses of __init and __initdata after initialization.
+
+config SCHEDSTATS
+       bool "Collect scheduler statistics"
+       depends on DEBUG_KERNEL && PROC_FS
+       help
+         If you say Y here, additional code will be inserted into the
+         scheduler and related routines to collect statistics about
+         scheduler behavior and provide them in /proc/schedstat.  These
+         stats may be useful for both tuning and debugging the scheduler
+         If you aren't debugging the scheduler or trying to tune a specific
+         application, you can say N to avoid the very slight overhead
+         this adds.
+
+config IOMMU_DEBUG
+       depends on GART_IOMMU && DEBUG_KERNEL
+       bool "Enable IOMMU debugging"
+       help
+         Force the IOMMU to on even when you have less than 4GB of
+        memory and add debugging code. On overflow always panic. And
+        allow to enable IOMMU leak tracing. Can be disabled at boot
+        time with iommu=noforce. This will also enable scatter gather
+        list merging.  Currently not recommended for production
+        code. When you use it make sure you have a big enough
+        IOMMU/AGP aperture.  Most of the options enabled by this can
+        be set more finegrained using the iommu= command line
+        options. See Documentation/x86_64/boot-options.txt for more
+        details.
+
+config IOMMU_LEAK
+       bool "IOMMU leak tracing"
+       depends on DEBUG_KERNEL
+       depends on IOMMU_DEBUG
+       help
+         Add a simple leak tracer to the IOMMU code. This is useful when you
+        are debugging a buggy device driver that leaks IOMMU mappings.
+
+#config X86_REMOTE_DEBUG
+#       bool "kgdb debugging stub"
+
+endmenu
index 1c2d3cb..99b7904 100644 (file)
@@ -30,7 +30,7 @@ targets               := vmlinux.bin bootsect bootsect.o \
 
 EXTRA_CFLAGS := -m32
 
-host-progs     := tools/build
+hostprogs-y    := tools/build
 subdir-                := compressed/  #Let make clean descend in compressed/
 # ---------------------------------------------------------------------------
 
index 5d4cdc1..fd0cc73 100644 (file)
@@ -66,6 +66,7 @@
 #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 */
@@ -97,7 +98,6 @@
 #define PARAM_LFB_PAGES                0x32
 #define PARAM_VESA_ATTRIB      0x34
 
-
 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
 #ifdef CONFIG_VIDEO_RETAIN
 #define DO_STORE call store_screen
@@ -133,6 +133,7 @@ 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
@@ -231,6 +232,41 @@ mopar_gr:
        xorl    %eax, %eax
        movw    18(%di), %ax
        movl    %eax, %fs:(PARAM_LFB_SIZE)
+
+# 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
@@ -440,7 +476,7 @@ setalias:
 
 # Setting of user mode (AX=mode ID) => CF=success
 mode_set:
-               movw    %ax, %fs:(0x01fa)
+       movw    %ax, %fs:(0x01fa)               # Store mode for use in acpi_wakeup.S
        movw    %ax, %bx
        cmpb    $0xff, %ah
        jz      setalias
@@ -744,7 +780,15 @@ set_80x60:
        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
@@ -969,6 +1013,10 @@ vga_modes:
        .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.
@@ -1875,6 +1923,39 @@ skip10:  movb    %ah, %al
        popw    %ax
        ret
 
+store_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    $0x440, %di
+       cld
+       rep
+       stosl
+
+       movw    $0x4f15, %ax                    # do VBE/DDC
+       movw    $0x01, %bx
+       movw    $0x00, %cx
+       movw    $0x01, %dx
+       movw    $0x440, %di
+       int     $0x10
+
+       popw    %di                             # restore all registers
+       popw    %dx
+       popw    %cx
+       popw    %bx
+       popw    %ax
+       popw    %es
+       ret
+
 # VIDEO_SELECT-only variables
 mt_end:                .word   0       # End of video mode table if built
 edit_buf:      .space  6       # Line editor buffer
@@ -1883,6 +1964,7 @@ 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
 
 # Status messages
 keymsg:                .ascii  "Press <RETURN> to see video modes available, "
index 164b6d0..1d8b391 100644 (file)
@@ -31,6 +31,8 @@ int iommu_aperture_allowed __initdata = 0;
 int fallback_aper_order __initdata = 1; /* 64MB */
 int fallback_aper_force __initdata = 0; 
 
+int fix_aperture __initdata = 1;
+
 /* This code runs before the PCI subsystem is initialized, so just 
    access the northbridge directly. */
 
@@ -202,7 +204,7 @@ void __init iommu_hole_init(void)
        u64 aper_base; 
        int valid_agp = 0;
 
-       if (iommu_aperture_disabled)
+       if (iommu_aperture_disabled || !fix_aperture)
                return;
 
        printk("Checking aperture...\n"); 
@@ -241,20 +243,15 @@ void __init iommu_hole_init(void)
                /* Got the aperture from the AGP bridge */
        } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
                   force_iommu ||
-                  valid_agp || 
+                  valid_agp ||
                   fallback_aper_force) { 
-               /* When there is a AGP bridge in the system assume the
-                  user wants to use the AGP driver too and needs an
-                  aperture.  However this case (AGP but no good
-                  aperture) should only happen with a more broken than
-                  usual BIOS, because it would even break Windows. */
-
-       printk("Your BIOS doesn't leave a aperture memory hole\n");
-       printk("Please enable the IOMMU option in the BIOS setup\n"); 
-               printk("This costs you %d MB of RAM\n", 32 << fallback_aper_order); 
+               printk("Your BIOS doesn't leave a aperture memory hole\n");
+               printk("Please enable the IOMMU option in the BIOS setup\n");
+               printk("This costs you %d MB of RAM\n",
+                      32 << fallback_aper_order);
+
                aper_order = fallback_aper_order;
-       aper_alloc = allocate_aperture(); 
+               aper_alloc = allocate_aperture();
                if (!aper_alloc) { 
                        /* Could disable AGP and IOMMU here, but it's probably
                           not worth it. But the later users cannot deal with
index 6fb84e2..ddd8aac 100644 (file)
@@ -33,6 +33,8 @@
 #include <asm/mpspec.h>
 #include <asm/pgalloc.h>
 
+int apic_verbosity;
+
 int disable_apic_timer __initdata;
 
 /* Using APIC to generate smp_local_timer_interrupt? */
@@ -123,7 +125,7 @@ void __init connect_bsp_APIC(void)
                 * PIC mode, enable APIC mode in the IMCR, i.e.
                 * connect BSP's local APIC to INT and NMI lines.
                 */
-               printk(KERN_INFO "leaving PIC mode, enabling APIC mode.\n");
+               apic_printk(APIC_VERBOSE, "leaving PIC mode, enabling APIC mode.\n");
                outb(0x70, 0x22);
                outb(0x01, 0x23);
        }
@@ -138,7 +140,7 @@ void disconnect_bsp_APIC(void)
                 * interrupts, including IPIs, won't work beyond
                 * this point!  The only exception are INIT IPIs.
                 */
-               printk(KERN_INFO "disabling APIC mode, entering PIC mode.\n");
+               apic_printk(APIC_QUIET, "disabling APIC mode, entering PIC mode.\n");
                outb(0x70, 0x22);
                outb(0x00, 0x23);
        }
@@ -172,10 +174,10 @@ int __init verify_local_APIC(void)
         * The version register is read-only in a real APIC.
         */
        reg0 = apic_read(APIC_LVR);
-       Dprintk("Getting VERSION: %x\n", reg0);
+       apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0);
        apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK);
        reg1 = apic_read(APIC_LVR);
-       Dprintk("Getting VERSION: %x\n", reg1);
+       apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1);
 
        /*
         * The two version reads above should print the same
@@ -199,10 +201,10 @@ int __init verify_local_APIC(void)
         * The ID register is read/write in a real APIC.
         */
        reg0 = apic_read(APIC_ID);
-       Dprintk("Getting ID: %x\n", reg0);
+       apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
        apic_write(APIC_ID, reg0 ^ APIC_ID_MASK);
        reg1 = apic_read(APIC_ID);
-       Dprintk("Getting ID: %x\n", reg1);
+       apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1);
        apic_write(APIC_ID, reg0);
        if (reg1 != (reg0 ^ APIC_ID_MASK))
                return 0;
@@ -213,9 +215,9 @@ int __init verify_local_APIC(void)
         * compatibility mode, but most boxes are anymore.
         */
        reg0 = apic_read(APIC_LVT0);
-       Dprintk("Getting LVT0: %x\n", reg0);
+       apic_printk(APIC_DEBUG,"Getting LVT0: %x\n", reg0);
        reg1 = apic_read(APIC_LVT1);
-       Dprintk("Getting LVT1: %x\n", reg1);
+       apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1);
 
        return 1;
 }
@@ -227,7 +229,7 @@ void __init sync_Arb_IDs(void)
         */
        apic_wait_icr_idle();
 
-       Dprintk("Synchronizing Arb IDs.\n");
+       apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
        apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
                                | APIC_DM_INIT);
 }
@@ -388,10 +390,10 @@ void __init setup_local_APIC (void)
        value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
        if (!smp_processor_id() && (pic_mode || !value)) {
                value = APIC_DM_EXTINT;
-               Dprintk(KERN_INFO "enabled ExtINT on CPU#%d\n", smp_processor_id());
+               apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", smp_processor_id());
        } else {
                value = APIC_DM_EXTINT | APIC_LVT_MASKED;
-               Dprintk(KERN_INFO "masked ExtINT on CPU#%d\n", smp_processor_id());
+               apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", smp_processor_id());
        }
        apic_write_around(APIC_LVT0, value);
 
@@ -407,12 +409,11 @@ void __init setup_local_APIC (void)
        apic_write_around(APIC_LVT1, value);
 
        if (APIC_INTEGRATED(ver) && !esr_disable) {             /* !82489DX */
+               unsigned oldvalue;
                maxlvt = get_maxlvt();
                if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
                        apic_write(APIC_ESR, 0);
-               value = apic_read(APIC_ESR);
-               Dprintk("ESR value before enabling vector: %08x\n", value);
-
+               oldvalue = apic_read(APIC_ESR);
                value = ERROR_APIC_VECTOR;      // enables sending errors
                apic_write_around(APIC_LVTERR, value);
                /*
@@ -421,7 +422,10 @@ void __init setup_local_APIC (void)
                if (maxlvt > 3)
                        apic_write(APIC_ESR, 0);
                value = apic_read(APIC_ESR);
-               Dprintk("ESR value after enabling vector: %08x\n", value);
+               if (value != oldvalue)
+                       apic_printk(APIC_VERBOSE,
+                       "ESR value after enabling vector: %08x, after %08x\n",
+                       oldvalue, value);
        } else {
                if (esr_disable)        
                        /* 
@@ -430,9 +434,9 @@ void __init setup_local_APIC (void)
                         * ESR disabled - we can't do anything useful with the
                         * errors anyway - mbligh
                         */
-                       printk("Leaving ESR disabled.\n");
+                       apic_printk(APIC_DEBUG, "Leaving ESR disabled.\n");
                else 
-                       printk("No ESR for 82489DX.\n");
+                       apic_printk(APIC_DEBUG, "No ESR for 82489DX.\n");
        }
 
        nmi_watchdog_default();
@@ -564,6 +568,21 @@ static void apic_pm_activate(void) { }
 
 #endif /* CONFIG_PM */
 
+static int __init apic_set_verbosity(char *str)
+{
+       if (strcmp("debug", str) == 0)
+               apic_verbosity = APIC_DEBUG;
+       else if (strcmp("verbose", str) == 0)
+               apic_verbosity = APIC_VERBOSE;
+       else
+               printk(KERN_WARNING "APIC Verbosity level %s not recognised"
+                               " use apic=verbose or apic=debug", str);
+
+       return 0;
+}
+
+__setup("apic=", apic_set_verbosity);
+
 /*
  * Detect and enable local APICs on non-SMP boards.
  * Original code written by Keir Fraser.
@@ -599,7 +618,7 @@ void __init init_apic_mappings(void)
                apic_phys = mp_lapic_addr;
 
        set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
-       Dprintk("mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys);
+       apic_printk(APIC_VERBOSE,"mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys);
 
        /*
         * Fetch the APIC ID of the BSP in case we have a
@@ -621,7 +640,7 @@ void __init init_apic_mappings(void)
                                ioapic_phys = __pa(ioapic_phys);
                        }
                        set_fixmap_nocache(idx, ioapic_phys);
-                       Dprintk("mapped IOAPIC to %016lx (%016lx)\n",
+                       apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n",
                                        __fix_to_virt(idx), ioapic_phys);
                        idx++;
                }
@@ -836,8 +855,7 @@ void smp_local_timer_interrupt(struct pt_regs *regs)
 {
        int cpu = smp_processor_id();
 
-       x86_do_profile(regs);
-
+       profile_tick(CPU_PROFILING, regs);
        if (--per_cpu(prof_counter, cpu) <= 0) {
                /*
                 * The multiplier may have changed since the last time we got
@@ -962,7 +980,7 @@ asmlinkage void smp_error_interrupt(void)
           6: Received illegal vector
           7: Illegal register address
        */
-       printk (KERN_INFO "APIC error on CPU%d: %02x(%02x)\n",
+       printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
                smp_processor_id(), v , v1);
        irq_exit();
 }
index 757f550..37d12fa 100644 (file)
@@ -7,8 +7,8 @@
 #include <linux/sched.h> 
 #include <linux/stddef.h>
 #include <linux/errno.h> 
+#include <linux/hardirq.h>
 #include <asm/pda.h>
-#include <asm/hardirq.h>
 #include <asm/processor.h>
 #include <asm/segment.h>
 #include <asm/thread_info.h>
index 1b3aefc..dcb518e 100644 (file)
@@ -41,4 +41,58 @@ config X86_POWERNOW_K8
 
          If in doubt, say N.
 
+config X86_POWERNOW_K8_ACPI
+       bool
+       depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y"))
+       default y
+
+config X86_SPEEDSTEP_CENTRINO
+       tristate "Intel Enhanced SpeedStep"
+       depends on CPU_FREQ_TABLE
+       help
+         This adds the CPUFreq driver for Enhanced SpeedStep enabled
+         mobile CPUs.  This means Intel Pentium M (Centrino) CPUs
+         or 64bit enabled Intel Xeons.
+
+         For details, take a look at <file:Documentation/cpu-freq/>.
+
+         If in doubt, say N.
+
+config X86_SPEEDSTEP_CENTRINO_TABLE
+       bool
+       depends on X86_SPEEDSTEP_CENTRINO
+       default y
+
+config X86_SPEEDSTEP_CENTRINO_ACPI
+       bool "Use ACPI tables to decode valid frequency/voltage pairs (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       depends on ((X86_SPEEDSTEP_CENTRINO = "m" && ACPI_PROCESSOR) || (X86_SPEEDSTEP_CENTRINO = "y" && ACPI_PROCESSOR = "y"))
+       help
+         Use primarily the information provided in the BIOS ACPI tables
+         to determine valid CPU frequency and voltage pairings.
+
+         If in doubt, say Y.
+
+config X86_ACPI_CPUFREQ
+       tristate "ACPI Processor P-States driver"
+       depends on CPU_FREQ_TABLE && ACPI_PROCESSOR
+       help
+         This driver adds a CPUFreq driver which utilizes the ACPI
+         Processor Performance States.
+
+         For details, take a look at <file:Documentation/cpu-freq/>.
+
+         If in doubt, say N.
+
+config X86_ACPI_CPUFREQ_PROC_INTF
+        bool "/proc/acpi/processor/../performance interface (deprecated)"
+       depends on X86_ACPI_CPUFREQ && PROC_FS
+       help
+         This enables the deprecated /proc/acpi/processor/../performance
+         interface. While it is helpful for debugging, the generic,
+         cross-architecture cpufreq interfaces should be used.
+
+         If in doubt, say N.
+
 endmenu
+
index f02ed52..d0f0b2c 100644 (file)
@@ -2,6 +2,12 @@
 # Reuse the i386 cpufreq drivers
 #
 
+SRCDIR := ../../../i386/kernel/cpu/cpufreq
+
 obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
+obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
+obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi.o
 
-powernow-k8-objs := ../../../i386/kernel/cpu/cpufreq/powernow-k8.o
+powernow-k8-objs := ${SRCDIR}/powernow-k8.o
+speedstep-centrino-objs := ${SRCDIR}/speedstep-centrino.o
+acpi-objs := ${SRCDIR}/acpi.o
index 98041f5..600ec81 100644 (file)
@@ -8,7 +8,7 @@
 /* Simple VGA output */
 
 #ifdef __i386__
-#define VGABASE                __pa(__PAGE_OFFSET + 0xb8000UL)
+#define VGABASE                (__ISA_IO_base + 0xb8000)
 #else
 #define VGABASE                0xffffffff800b8000UL
 #endif
@@ -99,18 +99,17 @@ static void early_serial_write(struct console *con, const char *s, unsigned n)
 
 #define DEFAULT_BAUD 9600
 
-static __init void early_serial_init(char *opt)
+static __init void early_serial_init(char *s)
 {
        unsigned char c; 
        unsigned divisor;
        unsigned baud = DEFAULT_BAUD;
-       char *s, *e;
+       char *e;
 
-       if (*opt == ',') 
-               ++opt;
+       if (*s == ',')
+               ++s;
 
-       s = strsep(&opt, ","); 
-       if (s != NULL) { 
+       if (*s) {
                unsigned port; 
                if (!strncmp(s,"0x",2)) {
                        early_serial_base = simple_strtoul(s, &e, 16);
@@ -124,6 +123,9 @@ static __init void early_serial_init(char *opt)
                                port = 0;
                        early_serial_base = bases[port];
                }
+               s += strcspn(s, ",");
+               if (*s == ',')
+                       s++;
        }
 
        outb(0x3, early_serial_base + LCR);     /* 8n1 */
@@ -131,8 +133,7 @@ static __init void early_serial_init(char *opt)
        outb(0, early_serial_base + FCR);       /* no fifo */
        outb(0x3, early_serial_base + MCR);     /* DTR + RTS */
 
-       s = strsep(&opt, ","); 
-       if (s != NULL) { 
+       if (*s) {
                baud = simple_strtoul(s, &e, 0); 
                if (baud == 0 || s == e) 
                        baud = DEFAULT_BAUD;
index 89f74f7..17d74eb 100644 (file)
@@ -297,7 +297,7 @@ int_very_careful:
        sti
        SAVE_REST
        /* Check for syscall exit trace */      
-       testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),%edx
+       testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
        jz int_signal
        pushq %rdi
        leaq 8(%rsp),%rdi       # &ptregs -> arg1       
@@ -305,6 +305,7 @@ int_very_careful:
        popq %rdi
        btr  $TIF_SYSCALL_TRACE,%edi
        btr  $TIF_SYSCALL_AUDIT,%edi
+       btr  $TIF_SINGLESTEP,%edi
        jmp int_restore_rest
        
 int_signal:
@@ -323,19 +324,20 @@ int_restore_rest:
  * Certain special system calls that need to save a complete full stack frame.
  */                                                            
        
-       .macro PTREGSCALL label,func
+       .macro PTREGSCALL label,func,arg
        .globl \label
 \label:
        leaq    \func(%rip),%rax
+       leaq    -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
        jmp     ptregscall_common
        .endm
 
-       PTREGSCALL stub_clone, sys_clone
-       PTREGSCALL stub_fork, sys_fork
-       PTREGSCALL stub_vfork, sys_vfork
-       PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend
-       PTREGSCALL stub_sigaltstack, sys_sigaltstack
-       PTREGSCALL stub_iopl, sys_iopl
+       PTREGSCALL stub_clone, sys_clone, %r8
+       PTREGSCALL stub_fork, sys_fork, %rdi
+       PTREGSCALL stub_vfork, sys_vfork, %rdi
+       PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx
+       PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
+       PTREGSCALL stub_iopl, sys_iopl, %rsi
 
 ENTRY(ptregscall_common)
        CFI_STARTPROC
@@ -385,6 +387,7 @@ ENTRY(stub_rt_sigreturn)
        CFI_STARTPROC
        addq $8, %rsp           
        SAVE_REST
+       movq %rsp,%rdi
        FIXUP_TOP_OF_STACK %r11
        call sys_rt_sigreturn
        movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
index 0a90fd0..cde0e86 100644 (file)
@@ -28,12 +28,12 @@ static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int ex
                        clear_bit(i, bitmap); 
 }
 
-
 /*
  * this changes the io permissions bitmap in the current task.
  */
 asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
+       unsigned int i, max_long, bytes, bytes_updated;
        struct thread_struct * t = &current->thread;
        struct tss_struct * tss;
        unsigned long *bitmap;
@@ -59,16 +59,34 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 
        /*
         * do it in the per-thread copy and in the TSS ...
+        *
+        * Disable preemption via get_cpu() - we must not switch away
+        * because the ->io_bitmap_max value must match the bitmap
+        * contents:
         */
+       tss = &per_cpu(init_tss, get_cpu());
+
        set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
-       tss = init_tss + get_cpu();
-       if (tss->io_bitmap_base == IO_BITMAP_OFFSET) { /* already active? */
-               set_bitmap(tss->io_bitmap, from, num, !turn_on);
-       } else {
-               memcpy(tss->io_bitmap, t->io_bitmap_ptr, IO_BITMAP_BYTES);
-               tss->io_bitmap_base = IO_BITMAP_OFFSET; /* Activate it in the TSS */
-       }
+
+       /*
+        * Search for a (possibly new) maximum. This is simple and stupid,
+        * to keep it obviously correct:
+        */
+       max_long = 0;
+       for (i = 0; i < IO_BITMAP_LONGS; i++)
+               if (t->io_bitmap_ptr[i] != ~0UL)
+                       max_long = i;
+
+       bytes = (max_long + 1) * sizeof(long);
+       bytes_updated = max(bytes, t->io_bitmap_max);
+
+       t->io_bitmap_max = bytes;
+
+       /* Update the TSS: */
+       memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated);
+
        put_cpu();
+
        return 0;
 }
 
@@ -83,9 +101,9 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
  * code.
  */
 
-asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs)
+asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
 {
-       unsigned int old = (regs.eflags >> 12) & 3;
+       unsigned int old = (regs->eflags >> 12) & 3;
 
        if (level > 3)
                return -EINVAL;
@@ -94,6 +112,6 @@ asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs)
                if (!capable(CAP_SYS_RAWIO))
                        return -EPERM;
        }
-       regs.eflags = (regs.eflags &~ 0x3000UL) | (level << 12);
+       regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12);
        return 0;
 }
index 35dd5df..4920c8d 100644 (file)
@@ -390,7 +390,8 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
                 */
                alert_counter[cpu]++;
                if (alert_counter[cpu] == 5*nmi_hz) {
-                       if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_BAD) { 
+                       if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
+                                                       == NOTIFY_STOP) {
                                alert_counter[cpu] = 0; 
                                return;
                        } 
index 7eb3fc7..cab471c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Dynamic DMA mapping support. Common code
+ * Dynamic DMA mapping support.
  */
 
 #include <linux/types.h>
  * Device ownership issues as mentioned above for pci_map_single are
  * the same here.
  */
-int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-                            int nents, int direction)
+int dma_map_sg(struct device *hwdev, struct scatterlist *sg,
+              int nents, int direction)
 {
        int i;
 
-       BUG_ON(direction == PCI_DMA_NONE);
+       BUG_ON(direction == DMA_NONE);
        for (i = 0; i < nents; i++ ) {
                struct scatterlist *s = &sg[i];
                BUG_ON(!s->page); 
-                       s->dma_address = pci_map_page(hwdev, s->page, s->offset, 
-                                                     s->length, direction); 
+               s->dma_address = virt_to_bus(page_address(s->page) +s->offset);
                s->dma_length = s->length;
        }
        return nents;
 }
 
-EXPORT_SYMBOL(pci_map_sg);
+EXPORT_SYMBOL(dma_map_sg);
 
 /* Unmap a set of streaming mode DMA translations.
  * Again, cpu read rules concerning calls here are the same as for
  * pci_unmap_single() above.
  */
-void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg, 
-                                 int nents, int dir)
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+                 int nents, int dir)
 {
        int i;
        for (i = 0; i < nents; i++) { 
                struct scatterlist *s = &sg[i];
                BUG_ON(s->page == NULL); 
                BUG_ON(s->dma_address == 0); 
-               pci_unmap_single(dev, s->dma_address, s->dma_length, dir); 
+               dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
        } 
 }
 
-EXPORT_SYMBOL(pci_unmap_sg);
+EXPORT_SYMBOL(dma_unmap_sg);
index 00fb264..67d90b8 100644 (file)
@@ -1,8 +1,11 @@
+/* Fallback functions when the main IOMMU code is not compiled in. This
+   code is roughly equivalent to i386. */
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <asm/proto.h>
+#include <asm/processor.h>
 
 int iommu_merge = 0;
 EXPORT_SYMBOL(iommu_merge);
@@ -10,57 +13,80 @@ EXPORT_SYMBOL(iommu_merge);
 dma_addr_t bad_dma_address;
 EXPORT_SYMBOL(bad_dma_address);
 
+int iommu_bio_merge = 0;
+EXPORT_SYMBOL(iommu_bio_merge);
+
+int iommu_sac_force = 0;
+EXPORT_SYMBOL(iommu_sac_force);
+
 /* 
  * Dummy IO MMU functions
  */
 
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                          dma_addr_t *dma_handle)
+void *dma_alloc_coherent(struct device *hwdev, size_t size,
+                        dma_addr_t *dma_handle, unsigned gfp)
 {
        void *ret;
-       int gfp = GFP_ATOMIC;
-       
-       if (hwdev == NULL ||
-           end_pfn > (hwdev->dma_mask>>PAGE_SHIFT) ||  /* XXX */
-           (u32)hwdev->dma_mask < 0xffffffff)
-               gfp |= GFP_DMA;
-       ret = (void *)__get_free_pages(gfp, get_order(size));
+       u64 mask;
+       int order = get_order(size);
 
-       if (ret != NULL) {
-               memset(ret, 0, size);
+       if (hwdev)
+               mask = hwdev->coherent_dma_mask & *hwdev->dma_mask;
+       else
+               mask = 0xffffffff;
+       for (;;) {
+               ret = (void *)__get_free_pages(gfp, order);
+               if (ret == NULL)
+                       return NULL;
                *dma_handle = virt_to_bus(ret);
+               if ((*dma_handle & ~mask) == 0)
+                       break;
+               free_pages((unsigned long)ret, order);
+               if (gfp & GFP_DMA)
+                       return NULL;
+               gfp |= GFP_DMA;
        }
+
+       memset(ret, 0, size);
        return ret;
 }
+EXPORT_SYMBOL(dma_alloc_coherent);
 
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+void dma_free_coherent(struct device *hwdev, size_t size,
                         void *vaddr, dma_addr_t dma_handle)
 {
        free_pages((unsigned long)vaddr, get_order(size));
 }
+EXPORT_SYMBOL(dma_free_coherent);
 
-int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
+int dma_supported(struct device *hwdev, u64 mask)
 {
         /*
          * we fall back to GFP_DMA when the mask isn't all 1s,
          * so we can't guarantee allocations that must be
          * within a tighter range than GFP_DMA..
-                * RED-PEN this won't work for pci_map_single. Caller has to
-                * use GFP_DMA in the first place.
+        * RED-PEN this won't work for pci_map_single. Caller has to
+        * use GFP_DMA in the first place.
          */
         if (mask < 0x00ffffff)
                 return 0;
 
        return 1;
 } 
+EXPORT_SYMBOL(dma_supported);
 
-EXPORT_SYMBOL(pci_dma_supported);
+int dma_get_cache_alignment(void)
+{
+       return boot_cpu_data.x86_clflush_size;
+}
+EXPORT_SYMBOL(dma_get_cache_alignment);
 
 static int __init check_ram(void) 
 { 
        if (end_pfn >= 0xffffffff>>PAGE_SHIFT) { 
-               printk(KERN_ERR "WARNING more than 4GB of memory but no IOMMU.\n"
-                      KERN_ERR "WARNING 32bit PCI may malfunction.\n"); 
+               printk(
+               KERN_ERR "WARNING more than 4GB of memory but IOMMU not compiled in.\n"
+               KERN_ERR "WARNING 32bit PCI may malfunction.\n");
        } 
        return 0;
 } 
index 99a1adf..8a39998 100644 (file)
@@ -1,22 +1,18 @@
-/* originally gcc generated, but now changed. don't overwrite. */
+/* Originally gcc generated, modified by hand
+ *
+ * This may not use any stack, nor any variable that is not "NoSave":
+ *
+ * Its rewriting one kernel image with another. What is stack in "old"
+ * image could very well be data page in "new" image, and overwriting
+ * your own stack under you is bad idea.
+ */
        
        .text
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/page.h>
 
-/* Input:
- * rdi resume flag 
- */    
-                       
-ENTRY(do_magic)
-.LFB5:
-       subq    $8, %rsp
-.LCFI2:
-       testl   %edi, %edi
-       jne     .L90
-       call    do_magic_suspend_1
-       call    save_processor_state
+ENTRY(swsusp_arch_suspend)
 
        movq %rsp, saved_context_esp(%rip)
        movq %rax, saved_context_eax(%rip)
@@ -36,36 +32,35 @@ ENTRY(do_magic)
        movq %r15, saved_context_r15(%rip)
        pushfq ; popq saved_context_eflags(%rip)
 
-       addq    $8, %rsp
-       jmp     do_magic_suspend_2
-.L90:
+       call swsusp_save
+       ret
+
+ENTRY(swsusp_arch_resume)
        /* set up cr3 */        
        leaq    init_level4_pgt(%rip),%rax
        subq    $__START_KERNEL_map,%rax
-       movq %rax,%cr3
+       movq    %rax,%cr3
 
        movq    mmu_cr4_features(%rip), %rax
        movq    %rax, %rdx
-       
        andq    $~(1<<7), %rdx  # PGE
-       movq %rdx, %cr4;  # turn off PGE     
-       movq %cr3, %rcx;  # flush TLB        
-       movq %rcx, %cr3;                     
-       movq %rax, %cr4;  # turn PGE back on 
+       movq    %rdx, %cr4;  # turn off PGE
+       movq    %cr3, %rcx;  # flush TLB
+       movq    %rcx, %cr3;
+       movq    %rax, %cr4;  # turn PGE back on
 
-       call    do_magic_resume_1
        movl    nr_copy_pages(%rip), %eax
        xorl    %ecx, %ecx
-       movq    $0, loop(%rip)
+       movq    $0, %r10
        testl   %eax, %eax
-       je      .L108
+       jz      done
 .L105:
        xorl    %esi, %esi
-       movq    $0, loop2(%rip)
+       movq    $0, %r11
        jmp     .L104
        .p2align 4,,7
-.L111:
-       movq    loop(%rip), %rcx
+copy_one_page:
+       movq    %r10, %rcx
 .L104:
        movq    pagedir_nosave(%rip), %rdx
        movq    %rcx, %rax
@@ -75,27 +70,26 @@ ENTRY(do_magic)
        movzbl  (%rsi,%rax), %eax
        movb    %al, (%rsi,%rcx)
 
-       movq %cr3, %rax;  # flush TLB 
-       movq %rax, %cr3;              
+       movq    %cr3, %rax;  # flush TLB
+       movq    %rax, %cr3;
 
-       movq    loop2(%rip), %rax
+       movq    %r11, %rax
        incq    %rax
        cmpq    $4095, %rax
        movq    %rax, %rsi
-       movq    %rax, loop2(%rip)
-       jbe     .L111
-       movq    loop(%rip), %rax
+       movq    %rax, %r11
+       jbe     copy_one_page
+       movq    %r10, %rax
        incq    %rax
        movq    %rax, %rcx
-       movq    %rax, loop(%rip)
+       movq    %rax, %r10
        mov     nr_copy_pages(%rip), %eax
        cmpq    %rax, %rcx
        jb      .L105
-.L108:
-       .align 4
+done:
        movl    $24, %eax
+       movl    %eax, %ds
 
-       movl %eax, %ds
        movq saved_context_esp(%rip), %rsp
        movq saved_context_ebp(%rip), %rbp
        movq saved_context_eax(%rip), %rax
@@ -113,13 +107,5 @@ ENTRY(do_magic)
        movq saved_context_r14(%rip), %r14
        movq saved_context_r15(%rip), %r15
        pushq saved_context_eflags(%rip) ; popfq
-       call    restore_processor_state
-       addq    $8, %rsp
-       jmp     do_magic_resume_2
-
-       .section .data.nosave
-loop:
-       .quad 0
-loop2: 
-       .quad 0         
-       .previous
+       call    swsusp_restore
+       ret
diff --git a/arch/x86_64/lib/bitops.c b/arch/x86_64/lib/bitops.c
new file mode 100644 (file)
index 0000000..6060dd9
--- /dev/null
@@ -0,0 +1,140 @@
+#include <linux/module.h>
+#include <asm/bitops.h>
+
+#undef find_first_zero_bit
+#undef find_next_zero_bit
+#undef find_first_bit
+#undef find_next_bit
+
+/**
+ * find_first_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first zero bit, not the number of the byte
+ * containing a bit.
+ */
+inline long find_first_zero_bit(const unsigned long * addr, unsigned long size)
+{
+       long d0, d1, d2;
+       long res;
+
+       if (!size)
+               return 0;
+       asm volatile(
+               "  repe; scasq\n"
+               "  je 1f\n"
+               "  xorq -8(%%rdi),%%rax\n"
+               "  subq $8,%%rdi\n"
+               "  bsfq %%rax,%%rdx\n"
+               "1:  subq %[addr],%%rdi\n"
+               "  shlq $3,%%rdi\n"
+               "  addq %%rdi,%%rdx"
+               :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
+               :"0" (0ULL), "1" ((size + 63) >> 6), "2" (addr), "3" (-1ULL),
+                [addr] "r" (addr) : "memory");
+       return res;
+}
+
+/**
+ * find_next_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+long find_next_zero_bit (const unsigned long * addr, long size, long offset)
+{
+       unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
+       unsigned long set = 0;
+       unsigned long res, bit = offset&63;
+
+       if (bit) {
+               /*
+                * Look for zero in first word
+                */
+               asm("bsfq %1,%0\n\t"
+                   "cmoveq %2,%0"
+                   : "=r" (set)
+                   : "r" (~(*p >> bit)), "r"(64L));
+               if (set < (64 - bit))
+                       return set + offset;
+               set = 64 - bit;
+               p++;
+       }
+       /*
+        * No zero yet, search remaining full words for a zero
+        */
+       res = find_first_zero_bit ((const unsigned long *)p,
+                                  size - 64 * (p - (unsigned long *) addr));
+       return (offset + set + res);
+}
+
+static inline long
+__find_first_bit(const unsigned long * addr, unsigned long size)
+{
+       long d0, d1;
+       long res;
+
+       asm volatile(
+               "   repe; scasq\n"
+               "   jz 1f\n"
+               "   subq $8,%%rdi\n"
+               "   bsfq (%%rdi),%%rax\n"
+               "1: subq %[addr],%%rdi\n"
+               "   shlq $3,%%rdi\n"
+               "   addq %%rdi,%%rax"
+               :"=a" (res), "=&c" (d0), "=&D" (d1)
+               :"0" (0ULL),
+                "1" ((size + 63) >> 6), "2" (addr),
+                [addr] "r" (addr) : "memory");
+       return res;
+}
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first set bit, not the number of the byte
+ * containing a bit.
+ */
+long find_first_bit(const unsigned long * addr, unsigned long size)
+{
+       return __find_first_bit(addr,size);
+}
+
+/**
+ * find_next_bit - find the first set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+long find_next_bit(const unsigned long * addr, long size, long offset)
+{
+       const unsigned long * p = addr + (offset >> 6);
+       unsigned long set = 0, bit = offset & 63, res;
+
+       if (bit) {
+               /*
+                * Look for nonzero in the first 64 bits:
+                */
+               asm("bsfq %1,%0\n\t"
+                   "cmoveq %2,%0\n\t"
+                   : "=r" (set)
+                   : "r" (*p >> bit), "r" (64L));
+               if (set < (64 - bit))
+                       return set + offset;
+               set = 64 - bit;
+               p++;
+       }
+       /*
+        * No set bit yet, search remaining full words for a bit
+        */
+       res = __find_first_bit (p, size - 64 * (p - addr));
+       return (offset + set + res);
+}
+
+EXPORT_SYMBOL(find_next_bit);
+EXPORT_SYMBOL(find_first_bit);
+EXPORT_SYMBOL(find_first_zero_bit);
+EXPORT_SYMBOL(find_next_zero_bit);
index 598d79d..e7ce82a 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/module.h>
 #include <asm/bitops.h>
 
 /* Find string of zero bits in a bitmap */ 
@@ -23,3 +24,5 @@ find_next_zero_string(unsigned long *bitmap, long start, long nbits, int len)
        }
        return n;
 }
+
+EXPORT_SYMBOL(find_next_zero_string);
index 12cac5b..e93d525 100644 (file)
@@ -10,18 +10,10 @@ void *memmove(void * dest,const void *src,size_t count)
        if (dest < src) { 
                __inline_memcpy(dest,src,count);
        } else {
-               /* Could be more clever and move longs */
-               unsigned long d0, d1, d2;
-               __asm__ __volatile__(
-                       "std\n\t"
-                       "rep\n\t"
-                       "movsb\n\t"
-                       "cld"
-                       : "=&c" (d0), "=&S" (d1), "=&D" (d2)
-                       :"0" (count),
-                       "1" (count-1+(const char *)src),
-                       "2" (count-1+(char *)dest)
-                       :"memory");
+               char *p = (char *) dest + count;
+               char *s = (char *) src + count;
+               while (count--)
+                       *--p = *--s;
        }
        return dest;
 } 
index 0ec22c1..0825e37 100644 (file)
@@ -100,8 +100,8 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
                limit <<= 24; 
                limit |= (1<<24)-1;
 
-               if (limit > end_pfn_map << PAGE_SHIFT) 
-                       limit = end_pfn_map << PAGE_SHIFT; 
+               if (limit > end_pfn << PAGE_SHIFT)
+                       limit = end_pfn << PAGE_SHIFT;
                if (limit <= base)
                        continue; 
                        
index 291985f..37c92e8 100644 (file)
@@ -3,7 +3,7 @@
 #
 # Reuse the i386 PCI subsystem
 #
-CFLAGS += -I arch/i386/pci
+CFLAGS += -Iarch/i386/pci
 
 obj-y          := i386.o
 obj-$(CONFIG_PCI_DIRECT)+= direct.o
@@ -13,6 +13,8 @@ obj-y                 += legacy.o irq.o common.o
 # mmconfig has a 64bit special
 obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o
 
+obj-$(CONFIG_NUMA)     += k8-bus.o
+
 direct-y += ../../i386/pci/direct.o
 acpi-y   += ../../i386/pci/acpi.o
 legacy-y += ../../i386/pci/legacy.o
diff --git a/arch/x86_64/pci/Makefile-BUS b/arch/x86_64/pci/Makefile-BUS
new file mode 100644 (file)
index 0000000..291985f
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# Makefile for X86_64 specific PCI routines
+#
+# Reuse the i386 PCI subsystem
+#
+CFLAGS += -I arch/i386/pci
+
+obj-y          := i386.o
+obj-$(CONFIG_PCI_DIRECT)+= direct.o
+obj-y          += fixup.o
+obj-$(CONFIG_ACPI_PCI) += acpi.o
+obj-y                  += legacy.o irq.o common.o
+# mmconfig has a 64bit special
+obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o
+
+direct-y += ../../i386/pci/direct.o
+acpi-y   += ../../i386/pci/acpi.o
+legacy-y += ../../i386/pci/legacy.o
+irq-y    += ../../i386/pci/irq.o
+common-y += ../../i386/pci/common.o
+fixup-y  += ../../i386/pci/fixup.o
+i386-y  += ../../i386/pci/i386.o
diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c
new file mode 100644 (file)
index 0000000..d1c728a
--- /dev/null
@@ -0,0 +1,74 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/mpspec.h>
+#include <linux/cpumask.h>
+
+/*
+ * This discovers the pcibus <-> node mapping on AMD K8.
+ *
+ * RED-PEN need to call this again on PCI hotplug
+ * RED-PEN empty cpus get reported wrong
+ */
+
+#define NODE_ID_REGISTER 0x60
+#define NODE_ID(dword) (dword & 0x07)
+#define LDT_BUS_NUMBER_REGISTER_0 0x94
+#define LDT_BUS_NUMBER_REGISTER_1 0xB4
+#define LDT_BUS_NUMBER_REGISTER_2 0xD4
+#define NR_LDT_BUS_NUMBER_REGISTERS 3
+#define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF)
+#define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
+#define PCI_DEVICE_ID_K8HTCONFIG 0x1100
+
+/**
+ * fill_mp_bus_to_cpumask()
+ * fills the mp_bus_to_cpumask array based according to the LDT Bus Number
+ * Registers found in the K8 northbridge
+ */
+__init static int
+fill_mp_bus_to_cpumask(void)
+{
+       struct pci_dev *nb_dev = NULL;
+       int i, j;
+       u32 ldtbus, nid;
+       static int lbnr[3] = {
+               LDT_BUS_NUMBER_REGISTER_0,
+               LDT_BUS_NUMBER_REGISTER_1,
+               LDT_BUS_NUMBER_REGISTER_2
+       };
+
+       while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+                       PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) {
+               pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid);
+
+               for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) {
+                       pci_read_config_dword(nb_dev, lbnr[i], &ldtbus);
+                       /*
+                        * if there are no busses hanging off of the current
+                        * ldt link then both the secondary and subordinate
+                        * bus number fields are set to 0.
+                        */
+                       if (!(SECONDARY_LDT_BUS_NUMBER(ldtbus) == 0
+                               && SUBORDINATE_LDT_BUS_NUMBER(ldtbus) == 0)) {
+                               for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
+                                    j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
+                                    j++)
+                                       pci_bus_to_cpumask[j] =
+                                               node_to_cpumask(NODE_ID(nid));
+                       }
+               }
+       }
+
+       /* quick sanity check */
+       for (i = 0; i < 256; i++) {
+               if (cpus_empty(pci_bus_to_cpumask[i])) {
+                       printk(KERN_ERR
+                              "k8-bus.c: bus %i has empty cpu mask\n", i);
+                       pci_bus_to_cpumask[i] = CPU_MASK_ALL;
+               }
+       }
+
+       return 0;
+}
+
+fs_initcall(fill_mp_bus_to_cpumask);
index 13b6daa..94b89a9 100644 (file)
@@ -102,10 +102,10 @@ struct aes_ctx {
 #define E_KEY ctx->E
 #define D_KEY ctx->D
 
-static u8 pow_tab[256];
-static u8 log_tab[256];
-static u8 sbx_tab[256];
-static u8 isb_tab[256];
+static u8 pow_tab[256] __initdata;
+static u8 log_tab[256] __initdata;
+static u8 sbx_tab[256] __initdata;
+static u8 isb_tab[256] __initdata;
 static u32 rco_tab[10];
 static u32 ft_tab[4][256];
 static u32 it_tab[4][256];
@@ -113,7 +113,7 @@ static u32 it_tab[4][256];
 static u32 fl_tab[4][256];
 static u32 il_tab[4][256];
 
-static inline u8
+static inline u8 __init
 f_mult (u8 a, u8 b)
 {
        u8 aa = log_tab[a], cc = aa + log_tab[b];
@@ -153,14 +153,14 @@ f_mult (u8 a, u8 b)
              il_tab[2][byte(bi[(n + 2) & 3],2)] ^              \
              il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
 
-static void
+static void __init
 gen_tabs (void)
 {
        u32 i, t;
        u8 p, q;
 
        /* log and power tables for GF(2**8) finite field with
-          0x011b as modular polynomial - the simplest prmitive
+          0x011b as modular polynomial - the simplest primitive
           root is 0x03, used here to generate the tables */
 
        for (i = 0, p = 1; i < 256; ++i) {
index b66eb1f..9efbcaa 100644 (file)
@@ -3,7 +3,7 @@
  *
  * ARC4 Cipher Algorithm
  *
- * Jon Oberheide <jon@focalhost.com>
+ * Jon Oberheide <jon@oberheide.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
@@ -100,4 +100,4 @@ module_exit(arc4_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
-MODULE_AUTHOR("Jon Oberheide <jon@focalhost.com>");
+MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
index 8fd18dc..b6bea82 100644 (file)
@@ -3,9 +3,9 @@
  *
  * Blowfish Cipher Algorithm, by Bruce Schneier.
  * http://www.counterpane.com/blowfish.html
- * 
- * Adapated from Kerneli implementation.
- * 
+ *
+ * Adapted from Kerneli implementation.
+ *
  * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
  * Copyright (c) Kyle McMartin <kyle@debian.org>
  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
index b51fad1..e68e438 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/kmod.h>
-#include <asm/hardirq.h>
 #include <asm/kmap_types.h>
 
 extern enum km_type crypto_km_types[];
index 540dd9a..f6a5c9e 100644 (file)
@@ -70,7 +70,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
 {
        /* walk->data may be pointing the first byte of the next page;
           however, we know we transfered at least one byte.  So,
-          walk->data - 1 will be a virutual address in the mapped page. */
+          walk->data - 1 will be a virtual address in the mapped page. */
 
        if (out)
                flush_dcache_page(walk->page);
index bf94329..588a143 100644 (file)
@@ -154,7 +154,7 @@ static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
 
        while (sum != limit) {
                y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; 
-               sum += TEA_DELTA;
+               sum += XTEA_DELTA;
                z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; 
        }
        
diff --git a/crypto/wp512.c b/crypto/wp512.c
new file mode 100644 (file)
index 0000000..fd6e20e
--- /dev/null
@@ -0,0 +1,1208 @@
+/*
+ * Cryptographic API.
+ *
+ * Whirlpool hashing Algorithm
+ *
+ * The Whirlpool algorithm was developed by Paulo S. L. M. Barreto and
+ * Vincent Rijmen.  It has been selected as one of cryptographic
+ * primitives by the NESSIE project http://www.cryptonessie.org/
+ *
+ * The original authors have disclaimed all copyright interest in this
+ * code and thus put it in the public domain. The subsequent authors
+ * have put this under the GNU General Public License.
+ *
+ * By Aaron Grothe ajgrothe@yahoo.com, August 23, 2004
+ *
+ * This program is free software; you can redistribute 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/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#define WP512_DIGEST_SIZE 64
+#define WP384_DIGEST_SIZE 48
+#define WP256_DIGEST_SIZE 32
+
+#define WP512_BLOCK_SIZE  64
+#define WP512_LENGTHBYTES 32
+
+#define WHIRLPOOL_ROUNDS 10
+
+struct wp512_ctx {
+       u8  bitLength[WP512_LENGTHBYTES];
+       u8  buffer[WP512_BLOCK_SIZE];
+       int bufferBits;
+       int bufferPos;
+       u64 hash[WP512_DIGEST_SIZE/8];
+};
+
+/*
+ * Though Whirlpool is endianness-neutral, the encryption tables are listed
+ * in BIG-ENDIAN format, which is adopted throughout this implementation
+ * (but little-endian notation would be equally suitable if consistently
+ * employed).
+ */
+
+static const u64 C0[256] = {
+       0x18186018c07830d8ULL, 0x23238c2305af4626ULL, 0xc6c63fc67ef991b8ULL,
+       0xe8e887e8136fcdfbULL, 0x878726874ca113cbULL, 0xb8b8dab8a9626d11ULL,
+       0x0101040108050209ULL, 0x4f4f214f426e9e0dULL, 0x3636d836adee6c9bULL,
+       0xa6a6a2a6590451ffULL, 0xd2d26fd2debdb90cULL, 0xf5f5f3f5fb06f70eULL,
+       0x7979f979ef80f296ULL, 0x6f6fa16f5fcede30ULL, 0x91917e91fcef3f6dULL,
+       0x52525552aa07a4f8ULL, 0x60609d6027fdc047ULL, 0xbcbccabc89766535ULL,
+       0x9b9b569baccd2b37ULL, 0x8e8e028e048c018aULL, 0xa3a3b6a371155bd2ULL,
+       0x0c0c300c603c186cULL, 0x7b7bf17bff8af684ULL, 0x3535d435b5e16a80ULL,
+       0x1d1d741de8693af5ULL, 0xe0e0a7e05347ddb3ULL, 0xd7d77bd7f6acb321ULL,
+       0xc2c22fc25eed999cULL, 0x2e2eb82e6d965c43ULL, 0x4b4b314b627a9629ULL,
+       0xfefedffea321e15dULL, 0x575741578216aed5ULL, 0x15155415a8412abdULL,
+       0x7777c1779fb6eee8ULL, 0x3737dc37a5eb6e92ULL, 0xe5e5b3e57b56d79eULL,
+       0x9f9f469f8cd92313ULL, 0xf0f0e7f0d317fd23ULL, 0x4a4a354a6a7f9420ULL,
+       0xdada4fda9e95a944ULL, 0x58587d58fa25b0a2ULL, 0xc9c903c906ca8fcfULL,
+       0x2929a429558d527cULL, 0x0a0a280a5022145aULL, 0xb1b1feb1e14f7f50ULL,
+       0xa0a0baa0691a5dc9ULL, 0x6b6bb16b7fdad614ULL, 0x85852e855cab17d9ULL,
+       0xbdbdcebd8173673cULL, 0x5d5d695dd234ba8fULL, 0x1010401080502090ULL,
+       0xf4f4f7f4f303f507ULL, 0xcbcb0bcb16c08bddULL, 0x3e3ef83eedc67cd3ULL,
+       0x0505140528110a2dULL, 0x676781671fe6ce78ULL, 0xe4e4b7e47353d597ULL,
+       0x27279c2725bb4e02ULL, 0x4141194132588273ULL, 0x8b8b168b2c9d0ba7ULL,
+       0xa7a7a6a7510153f6ULL, 0x7d7de97dcf94fab2ULL, 0x95956e95dcfb3749ULL,
+       0xd8d847d88e9fad56ULL, 0xfbfbcbfb8b30eb70ULL, 0xeeee9fee2371c1cdULL,
+       0x7c7ced7cc791f8bbULL, 0x6666856617e3cc71ULL, 0xdddd53dda68ea77bULL,
+       0x17175c17b84b2eafULL, 0x4747014702468e45ULL, 0x9e9e429e84dc211aULL,
+       0xcaca0fca1ec589d4ULL, 0x2d2db42d75995a58ULL, 0xbfbfc6bf9179632eULL,
+       0x07071c07381b0e3fULL, 0xadad8ead012347acULL, 0x5a5a755aea2fb4b0ULL,
+       0x838336836cb51befULL, 0x3333cc3385ff66b6ULL, 0x636391633ff2c65cULL,
+       0x02020802100a0412ULL, 0xaaaa92aa39384993ULL, 0x7171d971afa8e2deULL,
+       0xc8c807c80ecf8dc6ULL, 0x19196419c87d32d1ULL, 0x494939497270923bULL,
+       0xd9d943d9869aaf5fULL, 0xf2f2eff2c31df931ULL, 0xe3e3abe34b48dba8ULL,
+       0x5b5b715be22ab6b9ULL, 0x88881a8834920dbcULL, 0x9a9a529aa4c8293eULL,
+       0x262698262dbe4c0bULL, 0x3232c8328dfa64bfULL, 0xb0b0fab0e94a7d59ULL,
+       0xe9e983e91b6acff2ULL, 0x0f0f3c0f78331e77ULL, 0xd5d573d5e6a6b733ULL,
+       0x80803a8074ba1df4ULL, 0xbebec2be997c6127ULL, 0xcdcd13cd26de87ebULL,
+       0x3434d034bde46889ULL, 0x48483d487a759032ULL, 0xffffdbffab24e354ULL,
+       0x7a7af57af78ff48dULL, 0x90907a90f4ea3d64ULL, 0x5f5f615fc23ebe9dULL,
+       0x202080201da0403dULL, 0x6868bd6867d5d00fULL, 0x1a1a681ad07234caULL,
+       0xaeae82ae192c41b7ULL, 0xb4b4eab4c95e757dULL, 0x54544d549a19a8ceULL,
+       0x93937693ece53b7fULL, 0x222288220daa442fULL, 0x64648d6407e9c863ULL,
+       0xf1f1e3f1db12ff2aULL, 0x7373d173bfa2e6ccULL, 0x12124812905a2482ULL,
+       0x40401d403a5d807aULL, 0x0808200840281048ULL, 0xc3c32bc356e89b95ULL,
+       0xecec97ec337bc5dfULL, 0xdbdb4bdb9690ab4dULL, 0xa1a1bea1611f5fc0ULL,
+       0x8d8d0e8d1c830791ULL, 0x3d3df43df5c97ac8ULL, 0x97976697ccf1335bULL,
+       0x0000000000000000ULL, 0xcfcf1bcf36d483f9ULL, 0x2b2bac2b4587566eULL,
+       0x7676c57697b3ece1ULL, 0x8282328264b019e6ULL, 0xd6d67fd6fea9b128ULL,
+       0x1b1b6c1bd87736c3ULL, 0xb5b5eeb5c15b7774ULL, 0xafaf86af112943beULL,
+       0x6a6ab56a77dfd41dULL, 0x50505d50ba0da0eaULL, 0x45450945124c8a57ULL,
+       0xf3f3ebf3cb18fb38ULL, 0x3030c0309df060adULL, 0xefef9bef2b74c3c4ULL,
+       0x3f3ffc3fe5c37edaULL, 0x55554955921caac7ULL, 0xa2a2b2a2791059dbULL,
+       0xeaea8fea0365c9e9ULL, 0x656589650fecca6aULL, 0xbabad2bab9686903ULL,
+       0x2f2fbc2f65935e4aULL, 0xc0c027c04ee79d8eULL, 0xdede5fdebe81a160ULL,
+       0x1c1c701ce06c38fcULL, 0xfdfdd3fdbb2ee746ULL, 0x4d4d294d52649a1fULL,
+       0x92927292e4e03976ULL, 0x7575c9758fbceafaULL, 0x06061806301e0c36ULL,
+       0x8a8a128a249809aeULL, 0xb2b2f2b2f940794bULL, 0xe6e6bfe66359d185ULL,
+       0x0e0e380e70361c7eULL, 0x1f1f7c1ff8633ee7ULL, 0x6262956237f7c455ULL,
+       0xd4d477d4eea3b53aULL, 0xa8a89aa829324d81ULL, 0x96966296c4f43152ULL,
+       0xf9f9c3f99b3aef62ULL, 0xc5c533c566f697a3ULL, 0x2525942535b14a10ULL,
+       0x59597959f220b2abULL, 0x84842a8454ae15d0ULL, 0x7272d572b7a7e4c5ULL,
+       0x3939e439d5dd72ecULL, 0x4c4c2d4c5a619816ULL, 0x5e5e655eca3bbc94ULL,
+       0x7878fd78e785f09fULL, 0x3838e038ddd870e5ULL, 0x8c8c0a8c14860598ULL,
+       0xd1d163d1c6b2bf17ULL, 0xa5a5aea5410b57e4ULL, 0xe2e2afe2434dd9a1ULL,
+       0x616199612ff8c24eULL, 0xb3b3f6b3f1457b42ULL, 0x2121842115a54234ULL,
+       0x9c9c4a9c94d62508ULL, 0x1e1e781ef0663ceeULL, 0x4343114322528661ULL,
+       0xc7c73bc776fc93b1ULL, 0xfcfcd7fcb32be54fULL, 0x0404100420140824ULL,
+       0x51515951b208a2e3ULL, 0x99995e99bcc72f25ULL, 0x6d6da96d4fc4da22ULL,
+       0x0d0d340d68391a65ULL, 0xfafacffa8335e979ULL, 0xdfdf5bdfb684a369ULL,
+       0x7e7ee57ed79bfca9ULL, 0x242490243db44819ULL, 0x3b3bec3bc5d776feULL,
+       0xabab96ab313d4b9aULL, 0xcece1fce3ed181f0ULL, 0x1111441188552299ULL,
+       0x8f8f068f0c890383ULL, 0x4e4e254e4a6b9c04ULL, 0xb7b7e6b7d1517366ULL,
+       0xebeb8beb0b60cbe0ULL, 0x3c3cf03cfdcc78c1ULL, 0x81813e817cbf1ffdULL,
+       0x94946a94d4fe3540ULL, 0xf7f7fbf7eb0cf31cULL, 0xb9b9deb9a1676f18ULL,
+       0x13134c13985f268bULL, 0x2c2cb02c7d9c5851ULL, 0xd3d36bd3d6b8bb05ULL,
+       0xe7e7bbe76b5cd38cULL, 0x6e6ea56e57cbdc39ULL, 0xc4c437c46ef395aaULL,
+       0x03030c03180f061bULL, 0x565645568a13acdcULL, 0x44440d441a49885eULL,
+       0x7f7fe17fdf9efea0ULL, 0xa9a99ea921374f88ULL, 0x2a2aa82a4d825467ULL,
+       0xbbbbd6bbb16d6b0aULL, 0xc1c123c146e29f87ULL, 0x53535153a202a6f1ULL,
+       0xdcdc57dcae8ba572ULL, 0x0b0b2c0b58271653ULL, 0x9d9d4e9d9cd32701ULL,
+       0x6c6cad6c47c1d82bULL, 0x3131c43195f562a4ULL, 0x7474cd7487b9e8f3ULL,
+       0xf6f6fff6e309f115ULL, 0x464605460a438c4cULL, 0xacac8aac092645a5ULL,
+       0x89891e893c970fb5ULL, 0x14145014a04428b4ULL, 0xe1e1a3e15b42dfbaULL,
+       0x16165816b04e2ca6ULL, 0x3a3ae83acdd274f7ULL, 0x6969b9696fd0d206ULL,
+       0x09092409482d1241ULL, 0x7070dd70a7ade0d7ULL, 0xb6b6e2b6d954716fULL,
+       0xd0d067d0ceb7bd1eULL, 0xeded93ed3b7ec7d6ULL, 0xcccc17cc2edb85e2ULL,
+       0x424215422a578468ULL, 0x98985a98b4c22d2cULL, 0xa4a4aaa4490e55edULL,
+       0x2828a0285d885075ULL, 0x5c5c6d5cda31b886ULL, 0xf8f8c7f8933fed6bULL,
+       0x8686228644a411c2ULL,
+};
+
+static const u64 C1[256] = {
+       0xd818186018c07830ULL, 0x2623238c2305af46ULL, 0xb8c6c63fc67ef991ULL,
+       0xfbe8e887e8136fcdULL, 0xcb878726874ca113ULL, 0x11b8b8dab8a9626dULL,
+       0x0901010401080502ULL, 0x0d4f4f214f426e9eULL, 0x9b3636d836adee6cULL,
+       0xffa6a6a2a6590451ULL, 0x0cd2d26fd2debdb9ULL, 0x0ef5f5f3f5fb06f7ULL,
+       0x967979f979ef80f2ULL, 0x306f6fa16f5fcedeULL, 0x6d91917e91fcef3fULL,
+       0xf852525552aa07a4ULL, 0x4760609d6027fdc0ULL, 0x35bcbccabc897665ULL,
+       0x379b9b569baccd2bULL, 0x8a8e8e028e048c01ULL, 0xd2a3a3b6a371155bULL,
+       0x6c0c0c300c603c18ULL, 0x847b7bf17bff8af6ULL, 0x803535d435b5e16aULL,
+       0xf51d1d741de8693aULL, 0xb3e0e0a7e05347ddULL, 0x21d7d77bd7f6acb3ULL,
+       0x9cc2c22fc25eed99ULL, 0x432e2eb82e6d965cULL, 0x294b4b314b627a96ULL,
+       0x5dfefedffea321e1ULL, 0xd5575741578216aeULL, 0xbd15155415a8412aULL,
+       0xe87777c1779fb6eeULL, 0x923737dc37a5eb6eULL, 0x9ee5e5b3e57b56d7ULL,
+       0x139f9f469f8cd923ULL, 0x23f0f0e7f0d317fdULL, 0x204a4a354a6a7f94ULL,
+       0x44dada4fda9e95a9ULL, 0xa258587d58fa25b0ULL, 0xcfc9c903c906ca8fULL,
+       0x7c2929a429558d52ULL, 0x5a0a0a280a502214ULL, 0x50b1b1feb1e14f7fULL,
+       0xc9a0a0baa0691a5dULL, 0x146b6bb16b7fdad6ULL, 0xd985852e855cab17ULL,
+       0x3cbdbdcebd817367ULL, 0x8f5d5d695dd234baULL, 0x9010104010805020ULL,
+       0x07f4f4f7f4f303f5ULL, 0xddcbcb0bcb16c08bULL, 0xd33e3ef83eedc67cULL,
+       0x2d0505140528110aULL, 0x78676781671fe6ceULL, 0x97e4e4b7e47353d5ULL,
+       0x0227279c2725bb4eULL, 0x7341411941325882ULL, 0xa78b8b168b2c9d0bULL,
+       0xf6a7a7a6a7510153ULL, 0xb27d7de97dcf94faULL, 0x4995956e95dcfb37ULL,
+       0x56d8d847d88e9fadULL, 0x70fbfbcbfb8b30ebULL, 0xcdeeee9fee2371c1ULL,
+       0xbb7c7ced7cc791f8ULL, 0x716666856617e3ccULL, 0x7bdddd53dda68ea7ULL,
+       0xaf17175c17b84b2eULL, 0x454747014702468eULL, 0x1a9e9e429e84dc21ULL,
+       0xd4caca0fca1ec589ULL, 0x582d2db42d75995aULL, 0x2ebfbfc6bf917963ULL,
+       0x3f07071c07381b0eULL, 0xacadad8ead012347ULL, 0xb05a5a755aea2fb4ULL,
+       0xef838336836cb51bULL, 0xb63333cc3385ff66ULL, 0x5c636391633ff2c6ULL,
+       0x1202020802100a04ULL, 0x93aaaa92aa393849ULL, 0xde7171d971afa8e2ULL,
+       0xc6c8c807c80ecf8dULL, 0xd119196419c87d32ULL, 0x3b49493949727092ULL,
+       0x5fd9d943d9869aafULL, 0x31f2f2eff2c31df9ULL, 0xa8e3e3abe34b48dbULL,
+       0xb95b5b715be22ab6ULL, 0xbc88881a8834920dULL, 0x3e9a9a529aa4c829ULL,
+       0x0b262698262dbe4cULL, 0xbf3232c8328dfa64ULL, 0x59b0b0fab0e94a7dULL,
+       0xf2e9e983e91b6acfULL, 0x770f0f3c0f78331eULL, 0x33d5d573d5e6a6b7ULL,
+       0xf480803a8074ba1dULL, 0x27bebec2be997c61ULL, 0xebcdcd13cd26de87ULL,
+       0x893434d034bde468ULL, 0x3248483d487a7590ULL, 0x54ffffdbffab24e3ULL,
+       0x8d7a7af57af78ff4ULL, 0x6490907a90f4ea3dULL, 0x9d5f5f615fc23ebeULL,
+       0x3d202080201da040ULL, 0x0f6868bd6867d5d0ULL, 0xca1a1a681ad07234ULL,
+       0xb7aeae82ae192c41ULL, 0x7db4b4eab4c95e75ULL, 0xce54544d549a19a8ULL,
+       0x7f93937693ece53bULL, 0x2f222288220daa44ULL, 0x6364648d6407e9c8ULL,
+       0x2af1f1e3f1db12ffULL, 0xcc7373d173bfa2e6ULL, 0x8212124812905a24ULL,
+       0x7a40401d403a5d80ULL, 0x4808082008402810ULL, 0x95c3c32bc356e89bULL,
+       0xdfecec97ec337bc5ULL, 0x4ddbdb4bdb9690abULL, 0xc0a1a1bea1611f5fULL,
+       0x918d8d0e8d1c8307ULL, 0xc83d3df43df5c97aULL, 0x5b97976697ccf133ULL,
+       0x0000000000000000ULL, 0xf9cfcf1bcf36d483ULL, 0x6e2b2bac2b458756ULL,
+       0xe17676c57697b3ecULL, 0xe68282328264b019ULL, 0x28d6d67fd6fea9b1ULL,
+       0xc31b1b6c1bd87736ULL, 0x74b5b5eeb5c15b77ULL, 0xbeafaf86af112943ULL,
+       0x1d6a6ab56a77dfd4ULL, 0xea50505d50ba0da0ULL, 0x5745450945124c8aULL,
+       0x38f3f3ebf3cb18fbULL, 0xad3030c0309df060ULL, 0xc4efef9bef2b74c3ULL,
+       0xda3f3ffc3fe5c37eULL, 0xc755554955921caaULL, 0xdba2a2b2a2791059ULL,
+       0xe9eaea8fea0365c9ULL, 0x6a656589650feccaULL, 0x03babad2bab96869ULL,
+       0x4a2f2fbc2f65935eULL, 0x8ec0c027c04ee79dULL, 0x60dede5fdebe81a1ULL,
+       0xfc1c1c701ce06c38ULL, 0x46fdfdd3fdbb2ee7ULL, 0x1f4d4d294d52649aULL,
+       0x7692927292e4e039ULL, 0xfa7575c9758fbceaULL, 0x3606061806301e0cULL,
+       0xae8a8a128a249809ULL, 0x4bb2b2f2b2f94079ULL, 0x85e6e6bfe66359d1ULL,
+       0x7e0e0e380e70361cULL, 0xe71f1f7c1ff8633eULL, 0x556262956237f7c4ULL,
+       0x3ad4d477d4eea3b5ULL, 0x81a8a89aa829324dULL, 0x5296966296c4f431ULL,
+       0x62f9f9c3f99b3aefULL, 0xa3c5c533c566f697ULL, 0x102525942535b14aULL,
+       0xab59597959f220b2ULL, 0xd084842a8454ae15ULL, 0xc57272d572b7a7e4ULL,
+       0xec3939e439d5dd72ULL, 0x164c4c2d4c5a6198ULL, 0x945e5e655eca3bbcULL,
+       0x9f7878fd78e785f0ULL, 0xe53838e038ddd870ULL, 0x988c8c0a8c148605ULL,
+       0x17d1d163d1c6b2bfULL, 0xe4a5a5aea5410b57ULL, 0xa1e2e2afe2434dd9ULL,
+       0x4e616199612ff8c2ULL, 0x42b3b3f6b3f1457bULL, 0x342121842115a542ULL,
+       0x089c9c4a9c94d625ULL, 0xee1e1e781ef0663cULL, 0x6143431143225286ULL,
+       0xb1c7c73bc776fc93ULL, 0x4ffcfcd7fcb32be5ULL, 0x2404041004201408ULL,
+       0xe351515951b208a2ULL, 0x2599995e99bcc72fULL, 0x226d6da96d4fc4daULL,
+       0x650d0d340d68391aULL, 0x79fafacffa8335e9ULL, 0x69dfdf5bdfb684a3ULL,
+       0xa97e7ee57ed79bfcULL, 0x19242490243db448ULL, 0xfe3b3bec3bc5d776ULL,
+       0x9aabab96ab313d4bULL, 0xf0cece1fce3ed181ULL, 0x9911114411885522ULL,
+       0x838f8f068f0c8903ULL, 0x044e4e254e4a6b9cULL, 0x66b7b7e6b7d15173ULL,
+       0xe0ebeb8beb0b60cbULL, 0xc13c3cf03cfdcc78ULL, 0xfd81813e817cbf1fULL,
+       0x4094946a94d4fe35ULL, 0x1cf7f7fbf7eb0cf3ULL, 0x18b9b9deb9a1676fULL,
+       0x8b13134c13985f26ULL, 0x512c2cb02c7d9c58ULL, 0x05d3d36bd3d6b8bbULL,
+       0x8ce7e7bbe76b5cd3ULL, 0x396e6ea56e57cbdcULL, 0xaac4c437c46ef395ULL,
+       0x1b03030c03180f06ULL, 0xdc565645568a13acULL, 0x5e44440d441a4988ULL,
+       0xa07f7fe17fdf9efeULL, 0x88a9a99ea921374fULL, 0x672a2aa82a4d8254ULL,
+       0x0abbbbd6bbb16d6bULL, 0x87c1c123c146e29fULL, 0xf153535153a202a6ULL,
+       0x72dcdc57dcae8ba5ULL, 0x530b0b2c0b582716ULL, 0x019d9d4e9d9cd327ULL,
+       0x2b6c6cad6c47c1d8ULL, 0xa43131c43195f562ULL, 0xf37474cd7487b9e8ULL,
+       0x15f6f6fff6e309f1ULL, 0x4c464605460a438cULL, 0xa5acac8aac092645ULL,
+       0xb589891e893c970fULL, 0xb414145014a04428ULL, 0xbae1e1a3e15b42dfULL,
+       0xa616165816b04e2cULL, 0xf73a3ae83acdd274ULL, 0x066969b9696fd0d2ULL,
+       0x4109092409482d12ULL, 0xd77070dd70a7ade0ULL, 0x6fb6b6e2b6d95471ULL,
+       0x1ed0d067d0ceb7bdULL, 0xd6eded93ed3b7ec7ULL, 0xe2cccc17cc2edb85ULL,
+       0x68424215422a5784ULL, 0x2c98985a98b4c22dULL, 0xeda4a4aaa4490e55ULL,
+       0x752828a0285d8850ULL, 0x865c5c6d5cda31b8ULL, 0x6bf8f8c7f8933fedULL,
+       0xc28686228644a411ULL,
+};
+
+static const u64 C2[256] = {
+       0x30d818186018c078ULL, 0x462623238c2305afULL, 0x91b8c6c63fc67ef9ULL,
+       0xcdfbe8e887e8136fULL, 0x13cb878726874ca1ULL, 0x6d11b8b8dab8a962ULL,
+       0x0209010104010805ULL, 0x9e0d4f4f214f426eULL, 0x6c9b3636d836adeeULL,
+       0x51ffa6a6a2a65904ULL, 0xb90cd2d26fd2debdULL, 0xf70ef5f5f3f5fb06ULL,
+       0xf2967979f979ef80ULL, 0xde306f6fa16f5fceULL, 0x3f6d91917e91fcefULL,
+       0xa4f852525552aa07ULL, 0xc04760609d6027fdULL, 0x6535bcbccabc8976ULL,
+       0x2b379b9b569baccdULL, 0x018a8e8e028e048cULL, 0x5bd2a3a3b6a37115ULL,
+       0x186c0c0c300c603cULL, 0xf6847b7bf17bff8aULL, 0x6a803535d435b5e1ULL,
+       0x3af51d1d741de869ULL, 0xddb3e0e0a7e05347ULL, 0xb321d7d77bd7f6acULL,
+       0x999cc2c22fc25eedULL, 0x5c432e2eb82e6d96ULL, 0x96294b4b314b627aULL,
+       0xe15dfefedffea321ULL, 0xaed5575741578216ULL, 0x2abd15155415a841ULL,
+       0xeee87777c1779fb6ULL, 0x6e923737dc37a5ebULL, 0xd79ee5e5b3e57b56ULL,
+       0x23139f9f469f8cd9ULL, 0xfd23f0f0e7f0d317ULL, 0x94204a4a354a6a7fULL,
+       0xa944dada4fda9e95ULL, 0xb0a258587d58fa25ULL, 0x8fcfc9c903c906caULL,
+       0x527c2929a429558dULL, 0x145a0a0a280a5022ULL, 0x7f50b1b1feb1e14fULL,
+       0x5dc9a0a0baa0691aULL, 0xd6146b6bb16b7fdaULL, 0x17d985852e855cabULL,
+       0x673cbdbdcebd8173ULL, 0xba8f5d5d695dd234ULL, 0x2090101040108050ULL,
+       0xf507f4f4f7f4f303ULL, 0x8bddcbcb0bcb16c0ULL, 0x7cd33e3ef83eedc6ULL,
+       0x0a2d050514052811ULL, 0xce78676781671fe6ULL, 0xd597e4e4b7e47353ULL,
+       0x4e0227279c2725bbULL, 0x8273414119413258ULL, 0x0ba78b8b168b2c9dULL,
+       0x53f6a7a7a6a75101ULL, 0xfab27d7de97dcf94ULL, 0x374995956e95dcfbULL,
+       0xad56d8d847d88e9fULL, 0xeb70fbfbcbfb8b30ULL, 0xc1cdeeee9fee2371ULL,
+       0xf8bb7c7ced7cc791ULL, 0xcc716666856617e3ULL, 0xa77bdddd53dda68eULL,
+       0x2eaf17175c17b84bULL, 0x8e45474701470246ULL, 0x211a9e9e429e84dcULL,
+       0x89d4caca0fca1ec5ULL, 0x5a582d2db42d7599ULL, 0x632ebfbfc6bf9179ULL,
+       0x0e3f07071c07381bULL, 0x47acadad8ead0123ULL, 0xb4b05a5a755aea2fULL,
+       0x1bef838336836cb5ULL, 0x66b63333cc3385ffULL, 0xc65c636391633ff2ULL,
+       0x041202020802100aULL, 0x4993aaaa92aa3938ULL, 0xe2de7171d971afa8ULL,
+       0x8dc6c8c807c80ecfULL, 0x32d119196419c87dULL, 0x923b494939497270ULL,
+       0xaf5fd9d943d9869aULL, 0xf931f2f2eff2c31dULL, 0xdba8e3e3abe34b48ULL,
+       0xb6b95b5b715be22aULL, 0x0dbc88881a883492ULL, 0x293e9a9a529aa4c8ULL,
+       0x4c0b262698262dbeULL, 0x64bf3232c8328dfaULL, 0x7d59b0b0fab0e94aULL,
+       0xcff2e9e983e91b6aULL, 0x1e770f0f3c0f7833ULL, 0xb733d5d573d5e6a6ULL,
+       0x1df480803a8074baULL, 0x6127bebec2be997cULL, 0x87ebcdcd13cd26deULL,
+       0x68893434d034bde4ULL, 0x903248483d487a75ULL, 0xe354ffffdbffab24ULL,
+       0xf48d7a7af57af78fULL, 0x3d6490907a90f4eaULL, 0xbe9d5f5f615fc23eULL,
+       0x403d202080201da0ULL, 0xd00f6868bd6867d5ULL, 0x34ca1a1a681ad072ULL,
+       0x41b7aeae82ae192cULL, 0x757db4b4eab4c95eULL, 0xa8ce54544d549a19ULL,
+       0x3b7f93937693ece5ULL, 0x442f222288220daaULL, 0xc86364648d6407e9ULL,
+       0xff2af1f1e3f1db12ULL, 0xe6cc7373d173bfa2ULL, 0x248212124812905aULL,
+       0x807a40401d403a5dULL, 0x1048080820084028ULL, 0x9b95c3c32bc356e8ULL,
+       0xc5dfecec97ec337bULL, 0xab4ddbdb4bdb9690ULL, 0x5fc0a1a1bea1611fULL,
+       0x07918d8d0e8d1c83ULL, 0x7ac83d3df43df5c9ULL, 0x335b97976697ccf1ULL,
+       0x0000000000000000ULL, 0x83f9cfcf1bcf36d4ULL, 0x566e2b2bac2b4587ULL,
+       0xece17676c57697b3ULL, 0x19e68282328264b0ULL, 0xb128d6d67fd6fea9ULL,
+       0x36c31b1b6c1bd877ULL, 0x7774b5b5eeb5c15bULL, 0x43beafaf86af1129ULL,
+       0xd41d6a6ab56a77dfULL, 0xa0ea50505d50ba0dULL, 0x8a5745450945124cULL,
+       0xfb38f3f3ebf3cb18ULL, 0x60ad3030c0309df0ULL, 0xc3c4efef9bef2b74ULL,
+       0x7eda3f3ffc3fe5c3ULL, 0xaac755554955921cULL, 0x59dba2a2b2a27910ULL,
+       0xc9e9eaea8fea0365ULL, 0xca6a656589650fecULL, 0x6903babad2bab968ULL,
+       0x5e4a2f2fbc2f6593ULL, 0x9d8ec0c027c04ee7ULL, 0xa160dede5fdebe81ULL,
+       0x38fc1c1c701ce06cULL, 0xe746fdfdd3fdbb2eULL, 0x9a1f4d4d294d5264ULL,
+       0x397692927292e4e0ULL, 0xeafa7575c9758fbcULL, 0x0c3606061806301eULL,
+       0x09ae8a8a128a2498ULL, 0x794bb2b2f2b2f940ULL, 0xd185e6e6bfe66359ULL,
+       0x1c7e0e0e380e7036ULL, 0x3ee71f1f7c1ff863ULL, 0xc4556262956237f7ULL,
+       0xb53ad4d477d4eea3ULL, 0x4d81a8a89aa82932ULL, 0x315296966296c4f4ULL,
+       0xef62f9f9c3f99b3aULL, 0x97a3c5c533c566f6ULL, 0x4a102525942535b1ULL,
+       0xb2ab59597959f220ULL, 0x15d084842a8454aeULL, 0xe4c57272d572b7a7ULL,
+       0x72ec3939e439d5ddULL, 0x98164c4c2d4c5a61ULL, 0xbc945e5e655eca3bULL,
+       0xf09f7878fd78e785ULL, 0x70e53838e038ddd8ULL, 0x05988c8c0a8c1486ULL,
+       0xbf17d1d163d1c6b2ULL, 0x57e4a5a5aea5410bULL, 0xd9a1e2e2afe2434dULL,
+       0xc24e616199612ff8ULL, 0x7b42b3b3f6b3f145ULL, 0x42342121842115a5ULL,
+       0x25089c9c4a9c94d6ULL, 0x3cee1e1e781ef066ULL, 0x8661434311432252ULL,
+       0x93b1c7c73bc776fcULL, 0xe54ffcfcd7fcb32bULL, 0x0824040410042014ULL,
+       0xa2e351515951b208ULL, 0x2f2599995e99bcc7ULL, 0xda226d6da96d4fc4ULL,
+       0x1a650d0d340d6839ULL, 0xe979fafacffa8335ULL, 0xa369dfdf5bdfb684ULL,
+       0xfca97e7ee57ed79bULL, 0x4819242490243db4ULL, 0x76fe3b3bec3bc5d7ULL,
+       0x4b9aabab96ab313dULL, 0x81f0cece1fce3ed1ULL, 0x2299111144118855ULL,
+       0x03838f8f068f0c89ULL, 0x9c044e4e254e4a6bULL, 0x7366b7b7e6b7d151ULL,
+       0xcbe0ebeb8beb0b60ULL, 0x78c13c3cf03cfdccULL, 0x1ffd81813e817cbfULL,
+       0x354094946a94d4feULL, 0xf31cf7f7fbf7eb0cULL, 0x6f18b9b9deb9a167ULL,
+       0x268b13134c13985fULL, 0x58512c2cb02c7d9cULL, 0xbb05d3d36bd3d6b8ULL,
+       0xd38ce7e7bbe76b5cULL, 0xdc396e6ea56e57cbULL, 0x95aac4c437c46ef3ULL,
+       0x061b03030c03180fULL, 0xacdc565645568a13ULL, 0x885e44440d441a49ULL,
+       0xfea07f7fe17fdf9eULL, 0x4f88a9a99ea92137ULL, 0x54672a2aa82a4d82ULL,
+       0x6b0abbbbd6bbb16dULL, 0x9f87c1c123c146e2ULL, 0xa6f153535153a202ULL,
+       0xa572dcdc57dcae8bULL, 0x16530b0b2c0b5827ULL, 0x27019d9d4e9d9cd3ULL,
+       0xd82b6c6cad6c47c1ULL, 0x62a43131c43195f5ULL, 0xe8f37474cd7487b9ULL,
+       0xf115f6f6fff6e309ULL, 0x8c4c464605460a43ULL, 0x45a5acac8aac0926ULL,
+       0x0fb589891e893c97ULL, 0x28b414145014a044ULL, 0xdfbae1e1a3e15b42ULL,
+       0x2ca616165816b04eULL, 0x74f73a3ae83acdd2ULL, 0xd2066969b9696fd0ULL,
+       0x124109092409482dULL, 0xe0d77070dd70a7adULL, 0x716fb6b6e2b6d954ULL,
+       0xbd1ed0d067d0ceb7ULL, 0xc7d6eded93ed3b7eULL, 0x85e2cccc17cc2edbULL,
+       0x8468424215422a57ULL, 0x2d2c98985a98b4c2ULL, 0x55eda4a4aaa4490eULL,
+       0x50752828a0285d88ULL, 0xb8865c5c6d5cda31ULL, 0xed6bf8f8c7f8933fULL,
+       0x11c28686228644a4ULL,
+};
+
+static const u64 C3[256] = {
+       0x7830d818186018c0ULL, 0xaf462623238c2305ULL, 0xf991b8c6c63fc67eULL,
+       0x6fcdfbe8e887e813ULL, 0xa113cb878726874cULL, 0x626d11b8b8dab8a9ULL,
+       0x0502090101040108ULL, 0x6e9e0d4f4f214f42ULL, 0xee6c9b3636d836adULL,
+       0x0451ffa6a6a2a659ULL, 0xbdb90cd2d26fd2deULL, 0x06f70ef5f5f3f5fbULL,
+       0x80f2967979f979efULL, 0xcede306f6fa16f5fULL, 0xef3f6d91917e91fcULL,
+       0x07a4f852525552aaULL, 0xfdc04760609d6027ULL, 0x766535bcbccabc89ULL,
+       0xcd2b379b9b569bacULL, 0x8c018a8e8e028e04ULL, 0x155bd2a3a3b6a371ULL,
+       0x3c186c0c0c300c60ULL, 0x8af6847b7bf17bffULL, 0xe16a803535d435b5ULL,
+       0x693af51d1d741de8ULL, 0x47ddb3e0e0a7e053ULL, 0xacb321d7d77bd7f6ULL,
+       0xed999cc2c22fc25eULL, 0x965c432e2eb82e6dULL, 0x7a96294b4b314b62ULL,
+       0x21e15dfefedffea3ULL, 0x16aed55757415782ULL, 0x412abd15155415a8ULL,
+       0xb6eee87777c1779fULL, 0xeb6e923737dc37a5ULL, 0x56d79ee5e5b3e57bULL,
+       0xd923139f9f469f8cULL, 0x17fd23f0f0e7f0d3ULL, 0x7f94204a4a354a6aULL,
+       0x95a944dada4fda9eULL, 0x25b0a258587d58faULL, 0xca8fcfc9c903c906ULL,
+       0x8d527c2929a42955ULL, 0x22145a0a0a280a50ULL, 0x4f7f50b1b1feb1e1ULL,
+       0x1a5dc9a0a0baa069ULL, 0xdad6146b6bb16b7fULL, 0xab17d985852e855cULL,
+       0x73673cbdbdcebd81ULL, 0x34ba8f5d5d695dd2ULL, 0x5020901010401080ULL,
+       0x03f507f4f4f7f4f3ULL, 0xc08bddcbcb0bcb16ULL, 0xc67cd33e3ef83eedULL,
+       0x110a2d0505140528ULL, 0xe6ce78676781671fULL, 0x53d597e4e4b7e473ULL,
+       0xbb4e0227279c2725ULL, 0x5882734141194132ULL, 0x9d0ba78b8b168b2cULL,
+       0x0153f6a7a7a6a751ULL, 0x94fab27d7de97dcfULL, 0xfb374995956e95dcULL,
+       0x9fad56d8d847d88eULL, 0x30eb70fbfbcbfb8bULL, 0x71c1cdeeee9fee23ULL,
+       0x91f8bb7c7ced7cc7ULL, 0xe3cc716666856617ULL, 0x8ea77bdddd53dda6ULL,
+       0x4b2eaf17175c17b8ULL, 0x468e454747014702ULL, 0xdc211a9e9e429e84ULL,
+       0xc589d4caca0fca1eULL, 0x995a582d2db42d75ULL, 0x79632ebfbfc6bf91ULL,
+       0x1b0e3f07071c0738ULL, 0x2347acadad8ead01ULL, 0x2fb4b05a5a755aeaULL,
+       0xb51bef838336836cULL, 0xff66b63333cc3385ULL, 0xf2c65c636391633fULL,
+       0x0a04120202080210ULL, 0x384993aaaa92aa39ULL, 0xa8e2de7171d971afULL,
+       0xcf8dc6c8c807c80eULL, 0x7d32d119196419c8ULL, 0x70923b4949394972ULL,
+       0x9aaf5fd9d943d986ULL, 0x1df931f2f2eff2c3ULL, 0x48dba8e3e3abe34bULL,
+       0x2ab6b95b5b715be2ULL, 0x920dbc88881a8834ULL, 0xc8293e9a9a529aa4ULL,
+       0xbe4c0b262698262dULL, 0xfa64bf3232c8328dULL, 0x4a7d59b0b0fab0e9ULL,
+       0x6acff2e9e983e91bULL, 0x331e770f0f3c0f78ULL, 0xa6b733d5d573d5e6ULL,
+       0xba1df480803a8074ULL, 0x7c6127bebec2be99ULL, 0xde87ebcdcd13cd26ULL,
+       0xe468893434d034bdULL, 0x75903248483d487aULL, 0x24e354ffffdbffabULL,
+       0x8ff48d7a7af57af7ULL, 0xea3d6490907a90f4ULL, 0x3ebe9d5f5f615fc2ULL,
+       0xa0403d202080201dULL, 0xd5d00f6868bd6867ULL, 0x7234ca1a1a681ad0ULL,
+       0x2c41b7aeae82ae19ULL, 0x5e757db4b4eab4c9ULL, 0x19a8ce54544d549aULL,
+       0xe53b7f93937693ecULL, 0xaa442f222288220dULL, 0xe9c86364648d6407ULL,
+       0x12ff2af1f1e3f1dbULL, 0xa2e6cc7373d173bfULL, 0x5a24821212481290ULL,
+       0x5d807a40401d403aULL, 0x2810480808200840ULL, 0xe89b95c3c32bc356ULL,
+       0x7bc5dfecec97ec33ULL, 0x90ab4ddbdb4bdb96ULL, 0x1f5fc0a1a1bea161ULL,
+       0x8307918d8d0e8d1cULL, 0xc97ac83d3df43df5ULL, 0xf1335b97976697ccULL,
+       0x0000000000000000ULL, 0xd483f9cfcf1bcf36ULL, 0x87566e2b2bac2b45ULL,
+       0xb3ece17676c57697ULL, 0xb019e68282328264ULL, 0xa9b128d6d67fd6feULL,
+       0x7736c31b1b6c1bd8ULL, 0x5b7774b5b5eeb5c1ULL, 0x2943beafaf86af11ULL,
+       0xdfd41d6a6ab56a77ULL, 0x0da0ea50505d50baULL, 0x4c8a574545094512ULL,
+       0x18fb38f3f3ebf3cbULL, 0xf060ad3030c0309dULL, 0x74c3c4efef9bef2bULL,
+       0xc37eda3f3ffc3fe5ULL, 0x1caac75555495592ULL, 0x1059dba2a2b2a279ULL,
+       0x65c9e9eaea8fea03ULL, 0xecca6a656589650fULL, 0x686903babad2bab9ULL,
+       0x935e4a2f2fbc2f65ULL, 0xe79d8ec0c027c04eULL, 0x81a160dede5fdebeULL,
+       0x6c38fc1c1c701ce0ULL, 0x2ee746fdfdd3fdbbULL, 0x649a1f4d4d294d52ULL,
+       0xe0397692927292e4ULL, 0xbceafa7575c9758fULL, 0x1e0c360606180630ULL,
+       0x9809ae8a8a128a24ULL, 0x40794bb2b2f2b2f9ULL, 0x59d185e6e6bfe663ULL,
+       0x361c7e0e0e380e70ULL, 0x633ee71f1f7c1ff8ULL, 0xf7c4556262956237ULL,
+       0xa3b53ad4d477d4eeULL, 0x324d81a8a89aa829ULL, 0xf4315296966296c4ULL,
+       0x3aef62f9f9c3f99bULL, 0xf697a3c5c533c566ULL, 0xb14a102525942535ULL,
+       0x20b2ab59597959f2ULL, 0xae15d084842a8454ULL, 0xa7e4c57272d572b7ULL,
+       0xdd72ec3939e439d5ULL, 0x6198164c4c2d4c5aULL, 0x3bbc945e5e655ecaULL,
+       0x85f09f7878fd78e7ULL, 0xd870e53838e038ddULL, 0x8605988c8c0a8c14ULL,
+       0xb2bf17d1d163d1c6ULL, 0x0b57e4a5a5aea541ULL, 0x4dd9a1e2e2afe243ULL,
+       0xf8c24e616199612fULL, 0x457b42b3b3f6b3f1ULL, 0xa542342121842115ULL,
+       0xd625089c9c4a9c94ULL, 0x663cee1e1e781ef0ULL, 0x5286614343114322ULL,
+       0xfc93b1c7c73bc776ULL, 0x2be54ffcfcd7fcb3ULL, 0x1408240404100420ULL,
+       0x08a2e351515951b2ULL, 0xc72f2599995e99bcULL, 0xc4da226d6da96d4fULL,
+       0x391a650d0d340d68ULL, 0x35e979fafacffa83ULL, 0x84a369dfdf5bdfb6ULL,
+       0x9bfca97e7ee57ed7ULL, 0xb44819242490243dULL, 0xd776fe3b3bec3bc5ULL,
+       0x3d4b9aabab96ab31ULL, 0xd181f0cece1fce3eULL, 0x5522991111441188ULL,
+       0x8903838f8f068f0cULL, 0x6b9c044e4e254e4aULL, 0x517366b7b7e6b7d1ULL,
+       0x60cbe0ebeb8beb0bULL, 0xcc78c13c3cf03cfdULL, 0xbf1ffd81813e817cULL,
+       0xfe354094946a94d4ULL, 0x0cf31cf7f7fbf7ebULL, 0x676f18b9b9deb9a1ULL,
+       0x5f268b13134c1398ULL, 0x9c58512c2cb02c7dULL, 0xb8bb05d3d36bd3d6ULL,
+       0x5cd38ce7e7bbe76bULL, 0xcbdc396e6ea56e57ULL, 0xf395aac4c437c46eULL,
+       0x0f061b03030c0318ULL, 0x13acdc565645568aULL, 0x49885e44440d441aULL,
+       0x9efea07f7fe17fdfULL, 0x374f88a9a99ea921ULL, 0x8254672a2aa82a4dULL,
+       0x6d6b0abbbbd6bbb1ULL, 0xe29f87c1c123c146ULL, 0x02a6f153535153a2ULL,
+       0x8ba572dcdc57dcaeULL, 0x2716530b0b2c0b58ULL, 0xd327019d9d4e9d9cULL,
+       0xc1d82b6c6cad6c47ULL, 0xf562a43131c43195ULL, 0xb9e8f37474cd7487ULL,
+       0x09f115f6f6fff6e3ULL, 0x438c4c464605460aULL, 0x2645a5acac8aac09ULL,
+       0x970fb589891e893cULL, 0x4428b414145014a0ULL, 0x42dfbae1e1a3e15bULL,
+       0x4e2ca616165816b0ULL, 0xd274f73a3ae83acdULL, 0xd0d2066969b9696fULL,
+       0x2d12410909240948ULL, 0xade0d77070dd70a7ULL, 0x54716fb6b6e2b6d9ULL,
+       0xb7bd1ed0d067d0ceULL, 0x7ec7d6eded93ed3bULL, 0xdb85e2cccc17cc2eULL,
+       0x578468424215422aULL, 0xc22d2c98985a98b4ULL, 0x0e55eda4a4aaa449ULL,
+       0x8850752828a0285dULL, 0x31b8865c5c6d5cdaULL, 0x3fed6bf8f8c7f893ULL,
+       0xa411c28686228644ULL,
+};
+
+static const u64 C4[256] = {
+       0xc07830d818186018ULL, 0x05af462623238c23ULL, 0x7ef991b8c6c63fc6ULL,
+       0x136fcdfbe8e887e8ULL, 0x4ca113cb87872687ULL, 0xa9626d11b8b8dab8ULL,
+       0x0805020901010401ULL, 0x426e9e0d4f4f214fULL, 0xadee6c9b3636d836ULL,
+       0x590451ffa6a6a2a6ULL, 0xdebdb90cd2d26fd2ULL, 0xfb06f70ef5f5f3f5ULL,
+       0xef80f2967979f979ULL, 0x5fcede306f6fa16fULL, 0xfcef3f6d91917e91ULL,
+       0xaa07a4f852525552ULL, 0x27fdc04760609d60ULL, 0x89766535bcbccabcULL,
+       0xaccd2b379b9b569bULL, 0x048c018a8e8e028eULL, 0x71155bd2a3a3b6a3ULL,
+       0x603c186c0c0c300cULL, 0xff8af6847b7bf17bULL, 0xb5e16a803535d435ULL,
+       0xe8693af51d1d741dULL, 0x5347ddb3e0e0a7e0ULL, 0xf6acb321d7d77bd7ULL,
+       0x5eed999cc2c22fc2ULL, 0x6d965c432e2eb82eULL, 0x627a96294b4b314bULL,
+       0xa321e15dfefedffeULL, 0x8216aed557574157ULL, 0xa8412abd15155415ULL,
+       0x9fb6eee87777c177ULL, 0xa5eb6e923737dc37ULL, 0x7b56d79ee5e5b3e5ULL,
+       0x8cd923139f9f469fULL, 0xd317fd23f0f0e7f0ULL, 0x6a7f94204a4a354aULL,
+       0x9e95a944dada4fdaULL, 0xfa25b0a258587d58ULL, 0x06ca8fcfc9c903c9ULL,
+       0x558d527c2929a429ULL, 0x5022145a0a0a280aULL, 0xe14f7f50b1b1feb1ULL,
+       0x691a5dc9a0a0baa0ULL, 0x7fdad6146b6bb16bULL, 0x5cab17d985852e85ULL,
+       0x8173673cbdbdcebdULL, 0xd234ba8f5d5d695dULL, 0x8050209010104010ULL,
+       0xf303f507f4f4f7f4ULL, 0x16c08bddcbcb0bcbULL, 0xedc67cd33e3ef83eULL,
+       0x28110a2d05051405ULL, 0x1fe6ce7867678167ULL, 0x7353d597e4e4b7e4ULL,
+       0x25bb4e0227279c27ULL, 0x3258827341411941ULL, 0x2c9d0ba78b8b168bULL,
+       0x510153f6a7a7a6a7ULL, 0xcf94fab27d7de97dULL, 0xdcfb374995956e95ULL,
+       0x8e9fad56d8d847d8ULL, 0x8b30eb70fbfbcbfbULL, 0x2371c1cdeeee9feeULL,
+       0xc791f8bb7c7ced7cULL, 0x17e3cc7166668566ULL, 0xa68ea77bdddd53ddULL,
+       0xb84b2eaf17175c17ULL, 0x02468e4547470147ULL, 0x84dc211a9e9e429eULL,
+       0x1ec589d4caca0fcaULL, 0x75995a582d2db42dULL, 0x9179632ebfbfc6bfULL,
+       0x381b0e3f07071c07ULL, 0x012347acadad8eadULL, 0xea2fb4b05a5a755aULL,
+       0x6cb51bef83833683ULL, 0x85ff66b63333cc33ULL, 0x3ff2c65c63639163ULL,
+       0x100a041202020802ULL, 0x39384993aaaa92aaULL, 0xafa8e2de7171d971ULL,
+       0x0ecf8dc6c8c807c8ULL, 0xc87d32d119196419ULL, 0x7270923b49493949ULL,
+       0x869aaf5fd9d943d9ULL, 0xc31df931f2f2eff2ULL, 0x4b48dba8e3e3abe3ULL,
+       0xe22ab6b95b5b715bULL, 0x34920dbc88881a88ULL, 0xa4c8293e9a9a529aULL,
+       0x2dbe4c0b26269826ULL, 0x8dfa64bf3232c832ULL, 0xe94a7d59b0b0fab0ULL,
+       0x1b6acff2e9e983e9ULL, 0x78331e770f0f3c0fULL, 0xe6a6b733d5d573d5ULL,
+       0x74ba1df480803a80ULL, 0x997c6127bebec2beULL, 0x26de87ebcdcd13cdULL,
+       0xbde468893434d034ULL, 0x7a75903248483d48ULL, 0xab24e354ffffdbffULL,
+       0xf78ff48d7a7af57aULL, 0xf4ea3d6490907a90ULL, 0xc23ebe9d5f5f615fULL,
+       0x1da0403d20208020ULL, 0x67d5d00f6868bd68ULL, 0xd07234ca1a1a681aULL,
+       0x192c41b7aeae82aeULL, 0xc95e757db4b4eab4ULL, 0x9a19a8ce54544d54ULL,
+       0xece53b7f93937693ULL, 0x0daa442f22228822ULL, 0x07e9c86364648d64ULL,
+       0xdb12ff2af1f1e3f1ULL, 0xbfa2e6cc7373d173ULL, 0x905a248212124812ULL,
+       0x3a5d807a40401d40ULL, 0x4028104808082008ULL, 0x56e89b95c3c32bc3ULL,
+       0x337bc5dfecec97ecULL, 0x9690ab4ddbdb4bdbULL, 0x611f5fc0a1a1bea1ULL,
+       0x1c8307918d8d0e8dULL, 0xf5c97ac83d3df43dULL, 0xccf1335b97976697ULL,
+       0x0000000000000000ULL, 0x36d483f9cfcf1bcfULL, 0x4587566e2b2bac2bULL,
+       0x97b3ece17676c576ULL, 0x64b019e682823282ULL, 0xfea9b128d6d67fd6ULL,
+       0xd87736c31b1b6c1bULL, 0xc15b7774b5b5eeb5ULL, 0x112943beafaf86afULL,
+       0x77dfd41d6a6ab56aULL, 0xba0da0ea50505d50ULL, 0x124c8a5745450945ULL,
+       0xcb18fb38f3f3ebf3ULL, 0x9df060ad3030c030ULL, 0x2b74c3c4efef9befULL,
+       0xe5c37eda3f3ffc3fULL, 0x921caac755554955ULL, 0x791059dba2a2b2a2ULL,
+       0x0365c9e9eaea8feaULL, 0x0fecca6a65658965ULL, 0xb9686903babad2baULL,
+       0x65935e4a2f2fbc2fULL, 0x4ee79d8ec0c027c0ULL, 0xbe81a160dede5fdeULL,
+       0xe06c38fc1c1c701cULL, 0xbb2ee746fdfdd3fdULL, 0x52649a1f4d4d294dULL,
+       0xe4e0397692927292ULL, 0x8fbceafa7575c975ULL, 0x301e0c3606061806ULL,
+       0x249809ae8a8a128aULL, 0xf940794bb2b2f2b2ULL, 0x6359d185e6e6bfe6ULL,
+       0x70361c7e0e0e380eULL, 0xf8633ee71f1f7c1fULL, 0x37f7c45562629562ULL,
+       0xeea3b53ad4d477d4ULL, 0x29324d81a8a89aa8ULL, 0xc4f4315296966296ULL,
+       0x9b3aef62f9f9c3f9ULL, 0x66f697a3c5c533c5ULL, 0x35b14a1025259425ULL,
+       0xf220b2ab59597959ULL, 0x54ae15d084842a84ULL, 0xb7a7e4c57272d572ULL,
+       0xd5dd72ec3939e439ULL, 0x5a6198164c4c2d4cULL, 0xca3bbc945e5e655eULL,
+       0xe785f09f7878fd78ULL, 0xddd870e53838e038ULL, 0x148605988c8c0a8cULL,
+       0xc6b2bf17d1d163d1ULL, 0x410b57e4a5a5aea5ULL, 0x434dd9a1e2e2afe2ULL,
+       0x2ff8c24e61619961ULL, 0xf1457b42b3b3f6b3ULL, 0x15a5423421218421ULL,
+       0x94d625089c9c4a9cULL, 0xf0663cee1e1e781eULL, 0x2252866143431143ULL,
+       0x76fc93b1c7c73bc7ULL, 0xb32be54ffcfcd7fcULL, 0x2014082404041004ULL,
+       0xb208a2e351515951ULL, 0xbcc72f2599995e99ULL, 0x4fc4da226d6da96dULL,
+       0x68391a650d0d340dULL, 0x8335e979fafacffaULL, 0xb684a369dfdf5bdfULL,
+       0xd79bfca97e7ee57eULL, 0x3db4481924249024ULL, 0xc5d776fe3b3bec3bULL,
+       0x313d4b9aabab96abULL, 0x3ed181f0cece1fceULL, 0x8855229911114411ULL,
+       0x0c8903838f8f068fULL, 0x4a6b9c044e4e254eULL, 0xd1517366b7b7e6b7ULL,
+       0x0b60cbe0ebeb8bebULL, 0xfdcc78c13c3cf03cULL, 0x7cbf1ffd81813e81ULL,
+       0xd4fe354094946a94ULL, 0xeb0cf31cf7f7fbf7ULL, 0xa1676f18b9b9deb9ULL,
+       0x985f268b13134c13ULL, 0x7d9c58512c2cb02cULL, 0xd6b8bb05d3d36bd3ULL,
+       0x6b5cd38ce7e7bbe7ULL, 0x57cbdc396e6ea56eULL, 0x6ef395aac4c437c4ULL,
+       0x180f061b03030c03ULL, 0x8a13acdc56564556ULL, 0x1a49885e44440d44ULL,
+       0xdf9efea07f7fe17fULL, 0x21374f88a9a99ea9ULL, 0x4d8254672a2aa82aULL,
+       0xb16d6b0abbbbd6bbULL, 0x46e29f87c1c123c1ULL, 0xa202a6f153535153ULL,
+       0xae8ba572dcdc57dcULL, 0x582716530b0b2c0bULL, 0x9cd327019d9d4e9dULL,
+       0x47c1d82b6c6cad6cULL, 0x95f562a43131c431ULL, 0x87b9e8f37474cd74ULL,
+       0xe309f115f6f6fff6ULL, 0x0a438c4c46460546ULL, 0x092645a5acac8aacULL,
+       0x3c970fb589891e89ULL, 0xa04428b414145014ULL, 0x5b42dfbae1e1a3e1ULL,
+       0xb04e2ca616165816ULL, 0xcdd274f73a3ae83aULL, 0x6fd0d2066969b969ULL,
+       0x482d124109092409ULL, 0xa7ade0d77070dd70ULL, 0xd954716fb6b6e2b6ULL,
+       0xceb7bd1ed0d067d0ULL, 0x3b7ec7d6eded93edULL, 0x2edb85e2cccc17ccULL,
+       0x2a57846842421542ULL, 0xb4c22d2c98985a98ULL, 0x490e55eda4a4aaa4ULL,
+       0x5d8850752828a028ULL, 0xda31b8865c5c6d5cULL, 0x933fed6bf8f8c7f8ULL,
+       0x44a411c286862286ULL,
+};
+
+static const u64 C5[256] = {
+       0x18c07830d8181860ULL, 0x2305af462623238cULL, 0xc67ef991b8c6c63fULL,
+       0xe8136fcdfbe8e887ULL, 0x874ca113cb878726ULL, 0xb8a9626d11b8b8daULL,
+       0x0108050209010104ULL, 0x4f426e9e0d4f4f21ULL, 0x36adee6c9b3636d8ULL,
+       0xa6590451ffa6a6a2ULL, 0xd2debdb90cd2d26fULL, 0xf5fb06f70ef5f5f3ULL,
+       0x79ef80f2967979f9ULL, 0x6f5fcede306f6fa1ULL, 0x91fcef3f6d91917eULL,
+       0x52aa07a4f8525255ULL, 0x6027fdc04760609dULL, 0xbc89766535bcbccaULL,
+       0x9baccd2b379b9b56ULL, 0x8e048c018a8e8e02ULL, 0xa371155bd2a3a3b6ULL,
+       0x0c603c186c0c0c30ULL, 0x7bff8af6847b7bf1ULL, 0x35b5e16a803535d4ULL,
+       0x1de8693af51d1d74ULL, 0xe05347ddb3e0e0a7ULL, 0xd7f6acb321d7d77bULL,
+       0xc25eed999cc2c22fULL, 0x2e6d965c432e2eb8ULL, 0x4b627a96294b4b31ULL,
+       0xfea321e15dfefedfULL, 0x578216aed5575741ULL, 0x15a8412abd151554ULL,
+       0x779fb6eee87777c1ULL, 0x37a5eb6e923737dcULL, 0xe57b56d79ee5e5b3ULL,
+       0x9f8cd923139f9f46ULL, 0xf0d317fd23f0f0e7ULL, 0x4a6a7f94204a4a35ULL,
+       0xda9e95a944dada4fULL, 0x58fa25b0a258587dULL, 0xc906ca8fcfc9c903ULL,
+       0x29558d527c2929a4ULL, 0x0a5022145a0a0a28ULL, 0xb1e14f7f50b1b1feULL,
+       0xa0691a5dc9a0a0baULL, 0x6b7fdad6146b6bb1ULL, 0x855cab17d985852eULL,
+       0xbd8173673cbdbdceULL, 0x5dd234ba8f5d5d69ULL, 0x1080502090101040ULL,
+       0xf4f303f507f4f4f7ULL, 0xcb16c08bddcbcb0bULL, 0x3eedc67cd33e3ef8ULL,
+       0x0528110a2d050514ULL, 0x671fe6ce78676781ULL, 0xe47353d597e4e4b7ULL,
+       0x2725bb4e0227279cULL, 0x4132588273414119ULL, 0x8b2c9d0ba78b8b16ULL,
+       0xa7510153f6a7a7a6ULL, 0x7dcf94fab27d7de9ULL, 0x95dcfb374995956eULL,
+       0xd88e9fad56d8d847ULL, 0xfb8b30eb70fbfbcbULL, 0xee2371c1cdeeee9fULL,
+       0x7cc791f8bb7c7cedULL, 0x6617e3cc71666685ULL, 0xdda68ea77bdddd53ULL,
+       0x17b84b2eaf17175cULL, 0x4702468e45474701ULL, 0x9e84dc211a9e9e42ULL,
+       0xca1ec589d4caca0fULL, 0x2d75995a582d2db4ULL, 0xbf9179632ebfbfc6ULL,
+       0x07381b0e3f07071cULL, 0xad012347acadad8eULL, 0x5aea2fb4b05a5a75ULL,
+       0x836cb51bef838336ULL, 0x3385ff66b63333ccULL, 0x633ff2c65c636391ULL,
+       0x02100a0412020208ULL, 0xaa39384993aaaa92ULL, 0x71afa8e2de7171d9ULL,
+       0xc80ecf8dc6c8c807ULL, 0x19c87d32d1191964ULL, 0x497270923b494939ULL,
+       0xd9869aaf5fd9d943ULL, 0xf2c31df931f2f2efULL, 0xe34b48dba8e3e3abULL,
+       0x5be22ab6b95b5b71ULL, 0x8834920dbc88881aULL, 0x9aa4c8293e9a9a52ULL,
+       0x262dbe4c0b262698ULL, 0x328dfa64bf3232c8ULL, 0xb0e94a7d59b0b0faULL,
+       0xe91b6acff2e9e983ULL, 0x0f78331e770f0f3cULL, 0xd5e6a6b733d5d573ULL,
+       0x8074ba1df480803aULL, 0xbe997c6127bebec2ULL, 0xcd26de87ebcdcd13ULL,
+       0x34bde468893434d0ULL, 0x487a75903248483dULL, 0xffab24e354ffffdbULL,
+       0x7af78ff48d7a7af5ULL, 0x90f4ea3d6490907aULL, 0x5fc23ebe9d5f5f61ULL,
+       0x201da0403d202080ULL, 0x6867d5d00f6868bdULL, 0x1ad07234ca1a1a68ULL,
+       0xae192c41b7aeae82ULL, 0xb4c95e757db4b4eaULL, 0x549a19a8ce54544dULL,
+       0x93ece53b7f939376ULL, 0x220daa442f222288ULL, 0x6407e9c86364648dULL,
+       0xf1db12ff2af1f1e3ULL, 0x73bfa2e6cc7373d1ULL, 0x12905a2482121248ULL,
+       0x403a5d807a40401dULL, 0x0840281048080820ULL, 0xc356e89b95c3c32bULL,
+       0xec337bc5dfecec97ULL, 0xdb9690ab4ddbdb4bULL, 0xa1611f5fc0a1a1beULL,
+       0x8d1c8307918d8d0eULL, 0x3df5c97ac83d3df4ULL, 0x97ccf1335b979766ULL,
+       0x0000000000000000ULL, 0xcf36d483f9cfcf1bULL, 0x2b4587566e2b2bacULL,
+       0x7697b3ece17676c5ULL, 0x8264b019e6828232ULL, 0xd6fea9b128d6d67fULL,
+       0x1bd87736c31b1b6cULL, 0xb5c15b7774b5b5eeULL, 0xaf112943beafaf86ULL,
+       0x6a77dfd41d6a6ab5ULL, 0x50ba0da0ea50505dULL, 0x45124c8a57454509ULL,
+       0xf3cb18fb38f3f3ebULL, 0x309df060ad3030c0ULL, 0xef2b74c3c4efef9bULL,
+       0x3fe5c37eda3f3ffcULL, 0x55921caac7555549ULL, 0xa2791059dba2a2b2ULL,
+       0xea0365c9e9eaea8fULL, 0x650fecca6a656589ULL, 0xbab9686903babad2ULL,
+       0x2f65935e4a2f2fbcULL, 0xc04ee79d8ec0c027ULL, 0xdebe81a160dede5fULL,
+       0x1ce06c38fc1c1c70ULL, 0xfdbb2ee746fdfdd3ULL, 0x4d52649a1f4d4d29ULL,
+       0x92e4e03976929272ULL, 0x758fbceafa7575c9ULL, 0x06301e0c36060618ULL,
+       0x8a249809ae8a8a12ULL, 0xb2f940794bb2b2f2ULL, 0xe66359d185e6e6bfULL,
+       0x0e70361c7e0e0e38ULL, 0x1ff8633ee71f1f7cULL, 0x6237f7c455626295ULL,
+       0xd4eea3b53ad4d477ULL, 0xa829324d81a8a89aULL, 0x96c4f43152969662ULL,
+       0xf99b3aef62f9f9c3ULL, 0xc566f697a3c5c533ULL, 0x2535b14a10252594ULL,
+       0x59f220b2ab595979ULL, 0x8454ae15d084842aULL, 0x72b7a7e4c57272d5ULL,
+       0x39d5dd72ec3939e4ULL, 0x4c5a6198164c4c2dULL, 0x5eca3bbc945e5e65ULL,
+       0x78e785f09f7878fdULL, 0x38ddd870e53838e0ULL, 0x8c148605988c8c0aULL,
+       0xd1c6b2bf17d1d163ULL, 0xa5410b57e4a5a5aeULL, 0xe2434dd9a1e2e2afULL,
+       0x612ff8c24e616199ULL, 0xb3f1457b42b3b3f6ULL, 0x2115a54234212184ULL,
+       0x9c94d625089c9c4aULL, 0x1ef0663cee1e1e78ULL, 0x4322528661434311ULL,
+       0xc776fc93b1c7c73bULL, 0xfcb32be54ffcfcd7ULL, 0x0420140824040410ULL,
+       0x51b208a2e3515159ULL, 0x99bcc72f2599995eULL, 0x6d4fc4da226d6da9ULL,
+       0x0d68391a650d0d34ULL, 0xfa8335e979fafacfULL, 0xdfb684a369dfdf5bULL,
+       0x7ed79bfca97e7ee5ULL, 0x243db44819242490ULL, 0x3bc5d776fe3b3becULL,
+       0xab313d4b9aabab96ULL, 0xce3ed181f0cece1fULL, 0x1188552299111144ULL,
+       0x8f0c8903838f8f06ULL, 0x4e4a6b9c044e4e25ULL, 0xb7d1517366b7b7e6ULL,
+       0xeb0b60cbe0ebeb8bULL, 0x3cfdcc78c13c3cf0ULL, 0x817cbf1ffd81813eULL,
+       0x94d4fe354094946aULL, 0xf7eb0cf31cf7f7fbULL, 0xb9a1676f18b9b9deULL,
+       0x13985f268b13134cULL, 0x2c7d9c58512c2cb0ULL, 0xd3d6b8bb05d3d36bULL,
+       0xe76b5cd38ce7e7bbULL, 0x6e57cbdc396e6ea5ULL, 0xc46ef395aac4c437ULL,
+       0x03180f061b03030cULL, 0x568a13acdc565645ULL, 0x441a49885e44440dULL,
+       0x7fdf9efea07f7fe1ULL, 0xa921374f88a9a99eULL, 0x2a4d8254672a2aa8ULL,
+       0xbbb16d6b0abbbbd6ULL, 0xc146e29f87c1c123ULL, 0x53a202a6f1535351ULL,
+       0xdcae8ba572dcdc57ULL, 0x0b582716530b0b2cULL, 0x9d9cd327019d9d4eULL,
+       0x6c47c1d82b6c6cadULL, 0x3195f562a43131c4ULL, 0x7487b9e8f37474cdULL,
+       0xf6e309f115f6f6ffULL, 0x460a438c4c464605ULL, 0xac092645a5acac8aULL,
+       0x893c970fb589891eULL, 0x14a04428b4141450ULL, 0xe15b42dfbae1e1a3ULL,
+       0x16b04e2ca6161658ULL, 0x3acdd274f73a3ae8ULL, 0x696fd0d2066969b9ULL,
+       0x09482d1241090924ULL, 0x70a7ade0d77070ddULL, 0xb6d954716fb6b6e2ULL,
+       0xd0ceb7bd1ed0d067ULL, 0xed3b7ec7d6eded93ULL, 0xcc2edb85e2cccc17ULL,
+       0x422a578468424215ULL, 0x98b4c22d2c98985aULL, 0xa4490e55eda4a4aaULL,
+       0x285d8850752828a0ULL, 0x5cda31b8865c5c6dULL, 0xf8933fed6bf8f8c7ULL,
+       0x8644a411c2868622ULL,
+};
+
+static const u64 C6[256] = {
+       0x6018c07830d81818ULL, 0x8c2305af46262323ULL, 0x3fc67ef991b8c6c6ULL,
+       0x87e8136fcdfbe8e8ULL, 0x26874ca113cb8787ULL, 0xdab8a9626d11b8b8ULL,
+       0x0401080502090101ULL, 0x214f426e9e0d4f4fULL, 0xd836adee6c9b3636ULL,
+       0xa2a6590451ffa6a6ULL, 0x6fd2debdb90cd2d2ULL, 0xf3f5fb06f70ef5f5ULL,
+       0xf979ef80f2967979ULL, 0xa16f5fcede306f6fULL, 0x7e91fcef3f6d9191ULL,
+       0x5552aa07a4f85252ULL, 0x9d6027fdc0476060ULL, 0xcabc89766535bcbcULL,
+       0x569baccd2b379b9bULL, 0x028e048c018a8e8eULL, 0xb6a371155bd2a3a3ULL,
+       0x300c603c186c0c0cULL, 0xf17bff8af6847b7bULL, 0xd435b5e16a803535ULL,
+       0x741de8693af51d1dULL, 0xa7e05347ddb3e0e0ULL, 0x7bd7f6acb321d7d7ULL,
+       0x2fc25eed999cc2c2ULL, 0xb82e6d965c432e2eULL, 0x314b627a96294b4bULL,
+       0xdffea321e15dfefeULL, 0x41578216aed55757ULL, 0x5415a8412abd1515ULL,
+       0xc1779fb6eee87777ULL, 0xdc37a5eb6e923737ULL, 0xb3e57b56d79ee5e5ULL,
+       0x469f8cd923139f9fULL, 0xe7f0d317fd23f0f0ULL, 0x354a6a7f94204a4aULL,
+       0x4fda9e95a944dadaULL, 0x7d58fa25b0a25858ULL, 0x03c906ca8fcfc9c9ULL,
+       0xa429558d527c2929ULL, 0x280a5022145a0a0aULL, 0xfeb1e14f7f50b1b1ULL,
+       0xbaa0691a5dc9a0a0ULL, 0xb16b7fdad6146b6bULL, 0x2e855cab17d98585ULL,
+       0xcebd8173673cbdbdULL, 0x695dd234ba8f5d5dULL, 0x4010805020901010ULL,
+       0xf7f4f303f507f4f4ULL, 0x0bcb16c08bddcbcbULL, 0xf83eedc67cd33e3eULL,
+       0x140528110a2d0505ULL, 0x81671fe6ce786767ULL, 0xb7e47353d597e4e4ULL,
+       0x9c2725bb4e022727ULL, 0x1941325882734141ULL, 0x168b2c9d0ba78b8bULL,
+       0xa6a7510153f6a7a7ULL, 0xe97dcf94fab27d7dULL, 0x6e95dcfb37499595ULL,
+       0x47d88e9fad56d8d8ULL, 0xcbfb8b30eb70fbfbULL, 0x9fee2371c1cdeeeeULL,
+       0xed7cc791f8bb7c7cULL, 0x856617e3cc716666ULL, 0x53dda68ea77bddddULL,
+       0x5c17b84b2eaf1717ULL, 0x014702468e454747ULL, 0x429e84dc211a9e9eULL,
+       0x0fca1ec589d4cacaULL, 0xb42d75995a582d2dULL, 0xc6bf9179632ebfbfULL,
+       0x1c07381b0e3f0707ULL, 0x8ead012347acadadULL, 0x755aea2fb4b05a5aULL,
+       0x36836cb51bef8383ULL, 0xcc3385ff66b63333ULL, 0x91633ff2c65c6363ULL,
+       0x0802100a04120202ULL, 0x92aa39384993aaaaULL, 0xd971afa8e2de7171ULL,
+       0x07c80ecf8dc6c8c8ULL, 0x6419c87d32d11919ULL, 0x39497270923b4949ULL,
+       0x43d9869aaf5fd9d9ULL, 0xeff2c31df931f2f2ULL, 0xabe34b48dba8e3e3ULL,
+       0x715be22ab6b95b5bULL, 0x1a8834920dbc8888ULL, 0x529aa4c8293e9a9aULL,
+       0x98262dbe4c0b2626ULL, 0xc8328dfa64bf3232ULL, 0xfab0e94a7d59b0b0ULL,
+       0x83e91b6acff2e9e9ULL, 0x3c0f78331e770f0fULL, 0x73d5e6a6b733d5d5ULL,
+       0x3a8074ba1df48080ULL, 0xc2be997c6127bebeULL, 0x13cd26de87ebcdcdULL,
+       0xd034bde468893434ULL, 0x3d487a7590324848ULL, 0xdbffab24e354ffffULL,
+       0xf57af78ff48d7a7aULL, 0x7a90f4ea3d649090ULL, 0x615fc23ebe9d5f5fULL,
+       0x80201da0403d2020ULL, 0xbd6867d5d00f6868ULL, 0x681ad07234ca1a1aULL,
+       0x82ae192c41b7aeaeULL, 0xeab4c95e757db4b4ULL, 0x4d549a19a8ce5454ULL,
+       0x7693ece53b7f9393ULL, 0x88220daa442f2222ULL, 0x8d6407e9c8636464ULL,
+       0xe3f1db12ff2af1f1ULL, 0xd173bfa2e6cc7373ULL, 0x4812905a24821212ULL,
+       0x1d403a5d807a4040ULL, 0x2008402810480808ULL, 0x2bc356e89b95c3c3ULL,
+       0x97ec337bc5dfececULL, 0x4bdb9690ab4ddbdbULL, 0xbea1611f5fc0a1a1ULL,
+       0x0e8d1c8307918d8dULL, 0xf43df5c97ac83d3dULL, 0x6697ccf1335b9797ULL,
+       0x0000000000000000ULL, 0x1bcf36d483f9cfcfULL, 0xac2b4587566e2b2bULL,
+       0xc57697b3ece17676ULL, 0x328264b019e68282ULL, 0x7fd6fea9b128d6d6ULL,
+       0x6c1bd87736c31b1bULL, 0xeeb5c15b7774b5b5ULL, 0x86af112943beafafULL,
+       0xb56a77dfd41d6a6aULL, 0x5d50ba0da0ea5050ULL, 0x0945124c8a574545ULL,
+       0xebf3cb18fb38f3f3ULL, 0xc0309df060ad3030ULL, 0x9bef2b74c3c4efefULL,
+       0xfc3fe5c37eda3f3fULL, 0x4955921caac75555ULL, 0xb2a2791059dba2a2ULL,
+       0x8fea0365c9e9eaeaULL, 0x89650fecca6a6565ULL, 0xd2bab9686903babaULL,
+       0xbc2f65935e4a2f2fULL, 0x27c04ee79d8ec0c0ULL, 0x5fdebe81a160dedeULL,
+       0x701ce06c38fc1c1cULL, 0xd3fdbb2ee746fdfdULL, 0x294d52649a1f4d4dULL,
+       0x7292e4e039769292ULL, 0xc9758fbceafa7575ULL, 0x1806301e0c360606ULL,
+       0x128a249809ae8a8aULL, 0xf2b2f940794bb2b2ULL, 0xbfe66359d185e6e6ULL,
+       0x380e70361c7e0e0eULL, 0x7c1ff8633ee71f1fULL, 0x956237f7c4556262ULL,
+       0x77d4eea3b53ad4d4ULL, 0x9aa829324d81a8a8ULL, 0x6296c4f431529696ULL,
+       0xc3f99b3aef62f9f9ULL, 0x33c566f697a3c5c5ULL, 0x942535b14a102525ULL,
+       0x7959f220b2ab5959ULL, 0x2a8454ae15d08484ULL, 0xd572b7a7e4c57272ULL,
+       0xe439d5dd72ec3939ULL, 0x2d4c5a6198164c4cULL, 0x655eca3bbc945e5eULL,
+       0xfd78e785f09f7878ULL, 0xe038ddd870e53838ULL, 0x0a8c148605988c8cULL,
+       0x63d1c6b2bf17d1d1ULL, 0xaea5410b57e4a5a5ULL, 0xafe2434dd9a1e2e2ULL,
+       0x99612ff8c24e6161ULL, 0xf6b3f1457b42b3b3ULL, 0x842115a542342121ULL,
+       0x4a9c94d625089c9cULL, 0x781ef0663cee1e1eULL, 0x1143225286614343ULL,
+       0x3bc776fc93b1c7c7ULL, 0xd7fcb32be54ffcfcULL, 0x1004201408240404ULL,
+       0x5951b208a2e35151ULL, 0x5e99bcc72f259999ULL, 0xa96d4fc4da226d6dULL,
+       0x340d68391a650d0dULL, 0xcffa8335e979fafaULL, 0x5bdfb684a369dfdfULL,
+       0xe57ed79bfca97e7eULL, 0x90243db448192424ULL, 0xec3bc5d776fe3b3bULL,
+       0x96ab313d4b9aababULL, 0x1fce3ed181f0ceceULL, 0x4411885522991111ULL,
+       0x068f0c8903838f8fULL, 0x254e4a6b9c044e4eULL, 0xe6b7d1517366b7b7ULL,
+       0x8beb0b60cbe0ebebULL, 0xf03cfdcc78c13c3cULL, 0x3e817cbf1ffd8181ULL,
+       0x6a94d4fe35409494ULL, 0xfbf7eb0cf31cf7f7ULL, 0xdeb9a1676f18b9b9ULL,
+       0x4c13985f268b1313ULL, 0xb02c7d9c58512c2cULL, 0x6bd3d6b8bb05d3d3ULL,
+       0xbbe76b5cd38ce7e7ULL, 0xa56e57cbdc396e6eULL, 0x37c46ef395aac4c4ULL,
+       0x0c03180f061b0303ULL, 0x45568a13acdc5656ULL, 0x0d441a49885e4444ULL,
+       0xe17fdf9efea07f7fULL, 0x9ea921374f88a9a9ULL, 0xa82a4d8254672a2aULL,
+       0xd6bbb16d6b0abbbbULL, 0x23c146e29f87c1c1ULL, 0x5153a202a6f15353ULL,
+       0x57dcae8ba572dcdcULL, 0x2c0b582716530b0bULL, 0x4e9d9cd327019d9dULL,
+       0xad6c47c1d82b6c6cULL, 0xc43195f562a43131ULL, 0xcd7487b9e8f37474ULL,
+       0xfff6e309f115f6f6ULL, 0x05460a438c4c4646ULL, 0x8aac092645a5acacULL,
+       0x1e893c970fb58989ULL, 0x5014a04428b41414ULL, 0xa3e15b42dfbae1e1ULL,
+       0x5816b04e2ca61616ULL, 0xe83acdd274f73a3aULL, 0xb9696fd0d2066969ULL,
+       0x2409482d12410909ULL, 0xdd70a7ade0d77070ULL, 0xe2b6d954716fb6b6ULL,
+       0x67d0ceb7bd1ed0d0ULL, 0x93ed3b7ec7d6ededULL, 0x17cc2edb85e2ccccULL,
+       0x15422a5784684242ULL, 0x5a98b4c22d2c9898ULL, 0xaaa4490e55eda4a4ULL,
+       0xa0285d8850752828ULL, 0x6d5cda31b8865c5cULL, 0xc7f8933fed6bf8f8ULL,
+       0x228644a411c28686ULL,
+};
+
+static const u64 C7[256] = {
+       0x186018c07830d818ULL, 0x238c2305af462623ULL, 0xc63fc67ef991b8c6ULL,
+       0xe887e8136fcdfbe8ULL, 0x8726874ca113cb87ULL, 0xb8dab8a9626d11b8ULL,
+       0x0104010805020901ULL, 0x4f214f426e9e0d4fULL, 0x36d836adee6c9b36ULL,
+       0xa6a2a6590451ffa6ULL, 0xd26fd2debdb90cd2ULL, 0xf5f3f5fb06f70ef5ULL,
+       0x79f979ef80f29679ULL, 0x6fa16f5fcede306fULL, 0x917e91fcef3f6d91ULL,
+       0x525552aa07a4f852ULL, 0x609d6027fdc04760ULL, 0xbccabc89766535bcULL,
+       0x9b569baccd2b379bULL, 0x8e028e048c018a8eULL, 0xa3b6a371155bd2a3ULL,
+       0x0c300c603c186c0cULL, 0x7bf17bff8af6847bULL, 0x35d435b5e16a8035ULL,
+       0x1d741de8693af51dULL, 0xe0a7e05347ddb3e0ULL, 0xd77bd7f6acb321d7ULL,
+       0xc22fc25eed999cc2ULL, 0x2eb82e6d965c432eULL, 0x4b314b627a96294bULL,
+       0xfedffea321e15dfeULL, 0x5741578216aed557ULL, 0x155415a8412abd15ULL,
+       0x77c1779fb6eee877ULL, 0x37dc37a5eb6e9237ULL, 0xe5b3e57b56d79ee5ULL,
+       0x9f469f8cd923139fULL, 0xf0e7f0d317fd23f0ULL, 0x4a354a6a7f94204aULL,
+       0xda4fda9e95a944daULL, 0x587d58fa25b0a258ULL, 0xc903c906ca8fcfc9ULL,
+       0x29a429558d527c29ULL, 0x0a280a5022145a0aULL, 0xb1feb1e14f7f50b1ULL,
+       0xa0baa0691a5dc9a0ULL, 0x6bb16b7fdad6146bULL, 0x852e855cab17d985ULL,
+       0xbdcebd8173673cbdULL, 0x5d695dd234ba8f5dULL, 0x1040108050209010ULL,
+       0xf4f7f4f303f507f4ULL, 0xcb0bcb16c08bddcbULL, 0x3ef83eedc67cd33eULL,
+       0x05140528110a2d05ULL, 0x6781671fe6ce7867ULL, 0xe4b7e47353d597e4ULL,
+       0x279c2725bb4e0227ULL, 0x4119413258827341ULL, 0x8b168b2c9d0ba78bULL,
+       0xa7a6a7510153f6a7ULL, 0x7de97dcf94fab27dULL, 0x956e95dcfb374995ULL,
+       0xd847d88e9fad56d8ULL, 0xfbcbfb8b30eb70fbULL, 0xee9fee2371c1cdeeULL,
+       0x7ced7cc791f8bb7cULL, 0x66856617e3cc7166ULL, 0xdd53dda68ea77bddULL,
+       0x175c17b84b2eaf17ULL, 0x47014702468e4547ULL, 0x9e429e84dc211a9eULL,
+       0xca0fca1ec589d4caULL, 0x2db42d75995a582dULL, 0xbfc6bf9179632ebfULL,
+       0x071c07381b0e3f07ULL, 0xad8ead012347acadULL, 0x5a755aea2fb4b05aULL,
+       0x8336836cb51bef83ULL, 0x33cc3385ff66b633ULL, 0x6391633ff2c65c63ULL,
+       0x020802100a041202ULL, 0xaa92aa39384993aaULL, 0x71d971afa8e2de71ULL,
+       0xc807c80ecf8dc6c8ULL, 0x196419c87d32d119ULL, 0x4939497270923b49ULL,
+       0xd943d9869aaf5fd9ULL, 0xf2eff2c31df931f2ULL, 0xe3abe34b48dba8e3ULL,
+       0x5b715be22ab6b95bULL, 0x881a8834920dbc88ULL, 0x9a529aa4c8293e9aULL,
+       0x2698262dbe4c0b26ULL, 0x32c8328dfa64bf32ULL, 0xb0fab0e94a7d59b0ULL,
+       0xe983e91b6acff2e9ULL, 0x0f3c0f78331e770fULL, 0xd573d5e6a6b733d5ULL,
+       0x803a8074ba1df480ULL, 0xbec2be997c6127beULL, 0xcd13cd26de87ebcdULL,
+       0x34d034bde4688934ULL, 0x483d487a75903248ULL, 0xffdbffab24e354ffULL,
+       0x7af57af78ff48d7aULL, 0x907a90f4ea3d6490ULL, 0x5f615fc23ebe9d5fULL,
+       0x2080201da0403d20ULL, 0x68bd6867d5d00f68ULL, 0x1a681ad07234ca1aULL,
+       0xae82ae192c41b7aeULL, 0xb4eab4c95e757db4ULL, 0x544d549a19a8ce54ULL,
+       0x937693ece53b7f93ULL, 0x2288220daa442f22ULL, 0x648d6407e9c86364ULL,
+       0xf1e3f1db12ff2af1ULL, 0x73d173bfa2e6cc73ULL, 0x124812905a248212ULL,
+       0x401d403a5d807a40ULL, 0x0820084028104808ULL, 0xc32bc356e89b95c3ULL,
+       0xec97ec337bc5dfecULL, 0xdb4bdb9690ab4ddbULL, 0xa1bea1611f5fc0a1ULL,
+       0x8d0e8d1c8307918dULL, 0x3df43df5c97ac83dULL, 0x976697ccf1335b97ULL,
+       0x0000000000000000ULL, 0xcf1bcf36d483f9cfULL, 0x2bac2b4587566e2bULL,
+       0x76c57697b3ece176ULL, 0x82328264b019e682ULL, 0xd67fd6fea9b128d6ULL,
+       0x1b6c1bd87736c31bULL, 0xb5eeb5c15b7774b5ULL, 0xaf86af112943beafULL,
+       0x6ab56a77dfd41d6aULL, 0x505d50ba0da0ea50ULL, 0x450945124c8a5745ULL,
+       0xf3ebf3cb18fb38f3ULL, 0x30c0309df060ad30ULL, 0xef9bef2b74c3c4efULL,
+       0x3ffc3fe5c37eda3fULL, 0x554955921caac755ULL, 0xa2b2a2791059dba2ULL,
+       0xea8fea0365c9e9eaULL, 0x6589650fecca6a65ULL, 0xbad2bab9686903baULL,
+       0x2fbc2f65935e4a2fULL, 0xc027c04ee79d8ec0ULL, 0xde5fdebe81a160deULL,
+       0x1c701ce06c38fc1cULL, 0xfdd3fdbb2ee746fdULL, 0x4d294d52649a1f4dULL,
+       0x927292e4e0397692ULL, 0x75c9758fbceafa75ULL, 0x061806301e0c3606ULL,
+       0x8a128a249809ae8aULL, 0xb2f2b2f940794bb2ULL, 0xe6bfe66359d185e6ULL,
+       0x0e380e70361c7e0eULL, 0x1f7c1ff8633ee71fULL, 0x62956237f7c45562ULL,
+       0xd477d4eea3b53ad4ULL, 0xa89aa829324d81a8ULL, 0x966296c4f4315296ULL,
+       0xf9c3f99b3aef62f9ULL, 0xc533c566f697a3c5ULL, 0x25942535b14a1025ULL,
+       0x597959f220b2ab59ULL, 0x842a8454ae15d084ULL, 0x72d572b7a7e4c572ULL,
+       0x39e439d5dd72ec39ULL, 0x4c2d4c5a6198164cULL, 0x5e655eca3bbc945eULL,
+       0x78fd78e785f09f78ULL, 0x38e038ddd870e538ULL, 0x8c0a8c148605988cULL,
+       0xd163d1c6b2bf17d1ULL, 0xa5aea5410b57e4a5ULL, 0xe2afe2434dd9a1e2ULL,
+       0x6199612ff8c24e61ULL, 0xb3f6b3f1457b42b3ULL, 0x21842115a5423421ULL,
+       0x9c4a9c94d625089cULL, 0x1e781ef0663cee1eULL, 0x4311432252866143ULL,
+       0xc73bc776fc93b1c7ULL, 0xfcd7fcb32be54ffcULL, 0x0410042014082404ULL,
+       0x515951b208a2e351ULL, 0x995e99bcc72f2599ULL, 0x6da96d4fc4da226dULL,
+       0x0d340d68391a650dULL, 0xfacffa8335e979faULL, 0xdf5bdfb684a369dfULL,
+       0x7ee57ed79bfca97eULL, 0x2490243db4481924ULL, 0x3bec3bc5d776fe3bULL,
+       0xab96ab313d4b9aabULL, 0xce1fce3ed181f0ceULL, 0x1144118855229911ULL,
+       0x8f068f0c8903838fULL, 0x4e254e4a6b9c044eULL, 0xb7e6b7d1517366b7ULL,
+       0xeb8beb0b60cbe0ebULL, 0x3cf03cfdcc78c13cULL, 0x813e817cbf1ffd81ULL,
+       0x946a94d4fe354094ULL, 0xf7fbf7eb0cf31cf7ULL, 0xb9deb9a1676f18b9ULL,
+       0x134c13985f268b13ULL, 0x2cb02c7d9c58512cULL, 0xd36bd3d6b8bb05d3ULL,
+       0xe7bbe76b5cd38ce7ULL, 0x6ea56e57cbdc396eULL, 0xc437c46ef395aac4ULL,
+       0x030c03180f061b03ULL, 0x5645568a13acdc56ULL, 0x440d441a49885e44ULL,
+       0x7fe17fdf9efea07fULL, 0xa99ea921374f88a9ULL, 0x2aa82a4d8254672aULL,
+       0xbbd6bbb16d6b0abbULL, 0xc123c146e29f87c1ULL, 0x535153a202a6f153ULL,
+       0xdc57dcae8ba572dcULL, 0x0b2c0b582716530bULL, 0x9d4e9d9cd327019dULL,
+       0x6cad6c47c1d82b6cULL, 0x31c43195f562a431ULL, 0x74cd7487b9e8f374ULL,
+       0xf6fff6e309f115f6ULL, 0x4605460a438c4c46ULL, 0xac8aac092645a5acULL,
+       0x891e893c970fb589ULL, 0x145014a04428b414ULL, 0xe1a3e15b42dfbae1ULL,
+       0x165816b04e2ca616ULL, 0x3ae83acdd274f73aULL, 0x69b9696fd0d20669ULL,
+       0x092409482d124109ULL, 0x70dd70a7ade0d770ULL, 0xb6e2b6d954716fb6ULL,
+       0xd067d0ceb7bd1ed0ULL, 0xed93ed3b7ec7d6edULL, 0xcc17cc2edb85e2ccULL,
+       0x4215422a57846842ULL, 0x985a98b4c22d2c98ULL, 0xa4aaa4490e55eda4ULL,
+       0x28a0285d88507528ULL, 0x5c6d5cda31b8865cULL, 0xf8c7f8933fed6bf8ULL,
+       0x86228644a411c286ULL,
+};
+
+static const u64 rc[WHIRLPOOL_ROUNDS + 1] = {
+       0x0000000000000000ULL, 0x1823c6e887b8014fULL, 0x36a6d2f5796f9152ULL,
+       0x60bc9b8ea30c7b35ULL, 0x1de0d7c22e4bfe57ULL, 0x157737e59ff04adaULL,
+       0x58c9290ab1a06b85ULL, 0xbd5d10f4cb3e0567ULL, 0xe427418ba77d95d8ULL,
+       0xfbee7c66dd17479eULL, 0xca2dbf07ad5a8333ULL,
+};
+
+/**
+ * The core Whirlpool transform.
+ */
+
+static void wp512_process_buffer(struct wp512_ctx *wctx) {
+       int i, r;
+       u64 K[8];        /* the round key */
+       u64 block[8];    /* mu(buffer) */
+       u64 state[8];    /* the cipher state */
+       u64 L[8];
+       u8 *buffer = wctx->buffer;
+
+       for (i = 0; i < 8; i++, buffer += 8) {
+               block[i] =
+               (((u64)buffer[0]        ) << 56) ^
+               (((u64)buffer[1] & 0xffL) << 48) ^
+               (((u64)buffer[2] & 0xffL) << 40) ^
+               (((u64)buffer[3] & 0xffL) << 32) ^
+               (((u64)buffer[4] & 0xffL) << 24) ^
+               (((u64)buffer[5] & 0xffL) << 16) ^
+               (((u64)buffer[6] & 0xffL) <<  8) ^
+               (((u64)buffer[7] & 0xffL)      );
+       }
+
+       state[0] = block[0] ^ (K[0] = wctx->hash[0]);
+       state[1] = block[1] ^ (K[1] = wctx->hash[1]);
+       state[2] = block[2] ^ (K[2] = wctx->hash[2]);
+       state[3] = block[3] ^ (K[3] = wctx->hash[3]);
+       state[4] = block[4] ^ (K[4] = wctx->hash[4]);
+       state[5] = block[5] ^ (K[5] = wctx->hash[5]);
+       state[6] = block[6] ^ (K[6] = wctx->hash[6]);
+       state[7] = block[7] ^ (K[7] = wctx->hash[7]);
+
+       for (r = 1; r <= WHIRLPOOL_ROUNDS; r++) {
+
+               L[0] = C0[(int)(K[0] >> 56)       ] ^
+                          C1[(int)(K[7] >> 48) & 0xff] ^
+                          C2[(int)(K[6] >> 40) & 0xff] ^
+                          C3[(int)(K[5] >> 32) & 0xff] ^
+                          C4[(int)(K[4] >> 24) & 0xff] ^
+                          C5[(int)(K[3] >> 16) & 0xff] ^
+                          C6[(int)(K[2] >>  8) & 0xff] ^
+                          C7[(int)(K[1]      ) & 0xff] ^
+                          rc[r];
+
+               L[1] = C0[(int)(K[1] >> 56)       ] ^
+                          C1[(int)(K[0] >> 48) & 0xff] ^
+                          C2[(int)(K[7] >> 40) & 0xff] ^
+                          C3[(int)(K[6] >> 32) & 0xff] ^
+                          C4[(int)(K[5] >> 24) & 0xff] ^
+                          C5[(int)(K[4] >> 16) & 0xff] ^
+                          C6[(int)(K[3] >>  8) & 0xff] ^
+                          C7[(int)(K[2]      ) & 0xff];
+
+               L[2] = C0[(int)(K[2] >> 56)       ] ^
+                          C1[(int)(K[1] >> 48) & 0xff] ^
+                          C2[(int)(K[0] >> 40) & 0xff] ^
+                          C3[(int)(K[7] >> 32) & 0xff] ^
+                          C4[(int)(K[6] >> 24) & 0xff] ^
+                          C5[(int)(K[5] >> 16) & 0xff] ^
+                          C6[(int)(K[4] >>  8) & 0xff] ^
+                          C7[(int)(K[3]      ) & 0xff];
+
+               L[3] = C0[(int)(K[3] >> 56)       ] ^
+                          C1[(int)(K[2] >> 48) & 0xff] ^
+                          C2[(int)(K[1] >> 40) & 0xff] ^
+                          C3[(int)(K[0] >> 32) & 0xff] ^
+                          C4[(int)(K[7] >> 24) & 0xff] ^
+                          C5[(int)(K[6] >> 16) & 0xff] ^
+                          C6[(int)(K[5] >>  8) & 0xff] ^
+                          C7[(int)(K[4]      ) & 0xff];
+
+               L[4] = C0[(int)(K[4] >> 56)       ] ^
+                          C1[(int)(K[3] >> 48) & 0xff] ^
+                          C2[(int)(K[2] >> 40) & 0xff] ^
+                          C3[(int)(K[1] >> 32) & 0xff] ^
+                          C4[(int)(K[0] >> 24) & 0xff] ^
+                          C5[(int)(K[7] >> 16) & 0xff] ^
+                          C6[(int)(K[6] >>  8) & 0xff] ^
+                          C7[(int)(K[5]      ) & 0xff];
+
+               L[5] = C0[(int)(K[5] >> 56)       ] ^
+                          C1[(int)(K[4] >> 48) & 0xff] ^
+                          C2[(int)(K[3] >> 40) & 0xff] ^
+                          C3[(int)(K[2] >> 32) & 0xff] ^
+                          C4[(int)(K[1] >> 24) & 0xff] ^
+                          C5[(int)(K[0] >> 16) & 0xff] ^
+                          C6[(int)(K[7] >>  8) & 0xff] ^
+                          C7[(int)(K[6]      ) & 0xff];
+
+               L[6] = C0[(int)(K[6] >> 56)       ] ^
+                          C1[(int)(K[5] >> 48) & 0xff] ^
+                          C2[(int)(K[4] >> 40) & 0xff] ^
+                          C3[(int)(K[3] >> 32) & 0xff] ^
+                          C4[(int)(K[2] >> 24) & 0xff] ^
+                          C5[(int)(K[1] >> 16) & 0xff] ^
+                          C6[(int)(K[0] >>  8) & 0xff] ^
+                          C7[(int)(K[7]      ) & 0xff];
+
+               L[7] = C0[(int)(K[7] >> 56)       ] ^
+                          C1[(int)(K[6] >> 48) & 0xff] ^
+                          C2[(int)(K[5] >> 40) & 0xff] ^
+                          C3[(int)(K[4] >> 32) & 0xff] ^
+                          C4[(int)(K[3] >> 24) & 0xff] ^
+                          C5[(int)(K[2] >> 16) & 0xff] ^
+                          C6[(int)(K[1] >>  8) & 0xff] ^
+                          C7[(int)(K[0]      ) & 0xff];
+
+               K[0] = L[0];
+               K[1] = L[1];
+               K[2] = L[2];
+               K[3] = L[3];
+               K[4] = L[4];
+               K[5] = L[5];
+               K[6] = L[6];
+               K[7] = L[7];
+
+               L[0] = C0[(int)(state[0] >> 56)       ] ^
+                          C1[(int)(state[7] >> 48) & 0xff] ^
+                          C2[(int)(state[6] >> 40) & 0xff] ^
+                          C3[(int)(state[5] >> 32) & 0xff] ^
+                          C4[(int)(state[4] >> 24) & 0xff] ^
+                          C5[(int)(state[3] >> 16) & 0xff] ^
+                          C6[(int)(state[2] >>  8) & 0xff] ^
+                          C7[(int)(state[1]      ) & 0xff] ^
+                          K[0];
+
+               L[1] = C0[(int)(state[1] >> 56)       ] ^
+                          C1[(int)(state[0] >> 48) & 0xff] ^
+                          C2[(int)(state[7] >> 40) & 0xff] ^
+                          C3[(int)(state[6] >> 32) & 0xff] ^
+                          C4[(int)(state[5] >> 24) & 0xff] ^
+                          C5[(int)(state[4] >> 16) & 0xff] ^
+                          C6[(int)(state[3] >>  8) & 0xff] ^
+                          C7[(int)(state[2]      ) & 0xff] ^
+                          K[1];
+
+               L[2] = C0[(int)(state[2] >> 56)       ] ^
+                          C1[(int)(state[1] >> 48) & 0xff] ^
+                          C2[(int)(state[0] >> 40) & 0xff] ^
+                          C3[(int)(state[7] >> 32) & 0xff] ^
+                          C4[(int)(state[6] >> 24) & 0xff] ^
+                          C5[(int)(state[5] >> 16) & 0xff] ^
+                          C6[(int)(state[4] >>  8) & 0xff] ^
+                          C7[(int)(state[3]      ) & 0xff] ^
+                          K[2];
+
+               L[3] = C0[(int)(state[3] >> 56)       ] ^
+                          C1[(int)(state[2] >> 48) & 0xff] ^
+                          C2[(int)(state[1] >> 40) & 0xff] ^
+                          C3[(int)(state[0] >> 32) & 0xff] ^
+                          C4[(int)(state[7] >> 24) & 0xff] ^
+                          C5[(int)(state[6] >> 16) & 0xff] ^
+                          C6[(int)(state[5] >>  8) & 0xff] ^
+                          C7[(int)(state[4]      ) & 0xff] ^
+                          K[3];
+
+               L[4] = C0[(int)(state[4] >> 56)       ] ^
+                          C1[(int)(state[3] >> 48) & 0xff] ^
+                          C2[(int)(state[2] >> 40) & 0xff] ^
+                          C3[(int)(state[1] >> 32) & 0xff] ^
+                          C4[(int)(state[0] >> 24) & 0xff] ^
+                          C5[(int)(state[7] >> 16) & 0xff] ^
+                          C6[(int)(state[6] >>  8) & 0xff] ^
+                          C7[(int)(state[5]      ) & 0xff] ^
+                          K[4];
+
+               L[5] = C0[(int)(state[5] >> 56)       ] ^
+                          C1[(int)(state[4] >> 48) & 0xff] ^
+                          C2[(int)(state[3] >> 40) & 0xff] ^
+                          C3[(int)(state[2] >> 32) & 0xff] ^
+                          C4[(int)(state[1] >> 24) & 0xff] ^
+                          C5[(int)(state[0] >> 16) & 0xff] ^
+                          C6[(int)(state[7] >>  8) & 0xff] ^
+                          C7[(int)(state[6]      ) & 0xff] ^
+                          K[5];
+
+               L[6] = C0[(int)(state[6] >> 56)       ] ^
+                          C1[(int)(state[5] >> 48) & 0xff] ^
+                          C2[(int)(state[4] >> 40) & 0xff] ^
+                          C3[(int)(state[3] >> 32) & 0xff] ^
+                          C4[(int)(state[2] >> 24) & 0xff] ^
+                          C5[(int)(state[1] >> 16) & 0xff] ^
+                          C6[(int)(state[0] >>  8) & 0xff] ^
+                          C7[(int)(state[7]      ) & 0xff] ^
+                          K[6];
+
+               L[7] = C0[(int)(state[7] >> 56)       ] ^
+                          C1[(int)(state[6] >> 48) & 0xff] ^
+                          C2[(int)(state[5] >> 40) & 0xff] ^
+                          C3[(int)(state[4] >> 32) & 0xff] ^
+                          C4[(int)(state[3] >> 24) & 0xff] ^
+                          C5[(int)(state[2] >> 16) & 0xff] ^
+                          C6[(int)(state[1] >>  8) & 0xff] ^
+                          C7[(int)(state[0]      ) & 0xff] ^
+                          K[7];
+
+               state[0] = L[0];
+               state[1] = L[1];
+               state[2] = L[2];
+               state[3] = L[3];
+               state[4] = L[4];
+               state[5] = L[5];
+               state[6] = L[6];
+               state[7] = L[7];
+       }
+       /*
+       * apply the Miyaguchi-Preneel compression function:
+       */
+       wctx->hash[0] ^= state[0] ^ block[0];
+       wctx->hash[1] ^= state[1] ^ block[1];
+       wctx->hash[2] ^= state[2] ^ block[2];
+       wctx->hash[3] ^= state[3] ^ block[3];
+       wctx->hash[4] ^= state[4] ^ block[4];
+       wctx->hash[5] ^= state[5] ^ block[5];
+       wctx->hash[6] ^= state[6] ^ block[6];
+       wctx->hash[7] ^= state[7] ^ block[7];
+
+}
+
+static void wp512_init (void *ctx) {
+       int i;
+       struct wp512_ctx *wctx = ctx;
+
+       memset(wctx->bitLength, 0, 32);
+       wctx->bufferBits = wctx->bufferPos = 0;
+       wctx->buffer[0] = 0;
+       for (i = 0; i < 8; i++) {
+               wctx->hash[i] = 0L;
+       }
+}
+
+static void wp512_update(void *ctx, const u8 *source, unsigned int len)
+{
+
+       struct wp512_ctx *wctx = ctx;
+       int sourcePos    = 0;
+       unsigned int bits_len = len * 8; // convert to number of bits
+       int sourceGap    = (8 - ((int)bits_len & 7)) & 7;
+       int bufferRem    = wctx->bufferBits & 7;
+       int i;
+       u32 b, carry;
+       u8 *buffer       = wctx->buffer;
+       u8 *bitLength    = wctx->bitLength;
+       int bufferBits   = wctx->bufferBits;
+       int bufferPos    = wctx->bufferPos;
+
+       u64 value = bits_len;
+       for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != 0ULL); i--) {
+               carry += bitLength[i] + ((u32)value & 0xff);
+               bitLength[i] = (u8)carry;
+               carry >>= 8;
+               value >>= 8;
+       }
+       while (bits_len > 8) {
+               b = ((source[sourcePos] << sourceGap) & 0xff) |
+               ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap));
+               buffer[bufferPos++] |= (u8)(b >> bufferRem);
+               bufferBits += 8 - bufferRem;
+               if (bufferBits == WP512_BLOCK_SIZE * 8) {
+                       wp512_process_buffer(wctx);
+                       bufferBits = bufferPos = 0;
+               }
+               buffer[bufferPos] = b << (8 - bufferRem);
+               bufferBits += bufferRem;
+               bits_len -= 8;
+               sourcePos++;
+       }
+       if (bits_len > 0) {
+               b = (source[sourcePos] << sourceGap) & 0xff;
+               buffer[bufferPos] |= b >> bufferRem;
+       } else {
+               b = 0;
+       }
+       if (bufferRem + bits_len < 8) {
+               bufferBits += bits_len;
+       } else {
+               bufferPos++;
+               bufferBits += 8 - bufferRem;
+               bits_len -= 8 - bufferRem;
+               if (bufferBits == WP512_BLOCK_SIZE * 8) {
+                       wp512_process_buffer(wctx);
+                       bufferBits = bufferPos = 0;
+               }
+               buffer[bufferPos] = b << (8 - bufferRem);
+               bufferBits += (int)bits_len;
+       }
+
+       wctx->bufferBits   = bufferBits;
+       wctx->bufferPos    = bufferPos;
+
+}
+
+static void wp512_final(void *ctx, u8 *out)
+{
+       struct wp512_ctx *wctx = ctx;
+       int i;
+       u8 *buffer      = wctx->buffer;
+       u8 *bitLength   = wctx->bitLength;
+       int bufferBits  = wctx->bufferBits;
+       int bufferPos   = wctx->bufferPos;
+       u8 *digest      = out;
+
+       buffer[bufferPos] |= 0x80U >> (bufferBits & 7);
+       bufferPos++;
+       if (bufferPos > WP512_BLOCK_SIZE - WP512_LENGTHBYTES) {
+               if (bufferPos < WP512_BLOCK_SIZE) {
+               memset(&buffer[bufferPos], 0, WP512_BLOCK_SIZE - bufferPos);
+               }
+               wp512_process_buffer(wctx);
+               bufferPos = 0;
+       }
+       if (bufferPos < WP512_BLOCK_SIZE - WP512_LENGTHBYTES) {
+               memset(&buffer[bufferPos], 0,
+                         (WP512_BLOCK_SIZE - WP512_LENGTHBYTES) - bufferPos);
+       }
+       bufferPos = WP512_BLOCK_SIZE - WP512_LENGTHBYTES;
+       memcpy(&buffer[WP512_BLOCK_SIZE - WP512_LENGTHBYTES],
+                  bitLength, WP512_LENGTHBYTES);
+       wp512_process_buffer(wctx);
+       for (i = 0; i < WP512_DIGEST_SIZE/8; i++) {
+               digest[0] = (u8)(wctx->hash[i] >> 56);
+               digest[1] = (u8)(wctx->hash[i] >> 48);
+               digest[2] = (u8)(wctx->hash[i] >> 40);
+               digest[3] = (u8)(wctx->hash[i] >> 32);
+               digest[4] = (u8)(wctx->hash[i] >> 24);
+               digest[5] = (u8)(wctx->hash[i] >> 16);
+               digest[6] = (u8)(wctx->hash[i] >>  8);
+               digest[7] = (u8)(wctx->hash[i]      );
+               digest += 8;
+       }
+       wctx->bufferBits   = bufferBits;
+       wctx->bufferPos    = bufferPos;
+}
+
+static void wp384_final(void *ctx, u8 *out)
+{
+       struct wp512_ctx *wctx = ctx;
+       u8 D[64];
+
+       wp512_final (wctx, D);
+       memcpy (out, D, WP384_DIGEST_SIZE);
+       memset (D, 0, WP512_DIGEST_SIZE);
+}
+
+static void wp256_final(void *ctx, u8 *out)
+{
+       struct wp512_ctx *wctx = ctx;
+       u8 D[64];
+
+       wp512_final (wctx, D);
+       memcpy (out, D, WP256_DIGEST_SIZE);
+       memset (D, 0, WP512_DIGEST_SIZE);
+}
+
+static struct crypto_alg wp512 = {
+       .cra_name       =       "wp512",
+       .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
+       .cra_blocksize  =       WP512_BLOCK_SIZE,
+       .cra_ctxsize    =       sizeof(struct wp512_ctx),
+       .cra_module     =       THIS_MODULE,
+       .cra_list       =       LIST_HEAD_INIT(wp512.cra_list), 
+       .cra_u          =       { .digest = {
+       .dia_digestsize =       WP512_DIGEST_SIZE,
+       .dia_init       =       wp512_init,
+       .dia_update     =       wp512_update,
+       .dia_final      =       wp512_final } }
+};
+
+static struct crypto_alg wp384 = {
+       .cra_name       =       "wp384",
+       .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
+       .cra_blocksize  =       WP512_BLOCK_SIZE,
+       .cra_ctxsize    =       sizeof(struct wp512_ctx),
+       .cra_module     =       THIS_MODULE,
+       .cra_list       =       LIST_HEAD_INIT(wp384.cra_list), 
+       .cra_u          =       { .digest = {
+       .dia_digestsize =       WP384_DIGEST_SIZE,
+       .dia_init       =       wp512_init,
+       .dia_update     =       wp512_update,
+       .dia_final      =       wp384_final } }
+};
+
+static struct crypto_alg wp256 = {
+       .cra_name       =       "wp256",
+       .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
+       .cra_blocksize  =       WP512_BLOCK_SIZE,
+       .cra_ctxsize    =       sizeof(struct wp512_ctx),
+       .cra_module     =       THIS_MODULE,
+       .cra_list       =       LIST_HEAD_INIT(wp256.cra_list), 
+       .cra_u          =       { .digest = {
+       .dia_digestsize =       WP256_DIGEST_SIZE,
+       .dia_init       =       wp512_init,
+       .dia_update     =       wp512_update,
+       .dia_final      =       wp256_final } }
+};
+
+static int __init init(void)
+{
+       int ret = 0;
+
+       ret = crypto_register_alg(&wp512);
+
+       if (ret < 0)
+               goto out;
+
+       ret = crypto_register_alg(&wp384);
+       if (ret < 0)
+       {
+               crypto_unregister_alg(&wp512);
+               goto out;
+       }
+
+       ret = crypto_register_alg(&wp256);
+       if (ret < 0)
+       {
+               crypto_unregister_alg(&wp512);
+               crypto_unregister_alg(&wp384);
+       }
+out:
+       return ret;
+}
+
+static void __exit fini(void)
+{
+       crypto_unregister_alg(&wp512);
+       crypto_unregister_alg(&wp384);
+       crypto_unregister_alg(&wp256);
+}
+
+MODULE_ALIAS("wp384");
+MODULE_ALIAS("wp256");
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Whirlpool Message Digest Algorithm");
index beb93c6..bcc35ca 100644 (file)
@@ -47,4 +47,4 @@ obj-$(CONFIG_ACPI_DEBUG)      += debug.o
 obj-$(CONFIG_ACPI_NUMA)                += numa.o
 obj-$(CONFIG_ACPI_ASUS)                += asus_acpi.o
 obj-$(CONFIG_ACPI_TOSHIBA)     += toshiba_acpi.o
-obj-$(CONFIG_ACPI_BUS)         += scan.o 
+obj-$(CONFIG_ACPI_BUS)         += scan.o motherboard.o
index 9cf61ba..4c010e7 100644 (file)
@@ -2,7 +2,9 @@
  *  blacklist.c
  *
  *  Check to see if the given machine has a known bad ACPI BIOS
+ *  or if the BIOS is too old.
  *
+ *  Copyright (C) 2004 Len Brown <len.brown@intel.com>
  *  Copyright (C) 2002 Andy Grover <andrew.grover@intel.com>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -30,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
+#include <linux/dmi.h>
 
 enum acpi_blacklist_predicates
 {
@@ -56,20 +59,6 @@ struct acpi_blacklist_item
  */
 static struct acpi_blacklist_item acpi_blacklist[] __initdata =
 {
-       /* Portege 7020, BIOS 8.10 */
-       {"TOSHIB", "7020CT  ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0},
-       /* Portege 4030 */
-       {"TOSHIB", "4030    ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0},
-       /* Portege 310/320, BIOS 7.1 */
-       {"TOSHIB", "310     ", 0x19990511, ACPI_DSDT, all_versions, "Implicit Return", 0},
-       /* Seattle 2, old bios rev. */
-       {"INTEL ", "440BX   ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
-       /* ASUS K7M */
-       {"ASUS  ", "K7M     ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
-       /* Intel 810 Motherboard? */
-       {"MNTRAL", "MO81010A", 0x00000012, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
-       /* Compaq Presario 711FR */
-       {"COMAPQ", "EAGLES", 0x06040000, ACPI_DSDT, less_than_or_equal, "SCI issues (C2 disabled)", 0},
        /* Compaq Presario 1700 */
        {"PTLTD ", "  DSDT  ", 0x06040000, ACPI_DSDT, less_than_or_equal, "Multiple problems", 1},
        /* Sony FX120, FX140, FX150? */
@@ -84,6 +73,45 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata =
 };
 
 
+#if    CONFIG_ACPI_BLACKLIST_YEAR
+
+static int __init
+blacklist_by_year(void)
+{
+       int year;
+       char *s = dmi_get_system_info(DMI_BIOS_DATE);
+
+       if (!s)
+               return 0;
+       if (!*s)
+               return 0;
+
+       s = strrchr(s, '/');
+       if (!s)
+               return 0;
+
+       s += 1;
+
+       year = simple_strtoul(s,NULL,0); 
+
+       if (year < 100) {               /* 2-digit year */
+               year += 1900;
+               if (year < 1996)        /* no dates < spec 1.0 */
+                       year += 100;
+       }
+
+       if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
+               printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), " 
+                       "acpi=force is required to enable ACPI\n",
+                       year, CONFIG_ACPI_BLACKLIST_YEAR);
+               return 1;
+       }
+       return 0;
+}
+#else
+static inline int blacklist_by_year(void) { return 0; }
+#endif
+
 int __init
 acpi_blacklisted(void)
 {
@@ -134,6 +162,8 @@ acpi_blacklisted(void)
                }
        }
 
+       blacklisted += blacklist_by_year();
+
        return blacklisted;
 }
 
index 360fbe5..4fd3690 100644 (file)
  *
  * FUNCTION:    acpi_ds_parse_method
  *
- * PARAMETERS:  obj_handle      - Node of the method
- *              Level           - Current nesting level
- *              Context         - Points to a method counter
- *              return_value    - Not used
+ * PARAMETERS:  obj_handle      - Method node
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Call the parser and parse the AML that is
- *              associated with the method.
+ * DESCRIPTION: Call the parser and parse the AML that is associated with the
+ *              method.
  *
  * MUTEX:       Assumes parser is locked
  *
@@ -145,8 +142,9 @@ acpi_ds_parse_method (
                return_ACPI_STATUS (AE_NO_MEMORY);
        }
 
-       status = acpi_ds_init_aml_walk (walk_state, op, node, obj_desc->method.aml_start,
-                         obj_desc->method.aml_length, NULL, NULL, 1);
+       status = acpi_ds_init_aml_walk (walk_state, op, node,
+                         obj_desc->method.aml_start,
+                         obj_desc->method.aml_length, NULL, 1);
        if (ACPI_FAILURE (status)) {
                acpi_ds_delete_walk_state (walk_state);
                return_ACPI_STATUS (status);
@@ -190,8 +188,6 @@ acpi_ds_parse_method (
  *              increments the thread count, and waits at the method semaphore
  *              for clearance to execute.
  *
- * MUTEX:       Locks/unlocks parser.
- *
  ******************************************************************************/
 
 acpi_status
@@ -250,7 +246,8 @@ acpi_ds_begin_method_execution (
  *
  * FUNCTION:    acpi_ds_call_control_method
  *
- * PARAMETERS:  walk_state          - Current state of the walk
+ * PARAMETERS:  Thread              - Info for this thread
+ *              this_walk_state     - Current walk state
  *              Op                  - Current Op to be walked
  *
  * RETURN:      Status
@@ -267,8 +264,9 @@ acpi_ds_call_control_method (
 {
        acpi_status                     status;
        struct acpi_namespace_node      *method_node;
-       union acpi_operand_object       *obj_desc;
        struct acpi_walk_state          *next_walk_state;
+       union acpi_operand_object       *obj_desc;
+       struct acpi_parameter_info      info;
        u32                             i;
 
 
@@ -309,7 +307,6 @@ acpi_ds_call_control_method (
                        return_ACPI_STATUS (AE_NO_MEMORY);
                }
 
-
                /* Create and init a Root Node */
 
                op = acpi_ps_create_scope_op ();
@@ -320,7 +317,7 @@ acpi_ds_call_control_method (
 
                status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
                                  obj_desc->method.aml_start, obj_desc->method.aml_length,
-                                 NULL, NULL, 1);
+                                 NULL, 1);
                if (ACPI_FAILURE (status)) {
                        acpi_ds_delete_walk_state (next_walk_state);
                        goto cleanup;
@@ -348,9 +345,12 @@ acpi_ds_call_control_method (
         */
        this_walk_state->operands [this_walk_state->num_operands] = NULL;
 
+       info.parameters = &this_walk_state->operands[0];
+       info.parameter_type = ACPI_PARAM_ARGS;
+
        status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node,
                          obj_desc->method.aml_start, obj_desc->method.aml_length,
-                         &this_walk_state->operands[0], NULL, 3);
+                         &info, 3);
        if (ACPI_FAILURE (status)) {
                goto cleanup;
        }
@@ -382,7 +382,7 @@ acpi_ds_call_control_method (
        /* On error, we must delete the new walk state */
 
 cleanup:
-       if (next_walk_state->method_desc) {
+       if (next_walk_state && (next_walk_state->method_desc)) {
                /* Decrement the thread count on the method parse tree */
 
           next_walk_state->method_desc->method.thread_count--;
@@ -397,12 +397,13 @@ cleanup:
  *
  * FUNCTION:    acpi_ds_restart_control_method
  *
- * PARAMETERS:  walk_state          - State of the method when it was preempted
- *              Op                  - Pointer to new current op
+ * PARAMETERS:  walk_state          - State for preempted method (caller)
+ *              return_desc         - Return value from the called method
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Restart a method that was preempted
+ * DESCRIPTION: Restart a method that was preempted by another (nested) method
+ *              invocation.  Handle the return value (if any) from the callee.
  *
  ******************************************************************************/
 
@@ -417,17 +418,35 @@ acpi_ds_restart_control_method (
        ACPI_FUNCTION_TRACE_PTR ("ds_restart_control_method", walk_state);
 
 
+       ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+               "****Restart [%4.4s] Op %p return_value_from_callee %p\n",
+               (char *) &walk_state->method_node->name, walk_state->method_call_op,
+               return_desc));
+
+       ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+               "    return_from_this_method_used?=%X res_stack %p Walk %p\n",
+               walk_state->return_used,
+               walk_state->results, walk_state));
+
+       /* Did the called method return a value? */
+
        if (return_desc) {
+               /* Are we actually going to use the return value? */
+
                if (walk_state->return_used) {
-                       /*
-                        * Get the return value (if any) from the previous method.
-                        * NULL if no return value
-                        */
+                       /* Save the return value from the previous method */
+
                        status = acpi_ds_result_push (return_desc, walk_state);
                        if (ACPI_FAILURE (status)) {
                                acpi_ut_remove_reference (return_desc);
                                return_ACPI_STATUS (status);
                        }
+
+                       /*
+                        * Save as THIS method's return value in case it is returned
+                        * immediately to yet another method
+                        */
+                       walk_state->return_desc = return_desc;
                }
                else {
                        /*
@@ -438,11 +457,6 @@ acpi_ds_restart_control_method (
                }
        }
 
-       ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
-               "Method=%p Return=%p return_used?=%X res_stack=%p State=%p\n",
-               walk_state->method_call_op, return_desc, walk_state->return_used,
-               walk_state->results, walk_state));
-
        return_ACPI_STATUS (AE_OK);
 }
 
index e192653..befe750 100644 (file)
@@ -656,11 +656,13 @@ acpi_ds_store_object_to_local (
                                                new_obj_desc, current_obj_desc));
 
                                /*
-                                * Store this object to the Node
-                                * (perform the indirect store)
+                                * Store this object to the Node (perform the indirect store)
+                                * NOTE: No implicit conversion is performed, as per the ACPI
+                                * specification rules on storing to Locals/Args.
                                 */
                                status = acpi_ex_store_object_to_node (new_obj_desc,
-                                                current_obj_desc->reference.object, walk_state);
+                                                current_obj_desc->reference.object, walk_state,
+                                                ACPI_NO_IMPLICIT_CONVERSION);
 
                                /* Remove local reference if we copied the object above */
 
index 5c6a37e..2446278 100644 (file)
  *
  * FUNCTION:    acpi_ds_is_result_used
  *
- * PARAMETERS:  Op
- *              result_obj
- *              walk_state
+ * PARAMETERS:  Op                  - Current Op
+ *              walk_state          - Current State
  *
- * RETURN:      Status
+ * RETURN:      TRUE if result is used, FALSE otherwise
  *
  * DESCRIPTION: Check if a result object will be used by the parent
  *
@@ -89,18 +88,39 @@ acpi_ds_is_result_used (
        }
 
        /*
-        * If there is no parent, the result can't possibly be used!
-        * (An executing method typically has no parent, since each
-        * method is parsed separately)  However, a method that is
-        * invoked from another method has a parent.
+        * If there is no parent, we are executing at the method level.
+        * An executing method typically has no parent, since each method
+        * is parsed separately.
         */
        if (!op->common.parent) {
+               /*
+                * If this is the last statement in the method, we know it is not a
+                * Return() operator (would not come here.) The following code is the
+                * optional support for a so-called "implicit return". Some AML code
+                * assumes that the last value of the method is "implicitly" returned
+                * to the caller. Just save the last result as the return value.
+                * NOTE: this is optional because the ASL language does not actually
+                * support this behavior.
+                */
+               if ((acpi_gbl_enable_interpreter_slack) &&
+                       (walk_state->parser_state.aml >= walk_state->parser_state.aml_end)) {
+                       ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+                                       "Result of [%s] will be implicitly returned\n",
+                                       acpi_ps_get_opcode_name (op->common.aml_opcode)));
+
+                       /* Use the top of the result stack as the implicit return value */
+
+                       walk_state->return_desc = walk_state->results->results.obj_desc[0];
+                       return_VALUE (TRUE);
+               }
+
+               /* No parent, the return value cannot possibly be used */
+
                return_VALUE (FALSE);
        }
 
-       /*
-        * Get info on the parent.  The root Op is AML_SCOPE
-        */
+       /* Get info on the parent. The root_op is AML_SCOPE */
+
        parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
        if (parent_info->class == AML_CLASS_UNKNOWN) {
                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown parent opcode. Op=%p\n", op));
@@ -204,9 +224,9 @@ result_not_used:
  *
  * FUNCTION:    acpi_ds_delete_result_if_not_used
  *
- * PARAMETERS:  Op
- *              result_obj
- *              walk_state
+ * PARAMETERS:  Op              - Current parse Op
+ *              result_obj      - Result of the operation
+ *              walk_state      - Current state
  *
  * RETURN:      Status
  *
@@ -338,8 +358,9 @@ acpi_ds_clear_operands (
  *
  * FUNCTION:    acpi_ds_create_operand
  *
- * PARAMETERS:  walk_state
- *              Arg
+ * PARAMETERS:  walk_state      - Current walk state
+ *              Arg             - Parse object for the argument
+ *              arg_index       - Which argument (zero based)
  *
  * RETURN:      Status
  *
index 409aa6e..9c0d99e 100644 (file)
@@ -50,6 +50,9 @@
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
 
+#ifdef _ACPI_ASL_COMPILER
+#include <acpi/acdisasm.h>
+#endif
 
 #define _COMPONENT          ACPI_DISPATCHER
         ACPI_MODULE_NAME    ("dswload")
@@ -180,7 +183,17 @@ acpi_ds_load1_begin_op (
                status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
                                  ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
                if (ACPI_FAILURE (status)) {
+#ifdef _ACPI_ASL_COMPILER
+                       if (status == AE_NOT_FOUND) {
+                               acpi_dm_add_to_external_list (path);
+                               status = AE_OK;
+                       }
+                       else {
+                               ACPI_REPORT_NSERROR (path, status);
+                       }
+#else
                        ACPI_REPORT_NSERROR (path, status);
+#endif
                        return (status);
                }
 
@@ -529,7 +542,16 @@ acpi_ds_load2_begin_op (
                status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
                                  ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
                if (ACPI_FAILURE (status)) {
+#ifdef _ACPI_ASL_COMPILER
+                       if (status == AE_NOT_FOUND) {
+                               status = AE_OK;
+                       }
+                       else {
+                               ACPI_REPORT_NSERROR (buffer_ptr, status);
+                       }
+#else
                        ACPI_REPORT_NSERROR (buffer_ptr, status);
+#endif
                        return_ACPI_STATUS (status);
                }
                /*
index 2b39562..81c6b46 100644 (file)
@@ -906,8 +906,7 @@ acpi_ds_init_aml_walk (
        struct acpi_namespace_node      *method_node,
        u8                              *aml_start,
        u32                             aml_length,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_obj_desc,
+       struct acpi_parameter_info      *info,
        u32                             pass_number)
 {
        acpi_status                     status;
@@ -926,8 +925,17 @@ acpi_ds_init_aml_walk (
        /* The next_op of the next_walk will be the beginning of the method */
 
        walk_state->next_op             = NULL;
-       walk_state->params              = params;
-       walk_state->caller_return_desc  = return_obj_desc;
+
+       if (info) {
+               if (info->parameter_type == ACPI_PARAM_GPE) {
+                       walk_state->gpe_event_info = ACPI_CAST_PTR (struct acpi_gpe_event_info,
+                                          info->parameters);
+               }
+               else {
+                       walk_state->params              = info->parameters;
+                       walk_state->caller_return_desc  = &info->return_object;
+               }
+       }
 
        status = acpi_ps_init_scope (&walk_state->parser_state, op);
        if (ACPI_FAILURE (status)) {
@@ -949,7 +957,7 @@ acpi_ds_init_aml_walk (
 
                /* Init the method arguments */
 
-               status = acpi_ds_method_data_init_args (params, ACPI_METHOD_NUM_ARGS, walk_state);
+               status = acpi_ds_method_data_init_args (walk_state->params, ACPI_METHOD_NUM_ARGS, walk_state);
                if (ACPI_FAILURE (status)) {
                        return_ACPI_STATUS (status);
                }
index abdb3a5..558ec7b 100644 (file)
@@ -50,7 +50,7 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_initialize
+ * FUNCTION:    acpi_ev_initialize_events
  *
  * PARAMETERS:  None
  *
  ******************************************************************************/
 
 acpi_status
-acpi_ev_initialize (
+acpi_ev_initialize_events (
        void)
 {
        acpi_status                     status;
 
 
-       ACPI_FUNCTION_TRACE ("ev_initialize");
+       ACPI_FUNCTION_TRACE ("ev_initialize_events");
 
 
        /* Make sure we have ACPI tables */
@@ -104,7 +104,7 @@ acpi_ev_initialize (
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_handler_initialize
+ * FUNCTION:    acpi_ev_install_xrupt_handlers
  *
  * PARAMETERS:  None
  *
@@ -115,13 +115,13 @@ acpi_ev_initialize (
  ******************************************************************************/
 
 acpi_status
-acpi_ev_handler_initialize (
+acpi_ev_install_xrupt_handlers (
        void)
 {
        acpi_status                     status;
 
 
-       ACPI_FUNCTION_TRACE ("ev_handler_initialize");
+       ACPI_FUNCTION_TRACE ("ev_install_xrupt_handlers");
 
 
        /* Install the SCI handler */
index 221dca5..afb3688 100644 (file)
         ACPI_MODULE_NAME    ("evgpe")
 
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_set_gpe_type
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to set
+ *              Type                    - New type
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_set_gpe_type (
+       struct acpi_gpe_event_info      *gpe_event_info,
+       u8                              type)
+{
+       acpi_status                     status;
+
+
+       ACPI_FUNCTION_TRACE ("ev_set_gpe_type");
+
+
+       /* Validate type and update register enable masks */
+
+       switch (type) {
+       case ACPI_GPE_TYPE_WAKE:
+       case ACPI_GPE_TYPE_RUNTIME:
+       case ACPI_GPE_TYPE_WAKE_RUN:
+               break;
+
+       default:
+               return_ACPI_STATUS (AE_BAD_PARAMETER);
+       }
+
+       /* Disable the GPE if currently enabled */
+
+       status = acpi_ev_disable_gpe (gpe_event_info);
+
+       /* Type was validated above */
+
+       gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
+       gpe_event_info->flags |= type;              /* Insert type */
+       return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_update_gpe_enable_masks
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to update
+ *              Type                    - What to do: ACPI_GPE_DISABLE or
+ *                                        ACPI_GPE_ENABLE
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Updates GPE register enable masks based on the GPE type
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_update_gpe_enable_masks (
+       struct acpi_gpe_event_info      *gpe_event_info,
+       u8                              type)
+{
+       struct acpi_gpe_register_info   *gpe_register_info;
+       u8                              register_bit;
+
+
+       ACPI_FUNCTION_TRACE ("ev_update_gpe_enable_masks");
+
+
+       gpe_register_info = gpe_event_info->register_info;
+       if (!gpe_register_info) {
+               return_ACPI_STATUS (AE_NOT_EXIST);
+       }
+       register_bit = gpe_event_info->register_bit;
+
+       /* 1) Disable case.  Simply clear all enable bits */
+
+       if (type == ACPI_GPE_DISABLE) {
+               ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
+               ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
+               return_ACPI_STATUS (AE_OK);
+       }
+
+       /* 2) Enable case.  Set/Clear the appropriate enable bits */
+
+       switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
+       case ACPI_GPE_TYPE_WAKE:
+               ACPI_SET_BIT   (gpe_register_info->enable_for_wake, register_bit);
+               ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
+               break;
+
+       case ACPI_GPE_TYPE_RUNTIME:
+               ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
+               ACPI_SET_BIT   (gpe_register_info->enable_for_run, register_bit);
+               break;
+
+       case ACPI_GPE_TYPE_WAKE_RUN:
+               ACPI_SET_BIT   (gpe_register_info->enable_for_wake, register_bit);
+               ACPI_SET_BIT   (gpe_register_info->enable_for_run, register_bit);
+               break;
+
+       default:
+               return_ACPI_STATUS (AE_BAD_PARAMETER);
+       }
+
+       return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_enable_gpe
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to enable
+ *              write_to_hardware       - Enable now, or just mark data structs
+ *                                        (WAKE GPEs should be deferred)
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Enable a GPE based on the GPE type
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_enable_gpe (
+       struct acpi_gpe_event_info      *gpe_event_info,
+       u8                              write_to_hardware)
+{
+       acpi_status                     status;
+
+
+       ACPI_FUNCTION_TRACE ("ev_enable_gpe");
+
+
+       /* Make sure HW enable masks are updated */
+
+       status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_ENABLE);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
+       }
+
+       /* Mark wake-enabled or HW enable, or both */
+
+       switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
+       case ACPI_GPE_TYPE_WAKE:
+
+               ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+               break;
+
+       case ACPI_GPE_TYPE_WAKE_RUN:
+
+               ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+
+               /*lint -fallthrough */
+
+       case ACPI_GPE_TYPE_RUNTIME:
+
+               ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
+
+               if (write_to_hardware) {
+                       /* Clear the GPE (of stale events), then enable it */
+
+                       status = acpi_hw_clear_gpe (gpe_event_info);
+                       if (ACPI_FAILURE (status)) {
+                               return_ACPI_STATUS (status);
+                       }
+
+                       /* Enable the requested runtime GPE */
+
+                       status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
+               }
+               break;
+
+       default:
+               return_ACPI_STATUS (AE_BAD_PARAMETER);
+       }
+
+       return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_disable_gpe
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to disable
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Disable a GPE based on the GPE type
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_disable_gpe (
+       struct acpi_gpe_event_info      *gpe_event_info)
+{
+       acpi_status                     status;
+
+
+       ACPI_FUNCTION_TRACE ("ev_disable_gpe");
+
+
+       if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
+               return_ACPI_STATUS (AE_OK);
+       }
+
+       /* Make sure HW enable masks are updated */
+
+       status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
+       }
+
+       /* Mark wake-disabled or HW disable, or both */
+
+       switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
+       case ACPI_GPE_TYPE_WAKE:
+               ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+               break;
+
+       case ACPI_GPE_TYPE_WAKE_RUN:
+               ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+
+               /*lint -fallthrough */
+
+       case ACPI_GPE_TYPE_RUNTIME:
+
+               /* Disable the requested runtime GPE */
+
+               ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
+               status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
+               break;
+
+       default:
+               return_ACPI_STATUS (AE_BAD_PARAMETER);
+       }
+
+       return_ACPI_STATUS (AE_OK);
+}
+
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_get_gpe_event_info
@@ -139,11 +386,12 @@ acpi_ev_gpe_detect (
        u32                             int_status = ACPI_INTERRUPT_NOT_HANDLED;
        u8                              enabled_status_byte;
        struct acpi_gpe_register_info   *gpe_register_info;
-       u32                             in_value;
+       u32                             status_reg;
+       u32                             enable_reg;
        acpi_status                     status;
        struct acpi_gpe_block_info      *gpe_block;
-       u32                             i;
-       u32                             j;
+       acpi_native_uint                i;
+       acpi_native_uint                j;
 
 
        ACPI_FUNCTION_NAME ("ev_gpe_detect");
@@ -171,33 +419,32 @@ acpi_ev_gpe_detect (
 
                        /* Read the Status Register */
 
-                       status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
+                       status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &status_reg,
                                         &gpe_register_info->status_address);
-                       gpe_register_info->status = (u8) in_value;
                        if (ACPI_FAILURE (status)) {
                                goto unlock_and_exit;
                        }
 
                        /* Read the Enable Register */
 
-                       status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
+                       status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &enable_reg,
                                         &gpe_register_info->enable_address);
-                       gpe_register_info->enable = (u8) in_value;
                        if (ACPI_FAILURE (status)) {
                                goto unlock_and_exit;
                        }
 
                        ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
                                "GPE pair: Status %8.8X%8.8X = %02X, Enable %8.8X%8.8X = %02X\n",
-                               ACPI_FORMAT_UINT64 (gpe_register_info->status_address.address),
-                               gpe_register_info->status,
-                               ACPI_FORMAT_UINT64 (gpe_register_info->enable_address.address),
-                               gpe_register_info->enable));
+                               ACPI_FORMAT_UINT64 (
+                                       gpe_register_info->status_address.address),
+                                       status_reg,
+                               ACPI_FORMAT_UINT64 (
+                                       gpe_register_info->enable_address.address),
+                                       enable_reg));
 
                        /* First check if there is anything active at all in this register */
 
-                       enabled_status_byte = (u8) (gpe_register_info->status &
-                                          gpe_register_info->enable);
+                       enabled_status_byte = (u8) (status_reg & enable_reg);
                        if (!enabled_status_byte) {
                                /* No active GPEs in this register, move on */
 
@@ -216,7 +463,7 @@ acpi_ev_gpe_detect (
                                         */
                                        int_status |= acpi_ev_gpe_dispatch (
                                                          &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j],
-                                                         j + gpe_register_info->base_gpe_number);
+                                                         (u32) j + gpe_register_info->base_gpe_number);
                                }
                        }
                }
@@ -255,6 +502,7 @@ acpi_ev_asynch_execute_gpe_method (
        u32                             gpe_number = 0;
        acpi_status                     status;
        struct acpi_gpe_event_info      local_gpe_event_info;
+       struct acpi_parameter_info      info;
 
 
        ACPI_FUNCTION_TRACE ("ev_asynch_execute_gpe_method");
@@ -272,6 +520,10 @@ acpi_ev_asynch_execute_gpe_method (
                return_VOID;
        }
 
+       /* Set the GPE flags for return to enabled state */
+
+       (void) acpi_ev_enable_gpe (gpe_event_info, FALSE);
+
        /*
         * Take a snapshot of the GPE info for this level - we copy the
         * info to prevent a race condition with remove_handler/remove_block.
@@ -283,23 +535,33 @@ acpi_ev_asynch_execute_gpe_method (
                return_VOID;
        }
 
-       if (local_gpe_event_info.method_node) {
+       /*
+        * Must check for control method type dispatch one more
+        * time to avoid race with ev_gpe_install_handler
+        */
+       if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) {
                /*
-                * Invoke the GPE Method (_Lxx, _Exx):
-                * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.)
+                * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
+                * control method that corresponds to this GPE
                 */
-               status = acpi_ns_evaluate_by_handle (local_gpe_event_info.method_node, NULL, NULL);
+               info.node = local_gpe_event_info.dispatch.method_node;
+               info.parameters = ACPI_CAST_PTR (union acpi_operand_object *, gpe_event_info);
+               info.parameter_type = ACPI_PARAM_GPE;
+
+               status = acpi_ns_evaluate_by_handle (&info);
                if (ACPI_FAILURE (status)) {
-                       ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2X]\n",
+                       ACPI_REPORT_ERROR ((
+                               "%s while evaluating method [%4.4s] for GPE[%2X]\n",
                                acpi_format_exception (status),
-                               acpi_ut_get_node_name (local_gpe_event_info.method_node), gpe_number));
+                               acpi_ut_get_node_name (local_gpe_event_info.dispatch.method_node),
+                               gpe_number));
                }
        }
 
        if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
                /*
-                * GPE is level-triggered, we clear the GPE status bit after handling
-                * the event.
+                * GPE is level-triggered, we clear the GPE status bit after
+                * handling the event.
                 */
                status = acpi_hw_clear_gpe (&local_gpe_event_info);
                if (ACPI_FAILURE (status)) {
@@ -309,7 +571,7 @@ acpi_ev_asynch_execute_gpe_method (
 
        /* Enable this GPE */
 
-       (void) acpi_hw_enable_gpe (&local_gpe_event_info);
+       (void) acpi_hw_write_gpe_enable_reg (&local_gpe_event_info);
        return_VOID;
 }
 
@@ -354,6 +616,15 @@ acpi_ev_gpe_dispatch (
                }
        }
 
+       /* Save current system state */
+
+       if (acpi_gbl_system_awake_and_running) {
+               ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
+       }
+       else {
+               ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
+       }
+
        /*
         * Dispatch the GPE to either an installed handler, or the control
         * method associated with this GPE (_Lxx or _Exx).
@@ -361,10 +632,15 @@ acpi_ev_gpe_dispatch (
         * If there is neither a handler nor a method, we disable the level to
         * prevent further events from coming in here.
         */
-       if (gpe_event_info->handler) {
-               /* Invoke the installed handler (at interrupt level) */
+       switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
+       case ACPI_GPE_DISPATCH_HANDLER:
 
-               gpe_event_info->handler (gpe_event_info->context);
+               /*
+                * Invoke the installed handler (at interrupt level)
+                * Ignore return status for now.  TBD: leave GPE disabled on error?
+                */
+               (void) gpe_event_info->dispatch.handler->address (
+                                 gpe_event_info->dispatch.handler->context);
 
                /* It is now safe to clear level-triggered events. */
 
@@ -377,13 +653,15 @@ acpi_ev_gpe_dispatch (
                                return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
                        }
                }
-       }
-       else if (gpe_event_info->method_node) {
+               break;
+
+       case ACPI_GPE_DISPATCH_METHOD:
+
                /*
                 * Disable GPE, so it doesn't keep firing before the method has a
                 * chance to run.
                 */
-               status = acpi_hw_disable_gpe (gpe_event_info);
+               status = acpi_ev_disable_gpe (gpe_event_info);
                if (ACPI_FAILURE (status)) {
                        ACPI_REPORT_ERROR ((
                                "acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
@@ -402,8 +680,10 @@ acpi_ev_gpe_dispatch (
                                "acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2X], event is disabled\n",
                                gpe_number));
                }
-       }
-       else {
+               break;
+
+       default:
+
                /* No handler or method to run! */
 
                ACPI_REPORT_ERROR ((
@@ -414,15 +694,68 @@ acpi_ev_gpe_dispatch (
                 * Disable the GPE.  The GPE will remain disabled until the ACPI
                 * Core Subsystem is restarted, or a handler is installed.
                 */
-               status = acpi_hw_disable_gpe (gpe_event_info);
+               status = acpi_ev_disable_gpe (gpe_event_info);
                if (ACPI_FAILURE (status)) {
                        ACPI_REPORT_ERROR ((
                                "acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
                                gpe_number));
                        return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
                }
+               break;
        }
 
        return_VALUE (ACPI_INTERRUPT_HANDLED);
 }
 
+
+#ifdef ACPI_GPE_NOTIFY_CHECK
+
+/*******************************************************************************
+ * TBD: NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED
+ *
+ * FUNCTION:    acpi_ev_check_for_wake_only_gpe
+ *
+ * PARAMETERS:  gpe_event_info  - info for this GPE
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Determine if a a GPE is "wake-only".
+ *
+ *              Called from Notify() code in interpreter when a "device_wake"
+ *              Notify comes in.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_check_for_wake_only_gpe (
+       struct acpi_gpe_event_info      *gpe_event_info)
+{
+       acpi_status                     status;
+
+
+       ACPI_FUNCTION_TRACE ("ev_check_for_wake_only_gpe");
+
+
+       if ((gpe_event_info) &&  /* Only >0 for _Lxx/_Exx */
+          ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) /* System state at GPE time */ {
+               /* This must be a wake-only GPE, disable it */
+
+               status = acpi_ev_disable_gpe (gpe_event_info);
+
+               /* Set GPE to wake-only.  Do not change wake disabled/enabled status */
+
+               acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
+
+               ACPI_REPORT_INFO (("GPE %p was updated from wake/run to wake-only\n",
+                               gpe_event_info));
+
+               /* This was a wake-only GPE */
+
+               return_ACPI_STATUS (AE_WAKE_ONLY_GPE);
+       }
+
+       return_ACPI_STATUS (AE_OK);
+}
+#endif
+
+
index b1fbf7d..1913f4e 100644 (file)
@@ -53,7 +53,7 @@
  *
  * FUNCTION:    acpi_ev_valid_gpe_event
  *
- * PARAMETERS:  gpe_event_info - Info for this GPE
+ * PARAMETERS:  gpe_event_info              - Info for this GPE
  *
  * RETURN:      TRUE if the gpe_event is valid
  *
@@ -105,17 +105,18 @@ acpi_ev_valid_gpe_event (
  * FUNCTION:    acpi_ev_walk_gpe_list
  *
  * PARAMETERS:  gpe_walk_callback   - Routine called for each GPE block
+ *              Flags               - ACPI_NOT_ISR or ACPI_ISR
  *
  * RETURN:      Status
  *
  * DESCRIPTION: Walk the GPE lists.
- *              FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
 
 acpi_status
 acpi_ev_walk_gpe_list (
-       ACPI_GPE_CALLBACK       gpe_walk_callback)
+       ACPI_GPE_CALLBACK       gpe_walk_callback,
+       u32                             flags)
 {
        struct acpi_gpe_block_info      *gpe_block;
        struct acpi_gpe_xrupt_info      *gpe_xrupt_info;
@@ -125,7 +126,7 @@ acpi_ev_walk_gpe_list (
        ACPI_FUNCTION_TRACE ("ev_walk_gpe_list");
 
 
-       acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR);
+       acpi_os_acquire_lock (acpi_gbl_gpe_lock, flags);
 
        /* Walk the interrupt level descriptor list */
 
@@ -149,11 +150,58 @@ acpi_ev_walk_gpe_list (
        }
 
 unlock_and_exit:
-       acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
+       acpi_os_release_lock (acpi_gbl_gpe_lock, flags);
        return_ACPI_STATUS (status);
 }
 
 
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_delete_gpe_handlers
+ *
+ * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
+ *              gpe_block           - Gpe Block info
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
+ *              Used only prior to termination.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_delete_gpe_handlers (
+       struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+       struct acpi_gpe_block_info      *gpe_block)
+{
+       struct acpi_gpe_event_info      *gpe_event_info;
+       acpi_native_uint                i;
+       acpi_native_uint                j;
+
+
+       ACPI_FUNCTION_TRACE ("ev_delete_gpe_handlers");
+
+
+       /* Examine each GPE Register within the block */
+
+       for (i = 0; i < gpe_block->register_count; i++) {
+               /* Now look at the individual GPEs in this byte register */
+
+               for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
+                       gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+
+                       if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
+                               ACPI_MEM_FREE (gpe_event_info->dispatch.handler);
+                               gpe_event_info->dispatch.handler = NULL;
+                               gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK;
+                       }
+               }
+       }
+
+       return_ACPI_STATUS (AE_OK);
+}
+
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_save_method_info
@@ -188,6 +236,7 @@ acpi_ev_save_method_info (
        u32                             gpe_number;
        char                            name[ACPI_NAME_SIZE + 1];
        u8                              type;
+       acpi_status                     status;
 
 
        ACPI_FUNCTION_TRACE ("ev_save_method_info");
@@ -206,16 +255,16 @@ acpi_ev_save_method_info (
         * 2) Edge/Level determination is based on the 2nd character
         *    of the method name
         *
-        * NOTE: Default GPE type is RUNTIME.  May be changed later to WAKE if a
-        * _PRW object is found that points to this GPE.
+        * NOTE: Default GPE type is RUNTIME.  May be changed later to WAKE
+        * if a _PRW object is found that points to this GPE.
         */
        switch (name[1]) {
        case 'L':
-               type = ACPI_GPE_LEVEL_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
+               type = ACPI_GPE_LEVEL_TRIGGERED;
                break;
 
        case 'E':
-               type = ACPI_GPE_EDGE_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
+               type = ACPI_GPE_EDGE_TRIGGERED;
                break;
 
        default:
@@ -253,27 +302,35 @@ acpi_ev_save_method_info (
 
        /*
         * Now we can add this information to the gpe_event_info block
-        * for use during dispatch of this GPE.
+        * for use during dispatch of this GPE.  Default type is RUNTIME, although
+        * this may change when the _PRW methods are executed later.
         */
        gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
 
-       gpe_event_info->flags    = type;
-       gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle;
+       gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD |
+                          ACPI_GPE_TYPE_RUNTIME);
+
+       gpe_event_info->dispatch.method_node = (struct acpi_namespace_node *) obj_handle;
+
+       /* Update enable mask, but don't enable the HW GPE as of yet */
+
+       status = acpi_ev_enable_gpe (gpe_event_info, FALSE);
 
        ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
                "Registered GPE method %s as GPE number 0x%.2X\n",
                name, gpe_number));
-       return_ACPI_STATUS (AE_OK);
+       return_ACPI_STATUS (status);
 }
 
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_get_gpe_type
+ * FUNCTION:    acpi_ev_match_prw_and_gpe
  *
  * PARAMETERS:  Callback from walk_namespace
  *
- * RETURN:      Status
+ * RETURN:      Status.  NOTE: We ignore errors so that the _PRW walk is
+ *              not aborted on a single _PRW failure.
  *
  * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
  *              Device.  Run the _PRW method.  If present, extract the GPE
@@ -282,7 +339,7 @@ acpi_ev_save_method_info (
  ******************************************************************************/
 
 static acpi_status
-acpi_ev_get_gpe_type (
+acpi_ev_match_prw_and_gpe (
        acpi_handle                     obj_handle,
        u32                             level,
        void                            *info,
@@ -299,19 +356,18 @@ acpi_ev_get_gpe_type (
        acpi_status                     status;
 
 
-       ACPI_FUNCTION_TRACE ("ev_get_gpe_type");
+       ACPI_FUNCTION_TRACE ("ev_match_prw_and_gpe");
 
 
        /* Check for a _PRW method under this device */
 
        status = acpi_ut_evaluate_object (obj_handle, METHOD_NAME__PRW,
                         ACPI_BTYPE_PACKAGE, &pkg_desc);
-       if (status == AE_NOT_FOUND) {
+       if (ACPI_FAILURE (status)) {
+               /* Ignore all errors from _PRW, we don't want to abort the subsystem */
+
                return_ACPI_STATUS (AE_OK);
        }
-       else if (ACPI_FAILURE (status)) {
-               return_ACPI_STATUS (status);
-       }
 
        /* The returned _PRW package must have at least two elements */
 
@@ -370,16 +426,21 @@ acpi_ev_get_gpe_type (
        if ((gpe_device == target_gpe_device) &&
                (gpe_number >= gpe_block->block_base_number) &&
                (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
-               /* Mark GPE for WAKE but DISABLED (even for wake) */
-
                gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
-               gpe_event_info->flags |= ACPI_GPE_TYPE_WAKE;
+
+               /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
+
+               gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
+               status = acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
+               if (ACPI_FAILURE (status)) {
+                       goto cleanup;
+               }
+               status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
        }
 
 cleanup:
        acpi_ut_remove_reference (pkg_desc);
-
-       return_ACPI_STATUS (status);
+       return_ACPI_STATUS (AE_OK);
 }
 
 
@@ -742,7 +803,7 @@ acpi_ev_create_gpe_info_blocks (
                /* Init the event_info for each GPE within this register */
 
                for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
-                       this_event->bit_mask = acpi_gbl_decode_to8bit[j];
+                       this_event->register_bit = acpi_gbl_decode_to8bit[j];
                        this_event->register_info = this_register;
                        this_event++;
                }
@@ -817,6 +878,7 @@ acpi_ev_create_gpe_block (
        acpi_status                     status;
        struct acpi_gpe_walk_info       gpe_info;
 
+
        ACPI_FUNCTION_TRACE ("ev_create_gpe_block");
 
 
@@ -835,6 +897,7 @@ acpi_ev_create_gpe_block (
 
        gpe_block->register_count = register_count;
        gpe_block->block_base_number = gpe_block_base_number;
+       gpe_block->node           = gpe_device;
 
        ACPI_MEMCPY (&gpe_block->block_address, gpe_block_address, sizeof (struct acpi_generic_address));
 
@@ -854,18 +917,6 @@ acpi_ev_create_gpe_block (
                return_ACPI_STATUS (status);
        }
 
-       /* Dump info about this GPE block */
-
-       ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
-               "GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
-               gpe_block->block_base_number,
-               (u32) (gpe_block->block_base_number +
-                               ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
-               gpe_device->name.ascii,
-               gpe_block->register_count,
-               ACPI_FORMAT_UINT64 (gpe_block->block_address.address),
-               interrupt_level));
-
        /* Find all GPE methods (_Lxx, _Exx) for this block */
 
        status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device,
@@ -873,27 +924,28 @@ acpi_ev_create_gpe_block (
                          gpe_block, NULL);
 
        /*
-        * Runtime option: Should Wake GPEs be enabled at runtime?  The default is
-        * No,they should only be enabled just as the machine goes to sleep.
+        * Runtime option: Should Wake GPEs be enabled at runtime?  The default
+        * is No,they should only be enabled just as the machine goes to sleep.
         */
        if (acpi_gbl_leave_wake_gpes_disabled) {
                /*
-                * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods. (Each
-                * GPE that has one or more _PRWs that reference it is by definition a
-                * WAKE GPE and will not be enabled while the machine is running.)
+                * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods.
+                * (Each GPE that has one or more _PRWs that reference it is by
+                * definition a WAKE GPE and will not be enabled while the machine
+                * is running.)
                 */
                gpe_info.gpe_block = gpe_block;
                gpe_info.gpe_device = gpe_device;
 
                status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                                 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_get_gpe_type,
+                                 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_match_prw_and_gpe,
                                  &gpe_info, NULL);
        }
 
        /*
-        * Enable all GPEs in this block that are 1) "runtime" GPEs, and 2) have
-        * a corresponding _Lxx or _Exx method.  All other GPEs must be enabled via
-        * the acpi_enable_gpe() external interface.
+        * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs,
+        * and 2) have a corresponding _Lxx or _Exx method.  All other GPEs must
+        * be enabled via the acpi_enable_gpe() external interface.
         */
        wake_gpe_count = 0;
        gpe_enabled_count = 0;
@@ -903,23 +955,35 @@ acpi_ev_create_gpe_block (
                        /* Get the info block for this particular GPE */
 
                        gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
-                       if ((gpe_event_info->method_node) &&
-                          ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_RUNTIME)) {
-                               /* Enable this GPE, it is 1) RUNTIME and 2) has an _Lxx or _Exx method */
-
-                               status = acpi_hw_enable_gpe (gpe_event_info);
-                               if (ACPI_FAILURE (status)) {
-                                       return_ACPI_STATUS (status);
-                               }
+
+                       if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) &&
+                                (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) {
                                gpe_enabled_count++;
                        }
 
-                       if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_WAKE) {
+                       if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) {
                                wake_gpe_count++;
                        }
                }
        }
 
+       /* Dump info about this GPE block */
+
+       ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+               "GPE %02X to %02X [%4.4s] %u regs at %8.8X%8.8X on int 0x%X\n",
+               (u32) gpe_block->block_base_number,
+               (u32) (gpe_block->block_base_number +
+                               ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
+               gpe_device->name.ascii,
+               gpe_block->register_count,
+               ACPI_FORMAT_UINT64 (gpe_block->block_address.address),
+               interrupt_level));
+
+
+       /* Enable all valid GPEs found above */
+
+       status = acpi_hw_enable_runtime_gpe_block (NULL, gpe_block);
+
        ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
                        "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
                        wake_gpe_count, gpe_enabled_count));
@@ -1056,7 +1120,8 @@ acpi_ev_gpe_initialize (
        if ((register_count0 + register_count1) == 0) {
                /* GPEs are not required by ACPI, this is OK */
 
-               ACPI_REPORT_INFO (("There are no GPE blocks defined in the FADT\n"));
+               ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+                               "There are no GPE blocks defined in the FADT\n"));
                status = AE_OK;
                goto cleanup;
        }
index 1bfb10d..35e61d5 100644 (file)
@@ -88,9 +88,10 @@ acpi_ev_is_notify_object (
  *
  * FUNCTION:    acpi_ev_queue_notify_request
  *
- * PARAMETERS:
+ * PARAMETERS:  Node            - NS node for the notified object
+ *              notify_value    - Value from the Notify() request
  *
- * RETURN:      None.
+ * RETURN:      Status
  *
  * DESCRIPTION: Dispatch a device notification event to a previously
  *              installed handler.
@@ -139,14 +140,12 @@ acpi_ev_queue_notify_request (
                                acpi_notify_value_names[notify_value]));
        }
        else {
-               ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
-                               "notify value: 0x%2.2x **Device Specific**\n",
+               ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: 0x%2.2X **Device Specific**\n",
                                notify_value));
        }
 
-       /*
-        * Get the notify object attached to the NS Node
-        */
+       /* Get the notify object attached to the NS Node */
+
        obj_desc = acpi_ns_get_attached_object (node);
        if (obj_desc) {
                /* We have the notify object, Get the right handler */
@@ -194,11 +193,13 @@ acpi_ev_queue_notify_request (
        }
 
        if (!handler_obj) {
-               /* There is no per-device notify handler for this device */
-
+               /*
+                * There is no per-device notify handler for this device.
+                * This may or may not be a problem.
+                */
                ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
-                       "No notify handler for [%4.4s] node %p\n",
-                       acpi_ut_get_node_name (node), node));
+                       "No notify handler for Notify(%4.4s, %X) node %p\n",
+                       acpi_ut_get_node_name (node), notify_value, node));
        }
 
        return (status);
@@ -209,7 +210,7 @@ acpi_ev_queue_notify_request (
  *
  * FUNCTION:    acpi_ev_notify_dispatch
  *
- * PARAMETERS:
+ * PARAMETERS:  Context         - To be passsed to the notify handler
  *
  * RETURN:      None.
  *
@@ -276,6 +277,8 @@ acpi_ev_notify_dispatch (
  *
  * FUNCTION:    acpi_ev_global_lock_thread
  *
+ * PARAMETERS:  Context         - From thread interface, not used
+ *
  * RETURN:      None
  *
  * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the
@@ -309,7 +312,9 @@ acpi_ev_global_lock_thread (
  *
  * FUNCTION:    acpi_ev_global_lock_handler
  *
- * RETURN:      Status
+ * PARAMETERS:  Context         - From thread interface, not used
+ *
+ * RETURN:      ACPI_INTERRUPT_HANDLED or ACPI_INTERRUPT_NOT_HANDLED
  *
  * DESCRIPTION: Invoked directly from the SCI handler when a global lock
  *              release interrupt occurs.  Grab the global lock and queue
@@ -356,6 +361,8 @@ acpi_ev_global_lock_handler (
  *
  * FUNCTION:    acpi_ev_init_global_lock_handler
  *
+ * PARAMETERS:  None
+ *
  * RETURN:      Status
  *
  * DESCRIPTION: Install a handler for the global lock release event
@@ -395,6 +402,8 @@ acpi_ev_init_global_lock_handler (void)
  *
  * FUNCTION:    acpi_ev_acquire_global_lock
  *
+ * PARAMETERS:  Timeout         - Max time to wait for the lock, in millisec.
+ *
  * RETURN:      Status
  *
  * DESCRIPTION: Attempt to gain ownership of the Global Lock.
@@ -462,6 +471,10 @@ acpi_ev_acquire_global_lock (
  *
  * FUNCTION:    acpi_ev_release_global_lock
  *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
  * DESCRIPTION: Releases ownership of the Global Lock.
  *
  ******************************************************************************/
@@ -548,7 +561,7 @@ acpi_ev_terminate (void)
 
                /* Disable all GPEs in all GPE blocks */
 
-               status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block);
+               status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, ACPI_NOT_ISR);
 
                /* Remove SCI handler */
 
@@ -558,6 +571,10 @@ acpi_ev_terminate (void)
                }
        }
 
+       /* Deallocate all handler objects installed within GPE info structs */
+
+       status = acpi_ev_walk_gpe_list (acpi_ev_delete_gpe_handlers, ACPI_NOT_ISR);
+
        /* Return to original mode if necessary */
 
        if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
index ec81e58..b7ff3b1 100644 (file)
@@ -61,7 +61,7 @@ static u8                   acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPA
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_init_address_spaces
+ * FUNCTION:    acpi_ev_install_region_handlers
  *
  * PARAMETERS:  None
  *
@@ -72,15 +72,20 @@ static u8                   acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPA
  ******************************************************************************/
 
 acpi_status
-acpi_ev_init_address_spaces (
+acpi_ev_install_region_handlers (
        void) {
        acpi_status                     status;
        acpi_native_uint                i;
 
 
-       ACPI_FUNCTION_TRACE ("ev_init_address_spaces");
+       ACPI_FUNCTION_TRACE ("ev_install_region_handlers");
 
 
+       status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
+       }
+
        /*
         * All address spaces (PCI Config, EC, SMBus) are scope dependent
         * and registration must occur for a specific device.
@@ -99,9 +104,8 @@ acpi_ev_init_address_spaces (
         * has already been installed (via acpi_install_address_space_handler).
         * Similar for AE_SAME_HANDLER.
         */
-
        for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
-               status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node,
+               status = acpi_ev_install_space_handler (acpi_gbl_root_node,
                                  acpi_gbl_default_address_spaces[i],
                                  ACPI_DEFAULT_HANDLER, NULL, NULL);
                switch (status) {
@@ -111,15 +115,63 @@ acpi_ev_init_address_spaces (
 
                        /* These exceptions are all OK */
 
+                       status = AE_OK;
                        break;
 
                default:
 
-                       return_ACPI_STATUS (status);
+                       goto unlock_and_exit;
                }
        }
 
-       return_ACPI_STATUS (AE_OK);
+unlock_and_exit:
+       (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+       return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_initialize_op_regions
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Execute _REG methods for all Operation Regions that have
+ *              an installed default region handler.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_initialize_op_regions (
+       void)
+{
+       acpi_status                     status;
+       acpi_native_uint                i;
+
+
+       ACPI_FUNCTION_TRACE ("ev_initialize_op_regions");
+
+
+       status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
+       }
+
+       /*
+        * Run the _REG methods for op_regions in each default address space
+        */
+       for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
+               /* TBD: Make sure handler is the DEFAULT handler, otherwise
+                * _REG will have already been run.
+                */
+               status = acpi_ev_execute_reg_methods (acpi_gbl_root_node,
+                                 acpi_gbl_default_address_spaces[i]);
+       }
+
+       (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+       return_ACPI_STATUS (status);
 }
 
 
@@ -128,7 +180,7 @@ acpi_ev_init_address_spaces (
  * FUNCTION:    acpi_ev_execute_reg_method
  *
  * PARAMETERS:  region_obj          - Object structure
- *              Function            - On (1) or Off (0)
+ *              Function            - Passed to _REG:  On (1) or Off (0)
  *
  * RETURN:      Status
  *
@@ -138,11 +190,12 @@ acpi_ev_init_address_spaces (
 
 acpi_status
 acpi_ev_execute_reg_method (
-       union acpi_operand_object      *region_obj,
+       union acpi_operand_object       *region_obj,
        u32                             function)
 {
-       union acpi_operand_object      *params[3];
-       union acpi_operand_object      *region_obj2;
+       struct acpi_parameter_info      info;
+       union acpi_operand_object       *params[3];
+       union acpi_operand_object       *region_obj2;
        acpi_status                     status;
 
 
@@ -159,10 +212,11 @@ acpi_ev_execute_reg_method (
        }
 
        /*
-        * _REG method has two arguments
-        * Arg0:   Integer: Operation region space ID
+        * The _REG method has two arguments:
+        *
+        * Arg0, Integer: Operation region space ID
         *          Same value as region_obj->Region.space_id
-        * Arg1:   Integer: connection status
+        * Arg1, Integer: connection status
         *          1 for connecting the handler,
         *          0 for disconnecting the handler
         *          Passed as a parameter
@@ -178,16 +232,21 @@ acpi_ev_execute_reg_method (
                goto cleanup;
        }
 
-       /* Set up the parameter objects */
+       /* Setup the parameter objects */
 
        params[0]->integer.value = region_obj->region.space_id;
        params[1]->integer.value = function;
        params[2] = NULL;
 
+       info.node = region_obj2->extra.method_REG;
+       info.parameters = params;
+       info.parameter_type = ACPI_PARAM_ARGS;
+
        /* Execute the method, no return value */
 
-       ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, region_obj2->extra.method_REG, NULL));
-       status = acpi_ns_evaluate_by_handle (region_obj2->extra.method_REG, params, NULL);
+       ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (
+                          ACPI_TYPE_METHOD, info.node, NULL));
+       status = acpi_ns_evaluate_by_handle (&info);
 
        acpi_ut_remove_reference (params[1]);
 
@@ -203,7 +262,6 @@ cleanup:
  * FUNCTION:    acpi_ev_address_space_dispatch
  *
  * PARAMETERS:  region_obj          - Internal region object
- *              space_id            - ID of the address space (0-255)
  *              Function            - Read or Write operation
  *              Address             - Where in the space to read or write
  *              bit_width           - Field width in bits (8, 16, 32, or 64)
@@ -326,7 +384,7 @@ acpi_ev_address_space_dispatch (
                ACPI_FORMAT_UINT64 (address),
                acpi_ut_get_region_name (region_obj->region.space_id)));
 
-       if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+       if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
                /*
                 * For handlers other than the default (supplied) handlers, we must
                 * exit the interpreter because the handler *might* block -- we don't
@@ -347,7 +405,7 @@ acpi_ev_address_space_dispatch (
                        acpi_format_exception (status)));
        }
 
-       if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+       if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
                /*
                 * We just returned from a non-default handler, we must re-enter the
                 * interpreter
@@ -366,8 +424,8 @@ acpi_ev_address_space_dispatch (
  *
  * FUNCTION:    acpi_ev_detach_region
  *
- * PARAMETERS:  region_obj      - Region Object
- *              acpi_ns_is_locked - Namespace Region Already Locked?
+ * PARAMETERS:  region_obj          - Region Object
+ *              acpi_ns_is_locked   - Namespace Region Already Locked?
  *
  * RETURN:      None
  *
@@ -501,9 +559,9 @@ acpi_ev_detach_region(
  *
  * FUNCTION:    acpi_ev_attach_region
  *
- * PARAMETERS:  handler_obj     - Handler Object
- *              region_obj      - Region Object
- *              acpi_ns_is_locked - Namespace Region Already Locked?
+ * PARAMETERS:  handler_obj         - Handler Object
+ *              region_obj          - Region Object
+ *              acpi_ns_is_locked   - Namespace Region Already Locked?
  *
  * RETURN:      None
  *
@@ -676,6 +734,273 @@ acpi_ev_install_handler (
        return (status);
 }
 
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_install_space_handler
+ *
+ * PARAMETERS:  Node            - Namespace node for the device
+ *              space_id        - The address space ID
+ *              Handler         - Address of the handler
+ *              Setup           - Address of the setup function
+ *              Context         - Value passed to the handler on each access
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install a handler for all op_regions of a given space_id.
+ *              Assumes namespace is locked
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_install_space_handler (
+       struct acpi_namespace_node      *node,
+       acpi_adr_space_type             space_id,
+       acpi_adr_space_handler          handler,
+       acpi_adr_space_setup            setup,
+       void                            *context)
+{
+       union acpi_operand_object       *obj_desc;
+       union acpi_operand_object       *handler_obj;
+       acpi_status                     status;
+       acpi_object_type                type;
+       u16                             flags = 0;
+
+
+       ACPI_FUNCTION_TRACE ("ev_install_space_handler");
+
+
+       /*
+        * This registration is valid for only the types below
+        * and the root.  This is where the default handlers
+        * get placed.
+        */
+       if ((node->type != ACPI_TYPE_DEVICE)     &&
+               (node->type != ACPI_TYPE_PROCESSOR)  &&
+               (node->type != ACPI_TYPE_THERMAL)    &&
+               (node != acpi_gbl_root_node)) {
+               status = AE_BAD_PARAMETER;
+               goto unlock_and_exit;
+       }
+
+       if (handler == ACPI_DEFAULT_HANDLER) {
+               flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
+
+               switch (space_id) {
+               case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+                       handler = acpi_ex_system_memory_space_handler;
+                       setup   = acpi_ev_system_memory_region_setup;
+                       break;
+
+               case ACPI_ADR_SPACE_SYSTEM_IO:
+                       handler = acpi_ex_system_io_space_handler;
+                       setup   = acpi_ev_io_space_region_setup;
+                       break;
+
+               case ACPI_ADR_SPACE_PCI_CONFIG:
+                       handler = acpi_ex_pci_config_space_handler;
+                       setup   = acpi_ev_pci_config_region_setup;
+                       break;
+
+               case ACPI_ADR_SPACE_CMOS:
+                       handler = acpi_ex_cmos_space_handler;
+                       setup   = acpi_ev_cmos_region_setup;
+                       break;
+
+               case ACPI_ADR_SPACE_PCI_BAR_TARGET:
+                       handler = acpi_ex_pci_bar_space_handler;
+                       setup   = acpi_ev_pci_bar_region_setup;
+                       break;
+
+               case ACPI_ADR_SPACE_DATA_TABLE:
+                       handler = acpi_ex_data_table_space_handler;
+                       setup   = NULL;
+                       break;
+
+               default:
+                       status = AE_BAD_PARAMETER;
+                       goto unlock_and_exit;
+               }
+       }
+
+       /* If the caller hasn't specified a setup routine, use the default */
+
+       if (!setup) {
+               setup = acpi_ev_default_region_setup;
+       }
+
+       /* Check for an existing internal object */
+
+       obj_desc = acpi_ns_get_attached_object (node);
+       if (obj_desc) {
+               /*
+                * The attached device object already exists.
+                * Make sure the handler is not already installed.
+                */
+               handler_obj = obj_desc->device.handler;
+
+               /* Walk the handler list for this device */
+
+               while (handler_obj) {
+                       /* Same space_id indicates a handler already installed */
+
+                       if (handler_obj->address_space.space_id == space_id) {
+                               if (handler_obj->address_space.handler == handler) {
+                                       /*
+                                        * It is (relatively) OK to attempt to install the SAME
+                                        * handler twice. This can easily happen with PCI_Config space.
+                                        */
+                                       status = AE_SAME_HANDLER;
+                                       goto unlock_and_exit;
+                               }
+                               else {
+                                       /* A handler is already installed */
+
+                                       status = AE_ALREADY_EXISTS;
+                               }
+                               goto unlock_and_exit;
+                       }
+
+                       /* Walk the linked list of handlers */
+
+                       handler_obj = handler_obj->address_space.next;
+               }
+       }
+       else {
+               ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+                       "Creating object on Device %p while installing handler\n", node));
+
+               /* obj_desc does not exist, create one */
+
+               if (node->type == ACPI_TYPE_ANY) {
+                       type = ACPI_TYPE_DEVICE;
+               }
+               else {
+                       type = node->type;
+               }
+
+               obj_desc = acpi_ut_create_internal_object (type);
+               if (!obj_desc) {
+                       status = AE_NO_MEMORY;
+                       goto unlock_and_exit;
+               }
+
+               /* Init new descriptor */
+
+               obj_desc->common.type = (u8) type;
+
+               /* Attach the new object to the Node */
+
+               status = acpi_ns_attach_object (node, obj_desc, type);
+
+               /* Remove local reference to the object */
+
+               acpi_ut_remove_reference (obj_desc);
+
+               if (ACPI_FAILURE (status)) {
+                       goto unlock_and_exit;
+               }
+       }
+
+       ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+               "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
+               acpi_ut_get_region_name (space_id), space_id,
+               acpi_ut_get_node_name (node), node, obj_desc));
+
+       /*
+        * Install the handler
+        *
+        * At this point there is no existing handler.
+        * Just allocate the object for the handler and link it
+        * into the list.
+        */
+       handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
+       if (!handler_obj) {
+               status = AE_NO_MEMORY;
+               goto unlock_and_exit;
+       }
+
+       /* Init handler obj */
+
+       handler_obj->address_space.space_id  = (u8) space_id;
+       handler_obj->address_space.hflags    = flags;
+       handler_obj->address_space.region_list = NULL;
+       handler_obj->address_space.node      = node;
+       handler_obj->address_space.handler   = handler;
+       handler_obj->address_space.context   = context;
+       handler_obj->address_space.setup     = setup;
+
+       /* Install at head of Device.address_space list */
+
+       handler_obj->address_space.next      = obj_desc->device.handler;
+
+       /*
+        * The Device object is the first reference on the handler_obj.
+        * Each region that uses the handler adds a reference.
+        */
+       obj_desc->device.handler = handler_obj;
+
+       /*
+        * Walk the namespace finding all of the regions this
+        * handler will manage.
+        *
+        * Start at the device and search the branch toward
+        * the leaf nodes until either the leaf is encountered or
+        * a device is detected that has an address handler of the
+        * same type.
+        *
+        * In either case, back up and search down the remainder
+        * of the branch
+        */
+       status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+                         ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
+                         handler_obj, NULL);
+
+unlock_and_exit:
+       return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_execute_reg_methods
+ *
+ * PARAMETERS:  Node            - Namespace node for the device
+ *              space_id        - The address space ID
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Run all _REG methods for the input Space ID;
+ *              Note: assumes namespace is locked, or system init time.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_execute_reg_methods (
+       struct acpi_namespace_node      *node,
+       acpi_adr_space_type             space_id)
+{
+       acpi_status                     status;
+
+
+       ACPI_FUNCTION_TRACE ("ev_execute_reg_methods");
+
+
+       /*
+        * Run all _REG methods for all Operation Regions for this
+        * space ID.  This is a separate walk in order to handle any
+        * interdependencies between regions and _REG methods.  (i.e. handlers
+        * must be installed for all regions of this Space ID before we
+        * can run any _REG methods)
+        */
+       status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+                         ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
+                         &space_id, NULL);
+
+       return_ACPI_STATUS (status);
+}
+
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_reg_run
@@ -693,19 +1018,13 @@ acpi_ev_reg_run (
        void                            *context,
        void                            **return_value)
 {
-       union acpi_operand_object       *handler_obj;
        union acpi_operand_object       *obj_desc;
        struct acpi_namespace_node      *node;
+       acpi_adr_space_type             space_id;
        acpi_status                     status;
 
 
-       handler_obj = (union acpi_operand_object   *) context;
-
-       /* Parameter validation */
-
-       if (!handler_obj) {
-               return (AE_OK);
-       }
+       space_id = *ACPI_CAST_PTR (acpi_adr_space_type, context);
 
        /* Convert and validate the device handle */
 
@@ -732,10 +1051,9 @@ acpi_ev_reg_run (
                return (AE_OK);
        }
 
-
        /* Object is a Region */
 
-       if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
+       if (obj_desc->region.space_id != space_id) {
                /*
                 * This region is for a different address space
                 * -- just ignore it
index 2e480d3..e19d822 100644 (file)
@@ -54,7 +54,7 @@
  *
  * FUNCTION:    acpi_ev_system_memory_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -108,7 +108,7 @@ acpi_ev_system_memory_region_setup (
  *
  * FUNCTION:    acpi_ev_io_space_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -144,7 +144,7 @@ acpi_ev_io_space_region_setup (
  *
  * FUNCTION:    acpi_ev_pci_config_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle             - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -317,7 +317,7 @@ acpi_ev_pci_config_region_setup (
  *
  * FUNCTION:    acpi_ev_pci_bar_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -348,7 +348,7 @@ acpi_ev_pci_bar_region_setup (
  *
  * FUNCTION:    acpi_ev_cmos_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -379,7 +379,7 @@ acpi_ev_cmos_region_setup (
  *
  * FUNCTION:    acpi_ev_default_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
index 640f51f..e941678 100644 (file)
@@ -204,12 +204,11 @@ acpi_enable_event (
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_enable_gpe
+ * FUNCTION:    acpi_set_gpe_type
  *
  * PARAMETERS:  gpe_device      - Parent GPE Device
  *              gpe_number      - GPE level within the GPE block
- *              Flags           - Just enable, or also wake enable?
- *                                Called from ISR or not
+ *              Type            - New GPE type
  *
  * RETURN:      Status
  *
@@ -218,26 +217,17 @@ acpi_enable_event (
  ******************************************************************************/
 
 acpi_status
-acpi_enable_gpe (
+acpi_set_gpe_type (
        acpi_handle                     gpe_device,
        u32                             gpe_number,
-       u32                             flags)
+       u8                              type)
 {
        acpi_status                     status = AE_OK;
        struct acpi_gpe_event_info      *gpe_event_info;
 
 
-       ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
-
+       ACPI_FUNCTION_TRACE ("acpi_set_gpe_type");
 
-       /* Use semaphore lock if not executing at interrupt level */
-
-       if (flags & ACPI_NOT_ISR) {
-               status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
-               if (ACPI_FAILURE (status)) {
-                       return_ACPI_STATUS (status);
-               }
-       }
 
        /* Ensure that we have a valid GPE number */
 
@@ -247,91 +237,72 @@ acpi_enable_gpe (
                goto unlock_and_exit;
        }
 
-       /* Check for Wake vs Runtime GPE */
-
-       if (flags & ACPI_EVENT_WAKE_ENABLE) {
-               /* Ensure the requested wake GPE is disabled */
-
-               status = acpi_hw_disable_gpe (gpe_event_info);
-               if (ACPI_FAILURE (status)) {
-                       goto unlock_and_exit;
-               }
-
-               /* Defer Enable of Wake GPE until sleep time */
-
-               acpi_hw_enable_gpe_for_wakeup (gpe_event_info);
+       if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
+               return_ACPI_STATUS (AE_OK);
        }
-       else {
-               /* Enable the requested runtime GPE  */
 
-               status = acpi_hw_enable_gpe (gpe_event_info);
-               if (ACPI_FAILURE (status)) {
-                       goto unlock_and_exit;
-               }
-       }
+       /* Set the new type (will disable GPE if currently enabled) */
 
+       status = acpi_ev_set_gpe_type (gpe_event_info, type);
 
 unlock_and_exit:
-       if (flags & ACPI_NOT_ISR) {
-               (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
-       }
        return_ACPI_STATUS (status);
 }
 
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_disable_event
+ * FUNCTION:    acpi_enable_gpe
  *
- * PARAMETERS:  Event           - The fixed eventto be enabled
- *              Flags           - Reserved
+ * PARAMETERS:  gpe_device      - Parent GPE Device
+ *              gpe_number      - GPE level within the GPE block
+ *              Flags           - Just enable, or also wake enable?
+ *                                Called from ISR or not
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Disable an ACPI event (fixed)
+ * DESCRIPTION: Enable an ACPI event (general purpose)
  *
  ******************************************************************************/
 
 acpi_status
-acpi_disable_event (
-       u32                             event,
+acpi_enable_gpe (
+       acpi_handle                     gpe_device,
+       u32                             gpe_number,
        u32                             flags)
 {
        acpi_status                     status = AE_OK;
-       u32                             value;
+       struct acpi_gpe_event_info      *gpe_event_info;
 
 
-       ACPI_FUNCTION_TRACE ("acpi_disable_event");
+       ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
 
 
-       /* Decode the Fixed Event */
+       /* Use semaphore lock if not executing at interrupt level */
 
-       if (event > ACPI_EVENT_MAX) {
-               return_ACPI_STATUS (AE_BAD_PARAMETER);
+       if (flags & ACPI_NOT_ISR) {
+               status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
+               if (ACPI_FAILURE (status)) {
+                       return_ACPI_STATUS (status);
+               }
        }
 
-       /*
-        * Disable the requested fixed event (by writing a zero to the
-        * enable register bit)
-        */
-       status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
-                        0, ACPI_MTX_LOCK);
-       if (ACPI_FAILURE (status)) {
-               return_ACPI_STATUS (status);
-       }
+       /* Ensure that we have a valid GPE number */
 
-       status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
-                        &value, ACPI_MTX_LOCK);
-       if (ACPI_FAILURE (status)) {
-               return_ACPI_STATUS (status);
+       gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+       if (!gpe_event_info) {
+               status = AE_BAD_PARAMETER;
+               goto unlock_and_exit;
        }
 
-       if (value != 0) {
-               ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-                       "Could not disable %s events\n", acpi_ut_get_event_name (event)));
-               return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
-       }
+       /* Perform the enable */
+
+       status = acpi_ev_enable_gpe (gpe_event_info, TRUE);
 
+unlock_and_exit:
+       if (flags & ACPI_NOT_ISR) {
+               (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+       }
        return_ACPI_STATUS (status);
 }
 
@@ -342,7 +313,7 @@ acpi_disable_event (
  *
  * PARAMETERS:  gpe_device      - Parent GPE Device
  *              gpe_number      - GPE level within the GPE block
- *              Flags           - Just enable, or also wake enable?
+ *              Flags           - Just disable, or also wake disable?
  *                                Called from ISR or not
  *
  * RETURN:      Status
@@ -381,21 +352,69 @@ acpi_disable_gpe (
                goto unlock_and_exit;
        }
 
+       status = acpi_ev_disable_gpe (gpe_event_info);
+
+unlock_and_exit:
+       if (flags & ACPI_NOT_ISR) {
+               (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+       }
+       return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_disable_event
+ *
+ * PARAMETERS:  Event           - The fixed eventto be enabled
+ *              Flags           - Reserved
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Disable an ACPI event (fixed)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_disable_event (
+       u32                             event,
+       u32                             flags)
+{
+       acpi_status                     status = AE_OK;
+       u32                             value;
+
+
+       ACPI_FUNCTION_TRACE ("acpi_disable_event");
+
+
+       /* Decode the Fixed Event */
+
+       if (event > ACPI_EVENT_MAX) {
+               return_ACPI_STATUS (AE_BAD_PARAMETER);
+       }
+
        /*
-        * Only disable the requested GPE number for wake if specified.
-        * Otherwise, turn it totally off
+        * Disable the requested fixed event (by writing a zero to the
+        * enable register bit)
         */
-       if (flags & ACPI_EVENT_WAKE_DISABLE) {
-               acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
+       status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
+                        0, ACPI_MTX_LOCK);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
        }
-       else {
-               status = acpi_hw_disable_gpe (gpe_event_info);
+
+       status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
+                        &value, ACPI_MTX_LOCK);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
        }
 
-unlock_and_exit:
-       if (flags & ACPI_NOT_ISR) {
-               (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+       if (value != 0) {
+               ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+                       "Could not disable %s events\n", acpi_ut_get_event_name (event)));
+               return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
        }
+
        return_ACPI_STATUS (status);
 }
 
index b31d4fd..8eeb938 100644 (file)
@@ -46,7 +46,6 @@
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
-#include <acpi/acinterp.h>
 
 #define _COMPONENT          ACPI_EVENTS
         ACPI_MODULE_NAME    ("evxfregn")
@@ -76,12 +75,8 @@ acpi_install_address_space_handler (
        acpi_adr_space_setup            setup,
        void                            *context)
 {
-       union acpi_operand_object       *obj_desc;
-       union acpi_operand_object       *handler_obj;
        struct acpi_namespace_node      *node;
        acpi_status                     status;
-       acpi_object_type                type;
-       u16                             flags = 0;
 
 
        ACPI_FUNCTION_TRACE ("acpi_install_address_space_handler");
@@ -106,202 +101,16 @@ acpi_install_address_space_handler (
                goto unlock_and_exit;
        }
 
-       /*
-        * This registration is valid for only the types below
-        * and the root.  This is where the default handlers
-        * get placed.
-        */
-       if ((node->type != ACPI_TYPE_DEVICE)     &&
-               (node->type != ACPI_TYPE_PROCESSOR)  &&
-               (node->type != ACPI_TYPE_THERMAL)    &&
-               (node != acpi_gbl_root_node)) {
-               status = AE_BAD_PARAMETER;
-               goto unlock_and_exit;
-       }
-
-       if (handler == ACPI_DEFAULT_HANDLER) {
-               flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
-
-               switch (space_id) {
-               case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-                       handler = acpi_ex_system_memory_space_handler;
-                       setup   = acpi_ev_system_memory_region_setup;
-                       break;
-
-               case ACPI_ADR_SPACE_SYSTEM_IO:
-                       handler = acpi_ex_system_io_space_handler;
-                       setup   = acpi_ev_io_space_region_setup;
-                       break;
-
-               case ACPI_ADR_SPACE_PCI_CONFIG:
-                       handler = acpi_ex_pci_config_space_handler;
-                       setup   = acpi_ev_pci_config_region_setup;
-                       break;
-
-               case ACPI_ADR_SPACE_CMOS:
-                       handler = acpi_ex_cmos_space_handler;
-                       setup   = acpi_ev_cmos_region_setup;
-                       break;
-
-               case ACPI_ADR_SPACE_PCI_BAR_TARGET:
-                       handler = acpi_ex_pci_bar_space_handler;
-                       setup   = acpi_ev_pci_bar_region_setup;
-                       break;
-
-               case ACPI_ADR_SPACE_DATA_TABLE:
-                       handler = acpi_ex_data_table_space_handler;
-                       setup   = NULL;
-                       break;
-
-               default:
-                       status = AE_BAD_PARAMETER;
-                       goto unlock_and_exit;
-               }
-       }
-
-       /* If the caller hasn't specified a setup routine, use the default */
-
-       if (!setup) {
-               setup = acpi_ev_default_region_setup;
-       }
-
-       /* Check for an existing internal object */
-
-       obj_desc = acpi_ns_get_attached_object (node);
-       if (obj_desc) {
-               /*
-                * The attached device object already exists.
-                * Make sure the handler is not already installed.
-                */
-               handler_obj = obj_desc->device.handler;
-
-               /* Walk the handler list for this device */
-
-               while (handler_obj) {
-                       /* Same space_id indicates a handler already installed */
-
-                       if(handler_obj->address_space.space_id == space_id) {
-                               if (handler_obj->address_space.handler == handler) {
-                                       /*
-                                        * It is (relatively) OK to attempt to install the SAME
-                                        * handler twice. This can easily happen with PCI_Config space.
-                                        */
-                                       status = AE_SAME_HANDLER;
-                                       goto unlock_and_exit;
-                               }
-                               else {
-                                       /* A handler is already installed */
-
-                                       status = AE_ALREADY_EXISTS;
-                               }
-                               goto unlock_and_exit;
-                       }
-
-                       /* Walk the linked list of handlers */
-
-                       handler_obj = handler_obj->address_space.next;
-               }
-       }
-       else {
-               ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
-                       "Creating object on Device %p while installing handler\n", node));
-
-               /* obj_desc does not exist, create one */
-
-               if (node->type == ACPI_TYPE_ANY) {
-                       type = ACPI_TYPE_DEVICE;
-               }
-               else {
-                       type = node->type;
-               }
-
-               obj_desc = acpi_ut_create_internal_object (type);
-               if (!obj_desc) {
-                       status = AE_NO_MEMORY;
-                       goto unlock_and_exit;
-               }
-
-               /* Init new descriptor */
-
-               obj_desc->common.type = (u8) type;
-
-               /* Attach the new object to the Node */
+       /* Install the handler for all Regions for this Space ID */
 
-               status = acpi_ns_attach_object (node, obj_desc, type);
-
-               /* Remove local reference to the object */
-
-               acpi_ut_remove_reference (obj_desc);
-
-               if (ACPI_FAILURE (status)) {
-                       goto unlock_and_exit;
-               }
-       }
-
-       ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
-               "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
-               acpi_ut_get_region_name (space_id), space_id,
-               acpi_ut_get_node_name (node), node, obj_desc));
-
-       /*
-        * Install the handler
-        *
-        * At this point there is no existing handler.
-        * Just allocate the object for the handler and link it
-        * into the list.
-        */
-       handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
-       if (!handler_obj) {
-               status = AE_NO_MEMORY;
+       status = acpi_ev_install_space_handler (node, space_id, handler, setup, context);
+       if (ACPI_FAILURE (status)) {
                goto unlock_and_exit;
        }
 
-       /* Init handler obj */
-
-       handler_obj->address_space.space_id  = (u8) space_id;
-       handler_obj->address_space.hflags    = flags;
-       handler_obj->address_space.region_list = NULL;
-       handler_obj->address_space.node      = node;
-       handler_obj->address_space.handler   = handler;
-       handler_obj->address_space.context   = context;
-       handler_obj->address_space.setup     = setup;
-
-       /* Install at head of Device.address_space list */
-
-       handler_obj->address_space.next      = obj_desc->device.handler;
-
-       /*
-        * The Device object is the first reference on the handler_obj.
-        * Each region that uses the handler adds a reference.
-        */
-       obj_desc->device.handler = handler_obj;
-
-       /*
-        * Walk the namespace finding all of the regions this
-        * handler will manage.
-        *
-        * Start at the device and search the branch toward
-        * the leaf nodes until either the leaf is encountered or
-        * a device is detected that has an address handler of the
-        * same type.
-        *
-        * In either case, back up and search down the remainder
-        * of the branch
-        */
-       status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX,
-                         ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
-                         handler_obj, NULL);
-
-       /*
-        * Now we can run the _REG methods for all Regions for this
-        * space ID.  This is a separate walk in order to handle any
-        * interdependencies between regions and _REG methods.  (i.e. handlers
-        * must be installed for all regions of this Space ID before we
-        * can run any _REG methods.
-        */
-       status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX,
-                         ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
-                         handler_obj, NULL);
+       /* Run all _REG methods for this address space */
+
+       status = acpi_ev_execute_reg_methods (node, space_id);
 
 unlock_and_exit:
        (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
index dfe7e04..1e6a898 100644 (file)
@@ -48,6 +48,7 @@
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
 #include <acpi/actables.h>
+#include <acpi/acdispat.h>
 
 
 #define _COMPONENT          ACPI_EXECUTER
@@ -285,7 +286,7 @@ acpi_ex_load_op (
        union acpi_operand_object       *ddb_handle;
        union acpi_operand_object       *buffer_desc = NULL;
        struct acpi_table_header        *table_ptr = NULL;
-       u8                              *table_data_ptr;
+       acpi_physical_address           address;
        struct acpi_table_header        table_header;
        u32                             i;
 
@@ -300,18 +301,39 @@ acpi_ex_load_op (
                ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n",
                        obj_desc, acpi_ut_get_object_type_name (obj_desc)));
 
-               /* Get the table header */
+               /*
+                * If the Region Address and Length have not been previously evaluated,
+                * evaluate them now and save the results.
+                */
+               if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
+                       status = acpi_ds_get_region_arguments (obj_desc);
+                       if (ACPI_FAILURE (status)) {
+                               return_ACPI_STATUS (status);
+                       }
+               }
+
+               /* Get the base physical address of the region */
+
+               address = obj_desc->region.address;
+
+               /* Get the table length from the table header */
 
                table_header.length = 0;
-               for (i = 0; i < sizeof (struct acpi_table_header); i++) {
+               for (i = 0; i < 8; i++) {
                        status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
-                                          (acpi_physical_address) i, 8,
+                                          (acpi_physical_address) (i + address), 8,
                                           ((u8 *) &table_header) + i);
                        if (ACPI_FAILURE (status)) {
                                return_ACPI_STATUS (status);
                        }
                }
 
+               /* Sanity check the table length */
+
+               if (table_header.length < sizeof (struct acpi_table_header)) {
+                       return_ACPI_STATUS (AE_BAD_HEADER);
+               }
+
                /* Allocate a buffer for the entire table */
 
                table_ptr = ACPI_MEM_ALLOCATE (table_header.length);
@@ -319,17 +341,12 @@ acpi_ex_load_op (
                        return_ACPI_STATUS (AE_NO_MEMORY);
                }
 
-               /* Copy the header to the buffer */
-
-               ACPI_MEMCPY (table_ptr, &table_header, sizeof (struct acpi_table_header));
-               table_data_ptr = ACPI_PTR_ADD (u8, table_ptr, sizeof (struct acpi_table_header));
-
-               /* Get the table from the op region */
+               /* Get the entire table from the op region */
 
                for (i = 0; i < table_header.length; i++) {
                        status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
-                                          (acpi_physical_address) i, 8,
-                                          ((u8 *) table_data_ptr + i));
+                                          (acpi_physical_address) (i + address), 8,
+                                          ((u8 *) table_ptr + i));
                        if (ACPI_FAILURE (status)) {
                                goto cleanup;
                        }
@@ -355,6 +372,12 @@ acpi_ex_load_op (
                }
 
                table_ptr = ACPI_CAST_PTR (struct acpi_table_header, buffer_desc->buffer.pointer);
+
+                /* Sanity check the table length */
+
+               if (table_ptr->length < sizeof (struct acpi_table_header)) {
+                       return_ACPI_STATUS (AE_BAD_HEADER);
+               }
                break;
 
 
index 4ce49b9..03ccfb9 100644 (file)
@@ -130,6 +130,21 @@ acpi_ex_setup_region (
        if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset
                           + field_datum_byte_offset
                           + obj_desc->common_field.access_byte_width)) {
+               if (acpi_gbl_enable_interpreter_slack) {
+                       /*
+                        * Slack mode only:  We will go ahead and allow access to this
+                        * field if it is within the region length rounded up to the next
+                        * access width boundary.
+                        */
+                       if (ACPI_ROUND_UP (rgn_desc->region.length,
+                                          obj_desc->common_field.access_byte_width) >=
+                               (obj_desc->common_field.base_byte_offset +
+                                obj_desc->common_field.access_byte_width +
+                                field_datum_byte_offset)) {
+                               return_ACPI_STATUS (AE_OK);
+                       }
+               }
+
                if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) {
                        /*
                         * This is the case where the access_type (acc_word, etc.) is wider
@@ -154,40 +169,7 @@ acpi_ex_setup_region (
                        field_datum_byte_offset, obj_desc->common_field.access_byte_width,
                        acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
 
-               if (!acpi_strict) {
-                       /*
-                        * Allow access to the field if it is within the region size
-                        * rounded up to a multiple of the access byte width.  This
-                        * overcomes "off-by-one" programming errors in the AML often
-                        * found in Toshiba laptops.  These errors were allowed by
-                        * the Microsoft ASL compiler.
-                        */
-                       u32 rounded_length = ACPI_ROUND_UP(rgn_desc->region.length,
-                                                                       obj_desc->common_field.access_byte_width);
-
-                       if (rounded_length < (obj_desc->common_field.base_byte_offset
-                                               + field_datum_byte_offset
-                                               + obj_desc->common_field.access_byte_width)) {
-                               return_ACPI_STATUS (AE_AML_REGION_LIMIT);
-                       } else {
-                               static int      warn_once = 1;
-                               if (warn_once) {
-                                       // Could also associate a flag with each field, and
-                                       // warn once for each field.
-                                       ACPI_REPORT_WARNING((
-                                               "The ACPI AML in your computer contains errors, "
-                                               "please nag the manufacturer to correct it.\n"));
-                                       ACPI_REPORT_WARNING((
-                                               "Allowing relaxed access to fields; "
-                                               "turn on CONFIG_ACPI_DEBUG for details.\n"));
-                                       warn_once = 0;
-                               }
-                               return_ACPI_STATUS (AE_OK);
-                       }
-               }
-               else {
-                       return_ACPI_STATUS (AE_AML_REGION_LIMIT);
-               }
+               return_ACPI_STATUS (AE_AML_REGION_LIMIT);
        }
 
        return_ACPI_STATUS (AE_OK);
@@ -277,7 +259,7 @@ acpi_ex_access_region (
                                rgn_desc->region.space_id));
                }
                else if (status == AE_NOT_EXIST) {
-                       ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+                       ACPI_REPORT_ERROR ((
                                "Region %s(%X) has no handler\n",
                                acpi_ut_get_region_name (rgn_desc->region.space_id),
                                rgn_desc->region.space_id));
@@ -764,16 +746,85 @@ acpi_ex_set_buffer_datum (
 }
 
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_common_buffer_setup
+ *
+ * PARAMETERS:  obj_desc            - Field object
+ *              buffer_length       - Length of caller's buffer
+ *              datum_count         - Where the datum_count is returned
+ *
+ * RETURN:      Status, datum_count
+ *
+ * DESCRIPTION: Common code to validate the incoming buffer size and compute
+ *              the number of field "datums" that must be read or written.
+ *              A "datum" is the smallest unit that can be read or written
+ *              to the field, it is either 1,2,4, or 8 bytes.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ex_common_buffer_setup (
+       union acpi_operand_object       *obj_desc,
+       u32                             buffer_length,
+       u32                             *datum_count)
+{
+       u32                             byte_field_length;
+       u32                             actual_byte_field_length;
+
+
+       ACPI_FUNCTION_TRACE ("ex_common_buffer_setup");
+
+
+       /*
+        * Incoming buffer must be at least as long as the field, we do not
+        * allow "partial" field reads/writes.  We do not care if the buffer is
+        * larger than the field, this typically happens when an integer is
+        * read/written to a field that is actually smaller than an integer.
+        */
+       byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
+                        obj_desc->common_field.bit_length);
+       if (byte_field_length > buffer_length) {
+               ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+                       "Field size %X (bytes) is too large for buffer (%X)\n",
+                       byte_field_length, buffer_length));
+
+               return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
+       }
+
+       /*
+        * Create "actual" field byte count (minimum number of bytes that
+        * must be read), then convert to datum count (minimum number
+        * of datum-sized units that must be read)
+        */
+       actual_byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
+                         obj_desc->common_field.start_field_bit_offset +
+                         obj_desc->common_field.bit_length);
+
+
+       *datum_count = ACPI_ROUND_UP_TO (actual_byte_field_length,
+                          obj_desc->common_field.access_byte_width);
+
+       ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+               "buffer_bytes %X, actual_bytes %X, Datums %X, byte_gran %X\n",
+               byte_field_length, actual_byte_field_length,
+               *datum_count, obj_desc->common_field.access_byte_width));
+
+       return_ACPI_STATUS (AE_OK);
+}
+
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ex_extract_from_field
  *
- * PARAMETERS:  *obj_desc           - Field to be read
- *              *Value              - Where to store value
+ * PARAMETERS:  obj_desc            - Field to be read
+ *              Buffer              - Where to store the field data
+ *              buffer_length       - Length of Buffer
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Retrieve the value of the given field
+ * DESCRIPTION: Retrieve the current value of the given field
  *
  ******************************************************************************/
 
@@ -789,7 +840,6 @@ acpi_ex_extract_from_field (
        acpi_integer                    previous_raw_datum = 0;
        acpi_integer                    this_raw_datum = 0;
        acpi_integer                    merged_datum = 0;
-       u32                             byte_field_length;
        u32                             datum_count;
        u32                             i;
 
@@ -797,39 +847,13 @@ acpi_ex_extract_from_field (
        ACPI_FUNCTION_TRACE ("ex_extract_from_field");
 
 
-       /*
-        * The field must fit within the caller's buffer
-        */
-       byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);
-       if (byte_field_length > buffer_length) {
-               ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-                       "Field size %X (bytes) too large for buffer (%X)\n",
-                       byte_field_length, buffer_length));
-
-               return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
-       }
-
-       /* Convert field byte count to datum count, round up if necessary */
-
-       datum_count = ACPI_ROUND_UP_TO (byte_field_length,
-                          obj_desc->common_field.access_byte_width);
+       /* Validate buffer, compute number of datums */
 
-       /*
-        * If the field is not aligned on a datum boundary and does not
-        * fit within a single datum, we must read an extra datum.
-        *
-        * We could just split the aligned and non-aligned cases since the
-        * aligned case is so very simple, but this would require more code.
-        */
-       if ((obj_desc->common_field.end_field_valid_bits != 0)    &&
-               (!(obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM))) {
-               datum_count++;
+       status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
        }
 
-       ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-               "byte_len %X, datum_len %X, byte_gran %X\n",
-               byte_field_length, datum_count,obj_desc->common_field.access_byte_width));
-
        /*
         * Clear the caller's buffer (the whole buffer length as given)
         * This is very important, especially in the cases where the buffer
@@ -942,12 +966,13 @@ acpi_ex_extract_from_field (
  *
  * FUNCTION:    acpi_ex_insert_into_field
  *
- * PARAMETERS:  *obj_desc           - Field to be set
- *              Buffer              - Value to store
+ * PARAMETERS:  obj_desc            - Field to be written
+ *              Buffer              - Data to be written
+ *              buffer_length       - Length of Buffer
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Store the value into the given field
+ * DESCRIPTION: Store the Buffer contents into the given field
  *
  ******************************************************************************/
 
@@ -964,42 +989,19 @@ acpi_ex_insert_into_field (
        acpi_integer                    merged_datum;
        acpi_integer                    previous_raw_datum;
        acpi_integer                    this_raw_datum;
-       u32                             byte_field_length;
        u32                             datum_count;
 
 
        ACPI_FUNCTION_TRACE ("ex_insert_into_field");
 
 
-       /*
-        * Incoming buffer must be at least as long as the field, we do not
-        * allow "partial" field writes.  We do not care if the buffer is
-        * larger than the field, this typically happens when an integer is
-        * written to a field that is actually smaller than an integer.
-        */
-       byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
-                        obj_desc->common_field.bit_length);
-       if (buffer_length < byte_field_length) {
-               ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-                       "Buffer length %X too small for field %X\n",
-                       buffer_length, byte_field_length));
+       /* Validate buffer, compute number of datums */
 
-               return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
+       status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
        }
 
-       byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
-                        obj_desc->common_field.start_field_bit_offset +
-                        obj_desc->common_field.bit_length);
-
-       /* Convert byte count to datum count, round up if necessary */
-
-       datum_count = ACPI_ROUND_UP_TO (byte_field_length,
-                         obj_desc->common_field.access_byte_width);
-
-       ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-               "Bytes %X, Datums %X, byte_gran %X\n",
-               byte_field_length, datum_count, obj_desc->common_field.access_byte_width));
-
        /*
         * Break the request into up to three parts (similar to an I/O request):
         * 1) non-aligned part at start
index 74fd684..961a949 100644 (file)
@@ -389,6 +389,8 @@ acpi_ex_do_math_op (
        acpi_integer                    operand1)
 {
 
+       ACPI_FUNCTION_ENTRY ();
+
 
        switch (opcode) {
        case AML_ADD_OP:                /* Add (Operand0, Operand1, Result) */
@@ -452,15 +454,17 @@ acpi_ex_do_math_op (
  * FUNCTION:    acpi_ex_do_logical_op
  *
  * PARAMETERS:  Opcode              - AML opcode
- *              Operand0            - Integer operand #0
- *              Operand1            - Integer operand #1
+ *              obj_desc0           - operand #0
+ *              obj_desc1           - operand #1
  *
  * RETURN:      TRUE/FALSE result of the operation
  *
  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
  *              functions here is to prevent a lot of pointer dereferencing
  *              to obtain the operands and to simplify the generation of the
- *              logical value.
+ *              logical value.  Both operands must already be validated as
+ *              1) Both the same type, and
+ *              2) Either Integer, Buffer, or String type.
  *
  *              Note: cleanest machine code seems to be produced by the code
  *              below, rather than using statements of the form:
@@ -471,54 +475,137 @@ acpi_ex_do_math_op (
 u8
 acpi_ex_do_logical_op (
        u16                             opcode,
-       acpi_integer                    operand0,
-       acpi_integer                    operand1)
+       union acpi_operand_object       *obj_desc0,
+       union acpi_operand_object       *obj_desc1)
 {
+       acpi_integer                    operand0;
+       acpi_integer                    operand1;
+       u8                              *ptr0;
+       u8                              *ptr1;
+       u32                             length0;
+       u32                             length1;
+       u32                             i;
 
 
-       switch (opcode) {
+       ACPI_FUNCTION_ENTRY ();
 
-       case AML_LAND_OP:               /* LAnd (Operand0, Operand1) */
 
-               if (operand0 && operand1) {
-                       return (TRUE);
-               }
-               break;
+       if (ACPI_GET_OBJECT_TYPE (obj_desc0) == ACPI_TYPE_INTEGER) {
+               /* Both operands are of type integer */
 
+               operand0 = obj_desc0->integer.value;
+               operand1 = obj_desc1->integer.value;
 
-       case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
+               switch (opcode) {
+               case AML_LAND_OP:               /* LAnd (Operand0, Operand1) */
 
-               if (operand0 == operand1) {
-                       return (TRUE);
-               }
-               break;
+                       if (operand0 && operand1) {
+                               return (TRUE);
+                       }
+                       break;
 
+               case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
 
-       case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
+                       if (operand0 == operand1) {
+                               return (TRUE);
+                       }
+                       break;
 
-               if (operand0 > operand1) {
-                       return (TRUE);
-               }
-               break;
+               case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
+
+                       if (operand0 > operand1) {
+                               return (TRUE);
+                       }
+                       break;
+
+               case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
 
+                       if (operand0 < operand1) {
+                               return (TRUE);
+                       }
+                       break;
 
-       case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
+               case AML_LOR_OP:                 /* LOr (Operand0, Operand1) */
 
-               if (operand0 < operand1) {
-                       return (TRUE);
+                       if (operand0 || operand1) {
+                               return (TRUE);
+                       }
+                       break;
+
+               default:
+                       break;
                }
-               break;
+       }
+       else {
+               /*
+                * Case for Buffer/String objects.
+                * NOTE: takes advantage of common Buffer/String object fields
+                */
+               length0 = obj_desc0->buffer.length;
+               ptr0    = obj_desc0->buffer.pointer;
+
+               length1 = obj_desc1->buffer.length;
+               ptr1    = obj_desc1->buffer.pointer;
+
+               switch (opcode) {
+               case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
 
+                       /* Length and all bytes must be equal */
 
-       case AML_LOR_OP:                 /* LOr (Operand0, Operand1) */
+                       if (length0 != length1) {
+                               return (FALSE);
+                       }
 
-               if (operand0 || operand1) {
+                       for (i = 0; i < length0; i++) {
+                               if (ptr0[i] != ptr1[i]) {
+                                       return (FALSE);
+                               }
+                       }
                        return (TRUE);
-               }
-               break;
 
-       default:
-               break;
+               case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
+
+                       /* Lexicographic compare:  Scan the 1-to-1 data */
+
+                       for (i = 0; (i < length0) && (i < length1); i++) {
+                               if (ptr0[i] > ptr1[i]) {
+                                       return (TRUE);
+                               }
+                       }
+
+                       /* Bytes match, now check lengths */
+
+                       if (length0 > length1) {
+                               return (TRUE);
+                       }
+
+                       /* Length0 <= Length1 */
+
+                       return (FALSE);
+
+               case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
+
+                       /* Lexicographic compare:  Scan the 1-to-1 data */
+
+                       for (i = 0; (i < length0) && (i < length1); i++) {
+                               if (ptr0[i] < ptr1[i]) {
+                                       return (TRUE);
+                               }
+                       }
+
+                       /* Bytes match, now check lengths */
+
+                       if (length0 < length1) {
+                               return (TRUE);
+                       }
+
+                       /* Length0 >= Length1 */
+
+                       return (FALSE);
+
+               default:
+                       break;
+               }
        }
 
        return (FALSE);
index cee2c12..c709ed2 100644 (file)
@@ -54,7 +54,7 @@
  *
  * FUNCTION:    acpi_ex_unlink_mutex
  *
- * PARAMETERS:  *obj_desc           - The mutex to be unlinked
+ * PARAMETERS:  obj_desc            - The mutex to be unlinked
  *
  * RETURN:      Status
  *
@@ -73,6 +73,8 @@ acpi_ex_unlink_mutex (
                return;
        }
 
+       /* Doubly linked list */
+
        if (obj_desc->mutex.next) {
                (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev;
        }
@@ -90,8 +92,8 @@ acpi_ex_unlink_mutex (
  *
  * FUNCTION:    acpi_ex_link_mutex
  *
- * PARAMETERS:  *obj_desc           - The mutex to be linked
- *              *list_head          - head of the "acquired_mutex" list
+ * PARAMETERS:  obj_desc            - The mutex to be linked
+ *              list_head           - head of the "acquired_mutex" list
  *
  * RETURN:      Status
  *
@@ -130,8 +132,8 @@ acpi_ex_link_mutex (
  *
  * FUNCTION:    acpi_ex_acquire_mutex
  *
- * PARAMETERS:  *time_desc          - The 'time to delay' object descriptor
- *              *obj_desc           - The object descriptor for this op
+ * PARAMETERS:  time_desc           - The 'time to delay' object descriptor
+ *              obj_desc            - The object descriptor for this op
  *
  * RETURN:      Status
  *
@@ -173,9 +175,8 @@ acpi_ex_acquire_mutex (
                return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
        }
 
-       /*
-        * Support for multiple acquires by the owning thread
-        */
+       /* Support for multiple acquires by the owning thread */
+
        if (obj_desc->mutex.owner_thread) {
                /* Special case for Global Lock, allow all threads */
 
@@ -199,10 +200,11 @@ acpi_ex_acquire_mutex (
                return_ACPI_STATUS (status);
        }
 
-       /* Have the mutex, update mutex and walk info */
+       /* Have the mutex: update mutex and walk info and save the sync_level */
 
-       obj_desc->mutex.owner_thread    = walk_state->thread;
+       obj_desc->mutex.owner_thread     = walk_state->thread;
        obj_desc->mutex.acquisition_depth = 1;
+       obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level;
 
        walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
 
@@ -218,7 +220,7 @@ acpi_ex_acquire_mutex (
  *
  * FUNCTION:    acpi_ex_release_mutex
  *
- * PARAMETERS:  *obj_desc           - The object descriptor for this op
+ * PARAMETERS:  obj_desc            - The object descriptor for this op
  *
  * RETURN:      Status
  *
@@ -281,9 +283,8 @@ acpi_ex_release_mutex (
                return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
        }
 
-       /*
-        * Match multiple Acquires with multiple Releases
-        */
+       /* Match multiple Acquires with multiple Releases */
+
        obj_desc->mutex.acquisition_depth--;
        if (obj_desc->mutex.acquisition_depth != 0) {
                /* Just decrement the depth and return */
@@ -299,10 +300,10 @@ acpi_ex_release_mutex (
 
        status = acpi_ex_system_release_mutex (obj_desc);
 
-       /* Update the mutex and walk state */
+       /* Update the mutex and walk state, restore sync_level before acquire */
 
        obj_desc->mutex.owner_thread = NULL;
-       walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
+       walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level;
 
        return_ACPI_STATUS (status);
 }
@@ -312,7 +313,7 @@ acpi_ex_release_mutex (
  *
  * FUNCTION:    acpi_ex_release_all_mutexes
  *
- * PARAMETERS:  *mutex_list           - Head of the mutex list
+ * PARAMETERS:  mutex_list            - Head of the mutex list
  *
  * RETURN:      Status
  *
@@ -332,9 +333,8 @@ acpi_ex_release_all_mutexes (
        ACPI_FUNCTION_ENTRY ();
 
 
-       /*
-        * Traverse the list of owned mutexes, releasing each one.
-        */
+       /* Traverse the list of owned mutexes, releasing each one */
+
        while (next) {
                this = next;
                next = this->mutex.next;
@@ -352,7 +352,11 @@ acpi_ex_release_all_mutexes (
 
                /* Mark mutex unowned */
 
-               this->mutex.owner_thread     = NULL;
+               this->mutex.owner_thread = NULL;
+
+               /* Update Thread sync_level (Last mutex is the important one) */
+
+               thread->current_sync_level = this->mutex.original_sync_level;
        }
 }
 
index 70602ad..0b6f86a 100644 (file)
@@ -97,6 +97,7 @@ acpi_ex_opcode_2A_0T_0R (
 {
        union acpi_operand_object       **operand = &walk_state->operands[0];
        struct acpi_namespace_node      *node;
+       u32                             value;
        acpi_status                     status = AE_OK;
 
 
@@ -113,16 +114,46 @@ acpi_ex_opcode_2A_0T_0R (
 
                node = (struct acpi_namespace_node *) operand[0];
 
+               /* Second value is the notify value */
+
+               value = (u32) operand[1]->integer.value;
+
                /* Notifies allowed on this object? */
 
                if (!acpi_ev_is_notify_object (node)) {
-                       ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type [%s]\n",
+                       ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+                                       "Unexpected notify object type [%s]\n",
                                        acpi_ut_get_type_name (node->type)));
 
                        status = AE_AML_OPERAND_TYPE;
                        break;
                }
 
+#ifdef ACPI_GPE_NOTIFY_CHECK
+               /*
+                * GPE method wake/notify check.  Here, we want to ensure that we
+                * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx
+                * GPE method during system runtime.  If we do, the GPE is marked
+                * as "wake-only" and disabled.
+                *
+                * 1) Is the Notify() value == device_wake?
+                * 2) Is this a GPE deferred method?  (An _Lxx or _Exx method)
+                * 3) Did the original GPE happen at system runtime?
+                *    (versus during wake)
+                *
+                * If all three cases are true, this is a wake-only GPE that should
+                * be disabled at runtime.
+                */
+               if (value == 2)     /* device_wake */ {
+                       status = acpi_ev_check_for_wake_only_gpe (walk_state->gpe_event_info);
+                       if (ACPI_FAILURE (status)) {
+                               /* AE_WAKE_ONLY_GPE only error, means ignore this notify */
+
+                               return_ACPI_STATUS (AE_OK)
+                       }
+               }
+#endif
+
                /*
                 * Dispatch the notify to the appropriate handler
                 * NOTE: the request is queued for execution after this method
@@ -130,8 +161,7 @@ acpi_ex_opcode_2A_0T_0R (
                 * from this thread -- because handlers may in turn run other
                 * control methods.
                 */
-               status = acpi_ev_queue_notify_request (node,
-                                 (u32) operand[1]->integer.value);
+               status = acpi_ev_queue_notify_request (node, value);
                break;
 
 
@@ -543,9 +573,17 @@ acpi_ex_opcode_2A_0T_1R (
         * Execute the Opcode
         */
        if (walk_state->op_info->flags & AML_LOGICAL) /* logical_op (Operand0, Operand1) */ {
+               /* Both operands must be of the same type */
+
+               if (ACPI_GET_OBJECT_TYPE (operand[0]) !=
+                       ACPI_GET_OBJECT_TYPE (operand[1])) {
+                       status = AE_AML_OPERAND_TYPE;
+                       goto cleanup;
+               }
+
                logical_result = acpi_ex_do_logical_op (walk_state->opcode,
-                                operand[0]->integer.value,
-                                operand[1]->integer.value);
+                                operand[0],
+                                operand[1]);
                goto store_logical_result;
        }
 
index e998da7..504d53f 100644 (file)
@@ -187,15 +187,15 @@ acpi_ex_resolve_object_to_value (
                                return_ACPI_STATUS (status);
                        }
 
+                       ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] value_obj is %p\n",
+                               stack_desc->reference.offset, obj_desc));
+
                        /*
                         * Now we can delete the original Reference Object and
-                        * replace it with the resolve value
+                        * replace it with the resolved value
                         */
                        acpi_ut_remove_reference (stack_desc);
                        *stack_ptr = obj_desc;
-
-                       ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %d] value_obj is %p\n",
-                               stack_desc->reference.offset, obj_desc));
                        break;
 
 
index 8c88465..25464f7 100644 (file)
@@ -102,7 +102,8 @@ acpi_ex_store (
                 * Storing an object into a Named node.
                 */
                status = acpi_ex_store_object_to_node (source_desc,
-                                (struct acpi_namespace_node *) dest_desc, walk_state);
+                                (struct acpi_namespace_node *) dest_desc, walk_state,
+                                ACPI_IMPLICIT_CONVERSION);
 
                return_ACPI_STATUS (status);
        }
@@ -153,7 +154,7 @@ acpi_ex_store (
                /* Storing an object into a Name "container" */
 
                status = acpi_ex_store_object_to_node (source_desc, ref_desc->reference.object,
-                                 walk_state);
+                                 walk_state, ACPI_IMPLICIT_CONVERSION);
                break;
 
 
@@ -399,6 +400,7 @@ acpi_ex_store_object_to_index (
  * PARAMETERS:  source_desc             - Value to be stored
  *              Node                    - Named object to receive the value
  *              walk_state              - Current walk state
+ *              implicit_conversion     - Perform implicit conversion (yes/no)
  *
  * RETURN:      Status
  *
@@ -421,7 +423,8 @@ acpi_status
 acpi_ex_store_object_to_node (
        union acpi_operand_object       *source_desc,
        struct acpi_namespace_node      *node,
-       struct acpi_walk_state          *walk_state)
+       struct acpi_walk_state          *walk_state,
+       u8                              implicit_conversion)
 {
        acpi_status                     status = AE_OK;
        union acpi_operand_object       *target_desc;
@@ -451,6 +454,14 @@ acpi_ex_store_object_to_node (
                return_ACPI_STATUS (status);
        }
 
+       /* If no implicit conversion, drop into the default case below */
+
+       if (!implicit_conversion) {
+               /* Force execution of default (no implicit conversion) */
+
+               target_type = ACPI_TYPE_ANY;
+       }
+
        /*
         * Do the actual store operation
         */
index f3fddc2..3910b5e 100644 (file)
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_enable_gpe
+ * FUNCTION:    acpi_hw_write_gpe_enable_reg
  *
  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be enabled
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Enable a single GPE.
+ * DESCRIPTION: Write a GPE enable register.  Note: The bit for this GPE must
+ *              already be cleared or set in the parent register
+ *              enable_for_run mask.
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_enable_gpe (
-       struct acpi_gpe_event_info      *gpe_event_info)
-{
-       u32                             in_byte;
-       acpi_status                     status;
-
-
-       ACPI_FUNCTION_ENTRY ();
-
-
-       /*
-        * Read the current value of the register, set the appropriate bit
-        * to enable the GPE, and write out the new register.
-        */
-       status = acpi_hw_low_level_read (8, &in_byte,
-                         &gpe_event_info->register_info->enable_address);
-       if (ACPI_FAILURE (status)) {
-               return (status);
-       }
-
-       /* Write with the new GPE bit enabled */
-
-       status = acpi_hw_low_level_write (8, (in_byte | gpe_event_info->bit_mask),
-                         &gpe_event_info->register_info->enable_address);
-
-       return (status);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_hw_enable_gpe_for_wakeup
- *
- * PARAMETERS:  gpe_event_info      - Info block for the GPE to be enabled
- *
- * RETURN:      None
- *
- * DESCRIPTION: Keep track of which GPEs the OS has requested not be
- *              disabled when going to sleep.
- *
- ******************************************************************************/
-
-void
-acpi_hw_enable_gpe_for_wakeup (
+acpi_hw_write_gpe_enable_reg (
        struct acpi_gpe_event_info      *gpe_event_info)
 {
        struct acpi_gpe_register_info   *gpe_register_info;
-
-
-       ACPI_FUNCTION_ENTRY ();
-
-
-       /* Get the info block for the entire GPE register */
-
-       gpe_register_info = gpe_event_info->register_info;
-       if (!gpe_register_info) {
-               return;
-       }
-
-       /*
-        * Set the bit so we will not enable this GPE when sleeping (and disable
-        * it upon wake)
-        */
-       gpe_register_info->wake_enable |= gpe_event_info->bit_mask;
-       gpe_event_info->flags |= (ACPI_GPE_TYPE_WAKE | ACPI_GPE_ENABLED);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_hw_disable_gpe
- *
- * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Disable a single GPE.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_hw_disable_gpe (
-       struct acpi_gpe_event_info      *gpe_event_info)
-{
-       u32                             in_byte;
        acpi_status                     status;
-       struct acpi_gpe_register_info   *gpe_register_info;
 
 
        ACPI_FUNCTION_ENTRY ();
@@ -158,67 +78,15 @@ acpi_hw_disable_gpe (
 
        gpe_register_info = gpe_event_info->register_info;
        if (!gpe_register_info) {
-               return (AE_BAD_PARAMETER);
-       }
-
-       /*
-        * Read the current value of the register, clear the appropriate bit,
-        * and write out the new register value to disable the GPE.
-        */
-       status = acpi_hw_low_level_read (8, &in_byte,
-                         &gpe_register_info->enable_address);
-       if (ACPI_FAILURE (status)) {
-               return (status);
+               return (AE_NOT_EXIST);
        }
 
-       /* Write the byte with this GPE bit cleared */
+       /* Write the entire GPE (runtime) enable register */
 
-       status = acpi_hw_low_level_write (8, (in_byte & ~(gpe_event_info->bit_mask)),
+       status = acpi_hw_low_level_write (8, gpe_register_info->enable_for_run,
                          &gpe_register_info->enable_address);
-       if (ACPI_FAILURE (status)) {
-               return (status);
-       }
-
-       /* Make sure this GPE is disabled for wake, also */
-
-       acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
-       return (AE_OK);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_hw_disable_gpe_for_wakeup
- *
- * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
- *
- * RETURN:      None
- *
- * DESCRIPTION: Keep track of which GPEs the OS has requested not be
- *              disabled when going to sleep.
- *
- ******************************************************************************/
 
-void
-acpi_hw_disable_gpe_for_wakeup (
-       struct acpi_gpe_event_info      *gpe_event_info)
-{
-       struct acpi_gpe_register_info   *gpe_register_info;
-
-
-       ACPI_FUNCTION_ENTRY ();
-
-
-       /* Get the info block for the entire GPE register */
-
-       gpe_register_info = gpe_event_info->register_info;
-       if (!gpe_register_info) {
-               return;
-       }
-
-       /* Clear the bit so we will disable this when sleeping */
-
-       gpe_register_info->wake_enable &= ~(gpe_event_info->bit_mask);
+       return (status);
 }
 
 
@@ -228,7 +96,7 @@ acpi_hw_disable_gpe_for_wakeup (
  *
  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
  *
- * RETURN:      status_status
+ * RETURN:      Status
  *
  * DESCRIPTION: Clear the status bit for a single GPE.
  *
@@ -248,7 +116,7 @@ acpi_hw_clear_gpe (
         * Write a one to the appropriate bit in the status register to
         * clear this GPE.
         */
-       status = acpi_hw_low_level_write (8, gpe_event_info->bit_mask,
+       status = acpi_hw_low_level_write (8, gpe_event_info->register_bit,
                          &gpe_event_info->register_info->status_address);
 
        return (status);
@@ -274,7 +142,7 @@ acpi_hw_get_gpe_status (
        acpi_event_status               *event_status)
 {
        u32                             in_byte;
-       u8                              bit_mask;
+       u8                              register_bit;
        struct acpi_gpe_register_info   *gpe_register_info;
        acpi_status                     status;
        acpi_event_status               local_event_status = 0;
@@ -293,33 +161,28 @@ acpi_hw_get_gpe_status (
 
        /* Get the register bitmask for this GPE */
 
-       bit_mask = gpe_event_info->bit_mask;
-
-       /* GPE Enabled? */
+       register_bit = gpe_event_info->register_bit;
 
-       status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address);
-       if (ACPI_FAILURE (status)) {
-               goto unlock_and_exit;
-       }
+       /* GPE currently enabled? (enabled for runtime?) */
 
-       if (bit_mask & in_byte) {
+       if (register_bit & gpe_register_info->enable_for_run) {
                local_event_status |= ACPI_EVENT_FLAG_ENABLED;
        }
 
-       /* GPE Enabled for wake? */
+       /* GPE enabled for wake? */
 
-       if (bit_mask & gpe_register_info->wake_enable) {
+       if (register_bit & gpe_register_info->enable_for_wake) {
                local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
        }
 
-       /* GPE active (set)? */
+       /* GPE currently active (status bit == 1)? */
 
        status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address);
        if (ACPI_FAILURE (status)) {
                goto unlock_and_exit;
        }
 
-       if (bit_mask & in_byte) {
+       if (register_bit & in_byte) {
                local_event_status |= ACPI_EVENT_FLAG_SET;
        }
 
@@ -411,64 +274,43 @@ acpi_hw_clear_gpe_block (
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_prepare_gpe_block_for_sleep
+ * FUNCTION:    acpi_hw_enable_runtime_gpe_block
  *
  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
  *              gpe_block           - Gpe Block info
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Disable all runtime GPEs and enable all wakeup GPEs -- within
- *              a single GPE block
+ * DESCRIPTION: Enable all "runtime" GPEs within a GPE block. (Includes
+ *              combination wake/run GPEs.)
  *
  ******************************************************************************/
 
-static acpi_status
-acpi_hw_prepare_gpe_block_for_sleep (
+acpi_status
+acpi_hw_enable_runtime_gpe_block (
        struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
        struct acpi_gpe_block_info      *gpe_block)
 {
        u32                             i;
-       struct acpi_gpe_register_info   *gpe_register_info;
-       u32                             in_value;
        acpi_status                     status;
 
 
-       /* Get the register info for the entire GPE block */
-
-       gpe_register_info = gpe_block->register_info;
+       /* NOTE: assumes that all GPEs are currently disabled */
 
        /* Examine each GPE Register within the block */
 
        for (i = 0; i < gpe_block->register_count; i++) {
-               /*
-                * Read the enabled/disabled status of all GPEs. We
-                * will be using it to restore all the GPEs later.
-                *
-                * NOTE:  Wake GPEs are are ALL disabled at this time, so when we wake
-                * and restore this register, they will be automatically disabled.
-                */
-               status = acpi_hw_low_level_read (8, &in_value,
-                                &gpe_register_info->enable_address);
-               if (ACPI_FAILURE (status)) {
-                       return (status);
+               if (!gpe_block->register_info[i].enable_for_run) {
+                       continue;
                }
 
-               gpe_register_info->enable = (u8) in_value;
+               /* Enable all "runtime" GPEs in this register */
 
-               /*
-                * 1) Disable all runtime GPEs
-                * 2) Enable all wakeup GPEs
-                */
-               status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable,
-                               &gpe_register_info->enable_address);
+               status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_run,
+                                &gpe_block->register_info[i].enable_address);
                if (ACPI_FAILURE (status)) {
                        return (status);
                }
-
-               /* Point to next GPE register */
-
-               gpe_register_info++;
        }
 
        return (AE_OK);
@@ -477,122 +319,125 @@ acpi_hw_prepare_gpe_block_for_sleep (
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_prepare_gpes_for_sleep
+ * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
  *
- * PARAMETERS:  None
+ * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
+ *              gpe_block           - Gpe Block info
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Disable all runtime GPEs, enable all wake GPEs.
- *              Called with interrupts disabled. The interrupt handler also
- *              modifies gpe_register_info->Enable, so it should not be
- *              given the chance to run until after the runtime GPEs are
- *              re-enabled.
+ * DESCRIPTION: Enable all "wake" GPEs within a GPE block.  (Includes
+ *              combination wake/run GPEs.)
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_prepare_gpes_for_sleep (
-       void)
+acpi_hw_enable_wakeup_gpe_block (
+       struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+       struct acpi_gpe_block_info      *gpe_block)
 {
+       u32                             i;
        acpi_status                     status;
 
 
-       ACPI_FUNCTION_ENTRY ();
+       /* Examine each GPE Register within the block */
 
+       for (i = 0; i < gpe_block->register_count; i++) {
+               if (!gpe_block->register_info[i].enable_for_wake) {
+                       continue;
+               }
 
-       status = acpi_ev_walk_gpe_list (acpi_hw_prepare_gpe_block_for_sleep);
-       return (status);
+               /* Enable all "wake" GPEs in this register */
+
+               status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_wake,
+                                &gpe_block->register_info[i].enable_address);
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+       }
+
+       return (AE_OK);
 }
 
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_restore_gpe_block_on_wake
+ * FUNCTION:    acpi_hw_disable_all_gpes
  *
- * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
- *              gpe_block           - Gpe Block info
+ * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in one
- *              GPE block
+ * DESCRIPTION: Disable and clear all GPEs
  *
  ******************************************************************************/
 
-static acpi_status
-acpi_hw_restore_gpe_block_on_wake (
-       struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
-       struct acpi_gpe_block_info      *gpe_block)
+acpi_status
+acpi_hw_disable_all_gpes (
+       u32                             flags)
 {
-       u32                             i;
-       struct acpi_gpe_register_info   *gpe_register_info;
        acpi_status                     status;
 
 
-       /* This callback processes one entire GPE block */
+       ACPI_FUNCTION_TRACE ("hw_disable_all_gpes");
 
-       /* Get the register info for the entire GPE block */
 
-       gpe_register_info = gpe_block->register_info;
+       status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, flags);
+       status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, flags);
+       return_ACPI_STATUS (status);
+}
 
-       /* Examine each GPE register within the block */
 
-       for (i = 0; i < gpe_block->register_count; i++) {
-               /* Clear the entire status register */
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_enable_all_runtime_gpes
+ *
+ * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Enable all GPEs of the given type
+ *
+ ******************************************************************************/
 
-               status = acpi_hw_low_level_write (8, 0xFF,
-                                &gpe_block->register_info[i].status_address);
-               if (ACPI_FAILURE (status)) {
-                       return (status);
-               }
+acpi_status
+acpi_hw_enable_all_runtime_gpes (
+       u32                             flags)
+{
+       acpi_status                     status;
 
-               /*
-                * Restore the GPE Enable register, which will do the following:
-                *
-                * 1) Disable all wakeup GPEs
-                * 2) Enable all runtime GPEs
-                *
-                *  (On sleep, we saved the enabled status of all GPEs)
-                */
-               status = acpi_hw_low_level_write (8, gpe_register_info->enable,
-                                &gpe_register_info->enable_address);
-               if (ACPI_FAILURE (status)) {
-                       return (status);
-               }
 
-               /* Point to next GPE register */
+       ACPI_FUNCTION_TRACE ("hw_enable_all_runtime_gpes");
 
-               gpe_register_info++;
-       }
 
-       return (AE_OK);
+       status = acpi_ev_walk_gpe_list (acpi_hw_enable_runtime_gpe_block, flags);
+       return_ACPI_STATUS (status);
 }
 
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_restore_gpes_on_wake
+ * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
  *
- * PARAMETERS:  None
+ * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in all
- *              GPE blocks
+ * DESCRIPTION: Enable all GPEs of the given type
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_restore_gpes_on_wake (
-       void)
+acpi_hw_enable_all_wakeup_gpes (
+       u32                             flags)
 {
        acpi_status                     status;
 
 
-       ACPI_FUNCTION_ENTRY ();
+       ACPI_FUNCTION_TRACE ("hw_enable_all_wakeup_gpes");
 
 
-       status = acpi_ev_walk_gpe_list (acpi_hw_restore_gpe_block_on_wake);
-       return (status);
+       status = acpi_ev_walk_gpe_list (acpi_hw_enable_wakeup_gpe_block, flags);
+       return_ACPI_STATUS (status);
 }
+
index a7c6513..cb998fe 100644 (file)
@@ -61,6 +61,7 @@
  * RETURN:      none
  *
  * DESCRIPTION: Clears all fixed and general purpose status bits
+ *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
 
@@ -103,7 +104,7 @@ acpi_hw_clear_acpi_status (
 
        /* Clear the GPE Bits in all GPE registers in all GPE blocks */
 
-       status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block);
+       status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, ACPI_ISR);
 
 unlock_and_exit:
        if (flags & ACPI_MTX_LOCK) {
@@ -135,7 +136,7 @@ acpi_get_sleep_type_data (
        u8                              *sleep_type_b)
 {
        acpi_status                     status = AE_OK;
-       union acpi_operand_object       *obj_desc;
+       struct acpi_parameter_info      info;
 
 
        ACPI_FUNCTION_TRACE ("acpi_get_sleep_type_data");
@@ -152,8 +153,9 @@ acpi_get_sleep_type_data (
        /*
         * Evaluate the namespace object containing the values for this state
         */
+       info.parameters = NULL;
        status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_sleep_state_names[sleep_state],
-                         NULL, &obj_desc);
+                         &info);
        if (ACPI_FAILURE (status)) {
                ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating sleep_state [%s]\n",
                        acpi_format_exception (status), acpi_gbl_sleep_state_names[sleep_state]));
@@ -163,48 +165,50 @@ acpi_get_sleep_type_data (
 
        /* Must have a return object */
 
-       if (!obj_desc) {
+       if (!info.return_object) {
                ACPI_REPORT_ERROR (("Missing Sleep State object\n"));
                status = AE_NOT_EXIST;
        }
 
        /* It must be of type Package */
 
-       else if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_PACKAGE) {
+       else if (ACPI_GET_OBJECT_TYPE (info.return_object) != ACPI_TYPE_PACKAGE) {
                ACPI_REPORT_ERROR (("Sleep State object not a Package\n"));
                status = AE_AML_OPERAND_TYPE;
        }
 
        /* The package must have at least two elements */
 
-       else if (obj_desc->package.count < 2) {
+       else if (info.return_object->package.count < 2) {
                ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
                status = AE_AML_NO_OPERAND;
        }
 
        /* The first two elements must both be of type Integer */
 
-       else if ((ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_INTEGER) ||
-                        (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) {
+       else if ((ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[0]) != ACPI_TYPE_INTEGER) ||
+                        (ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[1]) != ACPI_TYPE_INTEGER)) {
                ACPI_REPORT_ERROR (("Sleep State package elements are not both Integers (%s, %s)\n",
-                       acpi_ut_get_object_type_name (obj_desc->package.elements[0]),
-                       acpi_ut_get_object_type_name (obj_desc->package.elements[1])));
+                       acpi_ut_get_object_type_name (info.return_object->package.elements[0]),
+                       acpi_ut_get_object_type_name (info.return_object->package.elements[1])));
                status = AE_AML_OPERAND_TYPE;
        }
        else {
                /*
                 * Valid _Sx_ package size, type, and value
                 */
-               *sleep_type_a = (u8) (obj_desc->package.elements[0])->integer.value;
-               *sleep_type_b = (u8) (obj_desc->package.elements[1])->integer.value;
+               *sleep_type_a = (u8) (info.return_object->package.elements[0])->integer.value;
+               *sleep_type_b = (u8) (info.return_object->package.elements[1])->integer.value;
        }
 
        if (ACPI_FAILURE (status)) {
-               ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
-                       acpi_gbl_sleep_state_names[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+               ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+                       "While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
+                       acpi_gbl_sleep_state_names[sleep_state], info.return_object,
+                       acpi_ut_get_object_type_name (info.return_object)));
        }
 
-       acpi_ut_remove_reference (obj_desc);
+       acpi_ut_remove_reference (info.return_object);
        return_ACPI_STATUS (status);
 }
 
@@ -245,8 +249,8 @@ acpi_hw_get_bit_register_info (
  *              return_value    - Value that was read from the register
  *              Flags           - Lock the hardware or not
  *
- * RETURN:      Value is read from specified Register.  Value returned is
- *              normalized to bit0 (is shifted all the way right)
+ * RETURN:      Status and the value read from specified Register.  Value
+ *              returned is normalized to bit0 (is shifted all the way right)
  *
  * DESCRIPTION: ACPI bit_register read function.
  *
@@ -280,6 +284,8 @@ acpi_get_register (
                }
        }
 
+       /* Read from the register */
+
        status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
                          bit_reg_info->parent_register, &register_value);
 
@@ -309,10 +315,10 @@ acpi_get_register (
  *
  * PARAMETERS:  register_id     - ID of ACPI bit_register to access
  *              Value           - (only used on write) value to write to the
- *                                Register, NOT pre-normalized to the bit pos.
+ *                                Register, NOT pre-normalized to the bit pos
  *              Flags           - Lock the hardware or not
  *
- * RETURN:      None
+ * RETURN:      Status
  *
  * DESCRIPTION: ACPI Bit Register write function.
  *
@@ -457,10 +463,11 @@ unlock_and_exit:
  *
  * FUNCTION:    acpi_hw_register_read
  *
- * PARAMETERS:  use_lock               - Mutex hw access.
- *              register_id            - register_iD + Offset.
+ * PARAMETERS:  use_lock            - Mutex hw access
+ *              register_id         - register_iD + Offset
+ *              return_value        - Value that was read from the register
  *
- * RETURN:      Value read or written.
+ * RETURN:      Status and the value read.
  *
  * DESCRIPTION: Acpi register read function.  Registers are read at the
  *              given offset.
@@ -568,10 +575,11 @@ unlock_and_exit:
  *
  * FUNCTION:    acpi_hw_register_write
  *
- * PARAMETERS:  use_lock               - Mutex hw access.
- *              register_id            - register_iD + Offset.
+ * PARAMETERS:  use_lock            - Mutex hw access
+ *              register_id         - register_iD + Offset
+ *              Value               - The value to write
  *
- * RETURN:      Value read or written.
+ * RETURN:      Status
  *
  * DESCRIPTION: Acpi register Write function.  Registers are written at the
  *              given offset.
@@ -687,11 +695,11 @@ unlock_and_exit:
  *
  * PARAMETERS:  Width               - 8, 16, or 32
  *              Value               - Where the value is returned
- *              Register            - GAS register structure
+ *              Reg                 - GAS register structure
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Read from either memory, IO, or PCI config space.
+ * DESCRIPTION: Read from either memory or IO space.
  *
  ******************************************************************************/
 
@@ -701,8 +709,6 @@ acpi_hw_low_level_read (
        u32                             *value,
        struct acpi_generic_address     *reg)
 {
-       struct acpi_pci_id              pci_id;
-       u16                             pci_register;
        acpi_status                     status;
 
 
@@ -721,8 +727,8 @@ acpi_hw_low_level_read (
        *value = 0;
 
        /*
-        * Three address spaces supported:
-        * Memory, IO, or PCI_Config.
+        * Two address spaces supported: Memory or IO.
+        * PCI_Config is not supported here because the GAS struct is insufficient
         */
        switch (reg->address_space_id) {
        case ACPI_ADR_SPACE_SYSTEM_MEMORY:
@@ -740,19 +746,6 @@ acpi_hw_low_level_read (
                break;
 
 
-       case ACPI_ADR_SPACE_PCI_CONFIG:
-
-               pci_id.segment = 0;
-               pci_id.bus     = 0;
-               pci_id.device  = ACPI_PCI_DEVICE (reg->address);
-               pci_id.function = ACPI_PCI_FUNCTION (reg->address);
-               pci_register   = (u16) ACPI_PCI_REGISTER (reg->address);
-
-               status = acpi_os_read_pci_configuration (&pci_id, pci_register,
-                                value, width);
-               break;
-
-
        default:
                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
                        "Unsupported address space: %X\n", reg->address_space_id));
@@ -774,11 +767,11 @@ acpi_hw_low_level_read (
  *
  * PARAMETERS:  Width               - 8, 16, or 32
  *              Value               - To be written
- *              Register            - GAS register structure
+ *              Reg                 - GAS register structure
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Write to either memory, IO, or PCI config space.
+ * DESCRIPTION: Write to either memory or IO space.
  *
  ******************************************************************************/
 
@@ -788,8 +781,6 @@ acpi_hw_low_level_write (
        u32                             value,
        struct acpi_generic_address     *reg)
 {
-       struct acpi_pci_id              pci_id;
-       u16                             pci_register;
        acpi_status                     status;
 
 
@@ -807,8 +798,8 @@ acpi_hw_low_level_write (
        }
 
        /*
-        * Three address spaces supported:
-        * Memory, IO, or PCI_Config.
+        * Two address spaces supported: Memory or IO.
+        * PCI_Config is not supported here because the GAS struct is insufficient
         */
        switch (reg->address_space_id) {
        case ACPI_ADR_SPACE_SYSTEM_MEMORY:
@@ -826,19 +817,6 @@ acpi_hw_low_level_write (
                break;
 
 
-       case ACPI_ADR_SPACE_PCI_CONFIG:
-
-               pci_id.segment = 0;
-               pci_id.bus     = 0;
-               pci_id.device  = ACPI_PCI_DEVICE (reg->address);
-               pci_id.function = ACPI_PCI_FUNCTION (reg->address);
-               pci_register   = (u16) ACPI_PCI_REGISTER (reg->address);
-
-               status = acpi_os_write_pci_configuration (&pci_id, pci_register,
-                                (acpi_integer) value, width);
-               break;
-
-
        default:
                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
                        "Unsupported address space: %X\n", reg->address_space_id));
index f0c0414..6ffa80b 100644 (file)
@@ -265,19 +265,21 @@ acpi_enter_sleep_state (
        sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
        sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
 
-       if (sleep_state != ACPI_STATE_S5) {
-               /* Clear wake status */
+       /* Clear wake status */
 
-               status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
-               if (ACPI_FAILURE (status)) {
-                       return_ACPI_STATUS (status);
-               }
+       status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
+       }
 
-               status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
-               if (ACPI_FAILURE (status)) {
-                       return_ACPI_STATUS (status);
-               }
+       /* Clear all fixed and general purpose status bits */
 
+       status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
+       }
+
+       if (sleep_state != ACPI_STATE_S5) {
                /* Disable BM arbitration */
 
                status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
@@ -287,10 +289,16 @@ acpi_enter_sleep_state (
        }
 
        /*
-        * 1) Disable all runtime GPEs
+        * 1) Disable/Clear all GPEs
         * 2) Enable all wakeup GPEs
         */
-       status = acpi_hw_prepare_gpes_for_sleep ();
+       status = acpi_hw_disable_all_gpes (ACPI_ISR);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
+       }
+       acpi_gbl_system_awake_and_running = FALSE;
+
+       status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
        if (ACPI_FAILURE (status)) {
                return_ACPI_STATUS (status);
        }
@@ -420,10 +428,16 @@ acpi_enter_sleep_state_s4bios (
        }
 
        /*
-        * 1) Disable all runtime GPEs
+        * 1) Disable/Clear all GPEs
         * 2) Enable all wakeup GPEs
         */
-       status = acpi_hw_prepare_gpes_for_sleep ();
+       status = acpi_hw_disable_all_gpes (ACPI_ISR);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
+       }
+       acpi_gbl_system_awake_and_running = FALSE;
+
+       status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
        if (ACPI_FAILURE (status)) {
                return_ACPI_STATUS (status);
        }
@@ -453,6 +467,7 @@ acpi_enter_sleep_state_s4bios (
  * RETURN:      Status
  *
  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
+ *              Called with interrupts ENABLED.
  *
  ******************************************************************************/
 
@@ -540,19 +555,25 @@ acpi_leave_sleep_state (
 
        /*
         * Restore the GPEs:
-        * 1) Disable all wakeup GPEs
+        * 1) Disable/Clear all GPEs
         * 2) Enable all runtime GPEs
         */
-       status = acpi_hw_restore_gpes_on_wake ();
+       status = acpi_hw_disable_all_gpes (ACPI_NOT_ISR);
+       if (ACPI_FAILURE (status)) {
+               return_ACPI_STATUS (status);
+       }
+       acpi_gbl_system_awake_and_running = TRUE;
+
+       status = acpi_hw_enable_all_runtime_gpes (ACPI_NOT_ISR);
        if (ACPI_FAILURE (status)) {
                return_ACPI_STATUS (status);
        }
 
        /* Enable power button */
 
-       acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
+       (void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
                        1, ACPI_MTX_DO_NOT_LOCK);
-       acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
+       (void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
                        1, ACPI_MTX_DO_NOT_LOCK);
 
        /* Enable BM arbitration */
index 8878aff..1f94d6f 100644 (file)
  *
  * FUNCTION:    acpi_get_timer_resolution
  *
- * PARAMETERS:  none
+ * PARAMETERS:  Resolution          - Where the resolution is returned
  *
- * RETURN:      Number of bits of resolution in the PM Timer (24 or 32).
+ * RETURN:      Status and timer resolution
  *
- * DESCRIPTION: Obtains resolution of the ACPI PM Timer.
+ * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
  *
  ******************************************************************************/
 
@@ -86,11 +86,11 @@ acpi_get_timer_resolution (
  *
  * FUNCTION:    acpi_get_timer
  *
- * PARAMETERS:  none
+ * PARAMETERS:  Ticks               - Where the timer value is returned
  *
- * RETURN:      Current value of the ACPI PM Timer (in ticks).
+ * RETURN:      Status and current ticks
  *
- * DESCRIPTION: Obtains current value of ACPI PM Timer.
+ * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
  *
  ******************************************************************************/
 
@@ -118,11 +118,11 @@ acpi_get_timer (
  *
  * FUNCTION:    acpi_get_timer_duration
  *
- * PARAMETERS:  start_ticks
- *              end_ticks
- *              time_elapsed
+ * PARAMETERS:  start_ticks         - Starting timestamp
+ *              end_ticks           - End timestamp
+ *              time_elapsed        - Where the elapsed time is returned
  *
- * RETURN:      time_elapsed
+ * RETURN:      Status and time_elapsed
  *
  * DESCRIPTION: Computes the time elapsed (in microseconds) between two
  *              PM Timer time stamps, taking into account the possibility of
@@ -136,7 +136,7 @@ acpi_get_timer (
  *              Note that this function accommodates only a single timer
  *              rollover.  Thus for 24-bit timers, this function should only
  *              be used for calculating durations less than ~4.6 seconds
- *              (~20 minutes for 32-bit timers) -- calculations below
+ *              (~20 minutes for 32-bit timers) -- calculations below:
  *
  *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
  *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
@@ -164,7 +164,6 @@ acpi_get_timer_duration (
 
        /*
         * Compute Tick Delta:
-        * -------------------
         * Handle (max one) timer rollovers on 24- versus 32-bit timers.
         */
        if (start_ticks < end_ticks) {
@@ -188,10 +187,7 @@ acpi_get_timer_duration (
        }
 
        /*
-        * Compute Duration:
-        * -----------------
-        *
-        * Requires a 64-bit divide:
+        * Compute Duration (Requires a 64-bit divide):
         *
         * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY;
         */
diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c
new file mode 100644 (file)
index 0000000..ee9c5d1
--- /dev/null
@@ -0,0 +1,177 @@
+/* 
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *  This program is free software; you can redistribute 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+/* Purpose: Prevent PCMCIA cards from using motherboard resources. */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+#define _COMPONENT             ACPI_SYSTEM_COMPONENT
+ACPI_MODULE_NAME               ("acpi_motherboard")
+
+/* Dell use PNP0C01 instead of PNP0C02 */
+#define ACPI_MB_HID1                   "PNP0C01"
+#define ACPI_MB_HID2                   "PNP0C02"
+
+/**
+ * Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved
+ * Doesn't care about the failure of 'request_region', since other may reserve 
+ * the io ports as well
+ */
+#define IS_RESERVED_ADDR(base, len) \
+       (((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \
+       && ((base) + (len) > PCIBIOS_MIN_IO))
+
+/*
+ * Clearing the flag (IORESOURCE_BUSY) allows drivers to use
+ * the io ports if they really know they can use it, while
+ * still preventing hotplug PCI devices from using it. 
+ */
+
+static acpi_status
+acpi_reserve_io_ranges (struct acpi_resource *res, void *data)
+{
+       struct resource *requested_res = NULL;
+
+       ACPI_FUNCTION_TRACE("acpi_reserve_io_ranges");
+
+       if (res->id == ACPI_RSTYPE_IO) {
+               struct acpi_resource_io *io_res = &res->data.io;
+
+               if (io_res->min_base_address != io_res->max_base_address)
+                       return AE_OK;
+               if (IS_RESERVED_ADDR(io_res->min_base_address, io_res->range_length)) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
+                               io_res->min_base_address, 
+                               io_res->min_base_address + io_res->range_length));
+                       requested_res = request_region(io_res->min_base_address, 
+                               io_res->range_length, "motherboard");
+               }
+       } else if (res->id == ACPI_RSTYPE_FIXED_IO) {
+               struct acpi_resource_fixed_io *fixed_io_res = &res->data.fixed_io;
+
+               if (IS_RESERVED_ADDR(fixed_io_res->base_address, fixed_io_res->range_length)) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
+                               fixed_io_res->base_address, 
+                               fixed_io_res->base_address + fixed_io_res->range_length));
+                       requested_res = request_region(fixed_io_res->base_address, 
+                               fixed_io_res->range_length, "motherboard");
+               }
+       } else {
+               /* Memory mapped IO? */
+       }
+
+       if (requested_res)
+               requested_res->flags &= ~IORESOURCE_BUSY;
+       return AE_OK;
+}
+
+static int acpi_motherboard_add (struct acpi_device *device)
+{
+       if (!device)
+               return -EINVAL;
+       acpi_walk_resources(device->handle, METHOD_NAME__CRS, 
+               acpi_reserve_io_ranges, NULL);
+
+       return 0;
+}
+
+static struct acpi_driver acpi_motherboard_driver1 = {
+       .name =         "motherboard",
+       .class =        "",
+       .ids =          ACPI_MB_HID1,
+       .ops =  {
+               .add =          acpi_motherboard_add,
+       },
+};
+
+static struct acpi_driver acpi_motherboard_driver2 = {
+       .name =         "motherboard",
+       .class =        "",
+       .ids =          ACPI_MB_HID2,
+       .ops =  {
+               .add =          acpi_motherboard_add,
+       },
+};
+
+static void __init
+acpi_reserve_resources (void)
+{
+       if (acpi_gbl_FADT->xpm1a_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
+               request_region(acpi_gbl_FADT->xpm1a_evt_blk.address, 
+                       acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK");
+
+       if (acpi_gbl_FADT->xpm1b_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
+               request_region(acpi_gbl_FADT->xpm1b_evt_blk.address,
+                       acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK");
+
+       if (acpi_gbl_FADT->xpm1a_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
+               request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address, 
+                       acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK");
+
+       if (acpi_gbl_FADT->xpm1b_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
+               request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address, 
+                       acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK");
+
+       if (acpi_gbl_FADT->xpm_tmr_blk.address && acpi_gbl_FADT->pm_tm_len == 4)
+               request_region(acpi_gbl_FADT->xpm_tmr_blk.address,
+                       4, "PM_TMR");
+
+       if (acpi_gbl_FADT->xpm2_cnt_blk.address && acpi_gbl_FADT->pm2_cnt_len)
+               request_region(acpi_gbl_FADT->xpm2_cnt_blk.address,
+                       acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK");
+
+       /* Length of GPE blocks must be a non-negative multiple of 2 */
+
+       if (acpi_gbl_FADT->xgpe0_blk.address && acpi_gbl_FADT->gpe0_blk_len &&
+                       !(acpi_gbl_FADT->gpe0_blk_len & 0x1))
+               request_region(acpi_gbl_FADT->xgpe0_blk.address,
+                       acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK");
+
+       if (acpi_gbl_FADT->xgpe1_blk.address && acpi_gbl_FADT->gpe1_blk_len &&
+                       !(acpi_gbl_FADT->gpe1_blk_len & 0x1))
+               request_region(acpi_gbl_FADT->xgpe1_blk.address,
+                       acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK");
+}
+
+static int __init acpi_motherboard_init(void)
+{
+       acpi_bus_register_driver(&acpi_motherboard_driver1);
+       acpi_bus_register_driver(&acpi_motherboard_driver2);
+       /* 
+        * Guarantee motherboard IO reservation first
+        * This module must run after scan.c
+        */
+       if (!acpi_disabled)
+               acpi_reserve_resources ();
+       return 0;
+}
+
+/**
+ * Reserve motherboard resources after PCI claim BARs,
+ * but before PCI assign resources for uninitialized PCI devices
+ */
+fs_initcall(acpi_motherboard_init);
index 23baf93..765217b 100644 (file)
@@ -193,7 +193,7 @@ acpi_ns_root_initialize (void)
                        case ACPI_TYPE_MUTEX:
 
                                obj_desc->mutex.node = new_node;
-                               obj_desc->mutex.sync_level = (u16) ACPI_STRTOUL
+                               obj_desc->mutex.sync_level = (u8) ACPI_STRTOUL
                                                  (val, NULL, 10);
 
                                if (ACPI_STRCMP (init_val->name, "_GL_") == 0) {
index b054b36..418f03e 100644 (file)
 
 acpi_status
 acpi_ns_evaluate_relative (
-       struct acpi_namespace_node      *handle,
        char                            *pathname,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_object)
+       struct acpi_parameter_info      *info)
 {
        acpi_status                     status;
-       struct acpi_namespace_node      *prefix_node;
        struct acpi_namespace_node      *node = NULL;
        union acpi_generic_state        *scope_info;
        char                            *internal_path = NULL;
@@ -95,7 +92,7 @@ acpi_ns_evaluate_relative (
        /*
         * Must have a valid object handle
         */
-       if (!handle) {
+       if (!info || !info->node) {
                return_ACPI_STATUS (AE_BAD_PARAMETER);
        }
 
@@ -118,8 +115,8 @@ acpi_ns_evaluate_relative (
                goto cleanup;
        }
 
-       prefix_node = acpi_ns_map_handle_to_node (handle);
-       if (!prefix_node) {
+       info->node = acpi_ns_map_handle_to_node (info->node);
+       if (!info->node) {
                (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
                status = AE_BAD_PARAMETER;
                goto cleanup;
@@ -127,7 +124,7 @@ acpi_ns_evaluate_relative (
 
        /* Lookup the name in the namespace */
 
-       scope_info->scope.node = prefix_node;
+       scope_info->scope.node = info->node;
        status = acpi_ns_lookup (scope_info, internal_path, ACPI_TYPE_ANY,
                         ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
                         &node);
@@ -147,7 +144,8 @@ acpi_ns_evaluate_relative (
        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
                pathname, node, acpi_ns_get_attached_object (node)));
 
-       status = acpi_ns_evaluate_by_handle (node, params, return_object);
+       info->node = node;
+       status = acpi_ns_evaluate_by_handle (info);
 
        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
                pathname));
@@ -166,6 +164,7 @@ cleanup1:
  * FUNCTION:    acpi_ns_evaluate_by_name
  *
  * PARAMETERS:  Pathname            - Fully qualified pathname to the object
+ *              Info                - Contains:
  *              return_object       - Where to put method's return value (if
  *                                    any).  If NULL, no value is returned.
  *              Params              - List of parameters to pass to the method,
@@ -184,11 +183,9 @@ cleanup1:
 acpi_status
 acpi_ns_evaluate_by_name (
        char                            *pathname,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_object)
+       struct acpi_parameter_info      *info)
 {
        acpi_status                     status;
-       struct acpi_namespace_node      *node = NULL;
        char                            *internal_path = NULL;
 
 
@@ -211,7 +208,7 @@ acpi_ns_evaluate_by_name (
 
        status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY,
                         ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
-                        &node);
+                        &info->node);
 
        (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 
@@ -226,9 +223,9 @@ acpi_ns_evaluate_by_name (
         * to evaluate it.
         */
        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
-               pathname, node, acpi_ns_get_attached_object (node)));
+               pathname, info->node, acpi_ns_get_attached_object (info->node)));
 
-       status = acpi_ns_evaluate_by_handle (node, params, return_object);
+       status = acpi_ns_evaluate_by_handle (info);
 
        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
                pathname));
@@ -254,6 +251,7 @@ cleanup:
  *              Params              - List of parameters to pass to the method,
  *                                    terminated by NULL.  Params itself may be
  *                                    NULL if no parameters are being passed.
+ *              param_type          - Type of Parameter list
  *              return_object       - Where to put method's return value (if
  *                                    any).  If NULL, no value is returned.
  *
@@ -267,13 +265,9 @@ cleanup:
 
 acpi_status
 acpi_ns_evaluate_by_handle (
-       struct acpi_namespace_node      *handle,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_object)
+       struct acpi_parameter_info      *info)
 {
-       struct acpi_namespace_node      *node;
        acpi_status                     status;
-       union acpi_operand_object       *local_return_object;
 
 
        ACPI_FUNCTION_TRACE ("ns_evaluate_by_handle");
@@ -287,15 +281,13 @@ acpi_ns_evaluate_by_handle (
 
        /* Parameter Validation */
 
-       if (!handle) {
+       if (!info) {
                return_ACPI_STATUS (AE_BAD_PARAMETER);
        }
 
-       if (return_object) {
-               /* Initialize the return value to an invalid object */
+       /* Initialize the return value to an invalid object */
 
-               *return_object = NULL;
-       }
+       info->return_object = NULL;
 
        /* Get the prefix handle and Node */
 
@@ -304,8 +296,8 @@ acpi_ns_evaluate_by_handle (
                return_ACPI_STATUS (status);
        }
 
-       node = acpi_ns_map_handle_to_node (handle);
-       if (!node) {
+       info->node = acpi_ns_map_handle_to_node (info->node);
+       if (!info->node) {
                (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
                return_ACPI_STATUS (AE_BAD_PARAMETER);
        }
@@ -315,8 +307,8 @@ acpi_ns_evaluate_by_handle (
         * so that proper scoping context will be established
         * before execution.
         */
-       if (acpi_ns_get_type (node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
-               node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
+       if (acpi_ns_get_type (info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+               info->node = ACPI_CAST_PTR (struct acpi_namespace_node, info->node->object);
        }
 
        /*
@@ -328,19 +320,18 @@ acpi_ns_evaluate_by_handle (
         * In both cases, the namespace is unlocked by the
         *  acpi_ns* procedure
         */
-       if (acpi_ns_get_type (node) == ACPI_TYPE_METHOD) {
+       if (acpi_ns_get_type (info->node) == ACPI_TYPE_METHOD) {
                /*
                 * Case 1) We have an actual control method to execute
                 */
-               status = acpi_ns_execute_control_method (node, params,
-                                &local_return_object);
+               status = acpi_ns_execute_control_method (info);
        }
        else {
                /*
                 * Case 2) Object is NOT a method, just return its
                 * current value
                 */
-               status = acpi_ns_get_object_value (node, &local_return_object);
+               status = acpi_ns_get_object_value (info);
        }
 
        /*
@@ -348,20 +339,6 @@ acpi_ns_evaluate_by_handle (
         * be dealt with
         */
        if (status == AE_CTRL_RETURN_VALUE) {
-               /*
-                * If the Method returned a value and the caller
-                * provided a place to store a returned value, Copy
-                * the returned value to the object descriptor provided
-                * by the caller.
-                */
-               if (return_object) {
-                       /*
-                        * Valid return object, copy the pointer to
-                        * the returned object
-                        */
-                       *return_object = local_return_object;
-               }
-
                /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
 
                status = AE_OK;
@@ -396,9 +373,7 @@ acpi_ns_evaluate_by_handle (
 
 acpi_status
 acpi_ns_execute_control_method (
-       struct acpi_namespace_node      *method_node,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_obj_desc)
+       struct acpi_parameter_info      *info)
 {
        acpi_status                     status;
        union acpi_operand_object       *obj_desc;
@@ -409,7 +384,7 @@ acpi_ns_execute_control_method (
 
        /* Verify that there is a method associated with this object */
 
-       obj_desc = acpi_ns_get_attached_object (method_node);
+       obj_desc = acpi_ns_get_attached_object (info->node);
        if (!obj_desc) {
                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n"));
 
@@ -417,7 +392,7 @@ acpi_ns_execute_control_method (
                return_ACPI_STATUS (AE_NULL_OBJECT);
        }
 
-       ACPI_DUMP_PATHNAME (method_node, "Execute Method:",
+       ACPI_DUMP_PATHNAME (info->node, "Execute Method:",
                ACPI_LV_INFO, _COMPONENT);
 
        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
@@ -444,7 +419,7 @@ acpi_ns_execute_control_method (
                return_ACPI_STATUS (status);
        }
 
-       status = acpi_psx_execute (method_node, params, return_obj_desc);
+       status = acpi_psx_execute (info);
        acpi_ex_exit_interpreter ();
 
        return_ACPI_STATUS (status);
@@ -468,11 +443,10 @@ acpi_ns_execute_control_method (
 
 acpi_status
 acpi_ns_get_object_value (
-       struct acpi_namespace_node      *node,
-       union acpi_operand_object       **return_obj_desc)
+       struct acpi_parameter_info      *info)
 {
        acpi_status                     status = AE_OK;
-       struct acpi_namespace_node      *resolved_node = node;
+       struct acpi_namespace_node      *resolved_node = info->node;
 
 
        ACPI_FUNCTION_TRACE ("ns_get_object_value");
@@ -518,9 +492,9 @@ acpi_ns_get_object_value (
 
                if (ACPI_SUCCESS (status)) {
                        status = AE_CTRL_RETURN_VALUE;
-                       *return_obj_desc = ACPI_CAST_PTR (union acpi_operand_object, resolved_node);
+                       info->return_object = ACPI_CAST_PTR (union acpi_operand_object, resolved_node);
                        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
-                               *return_obj_desc, acpi_ut_get_object_type_name (*return_obj_desc)));
+                               info->return_object, acpi_ut_get_object_type_name (info->return_object)));
                }
        }
 
index c8e9317..8617875 100644 (file)
@@ -149,7 +149,7 @@ acpi_ns_initialize_devices (
                return_ACPI_STATUS (status);
        }
 
-       /* Walk namespace for all objects of type Device or Processor */
+       /* Walk namespace for all objects */
 
        status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
                          ACPI_UINT32_MAX, TRUE, acpi_ns_init_one_device, &info, NULL);
@@ -337,25 +337,29 @@ acpi_ns_init_one_device (
        void                            *context,
        void                            **return_value)
 {
-       acpi_status                     status;
-       struct acpi_namespace_node     *node;
-       u32                             flags;
        struct acpi_device_walk_info   *info = (struct acpi_device_walk_info *) context;
+       struct acpi_parameter_info      pinfo;
+       u32                             flags;
+       acpi_status                     status;
 
 
        ACPI_FUNCTION_TRACE ("ns_init_one_device");
 
 
-       node = acpi_ns_map_handle_to_node (obj_handle);
-       if (!node) {
+       pinfo.parameters = NULL;
+       pinfo.parameter_type = ACPI_PARAM_ARGS;
+
+       pinfo.node = acpi_ns_map_handle_to_node (obj_handle);
+       if (!pinfo.node) {
                return_ACPI_STATUS (AE_BAD_PARAMETER);
        }
 
        /*
-        * We will run _STA/_INI on Devices and Processors only
+        * We will run _STA/_INI on Devices, Processors and thermal_zones only
         */
-       if ((node->type != ACPI_TYPE_DEVICE) &&
-               (node->type != ACPI_TYPE_PROCESSOR)) {
+       if ((pinfo.node->type != ACPI_TYPE_DEVICE)      &&
+               (pinfo.node->type != ACPI_TYPE_PROCESSOR)   &&
+               (pinfo.node->type != ACPI_TYPE_THERMAL)) {
                return_ACPI_STATUS (AE_OK);
        }
 
@@ -368,17 +372,17 @@ acpi_ns_init_one_device (
        /*
         * Run _STA to determine if we can run _INI on the device.
         */
-       ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, node, "_STA"));
-       status = acpi_ut_execute_STA (node, &flags);
+       ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_STA"));
+       status = acpi_ut_execute_STA (pinfo.node, &flags);
 
        if (ACPI_FAILURE (status)) {
-               if (node->type == ACPI_TYPE_DEVICE) {
+               if (pinfo.node->type == ACPI_TYPE_DEVICE) {
                        /* Ignore error and move on to next device */
 
                        return_ACPI_STATUS (AE_OK);
                }
 
-               /* _STA is not required for Processor objects */
+               /* _STA is not required for Processor or thermal_zone objects */
        }
        else {
                info->num_STA++;
@@ -393,22 +397,22 @@ acpi_ns_init_one_device (
        /*
         * The device is present. Run _INI.
         */
-       ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, obj_handle, "_INI"));
-       status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL);
+       ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_INI"));
+       status = acpi_ns_evaluate_relative ("_INI", &pinfo);
        if (ACPI_FAILURE (status)) {
                /* No _INI (AE_NOT_FOUND) means device requires no initialization */
 
                if (status != AE_NOT_FOUND) {
                        /* Ignore error and move on to next device */
 
-       #ifdef ACPI_DEBUG_OUTPUT
-                       char                *scope_name = acpi_ns_get_external_pathname (obj_handle);
+#ifdef ACPI_DEBUG_OUTPUT
+                       char                *scope_name = acpi_ns_get_external_pathname (pinfo.node);
 
                        ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n",
                                        scope_name, acpi_format_exception (status)));
 
                        ACPI_MEM_FREE (scope_name);
-       #endif
+#endif
                }
 
                status = AE_OK;
@@ -422,7 +426,7 @@ acpi_ns_init_one_device (
        if (acpi_gbl_init_handler) {
                /* External initialization handler is present, call it */
 
-               status = acpi_gbl_init_handler (obj_handle, ACPI_INIT_DEVICE_INI);
+               status = acpi_gbl_init_handler (pinfo.node, ACPI_INIT_DEVICE_INI);
        }
 
 
index f550ce5..530982a 100644 (file)
@@ -94,8 +94,9 @@ acpi_ns_one_complete_parse (
                return_ACPI_STATUS (AE_NO_MEMORY);
        }
 
-       status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL, table_desc->aml_start,
-                         table_desc->aml_length, NULL, NULL, pass_number);
+       status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL,
+                         table_desc->aml_start, table_desc->aml_length,
+                         NULL, pass_number);
        if (ACPI_FAILURE (status)) {
                acpi_ds_delete_walk_state (walk_state);
                return_ACPI_STATUS (status);
index 3128354..8e916b5 100644 (file)
@@ -174,8 +174,7 @@ acpi_evaluate_object (
 {
        acpi_status                     status;
        acpi_status                     status2;
-       union acpi_operand_object       **internal_params = NULL;
-       union acpi_operand_object       *internal_return_obj = NULL;
+       struct acpi_parameter_info      info;
        acpi_size                       buffer_space_needed;
        u32                             i;
 
@@ -183,6 +182,11 @@ acpi_evaluate_object (
        ACPI_FUNCTION_TRACE ("acpi_evaluate_object");
 
 
+       info.node = handle;
+       info.parameters = NULL;
+       info.return_object = NULL;
+       info.parameter_type = ACPI_PARAM_ARGS;
+
        /*
         * If there are parameters to be passed to the object
         * (which must be a control method), the external objects
@@ -193,9 +197,10 @@ acpi_evaluate_object (
                 * Allocate a new parameter block for the internal objects
                 * Add 1 to count to allow for null terminated internal list
                 */
-               internal_params = ACPI_MEM_CALLOCATE (((acpi_size) external_params->count + 1) *
-                                 sizeof (void *));
-               if (!internal_params) {
+               info.parameters = ACPI_MEM_CALLOCATE (
+                                ((acpi_size) external_params->count + 1) *
+                                sizeof (void *));
+               if (!info.parameters) {
                        return_ACPI_STATUS (AE_NO_MEMORY);
                }
 
@@ -205,15 +210,16 @@ acpi_evaluate_object (
                 */
                for (i = 0; i < external_params->count; i++) {
                        status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
-                                         &internal_params[i]);
+                                         &info.parameters[i]);
                        if (ACPI_FAILURE (status)) {
-                               acpi_ut_delete_internal_object_list (internal_params);
+                               acpi_ut_delete_internal_object_list (info.parameters);
                                return_ACPI_STATUS (status);
                        }
                }
-               internal_params[external_params->count] = NULL;
+               info.parameters[external_params->count] = NULL;
        }
 
+
        /*
         * Three major cases:
         * 1) Fully qualified pathname
@@ -225,8 +231,7 @@ acpi_evaluate_object (
                /*
                 *  The path is fully qualified, just evaluate by name
                 */
-               status = acpi_ns_evaluate_by_name (pathname, internal_params,
-                                &internal_return_obj);
+               status = acpi_ns_evaluate_by_name (pathname, &info);
        }
        else if (!handle) {
                /*
@@ -256,15 +261,13 @@ acpi_evaluate_object (
                         * The null pathname case means the handle is for
                         * the actual object to be evaluated
                         */
-                       status = acpi_ns_evaluate_by_handle (handle, internal_params,
-                                         &internal_return_obj);
+                       status = acpi_ns_evaluate_by_handle (&info);
                }
                else {
                   /*
                        * Both a Handle and a relative Pathname
                        */
-                       status = acpi_ns_evaluate_relative (handle, pathname, internal_params,
-                                         &internal_return_obj);
+                       status = acpi_ns_evaluate_relative (pathname, &info);
                }
        }
 
@@ -274,11 +277,11 @@ acpi_evaluate_object (
         * copy the return value to an external object.
         */
        if (return_buffer) {
-               if (!internal_return_obj) {
+               if (!info.return_object) {
                        return_buffer->length = 0;
                }
                else {
-                       if (ACPI_GET_DESCRIPTOR_TYPE (internal_return_obj) == ACPI_DESC_TYPE_NAMED) {
+                       if (ACPI_GET_DESCRIPTOR_TYPE (info.return_object) == ACPI_DESC_TYPE_NAMED) {
                                /*
                                 * If we received a NS Node as a return object, this means that
                                 * the object we are evaluating has nothing interesting to
@@ -288,7 +291,7 @@ acpi_evaluate_object (
                                 * support for various types at a later date if necessary.
                                 */
                                status = AE_TYPE;
-                               internal_return_obj = NULL; /* No need to delete a NS Node */
+                               info.return_object = NULL;  /* No need to delete a NS Node */
                                return_buffer->length = 0;
                        }
 
@@ -297,7 +300,7 @@ acpi_evaluate_object (
                                 * Find out how large a buffer is needed
                                 * to contain the returned object
                                 */
-                               status = acpi_ut_get_object_size (internal_return_obj,
+                               status = acpi_ut_get_object_size (info.return_object,
                                                   &buffer_space_needed);
                                if (ACPI_SUCCESS (status)) {
                                        /* Validate/Allocate/Clear caller buffer */
@@ -309,13 +312,14 @@ acpi_evaluate_object (
                                                 */
                                                ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                                                        "Needed buffer size %X, %s\n",
-                                                       (u32) buffer_space_needed, acpi_format_exception (status)));
+                                                       (u32) buffer_space_needed,
+                                                       acpi_format_exception (status)));
                                        }
                                        else {
                                                /*
                                                 *  We have enough space for the object, build it
                                                 */
-                                               status = acpi_ut_copy_iobject_to_eobject (internal_return_obj,
+                                               status = acpi_ut_copy_iobject_to_eobject (info.return_object,
                                                                  return_buffer);
                                        }
                                }
@@ -323,7 +327,7 @@ acpi_evaluate_object (
                }
        }
 
-       if (internal_return_obj) {
+       if (info.return_object) {
                /*
                 * Delete the internal return object.  NOTE: Interpreter
                 * must be locked to avoid race condition.
@@ -334,7 +338,7 @@ acpi_evaluate_object (
                         * Delete the internal return object. (Or at least
                         * decrement the reference count by one)
                         */
-                       acpi_ut_remove_reference (internal_return_obj);
+                       acpi_ut_remove_reference (info.return_object);
                        acpi_ex_exit_interpreter ();
                }
        }
@@ -342,10 +346,10 @@ acpi_evaluate_object (
        /*
         * Free the input parameter list (if we created one),
         */
-       if (internal_params) {
+       if (info.parameters) {
                /* Free the allocated parameter block */
 
-               acpi_ut_delete_internal_object_list (internal_params);
+               acpi_ut_delete_internal_object_list (info.parameters);
        }
 
        return_ACPI_STATUS (status);
index a1acb9f..0508b4d 100644 (file)
@@ -281,7 +281,7 @@ acpi_get_object_info (
        if (info.type == ACPI_TYPE_DEVICE) {
                /*
                 * Get extra info for ACPI Devices objects only:
-                * Run the Device _HID, _UID, _CID, _STA, and _ADR methods.
+                * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods.
                 *
                 * Note: none of these methods are required, so they may or may
                 * not be present for this device.  The Info.Valid bitfield is used
@@ -330,7 +330,7 @@ acpi_get_object_info (
 
                status = acpi_ut_execute_sxds (node, info.highest_dstates);
                if (ACPI_SUCCESS (status)) {
-                       info.valid |= ACPI_VALID_STA;
+                       info.valid |= ACPI_VALID_SXDS;
                }
 
                status = AE_OK;
index 0646b29..1f63b4d 100644 (file)
@@ -51,6 +51,7 @@ acpi_table_print_srat_entry (
        switch (header->type) {
 
        case ACPI_SRAT_PROCESSOR_AFFINITY:
+#ifdef ACPI_DEBUG_OUTPUT
        {
                struct acpi_table_processor_affinity *p =
                        (struct acpi_table_processor_affinity*) header;
@@ -58,9 +59,11 @@ acpi_table_print_srat_entry (
                       p->apic_id, p->lsapic_eid, p->proximity_domain,
                       p->flags.enabled?"enabled":"disabled"));
        }
+#endif /* ACPI_DEBUG_OUTPUT */
                break;
 
        case ACPI_SRAT_MEMORY_AFFINITY:
+#ifdef ACPI_DEBUG_OUTPUT
        {
                struct acpi_table_memory_affinity *p =
                        (struct acpi_table_memory_affinity*) header;
@@ -70,6 +73,7 @@ acpi_table_print_srat_entry (
                       p->flags.enabled ? "enabled" : "disabled",
                       p->flags.hot_pluggable ? " hot-pluggable" : ""));
        }
+#endif /* ACPI_DEBUG_OUTPUT */
                break;
 
        default:
@@ -94,8 +98,6 @@ acpi_parse_slit (unsigned long phys_addr, unsigned long size)
        /* downcast just for %llu vs %lu for i386/ia64  */
        localities = (u32) slit->localities;
 
-       printk(KERN_INFO PREFIX "SLIT localities %ux%u\n", localities, localities);
-
        acpi_numa_slit_init(slit);
 
        return 0;
@@ -103,7 +105,9 @@ acpi_parse_slit (unsigned long phys_addr, unsigned long size)
 
 
 static int __init
-acpi_parse_processor_affinity (acpi_table_entry_header *header)
+acpi_parse_processor_affinity (
+       acpi_table_entry_header *header,
+       const unsigned long end)
 {
        struct acpi_table_processor_affinity *processor_affinity;
 
@@ -121,7 +125,9 @@ acpi_parse_processor_affinity (acpi_table_entry_header *header)
 
 
 static int __init
-acpi_parse_memory_affinity (acpi_table_entry_header *header)
+acpi_parse_memory_affinity (
+       acpi_table_entry_header *header,
+       const unsigned long end)
 {
        struct acpi_table_memory_affinity *memory_affinity;
 
@@ -148,8 +154,6 @@ acpi_parse_srat (unsigned long phys_addr, unsigned long size)
 
        srat = (struct acpi_table_srat *) __va(phys_addr);
 
-       printk(KERN_INFO PREFIX "SRAT revision %d\n", srat->table_revision);
-
        return 0;
 }
 
index 198e220..3062037 100644 (file)
 #define ARGI_CREATE_FIELD_OP            ARGI_LIST4 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_INTEGER,      ARGI_REFERENCE)
 #define ARGI_CREATE_QWORD_FIELD_OP      ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
 #define ARGI_CREATE_WORD_FIELD_OP       ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
-#define ARGI_DATA_REGION_OP             ARGI_LIST3 (ARGI_STRING,     ARGI_STRING,       ARGI_STRING)
+#define ARGI_DATA_REGION_OP             ARGI_LIST3 (ARGI_STRING,     ARGI_STRING,        ARGI_STRING)
 #define ARGI_DEBUG_OP                   ARG_NONE
 #define ARGI_DECREMENT_OP               ARGI_LIST1 (ARGI_INTEGER_REF)
 #define ARGI_DEREF_OF_OP                ARGI_LIST1 (ARGI_REF_OR_STRING)
 #define ARGI_INDEX_FIELD_OP             ARGI_INVALID_OPCODE
 #define ARGI_INDEX_OP                   ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER,       ARGI_TARGETREF)
 #define ARGI_LAND_OP                    ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
-#define ARGI_LEQUAL_OP                  ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
-#define ARGI_LGREATER_OP                ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
+#define ARGI_LEQUAL_OP                  ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
+#define ARGI_LGREATER_OP                ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
 #define ARGI_LGREATEREQUAL_OP           ARGI_INVALID_OPCODE
-#define ARGI_LLESS_OP                   ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
+#define ARGI_LLESS_OP                   ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
 #define ARGI_LLESSEQUAL_OP              ARGI_INVALID_OPCODE
 #define ARGI_LNOT_OP                    ARGI_LIST1 (ARGI_INTEGER)
 #define ARGI_LNOTEQUAL_OP               ARGI_INVALID_OPCODE
index b7917cf..9281f6a 100644 (file)
@@ -57,7 +57,7 @@
  *
  * FUNCTION:    acpi_psx_execute
  *
- * PARAMETERS:  method_node         - A method object containing both the AML
+ * PARAMETERS:  Info->Node          - A method object containing both the AML
  *                                    address and length.
  *              **Params            - List of parameters to pass to method,
  *                                    terminated by NULL. Params itself may be
@@ -73,9 +73,7 @@
 
 acpi_status
 acpi_psx_execute (
-       struct acpi_namespace_node      *method_node,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_obj_desc)
+       struct acpi_parameter_info      *info)
 {
        acpi_status                     status;
        union acpi_operand_object       *obj_desc;
@@ -89,29 +87,30 @@ acpi_psx_execute (
 
        /* Validate the Node and get the attached object */
 
-       if (!method_node) {
+       if (!info || !info->node) {
                return_ACPI_STATUS (AE_NULL_ENTRY);
        }
 
-       obj_desc = acpi_ns_get_attached_object (method_node);
+       obj_desc = acpi_ns_get_attached_object (info->node);
        if (!obj_desc) {
                return_ACPI_STATUS (AE_NULL_OBJECT);
        }
 
        /* Init for new method, wait on concurrency semaphore */
 
-       status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL);
+       status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL);
        if (ACPI_FAILURE (status)) {
                return_ACPI_STATUS (status);
        }
 
-       if (params) {
+       if ((info->parameter_type == ACPI_PARAM_ARGS) &&
+               (info->parameters)) {
                /*
                 * The caller "owns" the parameters, so give each one an extra
                 * reference
                 */
-               for (i = 0; params[i]; i++) {
-                       acpi_ut_add_reference (params[i]);
+               for (i = 0; info->parameters[i]; i++) {
+                       acpi_ut_add_reference (info->parameters[i]);
                }
        }
 
@@ -121,7 +120,7 @@ acpi_psx_execute (
         */
        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
                "**** Begin Method Parse **** Entry=%p obj=%p\n",
-               method_node, obj_desc));
+               info->node, obj_desc));
 
        /* Create and init a Root Node */
 
@@ -147,8 +146,9 @@ acpi_psx_execute (
                goto cleanup2;
        }
 
-       status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
-                         obj_desc->method.aml_length, NULL, NULL, 1);
+       status = acpi_ds_init_aml_walk (walk_state, op, info->node,
+                         obj_desc->method.aml_start,
+                         obj_desc->method.aml_length, NULL, 1);
        if (ACPI_FAILURE (status)) {
                goto cleanup3;
        }
@@ -159,7 +159,6 @@ acpi_psx_execute (
        acpi_ps_delete_parse_tree (op);
        if (ACPI_FAILURE (status)) {
                goto cleanup1; /* Walk state is already deleted */
-
        }
 
        /*
@@ -167,7 +166,7 @@ acpi_psx_execute (
         */
        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
                "**** Begin Method Execution **** Entry=%p obj=%p\n",
-               method_node, obj_desc));
+               info->node, obj_desc));
 
        /* Create and init a Root Node */
 
@@ -179,8 +178,8 @@ acpi_psx_execute (
 
        /* Init new op with the method name and pointer back to the NS node */
 
-       acpi_ps_set_name (op, method_node->name.integer);
-       op->common.node = method_node;
+       acpi_ps_set_name (op, info->node->name.integer);
+       op->common.node = info->node;
 
        /* Create and initialize a new walk state */
 
@@ -190,8 +189,9 @@ acpi_psx_execute (
                goto cleanup2;
        }
 
-       status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
-                         obj_desc->method.aml_length, params, return_obj_desc, 3);
+       status = acpi_ds_init_aml_walk (walk_state, op, info->node,
+                         obj_desc->method.aml_start,
+                         obj_desc->method.aml_length, info, 3);
        if (ACPI_FAILURE (status)) {
                goto cleanup3;
        }
@@ -210,13 +210,14 @@ cleanup2:
        acpi_ps_delete_parse_tree (op);
 
 cleanup1:
-       if (params) {
+       if ((info->parameter_type == ACPI_PARAM_ARGS) &&
+               (info->parameters)) {
                /* Take away the extra reference that we gave the parameters above */
 
-               for (i = 0; params[i]; i++) {
+               for (i = 0; info->parameters[i]; i++) {
                        /* Ignore errors, just do them all */
 
-                       (void) acpi_ut_update_object_reference (params[i], REF_DECREMENT);
+                       (void) acpi_ut_update_object_reference (info->parameters[i], REF_DECREMENT);
                }
        }
 
@@ -228,10 +229,10 @@ cleanup1:
         * If the method has returned an object, signal this to the caller with
         * a control exception code
         */
-       if (*return_obj_desc) {
+       if (info->return_object) {
                ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n",
-                       *return_obj_desc));
-               ACPI_DUMP_STACK_ENTRY (*return_obj_desc);
+                       info->return_object));
+               ACPI_DUMP_STACK_ENTRY (info->return_object);
 
                status = AE_CTRL_RETURN_VALUE;
        }
index eaf77c6..01dea9b 100644 (file)
@@ -289,6 +289,7 @@ acpi_rs_set_srs_method_data (
        acpi_handle                     handle,
        struct acpi_buffer              *in_buffer)
 {
+       struct acpi_parameter_info      info;
        union acpi_operand_object       *params[2];
        acpi_status                     status;
        struct acpi_buffer              buffer;
@@ -329,10 +330,14 @@ acpi_rs_set_srs_method_data (
        params[0]->common.flags   = AOPOBJ_DATA_VALID;
        params[1] = NULL;
 
+       info.node = handle;
+       info.parameters = params;
+       info.parameter_type = ACPI_PARAM_ARGS;
+
        /*
         * Execute the method, no return value
         */
-       status = acpi_ns_evaluate_relative (handle, "_SRS", params, NULL);
+       status = acpi_ns_evaluate_relative ("_SRS", &info);
 
        /*
         * Clean up and return the status from acpi_ns_evaluate_relative
index 362f625..d02aa1d 100644 (file)
@@ -259,7 +259,8 @@ acpi_walk_resources (
        /* Setup pointers */
 
        resource  = (struct acpi_resource *) buffer.pointer;
-       buffer_end = (struct acpi_resource *) ((u8 *) buffer.pointer + buffer.length);
+       buffer_end = ACPI_CAST_PTR (struct acpi_resource,
+                         ((u8 *) buffer.pointer + buffer.length));
 
        /* Walk the resource list */
 
index 975d03d..bb52f85 100644 (file)
@@ -1,5 +1,5 @@
 obj-y                                  := poweroff.o
-obj-$(CONFIG_ACPI_SLEEP)               += main.o
+obj-$(CONFIG_ACPI_SLEEP)               += main.o wakeup.o
 obj-$(CONFIG_ACPI_SLEEP_PROC_FS)       += proc.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
index 7eb2060..666498e 100644 (file)
@@ -15,6 +15,7 @@
 
 #define ACPI_SYSTEM_FILE_SLEEP         "sleep"
 #define ACPI_SYSTEM_FILE_ALARM         "alarm"
+#define ACPI_SYSTEM_FILE_WAKEUP_DEVICE   "wakeup"
 
 #define _COMPONENT             ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME               ("sleep")
@@ -352,6 +353,84 @@ end:
        return_VALUE(result ? result : count);
 }
 
+extern struct list_head        acpi_wakeup_device_list;
+extern spinlock_t acpi_device_lock;
+
+static int
+acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
+{
+       struct list_head * node, * next;
+
+       seq_printf(seq, "Device Sleep state     Status\n");
+
+       spin_lock(&acpi_device_lock);
+       list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+               struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
+
+               if (!dev->wakeup.flags.valid)
+                       continue;
+               spin_unlock(&acpi_device_lock);
+               if (dev->wakeup.flags.run_wake)
+                       seq_printf(seq, "%4s    %4d             %8s\n",
+                               dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
+                               dev->wakeup.state.enabled ? "*enabled" : "*disabled");
+               else
+                       seq_printf(seq, "%4s    %4d             %8s\n",
+                               dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
+                               dev->wakeup.state.enabled ? "enabled" : "disabled");
+               spin_lock(&acpi_device_lock);
+       }
+       spin_unlock(&acpi_device_lock);
+       return 0;
+}
+
+static ssize_t
+acpi_system_write_wakeup_device (
+       struct file             *file,
+       const char __user       *buffer,
+       size_t                  count,
+       loff_t                  *ppos)
+{
+       struct list_head * node, * next;
+       char            strbuf[5];
+       char            str[5] = "";
+       int             len = count;
+
+       if (len > 4) len = 4;
+
+       if (copy_from_user(strbuf, buffer, len))
+               return -EFAULT;
+       strbuf[len] = '\0';
+       sscanf(strbuf, "%s", str);
+
+       spin_lock(&acpi_device_lock);
+       list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+               struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
+               if (!dev->wakeup.flags.valid)
+                       continue;
+
+               if (!strncmp(dev->pnp.bus_id, str, 4)) {
+                       dev->wakeup.state.enabled = dev->wakeup.state.enabled ? 0:1;
+                       break;
+               }
+       }
+       spin_unlock(&acpi_device_lock);
+       return count;
+}
+
+static int
+acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_system_wakeup_device_seq_show, PDE(inode)->data);
+}
+
+static struct file_operations acpi_system_wakeup_device_fops = {
+       .open           = acpi_system_wakeup_device_open_fs,
+       .read           = seq_read,
+       .write          = acpi_system_write_wakeup_device,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 
 static struct file_operations acpi_system_sleep_fops = {
        .open           = acpi_system_sleep_open_fs,
@@ -388,6 +467,13 @@ static int acpi_sleep_proc_init(void)
                S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
        if (entry)
                entry->proc_fops = &acpi_system_alarm_fops;
+
+       /* 'wakeup device' [R/W]*/
+       entry = create_proc_entry(ACPI_SYSTEM_FILE_WAKEUP_DEVICE,
+                                 S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
+       if (entry)
+               entry->proc_fops = &acpi_system_wakeup_device_fops;
+
        return 0;
 }
 
index ad38f41..cfaf8f5 100644 (file)
@@ -2,3 +2,6 @@
 extern u8 sleep_states[];
 extern int acpi_suspend (u32 state);
 
+extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
+extern void acpi_enable_wakeup_device(u8 sleep_state);
+extern void acpi_disable_wakeup_device(u8 sleep_state);
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
new file mode 100644 (file)
index 0000000..9c004b9
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * wakeup.c - support wakeup devices
+ */
+
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <acpi/acevents.h>
+#include "sleep.h"
+
+#define _COMPONENT             ACPI_SYSTEM_COMPONENT
+ACPI_MODULE_NAME               ("wakeup_devices")
+
+/**
+ * acpi_enable_wakeup_device_prep - prepare wakeup devices
+ *     @sleep_state:   ACPI state
+ * Enable all wakup devices power if the devices' wakeup level
+ * is higher than requested sleep level
+ */
+extern struct list_head        acpi_wakeup_device_list;
+extern spinlock_t acpi_device_lock;
+
+void
+acpi_enable_wakeup_device_prep(
+       u8              sleep_state)
+{
+       struct list_head * node, * next;
+
+       ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_prep");
+
+       spin_lock(&acpi_device_lock);
+       list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+               struct acpi_device * dev = container_of(node, 
+                       struct acpi_device, wakeup_list);
+               
+               if (!dev->wakeup.flags.valid || 
+                       !dev->wakeup.state.enabled ||
+                       (sleep_state > (u32) dev->wakeup.sleep_state))
+                       continue;
+
+               spin_unlock(&acpi_device_lock);
+               acpi_enable_wakeup_device_power(dev);
+               spin_lock(&acpi_device_lock);
+       }
+       spin_unlock(&acpi_device_lock);
+}
+
+/**
+ * acpi_enable_wakeup_device - enable wakeup devices
+ *     @sleep_state:   ACPI state
+ * Enable all wakup devices's GPE
+ */
+void
+acpi_enable_wakeup_device(
+       u8              sleep_state)
+{
+       struct list_head * node, * next;
+
+       /* 
+        * Caution: this routine must be invoked when interrupt is disabled 
+        * Refer ACPI2.0: P212
+        */
+       ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
+       spin_lock(&acpi_device_lock);
+       list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+               struct acpi_device * dev = container_of(node, 
+                       struct acpi_device, wakeup_list);
+
+               /* If users want to disable run-wake GPE,
+                * we only disable it for wake and leave it for runtime
+                */
+               if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
+                       spin_unlock(&acpi_device_lock);
+                       acpi_set_gpe_type(dev->wakeup.gpe_device, 
+                               dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
+                       /* Re-enable it, since set_gpe_type will disable it */
+                       acpi_enable_gpe(dev->wakeup.gpe_device, 
+                               dev->wakeup.gpe_number, ACPI_ISR);
+                       spin_lock(&acpi_device_lock);
+                       continue;
+               }
+
+               if (!dev->wakeup.flags.valid ||
+                       !dev->wakeup.state.enabled ||
+                       (sleep_state > (u32) dev->wakeup.sleep_state))
+                       continue;
+
+               spin_unlock(&acpi_device_lock);
+               /* run-wake GPE has been enabled */
+               if (!dev->wakeup.flags.run_wake)
+                       acpi_enable_gpe(dev->wakeup.gpe_device, 
+                               dev->wakeup.gpe_number, ACPI_ISR);
+               dev->wakeup.state.active = 1;
+               spin_lock(&acpi_device_lock);
+       }
+       spin_unlock(&acpi_device_lock);
+}
+
+/**
+ * acpi_disable_wakeup_device - disable devices' wakeup capability
+ *     @sleep_state:   ACPI state
+ * Disable all wakup devices's GPE and wakeup capability
+ */
+void
+acpi_disable_wakeup_device (
+       u8              sleep_state)
+{
+       struct list_head * node, * next;
+
+       ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device");
+
+       spin_lock(&acpi_device_lock);
+       list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+               struct acpi_device * dev = container_of(node, 
+                       struct acpi_device, wakeup_list);
+
+               if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
+                       spin_unlock(&acpi_device_lock);
+                       acpi_set_gpe_type(dev->wakeup.gpe_device, 
+                               dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
+                       /* Re-enable it, since set_gpe_type will disable it */
+                       acpi_enable_gpe(dev->wakeup.gpe_device, 
+                               dev->wakeup.gpe_number, ACPI_NOT_ISR);
+                       spin_lock(&acpi_device_lock);
+                       continue;
+               }
+
+               if (!dev->wakeup.flags.valid || 
+                       !dev->wakeup.state.active ||
+                       (sleep_state > (u32) dev->wakeup.sleep_state))
+                       continue;
+
+               spin_unlock(&acpi_device_lock);
+               acpi_disable_wakeup_device_power(dev);
+               /* Never disable run-wake GPE */
+               if (!dev->wakeup.flags.run_wake) {
+                       acpi_disable_gpe(dev->wakeup.gpe_device, 
+                               dev->wakeup.gpe_number, ACPI_NOT_ISR);
+                       acpi_clear_gpe(dev->wakeup.gpe_device, 
+                               dev->wakeup.gpe_number, ACPI_NOT_ISR);
+               }
+               dev->wakeup.state.active = 0;
+               spin_lock(&acpi_device_lock);
+       }
+       spin_unlock(&acpi_device_lock);
+}
+
+static int __init acpi_wakeup_device_init(void)
+{
+       struct list_head * node, * next;
+
+       if (acpi_disabled)
+               return 0;
+       printk("ACPI wakeup devices: \n");
+
+       spin_lock(&acpi_device_lock);
+       list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+               struct acpi_device * dev = container_of(node, 
+                       struct acpi_device, wakeup_list);
+               
+               /* In case user doesn't load button driver */
+               if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
+                       spin_unlock(&acpi_device_lock);
+                       acpi_set_gpe_type(dev->wakeup.gpe_device, 
+                               dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
+                       acpi_enable_gpe(dev->wakeup.gpe_device, 
+                               dev->wakeup.gpe_number, ACPI_NOT_ISR);
+                       dev->wakeup.state.enabled = 1;
+                       spin_lock(&acpi_device_lock);
+               }
+               printk("%4s ", dev->pnp.bus_id);
+       }
+       spin_unlock(&acpi_device_lock);
+       printk("\n");
+
+       return 0;
+}
+
+late_initcall(acpi_wakeup_device_init);
index b732834..4a96695 100644 (file)
@@ -115,17 +115,14 @@ acpi_tb_find_table (
  *              Instance        - the non zero instance of the table, allows
  *                                support for multiple tables of the same type
  *              Flags           - Physical/Virtual support
- *              ret_buffer      - pointer to a structure containing a buffer to
- *                                receive the table
+ *              table_pointer   - Where a buffer containing the table is
+ *                                returned
  *
  * RETURN:      Status
  *
- * DESCRIPTION: This function is called to get an ACPI table.  The caller
- *              supplies an out_buffer large enough to contain the entire ACPI
- *              table.  Upon completion
- *              the out_buffer->Length field will indicate the number of bytes
- *              copied into the out_buffer->buf_ptr buffer. This table will be
- *              a complete table including the header.
+ * DESCRIPTION: This function is called to get an ACPI table. A buffer is
+ *              allocated for the table and returned in table_pointer.
+ *              This table will be a complete table including the header.
  *
  ******************************************************************************/
 
@@ -136,12 +133,11 @@ acpi_get_firmware_table (
        u32                             flags,
        struct acpi_table_header        **table_pointer)
 {
-       struct acpi_pointer             rsdp_address;
-       struct acpi_pointer             address;
        acpi_status                     status;
-       struct acpi_table_header        header;
-       struct acpi_table_desc          table_info;
-       struct acpi_table_desc          rsdt_info;
+       struct acpi_pointer             address;
+       struct acpi_table_header        *header = NULL;
+       struct acpi_table_desc          *table_info = NULL;
+       struct acpi_table_desc          *rsdt_info;
        u32                             table_count;
        u32                             i;
        u32                             j;
@@ -152,45 +148,41 @@ acpi_get_firmware_table (
 
        /*
         * Ensure that at least the table manager is initialized.  We don't
-        * require that the entire ACPI subsystem is up for this interface
-        */
-
-       /*
-        *  If we have a buffer, we must have a length too
+        * require that the entire ACPI subsystem is up for this interface.
+        * If we have a buffer, we must have a length too
         */
-       if ((instance == 0)                 ||
-               (!signature)                    ||
+       if ((instance == 0)     ||
+               (!signature)        ||
                (!table_pointer)) {
                return_ACPI_STATUS (AE_BAD_PARAMETER);
        }
 
-       rsdt_info.pointer = NULL;
+       /* Ensure that we have a RSDP */
 
        if (!acpi_gbl_RSDP) {
                /* Get the RSDP */
 
-               status = acpi_os_get_root_pointer (flags, &rsdp_address);
+               status = acpi_os_get_root_pointer (flags, &address);
                if (ACPI_FAILURE (status)) {
-                       ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP  not found\n"));
+                       ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n"));
                        return_ACPI_STATUS (AE_NO_ACPI_TABLES);
                }
 
                /* Map and validate the RSDP */
 
                if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
-                       status = acpi_os_map_memory (rsdp_address.pointer.physical, sizeof (struct rsdp_descriptor),
+                       status = acpi_os_map_memory (address.pointer.physical, sizeof (struct rsdp_descriptor),
                                          (void *) &acpi_gbl_RSDP);
                        if (ACPI_FAILURE (status)) {
                                return_ACPI_STATUS (status);
                        }
                }
                else {
-                       acpi_gbl_RSDP = rsdp_address.pointer.logical;
+                       acpi_gbl_RSDP = address.pointer.logical;
                }
 
-               /*
-                *  The signature and checksum must both be correct
-                */
+               /* The signature and checksum must both be correct */
+
                if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
                        /* Nope, BAD Signature */
 
@@ -204,10 +196,9 @@ acpi_get_firmware_table (
                }
        }
 
-       /* Get the RSDT and validate it */
+       /* Get the RSDT address via the RSDP */
 
        acpi_tb_get_rsdt_address (&address);
-
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                "RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
                acpi_gbl_RSDP,
@@ -217,20 +208,40 @@ acpi_get_firmware_table (
 
        address.pointer_type |= flags;
 
-       status = acpi_tb_get_table (&address, &rsdt_info);
+       /* Get and validate the RSDT */
+
+       rsdt_info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc));
+       if (!rsdt_info) {
+               return_ACPI_STATUS (AE_NO_MEMORY);
+       }
+
+       status = acpi_tb_get_table (&address, rsdt_info);
        if (ACPI_FAILURE (status)) {
-               return_ACPI_STATUS (status);
+               goto cleanup;
        }
 
-       status = acpi_tb_validate_rsdt (rsdt_info.pointer);
+       status = acpi_tb_validate_rsdt (rsdt_info->pointer);
        if (ACPI_FAILURE (status)) {
                goto cleanup;
        }
 
-       /* Get the number of table pointers within the RSDT */
+       /* Allocate a scratch table header and table descriptor */
+
+       header = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_header));
+       if (!header) {
+               status = AE_NO_MEMORY;
+               goto cleanup;
+       }
+
+       table_info = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_desc));
+       if (!table_info) {
+               status = AE_NO_MEMORY;
+               goto cleanup;
+       }
 
-       table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info.pointer);
+       /* Get the number of table pointers within the RSDT */
 
+       table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info->pointer);
        address.pointer_type = acpi_gbl_table_flags | flags;
 
        /*
@@ -241,35 +252,36 @@ acpi_get_firmware_table (
                /* Get the next table pointer, handle RSDT vs. XSDT */
 
                if (acpi_gbl_RSDP->revision < 2) {
-                       address.pointer.value = (ACPI_CAST_PTR (RSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i];
+                       address.pointer.value = (ACPI_CAST_PTR (
+                               RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
                }
                else {
-                       address.pointer.value =
-                               (ACPI_CAST_PTR (XSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i];
+                       address.pointer.value = (ACPI_CAST_PTR (
+                               XSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
                }
 
                /* Get the table header */
 
-               status = acpi_tb_get_table_header (&address, &header);
+               status = acpi_tb_get_table_header (&address, header);
                if (ACPI_FAILURE (status)) {
                        goto cleanup;
                }
 
                /* Compare table signatures and table instance */
 
-               if (!ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) {
+               if (!ACPI_STRNCMP (header->signature, signature, ACPI_NAME_SIZE)) {
                        /* An instance of the table was found */
 
                        j++;
                        if (j >= instance) {
                                /* Found the correct instance, get the entire table */
 
-                               status = acpi_tb_get_table_body (&address, &header, &table_info);
+                               status = acpi_tb_get_table_body (&address, header, table_info);
                                if (ACPI_FAILURE (status)) {
                                        goto cleanup;
                                }
 
-                               *table_pointer = table_info.pointer;
+                               *table_pointer = table_info->pointer;
                                goto cleanup;
                        }
                }
@@ -281,7 +293,15 @@ acpi_get_firmware_table (
 
 
 cleanup:
-       acpi_os_unmap_memory (rsdt_info.pointer, (acpi_size) rsdt_info.pointer->length);
+       acpi_os_unmap_memory (rsdt_info->pointer, (acpi_size) rsdt_info->pointer->length);
+       ACPI_MEM_FREE (rsdt_info);
+
+       if (header) {
+               ACPI_MEM_FREE (header);
+       }
+       if (table_info) {
+               ACPI_MEM_FREE (table_info);
+       }
        return_ACPI_STATUS (status);
 }
 
@@ -389,14 +409,17 @@ acpi_tb_scan_memory_for_rsdp (
  *              Flags                   - Current memory mode (logical vs.
  *                                        physical addressing)
  *
- * RETURN:      Status
+ * RETURN:      Status, RSDP physical address
  *
  * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor
  *              pointer structure.  If it is found, set *RSDP to point to it.
  *
- *              NOTE: The RSDp must be either in the first 1_k of the Extended
- *              BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section
- *              5.2.2; assertion #421).
+ *              NOTE1: The RSDp must be either in the first 1_k of the Extended
+ *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
+ *              Only a 32-bit physical address is necessary.
+ *
+ *              NOTE2: This function is always available, regardless of the
+ *              initialization state of the rest of ACPI.
  *
  ******************************************************************************/
 
@@ -407,8 +430,8 @@ acpi_tb_find_rsdp (
 {
        u8                              *table_ptr;
        u8                              *mem_rover;
-       u64                             phys_addr;
-       acpi_status                     status = AE_OK;
+       u32                             physical_address;
+       acpi_status                     status;
 
 
        ACPI_FUNCTION_TRACE ("tb_find_rsdp");
@@ -419,36 +442,57 @@ acpi_tb_find_rsdp (
         */
        if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
                /*
-                * 1) Search EBDA (low memory) paragraphs
+                * 1a) Get the location of the EBDA
                 */
-               status = acpi_os_map_memory ((u64) ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE,
+               status = acpi_os_map_memory ((acpi_physical_address) ACPI_EBDA_PTR_LOCATION,
+                                 ACPI_EBDA_PTR_LENGTH,
                                  (void *) &table_ptr);
                if (ACPI_FAILURE (status)) {
-                       ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
-                               ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE));
+                       ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
+                               ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
                        return_ACPI_STATUS (status);
                }
 
-               mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE);
-               acpi_os_unmap_memory (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE);
+               ACPI_MOVE_16_TO_32 (&physical_address, table_ptr);
+               physical_address <<= 4;                 /* Convert segment to physical address */
+               acpi_os_unmap_memory (table_ptr, ACPI_EBDA_PTR_LENGTH);
 
-               if (mem_rover) {
-                       /* Found it, return the physical address */
+               /* EBDA present? */
 
-                       phys_addr = ACPI_LO_RSDP_WINDOW_BASE;
-                       phys_addr += ACPI_PTR_DIFF (mem_rover,table_ptr);
+               if (physical_address > 0x400) {
+                       /*
+                        * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length)
+                        */
+                       status = acpi_os_map_memory ((acpi_physical_address) physical_address,
+                                         ACPI_EBDA_WINDOW_SIZE,
+                                         (void *) &table_ptr);
+                       if (ACPI_FAILURE (status)) {
+                               ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
+                                       physical_address, ACPI_EBDA_WINDOW_SIZE));
+                               return_ACPI_STATUS (status);
+                       }
 
-                       table_info->physical_address = phys_addr;
-                       return_ACPI_STATUS (AE_OK);
+                       mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_EBDA_WINDOW_SIZE);
+                       acpi_os_unmap_memory (table_ptr, ACPI_EBDA_WINDOW_SIZE);
+
+                       if (mem_rover) {
+                               /* Found it, return the physical address */
+
+                               physical_address += ACPI_PTR_DIFF (mem_rover, table_ptr);
+
+                               table_info->physical_address = (acpi_physical_address) physical_address;
+                               return_ACPI_STATUS (AE_OK);
+                       }
                }
 
                /*
-                * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
+                * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
                 */
-               status = acpi_os_map_memory ((u64) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE,
+               status = acpi_os_map_memory ((acpi_physical_address) ACPI_HI_RSDP_WINDOW_BASE,
+                                 ACPI_HI_RSDP_WINDOW_SIZE,
                                  (void *) &table_ptr);
                if (ACPI_FAILURE (status)) {
-                       ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
+                       ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
                                ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE));
                        return_ACPI_STATUS (status);
                }
@@ -459,10 +503,9 @@ acpi_tb_find_rsdp (
                if (mem_rover) {
                        /* Found it, return the physical address */
 
-                       phys_addr = ACPI_HI_RSDP_WINDOW_BASE;
-                       phys_addr += ACPI_PTR_DIFF (mem_rover, table_ptr);
+                       physical_address = ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (mem_rover, table_ptr);
 
-                       table_info->physical_address = phys_addr;
+                       table_info->physical_address = (acpi_physical_address) physical_address;
                        return_ACPI_STATUS (AE_OK);
                }
        }
@@ -472,19 +515,29 @@ acpi_tb_find_rsdp (
         */
        else {
                /*
-                * 1) Search EBDA (low memory) paragraphs
+                * 1a) Get the location of the EBDA
                 */
-               mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_LO_RSDP_WINDOW_BASE),
-                                 ACPI_LO_RSDP_WINDOW_SIZE);
-               if (mem_rover) {
-                       /* Found it, return the physical address */
-
-                       table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
-                       return_ACPI_STATUS (AE_OK);
+               ACPI_MOVE_16_TO_32 (&physical_address, ACPI_EBDA_PTR_LOCATION);
+               physical_address <<= 4;     /* Convert segment to physical address */
+
+               /* EBDA present? */
+
+               if (physical_address > 0x400) {
+                       /*
+                        * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length)
+                        */
+                       mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (physical_address),
+                                         ACPI_EBDA_WINDOW_SIZE);
+                       if (mem_rover) {
+                               /* Found it, return the physical address */
+
+                               table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
+                               return_ACPI_STATUS (AE_OK);
+                       }
                }
 
                /*
-                * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
+                * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
                 */
                mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_HI_RSDP_WINDOW_BASE),
                                  ACPI_HI_RSDP_WINDOW_SIZE);
index 2050d23..58ec673 100644 (file)
@@ -259,8 +259,8 @@ acpi_ut_validate_buffer (
  *
  * FUNCTION:    acpi_ut_initialize_buffer
  *
- * PARAMETERS:  required_length     - Length needed
- *              Buffer              - Buffer to be validated
+ * PARAMETERS:  Buffer              - Buffer to be validated
+ *              required_length     - Length needed
  *
  * RETURN:      Status
  *
@@ -603,7 +603,8 @@ acpi_ut_free_and_track (
  *
  * FUNCTION:    acpi_ut_find_allocation
  *
- * PARAMETERS:  Allocation             - Address of allocated memory
+ * PARAMETERS:  list_id                 - Memory list to search
+ *              Allocation              - Address of allocated memory
  *
  * RETURN:      A list element if found; NULL otherwise.
  *
@@ -646,7 +647,8 @@ acpi_ut_find_allocation (
  *
  * FUNCTION:    acpi_ut_track_allocation
  *
- * PARAMETERS:  Allocation          - Address of allocated memory
+ * PARAMETERS:  list_id             - Memory list to search
+ *              Allocation          - Address of allocated memory
  *              Size                - Size of the allocation
  *              alloc_type          - MEM_MALLOC or MEM_CALLOC
  *              Component           - Component type of caller
@@ -733,7 +735,8 @@ unlock_and_exit:
  *
  * FUNCTION:    acpi_ut_remove_allocation
  *
- * PARAMETERS:  Allocation          - Address of allocated memory
+ * PARAMETERS:  list_id             - Memory list to search
+ *              Allocation          - Address of allocated memory
  *              Component           - Component type of caller
  *              Module              - Source file name of caller
  *              Line                - Line number of caller
index c3f5900..0aa1fde 100644 (file)
@@ -133,7 +133,7 @@ acpi_ut_evaluate_object (
        u32                             expected_return_btypes,
        union acpi_operand_object       **return_desc)
 {
-       union acpi_operand_object       *obj_desc;
+       struct acpi_parameter_info      info;
        acpi_status                     status;
        u32                             return_btype;
 
@@ -141,9 +141,13 @@ acpi_ut_evaluate_object (
        ACPI_FUNCTION_TRACE ("ut_evaluate_object");
 
 
+       info.node = prefix_node;
+       info.parameters = NULL;
+       info.parameter_type = ACPI_PARAM_ARGS;
+
        /* Evaluate the object/method */
 
-       status = acpi_ns_evaluate_relative (prefix_node, path, NULL, &obj_desc);
+       status = acpi_ns_evaluate_relative (path, &info);
        if (ACPI_FAILURE (status)) {
                if (status == AE_NOT_FOUND) {
                        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n",
@@ -159,7 +163,7 @@ acpi_ut_evaluate_object (
 
        /* Did we get a return object? */
 
-       if (!obj_desc) {
+       if (!info.return_object) {
                if (expected_return_btypes) {
                        ACPI_REPORT_METHOD_ERROR ("No object was returned from",
                                prefix_node, path, AE_NOT_EXIST);
@@ -172,7 +176,7 @@ acpi_ut_evaluate_object (
 
        /* Map the return object type to the bitmapped type */
 
-       switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+       switch (ACPI_GET_OBJECT_TYPE (info.return_object)) {
        case ACPI_TYPE_INTEGER:
                return_btype = ACPI_BTYPE_INTEGER;
                break;
@@ -202,17 +206,17 @@ acpi_ut_evaluate_object (
 
                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
                        "Type returned from %s was incorrect: %X\n",
-                       path, ACPI_GET_OBJECT_TYPE (obj_desc)));
+                       path, ACPI_GET_OBJECT_TYPE (info.return_object)));
 
                /* On error exit, we must delete the return object */
 
-               acpi_ut_remove_reference (obj_desc);
+               acpi_ut_remove_reference (info.return_object);
                return_ACPI_STATUS (AE_TYPE);
        }
 
        /* Object type is OK, return it */
 
-       *return_desc = obj_desc;
+       *return_desc = info.return_object;
        return_ACPI_STATUS (AE_OK);
 }
 
index e1d1993..f42848a 100644 (file)
@@ -142,16 +142,11 @@ unknown:
  */
 
 /* Debug switch - level and trace mask */
-
-#ifdef ACPI_DEBUG_OUTPUT
-u32                                 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
-#else
-u32                                 acpi_dbg_level = ACPI_NORMAL_DEFAULT;
-#endif
+u32                                 acpi_dbg_level = 0;
 
 /* Debug switch - layer (component) mask */
 
-u32                                 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT;
+u32                                 acpi_dbg_layer = 0;
 u32                                 acpi_gbl_nesting_level = 0;
 
 
@@ -171,27 +166,40 @@ u8                                  acpi_gbl_shutdown = TRUE;
 
 const u8                            acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128};
 
-const char                          *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
-                         "\\_S0_",
-                         "\\_S1_",
-                         "\\_S2_",
-                         "\\_S3_",
-                         "\\_S4_",
-                         "\\_S5_"};
-
-const char                          *acpi_gbl_highest_dstate_names[4] = {
-                                          "_S1D",
-                                          "_S2D",
-                                          "_S3D",
-                                          "_S4D"};
+const char                          *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] =
+{
+       "\\_S0_",
+       "\\_S1_",
+       "\\_S2_",
+       "\\_S3_",
+       "\\_S4_",
+       "\\_S5_"
+};
 
-/* Strings supported by the _OSI predefined (internal) method */
+const char                          *acpi_gbl_highest_dstate_names[4] =
+{
+       "_S1D",
+       "_S2D",
+       "_S3D",
+       "_S4D"
+};
 
-const char                          *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = {
-                                                        "Linux",
-                                                        "Windows 2000",
-                                                        "Windows 2001",
-                                                        "Windows 2001.1"};
+/*
+ * Strings supported by the _OSI predefined (internal) method.
+ * When adding strings, be sure to update ACPI_NUM_OSI_STRINGS.
+ */
+const char                          *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] =
+{
+       "Linux",
+       "Windows 2000",
+       "Windows 2001",
+       "Windows 2001.1",
+       "Windows 2001 SP0",
+       "Windows 2001 SP1",
+       "Windows 2001 SP2",
+       "Windows 2001 SP3",
+       "Windows 2001 SP4"
+};
 
 
 /******************************************************************************
@@ -213,7 +221,7 @@ const struct acpi_predefined_names      acpi_gbl_pre_defined_names[] =
        {"_PR_",    ACPI_TYPE_LOCAL_SCOPE,      NULL},
        {"_SB_",    ACPI_TYPE_DEVICE,           NULL},
        {"_SI_",    ACPI_TYPE_LOCAL_SCOPE,      NULL},
-       {"_TZ_",    ACPI_TYPE_LOCAL_SCOPE,      NULL},
+       {"_TZ_",    ACPI_TYPE_THERMAL,          NULL},
        {"_REV",    ACPI_TYPE_INTEGER,          "2"},
        {"_OS_",    ACPI_TYPE_STRING,           ACPI_OS_NAME},
        {"_GL_",    ACPI_TYPE_MUTEX,            "0"},
@@ -561,26 +569,37 @@ acpi_ut_get_node_name (
        struct acpi_namespace_node      *node = (struct acpi_namespace_node *) object;
 
 
+       /* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */
+
        if (!object)
        {
-               return ("NULL NODE");
+               return ("NULL");
        }
 
-       if (object == ACPI_ROOT_OBJECT)
+       /* Check for Root node */
+
+       if ((object == ACPI_ROOT_OBJECT) ||
+               (object == acpi_gbl_root_node))
        {
-               node = acpi_gbl_root_node;
+               return ("\"\\\" ");
        }
 
+       /* Descriptor must be a namespace node */
+
        if (node->descriptor != ACPI_DESC_TYPE_NAMED)
        {
-               return ("****");
+               return ("####");
        }
 
+       /* Name must be a valid ACPI name */
+
        if (!acpi_ut_valid_acpi_name (* (u32 *) node->name.ascii))
        {
-               return ("----");
+               return ("????");
        }
 
+       /* Return the name */
+
        return (node->name.ascii);
 }
 
@@ -783,10 +802,6 @@ acpi_ut_init_globals (
 
        ACPI_FUNCTION_TRACE ("ut_init_globals");
 
-       /* Runtime configuration */
-
-       acpi_gbl_create_osi_method = TRUE;
-       acpi_gbl_all_methods_serialized = FALSE;
 
        /* Memory allocation and cache lists */
 
@@ -880,6 +895,7 @@ acpi_ut_init_globals (
        /* Hardware oriented */
 
        acpi_gbl_events_initialized         = FALSE;
+       acpi_gbl_system_awake_and_running   = TRUE;
 
        /* Namespace */
 
index 5cbd93e..45c14f9 100644 (file)
@@ -157,9 +157,8 @@ acpi_enable_subsystem (
                }
        }
 
-       /*
-        * Enable ACPI mode
-        */
+       /* Enable ACPI mode */
+
        if (!(flags & ACPI_NO_ACPI_ENABLE)) {
                ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n"));
 
@@ -173,7 +172,21 @@ acpi_enable_subsystem (
        }
 
        /*
-        * Initialize ACPI Event handling
+        * Install the default op_region handlers. These are installed unless
+        * other handlers have already been installed via the
+        * install_address_space_handler interface.
+        */
+       if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
+               ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n"));
+
+               status = acpi_ev_install_region_handlers ();
+               if (ACPI_FAILURE (status)) {
+                       return_ACPI_STATUS (status);
+               }
+       }
+
+       /*
+        * Initialize ACPI Event handling (Fixed and General Purpose)
         *
         * NOTE: We must have the hardware AND events initialized before we can execute
         * ANY control methods SAFELY.  Any control method can require ACPI hardware
@@ -182,18 +195,18 @@ acpi_enable_subsystem (
        if (!(flags & ACPI_NO_EVENT_INIT)) {
                ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI events\n"));
 
-               status = acpi_ev_initialize ();
+               status = acpi_ev_initialize_events ();
                if (ACPI_FAILURE (status)) {
                        return_ACPI_STATUS (status);
                }
        }
 
-       /* Install the SCI handler, Global Lock handler, and GPE handlers */
+       /* Install the SCI handler and Global Lock handler */
 
        if (!(flags & ACPI_NO_HANDLER_INIT)) {
-               ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL/GPE handlers\n"));
+               ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL handlers\n"));
 
-               status = acpi_ev_handler_initialize ();
+               status = acpi_ev_install_xrupt_handlers ();
                if (ACPI_FAILURE (status)) {
                        return_ACPI_STATUS (status);
                }
@@ -226,18 +239,16 @@ acpi_initialize_objects (
 
 
        /*
-        * Install the default op_region handlers. These are installed unless
-        * other handlers have already been installed via the
-        * install_address_space_handler interface.
+        * Run all _REG methods
         *
-        * NOTE: This will cause _REG methods to be run.  Any objects accessed
+        * NOTE: Any objects accessed
         * by the _REG methods will be automatically initialized, even if they
         * contain executable AML (see call to acpi_ns_initialize_objects below).
         */
        if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
-               ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n"));
+               ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Executing _REG op_region methods\n"));
 
-               status = acpi_ev_init_address_spaces ();
+               status = acpi_ev_initialize_op_regions ();
                if (ACPI_FAILURE (status)) {
                        return_ACPI_STATUS (status);
                }
@@ -249,7 +260,7 @@ acpi_initialize_objects (
         * objects: operation_regions, buffer_fields, Buffers, and Packages.
         */
        if (!(flags & ACPI_NO_OBJECT_INIT)) {
-               ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Objects\n"));
+               ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Completing Initialization of ACPI Objects\n"));
 
                status = acpi_ns_initialize_objects ();
                if (ACPI_FAILURE (status)) {
index bcd60fb..907c593 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 fore_200e-objs := fore200e.o
-host-progs     := fore200e_mkfirm
+hostprogs-y    := fore200e_mkfirm
 
 # Files generated that shall be removed upon make clean
 clean-files := atmsar11.bin atmsar11.bin1 atmsar11.bin2 pca200e.bin \
index 8b13703..81127d1 100644 (file)
@@ -173,7 +173,7 @@ static void dump_mem(struct eni_dev *eni_dev)
        int i;
 
        for (i = 0; i < eni_dev->free_len; i++)
-               printk(KERN_DEBUG "  %d: 0x%lx %d\n",i,
+               printk(KERN_DEBUG "  %d: %p %d\n",i,
                    eni_dev->free_list[i].start,
                    1 << eni_dev->free_list[i].order);
 }
@@ -191,19 +191,19 @@ static void dump(struct atm_dev *dev)
        printk(KERN_NOTICE "TX buffers\n");
        for (i = 0; i < NR_CHAN; i++)
                if (eni_dev->tx[i].send)
-                       printk(KERN_NOTICE "  TX %d @ 0x%lx: %ld\n",i,
+                       printk(KERN_NOTICE "  TX %d @ %p: %ld\n",i,
                            eni_dev->tx[i].send,eni_dev->tx[i].words*4);
        printk(KERN_NOTICE "RX buffers\n");
        for (i = 0; i < 1024; i++)
                if (eni_dev->rx_map[i] && ENI_VCC(eni_dev->rx_map[i])->rx)
-                       printk(KERN_NOTICE "  RX %d @ 0x%lx: %ld\n",i,
+                       printk(KERN_NOTICE "  RX %d @ %p: %ld\n",i,
                            ENI_VCC(eni_dev->rx_map[i])->recv,
                            ENI_VCC(eni_dev->rx_map[i])->words*4);
        printk(KERN_NOTICE "----\n");
 }
 
 
-static void eni_put_free(struct eni_dev *eni_dev,unsigned long start,
+static void eni_put_free(struct eni_dev *eni_dev, void __iomem *start,
     unsigned long size)
 {
        struct eni_free *list;
@@ -215,17 +215,17 @@ static void eni_put_free(struct eni_dev *eni_dev,unsigned long start,
        len = eni_dev->free_len;
        while (size) {
                if (len >= eni_dev->free_list_size) {
-                       printk(KERN_CRIT "eni_put_free overflow (0x%lx,%ld)\n",
+                       printk(KERN_CRIT "eni_put_free overflow (%p,%ld)\n",
                            start,size);
                        break;
                }
-               for (order = 0; !((start | size) & (1 << order)); order++);
+               for (order = 0; !(((unsigned long)start | size) & (1 << order)); order++);
                if (MID_MIN_BUF_SIZE > (1 << order)) {
                        printk(KERN_CRIT "eni_put_free: order %d too small\n",
                            order);
                        break;
                }
-               list[len].start = start;
+               list[len].start = (void __iomem *) start;
                list[len].order = order;
                len++;
                start += 1 << order;
@@ -236,10 +236,10 @@ static void eni_put_free(struct eni_dev *eni_dev,unsigned long start,
 }
 
 
-static unsigned long eni_alloc_mem(struct eni_dev *eni_dev,unsigned long *size)
+static void __iomem *eni_alloc_mem(struct eni_dev *eni_dev, unsigned long *size)
 {
        struct eni_free *list;
-       unsigned long start;
+       void __iomem *start;
        int len,i,order,best_order,index;
 
        list = eni_dev->free_list;
@@ -273,7 +273,7 @@ static unsigned long eni_alloc_mem(struct eni_dev *eni_dev,unsigned long *size)
 }
 
 
-static void eni_free_mem(struct eni_dev *eni_dev,unsigned long start,
+static void eni_free_mem(struct eni_dev *eni_dev, void __iomem *start,
     unsigned long size)
 {
        struct eni_free *list;
@@ -283,20 +283,20 @@ static void eni_free_mem(struct eni_dev *eni_dev,unsigned long start,
        list = eni_dev->free_list;
        len = eni_dev->free_len;
        for (order = -1; size; order++) size >>= 1;
-       DPRINTK("eni_free_mem: 0x%lx+0x%lx (order %d)\n",start,size,order);
+       DPRINTK("eni_free_mem: %p+0x%lx (order %d)\n",start,size,order);
        for (i = 0; i < len; i++)
-               if (list[i].start == (start^(1 << order)) &&
+               if (((unsigned long) list[i].start) == ((unsigned long)start^(1 << order)) &&
                    list[i].order == order) {
                        DPRINTK("match[%d]: 0x%lx/0x%lx(0x%x), %d/%d\n",i,
                            list[i].start,start,1 << order,list[i].order,order);
                        list[i] = list[--len];
-                       start &= ~(unsigned long) (1 << order);
+                       start = (void __iomem *) ((unsigned long) start & ~(unsigned long) (1 << order));
                        order++;
                        i = -1;
                        continue;
                }
        if (len >= eni_dev->free_list_size) {
-               printk(KERN_ALERT "eni_free_mem overflow (0x%lx,%d)\n",start,
+               printk(KERN_ALERT "eni_free_mem overflow (%p,%d)\n",start,
                    order);
                return;
        }
@@ -333,7 +333,7 @@ static void rx_ident_err(struct atm_vcc *vcc)
        printk(KERN_ALERT "  host descr 0x%lx, rx pos 0x%lx, descr value "
            "0x%x\n",eni_vcc->descr,eni_vcc->rx_pos,
            (unsigned) readl(eni_vcc->recv+eni_vcc->descr*4));
-       printk(KERN_ALERT "  last 0x%p, servicing %d\n",eni_vcc->last,
+       printk(KERN_ALERT "  last %p, servicing %d\n",eni_vcc->last,
            eni_vcc->servicing);
        EVENT("---dump ends here---\n",0,0);
        printk(KERN_NOTICE "---recent events---\n");
@@ -617,7 +617,8 @@ static int rx_aal5(struct atm_vcc *vcc)
 
 static inline int rx_vcc(struct atm_vcc *vcc)
 {
-       unsigned long vci_dsc,tmp;
+       void __iomem *vci_dsc;
+       unsigned long tmp;
        struct eni_vcc *eni_vcc;
 
        eni_vcc = ENI_VCC(vcc);
@@ -728,7 +729,7 @@ static void dequeue_rx(struct atm_dev *dev)
        struct eni_vcc *eni_vcc;
        struct atm_vcc *vcc;
        struct sk_buff *skb;
-       unsigned long vci_dsc;
+       void __iomem *vci_dsc;
        int first;
 
        eni_dev = ENI_DEV(dev);
@@ -808,7 +809,7 @@ static int open_rx_first(struct atm_vcc *vcc)
 
 static int open_rx_second(struct atm_vcc *vcc)
 {
-       unsigned long here;
+       void __iomem *here;
        struct eni_dev *eni_dev;
        struct eni_vcc *eni_vcc;
        unsigned long size;
@@ -840,7 +841,7 @@ static int open_rx_second(struct atm_vcc *vcc)
 static void close_rx(struct atm_vcc *vcc)
 {
        DECLARE_WAITQUEUE(wait,current);
-       unsigned long here;
+       void __iomem *here;
        struct eni_dev *eni_dev;
        struct eni_vcc *eni_vcc;
 
@@ -1289,7 +1290,8 @@ static int reserve_or_set_tx(struct atm_vcc *vcc,struct atm_trafprm *txtp,
        struct eni_dev *eni_dev = ENI_DEV(vcc->dev);
        struct eni_vcc *eni_vcc = ENI_VCC(vcc);
        struct eni_tx *tx;
-       unsigned long size,mem;
+       unsigned long size;
+       void __iomem *mem;
        int rate,ubr,unlimited,new_tx;
        int pre,res,order;
        int error;
@@ -1687,9 +1689,9 @@ static int __devinit get_esi_asic(struct atm_dev *dev)
 #undef GET_SEPROM
 
 
-static int __devinit get_esi_fpga(struct atm_dev *dev,unsigned long base)
+static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base)
 {
-       unsigned long mac_base;
+       void __iomem *mac_base;
        int i;
 
        mac_base = base+EPROM_SIZE-sizeof(struct midway_eprom);
@@ -1703,7 +1705,8 @@ static int __devinit eni_do_init(struct atm_dev *dev)
        struct midway_eprom *eprom;
        struct eni_dev *eni_dev;
        struct pci_dev *pci_dev;
-       unsigned long real_base,base;
+       unsigned long real_base;
+       void __iomem *base;
        unsigned char revision;
        int error,i,last;
 
@@ -1730,13 +1733,13 @@ static int __devinit eni_do_init(struct atm_dev *dev)
        }
        printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,",
            dev->number,revision,real_base,eni_dev->irq);
-       if (!(base = (unsigned long) ioremap_nocache(real_base,MAP_MAX_SIZE))) {
+       if (!(base = ioremap_nocache(real_base,MAP_MAX_SIZE))) {
                printk("\n");
                printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page "
                    "mapping\n",dev->number);
                return error;
        }
-       eni_dev->base_diff = real_base-base;
+       eni_dev->base_diff = real_base - (unsigned long) base;
        /* id may not be present in ASIC Tonga boards - check this @@@ */
        if (!eni_dev->asic) {
                eprom = (struct midway_eprom *) (base+EPROM_SIZE-sizeof(struct
@@ -1790,7 +1793,9 @@ static int __devinit eni_do_init(struct atm_dev *dev)
 static int __devinit eni_start(struct atm_dev *dev)
 {
        struct eni_dev *eni_dev;
-       unsigned long buf,buffer_mem;
+       
+       void __iomem *buf;
+       unsigned long buffer_mem;
        int error;
 
        DPRINTK(">eni_start\n");
@@ -1828,7 +1833,7 @@ static int __devinit eni_start(struct atm_dev *dev)
        tasklet_init(&eni_dev->task,eni_tasklet,(unsigned long) dev);
        eni_dev->events = 0;
        /* initialize memory management */
-       buffer_mem = eni_dev->mem-(buf-eni_dev->ram);
+       buffer_mem = eni_dev->mem - (buf - eni_dev->ram);
        eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
        eni_dev->free_list = (struct eni_free *) kmalloc(
            sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL);
@@ -1955,7 +1960,7 @@ static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs)
         */
        tasklet_disable(&eni_dev->task);
        skb_queue_walk(&eni_dev->tx_queue, skb) {
-               unsigned long dsc;
+               void __iomem *dsc;
 
                if (ATM_SKB(skb)->vcc != vcc) continue;
                dsc = tx->send+ENI_PRV_POS(skb)*4;
@@ -2136,9 +2141,9 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
 
                if (!tx->send) continue;
                if (!--left) {
-                       return sprintf(page,"tx[%d]:    0x%06lx-0x%06lx "
+                       return sprintf(page,"tx[%d]:    0x%ld-0x%ld "
                            "(%6ld bytes), rsv %d cps, shp %d cps%s\n",i,
-                           tx->send-eni_dev->ram,
+                           (unsigned long) (tx->send - eni_dev->ram),
                            tx->send-eni_dev->ram+tx->words*4-1,tx->words*4,
                            tx->reserved,tx->shaping,
                            tx == eni_dev->ubr ? " (UBR)" : "");
@@ -2162,9 +2167,9 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
                        if (--left) continue;
                        length = sprintf(page,"vcc %4d: ",vcc->vci);
                        if (eni_vcc->rx) {
-                               length += sprintf(page+length,"0x%06lx-0x%06lx "
+                               length += sprintf(page+length,"0x%ld-0x%ld "
                                    "(%6ld bytes)",
-                                   eni_vcc->recv-eni_dev->ram,
+                                   (unsigned long) (eni_vcc->recv - eni_dev->ram),
                                    eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1,
                                    eni_vcc->words*4);
                                if (eni_vcc->tx) length += sprintf(page+length,", ");
@@ -2183,8 +2188,8 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
                unsigned long offset;
 
                if (--left) continue;
-               offset = eni_dev->ram+eni_dev->base_diff;
-               return sprintf(page,"free      0x%06lx-0x%06lx (%6d bytes)\n",
+               offset = (unsigned long) eni_dev->ram+eni_dev->base_diff;
+               return sprintf(page,"free      %p-%p (%6d bytes)\n",
                    fe->start-offset,fe->start-offset+(1 << fe->order)-1,
                    1 << fe->order);
        }
index e7af66b..385090c 100644 (file)
 
 
 struct eni_free {
-       unsigned long start;            /* counting in bytes */
+       void __iomem *start;            /* counting in bytes */
        int order;
 };
 
 struct eni_tx {
-       unsigned long send;             /* base, 0 if unused */
+       void __iomem *send;             /* base, 0 if unused */
        int prescaler;                  /* shaping prescaler */
        int resolution;                 /* shaping divider */
        unsigned long tx_pos;           /* current TX write position */
@@ -51,7 +51,7 @@ struct eni_tx {
 
 struct eni_vcc {
        int (*rx)(struct atm_vcc *vcc); /* RX function, NULL if none */
-       unsigned long recv;             /* receive buffer */
+       void __iomem *recv;             /* receive buffer */
        unsigned long words;            /* its size in words */
        unsigned long descr;            /* next descriptor (RX) */
        unsigned long rx_pos;           /* current RX descriptor pos */
@@ -72,13 +72,13 @@ struct eni_dev {
        u32 events;                     /* pending events */
        /*-------------------------------- base pointers into Midway address
                                           space */
-       unsigned long phy;              /* PHY interface chip registers */
-       unsigned long reg;              /* register base */
-       unsigned long ram;              /* RAM base */
-       unsigned long vci;              /* VCI table */
-       unsigned long rx_dma;           /* RX DMA queue */
-       unsigned long tx_dma;           /* TX DMA queue */
-       unsigned long service;          /* service list */
+       void __iomem *phy;              /* PHY interface chip registers */
+       void __iomem *reg;              /* register base */
+       void __iomem *ram;              /* RAM base */
+       void __iomem *vci;              /* VCI table */
+       void __iomem *rx_dma;           /* RX DMA queue */
+       void __iomem *tx_dma;           /* TX DMA queue */
+       void __iomem *service;          /* service list */
        /*-------------------------------- TX part */
        struct eni_tx tx[NR_CHAN];      /* TX channels */
        struct eni_tx *ubr;             /* UBR channel */
index 8ef266c..49e783e 100644 (file)
@@ -477,7 +477,7 @@ struct fs_dev {
        struct timer_list timer;
 
        unsigned long hw_base;          /* mem base address */
-       unsigned long base;             /* Mapping of base address */
+       void __iomem *base;             /* Mapping of base address */
        int channo;
        unsigned long channel_mask;
 
index 0a4adaf..7075ef4 100644 (file)
@@ -265,7 +265,7 @@ struct he_cs_stper
 struct he_dev {
        unsigned int number;
        unsigned int irq;
-       unsigned long membase;
+       void __iomem *membase;
 
        char prod_id[30];
        char mac_addr[6];
index 5a087c4..cfdd15e 100644 (file)
@@ -355,9 +355,9 @@ struct idt77252_dev
        struct pci_dev          *pcidev;        /* PCI handle (desriptor) */
        struct atm_dev          *atmdev;        /* ATM device desriptor */
 
-       unsigned long           membase;        /* SAR's memory base address */
+       void __iomem            *membase;       /* SAR's memory base address */
        unsigned long           srambase;       /* SAR's sram  base address */
-       unsigned long           fbq[4];         /* FBQ fill addresses */
+       void __iomem            *fbq[4];        /* FBQ fill addresses */
 
        struct semaphore        mutex;
        spinlock_t              cmd_lock;       /* for r/w utility/sram */
index b63669c..3f18782 100644 (file)
@@ -467,6 +467,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
    u32 u32d[4];
    u32 ns_cfg_rctsize;
    int bcount;
+   unsigned long membase;
 
    error = 0;
 
@@ -494,8 +495,8 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
    card->index = i;
    card->atmdev = NULL;
    card->pcidev = pcidev;
-   card->membase = pci_resource_start(pcidev, 1);
-   card->membase = (unsigned long) ioremap(card->membase, NS_IOREMAP_SIZE);
+   membase = pci_resource_start(pcidev, 1);
+   card->membase = ioremap(membase, NS_IOREMAP_SIZE);
    if (card->membase == 0)
    {
       printk("nicstar%d: can't ioremap() membase.\n",i);
index f762abc..a7eaee7 100644 (file)
@@ -763,7 +763,7 @@ typedef struct ns_dev
 {
    int index;                          /* Card ID to the device driver */
    int sram_size;                      /* In k x 32bit words. 32 or 128 */
-   unsigned long membase;                      /* Card's memory base address */
+   void __iomem *membase;              /* Card's memory base address */
    unsigned long max_pcr;
    int rct_size;                       /* Number of entries */
    int vpibits;
index ef6b0c9..7a842ef 100644 (file)
@@ -162,7 +162,7 @@ nicstar_read_eprom_status( virt_addr_t base )
  */
  
 static u_int8_t 
-read_eprom_byte(u_int32_t base, u_int8_t offset)
+read_eprom_byte(virt_addr_t base, u_int8_t offset)
 {
    u_int32_t val = 0;
    int i,j=0;
index 0592dae..80beec5 100644 (file)
@@ -7,7 +7,7 @@
  ******************************************************************************/
 
 
-typedef unsigned int virt_addr_t;
+typedef void __iomem *virt_addr_t;
 
 u_int32_t nicstar_read_eprom_status( virt_addr_t base );
 void nicstar_init_eprom( virt_addr_t base );
index be8f899..d5e8e71 100644 (file)
@@ -2282,8 +2282,8 @@ DAC960_Command_T;
 
 typedef struct DAC960_Controller
 {
-  void *BaseAddress;
-  void *MemoryMappedAddress;
+  void __iomem *BaseAddress;
+  void __iomem *MemoryMappedAddress;
   DAC960_FirmwareType_T FirmwareType;
   DAC960_HardwareType_T HardwareType;
   DAC960_IO_Address_T IO_Address;
@@ -2527,7 +2527,7 @@ DAC960_Controller_T;
  * dma_addr_t.
  */
 static inline
-void dma_addr_writeql(dma_addr_t addr, void *write_address)
+void dma_addr_writeql(dma_addr_t addr, void __iomem *write_address)
 {
        union {
                u64 wq;
@@ -2643,7 +2643,7 @@ DAC960_BA_ErrorStatusRegister_T;
 */
 
 static inline
-void DAC960_BA_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_BA_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2653,7 +2653,7 @@ void DAC960_BA_HardwareMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2663,7 +2663,7 @@ void DAC960_BA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2673,7 +2673,7 @@ void DAC960_BA_GenerateInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_ControllerReset(void *ControllerBaseAddress)
+void DAC960_BA_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2683,7 +2683,7 @@ void DAC960_BA_ControllerReset(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_BA_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2693,7 +2693,7 @@ void DAC960_BA_MemoryMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_BA_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_BA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -2702,7 +2702,7 @@ boolean DAC960_BA_HardwareMailboxFullP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_BA_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_BA_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -2711,7 +2711,7 @@ boolean DAC960_BA_InitializationInProgressP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -2721,7 +2721,7 @@ void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -2731,7 +2731,7 @@ void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -2742,7 +2742,7 @@ void DAC960_BA_AcknowledgeInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_BA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_BA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -2751,7 +2751,7 @@ boolean DAC960_BA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_BA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_BA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -2760,7 +2760,7 @@ boolean DAC960_BA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_BA_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -2771,7 +2771,7 @@ void DAC960_BA_EnableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_BA_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -2782,7 +2782,7 @@ void DAC960_BA_DisableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_BA_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_BA_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -2805,7 +2805,7 @@ void DAC960_BA_WriteCommandMailbox(DAC960_V2_CommandMailbox_T
 
 
 static inline
-void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_BA_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
                                    dma_addr_t CommandMailboxDMA)
 {
        dma_addr_writeql(CommandMailboxDMA,
@@ -2814,19 +2814,19 @@ void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress,
 }
 
 static inline DAC960_V2_CommandIdentifier_T
-DAC960_BA_ReadCommandIdentifier(void *ControllerBaseAddress)
+DAC960_BA_ReadCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset);
 }
 
 static inline DAC960_V2_CommandStatus_T
-DAC960_BA_ReadCommandStatus(void *ControllerBaseAddress)
+DAC960_BA_ReadCommandStatus(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset + 2);
 }
 
 static inline boolean
-DAC960_BA_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_BA_ReadErrorStatus(void __iomem *ControllerBaseAddress,
                          unsigned char *ErrorStatus,
                          unsigned char *Parameter0,
                          unsigned char *Parameter1)
@@ -2948,7 +2948,7 @@ DAC960_LP_ErrorStatusRegister_T;
 */
 
 static inline
-void DAC960_LP_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LP_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2958,7 +2958,7 @@ void DAC960_LP_HardwareMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2968,7 +2968,7 @@ void DAC960_LP_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2978,7 +2978,7 @@ void DAC960_LP_GenerateInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_ControllerReset(void *ControllerBaseAddress)
+void DAC960_LP_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2988,7 +2988,7 @@ void DAC960_LP_ControllerReset(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LP_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2998,7 +2998,7 @@ void DAC960_LP_MemoryMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LP_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_LP_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3007,7 +3007,7 @@ boolean DAC960_LP_HardwareMailboxFullP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LP_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_LP_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3016,7 +3016,7 @@ boolean DAC960_LP_InitializationInProgressP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3026,7 +3026,7 @@ void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3036,7 +3036,7 @@ void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3047,7 +3047,7 @@ void DAC960_LP_AcknowledgeInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LP_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LP_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3056,7 +3056,7 @@ boolean DAC960_LP_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LP_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LP_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3065,7 +3065,7 @@ boolean DAC960_LP_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_LP_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3075,7 +3075,7 @@ void DAC960_LP_EnableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_LP_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3085,7 +3085,7 @@ void DAC960_LP_DisableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LP_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_LP_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3107,7 +3107,7 @@ void DAC960_LP_WriteCommandMailbox(DAC960_V2_CommandMailbox_T
 }
 
 static inline
-void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_LP_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
                                    dma_addr_t CommandMailboxDMA)
 {
        dma_addr_writeql(CommandMailboxDMA,
@@ -3116,19 +3116,19 @@ void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress,
 }
 
 static inline DAC960_V2_CommandIdentifier_T
-DAC960_LP_ReadCommandIdentifier(void *ControllerBaseAddress)
+DAC960_LP_ReadCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset);
 }
 
 static inline DAC960_V2_CommandStatus_T
-DAC960_LP_ReadCommandStatus(void *ControllerBaseAddress)
+DAC960_LP_ReadCommandStatus(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset + 2);
 }
 
 static inline boolean
-DAC960_LP_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_LP_ReadErrorStatus(void __iomem *ControllerBaseAddress,
                          unsigned char *ErrorStatus,
                          unsigned char *Parameter0,
                          unsigned char *Parameter1)
@@ -3262,7 +3262,7 @@ DAC960_LA_ErrorStatusRegister_T;
 */
 
 static inline
-void DAC960_LA_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LA_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3272,7 +3272,7 @@ void DAC960_LA_HardwareMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3282,7 +3282,7 @@ void DAC960_LA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3292,7 +3292,7 @@ void DAC960_LA_GenerateInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_ControllerReset(void *ControllerBaseAddress)
+void DAC960_LA_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3302,7 +3302,7 @@ void DAC960_LA_ControllerReset(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LA_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3312,7 +3312,7 @@ void DAC960_LA_MemoryMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LA_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_LA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3321,7 +3321,7 @@ boolean DAC960_LA_HardwareMailboxFullP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LA_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_LA_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3330,7 +3330,7 @@ boolean DAC960_LA_InitializationInProgressP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3340,7 +3340,7 @@ void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3350,7 +3350,7 @@ void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3361,7 +3361,7 @@ void DAC960_LA_AcknowledgeInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3370,7 +3370,7 @@ boolean DAC960_LA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3379,7 +3379,7 @@ boolean DAC960_LA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_LA_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3389,7 +3389,7 @@ void DAC960_LA_EnableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_LA_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3399,7 +3399,7 @@ void DAC960_LA_DisableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LA_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_LA_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3422,7 +3422,7 @@ void DAC960_LA_WriteCommandMailbox(DAC960_V1_CommandMailbox_T
 }
 
 static inline
-void DAC960_LA_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_LA_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
                                    DAC960_V1_CommandMailbox_T *CommandMailbox)
 {
   writel(CommandMailbox->Words[0],
@@ -3436,20 +3436,20 @@ void DAC960_LA_WriteHardwareMailbox(void *ControllerBaseAddress,
 }
 
 static inline DAC960_V1_CommandIdentifier_T
-DAC960_LA_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+DAC960_LA_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readb(ControllerBaseAddress
               + DAC960_LA_StatusCommandIdentifierRegOffset);
 }
 
 static inline DAC960_V1_CommandStatus_T
-DAC960_LA_ReadStatusRegister(void *ControllerBaseAddress)
+DAC960_LA_ReadStatusRegister(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_LA_StatusRegisterOffset);
 }
 
 static inline boolean
-DAC960_LA_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_LA_ReadErrorStatus(void __iomem *ControllerBaseAddress,
                          unsigned char *ErrorStatus,
                          unsigned char *Parameter0,
                          unsigned char *Parameter1)
@@ -3583,7 +3583,7 @@ DAC960_PG_ErrorStatusRegister_T;
 */
 
 static inline
-void DAC960_PG_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_PG_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3593,7 +3593,7 @@ void DAC960_PG_HardwareMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3603,7 +3603,7 @@ void DAC960_PG_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3613,7 +3613,7 @@ void DAC960_PG_GenerateInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_ControllerReset(void *ControllerBaseAddress)
+void DAC960_PG_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3623,7 +3623,7 @@ void DAC960_PG_ControllerReset(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_PG_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3633,7 +3633,7 @@ void DAC960_PG_MemoryMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PG_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_PG_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3642,7 +3642,7 @@ boolean DAC960_PG_HardwareMailboxFullP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PG_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_PG_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3651,7 +3651,7 @@ boolean DAC960_PG_InitializationInProgressP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3661,7 +3661,7 @@ void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3671,7 +3671,7 @@ void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3682,7 +3682,7 @@ void DAC960_PG_AcknowledgeInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PG_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_PG_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3691,7 +3691,7 @@ boolean DAC960_PG_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PG_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_PG_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3700,7 +3700,7 @@ boolean DAC960_PG_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_PG_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0;
@@ -3712,7 +3712,7 @@ void DAC960_PG_EnableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_PG_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0;
@@ -3724,7 +3724,7 @@ void DAC960_PG_DisableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PG_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_PG_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3747,7 +3747,7 @@ void DAC960_PG_WriteCommandMailbox(DAC960_V1_CommandMailbox_T
 }
 
 static inline
-void DAC960_PG_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_PG_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
                                    DAC960_V1_CommandMailbox_T *CommandMailbox)
 {
   writel(CommandMailbox->Words[0],
@@ -3761,20 +3761,20 @@ void DAC960_PG_WriteHardwareMailbox(void *ControllerBaseAddress,
 }
 
 static inline DAC960_V1_CommandIdentifier_T
-DAC960_PG_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+DAC960_PG_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readb(ControllerBaseAddress
               + DAC960_PG_StatusCommandIdentifierRegOffset);
 }
 
 static inline DAC960_V1_CommandStatus_T
-DAC960_PG_ReadStatusRegister(void *ControllerBaseAddress)
+DAC960_PG_ReadStatusRegister(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_PG_StatusRegisterOffset);
 }
 
 static inline boolean
-DAC960_PG_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_PG_ReadErrorStatus(void __iomem *ControllerBaseAddress,
                          unsigned char *ErrorStatus,
                          unsigned char *Parameter0,
                          unsigned char *Parameter1)
@@ -3903,7 +3903,7 @@ DAC960_PD_ErrorStatusRegister_T;
 */
 
 static inline
-void DAC960_PD_NewCommand(void *ControllerBaseAddress)
+void DAC960_PD_NewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3913,7 +3913,7 @@ void DAC960_PD_NewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_AcknowledgeStatus(void *ControllerBaseAddress)
+void DAC960_PD_AcknowledgeStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3923,7 +3923,7 @@ void DAC960_PD_AcknowledgeStatus(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_PD_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3933,7 +3933,7 @@ void DAC960_PD_GenerateInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_ControllerReset(void *ControllerBaseAddress)
+void DAC960_PD_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3943,7 +3943,7 @@ void DAC960_PD_ControllerReset(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PD_MailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_PD_MailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3952,7 +3952,7 @@ boolean DAC960_PD_MailboxFullP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PD_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_PD_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3961,7 +3961,7 @@ boolean DAC960_PD_InitializationInProgressP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_PD_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3971,7 +3971,7 @@ void DAC960_PD_AcknowledgeInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PD_StatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_PD_StatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3980,7 +3980,7 @@ boolean DAC960_PD_StatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_PD_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister;
   InterruptEnableRegister.All = 0;
@@ -3990,7 +3990,7 @@ void DAC960_PD_EnableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_PD_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister;
   InterruptEnableRegister.All = 0;
@@ -4000,7 +4000,7 @@ void DAC960_PD_DisableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PD_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_PD_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister;
   InterruptEnableRegister.All =
@@ -4009,7 +4009,7 @@ boolean DAC960_PD_InterruptsEnabledP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_WriteCommandMailbox(void *ControllerBaseAddress,
+void DAC960_PD_WriteCommandMailbox(void __iomem *ControllerBaseAddress,
                                   DAC960_V1_CommandMailbox_T *CommandMailbox)
 {
   writel(CommandMailbox->Words[0],
@@ -4023,20 +4023,20 @@ void DAC960_PD_WriteCommandMailbox(void *ControllerBaseAddress,
 }
 
 static inline DAC960_V1_CommandIdentifier_T
-DAC960_PD_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+DAC960_PD_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readb(ControllerBaseAddress
               + DAC960_PD_StatusCommandIdentifierRegOffset);
 }
 
 static inline DAC960_V1_CommandStatus_T
-DAC960_PD_ReadStatusRegister(void *ControllerBaseAddress)
+DAC960_PD_ReadStatusRegister(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_PD_StatusRegisterOffset);
 }
 
 static inline boolean
-DAC960_PD_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_PD_ReadErrorStatus(void __iomem *ControllerBaseAddress,
                          unsigned char *ErrorStatus,
                          unsigned char *Parameter0,
                          unsigned char *Parameter1)
index 42c1e56..62e3a7e 100644 (file)
@@ -386,16 +386,6 @@ static void fd_motor_off(unsigned long drive)
        fd_select(drive);
        udelay (1);
        fd_deselect(drive);
-
-#ifdef MODULE
-/*
-  this is the last interrupt for any drive access, happens after
-  release (from floppy_off). So we have to wait until now to decrease
-  the use count.
-*/
-       if (decusecount)
-               MOD_DEC_USE_COUNT;
-#endif
 }
 
 static void floppy_off (unsigned int nr)
@@ -1590,10 +1580,6 @@ static int floppy_open(struct inode *inode, struct file *filp)
        local_irq_save(flags);
        fd_ref[drive]++;
        fd_device[drive] = system;
-#ifdef MODULE
-       if (unit[drive].motor == 0)
-               MOD_INC_USE_COUNT;
-#endif
        local_irq_restore(flags);
 
        unit[drive].dtype=&data_types[system];
@@ -1839,6 +1825,7 @@ int init_module(void)
        return amiga_floppy_init();
 }
 
+#if 0 /* not safe to unload */
 void cleanup_module(void)
 {
        int i;
@@ -1860,3 +1847,4 @@ void cleanup_module(void)
        unregister_blkdev(FLOPPY_MAJOR, "fd");
 }
 #endif
+#endif
index 825855c..8ab689c 100644 (file)
@@ -43,12 +43,12 @@ struct ctlr_info
        char    firm_ver[4]; // Firmware version 
        struct pci_dev *pdev;
        __u32   board_id;
-       unsigned long vaddr;
+       void __iomem *vaddr;
        unsigned long paddr;
        unsigned long io_mem_addr;
        unsigned long io_mem_length;
-       CfgTable_struct *cfgtable;
-       int     intr;
+       CfgTable_struct __iomem *cfgtable;
+       unsigned int intr;
        int     interrupts_enabled;
        int     max_commands;
        int     commands_outstanding;
index 112e394..6a9ded0 100644 (file)
@@ -90,7 +90,7 @@ struct ctlr_info {
        __u32   board_id;
        char    *product_name;  
 
-       void *vaddr;
+       void __iomem *vaddr;
        unsigned long paddr;
        unsigned long io_mem_addr;
        unsigned long io_mem_length;
index b98b70b..75ad39d 100644 (file)
@@ -128,23 +128,11 @@ static void nbd_end_request(struct request *req)
 {
        int uptodate = (req->errors == 0) ? 1 : 0;
        request_queue_t *q = req->q;
-       struct nbd_device *lo = req->rq_disk->private_data;
        unsigned long flags;
 
        dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
                        req, uptodate? "done": "failed");
 
-       spin_lock(&lo->queue_lock);
-       while (req->ref_count > 1) { /* still in send */
-               spin_unlock(&lo->queue_lock);
-               printk(KERN_DEBUG "%s: request %p still in use (%d), waiting\n",
-                   lo->disk->disk_name, req, req->ref_count);
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(HZ); /* wait a second */
-               spin_lock(&lo->queue_lock);
-       }
-       spin_unlock(&lo->queue_lock);
-
        spin_lock_irqsave(q->queue_lock, flags);
        if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
                end_that_request_last(req);
@@ -228,7 +216,7 @@ static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec,
        return result;
 }
 
-void nbd_send_req(struct nbd_device *lo, struct request *req)
+static int nbd_send_req(struct nbd_device *lo, struct request *req)
 {
        int result, i, flags;
        struct nbd_request request;
@@ -288,11 +276,11 @@ void nbd_send_req(struct nbd_device *lo, struct request *req)
                }
        }
        up(&lo->tx_lock);
-       return;
+       return 0;
 
 error_out:
        up(&lo->tx_lock);
-       req->errors++;
+       return 1;
 }
 
 static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
@@ -477,26 +465,19 @@ static void do_nbd_request(request_queue_t * q)
                }
 
                list_add(&req->queuelist, &lo->queue_head);
-               req->ref_count++; /* make sure req does not get freed */
                spin_unlock(&lo->queue_lock);
 
-               nbd_send_req(lo, req);
-
-               if (req->errors) {
+               if (nbd_send_req(lo, req) != 0) {
                        printk(KERN_ERR "%s: Request send failed\n",
                                        lo->disk->disk_name);
-                       spin_lock(&lo->queue_lock);
-                       list_del_init(&req->queuelist);
-                       req->ref_count--;
-                       spin_unlock(&lo->queue_lock);
-                       nbd_end_request(req);
-                       spin_lock_irq(q->queue_lock);
-                       continue;
+                       if (nbd_find_request(lo, (char *)&req) != NULL) {
+                               /* we still own req */
+                               req->errors++;
+                               nbd_end_request(req);
+                       } else /* we're racing with nbd_clear_que */
+                               printk(KERN_DEBUG "nbd: can't find req\n");
                }
 
-               spin_lock(&lo->queue_lock);
-               req->ref_count--;
-               spin_unlock(&lo->queue_lock);
                spin_lock_irq(q->queue_lock);
                continue;
 
index 0a02341..02a541a 100644 (file)
@@ -242,7 +242,7 @@ struct carm_request {
 
 struct carm_host {
        unsigned long                   flags;
-       void                            *mmio;
+       void                            __iomem *mmio;
        void                            *shm;
        dma_addr_t                      shm_dma;
 
@@ -283,13 +283,13 @@ struct carm_host {
 };
 
 struct carm_response {
-       u32 ret_handle;
-       u32 status;
+       __le32 ret_handle;
+       __le32 status;
 }  __attribute__((packed));
 
 struct carm_msg_sg {
-       u32 start;
-       u32 len;
+       __le32 start;
+       __le32 len;
 }  __attribute__((packed));
 
 struct carm_msg_rw {
@@ -297,10 +297,10 @@ struct carm_msg_rw {
        u8 id;
        u8 sg_count;
        u8 sg_type;
-       u32 handle;
-       u32 lba;
-       u16 lba_count;
-       u16 lba_high;
+       __le32 handle;
+       __le32 lba;
+       __le16 lba_count;
+       __le16 lba_high;
        struct carm_msg_sg sg[32];
 }  __attribute__((packed));
 
@@ -309,15 +309,15 @@ struct carm_msg_allocbuf {
        u8 subtype;
        u8 n_sg;
        u8 sg_type;
-       u32 handle;
-       u32 addr;
-       u32 len;
-       u32 evt_pool;
-       u32 n_evt;
-       u32 rbuf_pool;
-       u32 n_rbuf;
-       u32 msg_pool;
-       u32 n_msg;
+       __le32 handle;
+       __le32 addr;
+       __le32 len;
+       __le32 evt_pool;
+       __le32 n_evt;
+       __le32 rbuf_pool;
+       __le32 n_rbuf;
+       __le32 msg_pool;
+       __le32 n_msg;
        struct carm_msg_sg sg[8];
 }  __attribute__((packed));
 
@@ -326,8 +326,8 @@ struct carm_msg_ioctl {
        u8 subtype;
        u8 array_id;
        u8 reserved1;
-       u32 handle;
-       u32 data_addr;
+       __le32 handle;
+       __le32 data_addr;
        u32 reserved2;
 }  __attribute__((packed));
 
@@ -335,48 +335,48 @@ struct carm_msg_sync_time {
        u8 type;
        u8 subtype;
        u16 reserved1;
-       u32 handle;
+       __le32 handle;
        u32 reserved2;
-       u32 timestamp;
+       __le32 timestamp;
 }  __attribute__((packed));
 
 struct carm_msg_get_fw_ver {
        u8 type;
        u8 subtype;
        u16 reserved1;
-       u32 handle;
-       u32 data_addr;
+       __le32 handle;
+       __le32 data_addr;
        u32 reserved2;
 }  __attribute__((packed));
 
 struct carm_fw_ver {
-       u32 version;
+       __le32 version;
        u8 features;
        u8 reserved1;
        u16 reserved2;
 }  __attribute__((packed));
 
 struct carm_array_info {
-       u32 size;
+       __le32 size;
 
-       u16 size_hi;
-       u16 stripe_size;
+       __le16 size_hi;
+       __le16 stripe_size;
 
-       u32 mode;
+       __le32 mode;
 
-       u16 stripe_blk_sz;
-       u16 reserved1;
+       __le16 stripe_blk_sz;
+       __le16 reserved1;
 
-       u16 cyl;
-       u16 head;
+       __le16 cyl;
+       __le16 head;
 
-       u16 sect;
+       __le16 sect;
        u8 array_id;
        u8 reserved2;
 
        char name[40];
 
-       u32 array_status;
+       __le32 array_status;
 
        /* device list continues beyond this point? */
 }  __attribute__((packed));
@@ -451,7 +451,7 @@ static inline int carm_lookup_bucket(u32 msg_size)
        return -ENOENT;
 }
 
-static void carm_init_buckets(void *mmio)
+static void carm_init_buckets(void __iomem *mmio)
 {
        unsigned int i;
 
@@ -474,7 +474,7 @@ static inline dma_addr_t carm_ref_msg_dma(struct carm_host *host,
 static int carm_send_msg(struct carm_host *host,
                         struct carm_request *crq)
 {
-       void *mmio = host->mmio;
+       void __iomem *mmio = host->mmio;
        u32 msg = (u32) carm_ref_msg_dma(host, crq->tag);
        u32 cm_bucket = crq->msg_bucket;
        u32 tmp;
@@ -965,7 +965,7 @@ static void carm_handle_array_info(struct carm_host *host,
        port = &host->port[cur_port];
 
        lo = (u64) le32_to_cpu(desc->size);
-       hi = (u64) le32_to_cpu(desc->size_hi);
+       hi = (u64) le16_to_cpu(desc->size_hi);
 
        port->capacity = lo | (hi << 32);
        port->dev_geom_head = le16_to_cpu(desc->head);
@@ -1060,7 +1060,7 @@ static inline void carm_handle_rw(struct carm_host *host,
 }
 
 static inline void carm_handle_resp(struct carm_host *host,
-                                   u32 ret_handle_le, u32 status)
+                                   __le32 ret_handle_le, u32 status)
 {
        u32 handle = le32_to_cpu(ret_handle_le);
        unsigned int msg_idx;
@@ -1158,7 +1158,7 @@ err_out:
 
 static inline void carm_handle_responses(struct carm_host *host)
 {
-       void *mmio = host->mmio;
+       void __iomem *mmio = host->mmio;
        struct carm_response *resp = (struct carm_response *) host->shm;
        unsigned int work = 0;
        unsigned int idx = host->resp_idx % RMSG_Q_LEN;
@@ -1176,7 +1176,7 @@ static inline void carm_handle_responses(struct carm_host *host)
                else if ((status & (1 << 31)) == 0) {
                        VPRINTK("handling msg response on index %u\n", idx);
                        carm_handle_resp(host, resp[idx].ret_handle, status);
-                       resp[idx].status = 0xffffffff;
+                       resp[idx].status = cpu_to_le32(0xffffffff);
                }
 
                /* asynchronous events the hardware throws our way */
@@ -1185,7 +1185,7 @@ static inline void carm_handle_responses(struct carm_host *host)
                        u8 evt_type = *evt_type_ptr;
                        printk(KERN_WARNING DRV_NAME "(%s): unhandled event type %d\n",
                               pci_name(host->pdev), (int) evt_type);
-                       resp[idx].status = 0xffffffff;
+                       resp[idx].status = cpu_to_le32(0xffffffff);
                }
 
                idx = NEXT_RESP(idx);
@@ -1199,7 +1199,7 @@ static inline void carm_handle_responses(struct carm_host *host)
 static irqreturn_t carm_interrupt(int irq, void *__host, struct pt_regs *regs)
 {
        struct carm_host *host = __host;
-       void *mmio;
+       void __iomem *mmio;
        u32 mask;
        int handled = 0;
        unsigned long flags;
@@ -1364,7 +1364,7 @@ static void carm_fsm_task (void *_data)
                schedule_work(&host->fsm_task);
 }
 
-static int carm_init_wait(void *mmio, u32 bits, unsigned int test_bit)
+static int carm_init_wait(void __iomem *mmio, u32 bits, unsigned int test_bit)
 {
        unsigned int i;
 
@@ -1390,19 +1390,19 @@ static int carm_init_wait(void *mmio, u32 bits, unsigned int test_bit)
 
 static void carm_init_responses(struct carm_host *host)
 {
-       void *mmio = host->mmio;
+       void __iomem *mmio = host->mmio;
        unsigned int i;
        struct carm_response *resp = (struct carm_response *) host->shm;
 
        for (i = 0; i < RMSG_Q_LEN; i++)
-               resp[i].status = 0xffffffff;
+               resp[i].status = cpu_to_le32(0xffffffff);
 
        writel(0, mmio + CARM_RESP_IDX);
 }
 
 static int carm_init_host(struct carm_host *host)
 {
-       void *mmio = host->mmio;
+       void __iomem *mmio = host->mmio;
        u32 tmp;
        u8 tmp8;
        int rc;
@@ -1414,7 +1414,7 @@ static int carm_init_host(struct carm_host *host)
        tmp8 = readb(mmio + CARM_INITC);
        if (tmp8 & 0x01) {
                tmp8 &= ~0x01;
-               writeb(tmp8, CARM_INITC);
+               writeb(tmp8, mmio + CARM_INITC);
                readb(mmio + CARM_INITC);       /* flush */
 
                DPRINTK("snooze...\n");
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
new file mode 100644 (file)
index 0000000..f605535
--- /dev/null
@@ -0,0 +1,2097 @@
+/*
+ * The low performance USB storage driver (ub).
+ *
+ * Copyright (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ * Copyright (C) 2004 Pete Zaitcev (zaitcev@yahoo.com)
+ *
+ * This work is a part of Linux kernel, is derived from it,
+ * and is not licensed separately. See file COPYING for details.
+ *
+ * TODO (sorted by decreasing priority)
+ *  -- ZIP does "ub: resid 18 len 0 act 0" and whole transport quits (toggles?)
+ *  -- set readonly flag for CDs, set removable flag for CF readers
+ *  -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
+ *  -- support pphaneuf's SDDR-75 with two LUNs (also broken capacity...)
+ *  -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
+ *  -- do something about spin-down devices, they are extremely dangerous
+ *     (ZIP is one. Needs spin-up command as well.)
+ *  -- verify the 13 conditions and do bulk resets
+ *  -- normal pool of commands instead of cmdv[]?
+ *  -- kill last_pipe and simply do two-state clearing on both pipes
+ *  -- verify protocol (bulk) from USB descriptors (maybe...)
+ *  -- highmem and sg
+ *  -- move top_sense and work_bcs into separate allocations (if they survive)
+ *     for cache purists and esoteric architectures.
+ *  -- prune comments, they are too volumnous
+ *  -- Exterminate P3 printks
+ *  -- Resove XXX's
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/blkdev.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/timer.h>
+#include <scsi/scsi.h>
+
+#define DRV_NAME "ub"
+#define DEVFS_NAME DRV_NAME
+
+#define UB_MAJOR 125   /* Stolen from Experimental range for a week - XXX */
+
+/*
+ * Definitions which have to be scattered once we understand the layout better.
+ */
+
+/* Transport (despite PR in the name) */
+#define US_PR_BULK     0x50            /* bulk only */
+
+/* Protocol */
+#define US_SC_SCSI     0x06            /* Transparent */
+
+/*
+ */
+#define UB_MINORS_PER_MAJOR    8
+
+#define UB_MAX_CDB_SIZE      16                /* Corresponds to Bulk */
+
+#define UB_SENSE_SIZE  18
+
+/*
+ */
+
+/* command block wrapper */
+struct bulk_cb_wrap {
+       u32     Signature;              /* contains 'USBC' */
+       u32     Tag;                    /* unique per command id */
+       u32     DataTransferLength;     /* size of data */
+       u8      Flags;                  /* direction in bit 0 */
+       u8      Lun;                    /* LUN normally 0 */
+       u8      Length;                 /* of of the CDB */
+       u8      CDB[UB_MAX_CDB_SIZE];   /* max command */
+};
+
+#define US_BULK_CB_WRAP_LEN    31
+#define US_BULK_CB_SIGN                0x43425355      /*spells out USBC */
+#define US_BULK_FLAG_IN                1
+#define US_BULK_FLAG_OUT       0
+
+/* command status wrapper */
+struct bulk_cs_wrap {
+       u32     Signature;              /* should = 'USBS' */
+       u32     Tag;                    /* same as original command */
+       u32     Residue;                /* amount not transferred */
+       u8      Status;                 /* see below */
+};
+
+#define US_BULK_CS_WRAP_LEN    13
+#define US_BULK_CS_SIGN                0x53425355      /* spells out 'USBS' */
+/* This is for Olympus Camedia digital cameras */
+#define US_BULK_CS_OLYMPUS_SIGN        0x55425355      /* spells out 'USBU' */
+#define US_BULK_STAT_OK                0
+#define US_BULK_STAT_FAIL      1
+#define US_BULK_STAT_PHASE     2
+
+/* bulk-only class specific requests */
+#define US_BULK_RESET_REQUEST  0xff
+#define US_BULK_GET_MAX_LUN    0xfe
+
+/*
+ */
+struct ub_dev;
+
+#define UB_MAX_REQ_SG  1
+#define UB_MAX_SECTORS 64
+
+/*
+ * A second ought to be enough for a 32K transfer (UB_MAX_SECTORS)
+ * even if a webcam hogs the bus (famous last words).
+ * Some CDs need a second to spin up though.
+ * ZIP drive rejects commands when it's not spinning,
+ * so it does not need long timeouts either.
+ */
+#define UB_URB_TIMEOUT (HZ*2)
+#define UB_CTRL_TIMEOUT        (HZ/2) /* 500ms ought to be enough to clear a stall */
+
+/*
+ * An instance of a SCSI command in transit.
+ */
+#define UB_DIR_NONE    0
+#define UB_DIR_READ    1
+#define UB_DIR_ILLEGAL2        2
+#define UB_DIR_WRITE   3
+
+#define UB_DIR_CHAR(c)  (((c)==UB_DIR_WRITE)? 'w': \
+                        (((c)==UB_DIR_READ)? 'r': 'n'))
+
+enum ub_scsi_cmd_state {
+       UB_CMDST_INIT,                  /* Initial state */
+       UB_CMDST_CMD,                   /* Command submitted */
+       UB_CMDST_DATA,                  /* Data phase */
+       UB_CMDST_CLR2STS,               /* Clearing before requesting status */
+       UB_CMDST_STAT,                  /* Status phase */
+       UB_CMDST_CLEAR,                 /* Clearing a stall (halt, actually) */
+       UB_CMDST_SENSE,                 /* Sending Request Sense */
+       UB_CMDST_DONE                   /* Final state */
+};
+
+static char *ub_scsi_cmd_stname[] = {
+       ".  ",
+       "Cmd",
+       "dat",
+       "c2s",
+       "sts",
+       "clr",
+       "Sen",
+       "fin"
+};
+
+struct ub_scsi_cmd {
+       unsigned char cdb[UB_MAX_CDB_SIZE];
+       unsigned char cdb_len;
+
+       unsigned char dir;              /* 0 - none, 1 - read, 3 - write. */
+       unsigned char trace_index;
+       enum ub_scsi_cmd_state state;
+       unsigned int tag;
+       struct ub_scsi_cmd *next;
+
+       int error;                      /* Return code - valid upon done */
+       int act_len;                    /* Return size */
+
+       int stat_count;                 /* Retries getting status. */
+
+       /*
+        * We do not support transfers from highmem pages
+        * because the underlying USB framework does not do what we need.
+        */
+       char *data;                     /* Requested buffer */
+       unsigned int len;               /* Requested length */
+       // struct scatterlist sgv[UB_MAX_REQ_SG];
+
+       void (*done)(struct ub_dev *, struct ub_scsi_cmd *);
+       void *back;
+};
+
+/*
+ */
+struct ub_capacity {
+       unsigned long nsec;             /* Linux size - 512 byte sectors */
+       unsigned int bsize;             /* Linux hardsect_size */
+       unsigned int bshift;            /* Shift between 512 and hard sects */
+};
+
+/*
+ * The SCSI command tracing structure.
+ */
+
+#define SCMD_ST_HIST_SZ   8
+#define SCMD_TRACE_SZ    15    /* No more than 256 (trace_index) */
+
+struct ub_scsi_cmd_trace {
+       int hcur;
+       unsigned int tag;
+       unsigned int req_size, act_size;
+       unsigned char op;
+       unsigned char dir;
+       unsigned char key, asc, ascq;
+       char st_hst[SCMD_ST_HIST_SZ];   
+};
+
+struct ub_scsi_trace {
+       int cur;
+       struct ub_scsi_cmd_trace vec[SCMD_TRACE_SZ];
+};
+
+/*
+ * This is a direct take-off from linux/include/completion.h
+ * The difference is that I do not wait on this thing, just poll.
+ * When I want to wait (ub_probe), I just use the stock completion.
+ *
+ * Note that INIT_COMPLETION takes no lock. It is correct. But why
+ * in the bloody hell that thing takes struct instead of pointer to struct
+ * is quite beyond me. I just copied it from the stock completion.
+ */
+struct ub_completion {
+       unsigned int done;
+       spinlock_t lock;
+};
+
+static inline void ub_init_completion(struct ub_completion *x)
+{
+       x->done = 0;
+       spin_lock_init(&x->lock);
+}
+
+#define UB_INIT_COMPLETION(x)  ((x).done = 0)
+
+static void ub_complete(struct ub_completion *x)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&x->lock, flags);
+       x->done++;
+       spin_unlock_irqrestore(&x->lock, flags);
+}
+
+static int ub_is_completed(struct ub_completion *x)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&x->lock, flags);
+       ret = x->done;
+       spin_unlock_irqrestore(&x->lock, flags);
+       return ret;
+}
+
+/*
+ */
+struct ub_scsi_cmd_queue {
+       int qlen, qmax;
+       struct ub_scsi_cmd *head, *tail;
+};
+
+/*
+ * The UB device instance.
+ */
+struct ub_dev {
+       spinlock_t lock;
+       int id;                         /* Number among ub's */
+       atomic_t poison;                /* The USB device is disconnected */
+       int openc;                      /* protected by ub_lock! */
+                                       /* kref is too implicit for our taste */
+       unsigned int tagcnt;
+       int changed;                    /* Media was changed */
+       int removable;
+       int readonly;
+       char name[8];
+       struct usb_device *dev;
+       struct usb_interface *intf;
+
+       struct ub_capacity capacity; 
+       struct gendisk *disk;
+
+       unsigned int send_bulk_pipe;    /* cached pipe values */
+       unsigned int recv_bulk_pipe;
+       unsigned int send_ctrl_pipe;
+       unsigned int recv_ctrl_pipe;
+
+       struct tasklet_struct tasklet;
+
+       /* XXX Use Ingo's mempool (once we have more than one) */
+       int cmda[1];
+       struct ub_scsi_cmd cmdv[1];
+
+       struct ub_scsi_cmd_queue cmd_queue;
+       struct ub_scsi_cmd top_rqs_cmd; /* REQUEST SENSE */
+       unsigned char top_sense[UB_SENSE_SIZE];
+
+       struct ub_completion work_done;
+       struct urb work_urb;
+       struct timer_list work_timer;
+       int last_pipe;                  /* What might need clearing */
+       struct bulk_cb_wrap work_bcb;
+       struct bulk_cs_wrap work_bcs;
+       struct usb_ctrlrequest work_cr;
+
+       struct ub_scsi_trace tr;
+};
+
+/*
+ */
+static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static void ub_end_rq(struct request *rq, int uptodate);
+static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static void ub_urb_complete(struct urb *urb, struct pt_regs *pt);
+static void ub_scsi_action(unsigned long _dev);
+static void ub_scsi_dispatch(struct ub_dev *sc);
+static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc);
+static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+    int stalled_pipe);
+static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
+static int ub_sync_tur(struct ub_dev *sc);
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret);
+
+/*
+ */
+static struct usb_device_id ub_usb_ids[] = {
+       // { USB_DEVICE_VER(0x0781, 0x0002, 0x0009, 0x0009) },  /* SDDR-31 */
+       { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
+       { }
+};
+
+MODULE_DEVICE_TABLE(usb, ub_usb_ids);
+
+/*
+ * Find me a way to identify "next free minor" for add_disk(),
+ * and the array disappears the next day. However, the number of
+ * hosts has something to do with the naming and /proc/partitions.
+ * This has to be thought out in detail before changing.
+ * If UB_MAX_HOST was 1000, we'd use a bitmap. Or a better data structure.
+ */
+#define UB_MAX_HOSTS  26
+static char ub_hostv[UB_MAX_HOSTS];
+static spinlock_t ub_lock = SPIN_LOCK_UNLOCKED;        /* Locks globals and ->openc */
+
+/*
+ * The SCSI command tracing procedures.
+ */
+
+static void ub_cmdtr_new(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       int n;
+       struct ub_scsi_cmd_trace *t;
+
+       if ((n = sc->tr.cur + 1) == SCMD_TRACE_SZ) n = 0;
+       t = &sc->tr.vec[n];
+
+       memset(t, 0, sizeof(struct ub_scsi_cmd_trace));
+       t->tag = cmd->tag;
+       t->op = cmd->cdb[0];
+       t->dir = cmd->dir;
+       t->req_size = cmd->len;
+       t->st_hst[0] = cmd->state;
+
+       sc->tr.cur = n;
+       cmd->trace_index = n;
+}
+
+static void ub_cmdtr_state(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       int n;
+       struct ub_scsi_cmd_trace *t;
+
+       t = &sc->tr.vec[cmd->trace_index];
+       if (t->tag == cmd->tag) {
+               if ((n = t->hcur + 1) == SCMD_ST_HIST_SZ) n = 0;
+               t->st_hst[n] = cmd->state;
+               t->hcur = n;
+       }
+}
+
+static void ub_cmdtr_act_len(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       struct ub_scsi_cmd_trace *t;
+
+       t = &sc->tr.vec[cmd->trace_index];
+       if (t->tag == cmd->tag)
+               t->act_size = cmd->act_len;
+}
+
+static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+    unsigned char *sense)
+{
+       struct ub_scsi_cmd_trace *t;
+
+       t = &sc->tr.vec[cmd->trace_index];
+       if (t->tag == cmd->tag) {
+               t->key = sense[2] & 0x0F;
+               t->asc = sense[12];
+               t->ascq = sense[13];
+       }
+}
+
+static ssize_t ub_diag_show(struct device *dev, char *page)
+{
+       struct usb_interface *intf;
+       struct ub_dev *sc;
+       int cnt;
+       unsigned long flags;
+       int nc, nh;
+       int i, j;
+       struct ub_scsi_cmd_trace *t;
+
+       intf = to_usb_interface(dev);
+       sc = usb_get_intfdata(intf);
+       if (sc == NULL)
+               return 0;
+
+       cnt = 0;
+       spin_lock_irqsave(&sc->lock, flags);
+
+       cnt += sprintf(page + cnt,
+           "qlen %d qmax %d changed %d removable %d readonly %d\n",
+           sc->cmd_queue.qlen, sc->cmd_queue.qmax,
+           sc->changed, sc->removable, sc->readonly);
+
+       if ((nc = sc->tr.cur + 1) == SCMD_TRACE_SZ) nc = 0;
+       for (j = 0; j < SCMD_TRACE_SZ; j++) {
+               t = &sc->tr.vec[nc];
+
+               cnt += sprintf(page + cnt, "%08x %02x", t->tag, t->op);
+               if (t->op == REQUEST_SENSE) {
+                       cnt += sprintf(page + cnt, " [sense %x %02x %02x]",
+                                       t->key, t->asc, t->ascq);
+               } else {
+                       cnt += sprintf(page + cnt, " %c", UB_DIR_CHAR(t->dir));
+                       cnt += sprintf(page + cnt, " [%5d %5d]",
+                                       t->req_size, t->act_size);
+               }
+               if ((nh = t->hcur + 1) == SCMD_ST_HIST_SZ) nh = 0;
+               for (i = 0; i < SCMD_ST_HIST_SZ; i++) {
+                       cnt += sprintf(page + cnt, " %s",
+                                       ub_scsi_cmd_stname[(int)t->st_hst[nh]]);
+                       if (++nh == SCMD_ST_HIST_SZ) nh = 0;
+               }
+               cnt += sprintf(page + cnt, "\n");
+
+               if (++nc == SCMD_TRACE_SZ) nc = 0;
+       }
+
+       spin_unlock_irqrestore(&sc->lock, flags);
+       return cnt;
+}
+
+static DEVICE_ATTR(diag, S_IRUGO, ub_diag_show, NULL); /* N.B. World readable */
+
+/*
+ * The id allocator.
+ *
+ * This also stores the host for indexing by minor, which is somewhat dirty.
+ */
+static int ub_id_get(void)
+{
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&ub_lock, flags);
+       for (i = 0; i < UB_MAX_HOSTS; i++) {
+               if (ub_hostv[i] == 0) {
+                       ub_hostv[i] = 1;
+                       spin_unlock_irqrestore(&ub_lock, flags);
+                       return i;
+               }
+       }
+       spin_unlock_irqrestore(&ub_lock, flags);
+       return -1;
+}
+
+static void ub_id_put(int id)
+{
+
+       if (id < 0 || id >= UB_MAX_HOSTS) {
+               printk(KERN_ERR DRV_NAME ": bad host ID %d\n", id);
+               return;
+       }
+       if (ub_hostv[id] == 0) {
+               printk(KERN_ERR DRV_NAME ": freeing free host ID %d\n", id);
+               return;
+       }
+       ub_hostv[id] = 0;
+}
+
+/*
+ * Final cleanup and deallocation.
+ * This must be called with ub_lock taken.
+ */
+static void ub_cleanup(struct ub_dev *sc)
+{
+       ub_id_put(sc->id);
+       kfree(sc);
+}
+
+/*
+ * The "command allocator".
+ */
+static struct ub_scsi_cmd *ub_get_cmd(struct ub_dev *sc)
+{
+       struct ub_scsi_cmd *ret;
+
+       if (sc->cmda[0])
+               return NULL;
+       ret = &sc->cmdv[0];
+       sc->cmda[0] = 1;
+       return ret;
+}
+
+static void ub_put_cmd(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       if (cmd != &sc->cmdv[0]) {
+               printk(KERN_WARNING "%s: releasing a foreign cmd %p\n",
+                   sc->name, cmd);
+               return;
+       }
+       if (!sc->cmda[0]) {
+               printk(KERN_WARNING "%s: releasing a free cmd\n", sc->name);
+               return;
+       }
+       sc->cmda[0] = 0;
+}
+
+/*
+ * The command queue.
+ */
+static void ub_cmdq_add(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       struct ub_scsi_cmd_queue *t = &sc->cmd_queue;
+
+       if (t->qlen++ == 0) {
+               t->head = cmd;
+               t->tail = cmd;
+       } else {
+               t->tail->next = cmd;
+               t->tail = cmd;
+       }
+
+       if (t->qlen > t->qmax)
+               t->qmax = t->qlen;
+}
+
+static void ub_cmdq_insert(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       struct ub_scsi_cmd_queue *t = &sc->cmd_queue;
+
+       if (t->qlen++ == 0) {
+               t->head = cmd;
+               t->tail = cmd;
+       } else {
+               cmd->next = t->head;
+               t->head = cmd;
+       }
+
+       if (t->qlen > t->qmax)
+               t->qmax = t->qlen;
+}
+
+static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc)
+{
+       struct ub_scsi_cmd_queue *t = &sc->cmd_queue;
+       struct ub_scsi_cmd *cmd;
+
+       if (t->qlen == 0)
+               return NULL;
+       if (--t->qlen == 0)
+               t->tail = NULL;
+       cmd = t->head;
+       t->head = cmd->next;
+       cmd->next = NULL;
+       return cmd;
+}
+
+#define ub_cmdq_peek(sc)  ((sc)->cmd_queue.head)
+
+/*
+ * The request function is our main entry point
+ */
+
+static inline int ub_bd_rq_fn_1(request_queue_t *q)
+{
+#if 0
+       int writing = 0, pci_dir, i, n_elem;
+       u32 tmp;
+       unsigned int msg_size;
+#endif
+       struct ub_dev *sc = q->queuedata;
+       struct request *rq;
+#if 0 /* We use rq->buffer for now */
+       struct scatterlist *sg;
+       int n_elem;
+#endif
+       struct ub_scsi_cmd *cmd;
+       int ub_dir;
+       unsigned int block, nblks;
+       int rc;
+
+       if ((rq = elv_next_request(q)) == NULL)
+               return 1;
+
+       if (atomic_read(&sc->poison) || sc->changed) {
+               blkdev_dequeue_request(rq);
+               ub_end_rq(rq, 0);
+               return 0;
+       }
+
+       if ((cmd = ub_get_cmd(sc)) == NULL) {
+               blk_stop_queue(q);
+               return 1;
+       }
+
+       blkdev_dequeue_request(rq);
+
+       if (rq_data_dir(rq) == WRITE)
+               ub_dir = UB_DIR_WRITE;
+       else
+               ub_dir = UB_DIR_READ;
+
+       /*
+        * get scatterlist from block layer
+        */
+#if 0 /* We use rq->buffer for now */
+       sg = &cmd->sgv[0];
+       n_elem = blk_rq_map_sg(q, rq, sg);
+       if (n_elem <= 0) {
+               ub_put_cmd(sc, cmd);
+               ub_end_rq(rq, 0);
+               blk_start_queue(q);
+               return 0;               /* request with no s/g entries? */
+       }
+
+       if (n_elem != 1) {              /* Paranoia */
+               printk(KERN_WARNING "%s: request with %d segments\n",
+                   sc->name, n_elem);
+               ub_put_cmd(sc, cmd);
+               ub_end_rq(rq, 0);
+               blk_start_queue(q);
+               return 0;
+       }
+#endif
+       /*
+        * XXX Unfortunately, this check does not work. It is quite possible
+        * to get bogus non-null rq->buffer if you allow sg by mistake.
+        */
+       if (rq->buffer == NULL) {
+               /*
+                * This must not happen if we set the queue right.
+                * The block level must create bounce buffers for us.
+                */
+               static int do_print = 1;
+               if (do_print) {
+                       printk(KERN_WARNING "%s: unmapped request\n", sc->name);
+                       do_print = 0;
+               }
+               ub_put_cmd(sc, cmd);
+               ub_end_rq(rq, 0);
+               blk_start_queue(q);
+               return 0;
+       }
+
+       /*
+        * build the command
+        */
+       block = rq->sector;
+       nblks = rq->nr_sectors;
+
+       memset(cmd, 0, sizeof(struct ub_scsi_cmd));
+       cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
+       /* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
+       cmd->cdb[2] = block >> 24;
+       cmd->cdb[3] = block >> 16;
+       cmd->cdb[4] = block >> 8;
+       cmd->cdb[5] = block;
+       cmd->cdb[7] = nblks >> 8;
+       cmd->cdb[8] = nblks;
+       cmd->cdb_len = 10;
+       cmd->dir = ub_dir;
+       cmd->state = UB_CMDST_INIT;
+       cmd->data = rq->buffer;
+       cmd->len = nblks * 512;
+       cmd->done = ub_rw_cmd_done;
+       cmd->back = rq;
+
+       cmd->tag = sc->tagcnt++;
+       if ((rc = ub_submit_scsi(sc, cmd)) != 0) {
+               ub_put_cmd(sc, cmd);
+               ub_end_rq(rq, 0);
+               blk_start_queue(q);
+               return 0;
+       }
+
+       return 0;
+}
+
+static void ub_bd_rq_fn(request_queue_t *q)
+{
+       do { } while (ub_bd_rq_fn_1(q) == 0);
+}
+
+static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       struct request *rq = cmd->back;
+       struct gendisk *disk = sc->disk;
+       request_queue_t *q = disk->queue;
+       int uptodate;
+
+       if (cmd->error == 0)
+               uptodate = 1;
+       else
+               uptodate = 0;
+
+       ub_put_cmd(sc, cmd);
+       ub_end_rq(rq, uptodate);
+       blk_start_queue(q);
+}
+
+static void ub_end_rq(struct request *rq, int uptodate)
+{
+       int rc;
+
+       rc = end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
+       // assert(rc == 0);
+       end_that_request_last(rq);
+}
+
+/*
+ * Submit a regular SCSI operation (not an auto-sense).
+ *
+ * The Iron Law of Good Submit Routine is:
+ * Zero return - callback is done, Nonzero return - callback is not done.
+ * No exceptions.
+ *
+ * Host is assumed locked.
+ *
+ * XXX We only support Bulk for the moment.
+ */
+static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+
+       if (cmd->state != UB_CMDST_INIT ||
+           (cmd->dir != UB_DIR_NONE && cmd->len == 0)) {
+               return -EINVAL;
+       }
+
+       ub_cmdq_add(sc, cmd);
+       /*
+        * We can call ub_scsi_dispatch(sc) right away here, but it's a little
+        * safer to jump to a tasklet, in case upper layers do something silly.
+        */
+       tasklet_schedule(&sc->tasklet);
+       return 0;
+}
+
+/*
+ * Submit the first URB for the queued command.
+ * This function does not deal with queueing in any way.
+ */
+static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       struct bulk_cb_wrap *bcb;
+       int rc;
+
+       bcb = &sc->work_bcb;
+
+       /* set up the command wrapper */
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->Tag = cmd->tag;            /* Endianness is not important */
+       bcb->DataTransferLength = cpu_to_le32(cmd->len);
+       bcb->Flags = (cmd->dir == UB_DIR_READ) ? 0x80 : 0;
+       bcb->Lun = 0;                   /* No multi-LUN yet */
+       bcb->Length = cmd->cdb_len;
+
+       /* copy the command payload */
+       memcpy(bcb->CDB, cmd->cdb, UB_MAX_CDB_SIZE);
+
+       UB_INIT_COMPLETION(sc->work_done);
+
+       sc->last_pipe = sc->send_bulk_pipe;
+       usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
+           bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
+       sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
+
+       /* Fill what we shouldn't be filling, because usb-storage did so. */
+       sc->work_urb.actual_length = 0;
+       sc->work_urb.error_count = 0;
+       sc->work_urb.status = 0;
+
+       sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+       add_timer(&sc->work_timer);
+
+       if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+               /* XXX Clear stalls */
+               printk("ub: cmd #%d start failed (%d)\n", cmd->tag, rc); /* P3 */
+               del_timer(&sc->work_timer);
+               ub_complete(&sc->work_done);
+               return rc;
+       }
+
+       cmd->state = UB_CMDST_CMD;
+       ub_cmdtr_state(sc, cmd);
+       return 0;
+}
+
+/*
+ * Timeout handler.
+ */
+static void ub_urb_timeout(unsigned long arg)
+{
+       struct ub_dev *sc = (struct ub_dev *) arg;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sc->lock, flags);
+       usb_unlink_urb(&sc->work_urb);
+       spin_unlock_irqrestore(&sc->lock, flags);
+}
+
+/*
+ * Completion routine for the work URB.
+ *
+ * This can be called directly from usb_submit_urb (while we have
+ * the sc->lock taken) and from an interrupt (while we do NOT have
+ * the sc->lock taken). Therefore, bounce this off to a tasklet.
+ */
+static void ub_urb_complete(struct urb *urb, struct pt_regs *pt)
+{
+       struct ub_dev *sc = urb->context;
+
+       ub_complete(&sc->work_done);
+       tasklet_schedule(&sc->tasklet);
+}
+
+static void ub_scsi_action(unsigned long _dev)
+{
+       struct ub_dev *sc = (struct ub_dev *) _dev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sc->lock, flags);
+       ub_scsi_dispatch(sc);
+       spin_unlock_irqrestore(&sc->lock, flags);
+}
+
+static void ub_scsi_dispatch(struct ub_dev *sc)
+{
+       struct ub_scsi_cmd *cmd;
+       int rc;
+
+       while ((cmd = ub_cmdq_peek(sc)) != NULL) {
+               if (cmd->state == UB_CMDST_DONE) {
+                       ub_cmdq_pop(sc);
+                       (*cmd->done)(sc, cmd);
+               } else if (cmd->state == UB_CMDST_INIT) {
+                       ub_cmdtr_new(sc, cmd);
+                       if ((rc = ub_scsi_cmd_start(sc, cmd)) == 0)
+                               break;
+                       cmd->error = rc;
+                       cmd->state = UB_CMDST_DONE;
+                       ub_cmdtr_state(sc, cmd);
+               } else {
+                       if (!ub_is_completed(&sc->work_done))
+                               break;
+                       ub_scsi_urb_compl(sc, cmd);
+               }
+       }
+}
+
+static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       struct urb *urb = &sc->work_urb;
+       struct bulk_cs_wrap *bcs;
+       int pipe;
+       int rc;
+
+/* P3 */ /** printk("ub: urb status %d pipe 0x%08x len %d act %d\n",
+ urb->status, urb->pipe, urb->transfer_buffer_length, urb->actual_length); **/
+
+       if (atomic_read(&sc->poison)) {
+               /* A little too simplistic, I feel... */
+               goto Bad_End;
+       }
+
+       if (cmd->state == UB_CMDST_CLEAR) {
+               if (urb->status == -EPIPE) {
+                       /*
+                        * STALL while clearning STALL.
+                        * A STALL is illegal on a control pipe!
+                        * XXX Might try to reset the device here and retry.
+                        */
+                       printk(KERN_NOTICE "%s: "
+                           "stall on control pipe for device %u\n",
+                           sc->name, sc->dev->devnum);
+                       goto Bad_End;
+               }
+
+               /*
+                * We ignore the result for the halt clear.
+                */
+
+               /* reset the endpoint toggle */
+               usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
+                       usb_pipeout(sc->last_pipe), 0);
+
+               ub_state_sense(sc, cmd);
+
+       } else if (cmd->state == UB_CMDST_CLR2STS) {
+               if (urb->status == -EPIPE) {
+                       /*
+                        * STALL while clearning STALL.
+                        * A STALL is illegal on a control pipe!
+                        * XXX Might try to reset the device here and retry.
+                        */
+                       printk(KERN_NOTICE "%s: "
+                           "stall on control pipe for device %u\n",
+                           sc->name, sc->dev->devnum);
+                       goto Bad_End;
+               }
+
+               /*
+                * We ignore the result for the halt clear.
+                */
+
+               /* reset the endpoint toggle */
+               usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
+                       usb_pipeout(sc->last_pipe), 0);
+
+               ub_state_stat(sc, cmd);
+
+       } else if (cmd->state == UB_CMDST_CMD) {
+               if (urb->status == -EPIPE) {
+                       rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
+                       if (rc != 0) {
+                               printk(KERN_NOTICE "%s: "
+                                   "unable to submit clear for device %u (%d)\n",
+                                   sc->name, sc->dev->devnum, rc);
+                               /*
+                                * This is typically ENOMEM or some other such shit.
+                                * Retrying is pointless. Just do Bad End on it...
+                                */
+                               goto Bad_End;
+                       }
+                       cmd->state = UB_CMDST_CLEAR;
+                       ub_cmdtr_state(sc, cmd);
+                       return;
+               }
+               if (urb->status != 0)
+                       goto Bad_End;
+               if (urb->actual_length != US_BULK_CB_WRAP_LEN) {
+                       /* XXX Must do reset here to unconfuse the device */
+                       goto Bad_End;
+               }
+
+               if (cmd->dir == UB_DIR_NONE) {
+                       ub_state_stat(sc, cmd);
+                       return;
+               }
+
+               UB_INIT_COMPLETION(sc->work_done);
+
+               if (cmd->dir == UB_DIR_READ)
+                       pipe = sc->recv_bulk_pipe;
+               else
+                       pipe = sc->send_bulk_pipe;
+               sc->last_pipe = pipe;
+               usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
+                   cmd->data, cmd->len, ub_urb_complete, sc);
+               sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
+               sc->work_urb.actual_length = 0;
+               sc->work_urb.error_count = 0;
+               sc->work_urb.status = 0;
+
+               sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+               add_timer(&sc->work_timer);
+
+               if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+                       /* XXX Clear stalls */
+                       printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
+                       del_timer(&sc->work_timer);
+                       ub_complete(&sc->work_done);
+                       ub_state_done(sc, cmd, rc);
+                       return;
+               }
+
+               cmd->state = UB_CMDST_DATA;
+               ub_cmdtr_state(sc, cmd);
+
+       } else if (cmd->state == UB_CMDST_DATA) {
+               if (urb->status == -EPIPE) {
+                       rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
+                       if (rc != 0) {
+                               printk(KERN_NOTICE "%s: "
+                                   "unable to submit clear for device %u (%d)\n",
+                                   sc->name, sc->dev->devnum, rc);
+                               /*
+                                * This is typically ENOMEM or some other such shit.
+                                * Retrying is pointless. Just do Bad End on it...
+                                */
+                               goto Bad_End;
+                       }
+                       cmd->state = UB_CMDST_CLR2STS;
+                       ub_cmdtr_state(sc, cmd);
+                       return;
+               }
+               if (urb->status == -EOVERFLOW) {
+                       /*
+                        * A babble? Failure, but we must transfer CSW now.
+                        */
+                       cmd->error = -EOVERFLOW;        /* A cheap trick... */
+               } else {
+                       if (urb->status != 0)
+                               goto Bad_End;
+               }
+
+               cmd->act_len = urb->actual_length;
+               ub_cmdtr_act_len(sc, cmd);
+
+               ub_state_stat(sc, cmd);
+
+       } else if (cmd->state == UB_CMDST_STAT) {
+               if (urb->status == -EPIPE) {
+                       rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
+                       if (rc != 0) {
+                               printk(KERN_NOTICE "%s: "
+                                   "unable to submit clear for device %u (%d)\n",
+                                   sc->name, sc->dev->devnum, rc);
+                               /*
+                                * This is typically ENOMEM or some other such shit.
+                                * Retrying is pointless. Just do Bad End on it...
+                                */
+                               goto Bad_End;
+                       }
+                       cmd->state = UB_CMDST_CLEAR;
+                       ub_cmdtr_state(sc, cmd);
+                       return;
+               }
+               if (urb->status != 0)
+                       goto Bad_End;
+
+               if (urb->actual_length == 0) {
+                       /*
+                        * Some broken devices add unnecessary zero-length
+                        * packets to the end of their data transfers.
+                        * Such packets show up as 0-length CSWs. If we
+                        * encounter such a thing, try to read the CSW again.
+                        */
+                       if (++cmd->stat_count >= 4) {
+                               printk(KERN_NOTICE "%s: "
+                                   "unable to get CSW on device %u\n",
+                                   sc->name, sc->dev->devnum);
+                               goto Bad_End;
+                       }
+
+                       /*
+                        * ub_state_stat only not dropping the count...
+                        */
+                       UB_INIT_COMPLETION(sc->work_done);
+
+                       sc->last_pipe = sc->recv_bulk_pipe;
+                       usb_fill_bulk_urb(&sc->work_urb, sc->dev,
+                           sc->recv_bulk_pipe, &sc->work_bcs,
+                           US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
+                       sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
+                       sc->work_urb.actual_length = 0;
+                       sc->work_urb.error_count = 0;
+                       sc->work_urb.status = 0;
+
+                       sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+                       add_timer(&sc->work_timer);
+
+                       rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC);
+                       if (rc != 0) {
+                               /* XXX Clear stalls */
+                               printk("%s: CSW #%d submit failed (%d)\n",
+                                  sc->name, cmd->tag, rc); /* P3 */
+                               del_timer(&sc->work_timer);
+                               ub_complete(&sc->work_done);
+                               ub_state_done(sc, cmd, rc);
+                               return;
+                       }
+                       return;
+               }
+
+               /*
+                * Check the returned Bulk protocol status.
+                */
+
+               bcs = &sc->work_bcs;
+               rc = le32_to_cpu(bcs->Residue);
+               if (rc != cmd->len - cmd->act_len) {
+                       /*
+                        * It is all right to transfer less, the caller has
+                        * to check. But it's not all right if the device
+                        * counts disagree with our counts.
+                        */
+                       /* P3 */ printk("%s: resid %d len %d act %d\n",
+                           sc->name, rc, cmd->len, cmd->act_len);
+                       goto Bad_End;
+               }
+
+               if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
+                   bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) {
+                       /* XXX Rate-limit, even for P3 tagged */
+                       /* P3 */ printk("ub: signature 0x%x\n", bcs->Signature);
+                       /* Windows ignores signatures, so do we. */
+               }
+
+               if (bcs->Tag != cmd->tag) {
+                       /* P3 */ printk("%s: tag orig 0x%x reply 0x%x\n",
+                           sc->name, cmd->tag, bcs->Tag);
+                       goto Bad_End;
+               }
+
+               switch (bcs->Status) {
+               case US_BULK_STAT_OK:
+                       break;
+               case US_BULK_STAT_FAIL:
+                       ub_state_sense(sc, cmd);
+                       return;
+               case US_BULK_STAT_PHASE:
+                       /* XXX We must reset the transport here */
+                       /* P3 */ printk("%s: status PHASE\n", sc->name);
+                       goto Bad_End;
+               default:
+                       printk(KERN_INFO "%s: unknown CSW status 0x%x\n",
+                           sc->name, bcs->Status);
+                       goto Bad_End;
+               }
+
+               /* Not zeroing error to preserve a babble indicator */
+               cmd->state = UB_CMDST_DONE;
+               ub_cmdtr_state(sc, cmd);
+               ub_cmdq_pop(sc);
+               (*cmd->done)(sc, cmd);
+
+       } else if (cmd->state == UB_CMDST_SENSE) {
+               /* 
+                * We do not look at sense, because even if there was no sense,
+                * we get into UB_CMDST_SENSE from a STALL or CSW FAIL only.
+                * We request sense because we want to clear CHECK CONDITION
+                * on devices with delusions of SCSI, and not because we
+                * are curious in any way about the sense itself.
+                */
+               /* if ((cmd->top_sense[2] & 0x0F) == NO_SENSE) { foo } */
+
+               ub_state_done(sc, cmd, -EIO);
+       } else {
+               printk(KERN_WARNING "%s: "
+                   "wrong command state %d on device %u\n",
+                   sc->name, cmd->state, sc->dev->devnum);
+               goto Bad_End;
+       }
+       return;
+
+Bad_End: /* Little Excel is dead */
+       ub_state_done(sc, cmd, -EIO);
+}
+
+/*
+ * Factorization helper for the command state machine:
+ * Finish the command.
+ */
+static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc)
+{
+
+       cmd->error = rc;
+       cmd->state = UB_CMDST_DONE;
+       ub_cmdtr_state(sc, cmd);
+       ub_cmdq_pop(sc);
+       (*cmd->done)(sc, cmd);
+}
+
+/*
+ * Factorization helper for the command state machine:
+ * Submit a CSW read and go to STAT state.
+ */
+static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       int rc;
+
+       UB_INIT_COMPLETION(sc->work_done);
+
+       sc->last_pipe = sc->recv_bulk_pipe;
+       usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
+           &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
+       sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
+       sc->work_urb.actual_length = 0;
+       sc->work_urb.error_count = 0;
+       sc->work_urb.status = 0;
+
+       sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+       add_timer(&sc->work_timer);
+
+       if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+               /* XXX Clear stalls */
+               printk("ub: CSW #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
+               del_timer(&sc->work_timer);
+               ub_complete(&sc->work_done);
+               ub_state_done(sc, cmd, rc);
+               return;
+       }
+
+       cmd->stat_count = 0;
+       cmd->state = UB_CMDST_STAT;
+       ub_cmdtr_state(sc, cmd);
+}
+
+/*
+ * Factorization helper for the command state machine:
+ * Submit a REQUEST SENSE and go to SENSE state.
+ */
+static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       struct ub_scsi_cmd *scmd;
+       int rc;
+
+       if (cmd->cdb[0] == REQUEST_SENSE) {
+               rc = -EPIPE;
+               goto error;
+       }
+
+       memset(&sc->top_sense, 0, UB_SENSE_SIZE);
+       scmd = &sc->top_rqs_cmd;
+       scmd->cdb[0] = REQUEST_SENSE;
+       scmd->cdb_len = 6;
+       scmd->dir = UB_DIR_READ;
+       scmd->state = UB_CMDST_INIT;
+       scmd->data = sc->top_sense;
+       scmd->len = UB_SENSE_SIZE;
+       scmd->done = ub_top_sense_done;
+       scmd->back = cmd;
+
+       scmd->tag = sc->tagcnt++;
+
+       cmd->state = UB_CMDST_SENSE;
+       ub_cmdtr_state(sc, cmd);
+
+       ub_cmdq_insert(sc, scmd);
+       return;
+
+error:
+       ub_state_done(sc, cmd, rc);
+}
+
+/*
+ * A helper for the command's state machine:
+ * Submit a stall clear.
+ */
+static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+    int stalled_pipe)
+{
+       int endp;
+       struct usb_ctrlrequest *cr;
+       int rc;
+
+       endp = usb_pipeendpoint(stalled_pipe);
+       if (usb_pipein (stalled_pipe))
+               endp |= USB_DIR_IN;
+
+       cr = &sc->work_cr;
+       cr->bRequestType = USB_RECIP_ENDPOINT;
+       cr->bRequest = USB_REQ_CLEAR_FEATURE;
+       cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT);
+       cr->wIndex = cpu_to_le16(endp);
+       cr->wLength = cpu_to_le16(0);
+
+       UB_INIT_COMPLETION(sc->work_done);
+
+       usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
+           (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
+       sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
+       sc->work_urb.actual_length = 0;
+       sc->work_urb.error_count = 0;
+       sc->work_urb.status = 0;
+
+       sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT;
+       add_timer(&sc->work_timer);
+
+       if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+               del_timer(&sc->work_timer);
+               ub_complete(&sc->work_done);
+               return rc;
+       }
+       return 0;
+}
+
+/*
+ */
+static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
+{
+       unsigned char *sense = scmd->data;
+       struct ub_scsi_cmd *cmd;
+
+       ub_cmdtr_sense(sc, scmd, sense);
+
+       if ((cmd = ub_cmdq_peek(sc)) == NULL) {
+               printk(KERN_WARNING "%s: sense done while idle\n", sc->name);
+               return;
+       }
+       if (cmd != scmd->back) {
+               printk(KERN_WARNING "%s: "
+                   "sense done for wrong command 0x%x on device %u\n",
+                   sc->name, cmd->tag, sc->dev->devnum);
+               return;
+       }
+       if (cmd->state != UB_CMDST_SENSE) {
+               printk(KERN_WARNING "%s: "
+                   "sense done with bad cmd state %d on device %u\n",
+                   sc->name, cmd->state, sc->dev->devnum);
+               return;
+       }
+
+       ub_scsi_urb_compl(sc, cmd);
+}
+
+#if 0
+/* Determine what the maximum LUN supported is */
+int usb_stor_Bulk_max_lun(struct us_data *us)
+{
+       int result;
+
+       /* issue the command */
+       result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
+                                US_BULK_GET_MAX_LUN, 
+                                USB_DIR_IN | USB_TYPE_CLASS | 
+                                USB_RECIP_INTERFACE,
+                                0, us->ifnum, us->iobuf, 1, HZ);
+
+       /* 
+        * Some devices (i.e. Iomega Zip100) need this -- apparently
+        * the bulk pipes get STALLed when the GetMaxLUN request is
+        * processed.   This is, in theory, harmless to all other devices
+        * (regardless of if they stall or not).
+        */
+       if (result < 0) {
+               usb_stor_clear_halt(us, us->recv_bulk_pipe);
+               usb_stor_clear_halt(us, us->send_bulk_pipe);
+       }
+
+       US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
+                 result, us->iobuf[0]);
+
+       /* if we have a successful request, return the result */
+       if (result == 1)
+               return us->iobuf[0];
+
+       /* return the default -- no LUNs */
+       return 0;
+}
+#endif
+
+/*
+ * This is called from a process context.
+ */
+static void ub_revalidate(struct ub_dev *sc)
+{
+
+       sc->readonly = 0;       /* XXX Query this from the device */
+
+       /*
+        * XXX sd.c sets capacity to zero in such case. However, it doesn't
+        * work for us. In case of zero capacity, block layer refuses to
+        * have the /dev/uba opened (why?) Set capacity to some random value.
+        */
+       sc->capacity.nsec = 50;
+       sc->capacity.bsize = 512;
+       sc->capacity.bshift = 0;
+
+       if (ub_sync_tur(sc) != 0)
+               return;                 /* Not ready */
+       sc->changed = 0;
+
+       if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
+               /*
+                * The retry here means something is wrong, either with the
+                * device, with the transport, or with our code.
+                * We keep this because sd.c has retries for capacity.
+                */
+               if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
+                       sc->capacity.nsec = 100;
+                       sc->capacity.bsize = 512;
+                       sc->capacity.bshift = 0;
+               }
+       }
+}
+
+/*
+ * The open funcion.
+ * This is mostly needed to keep refcounting, but also to support
+ * media checks on removable media drives.
+ */
+static int ub_bd_open(struct inode *inode, struct file *filp)
+{
+       struct gendisk *disk = inode->i_bdev->bd_disk;
+       struct ub_dev *sc;
+       unsigned long flags;
+       int rc;
+
+       if ((sc = disk->private_data) == NULL)
+               return -ENXIO;
+       spin_lock_irqsave(&ub_lock, flags);
+       if (atomic_read(&sc->poison)) {
+               spin_unlock_irqrestore(&ub_lock, flags);
+               return -ENXIO;
+       }
+       sc->openc++;
+       spin_unlock_irqrestore(&ub_lock, flags);
+
+       if (sc->removable || sc->readonly)
+               check_disk_change(inode->i_bdev);
+
+       /* XXX sd.c and floppy.c bail on open if media is not present. */
+
+       if (sc->readonly && (filp->f_mode & FMODE_WRITE)) {
+               rc = -EROFS;
+               goto err_open;
+       }
+
+       return 0;
+
+err_open:
+       spin_lock_irqsave(&ub_lock, flags);
+       --sc->openc;
+       if (sc->openc == 0 && atomic_read(&sc->poison))
+               ub_cleanup(sc);
+       spin_unlock_irqrestore(&ub_lock, flags);
+       return rc;
+}
+
+/*
+ */
+static int ub_bd_release(struct inode *inode, struct file *filp)
+{
+       struct gendisk *disk = inode->i_bdev->bd_disk;
+       struct ub_dev *sc = disk->private_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ub_lock, flags);
+       --sc->openc;
+       if (sc->openc == 0 && atomic_read(&sc->poison))
+               ub_cleanup(sc);
+       spin_unlock_irqrestore(&ub_lock, flags);
+       return 0;
+}
+
+/*
+ * The ioctl interface.
+ */
+static int ub_bd_ioctl(struct inode *inode, struct file *filp,
+    unsigned int cmd, unsigned long arg)
+{
+// void __user *usermem = (void *) arg;
+// struct carm_port *port = ino->i_bdev->bd_disk->private_data;
+// struct hd_geometry geom;
+
+#if 0
+       switch (cmd) {
+       case HDIO_GETGEO:
+               if (usermem == NULL)            // XXX Bizzare. Why?
+                       return -EINVAL;
+
+               geom.heads = (u8) port->dev_geom_head;
+               geom.sectors = (u8) port->dev_geom_sect;
+               geom.cylinders = port->dev_geom_cyl;
+               geom.start = get_start_sect(ino->i_bdev);
+
+               if (copy_to_user(usermem, &geom, sizeof(geom)))
+                       return -EFAULT;
+               return 0;
+
+       default: ;
+       }
+#endif
+
+       return -ENOTTY;
+}
+
+/*
+ * This is called once a new disk was seen by the block layer or by ub_probe().
+ * The main onjective here is to discover the features of the media such as
+ * the capacity, read-only status, etc. USB storage generally does not
+ * need to be spun up, but if we needed it, this would be the place.
+ *
+ * This call can sleep.
+ *
+ * The return code is not used.
+ */
+static int ub_bd_revalidate(struct gendisk *disk)
+{
+       struct ub_dev *sc = disk->private_data;
+
+       ub_revalidate(sc);
+       /* This is pretty much a long term P3 */
+       printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
+           sc->name, sc->dev->devnum, sc->capacity.nsec, sc->capacity.bsize);
+
+       set_capacity(disk, sc->capacity.nsec);
+       // set_disk_ro(sdkp->disk, sc->readonly);
+       return 0;
+}
+
+/*
+ * The check is called by the block layer to verify if the media
+ * is still available. It is supposed to be harmless, lightweight and
+ * non-intrusive in case the media was not changed.
+ *
+ * This call can sleep.
+ *
+ * The return code is bool!
+ */
+static int ub_bd_media_changed(struct gendisk *disk)
+{
+       struct ub_dev *sc = disk->private_data;
+
+       if (!sc->removable)
+               return 0;
+
+       /*
+        * We clean checks always after every command, so this is not
+        * as dangerous as it looks. If the TEST_UNIT_READY fails here,
+        * the device is actually not ready with operator or software
+        * intervention required. One dangerous item might be a drive which
+        * spins itself down, and come the time to write dirty pages, this
+        * will fail, then block layer discards the data. Since we never
+        * spin drives up, such devices simply cannot be used with ub anyway.
+        */
+       if (ub_sync_tur(sc) != 0) {
+               sc->changed = 1;
+               /* P3 */ printk("%s: made changed\n", sc->name);
+               return 1;
+       }
+
+       /* The sd.c clears this before returning (one-shot flag). Why? */
+       /* P3 */ printk("%s: %s changed\n", sc->name,
+           sc->changed? "is": "was not");
+       return sc->changed;
+}
+
+static struct block_device_operations ub_bd_fops = {
+       .owner          = THIS_MODULE,
+       .open           = ub_bd_open,
+       .release        = ub_bd_release,
+       .ioctl          = ub_bd_ioctl,
+       .media_changed  = ub_bd_media_changed,
+       .revalidate_disk = ub_bd_revalidate,
+};
+
+/*
+ * Common ->done routine for commands executed synchronously.
+ */
+static void ub_probe_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+       struct completion *cop = cmd->back;
+       complete(cop);
+}
+
+/*
+ * Test if the device has a check condition on it, synchronously.
+ */
+static int ub_sync_tur(struct ub_dev *sc)
+{
+       struct ub_scsi_cmd *cmd;
+       enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) };
+       unsigned long flags;
+       struct completion compl;
+       int rc;
+
+       init_completion(&compl);
+
+       rc = -ENOMEM;
+       if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)
+               goto err_alloc;
+       memset(cmd, 0, ALLOC_SIZE);
+
+       cmd->cdb[0] = TEST_UNIT_READY;
+       cmd->cdb_len = 6;
+       cmd->dir = UB_DIR_NONE;
+       cmd->state = UB_CMDST_INIT;
+       cmd->done = ub_probe_done;
+       cmd->back = &compl;
+
+       spin_lock_irqsave(&sc->lock, flags);
+       cmd->tag = sc->tagcnt++;
+
+       rc = ub_submit_scsi(sc, cmd);
+       spin_unlock_irqrestore(&sc->lock, flags);
+
+       if (rc != 0) {
+               printk("ub: testing ready: submit error (%d)\n", rc); /* P3 */
+               goto err_submit;
+       }
+
+       wait_for_completion(&compl);
+
+       rc = cmd->error;
+
+err_submit:
+       kfree(cmd);
+err_alloc:
+       return rc;
+}
+
+/*
+ * Read the SCSI capacity synchronously (for probing).
+ */
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret)
+{
+       struct ub_scsi_cmd *cmd;
+       char *p;
+       enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) + 8 };
+       unsigned long flags;
+       unsigned int bsize, shift;
+       unsigned long nsec;
+       struct completion compl;
+       int rc;
+
+       init_completion(&compl);
+
+       rc = -ENOMEM;
+       if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)
+               goto err_alloc;
+       memset(cmd, 0, ALLOC_SIZE);
+       p = (char *)cmd + sizeof(struct ub_scsi_cmd);
+
+       cmd->cdb[0] = 0x25;
+       cmd->cdb_len = 10;
+       cmd->dir = UB_DIR_READ;
+       cmd->state = UB_CMDST_INIT;
+       cmd->data = p;
+       cmd->len = 8;
+       cmd->done = ub_probe_done;
+       cmd->back = &compl;
+
+       spin_lock_irqsave(&sc->lock, flags);
+       cmd->tag = sc->tagcnt++;
+
+       rc = ub_submit_scsi(sc, cmd);
+       spin_unlock_irqrestore(&sc->lock, flags);
+
+       if (rc != 0) {
+               printk("ub: reading capacity: submit error (%d)\n", rc); /* P3 */
+               goto err_submit;
+       }
+
+       wait_for_completion(&compl);
+
+       if (cmd->error != 0) {
+               printk("ub: reading capacity: error %d\n", cmd->error); /* P3 */
+               rc = -EIO;
+               goto err_read;
+       }
+       if (cmd->act_len != 8) {
+               printk("ub: reading capacity: size %d\n", cmd->act_len); /* P3 */
+               rc = -EIO;
+               goto err_read;
+       }
+
+       /* sd.c special-cases sector size of 0 to mean 512. Needed? Safe? */
+       nsec = be32_to_cpu(*(u32 *)p) + 1;
+       bsize = be32_to_cpu(*(u32 *)(p + 4));
+       switch (bsize) {
+       case 512:       shift = 0;      break;
+       case 1024:      shift = 1;      break;
+       case 2048:      shift = 2;      break;
+       case 4096:      shift = 3;      break;
+       default:
+               printk("ub: Bad sector size %u\n", bsize); /* P3 */
+               rc = -EDOM;
+               goto err_inv_bsize;
+       }
+
+       ret->bsize = bsize;
+       ret->bshift = shift;
+       ret->nsec = nsec << shift;
+       rc = 0;
+
+err_inv_bsize:
+err_read:
+err_submit:
+       kfree(cmd);
+err_alloc:
+       return rc;
+}
+
+/*
+ */
+static void ub_probe_urb_complete(struct urb *urb, struct pt_regs *pt)
+{
+       struct completion *cop = urb->context;
+       complete(cop);
+}
+
+static void ub_probe_timeout(unsigned long arg)
+{
+       struct completion *cop = (struct completion *) arg;
+       complete(cop);
+}
+
+/*
+ * Clear initial stalls.
+ */
+static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
+{
+       int endp;
+       struct usb_ctrlrequest *cr;
+       struct completion compl;
+       struct timer_list timer;
+       int rc;
+
+       init_completion(&compl);
+
+       endp = usb_pipeendpoint(stalled_pipe);
+       if (usb_pipein (stalled_pipe))
+               endp |= USB_DIR_IN;
+
+       cr = &sc->work_cr;
+       cr->bRequestType = USB_RECIP_ENDPOINT;
+       cr->bRequest = USB_REQ_CLEAR_FEATURE;
+       cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT);
+       cr->wIndex = cpu_to_le16(endp);
+       cr->wLength = cpu_to_le16(0);
+
+       usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
+           (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
+       sc->work_urb.transfer_flags = 0;
+       sc->work_urb.actual_length = 0;
+       sc->work_urb.error_count = 0;
+       sc->work_urb.status = 0;
+
+       init_timer(&timer);
+       timer.function = ub_probe_timeout;
+       timer.data = (unsigned long) &compl;
+       timer.expires = jiffies + UB_CTRL_TIMEOUT;
+       add_timer(&timer);
+
+       if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
+               printk(KERN_WARNING
+                    "%s: Unable to submit a probe clear (%d)\n", sc->name, rc);
+               del_timer_sync(&timer);
+               return rc;
+       }
+
+       wait_for_completion(&compl);
+
+       del_timer_sync(&timer);
+       /*
+        * Most of the time, URB was done and dev set to NULL, and so
+        * the unlink bounces out with ENODEV. We do not call usb_kill_urb
+        * because we still think about a backport to 2.4.
+        */
+       usb_unlink_urb(&sc->work_urb);
+
+       /* reset the endpoint toggle */
+       usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0);
+
+       return 0;
+}
+
+/*
+ * Get the pipe settings.
+ */
+static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
+    struct usb_interface *intf)
+{
+       struct usb_host_interface *altsetting = intf->cur_altsetting;
+       struct usb_endpoint_descriptor *ep_in = NULL;
+       struct usb_endpoint_descriptor *ep_out = NULL;
+       struct usb_endpoint_descriptor *ep;
+       int i;
+
+       /*
+        * Find the endpoints we need.
+        * We are expecting a minimum of 2 endpoints - in and out (bulk).
+        * We will ignore any others.
+        */
+       for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
+               ep = &altsetting->endpoint[i].desc;
+
+               /* Is it a BULK endpoint? */
+               if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+                               == USB_ENDPOINT_XFER_BULK) {
+                       /* BULK in or out? */
+                       if (ep->bEndpointAddress & USB_DIR_IN)
+                               ep_in = ep;
+                       else
+                               ep_out = ep;
+               }
+       }
+
+       if (ep_in == NULL || ep_out == NULL) {
+               printk(KERN_NOTICE "%s: device %u failed endpoint check\n",
+                   sc->name, sc->dev->devnum);
+               return -EIO;
+       }
+
+       /* Calculate and store the pipe values */
+       sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0);
+       sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0);
+       sc->send_bulk_pipe = usb_sndbulkpipe(dev,
+               ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+       sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, 
+               ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+
+       return 0;
+}
+
+/*
+ * Probing is done in the process context, which allows us to cheat
+ * and not to build a state machine for the discovery.
+ */
+static int ub_probe(struct usb_interface *intf,
+    const struct usb_device_id *dev_id)
+{
+       struct ub_dev *sc;
+       request_queue_t *q;
+       struct gendisk *disk;
+       int rc;
+
+       rc = -ENOMEM;
+       if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL)
+               goto err_core;
+       memset(sc, 0, sizeof(struct ub_dev));
+       spin_lock_init(&sc->lock);
+       usb_init_urb(&sc->work_urb);
+       tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
+       atomic_set(&sc->poison, 0);
+
+       init_timer(&sc->work_timer);
+       sc->work_timer.data = (unsigned long) sc;
+       sc->work_timer.function = ub_urb_timeout;
+
+       ub_init_completion(&sc->work_done);
+       sc->work_done.done = 1;         /* A little yuk, but oh well... */
+
+       rc = -ENOSR;
+       if ((sc->id = ub_id_get()) == -1)
+               goto err_id;
+       snprintf(sc->name, 8, DRV_NAME "%c", sc->id + 'a');
+
+       sc->dev = interface_to_usbdev(intf);
+       sc->intf = intf;
+       // sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+       usb_set_intfdata(intf, sc);
+       usb_get_dev(sc->dev);
+       // usb_get_intf(sc->intf);      /* Do we need this? */
+
+       /* XXX Verify that we can handle the device (from descriptors) */
+
+       ub_get_pipes(sc, sc->dev, intf);
+
+       if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0)
+               goto err_diag;
+
+       /*
+        * At this point, all USB initialization is done, do upper layer.
+        * We really hate halfway initialized structures, so from the
+        * invariants perspective, this ub_dev is fully constructed at
+        * this point.
+        */
+
+       /*
+        * This is needed to clear toggles. It is a problem only if we do
+        * `rmmod ub && modprobe ub` without disconnects, but we like that.
+        */
+       ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
+       ub_probe_clear_stall(sc, sc->send_bulk_pipe);
+
+       /*
+        * The way this is used by the startup code is a little specific.
+        * A SCSI check causes a USB stall. Our common case code sees it
+        * and clears the check, after which the device is ready for use.
+        * But if a check was not present, any command other than
+        * TEST_UNIT_READY ends with a lockup (including REQUEST_SENSE).
+        *
+        * If we neglect to clear the SCSI check, the first real command fails
+        * (which is the capacity readout). We clear that and retry, but why
+        * causing spurious retries for no reason.
+        *
+        * Revalidation may start with its own TEST_UNIT_READY, but that one
+        * has to succeed, so we clear checks with an additional one here.
+        * In any case it's not our business how revaliadation is implemented.
+        */
+       ub_sync_tur(sc);
+
+       sc->removable = 1;              /* XXX Query this from the device */
+
+       ub_revalidate(sc);
+       /* This is pretty much a long term P3 */
+       printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
+           sc->name, sc->dev->devnum, sc->capacity.nsec, sc->capacity.bsize);
+
+       /*
+        * Just one disk per sc currently, but maybe more.
+        */
+       rc = -ENOMEM;
+       if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL)
+               goto err_diskalloc;
+
+       sc->disk = disk;
+       sprintf(disk->disk_name, DRV_NAME "%c", sc->id + 'a');
+       sprintf(disk->devfs_name, DEVFS_NAME "/%c", sc->id + 'a');
+       disk->major = UB_MAJOR;
+       disk->first_minor = sc->id * UB_MINORS_PER_MAJOR;
+       disk->fops = &ub_bd_fops;
+       disk->private_data = sc;
+       disk->driverfs_dev = &intf->dev;
+
+       rc = -ENOMEM;
+       if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL)
+               goto err_blkqinit;
+
+       disk->queue = q;
+
+        // blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
+       blk_queue_max_hw_segments(q, UB_MAX_REQ_SG);
+       blk_queue_max_phys_segments(q, UB_MAX_REQ_SG);
+       // blk_queue_segment_boundary(q, CARM_SG_BOUNDARY);
+       blk_queue_max_sectors(q, UB_MAX_SECTORS);
+       // blk_queue_hardsect_size(q, xxxxx);
+
+       /*
+        * This is a serious infraction, caused by a deficiency in the
+        * USB sg interface (usb_sg_wait()). We plan to remove this once
+        * we get mileage on the driver and can justify a change to USB API.
+        * See blk_queue_bounce_limit() to understand this part.
+        *
+        * XXX And I still need to be aware of the DMA mask in the HC.
+        */
+       q->bounce_pfn = blk_max_low_pfn;
+       q->bounce_gfp = GFP_NOIO;
+
+       q->queuedata = sc;
+
+       set_capacity(disk, sc->capacity.nsec);
+       if (sc->removable)
+               disk->flags |= GENHD_FL_REMOVABLE;
+
+       add_disk(disk);
+
+       return 0;
+
+err_blkqinit:
+       put_disk(disk);
+err_diskalloc:
+       device_remove_file(&sc->intf->dev, &dev_attr_diag);
+err_diag:
+       usb_set_intfdata(intf, NULL);
+       // usb_put_intf(sc->intf);
+       usb_put_dev(sc->dev);
+       spin_lock_irq(&ub_lock);
+       ub_id_put(sc->id);
+       spin_unlock_irq(&ub_lock);
+err_id:
+       kfree(sc);
+err_core:
+       return rc;
+}
+
+static void ub_disconnect(struct usb_interface *intf)
+{
+       struct ub_dev *sc = usb_get_intfdata(intf);
+       struct gendisk *disk = sc->disk;
+       request_queue_t *q = disk->queue;
+       unsigned long flags;
+
+       /*
+        * Fence stall clearnings, operations triggered by unlinkings and so on.
+        * We do not attempt to unlink any URBs, because we do not trust the
+        * unlink paths in HC drivers. Also, we get -84 upon disconnect anyway.
+        */
+       atomic_set(&sc->poison, 1);
+
+       /*
+        * Blow away queued commands.
+        *
+        * Actually, this never works, because before we get here
+        * the HCD terminates outstanding URB(s). It causes our
+        * SCSI command queue to advance, commands fail to submit,
+        * and the whole queue drains. So, we just use this code to
+        * print warnings.
+        */
+       spin_lock_irqsave(&sc->lock, flags);
+       {
+               struct ub_scsi_cmd *cmd;
+               int cnt = 0;
+               while ((cmd = ub_cmdq_pop(sc)) != NULL) {
+                       cmd->error = -ENOTCONN;
+                       cmd->state = UB_CMDST_DONE;
+                       ub_cmdtr_state(sc, cmd);
+                       ub_cmdq_pop(sc);
+                       (*cmd->done)(sc, cmd);
+                       cnt++;
+               }
+               if (cnt != 0) {
+                       printk(KERN_WARNING "%s: "
+                           "%d was queued after shutdown\n", sc->name, cnt);
+               }
+       }
+       spin_unlock_irqrestore(&sc->lock, flags);
+
+       /*
+        * Unregister the upper layer, this waits for all commands to end.
+        */
+       if (disk->flags & GENHD_FL_UP)
+               del_gendisk(disk);
+       if (q)
+               blk_cleanup_queue(q);
+
+       /*
+        * If we zero disk->private_data BEFORE put_disk, we have to check
+        * for NULL all over the place in open, release, check_media and
+        * revalidate, because the block level semaphore is well inside the
+        * put_disk. But we cannot zero after the call, because *disk is gone.
+        * The sd.c is blatantly racy in this area.
+        */
+       /* disk->private_data = NULL; */
+       put_disk(disk);
+       sc->disk = NULL;
+
+       /*
+        * We really expect blk_cleanup_queue() to wait, so no amount
+        * of paranoya is too much.
+        *
+        * Taking a lock on a structure which is about to be freed
+        * is very nonsensual. Here it is largely a way to do a debug freeze,
+        * and a bracket which shows where the nonsensual code segment ends.
+        *
+        * Testing for -EINPROGRESS is always a bug, so we are bending
+        * the rules a little.
+        */
+       spin_lock_irqsave(&sc->lock, flags);
+       if (sc->work_urb.status == -EINPROGRESS) {      /* janitors: ignore */
+               printk(KERN_WARNING "%s: "
+                   "URB is active after disconnect\n", sc->name);
+       }
+       spin_unlock_irqrestore(&sc->lock, flags);
+
+       /*
+        * At this point there must be no commands coming from anyone
+        * and no URBs left in transit.
+        */
+
+       device_remove_file(&sc->intf->dev, &dev_attr_diag);
+       usb_set_intfdata(intf, NULL);
+       // usb_put_intf(sc->intf);
+       sc->intf = NULL;
+       usb_put_dev(sc->dev);
+       sc->dev = NULL;
+
+       spin_lock_irqsave(&ub_lock, flags);
+       if (sc->openc == 0)
+               ub_cleanup(sc);
+       spin_unlock_irqrestore(&ub_lock, flags);
+}
+
+struct usb_driver ub_driver = {
+       .owner =        THIS_MODULE,
+       .name =         "ub",
+       .probe =        ub_probe,
+       .disconnect =   ub_disconnect,
+       .id_table =     ub_usb_ids,
+};
+
+static int __init ub_init(void)
+{
+       int rc;
+
+       /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu\n",
+                       sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev));
+
+       if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
+               goto err_regblkdev;
+       devfs_mk_dir(DEVFS_NAME);
+
+       if ((rc = usb_register(&ub_driver)) != 0)
+               goto err_register;
+
+       return 0;
+
+err_register:
+       devfs_remove(DEVFS_NAME);
+       unregister_blkdev(UB_MAJOR, DRV_NAME);
+err_regblkdev:
+       return rc;
+}
+
+static void __exit ub_exit(void)
+{
+       usb_deregister(&ub_driver);
+
+       devfs_remove(DEVFS_NAME);
+       unregister_blkdev(UB_MAJOR, DRV_NAME);
+}
+
+module_init(ub_init);
+module_exit(ub_exit);
+
+MODULE_LICENSE("GPL");
index cbe3364..09873fa 100644 (file)
@@ -729,8 +729,7 @@ static void restart_on_error(void)
                       res_reg[1]);
        }
 
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(2 * HZ);
+       msleep(2000);
 
        sony_get_toc();
 }
@@ -960,8 +959,7 @@ retry_cd_operation:
        if (((result_buffer[0] & 0xf0) == 0x20)
            && (num_retries < MAX_CDU31A_RETRIES)) {
                num_retries++;
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(HZ / 10);      /* Wait .1 seconds on retries */
+               msleep(100);
                goto retry_cd_operation;
        }
 
index 4cb0fb4..b4f5e02 100644 (file)
@@ -1021,10 +1021,9 @@ static int mcd_open(struct cdrom_device_info *cdi, int purpose)
                st = statusCmd();       /* check drive status */
                if (st == -1)
                        goto err_out;   /* drive doesn't respond */
-               if ((st & MST_READY) == 0) {    /* no disk? wait a sec... */
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(HZ);
-               }
+               if ((st & MST_READY) == 0)      /* no disk? wait a sec... */
+                       msleep(1000);
+
        } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);
 
        if (updateToc() < 0)
index 2128374..f83e3e3 100644 (file)
@@ -123,7 +123,7 @@ struct agp_bridge_data {
        void *current_size;
        void *dev_private_data;
        struct pci_dev *dev;
-       u32 *gatt_table;
+       u32 __iomem *gatt_table;
        u32 *gatt_table_real;
        unsigned long scratch_page;
        unsigned long scratch_page_real;
index 5fd2adc..323a6b6 100644 (file)
@@ -59,8 +59,8 @@ static struct gatt_mask hp_zx1_masks[] =
 };
 
 static struct _hp_private {
-       volatile u8 *ioc_regs;
-       volatile u8 *lba_regs;
+       volatile u8 __iomem *ioc_regs;
+       volatile u8 __iomem *lba_regs;
        int lba_cap_offset;
        u64 *io_pdir;           // PDIR for entire IOVA
        u64 *gatt;              // PDIR just for GART (subset of above)
@@ -97,7 +97,7 @@ static int __init hp_zx1_ioc_shared(void)
                default:
                        printk(KERN_ERR PFX "Invalid IOTLB page size "
                               "configuration 0x%x\n", hp->io_tlb_ps);
-                       hp->gatt = 0;
+                       hp->gatt = NULL;
                        hp->gatt_entries = 0;
                        return -ENODEV;
        }
@@ -115,7 +115,7 @@ static int __init hp_zx1_ioc_shared(void)
 
        if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
                /* Normal case when no AGP device in system */
-               hp->gatt = 0;
+               hp->gatt = NULL;
                hp->gatt_entries = 0;
                printk(KERN_ERR PFX "No reserved IO PDIR entry found; "
                       "GART disabled\n");
@@ -183,7 +183,7 @@ hp_zx1_ioc_init (u64 hpa)
 }
 
 static int
-hp_zx1_lba_find_capability (volatile u8 *hpa, int cap)
+hp_zx1_lba_find_capability (volatile u8 __iomem *hpa, int cap)
 {
        u16 status;
        u8 pos, id;
@@ -267,10 +267,10 @@ hp_zx1_cleanup (void)
        if (hp->ioc_regs) {
                if (hp->io_pdir_owner)
                        OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0);
-               iounmap((void *) hp->ioc_regs);
+               iounmap(hp->ioc_regs);
        }
        if (hp->lba_regs)
-               iounmap((void *) hp->lba_regs);
+               iounmap(hp->lba_regs);
 }
 
 static void
@@ -294,7 +294,7 @@ hp_zx1_create_gatt_table (void)
                if (!hp->io_pdir) {
                        printk(KERN_ERR PFX "Couldn't allocate contiguous "
                                "memory for I/O PDIR\n");
-                       hp->gatt = 0;
+                       hp->gatt = NULL;
                        hp->gatt_entries = 0;
                        return -ENOMEM;
                }
index 3dc61d4..f11cf4e 100644 (file)
@@ -118,10 +118,6 @@ static struct serial_state rs_table[1];
 
 #define NR_PORTS       (sizeof(rs_table)/sizeof(struct serial_state))
 
-#ifndef MIN
-#define MIN(a,b)       ((a) < (b) ? (a) : (b))
-#endif
-
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
  * lock it in case the copy_from_user blocks while swapping in a page,
@@ -430,7 +426,7 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
 
        if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) {
 #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
-               printk("ttyS%02d CD now %s...", info->line,
+               printk("ttyS%d CD now %s...", info->line,
                       (!(status & SER_DCD)) ? "on" : "off");
 #endif
                if (!(status & SER_DCD))
@@ -557,9 +553,7 @@ static void do_softint(unsigned long private_)
                return;
 
        if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   tty->ldisc.write_wakeup)
-                       (tty->ldisc.write_wakeup)(tty);
+               tty_wakeup(tty);
                wake_up_interruptible(&tty->write_wait);
        }
 }
@@ -1023,9 +1017,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
        info->xmit.head = info->xmit.tail = 0;
        local_irq_restore(flags);
        wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
 }
 
 /*
@@ -1564,8 +1556,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
        shutdown(info);
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+               
+       tty_ldisc_flush(tty);
        tty->closing = 0;
        info->event = 0;
        info->tty = 0;
@@ -1610,7 +1602,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
        if (char_time == 0)
                char_time = 1;
        if (timeout)
-         char_time = MIN(char_time, timeout);
+         char_time = min_t(unsigned long, char_time, timeout);
        /*
         * If the transmitter hasn't cleared in twice the approximate
         * amount of time to send the entire FIFO, it probably won't
@@ -2095,7 +2087,7 @@ static int __init rs_init(void)
          continue;
        */
 
-       printk(KERN_INFO "ttyS%02d is the amiga builtin serial port\n",
+       printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
                       state->line);
 
        /* Hardware set up */
index f0acc5e..d59102e 100644 (file)
@@ -8,6 +8,7 @@ r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o
 mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
 i810-objs   := i810_drv.o i810_dma.o
 i830-objs   := i830_drv.o i830_dma.o i830_irq.o
+i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
 radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
 ffb-objs    := ffb_drv.o ffb_context.o
 sis-objs    := sis_drv.o sis_ds.o sis_mm.o
@@ -19,6 +20,7 @@ obj-$(CONFIG_DRM_RADEON)+= radeon.o
 obj-$(CONFIG_DRM_MGA)  += mga.o
 obj-$(CONFIG_DRM_I810) += i810.o
 obj-$(CONFIG_DRM_I830) += i830.o
+obj-$(CONFIG_DRM_I915)  += i915.o
 obj-$(CONFIG_DRM_FFB)   += ffb.o
 obj-$(CONFIG_DRM_SIS)   += sis.o
 
diff --git a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h
new file mode 100644 (file)
index 0000000..8ebab5a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2004 Jon Smirl <jonsmirl@gmail.com>
+ *
+ * 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.
+ */
+
+#include "drm_auth.h"
+#include "drm_agpsupport.h"
+#include "drm_bufs.h"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_irq.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lock.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
+#include "drm_scatter.h"
index 04bb0ac..d26c999 100644 (file)
 
 #include <linux/interrupt.h>   /* For task queue support */
 
-#ifndef __HAVE_SHARED_IRQ
-#define __HAVE_SHARED_IRQ      0
-#endif
-
-#if __HAVE_SHARED_IRQ
-#define DRM_IRQ_TYPE           SA_SHIRQ
-#else
-#define DRM_IRQ_TYPE           0
-#endif
-
 /**
  * Get interrupt from bus id.
  * 
@@ -68,6 +58,9 @@ int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
        drm_irq_busid_t __user *argp = (void __user *)arg;
        drm_irq_busid_t p;
 
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+               return -EINVAL;
+
        if (copy_from_user(&p, argp, sizeof(p)))
                return -EFAULT;
 
@@ -86,8 +79,6 @@ int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
        return 0;
 }
 
-#if __HAVE_IRQ
-
 /**
  * Install IRQ handler.
  *
@@ -101,7 +92,11 @@ int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
 int DRM(irq_install)( drm_device_t *dev )
 {
        int ret;
+       unsigned long sh_flags=0;
+
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+               return -EINVAL;
+
        if ( dev->irq == 0 )
                return -EINVAL;
 
@@ -122,32 +117,25 @@ int DRM(irq_install)( drm_device_t *dev )
 
        DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
 
-#if __HAVE_DMA
-       dev->dma->next_buffer = NULL;
-       dev->dma->next_queue = NULL;
-       dev->dma->this_buffer = NULL;
-#endif
-
-#ifdef __HAVE_IRQ_BH
-       INIT_WORK(&dev->work, DRM(irq_immediate_bh), dev);
-#endif
-
-#ifdef __HAVE_VBL_IRQ
-       init_waitqueue_head(&dev->vbl_queue);
-
-       spin_lock_init( &dev->vbl_lock );
-
-       INIT_LIST_HEAD( &dev->vbl_sigs.head );
-
-       dev->vbl_pending = 0;
-#endif
+       if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
+               init_waitqueue_head(&dev->vbl_queue);
+               
+               spin_lock_init( &dev->vbl_lock );
+               
+               INIT_LIST_HEAD( &dev->vbl_sigs.head );
+               
+               dev->vbl_pending = 0;
+       }
 
                                /* Before installing handler */
-       DRM(driver_irq_preinstall)(dev);
+       dev->fn_tbl.irq_preinstall(dev);
 
                                /* Install handler */
-       ret = request_irq( dev->irq, DRM(irq_handler),
-                          DRM_IRQ_TYPE, dev->devname, dev );
+       if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
+               sh_flags = SA_SHIRQ;
+       
+       ret = request_irq( dev->irq, dev->fn_tbl.irq_handler,
+                          sh_flags, dev->devname, dev );
        if ( ret < 0 ) {
                down( &dev->struct_sem );
                dev->irq_enabled = 0;
@@ -156,7 +144,7 @@ int DRM(irq_install)( drm_device_t *dev )
        }
 
                                /* After installing handler */
-       DRM(driver_irq_postinstall)(dev);
+       dev->fn_tbl.irq_postinstall(dev);
 
        return 0;
 }
@@ -172,6 +160,9 @@ int DRM(irq_uninstall)( drm_device_t *dev )
 {
        int irq_enabled;
 
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+               return -EINVAL;
+
        down( &dev->struct_sem );
        irq_enabled = dev->irq_enabled;
        dev->irq_enabled = 0;
@@ -182,7 +173,7 @@ int DRM(irq_uninstall)( drm_device_t *dev )
 
        DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
 
-       DRM(driver_irq_uninstall)( dev );
+       dev->fn_tbl.irq_uninstall(dev);
 
        free_irq( dev->irq, dev );
 
@@ -206,25 +197,29 @@ int DRM(control)( struct inode *inode, struct file *filp,
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->dev;
        drm_control_t ctl;
+       
+       /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
 
        if ( copy_from_user( &ctl, (drm_control_t __user *)arg, sizeof(ctl) ) )
                return -EFAULT;
 
        switch ( ctl.func ) {
        case DRM_INST_HANDLER:
+               if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+                       return 0;
                if (dev->if_version < DRM_IF_VERSION(1, 2) &&
                    ctl.irq != dev->irq)
                        return -EINVAL;
                return DRM(irq_install)( dev );
        case DRM_UNINST_HANDLER:
+               if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+                       return 0;
                return DRM(irq_uninstall)( dev );
        default:
                return -EINVAL;
        }
 }
 
-#ifdef __HAVE_VBL_IRQ
-
 /**
  * Wait for VBLANK.
  *
@@ -254,6 +249,9 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS )
        int ret = 0;
        unsigned int flags;
 
+       if (!drm_core_check_feature(dev, DRIVER_IRQ_VBL))
+               return -EINVAL;
+
        if (!dev->irq)
                return -EINVAL;
 
@@ -318,7 +316,8 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS )
 
                spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
        } else {
-               ret = DRM(vblank_wait)( dev, &vblwait.request.sequence );
+               if (dev->fn_tbl.vblank_wait)
+                       ret = dev->fn_tbl.vblank_wait( dev, &vblwait.request.sequence );
 
                do_gettimeofday( &now );
                vblwait.reply.tval_sec = now.tv_sec;
@@ -366,6 +365,4 @@ void DRM(vbl_send_signals)( drm_device_t *dev )
        spin_unlock_irqrestore( &dev->vbl_lock, flags );
 }
 
-#endif /* __HAVE_VBL_IRQ */
 
-#endif /* __HAVE_IRQ */
index 9adfe79..c68e8d5 100644 (file)
@@ -44,7 +44,7 @@
  */
 #define DEBUG_MEMORY 0
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 
 #include <linux/vmalloc.h>
 
@@ -130,46 +130,56 @@ drm_follow_page (void *vaddr)
        return pte_pfn(*ptep) << PAGE_SHIFT;
 }
 
-#endif /* __REALLY_HAVE_AGP */
+#else /* __OS_HAS_AGP */
+
+static inline drm_map_t *drm_lookup_map(unsigned long offset, unsigned long size, drm_device_t *dev)
+{
+  return NULL;
+}
+
+static inline void *agp_remap(unsigned long offset, unsigned long size, drm_device_t *dev)
+{
+  return NULL;
+}
+
+static inline unsigned long drm_follow_page (void *vaddr)
+{
+  return 0;
+}
+
+#endif
 
 static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev)
 {
-#if __REALLY_HAVE_AGP
-       if (dev->agp && dev->agp->cant_use_aperture) {
+       if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
                drm_map_t *map = drm_lookup_map(offset, size, dev);
 
                if (map && map->type == _DRM_AGP)
                        return agp_remap(offset, size, dev);
        }
-#endif
-
        return ioremap(offset, size);
 }
 
 static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
                                        drm_device_t *dev)
 {
-#if __REALLY_HAVE_AGP
-       if (dev->agp && dev->agp->cant_use_aperture) {
+       if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
                drm_map_t *map = drm_lookup_map(offset, size, dev);
 
                if (map && map->type == _DRM_AGP)
                        return agp_remap(offset, size, dev);
        }
-#endif
-
        return ioremap_nocache(offset, size);
 }
 
 static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev)
 {
-#if __REALLY_HAVE_AGP
        /*
         * This is a bit ugly.  It would be much cleaner if the DRM API would use separate
         * routines for handling mappings in the AGP space.  Hopefully this can be done in
         * a future revision of the interface...
         */
-       if (dev->agp && dev->agp->cant_use_aperture
+       if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
            && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END))
        {
                unsigned long offset;
@@ -182,11 +192,11 @@ static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *d
                        return;
                }
        }
-#endif
 
        iounmap(pt);
 }
 
+
 #if DEBUG_MEMORY
 #include "drm_memory_debug.h"
 #else
@@ -331,7 +341,7 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
        drm_ioremapfree(pt, size, dev);
 }
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 /** Wrapper around agp_allocate_memory() */
 DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
 {
index 3b5f8d3..768c131 100644 (file)
 #define ffb_PCI_IDS \
        {0, 0, 0}
 
+#define i915_PCI_IDS \
+       {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0, 0, 0}
+
index e5d8293..436a017 100644 (file)
@@ -73,6 +73,9 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
 
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
+       if (!drm_core_check_feature(dev, DRIVER_SG))
+               return -EINVAL;
+
        if ( dev->sg )
                return -EINVAL;
 
@@ -206,6 +209,9 @@ int DRM(sg_free)( struct inode *inode, struct file *filp,
        drm_scatter_gather_t request;
        drm_sg_mem_t *entry;
 
+       if (!drm_core_check_feature(dev, DRIVER_SG))
+               return -EINVAL;
+
        if ( copy_from_user( &request,
                             (drm_scatter_gather_t __user *)arg,
                             sizeof(request) ) )
index 6fae05c..f518120 100644 (file)
@@ -354,7 +354,7 @@ static void FFBWait(ffb_fbcPtr ffb)
        } while (--limit);
 }
 
-int DRM(context_switch)(drm_device_t *dev, int old, int new)
+int ffb_driver_context_switch(drm_device_t *dev, int old, int new)
 {
        ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
 
@@ -380,7 +380,7 @@ int DRM(context_switch)(drm_device_t *dev, int old, int new)
         return 0;
 }
 
-int DRM(resctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
                unsigned long arg)
 {
        drm_ctx_res_t   res;
@@ -407,7 +407,7 @@ int DRM(resctx)(struct inode *inode, struct file *filp, unsigned int cmd,
 }
 
 
-int DRM(addctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
                unsigned long arg)
 {
        drm_file_t      *priv   = filp->private_data;
@@ -428,7 +428,7 @@ int DRM(addctx)(struct inode *inode, struct file *filp, unsigned int cmd,
        return 0;
 }
 
-int DRM(modctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
                unsigned long arg)
 {
        drm_file_t      *priv   = filp->private_data;
@@ -457,7 +457,7 @@ int DRM(modctx)(struct inode *inode, struct file *filp, unsigned int cmd,
        return 0;
 }
 
-int DRM(getctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
                unsigned long arg)
 {
        drm_file_t      *priv   = filp->private_data;
@@ -489,7 +489,7 @@ int DRM(getctx)(struct inode *inode, struct file *filp, unsigned int cmd,
        return 0;
 }
 
-int DRM(switchctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
                   unsigned long arg)
 {
        drm_file_t      *priv   = filp->private_data;
@@ -499,10 +499,10 @@ int DRM(switchctx)(struct inode *inode, struct file *filp, unsigned int cmd,
        if (copy_from_user(&ctx, (drm_ctx_t  __user *)arg, sizeof(ctx)))
                return -EFAULT;
        DRM_DEBUG("%d\n", ctx.handle);
-       return DRM(context_switch)(dev, dev->last_context, ctx.handle);
+       return ffb_driver_context_switch(dev, dev->last_context, ctx.handle);
 }
 
-int DRM(newctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
                unsigned long arg)
 {
        drm_ctx_t       ctx;
@@ -514,7 +514,7 @@ int DRM(newctx)(struct inode *inode, struct file *filp, unsigned int cmd,
        return 0;
 }
 
-int DRM(rmctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
               unsigned long arg)
 {
        drm_ctx_t       ctx;
@@ -537,3 +537,15 @@ int DRM(rmctx)(struct inode *inode, struct file *filp, unsigned int cmd,
        }
        return 0;
 }
+
+void ffb_set_context_ioctls(void)
+{
+       DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)].func = ffb_driver_addctx;
+       DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)].func = ffb_driver_rmctx;
+       DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)].func = ffb_driver_modctx;
+       DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)].func = ffb_driver_getctx;
+       DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func = ffb_driver_switchctx;
+       DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)].func = ffb_driver_newctx;
+       DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)].func = ffb_driver_resctx;
+
+}
index 094bbce..3b35467 100644 (file)
@@ -274,3 +274,13 @@ typedef struct ffb_dev_priv {
        /* Context table. */
        struct ffb_hw_context   *hw_state[FFB_MAX_CTXS];
 } ffb_dev_priv_t;
+
+extern struct file_operations DRM(fops);
+extern unsigned long ffb_get_unmapped_area(struct file *filp,
+                                          unsigned long hint,
+                                          unsigned long len,
+                                          unsigned long pgoff,
+                                          unsigned long flags);
+extern void ffb_set_context_ioctls(void);
+extern drm_ioctl_desc_t DRM(ioctls)[];
+
index d3c8c29..d11b507 100644 (file)
@@ -42,7 +42,7 @@
    the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
    DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
 
-ssize_t DRM(read)(struct file *filp, char __user *buf, size_t count, loff_t *off)
+ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
 {
        drm_file_t    *priv   = filp->private_data;
        drm_device_t  *dev    = priv->dev;
@@ -128,7 +128,7 @@ int DRM(write_string)(drm_device_t *dev, const char *s)
        return 0;
 }
 
-unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
+unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait)
 {
        drm_file_t   *priv = filp->private_data;
        drm_device_t *dev  = priv->dev;
index fc78a11..146fcc6 100644 (file)
@@ -35,7 +35,6 @@
 typedef struct drm_gamma_private {
        drm_gamma_sarea_t *sarea_priv;
        drm_map_t *sarea;
-       drm_map_t *buffers;
        drm_map_t *mmio0;
        drm_map_t *mmio1;
        drm_map_t *mmio2;
@@ -91,6 +90,10 @@ extern int        DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl,
                                       drm_buf_t *buf);
 extern drm_buf_t     *DRM(freelist_get)(drm_freelist_t *bl, int block);
 
+/* externs for gamma changes to the ops */
+extern struct file_operations DRM(fops);
+extern unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait);
+extern ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off);
 
 
 #define GLINT_DRI_BUF_COUNT 256
index 0bc7938..00ca551 100644 (file)
 #include "i810_drm.h"
 #include "i810_drv.h"
 
-#include "drm_agpsupport.h"
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
+#include "drm_core.h"
index 736c20d..67c5c88 100644 (file)
@@ -53,7 +53,6 @@ typedef struct _drm_i810_ring_buffer{
 
 typedef struct drm_i810_private {
        drm_map_t *sarea_map;
-       drm_map_t *buffer_map;
        drm_map_t *mmio_map;
 
        drm_i810_sarea_t *sarea_priv;
index c6d805f..c3cab2d 100644 (file)
@@ -53,7 +53,6 @@ typedef struct _drm_i830_ring_buffer{
 
 typedef struct drm_i830_private {
        drm_map_t *sarea_map;
-       drm_map_t *buffer_map;
        drm_map_t *mmio_map;
 
        drm_i830_sarea_t *sarea_priv;
@@ -137,6 +136,10 @@ extern int i830_irq_wait( struct inode *inode, struct file *filp,
 extern int i830_wait_irq(drm_device_t *dev, int irq_nr);
 extern int i830_emit_irq(drm_device_t *dev);
 
+extern irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS );
+extern void i830_driver_irq_preinstall( drm_device_t *dev );
+extern void i830_driver_irq_postinstall( drm_device_t *dev );
+extern void i830_driver_irq_uninstall( drm_device_t *dev );
 
 #define I830_BASE(reg)         ((unsigned long) \
                                dev_priv->mmio_map->handle)
diff --git a/drivers/char/drm/i915.h b/drivers/char/drm/i915.h
new file mode 100644 (file)
index 0000000..d76d737
--- /dev/null
@@ -0,0 +1,53 @@
+/* i915.h -- Intel I915 DRM template customization -*- linux-c -*-
+ */
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#ifndef __I915_H__
+#define __I915_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) i915_##x
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR          "Tungsten Graphics, Inc."
+
+#define DRIVER_NAME            "i915"
+#define DRIVER_DESC            "Intel Graphics"
+#define DRIVER_DATE            "20040405"
+
+/* Interface history:
+ *
+ * 1.1: Original.
+ */
+#define DRIVER_MAJOR           1
+#define DRIVER_MINOR           1
+#define DRIVER_PATCHLEVEL      0
+
+#define DRIVER_IOCTLS                                                      \
+       [DRM_IOCTL_NR(DRM_IOCTL_I915_INIT)]   = { i915_dma_init,    1, 1 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I915_FLUSH)]  = { i915_flush_ioctl, 1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I915_FLIP)]   = { i915_flip_bufs,   1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I915_BATCHBUFFER)] = { i915_batchbuffer, 1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I915_IRQ_EMIT)] = { i915_irq_emit,  1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I915_IRQ_WAIT)] = { i915_irq_wait,  1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I915_GETPARAM)] = { i915_getparam,  1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I915_SETPARAM)] = { i915_setparam,  1, 1 }, \
+        [DRM_IOCTL_NR(DRM_IOCTL_I915_ALLOC)]   = { i915_mem_alloc,  1, 0 }, \
+        [DRM_IOCTL_NR(DRM_IOCTL_I915_FREE)]    = { i915_mem_free,    1, 0 }, \
+        [DRM_IOCTL_NR(DRM_IOCTL_I915_INIT_HEAP)] = { i915_mem_init_heap, 1, 1 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I915_CMDBUFFER)] = { i915_cmdbuffer, 1, 0 }
+
+/* We use our own dma mechanisms, not the drm template code.  However,
+ * the shared IRQ code is useful to us:
+ */
+#define __HAVE_PM              1
+
+#endif
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
new file mode 100644 (file)
index 0000000..e33853b
--- /dev/null
@@ -0,0 +1,755 @@
+/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
+ */
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "i915.h"
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+static inline void i915_print_status_page(drm_device_t * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       u32 *temp = dev_priv->hw_status_page;
+
+       if (!temp) {
+               DRM_DEBUG("no status page\n");
+               return;
+       }
+
+       DRM_DEBUG("hw_status: Interrupt Status : %x\n", temp[0]);
+       DRM_DEBUG("hw_status: LpRing Head ptr : %x\n", temp[1]);
+       DRM_DEBUG("hw_status: IRing Head ptr : %x\n", temp[2]);
+       DRM_DEBUG("hw_status: Reserved : %x\n", temp[3]);
+       DRM_DEBUG("hw_status: Driver Counter : %d\n", temp[5]);
+
+}
+
+/* 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
+ * the head pointer changes, so that EBUSY only happens if the ring
+ * actually stalls for (eg) 3 seconds.
+ */
+int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+       u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+       int i;
+
+       for (i = 0; i < 10000; i++) {
+               ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+               ring->space = ring->head - (ring->tail + 8);
+               if (ring->space < 0)
+                       ring->space += ring->Size;
+               if (ring->space >= n)
+                       return 0;
+
+               dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+
+               if (ring->head != last_head)
+                       i = 0;
+
+               last_head = ring->head;
+       }
+
+       return DRM_ERR(EBUSY);
+}
+
+void i915_kernel_lost_context(drm_device_t * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+
+       ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+       ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
+       ring->space = ring->head - (ring->tail + 8);
+       if (ring->space < 0)
+               ring->space += ring->Size;
+
+       if (ring->head == ring->tail)
+               dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
+}
+
+int i915_dma_cleanup(drm_device_t * dev)
+{
+       /* Make sure interrupts are disabled here because the uninstall ioctl
+        * may not have been called from userspace and after dev_private
+        * is freed, it's too late.
+        */
+       if (dev->irq)
+               DRM(irq_uninstall) (dev);
+
+       if (dev->dev_private) {
+               drm_i915_private_t *dev_priv =
+                   (drm_i915_private_t *) dev->dev_private;
+
+               if (dev_priv->ring.virtual_start) {
+                       drm_core_ioremapfree( &dev_priv->ring.map, dev);
+               }
+
+               if (dev_priv->hw_status_page) {
+                       pci_free_consistent(dev->pdev, PAGE_SIZE,
+                                           dev_priv->hw_status_page,
+                                           dev_priv->dma_status_page);
+                       /* Need to rewrite hardware status page */
+                       I915_WRITE(0x02080, 0x1ffff000);
+               }
+
+               DRM(free) (dev->dev_private, sizeof(drm_i915_private_t),
+                          DRM_MEM_DRIVER);
+
+               dev->dev_private = NULL;
+       }
+
+       return 0;
+}
+
+static int i915_initialize(drm_device_t * dev,
+                          drm_i915_private_t * dev_priv,
+                          drm_i915_init_t * init)
+{
+       memset(dev_priv, 0, sizeof(drm_i915_private_t));
+
+       DRM_GETSAREA();
+       if (!dev_priv->sarea) {
+               DRM_ERROR("can not find sarea!\n");
+               dev->dev_private = (void *)dev_priv;
+               i915_dma_cleanup(dev);
+               return DRM_ERR(EINVAL);
+       }
+
+       dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
+       if (!dev_priv->mmio_map) {
+               dev->dev_private = (void *)dev_priv;
+               i915_dma_cleanup(dev);
+               DRM_ERROR("can not find mmio map!\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       dev_priv->sarea_priv = (drm_i915_sarea_t *)
+           ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
+
+       dev_priv->ring.Start = init->ring_start;
+       dev_priv->ring.End = init->ring_end;
+       dev_priv->ring.Size = init->ring_size;
+       dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
+       dev_priv->ring.map.offset = init->ring_start;
+       dev_priv->ring.map.size = init->ring_size;
+       dev_priv->ring.map.type = 0;
+       dev_priv->ring.map.flags = 0;
+       dev_priv->ring.map.mtrr = 0;
+
+       drm_core_ioremap( &dev_priv->ring.map, dev );
+
+       if (dev_priv->ring.map.handle == NULL) {
+               dev->dev_private = (void *)dev_priv;
+               i915_dma_cleanup(dev);
+               DRM_ERROR("can not ioremap virtual address for"
+                         " ring buffer\n");
+               return DRM_ERR(ENOMEM);
+       }
+
+       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+       dev_priv->back_offset = init->back_offset;
+       dev_priv->front_offset = init->front_offset;
+       dev_priv->current_page = 0;
+       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+
+       /* We are using separate values as placeholders for mechanisms for
+        * private backbuffer/depthbuffer usage.
+        */
+       dev_priv->use_mi_batchbuffer_start = 0;
+
+       /* Allow hardware batchbuffers unless told otherwise.
+        */
+       dev_priv->allow_batchbuffer = 1;
+
+       /* Program Hardware Status Page */
+       dev_priv->hw_status_page =
+           pci_alloc_consistent(dev->pdev, PAGE_SIZE,
+                                &dev_priv->dma_status_page);
+
+       if (!dev_priv->hw_status_page) {
+               dev->dev_private = (void *)dev_priv;
+               i915_dma_cleanup(dev);
+               DRM_ERROR("Can not allocate hardware status page\n");
+               return DRM_ERR(ENOMEM);
+       }
+       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+       DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+
+       I915_WRITE(0x02080, dev_priv->dma_status_page);
+       DRM_DEBUG("Enabled hardware status page\n");
+
+       dev->dev_private = (void *)dev_priv;
+
+       return 0;
+}
+
+static int i915_resume(drm_device_t * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       if (!dev_priv->sarea) {
+               DRM_ERROR("can not find sarea!\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       if (!dev_priv->mmio_map) {
+               DRM_ERROR("can not find mmio map!\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       if (dev_priv->ring.map.handle == NULL) {
+               DRM_ERROR("can not ioremap virtual address for"
+                         " ring buffer\n");
+               return DRM_ERR(ENOMEM);
+       }
+
+       /* Program Hardware Status Page */
+       if (!dev_priv->hw_status_page) {
+               DRM_ERROR("Can not find hardware status page\n");
+               return DRM_ERR(EINVAL);
+       }
+       DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+
+       I915_WRITE(0x02080, dev_priv->dma_status_page);
+       DRM_DEBUG("Enabled hardware status page\n");
+
+       return 0;
+}
+
+int i915_dma_init(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_i915_private_t *dev_priv;
+       drm_i915_init_t init;
+       int retcode = 0;
+
+       DRM_COPY_FROM_USER_IOCTL(init, (drm_i915_init_t __user *) data,
+                                sizeof(init));
+
+       switch (init.func) {
+       case I915_INIT_DMA:
+               dev_priv = DRM(alloc) (sizeof(drm_i915_private_t),
+                                      DRM_MEM_DRIVER);
+               if (dev_priv == NULL)
+                       return DRM_ERR(ENOMEM);
+               retcode = i915_initialize(dev, dev_priv, &init);
+               break;
+       case I915_CLEANUP_DMA:
+               retcode = i915_dma_cleanup(dev);
+               break;
+       case I915_RESUME_DMA:
+               retcode = i915_resume(dev);
+               break;
+       default:
+               retcode = -EINVAL;
+               break;
+       }
+
+       return retcode;
+}
+
+/* Implement basically the same security restrictions as hardware does
+ * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
+ *
+ * Most of the calculations below involve calculating the size of a
+ * particular instruction.  It's important to get the size right as
+ * that tells us where the next instruction to check is.  Any illegal
+ * instruction detected will be given a size of zero, which is a
+ * signal to abort the rest of the buffer.
+ */
+static int do_validate_cmd(int cmd)
+{
+       switch (((cmd >> 29) & 0x7)) {
+       case 0x0:
+               switch ((cmd >> 23) & 0x3f) {
+               case 0x0:
+                       return 1;       /* MI_NOOP */
+               case 0x4:
+                       return 1;       /* MI_FLUSH */
+               default:
+                       return 0;       /* disallow everything else */
+               }
+               break;
+       case 0x1:
+               return 0;       /* reserved */
+       case 0x2:
+               return (cmd & 0xff) + 2;        /* 2d commands */
+       case 0x3:
+               if (((cmd >> 24) & 0x1f) <= 0x18)
+                       return 1;
+
+               switch ((cmd >> 24) & 0x1f) {
+               case 0x1c:
+                       return 1;
+               case 0x1d:
+                       switch ((cmd>>16)&0xff) {
+                       case 0x3:
+                               return (cmd & 0x1f) + 2;
+                       case 0x4:
+                               return (cmd & 0xf) + 2;
+                       default:
+                               return (cmd & 0xffff) + 2;
+                       }
+               case 0x1e:
+                       if (cmd & (1 << 23))
+                               return (cmd & 0xffff) + 1;
+                       else
+                               return 1;
+               case 0x1f:
+                       if ((cmd & (1 << 23)) == 0)     /* inline vertices */
+                               return (cmd & 0x1ffff) + 2;
+                       else if (cmd & (1 << 17))       /* indirect random */
+                               if ((cmd & 0xffff) == 0)
+                                       return 0;       /* unknown length, too hard */
+                               else
+                                       return (((cmd & 0xffff) + 1) / 2) + 1;
+                       else
+                               return 2;       /* indirect sequential */
+               default:
+                       return 0;
+               }
+       default:
+               return 0;
+       }
+
+       return 0;
+}
+
+static int validate_cmd(int cmd)
+{
+       int ret = do_validate_cmd(cmd);
+
+/*     printk("validate_cmd( %x ): %d\n", cmd, ret); */
+
+       return ret;
+}
+
+static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       int i;
+       RING_LOCALS;
+
+       for (i = 0; i < dwords;) {
+               int cmd, sz;
+
+               if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
+                       return DRM_ERR(EINVAL);
+
+/*             printk("%d/%d ", i, dwords); */
+
+               if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
+                       return DRM_ERR(EINVAL);
+
+               BEGIN_LP_RING(sz);
+               OUT_RING(cmd);
+
+               while (++i, --sz) {
+                       if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
+                                                        sizeof(cmd))) {
+                               return DRM_ERR(EINVAL);
+                       }
+                       OUT_RING(cmd);
+               }
+               ADVANCE_LP_RING();
+       }
+
+       return 0;
+}
+
+static int i915_emit_box(drm_device_t * dev,
+                        drm_clip_rect_t __user * boxes,
+                        int i, int DR1, int DR4)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_clip_rect_t box;
+       RING_LOCALS;
+
+       if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
+               return EFAULT;
+       }
+
+       if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
+               DRM_ERROR("Bad box %d,%d..%d,%d\n",
+                         box.x1, box.y1, box.x2, box.y2);
+               return DRM_ERR(EINVAL);
+       }
+
+       BEGIN_LP_RING(6);
+       OUT_RING(GFX_OP_DRAWRECT_INFO);
+       OUT_RING(DR1);
+       OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
+       OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+       OUT_RING(DR4);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       return 0;
+}
+
+static int i915_dispatch_cmdbuffer(drm_device_t * dev,
+                                  drm_i915_cmdbuffer_t * cmd)
+{
+       int nbox = cmd->num_cliprects;
+       int i = 0, count, ret;
+
+       if (cmd->sz & 0x3) {
+               DRM_ERROR("alignment");
+               return DRM_ERR(EINVAL);
+       }
+
+       i915_kernel_lost_context(dev);
+
+       count = nbox ? nbox : 1;
+
+       for (i = 0; i < count; i++) {
+               if (i < nbox) {
+                       ret = i915_emit_box(dev, cmd->cliprects, i,
+                                           cmd->DR1, cmd->DR4);
+                       if (ret)
+                               return ret;
+               }
+
+               ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int i915_dispatch_batchbuffer(drm_device_t * dev,
+                                    drm_i915_batchbuffer_t * batch)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_clip_rect_t __user *boxes = batch->cliprects;
+       int nbox = batch->num_cliprects;
+       int i = 0, count;
+       RING_LOCALS;
+
+       if ((batch->start | batch->used) & 0x7) {
+               DRM_ERROR("alignment");
+               return DRM_ERR(EINVAL);
+       }
+
+       i915_kernel_lost_context(dev);
+
+       count = nbox ? nbox : 1;
+
+       for (i = 0; i < count; i++) {
+               if (i < nbox) {
+                       int ret = i915_emit_box(dev, boxes, i,
+                                               batch->DR1, batch->DR4);
+                       if (ret)
+                               return ret;
+               }
+
+               if (dev_priv->use_mi_batchbuffer_start) {
+                       BEGIN_LP_RING(2);
+                       OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+                       OUT_RING(batch->start | MI_BATCH_NON_SECURE);
+                       ADVANCE_LP_RING();
+               } else {
+                       BEGIN_LP_RING(4);
+                       OUT_RING(MI_BATCH_BUFFER);
+                       OUT_RING(batch->start | MI_BATCH_NON_SECURE);
+                       OUT_RING(batch->start + batch->used - 4);
+                       OUT_RING(0);
+                       ADVANCE_LP_RING();
+               }
+       }
+
+       dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+
+       BEGIN_LP_RING(4);
+       OUT_RING(CMD_STORE_DWORD_IDX);
+       OUT_RING(20);
+       OUT_RING(dev_priv->counter);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       return 0;
+}
+
+static int i915_dispatch_flip(drm_device_t * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+                 __FUNCTION__,
+                 dev_priv->current_page,
+                 dev_priv->sarea_priv->pf_current_page);
+
+       i915_kernel_lost_context(dev);
+
+       BEGIN_LP_RING(2);
+       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       BEGIN_LP_RING(6);
+       OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
+       OUT_RING(0);
+       if (dev_priv->current_page == 0) {
+               OUT_RING(dev_priv->back_offset);
+               dev_priv->current_page = 1;
+       } else {
+               OUT_RING(dev_priv->front_offset);
+               dev_priv->current_page = 0;
+       }
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       BEGIN_LP_RING(2);
+       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+
+       BEGIN_LP_RING(4);
+       OUT_RING(CMD_STORE_DWORD_IDX);
+       OUT_RING(20);
+       OUT_RING(dev_priv->counter);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+       return 0;
+}
+
+static int i915_quiescent(drm_device_t * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+
+       i915_kernel_lost_context(dev);
+       return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
+}
+
+int i915_flush_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+
+       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i915_flush_ioctl called without lock held\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       return i915_quiescent(dev);
+}
+
+int i915_batchbuffer(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 *hw_status = dev_priv->hw_status_page;
+       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+           dev_priv->sarea_priv;
+       drm_i915_batchbuffer_t batch;
+       int ret;
+
+       if (!dev_priv->allow_batchbuffer) {
+               DRM_ERROR("Batchbuffer ioctl disabled\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL(batch, (drm_i915_batchbuffer_t __user *) data,
+                                sizeof(batch));
+
+       DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
+                 batch.start, batch.used, batch.num_cliprects);
+
+       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i915_batchbuffer called without lock held\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
+                                                      batch.num_cliprects *
+                                                      sizeof(drm_clip_rect_t)))
+               return DRM_ERR(EFAULT);
+
+       ret = i915_dispatch_batchbuffer(dev, &batch);
+
+       sarea_priv->last_dispatch = (int)hw_status[5];
+       return ret;
+}
+
+int i915_cmdbuffer(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 *hw_status = dev_priv->hw_status_page;
+       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+           dev_priv->sarea_priv;
+       drm_i915_cmdbuffer_t cmdbuf;
+       int ret;
+
+       DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_i915_cmdbuffer_t __user *) data,
+                                sizeof(cmdbuf));
+
+       DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
+                 cmdbuf.buf, cmdbuf.sz, cmdbuf.num_cliprects);
+
+       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i915_cmdbuffer called without lock held\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       if (cmdbuf.num_cliprects &&
+           DRM_VERIFYAREA_READ(cmdbuf.cliprects,
+                               cmdbuf.num_cliprects *
+                               sizeof(drm_clip_rect_t))) {
+               DRM_ERROR("Fault accessing cliprects\n");
+               return DRM_ERR(EFAULT);
+       }
+
+       ret = i915_dispatch_cmdbuffer(dev, &cmdbuf);
+       if (ret) {
+               DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
+               return ret;
+       }
+
+       sarea_priv->last_dispatch = (int)hw_status[5];
+       return 0;
+}
+
+int i915_do_cleanup_pageflip(drm_device_t * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+       if (dev_priv->current_page != 0)
+               i915_dispatch_flip(dev);
+
+       return 0;
+}
+
+int i915_flip_bufs(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i915_flip_buf called without lock held\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       return i915_dispatch_flip(dev);
+}
+
+int i915_getparam(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_getparam_t param;
+       int value;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_getparam_t __user *) data,
+                                sizeof(param));
+
+       switch (param.param) {
+       case I915_PARAM_IRQ_ACTIVE:
+               value = dev->irq ? 1 : 0;
+               break;
+       case I915_PARAM_ALLOW_BATCHBUFFER:
+               value = dev_priv->allow_batchbuffer ? 1 : 0;
+               break;
+       default:
+               DRM_ERROR("Unkown parameter %d\n", param.param);
+               return DRM_ERR(EINVAL);
+       }
+
+       if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+               DRM_ERROR("DRM_COPY_TO_USER failed\n");
+               return DRM_ERR(EFAULT);
+       }
+
+       return 0;
+}
+
+int i915_setparam(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_setparam_t param;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_setparam_t __user *) data,
+                                sizeof(param));
+
+       switch (param.param) {
+       case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
+               dev_priv->use_mi_batchbuffer_start = param.value;
+               break;
+       case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
+               dev_priv->tex_lru_log_granularity = param.value;
+               break;
+       case I915_SETPARAM_ALLOW_BATCHBUFFER:
+               dev_priv->allow_batchbuffer = param.value;
+               break;
+       default:
+               DRM_ERROR("unknown parameter %d\n", param.param);
+               return DRM_ERR(EINVAL);
+       }
+
+       return 0;
+}
+
+static void i915_driver_pretakedown(drm_device_t *dev)
+{
+       if ( dev->dev_private ) {
+               drm_i915_private_t *dev_priv = dev->dev_private;
+               i915_mem_takedown( &(dev_priv->agp_heap) );
+       }
+       i915_dma_cleanup( dev );
+}
+
+static void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+{
+       if ( dev->dev_private ) {
+               drm_i915_private_t *dev_priv = dev->dev_private;
+                i915_mem_release( dev, filp, dev_priv->agp_heap );
+       }
+}
+
+void i915_driver_register_fns(drm_device_t *dev)
+{
+       dev->driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED;
+       dev->fn_tbl.pretakedown = i915_driver_pretakedown;
+       dev->fn_tbl.prerelease = i915_driver_prerelease;
+       dev->fn_tbl.irq_preinstall = i915_driver_irq_preinstall;
+       dev->fn_tbl.irq_postinstall = i915_driver_irq_postinstall;
+       dev->fn_tbl.irq_uninstall = i915_driver_irq_uninstall;
+       dev->fn_tbl.irq_handler = i915_driver_irq_handler;
+       
+       dev->counters += 4;
+       dev->types[6] = _DRM_STAT_IRQ;
+       dev->types[7] = _DRM_STAT_PRIMARY;
+       dev->types[8] = _DRM_STAT_SECONDARY;
+       dev->types[9] = _DRM_STAT_DMA;
+}
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
new file mode 100644 (file)
index 0000000..24f4cd6
--- /dev/null
@@ -0,0 +1,154 @@
+#ifndef _I915_DRM_H_
+#define _I915_DRM_H_
+
+/* Please note that modifications to all structs defined here are
+ * subject to backwards-compatibility constraints.
+ */
+
+#include "drm.h"
+
+/* Each region is a minimum of 16k, and there are at most 255 of them.
+ */
+#define I915_NR_TEX_REGIONS 255        /* table size 2k - maximum due to use
+                                * of chars for next/prev indices */
+#define I915_LOG_MIN_TEX_REGION_SIZE 14
+
+typedef struct _drm_i915_init {
+       enum {
+               I915_INIT_DMA = 0x01,
+               I915_CLEANUP_DMA = 0x02,
+               I915_RESUME_DMA = 0x03
+       } func;
+       unsigned int mmio_offset;
+       int sarea_priv_offset;
+       unsigned int ring_start;
+       unsigned int ring_end;
+       unsigned int ring_size;
+       unsigned int front_offset;
+       unsigned int back_offset;
+       unsigned int depth_offset;
+       unsigned int w;
+       unsigned int h;
+       unsigned int pitch;
+       unsigned int pitch_bits;
+       unsigned int back_pitch;
+       unsigned int depth_pitch;
+       unsigned int cpp;
+       unsigned int chipset;
+} drm_i915_init_t;
+
+typedef struct _drm_i915_sarea {
+       drm_tex_region_t texList[I915_NR_TEX_REGIONS + 1];
+       int last_upload;        /* last time texture was uploaded */
+       int last_enqueue;       /* last time a buffer was enqueued */
+       int last_dispatch;      /* age of the most recently dispatched buffer */
+       int ctxOwner;           /* last context to upload state */
+       int texAge;
+       int pf_enabled;         /* is pageflipping allowed? */
+       int pf_active;
+       int pf_current_page;    /* which buffer is being displayed? */
+       int perf_boxes;         /* performance boxes to be displayed */
+} drm_i915_sarea_t;
+
+/* Flags for perf_boxes
+ */
+#define I915_BOX_RING_EMPTY    0x1
+#define I915_BOX_FLIP          0x2
+#define I915_BOX_WAIT          0x4
+#define I915_BOX_TEXTURE_LOAD  0x8
+#define I915_BOX_LOST_CONTEXT  0x10
+
+/* I915 specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_IOCTL_I915_INIT            DRM_IOW( 0x40, drm_i915_init_t)
+#define DRM_IOCTL_I915_FLUSH           DRM_IO ( 0x41)
+#define DRM_IOCTL_I915_FLIP            DRM_IO ( 0x42)
+#define DRM_IOCTL_I915_BATCHBUFFER     DRM_IOW( 0x43, drm_i915_batchbuffer_t)
+#define DRM_IOCTL_I915_IRQ_EMIT         DRM_IOWR(0x44, drm_i915_irq_emit_t)
+#define DRM_IOCTL_I915_IRQ_WAIT         DRM_IOW( 0x45, drm_i915_irq_wait_t)
+#define DRM_IOCTL_I915_GETPARAM         DRM_IOWR(0x46, drm_i915_getparam_t)
+#define DRM_IOCTL_I915_SETPARAM         DRM_IOW( 0x47, drm_i915_setparam_t)
+#define DRM_IOCTL_I915_ALLOC            DRM_IOWR(0x48, drm_i915_mem_alloc_t)
+#define DRM_IOCTL_I915_FREE             DRM_IOW( 0x49, drm_i915_mem_free_t)
+#define DRM_IOCTL_I915_INIT_HEAP        DRM_IOW( 0x4a, drm_i915_mem_init_heap_t)
+#define DRM_IOCTL_I915_CMDBUFFER       DRM_IOW( 0x4b, drm_i915_cmdbuffer_t)
+
+/* Allow drivers to submit batchbuffers directly to hardware, relying
+ * on the security mechanisms provided by hardware.
+ */
+typedef struct _drm_i915_batchbuffer {
+       int start;              /* agp offset */
+       int used;               /* nr bytes in use */
+       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
+       int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
+       int num_cliprects;      /* mulitpass with multiple cliprects? */
+       drm_clip_rect_t __user *cliprects;      /* pointer to userspace cliprects */
+} drm_i915_batchbuffer_t;
+
+/* As above, but pass a pointer to userspace buffer which can be
+ * validated by the kernel prior to sending to hardware.
+ */
+typedef struct _drm_i915_cmdbuffer {
+       char __user *buf;       /* pointer to userspace command buffer */
+       int sz;                 /* nr bytes in buf */
+       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
+       int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
+       int num_cliprects;      /* mulitpass with multiple cliprects? */
+       drm_clip_rect_t __user *cliprects;      /* pointer to userspace cliprects */
+} drm_i915_cmdbuffer_t;
+
+/* Userspace can request & wait on irq's:
+ */
+typedef struct drm_i915_irq_emit {
+       int __user *irq_seq;
+} drm_i915_irq_emit_t;
+
+typedef struct drm_i915_irq_wait {
+       int irq_seq;
+} drm_i915_irq_wait_t;
+
+/* Ioctl to query kernel params:
+ */
+#define I915_PARAM_IRQ_ACTIVE            1
+#define I915_PARAM_ALLOW_BATCHBUFFER     2
+
+typedef struct drm_i915_getparam {
+       int param;
+       int __user *value;
+} drm_i915_getparam_t;
+
+/* Ioctl to set kernel params:
+ */
+#define I915_SETPARAM_USE_MI_BATCHBUFFER_START            1
+#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY             2
+#define I915_SETPARAM_ALLOW_BATCHBUFFER                   3
+
+typedef struct drm_i915_setparam {
+       int param;
+       int value;
+} drm_i915_setparam_t;
+
+/* A memory manager for regions of shared memory:
+ */
+#define I915_MEM_REGION_AGP 1
+
+typedef struct drm_i915_mem_alloc {
+       int region;
+       int alignment;
+       int size;
+       int __user *region_offset;      /* offset from start of fb or agp */
+} drm_i915_mem_alloc_t;
+
+typedef struct drm_i915_mem_free {
+       int region;
+       int region_offset;
+} drm_i915_mem_free_t;
+
+typedef struct drm_i915_mem_init_heap {
+       int region;
+       int size;
+       int start;
+} drm_i915_mem_init_heap_t;
+
+#endif                         /* _I915_DRM_H_ */
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
new file mode 100644 (file)
index 0000000..becce4d
--- /dev/null
@@ -0,0 +1,17 @@
+/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
+ */
+
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "i915.h"
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#include "drm_core.h"
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
new file mode 100644 (file)
index 0000000..7564cd0
--- /dev/null
@@ -0,0 +1,219 @@
+/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
+ */
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#ifndef _I915_DRV_H_
+#define _I915_DRV_H_
+
+typedef struct _drm_i915_ring_buffer {
+       int tail_mask;
+       unsigned long Start;
+       unsigned long End;
+       unsigned long Size;
+       u8 *virtual_start;
+       int head;
+       int tail;
+       int space;
+       drm_local_map_t map;
+} drm_i915_ring_buffer_t;
+
+struct mem_block {
+       struct mem_block *next;
+       struct mem_block *prev;
+       int start;
+       int size;
+       DRMFILE filp;           /* 0: free, -1: heap, other: real files */
+};
+
+typedef struct drm_i915_private {
+       drm_local_map_t *sarea;
+       drm_local_map_t *mmio_map;
+
+       drm_i915_sarea_t *sarea_priv;
+       drm_i915_ring_buffer_t ring;
+
+       void *hw_status_page;
+       unsigned long counter;
+       dma_addr_t dma_status_page;
+
+       int back_offset;
+       int front_offset;
+       int current_page;
+       int page_flipping;
+       int use_mi_batchbuffer_start;
+
+       wait_queue_head_t irq_queue;
+       atomic_t irq_received;
+       atomic_t irq_emitted;
+
+       int tex_lru_log_granularity;
+       int allow_batchbuffer;
+       struct mem_block *agp_heap;
+} drm_i915_private_t;
+
+                               /* i915_dma.c */
+extern int i915_dma_init(DRM_IOCTL_ARGS);
+extern int i915_dma_cleanup(drm_device_t * dev);
+extern int i915_flush_ioctl(DRM_IOCTL_ARGS);
+extern int i915_batchbuffer(DRM_IOCTL_ARGS);
+extern int i915_flip_bufs(DRM_IOCTL_ARGS);
+extern int i915_getparam(DRM_IOCTL_ARGS);
+extern int i915_setparam(DRM_IOCTL_ARGS);
+extern int i915_cmdbuffer(DRM_IOCTL_ARGS);
+extern void i915_kernel_lost_context(drm_device_t * dev);
+
+/* i915_irq.c */
+extern int i915_irq_emit(DRM_IOCTL_ARGS);
+extern int i915_irq_wait(DRM_IOCTL_ARGS);
+extern int i915_wait_irq(drm_device_t * dev, int irq_nr);
+extern int i915_emit_irq(drm_device_t * dev);
+
+extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
+extern void i915_driver_irq_preinstall(drm_device_t *dev);
+extern void i915_driver_irq_postinstall(drm_device_t *dev);
+extern void i915_driver_irq_uninstall(drm_device_t *dev);
+
+/* i915_mem.c */
+extern int i915_mem_alloc(DRM_IOCTL_ARGS);
+extern int i915_mem_free(DRM_IOCTL_ARGS);
+extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
+extern void i915_mem_takedown(struct mem_block **heap);
+extern void i915_mem_release(drm_device_t * dev,
+                            DRMFILE filp, struct mem_block *heap);
+
+#define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, reg)
+#define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, reg, val)
+#define I915_READ16(reg)       DRM_READ16(dev_priv->mmio_map, reg)
+#define I915_WRITE16(reg,val)  DRM_WRITE16(dev_priv->mmio_map, reg, val)
+
+#define I915_VERBOSE 0
+
+#define RING_LOCALS    unsigned int outring, ringmask, outcount; \
+                        volatile char *virt;
+
+#define BEGIN_LP_RING(n) do {                          \
+       if (I915_VERBOSE)                               \
+               DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n",  \
+                         n, __FUNCTION__);             \
+       if (dev_priv->ring.space < n*4)                 \
+               i915_wait_ring(dev, n*4, __FUNCTION__);         \
+       outcount = 0;                                   \
+       outring = dev_priv->ring.tail;                  \
+       ringmask = dev_priv->ring.tail_mask;            \
+       virt = dev_priv->ring.virtual_start;            \
+} while (0)
+
+#define OUT_RING(n) do {                                       \
+       if (I915_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));      \
+       *(volatile unsigned int *)(virt + outring) = n;         \
+        outcount++;                                            \
+       outring += 4;                                           \
+       outring &= ringmask;                                    \
+} while (0)
+
+#define ADVANCE_LP_RING() do {                                         \
+       if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring);   \
+       dev_priv->ring.tail = outring;                                  \
+       dev_priv->ring.space -= outcount * 4;                           \
+       I915_WRITE(LP_RING + RING_TAIL, outring);                       \
+} while(0)
+
+extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
+
+#define GFX_OP_USER_INTERRUPT          ((0<<29)|(2<<23))
+#define GFX_OP_BREAKPOINT_INTERRUPT    ((0<<29)|(1<<23))
+#define CMD_REPORT_HEAD                        (7<<23)
+#define CMD_STORE_DWORD_IDX            ((0x21<<23) | 0x1)
+#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
+
+#define INST_PARSER_CLIENT   0x00000000
+#define INST_OP_FLUSH        0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+#define BB1_START_ADDR_MASK   (~0x7)
+#define BB1_PROTECTED         (1<<0)
+#define BB1_UNPROTECTED       (0<<0)
+#define BB2_END_ADDR_MASK     (~0x7)
+
+#define I915REG_HWSTAM         0x02098
+#define I915REG_INT_IDENTITY_R 0x020a4
+#define I915REG_INT_MASK_R     0x020a8
+#define I915REG_INT_ENABLE_R   0x020a0
+
+#define SRX_INDEX              0x3c4
+#define SRX_DATA               0x3c5
+#define SR01                   1
+#define SR01_SCREEN_OFF        (1<<5)
+
+#define PPCR                   0x61204
+#define PPCR_ON                        (1<<0)
+
+#define ADPA                   0x61100
+#define ADPA_DPMS_MASK         (~(3<<10))
+#define ADPA_DPMS_ON           (0<<10)
+#define ADPA_DPMS_SUSPEND      (1<<10)
+#define ADPA_DPMS_STANDBY      (2<<10)
+#define ADPA_DPMS_OFF          (3<<10)
+
+#define NOPID                   0x2094
+#define LP_RING                0x2030
+#define HP_RING                0x2040
+#define RING_TAIL                      0x00
+#define TAIL_ADDR              0x001FFFF8
+#define RING_HEAD                      0x04
+#define HEAD_WRAP_COUNT        0xFFE00000
+#define HEAD_WRAP_ONE          0x00200000
+#define HEAD_ADDR              0x001FFFFC
+#define RING_START                     0x08
+#define START_ADDR             0x0xFFFFF000
+#define RING_LEN                       0x0C
+#define RING_NR_PAGES          0x001FF000
+#define RING_REPORT_MASK       0x00000006
+#define RING_REPORT_64K        0x00000002
+#define RING_REPORT_128K       0x00000004
+#define RING_NO_REPORT         0x00000000
+#define RING_VALID_MASK        0x00000001
+#define RING_VALID             0x00000001
+#define RING_INVALID           0x00000000
+
+#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define SC_UPDATE_SCISSOR       (0x1<<1)
+#define SC_ENABLE_MASK          (0x1<<0)
+#define SC_ENABLE               (0x1<<0)
+
+#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
+#define SCI_YMIN_MASK      (0xffff<<16)
+#define SCI_XMIN_MASK      (0xffff<<0)
+#define SCI_YMAX_MASK      (0xffff<<16)
+#define SCI_XMAX_MASK      (0xffff<<0)
+
+#define GFX_OP_SCISSOR_ENABLE   ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define GFX_OP_SCISSOR_RECT     ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+
+#define MI_BATCH_BUFFER        ((0x30<<23)|1)
+#define MI_BATCH_BUFFER_START  (0x31<<23)
+#define MI_BATCH_BUFFER_END    (0xA<<23)
+#define MI_BATCH_NON_SECURE    (1)
+
+#define MI_WAIT_FOR_EVENT       ((0x3<<23))
+#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
+#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+
+#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
+
+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
+#define ASYNC_FLIP                (1<<22)
+
+#define CMD_OP_DESTBUFFER_INFO  ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+
+#endif
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
new file mode 100644 (file)
index 0000000..de91aba
--- /dev/null
@@ -0,0 +1,165 @@
+/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
+ */
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "i915.h"
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#define USER_INT_FLAG 0x2
+#define MAX_NOPID ((u32)~0)
+#define READ_BREADCRUMB(dev_priv)  (((u32*)(dev_priv->hw_status_page))[5])
+
+irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
+{
+       drm_device_t *dev = (drm_device_t *) arg;
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u16 temp;
+
+       temp = I915_READ16(I915REG_INT_IDENTITY_R);
+       temp &= USER_INT_FLAG;
+
+       DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
+
+       if (temp == 0)
+               return IRQ_NONE;
+
+       I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+       DRM_WAKEUP(&dev_priv->irq_queue);
+
+       return IRQ_HANDLED;
+}
+
+int i915_emit_irq(drm_device_t * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       u32 ret;
+       RING_LOCALS;
+
+       i915_kernel_lost_context(dev);
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       ret = dev_priv->counter;
+
+       BEGIN_LP_RING(2);
+       OUT_RING(0);
+       OUT_RING(GFX_OP_USER_INTERRUPT);
+       ADVANCE_LP_RING();
+
+       return ret;
+}
+
+int i915_wait_irq(drm_device_t * dev, int irq_nr)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int ret = 0;
+
+       DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
+                 READ_BREADCRUMB(dev_priv));
+
+       if (READ_BREADCRUMB(dev_priv) >= irq_nr)
+               return 0;
+
+       dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+
+       DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
+                   READ_BREADCRUMB(dev_priv) >= irq_nr);
+
+       if (ret == DRM_ERR(EBUSY)) {
+               DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
+                         __FUNCTION__,
+                         READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
+       }
+
+       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+       return ret;
+}
+
+/* Needs the lock as it touches the ring.
+ */
+int i915_irq_emit(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_irq_emit_t emit;
+       int result;
+
+       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i915_irq_emit called without lock held\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data,
+                                sizeof(emit));
+
+       result = i915_emit_irq(dev);
+
+       if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return DRM_ERR(EFAULT);
+       }
+
+       return 0;
+}
+
+/* Doesn't need the hardware lock.
+ */
+int i915_irq_wait(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_irq_wait_t irqwait;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data,
+                                sizeof(irqwait));
+
+       return i915_wait_irq(dev, irqwait.irq_seq);
+}
+
+/* drm_dma.h hooks
+*/
+void i915_driver_irq_preinstall(drm_device_t * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+       I915_WRITE16(I915REG_HWSTAM, 0xfffe);
+       I915_WRITE16(I915REG_INT_MASK_R, 0x0);
+       I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+}
+
+void i915_driver_irq_postinstall(drm_device_t * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+       I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG);
+       DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+}
+
+void i915_driver_irq_uninstall(drm_device_t * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       if (!dev_priv)
+               return;
+
+       I915_WRITE16(I915REG_HWSTAM, 0xffff);
+       I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
+       I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+}
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
new file mode 100644 (file)
index 0000000..42c1e35
--- /dev/null
@@ -0,0 +1,347 @@
+/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
+ */
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "i915.h"
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/* This memory manager is integrated into the global/local lru
+ * mechanisms used by the clients.  Specifically, it operates by
+ * setting the 'in_use' fields of the global LRU to indicate whether
+ * this region is privately allocated to a client.
+ *
+ * This does require the client to actually respect that field.
+ *
+ * Currently no effort is made to allocate 'private' memory in any
+ * clever way - the LRU information isn't used to determine which
+ * block to allocate, and the ring is drained prior to allocations --
+ * in other words allocation is expensive.
+ */
+static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_tex_region_t *list;
+       unsigned shift, nr;
+       unsigned start;
+       unsigned end;
+       unsigned i;
+       int age;
+
+       shift = dev_priv->tex_lru_log_granularity;
+       nr = I915_NR_TEX_REGIONS;
+
+       start = p->start >> shift;
+       end = (p->start + p->size - 1) >> shift;
+
+       age = ++sarea_priv->texAge;
+       list = sarea_priv->texList;
+
+       /* Mark the regions with the new flag and update their age.  Move
+        * them to head of list to preserve LRU semantics.
+        */
+       for (i = start; i <= end; i++) {
+               list[i].in_use = in_use;
+               list[i].age = age;
+
+               /* remove_from_list(i)
+                */
+               list[(unsigned)list[i].next].prev = list[i].prev;
+               list[(unsigned)list[i].prev].next = list[i].next;
+
+               /* insert_at_head(list, i)
+                */
+               list[i].prev = nr;
+               list[i].next = list[nr].next;
+               list[(unsigned)list[nr].next].prev = i;
+               list[nr].next = i;
+       }
+}
+
+/* Very simple allocator for agp memory, working on a static range
+ * already mapped into each client's address space.  
+ */
+
+static struct mem_block *split_block(struct mem_block *p, int start, int size,
+                                    DRMFILE filp)
+{
+       /* Maybe cut off the start of an existing block */
+       if (start > p->start) {
+               struct mem_block *newblock = DRM_MALLOC(sizeof(*newblock));
+               if (!newblock)
+                       goto out;
+               newblock->start = start;
+               newblock->size = p->size - (start - p->start);
+               newblock->filp = NULL;
+               newblock->next = p->next;
+               newblock->prev = p;
+               p->next->prev = newblock;
+               p->next = newblock;
+               p->size -= newblock->size;
+               p = newblock;
+       }
+
+       /* Maybe cut off the end of an existing block */
+       if (size < p->size) {
+               struct mem_block *newblock = DRM_MALLOC(sizeof(*newblock));
+               if (!newblock)
+                       goto out;
+               newblock->start = start + size;
+               newblock->size = p->size - size;
+               newblock->filp = NULL;
+               newblock->next = p->next;
+               newblock->prev = p;
+               p->next->prev = newblock;
+               p->next = newblock;
+               p->size = size;
+       }
+
+      out:
+       /* Our block is in the middle */
+       p->filp = filp;
+       return p;
+}
+
+static struct mem_block *alloc_block(struct mem_block *heap, int size,
+                                    int align2, DRMFILE filp)
+{
+       struct mem_block *p;
+       int mask = (1 << align2) - 1;
+
+       for (p = heap->next; p != heap; p = p->next) {
+               int start = (p->start + mask) & ~mask;
+               if (p->filp == NULL && start + size <= p->start + p->size)
+                       return split_block(p, start, size, filp);
+       }
+
+       return NULL;
+}
+
+static struct mem_block *find_block(struct mem_block *heap, int start)
+{
+       struct mem_block *p;
+
+       for (p = heap->next; p != heap; p = p->next)
+               if (p->start == start)
+                       return p;
+
+       return NULL;
+}
+
+static void free_block(struct mem_block *p)
+{
+       p->filp = NULL;
+
+       /* Assumes a single contiguous range.  Needs a special filp in
+        * 'heap' to stop it being subsumed.
+        */
+       if (p->next->filp == NULL) {
+               struct mem_block *q = p->next;
+               p->size += q->size;
+               p->next = q->next;
+               p->next->prev = p;
+               DRM_FREE(q, sizeof(*q));
+       }
+
+       if (p->prev->filp == NULL) {
+               struct mem_block *q = p->prev;
+               q->size += p->size;
+               q->next = p->next;
+               q->next->prev = q;
+               DRM_FREE(p, sizeof(*q));
+       }
+}
+
+/* Initialize.  How to check for an uninitialized heap?
+ */
+static int init_heap(struct mem_block **heap, int start, int size)
+{
+       struct mem_block *blocks = DRM_MALLOC(sizeof(*blocks));
+
+       if (!blocks)
+               return -ENOMEM;
+
+       *heap = DRM_MALLOC(sizeof(**heap));
+       if (!*heap) {
+               DRM_FREE(blocks, sizeof(*blocks));
+               return -ENOMEM;
+       }
+
+       blocks->start = start;
+       blocks->size = size;
+       blocks->filp = NULL;
+       blocks->next = blocks->prev = *heap;
+
+       memset(*heap, 0, sizeof(**heap));
+       (*heap)->filp = (DRMFILE) - 1;
+       (*heap)->next = (*heap)->prev = blocks;
+       return 0;
+}
+
+/* Free all blocks associated with the releasing file.
+ */
+void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap)
+{
+       struct mem_block *p;
+
+       if (!heap || !heap->next)
+               return;
+
+       for (p = heap->next; p != heap; p = p->next) {
+               if (p->filp == filp) {
+                       p->filp = NULL;
+                       mark_block(dev, p, 0);
+               }
+       }
+
+       /* Assumes a single contiguous range.  Needs a special filp in
+        * 'heap' to stop it being subsumed.
+        */
+       for (p = heap->next; p != heap; p = p->next) {
+               while (p->filp == NULL && p->next->filp == NULL) {
+                       struct mem_block *q = p->next;
+                       p->size += q->size;
+                       p->next = q->next;
+                       p->next->prev = p;
+                       DRM_FREE(q, sizeof(*q));
+               }
+       }
+}
+
+/* Shutdown.
+ */
+void i915_mem_takedown(struct mem_block **heap)
+{
+       struct mem_block *p;
+
+       if (!*heap)
+               return;
+
+       for (p = (*heap)->next; p != *heap;) {
+               struct mem_block *q = p;
+               p = p->next;
+               DRM_FREE(q, sizeof(*q));
+       }
+
+       DRM_FREE(*heap, sizeof(**heap));
+       *heap = NULL;
+}
+
+static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
+{
+       switch (region) {
+       case I915_MEM_REGION_AGP:
+               return &dev_priv->agp_heap;
+       default:
+               return NULL;
+       }
+}
+
+/* IOCTL HANDLERS */
+
+int i915_mem_alloc(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_mem_alloc_t alloc;
+       struct mem_block *block, **heap;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL(alloc, (drm_i915_mem_alloc_t __user *) data,
+                                sizeof(alloc));
+
+       heap = get_heap(dev_priv, alloc.region);
+       if (!heap || !*heap)
+               return DRM_ERR(EFAULT);
+
+       /* Make things easier on ourselves: all allocations at least
+        * 4k aligned.
+        */
+       if (alloc.alignment < 12)
+               alloc.alignment = 12;
+
+       block = alloc_block(*heap, alloc.size, alloc.alignment, filp);
+
+       if (!block)
+               return DRM_ERR(ENOMEM);
+
+       mark_block(dev, block, 1);
+
+       if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return DRM_ERR(EFAULT);
+       }
+
+       return 0;
+}
+
+int i915_mem_free(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_mem_free_t memfree;
+       struct mem_block *block, **heap;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL(memfree, (drm_i915_mem_free_t __user *) data,
+                                sizeof(memfree));
+
+       heap = get_heap(dev_priv, memfree.region);
+       if (!heap || !*heap)
+               return DRM_ERR(EFAULT);
+
+       block = find_block(*heap, memfree.region_offset);
+       if (!block)
+               return DRM_ERR(EFAULT);
+
+       if (block->filp != filp)
+               return DRM_ERR(EPERM);
+
+       mark_block(dev, block, 0);
+       free_block(block);
+       return 0;
+}
+
+int i915_mem_init_heap(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_mem_init_heap_t initheap;
+       struct mem_block **heap;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL(initheap,
+                                (drm_i915_mem_init_heap_t __user *) data,
+                                sizeof(initheap));
+
+       heap = get_heap(dev_priv, initheap.region);
+       if (!heap)
+               return DRM_ERR(EFAULT);
+
+       if (*heap) {
+               DRM_ERROR("heap already initialized?");
+               return DRM_ERR(EFAULT);
+       }
+
+       return init_heap(heap, initheap.start, initheap.size);
+}
index 7bdc99c..838e360 100644 (file)
 
 /* General customization:
  */
-#define __HAVE_AGP             1
-#define __MUST_HAVE_AGP                0
-#define __HAVE_MTRR            1
-#define __HAVE_CTX_BITMAP      1
 
 #define DRIVER_AUTHOR          "SIS"
 #define DRIVER_NAME            "sis"
        [DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_FREE)]  = { sis_ioctl_agp_free, 1, 0 }, \
        [DRM_IOCTL_NR(DRM_IOCTL_SIS_FB_INIT)]   = { sis_fb_init,        1, 1 }
 
-#define __HAVE_COUNTERS                5
-
-/* Buffer customization:
- */
-#define DRIVER_AGP_BUFFERS_MAP( dev )                                  \
-       ((drm_sis_private_t *)((dev)->dev_private))->buffers
-
-extern int sis_init_context(int context);
-extern int sis_final_context(int context);
-
-#define DRIVER_CTX_CTOR sis_init_context
-#define DRIVER_CTX_DTOR sis_final_context
-
 #endif
index 3dd075d..f057343 100644 (file)
 #include "sis_drm.h"
 #include "sis_drv.h"
 
-#include "drm_auth.h"
-#include "drm_agpsupport.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
+#include "drm_core.h"
index 40e7f46..a870018 100644 (file)
@@ -31,8 +31,6 @@
 #include "sis_ds.h"
 
 typedef struct drm_sis_private {
-       drm_map_t *buffers;
-
        memHeap_t *AGPHeap;
        memHeap_t *FBHeap;
 } drm_sis_private_t;
index e2c4eca..7def6ad 100644 (file)
@@ -373,8 +373,7 @@ static int __init ds1620_init(void)
        th_start.hi = 1;
        ds1620_write_state(&th_start);
 
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout(2*HZ);
+       msleep(2000);
 
        ds1620_write_state(&th);
 
index b022aca..37d6649 100644 (file)
 #define DSP56K_TRANSMIT                (dsp56k_host_interface.isr & DSP56K_ISR_TXDE)
 #define DSP56K_RECEIVE         (dsp56k_host_interface.isr & DSP56K_ISR_RXDF)
 
-#define wait_some(n) \
-{ \
-       set_current_state(TASK_INTERRUPTIBLE); \
-       schedule_timeout(n); \
-}
-
 #define handshake(count, maxio, timeout, ENABLE, f) \
 { \
        long i, t, m; \
                m = min_t(unsigned long, count, maxio); \
                for (i = 0; i < m; i++) { \
                        for (t = 0; t < timeout && !ENABLE; t++) \
-                               wait_some(HZ/50); \
+                               msleep(20); \
                        if(!ENABLE) \
                                return -EIO; \
                        f; \
                } \
                count -= m; \
-               if (m == maxio) wait_some(HZ/50); \
+               if (m == maxio) msleep(20); \
        } \
 }
 
@@ -85,7 +79,7 @@
 { \
        int t; \
        for(t = 0; t < n && !DSP56K_TRANSMIT; t++) \
-               wait_some(HZ/100); \
+               msleep(10); \
        if(!DSP56K_TRANSMIT) { \
                return -EIO; \
        } \
@@ -95,7 +89,7 @@
 { \
        int t; \
        for(t = 0; t < n && !DSP56K_RECEIVE; t++) \
-               wait_some(HZ/100); \
+               msleep(10); \
        if(!DSP56K_RECEIVE) { \
                return -EIO; \
        } \
index 933282d..b3289d9 100644 (file)
@@ -412,7 +412,7 @@ static void ec3104_keyb_clear_state(void)
        k->last_msr = 0;
 
        for (;;) {
-               schedule_timeout(HZ/10);
+               msleep(100);
 
                msr = ctrl_inb(EC3104_SER4_MSR);
        
index 6d0b812..1845739 100644 (file)
@@ -155,7 +155,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        efi_time_t      eft;
        efi_time_cap_t  cap;
        struct rtc_time wtime;
-       struct rtc_wkalrm *ewp;
+       struct rtc_wkalrm __user *ewp;
        unsigned char   enabled, pending;
 
        switch (cmd) {
@@ -189,13 +189,15 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                        convert_from_efi_time(&eft, &wtime);
 
-                       return copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)) ? - EFAULT : 0;
+                       return copy_to_user((void __user *)arg, &wtime,
+                                           sizeof (struct rtc_time)) ? - EFAULT : 0;
 
                case RTC_SET_TIME:
 
                        if (!capable(CAP_SYS_TIME)) return -EACCES;
 
-                       if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) )
+                       if (copy_from_user(&wtime, (struct rtc_time __user *)arg,
+                                          sizeof(struct rtc_time)) )
                                return -EFAULT;
 
                        convert_to_efi_time(&wtime, &eft);
@@ -212,19 +214,19 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                        if (!capable(CAP_SYS_TIME)) return -EACCES;
 
-                       ewp = (struct rtc_wkalrm *)arg;
+                       ewp = (struct rtc_wkalrm __user *)arg;
 
                        if (  get_user(enabled, &ewp->enabled)
                           || copy_from_user(&wtime, &ewp->time, sizeof(struct rtc_time)) )
                                return -EFAULT;
 
                        convert_to_efi_time(&wtime, &eft);
-                       
+
                        spin_lock_irqsave(&efi_rtc_lock, flags);
                        /*
                         * XXX Fixme:
                         * As of EFI 0.92 with the firmware I have on my
-                        * machine this call does not seem to work quite 
+                        * machine this call does not seem to work quite
                         * right
                         */
                        status = efi.set_wakeup_time((efi_bool_t)enabled, &eft);
@@ -243,14 +245,15 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                        if (status != EFI_SUCCESS) return -EINVAL;
 
-                       ewp = (struct rtc_wkalrm *)arg;
+                       ewp = (struct rtc_wkalrm __user *)arg;
 
                        if (  put_user(enabled, &ewp->enabled)
                           || put_user(pending, &ewp->pending)) return -EFAULT;
 
                        convert_from_efi_time(&eft, &wtime);
 
-                       return copy_to_user((void *)&ewp->time, &wtime, sizeof(struct rtc_time)) ? -EFAULT : 0;
+                       return copy_to_user(&ewp->time, &wtime,
+                                           sizeof(struct rtc_time)) ? -EFAULT : 0;
        }
        return -EINVAL;
 }
index 854d16a..0f13bef 100644 (file)
@@ -74,7 +74,6 @@
 #define DIGIINFOMAJOR       35  /* For Digi specific ioctl */ 
 
 
-#define MIN(a,b)       ((a) < (b) ? (a) : (b))
 #define MAXCARDS 7
 #define epcaassert(x, msg)  if (!(x)) epca_error(__LINE__, msg)
 
@@ -551,9 +550,7 @@ static void pc_close(struct tty_struct * tty, struct file * filp)
                if (tty->driver->flush_buffer)
                        tty->driver->flush_buffer(tty);
 
-               if (tty->ldisc.flush_buffer)
-                       tty->ldisc.flush_buffer(tty);
-
+               tty_ldisc_flush(tty);
                shutdown(ch);
                tty->closing = 0;
                ch->event = 0;
@@ -657,10 +654,7 @@ static void pc_hangup(struct tty_struct *tty)
                cli();
                if (tty->driver->flush_buffer)
                        tty->driver->flush_buffer(tty);
-
-               if (tty->ldisc.flush_buffer)
-                       tty->ldisc.flush_buffer(tty);
-
+               tty_ldisc_flush(tty);
                shutdown(ch);
 
                ch->tty   = NULL;
@@ -826,7 +820,7 @@ static int pc_write(struct tty_struct * tty, int from_user,
                        bytesAvailable will then take on this newly calculated value.
                ---------------------------------------------------------------------- */
 
-               bytesAvailable = MIN(dataLen, bytesAvailable);
+               bytesAvailable = min(dataLen, bytesAvailable);
 
                /* First we read the data in from the file system into a temp buffer */
 
@@ -912,7 +906,7 @@ static int pc_write(struct tty_struct * tty, int from_user,
                        space; reduce the amount of data to fit the space.
        ---------------------------------------------------------------------- */
 
-       bytesAvailable = MIN(remain, bytesAvailable);
+       bytesAvailable = min(remain, bytesAvailable);
 
        txwinon(ch);
        while (bytesAvailable > 0) 
@@ -923,7 +917,7 @@ static int pc_write(struct tty_struct * tty, int from_user,
                        data copy fills to the end of card buffer.
                ------------------------------------------------------------------- */
 
-               dataLen = MIN(bytesAvailable, dataLen);
+               dataLen = min(bytesAvailable, dataLen);
                memcpy(ch->txptr + head, buf, dataLen);
                buf += dataLen;
                head += dataLen;
@@ -1120,8 +1114,7 @@ static void pc_flush_buffer(struct tty_struct *tty)
        restore_flags(flags);
 
        wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
 
 } /* End pc_flush_buffer */
 
@@ -2262,9 +2255,7 @@ static void doevent(int crd)
                                { /* Begin if LOWWAIT */
 
                                        ch->statusflags &= ~LOWWAIT;
-                                       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                                                 tty->ldisc.write_wakeup)
-                                               (tty->ldisc.write_wakeup)(tty);
+                                       tty_wakeup(tty);
                                        wake_up_interruptible(&tty->write_wait);
 
                                } /* End if LOWWAIT */
@@ -2281,9 +2272,7 @@ static void doevent(int crd)
                                { /* Begin if EMPTYWAIT */
 
                                        ch->statusflags &= ~EMPTYWAIT;
-                                       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                                                 tty->ldisc.write_wakeup)
-                                               (tty->ldisc.write_wakeup)(tty);
+                                       tty_wakeup(tty);
 
                                        wake_up_interruptible(&tty->write_wait);
 
@@ -3136,6 +3125,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                        }
                        else 
                        {
+                               /* ldisc lock already held in ioctl */
                                if (tty->ldisc.flush_buffer)
                                        tty->ldisc.flush_buffer(tty);
                        }
@@ -3307,7 +3297,6 @@ static void do_softint(void *private_)
                }
 
        } /* End EPCA_MAGIC */
-       MOD_DEC_USE_COUNT;
 } /* End do_softint */
 
 /* ------------------------------------------------------------
index 34f0e69..956b258 100644 (file)
 #include <asm/io.h>
 #if defined(__alpha__)
 # include <asm/hwrpb.h>
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__x86_64__)
+# include <asm/msr.h>
+# include <asm/timex.h>
+#elif defined(__i386__)
 # include <linux/timex.h>
 #endif
 #include <linux/ftape.h>
@@ -45,7 +48,7 @@
 # error Ftape is not implemented for this architecture!
 #endif
 
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
 static unsigned long ps_per_cycle = 0;
 #endif
 
@@ -72,7 +75,18 @@ unsigned int ftape_timestamp(void)
 
        asm volatile ("rpcc %0" : "=r" (r));
        return r;
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__x86_64__)
+       unsigned long r;
+       rdtscl(r);
+       return r;
+#elif defined(__i386__)
+
+/*
+ * Note that there is some time between counter underflowing and jiffies
+ * increasing, so the code below won't always give correct output.
+ * -Vojtech
+ */
+
        unsigned long flags;
        __u16 lo;
        __u16 hi;
@@ -89,9 +103,9 @@ unsigned int ftape_timestamp(void)
 
 static unsigned int short_ftape_timestamp(void)
 {
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
        return ftape_timestamp();
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
        unsigned int count;
        unsigned long flags;
  
@@ -106,9 +120,9 @@ static unsigned int short_ftape_timestamp(void)
 
 static unsigned int diff(unsigned int t0, unsigned int t1)
 {
-#if defined(__alpha__)
-       return (t1 <= t0) ? t1 + (1UL << 32) - t0 : t1 - t0;
-#elif defined(__i386__) || defined(__x86_64__)
+#if defined(__alpha__) || defined(__x86_64__)
+       return (t1 - t0);
+#elif defined(__i386__)
        /*
         * This is tricky: to work for both short and full ftape_timestamps
         * we'll have to discriminate between these.
@@ -122,9 +136,9 @@ static unsigned int diff(unsigned int t0, unsigned int t1)
 
 static unsigned int usecs(unsigned int count)
 {
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
        return (ps_per_cycle * count) / 1000000UL;
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
        return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100);
 #endif
 }
@@ -163,38 +177,13 @@ static void time_inb(void)
 
 static void init_clock(void)
 {
-#if defined(__i386__) || defined(__x86_64__)
-       unsigned int t;
-       int i;
        TRACE_FUN(ft_t_any);
 
-       /*  Haven't studied on why, but there sometimes is a problem
-        *  with the tick timer readout. The two bytes get swapped.
-        *  This hack solves that problem by doing one extra input.
-        */
-       for (i = 0; i < 1000; ++i) {
-               t = short_ftape_timestamp();
-               if (t > LATCH) {
-                       inb_p(0x40);    /* get in sync again */
-                       TRACE(ft_t_warn, "clock counter fixed");
-                       break;
-               }
-       }
+#if defined(__x86_64__)
+       ps_per_cycle = 1000000000UL / cpu_khz;
 #elif defined(__alpha__)
-#if CONFIG_FT_ALPHA_CLOCK == 0
-#error You must define and set CONFIG_FT_ALPHA_CLOCK in 'make config' !
-#endif
        extern struct hwrpb_struct *hwrpb;
-       TRACE_FUN(ft_t_any);
-
-       if (hwrpb->cycle_freq != 0) {
-               ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
-       } else {
-               /*
-                * HELP:  Linux 2.0.x doesn't set cycle_freq on my noname !
-                */
-               ps_per_cycle = (1000*1000*1000*1000UL) / CONFIG_FT_ALPHA_CLOCK;
-       }
+       ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
 #endif
        TRACE_EXIT;
 }
@@ -213,7 +202,7 @@ void ftape_calibrate(char *name,
        unsigned int tc = 0;
        unsigned int count;
        unsigned int time;
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__)
        unsigned int old_tc = 0;
        unsigned int old_count = 1;
        unsigned int old_time = 1;
@@ -255,7 +244,7 @@ void ftape_calibrate(char *name,
                tc = (1000 * time) / (count - 1);
                TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns",
                        usecs(once), count - 1, usecs(multiple), tc);
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
                /*
                 * Increase the calibration count exponentially until the
                 * calibration time exceeds 100 ms.
@@ -263,7 +252,7 @@ void ftape_calibrate(char *name,
                if (time >= 100*1000) {
                        break;
                }
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
                /*
                 * increase the count until the resulting time nears 2/HZ,
                 * then the tc will drop sharply because we lose LATCH counts.
index 1027eb7..45bc1be 100644 (file)
@@ -436,9 +436,7 @@ void gs_flush_buffer(struct tty_struct *tty)
        restore_flags(flags);
 
        wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
        func_exit ();
 }
 
@@ -578,9 +576,7 @@ void gs_do_softint(void *private_)
        if (!tty) return;
 
        if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   tty->ldisc.write_wakeup)
-                       (tty->ldisc.write_wakeup)(tty);
+               tty_wakeup(tty);
                wake_up_interruptible(&tty->write_wait);
        }
        func_exit ();
@@ -694,7 +690,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
 {
        unsigned long flags;
        struct gs_port *port;
-
+       
        func_enter ();
 
        if (!tty) return;
@@ -760,8 +756,8 @@ void gs_close(struct tty_struct * tty, struct file * filp)
 
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+               
+       tty_ldisc_flush(tty);
        tty->closing = 0;
 
        port->event = 0;
index 5e8c472..22d46cd 100644 (file)
@@ -60,8 +60,8 @@ static spinlock_t hpet_task_lock = SPIN_LOCK_UNLOCKED;
 
 struct hpet_dev {
        struct hpets *hd_hpets;
-       struct hpet *hd_hpet;
-       struct hpet_timer *hd_timer;
+       struct hpet __iomem *hd_hpet;
+       struct hpet_timer __iomem *hd_timer;
        unsigned long hd_ireqfreq;
        unsigned long hd_irqdata;
        wait_queue_head_t hd_waitqueue;
@@ -75,7 +75,7 @@ struct hpet_dev {
 
 struct hpets {
        struct hpets *hp_next;
-       struct hpet *hp_hpet;
+       struct hpet __iomem *hp_hpet;
        unsigned long hp_period;
        unsigned long hp_delta;
        unsigned int hp_ntimer;
@@ -98,14 +98,14 @@ static struct hpets *hpets;
 #endif
 
 #ifndef readq
-static unsigned long long __inline readq(void *addr)
+static unsigned long long __inline readq(void __iomem *addr)
 {
        return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL);
 }
 #endif
 
 #ifndef writeq
-static void __inline writeq(unsigned long long v, void *addr)
+static void __inline writeq(unsigned long long v, void __iomem *addr)
 {
        writel(v & 0xffffffff, addr);
        writel(v >> 32, addr + 4);
@@ -300,7 +300,7 @@ static int hpet_fasync(int fd, struct file *file, int on)
 static int hpet_release(struct inode *inode, struct file *file)
 {
        struct hpet_dev *devp;
-       struct hpet_timer *timer;
+       struct hpet_timer __iomem *timer;
        int irq = 0;
 
        devp = file->private_data;
@@ -352,8 +352,8 @@ hpet_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 static int hpet_ioctl_ieon(struct hpet_dev *devp)
 {
-       struct hpet_timer *timer;
-       struct hpet *hpet;
+       struct hpet_timer __iomem *timer;
+       struct hpet __iomem *hpet;
        struct hpets *hpetp;
        int irq;
        unsigned long g, v, t, m;
@@ -435,8 +435,8 @@ static inline unsigned long hpet_time_div(unsigned long dis)
 static int
 hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
 {
-       struct hpet_timer *timer;
-       struct hpet *hpet;
+       struct hpet_timer __iomem *timer;
+       struct hpet __iomem *hpet;
        struct hpets *hpetp;
        int err;
        unsigned long v;
@@ -547,7 +547,7 @@ int hpet_register(struct hpet_task *tp, int periodic)
 {
        unsigned int i;
        u64 mask;
-       struct hpet_timer *timer;
+       struct hpet_timer __iomem *timer;
        struct hpet_dev *devp;
        struct hpets *hpetp;
 
@@ -615,7 +615,7 @@ static inline int hpet_tpcheck(struct hpet_task *tp)
 int hpet_unregister(struct hpet_task *tp)
 {
        struct hpet_dev *devp;
-       struct hpet_timer *timer;
+       struct hpet_timer __iomem *timer;
        int err;
 
        if ((err = hpet_tpcheck(tp)))
@@ -662,40 +662,9 @@ int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
 
 #ifdef CONFIG_TIME_INTERPOLATION
 
-static unsigned long hpet_offset, last_wall_hpet;
-static long hpet_nsecs_per_cycle, hpet_cycles_per_sec;
-
-static unsigned long hpet_getoffset(void)
-{
-       return hpet_offset + (read_counter(&hpets->hp_hpet->hpet_mc) -
-                             last_wall_hpet) * hpet_nsecs_per_cycle;
-}
-
-static void hpet_update(long delta)
-{
-       unsigned long mc;
-       unsigned long offset;
-
-       mc = read_counter(&hpets->hp_hpet->hpet_mc);
-       offset = hpet_offset + (mc - last_wall_hpet) * hpet_nsecs_per_cycle;
-
-       if (delta < 0 || (unsigned long)delta < offset)
-               hpet_offset = offset - delta;
-       else
-               hpet_offset = 0;
-       last_wall_hpet = mc;
-}
-
-static void hpet_reset(void)
-{
-       hpet_offset = 0;
-       last_wall_hpet = read_counter(&hpets->hp_hpet->hpet_mc);
-}
-
 static struct time_interpolator hpet_interpolator = {
-       .get_offset = hpet_getoffset,
-       .update = hpet_update,
-       .reset = hpet_reset
+       .source = TIME_SOURCE_MMIO64,
+       .shift = 10
 };
 
 #endif
@@ -745,11 +714,11 @@ static struct ctl_table_header *sysctl_header;
 
 static unsigned long __init hpet_calibrate(struct hpets *hpetp)
 {
-       struct hpet_timer *timer = NULL;
+       struct hpet_timer __iomem *timer = NULL;
        unsigned long t, m, count, i, flags, start;
        struct hpet_dev *devp;
        int j;
-       struct hpet *hpet;
+       struct hpet __iomem *hpet;
 
        for (j = 0, devp = hpetp->hp_dev; j < hpetp->hp_ntimer; j++, devp++)
                if ((devp->hd_flags & HPET_OPEN) == 0) {
@@ -787,8 +756,9 @@ int __init hpet_alloc(struct hpet_data *hdp)
        u32 i, ntimer;
        struct hpets *hpetp;
        size_t siz;
-       struct hpet *hpet;
+       struct hpet __iomem *hpet;
        static struct hpets *last __initdata = (struct hpets *)0;
+       unsigned long ns;
 
        /*
         * hpet_alloc can be called by platform dependent code.
@@ -796,7 +766,7 @@ int __init hpet_alloc(struct hpet_data *hdp)
         * ACPI also reports hpet, then we catch it here.
         */
        for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
-               if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address))
+               if (hpetp->hp_hpet == hdp->hd_address)
                        return 0;
 
        siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
@@ -810,7 +780,7 @@ int __init hpet_alloc(struct hpet_data *hdp)
        memset(hpetp, 0, siz);
 
        hpetp->hp_which = hpet_nhpet++;
-       hpetp->hp_hpet = (struct hpet *)hdp->hd_address;
+       hpetp->hp_hpet = hdp->hd_address;
 
        hpetp->hp_ntimer = hdp->hd_nirqs;
 
@@ -840,6 +810,18 @@ int __init hpet_alloc(struct hpet_data *hdp)
        hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
            HPET_COUNTER_CLK_PERIOD_SHIFT;
 
+       printk(KERN_INFO "hpet%d: at MMIO 0x%p, IRQ%s",
+               hpetp->hp_which, hpet, hpetp->hp_ntimer > 1 ? "s" : "");
+       for (i = 0; i < hpetp->hp_ntimer; i++)
+               printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
+       printk("\n");
+
+       ns = hpetp->hp_period;  /* femptoseconds, 10^-15 */
+       do_div(ns, 1000000);    /* convert to nanoseconds, 10^-9 */
+       printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n",
+               hpetp->hp_which, ns, hpetp->hp_ntimer,
+               cap & HPET_COUNTER_SIZE_MASK ? 64 : 32);
+
        mcfg = readq(&hpet->hpet_config);
        if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
                write_counter(0L, &hpet->hpet_mc);
@@ -850,7 +832,7 @@ int __init hpet_alloc(struct hpet_data *hdp)
        for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer;
             i++, hpet_ntimer++, devp++) {
                unsigned long v;
-               struct hpet_timer *timer;
+               struct hpet_timer __iomem *timer;
 
                timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
                v = readq(&timer->hpet_config);
@@ -891,11 +873,10 @@ static acpi_status __init hpet_resources(struct acpi_resource *res, void *data)
                unsigned long size;
 
                size = addr.max_address_range - addr.min_address_range + 1;
-               hdp->hd_address =
-                   (unsigned long)ioremap(addr.min_address_range, size);
+               hdp->hd_address = ioremap(addr.min_address_range, size);
 
                for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
-                       if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address))
+                       if (hpetp->hp_hpet == hdp->hd_address)
                                return -EBUSY;
        } else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
                struct acpi_resource_ext_irq *irqp;
@@ -944,9 +925,8 @@ static int __init hpet_acpi_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static struct acpi_driver hpet_acpi_driver __initdata = {
+static struct acpi_driver hpet_acpi_driver = {
        .name = "hpet",
-       .class = "",
        .ids = "PNP0103",
        .ops = {
                .add = hpet_acpi_add,
@@ -971,11 +951,10 @@ static int __init hpet_init(void)
                        struct hpet *hpet;
 
                        hpet = hpets->hp_hpet;
-                       hpet_cycles_per_sec = hpet_time_div(hpets->hp_period);
-                       hpet_interpolator.frequency = hpet_cycles_per_sec;
-                       hpet_interpolator.drift = hpet_cycles_per_sec *
+                       hpet_interpolator.addr = &hpets->hp_hpet->hpet_mc;
+                       hpet_interpolator.frequency = hpet_time_div(hpets->hp_period);
+                       hpet_interpolator.drift = hpet_interpolator.frequency *
                            HPET_DRIFT / 1000000;
-                       hpet_nsecs_per_cycle = 1000000000 / hpet_cycles_per_sec;
                        register_time_interpolator(&hpet_interpolator);
                }
 #endif
index d4bf205..3c0af2c 100644 (file)
@@ -1,6 +1,11 @@
 /*
  * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
  * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM
+ * Copyright (C) 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Additional Author(s):
+ *  Ryan S. Arnold <rsa@us.ibm.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
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/console.h>
+#include <linux/cpumask.h>
 #include <linux/init.h>
+#include <linux/kbd_kern.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
 #include <linux/module.h>
-#include <linux/console.h>
 #include <linux/major.h>
-#include <linux/kernel.h>
 #include <linux/sysrq.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/sched.h>
-#include <linux/kbd_kern.h>
-#include <asm/uaccess.h>
 #include <linux/spinlock.h>
-#include <linux/cpumask.h>
-
-extern int hvc_count(int *);
-extern int hvc_get_chars(int index, char *buf, int count);
-extern int hvc_put_chars(int index, const char *buf, int count);
+#include <asm/uaccess.h>
+#include <asm/hvconsole.h>
+#include <asm/vio.h>
 
 #define HVC_MAJOR      229
 #define HVC_MINOR      0
 
-#define MAX_NR_HVC_CONSOLES    4
-
 #define TIMEOUT                ((HZ + 99) / 100)
 
+/*
+ * Wait this long per iteration while trying to push buffered data to the
+ * hypervisor before allowing the tty to complete a close operation.
+ */
+#define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
+
+/*
+ * The Linux TTY code does not support dynamic addition of tty derived devices
+ * so we need to know how many tty devices we might need when space is allocated
+ * for the tty device.  Since this driver supports hotplug of vty adapters we
+ * need to make sure we have enough allocated.
+ */
+#define HVC_ALLOC_TTY_ADAPTERS 8
+
 static struct tty_driver *hvc_driver;
-static int hvc_offset;
 #ifdef CONFIG_MAGIC_SYSRQ
 static int sysrq_pressed;
 #endif
 
 #define N_OUTBUF       16
+#define N_INBUF                16
 
 #define __ALIGNED__    __attribute__((__aligned__(8)))
 
@@ -60,59 +78,249 @@ struct hvc_struct {
        int do_wakeup;
        char outbuf[N_OUTBUF] __ALIGNED__;
        int n_outbuf;
+       uint32_t vtermno;
+       int irq_requested;
+       int irq;
+       struct list_head next;
+       struct kobject kobj; /* ref count & hvc_struct lifetime */
+       struct vio_dev *vdev;
 };
 
-struct hvc_struct hvc_struct[MAX_NR_HVC_CONSOLES];
+/* dynamic list of hvc_struct instances */
+static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs);
+
+/*
+ * Protect the list of hvc_struct instances from inserts and removals during
+ * list traversal.
+ */
+static spinlock_t hvc_structs_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Initial console vtermnos for console API usage prior to full console
+ * initialization.  Any vty adapter outside this range will not have usable
+ * console interfaces but can still be used as a tty device.  This has to be
+ * static because kmalloc will not work during early console init.
+ */
+static uint32_t vtermnos[MAX_NR_HVC_CONSOLES];
+
+/* Used for accounting purposes */
+static int num_vterms = 0;
+
+static struct task_struct *hvc_task;
+
+/*
+ * This value is used to associate a tty->index value to a hvc_struct based
+ * upon order of exposure via hvc_probe().
+ */
+static int hvc_count = -1;
+
+/* Picks up late kicks after list walk but before schedule() */
+static int hvc_kicked;
+
+/* Wake the sleeping khvcd */
+static void hvc_kick(void)
+{
+       hvc_kicked = 1;
+       wake_up_process(hvc_task);
+}
+
+/*
+ * NOTE: This API isn't used if the console adapter doesn't support interrupts.
+ * In this case the console is poll driven.
+ */
+static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+       hvc_kick();
+       return IRQ_HANDLED;
+}
+
+static void hvc_unthrottle(struct tty_struct *tty)
+{
+       hvc_kick();
+}
+
+/*
+ * Do not call this function with either the hvc_strucst_lock or the hvc_struct
+ * lock held.  If successful, this function increments the kobject reference
+ * count against the target hvc_struct so it should be released when finished.
+ */
+struct hvc_struct *hvc_get_by_index(int index)
+{
+       struct hvc_struct *hp;
+       unsigned long flags;
+
+       spin_lock(&hvc_structs_lock);
 
+       list_for_each_entry(hp, &hvc_structs, next) {
+               spin_lock_irqsave(&hp->lock, flags);
+               if (hp->index == index) {
+                       kobject_get(&hp->kobj);
+                       spin_unlock_irqrestore(&hp->lock, flags);
+                       spin_unlock(&hvc_structs_lock);
+                       return hp;
+               }
+               spin_unlock_irqrestore(&hp->lock, flags);
+       }
+       hp = NULL;
+
+       spin_unlock(&hvc_structs_lock);
+       return hp;
+}
+
+/*
+ * The TTY interface won't be used until after the vio layer has exposed the vty
+ * adapter to the kernel.
+ */
 static int hvc_open(struct tty_struct *tty, struct file * filp)
 {
-       int line = tty->index;
        struct hvc_struct *hp;
        unsigned long flags;
+       int irq = NO_IRQ;
+       int rc = 0;
+       struct kobject *kobjp;
 
-       if (line < 0 || line >= MAX_NR_HVC_CONSOLES)
+       /* Auto increments kobject reference if found. */
+       if (!(hp = hvc_get_by_index(tty->index))) {
+               printk(KERN_WARNING "hvc_console: tty open failed, no vty associated with tty.\n");
                return -ENODEV;
-       hp = &hvc_struct[line];
+       }
 
-       tty->driver_data = hp;
        spin_lock_irqsave(&hp->lock, flags);
+       /* Check and then increment for fast path open. */
+       if (hp->count++ > 0) {
+               spin_unlock_irqrestore(&hp->lock, flags);
+               hvc_kick();
+               return 0;
+       } /* else count == 0 */
+
+       tty->driver_data = hp;
        hp->tty = tty;
-       hp->count++;
+       /* Save for request_irq outside of spin_lock. */
+       irq = hp->irq;
+       if (irq != NO_IRQ)
+               hp->irq_requested = 1;
+
+       kobjp = &hp->kobj;
+
        spin_unlock_irqrestore(&hp->lock, flags);
+       /* check error, fallback to non-irq */
+       if (irq != NO_IRQ)
+               rc = request_irq(irq, hvc_handle_interrupt, SA_INTERRUPT, "hvc_console", hp);
+
+       /*
+        * If the request_irq() fails and we return an error.  The tty layer
+        * will call hvc_close() after a failed open but we don't want to clean
+        * up there so we'll clean up here and clear out the previously set
+        * tty fields and return the kobject reference.
+        */
+       if (rc) {
+               spin_lock_irqsave(&hp->lock, flags);
+               hp->tty = NULL;
+               hp->irq_requested = 0;
+               spin_unlock_irqrestore(&hp->lock, flags);
+               tty->driver_data = NULL;
+               kobject_put(kobjp);
+       }
+       /* Force wakeup of the polling thread */
+       hvc_kick();
 
-       return 0;
+       return rc;
 }
 
 static void hvc_close(struct tty_struct *tty, struct file * filp)
 {
-       struct hvc_struct *hp = tty->driver_data;
+       struct hvc_struct *hp;
+       struct kobject *kobjp;
+       int irq = NO_IRQ;
        unsigned long flags;
 
        if (tty_hung_up_p(filp))
                return;
+
+       /*
+        * No driver_data means that this close was issued after a failed
+        * hvcs_open by the tty layer's release_dev() function and we can just
+        * exit cleanly because the kobject reference wasn't made.
+        */
+       if (!tty->driver_data)
+               return;
+
+       hp = tty->driver_data;
        spin_lock_irqsave(&hp->lock, flags);
-       if (--hp->count == 0)
+
+       kobjp = &hp->kobj;
+       if (--hp->count == 0) {
+               if (hp->irq_requested)
+                       irq = hp->irq;
+               hp->irq_requested = 0;
+
+               /* We are done with the tty pointer now. */
                hp->tty = NULL;
-       else if (hp->count < 0)
-               printk(KERN_ERR "hvc_close %lu: oops, count is %d\n",
-                      hp - hvc_struct, hp->count);
-       spin_unlock_irqrestore(&hp->lock, flags);
+               spin_unlock_irqrestore(&hp->lock, flags);
+
+               /*
+                * Chain calls chars_in_buffer() and returns immediately if
+                * there is no buffered data otherwise sleeps on a wait queue
+                * waking periodically to check chars_in_buffer().
+                */
+               tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
+
+               /*
+                * Since the line disc doesn't block writes during tty close
+                * operations we'll set driver_data to NULL and then make sure
+                * to check tty->driver_data for NULL in hvc_write().
+                */
+               tty->driver_data = NULL;
+
+               if (irq != NO_IRQ)
+                       free_irq(irq, hp);
+
+       } else {
+               if (hp->count < 0)
+                       printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
+                               hp->vtermno, hp->count);
+               spin_unlock_irqrestore(&hp->lock, flags);
+       }
+
+       kobject_put(kobjp);
 }
 
 static void hvc_hangup(struct tty_struct *tty)
 {
        struct hvc_struct *hp = tty->driver_data;
+       unsigned long flags;
+       int irq = NO_IRQ;
+       int temp_open_count;
+       struct kobject *kobjp;
 
+       spin_lock_irqsave(&hp->lock, flags);
+       kobjp = &hp->kobj;
+       temp_open_count = hp->count;
        hp->count = 0;
+       hp->n_outbuf = 0;
        hp->tty = NULL;
+       if (hp->irq_requested)
+               /* Saved for use outside of spin_lock. */
+               irq = hp->irq;
+       hp->irq_requested = 0;
+       spin_unlock_irqrestore(&hp->lock, flags);
+       if (irq != NO_IRQ)
+               free_irq(irq, hp);
+       while(temp_open_count) {
+               --temp_open_count;
+               kobject_put(kobjp);
+       }
 }
 
-/* called with hp->lock held */
+/*
+ * Push buffered characters whether they were just recently buffered or waiting
+ * on a blocked hypervisor.  Call this function with hp->lock held.
+ */
 static void hvc_push(struct hvc_struct *hp)
 {
        int n;
 
-       n = hvc_put_chars(hp->index + hvc_offset, hp->outbuf, hp->n_outbuf);
+       n = hvc_put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
        if (n <= 0) {
                if (n == 0)
                        return;
@@ -127,77 +335,126 @@ static void hvc_push(struct hvc_struct *hp)
                hp->do_wakeup = 1;
 }
 
-static int hvc_write(struct tty_struct *tty, int from_user,
-                    const unsigned char *buf, int count)
+static inline int __hvc_write_user(struct hvc_struct *hp,
+                                  const unsigned char *buf, int count)
 {
-       struct hvc_struct *hp = tty->driver_data;
        char *tbuf, *p;
        int tbsize, rsize, written = 0;
        unsigned long flags;
 
-       if (from_user) {
-               tbsize = min(count, (int)PAGE_SIZE);
-               if (!(tbuf = kmalloc(tbsize, GFP_KERNEL)))
-                       return -ENOMEM;
-
-               while ((rsize = count - written) > 0) {
-                       int wsize;
-                       if (rsize > tbsize)
-                               rsize = tbsize;
-
-                       p = tbuf;
-                       rsize -= copy_from_user(p, buf, rsize);
-                       if (!rsize) {
-                               if (written == 0)
-                                       written = -EFAULT;
-                               break;
-                       }
-                       buf += rsize;
-                       written += rsize;
-
-                       spin_lock_irqsave(&hp->lock, flags);
-                       for (wsize = N_OUTBUF - hp->n_outbuf; rsize && wsize;
-                                       wsize = N_OUTBUF - hp->n_outbuf) {
-                               if (wsize > rsize)
-                                       wsize = rsize;
-                               memcpy(hp->outbuf + hp->n_outbuf, p, wsize);
-                               hp->n_outbuf += wsize;
-                               hvc_push(hp);
-                               rsize -= wsize;
-                               p += wsize;
-                       }
-                       spin_unlock_irqrestore(&hp->lock, flags);
-
-                       if (rsize)
-                               break;
+       tbsize = min(count, (int)PAGE_SIZE);
+       if (!(tbuf = kmalloc(tbsize, GFP_KERNEL)))
+               return -ENOMEM;
 
-                       if (count < tbsize)
-                               tbsize = count;
+       while ((rsize = count - written) > 0) {
+               int wsize;
+               if (rsize > tbsize)
+                       rsize = tbsize;
+
+               p = tbuf;
+               rsize -= copy_from_user(p, buf, rsize);
+               if (!rsize) {
+                       if (written == 0)
+                               written = -EFAULT;
+                       break;
                }
+               buf += rsize;
 
-               kfree(tbuf);
-       } else {
                spin_lock_irqsave(&hp->lock, flags);
-               while (count > 0 && (rsize = N_OUTBUF - hp->n_outbuf) > 0) {
-                       if (rsize > count)
-                               rsize = count;
-                       memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
-                       count -= rsize;
-                       buf += rsize;
-                       hp->n_outbuf += rsize;
-                       written += rsize;
+
+               /* Push pending writes: make some room in buffer */
+               if (hp->n_outbuf > 0)
                        hvc_push(hp);
+
+               for (wsize = N_OUTBUF - hp->n_outbuf; rsize && wsize;
+                    wsize = N_OUTBUF - hp->n_outbuf) {
+                       if (wsize > rsize)
+                               wsize = rsize;
+                       memcpy(hp->outbuf + hp->n_outbuf, p, wsize);
+                       hp->n_outbuf += wsize;
+                       hvc_push(hp);
+                       rsize -= wsize;
+                       p += wsize;
+                       written += wsize;
                }
                spin_unlock_irqrestore(&hp->lock, flags);
+
+               if (rsize)
+                       break;
+
+               if (count < tbsize)
+                       tbsize = count;
+       }
+
+       kfree(tbuf);
+
+       return written;
+}
+
+static inline int __hvc_write_kernel(struct hvc_struct *hp,
+                                  const unsigned char *buf, int count)
+{
+       unsigned long flags;
+       int rsize, written = 0;
+
+       spin_lock_irqsave(&hp->lock, flags);
+
+       /* Push pending writes */
+       if (hp->n_outbuf > 0)
+               hvc_push(hp);
+
+       while (count > 0 && (rsize = N_OUTBUF - hp->n_outbuf) > 0) {
+               if (rsize > count)
+                       rsize = count;
+               memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
+               count -= rsize;
+               buf += rsize;
+               hp->n_outbuf += rsize;
+               written += rsize;
+               hvc_push(hp);
        }
+       spin_unlock_irqrestore(&hp->lock, flags);
+
+       return written;
+}
+static int hvc_write(struct tty_struct *tty, int from_user,
+                    const unsigned char *buf, int count)
+{
+       struct hvc_struct *hp = tty->driver_data;
+       int written;
+
+       /* This write was probably executed during a tty close. */
+       if (!hp)
+               return -EPIPE;
+
+       if (from_user)
+               written = __hvc_write_user(hp, buf, count);
+       else
+               written = __hvc_write_kernel(hp, buf, count);
+
+       /*
+        * Racy, but harmless, kick thread if there is still pending data.
+        * There really is nothing wrong with kicking the thread, even if there
+        * is no buffered data.
+        */
+       if (hp->n_outbuf)
+               hvc_kick();
 
        return written;
 }
 
+/*
+ * This is actually a contract between the driver and the tty layer outlining
+ * how much write room the driver can guarentee will be sent OR BUFFERED.  This
+ * driver MUST honor the return value.
+ */
 static int hvc_write_room(struct tty_struct *tty)
 {
        struct hvc_struct *hp = tty->driver_data;
 
+       if (!hp)
+               return -1;
+
        return N_OUTBUF - hp->n_outbuf;
 }
 
@@ -205,57 +462,108 @@ static int hvc_chars_in_buffer(struct tty_struct *tty)
 {
        struct hvc_struct *hp = tty->driver_data;
 
+       if (!hp)
+               return -1;
        return hp->n_outbuf;
 }
 
-static void hvc_poll(int index)
+#define HVC_POLL_READ  0x00000001
+#define HVC_POLL_WRITE 0x00000002
+#define HVC_POLL_QUICK 0x00000004
+
+static int hvc_poll(struct hvc_struct *hp)
 {
-       struct hvc_struct *hp = &hvc_struct[index];
        struct tty_struct *tty;
-       int i, n;
-       char buf[16] __ALIGNED__;
+       int i, n, poll_mask = 0;
+       char buf[N_INBUF] __ALIGNED__;
        unsigned long flags;
+       int read_total = 0;
 
        spin_lock_irqsave(&hp->lock, flags);
 
+       /* Push pending writes */
        if (hp->n_outbuf > 0)
                hvc_push(hp);
+       /* Reschedule us if still some write pending */
+       if (hp->n_outbuf > 0)
+               poll_mask |= HVC_POLL_WRITE;
 
+       /* No tty attached, just skip */
        tty = hp->tty;
-       if (tty) {
-               for (;;) {
-                       if (TTY_FLIPBUF_SIZE - tty->flip.count < sizeof(buf))
-                               break;
-                       n = hvc_get_chars(index + hvc_offset, buf, sizeof(buf));
-                       if (n <= 0)
-                               break;
-                       for (i = 0; i < n; ++i) {
-#ifdef CONFIG_MAGIC_SYSRQ              /* Handle the SysRq Hack */
-                               if (buf[i] == '\x0f') { /* ^O -- should support a sequence */
-                                       sysrq_pressed = 1;
-                                       continue;
-                               } else if (sysrq_pressed) {
-                                       handle_sysrq(buf[i], NULL, tty);
-                                       sysrq_pressed = 0;
-                                       continue;
-                               }
-#endif
-                               tty_insert_flip_char(tty, buf[i], 0);
+       if (tty == NULL)
+               goto bail;
+
+       /* Now check if we can get data (are we throttled ?) */
+       if (test_bit(TTY_THROTTLED, &tty->flags))
+               goto throttled;
+
+       /* If we aren't interrupt driven and aren't throttled, we always
+        * request a reschedule
+        */
+       if (hp->irq == NO_IRQ)
+               poll_mask |= HVC_POLL_READ;
+
+       /* Read data if any */
+       for (;;) {
+               int count = N_INBUF;
+               if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
+                       count = TTY_FLIPBUF_SIZE - tty->flip.count;
+
+               /* If flip is full, just reschedule a later read */
+               if (count == 0) {
+                       poll_mask |= HVC_POLL_READ;
+                       break;
+               }
+
+               n = hvc_get_chars(hp->vtermno, buf, count);
+               if (n <= 0) {
+                       /* Hangup the tty when disconnected from host */
+                       if (n == -EPIPE) {
+                               spin_unlock_irqrestore(&hp->lock, flags);
+                               tty_hangup(tty);
+                               spin_lock_irqsave(&hp->lock, flags);
                        }
+                       break;
                }
+               for (i = 0; i < n; ++i) {
+#ifdef CONFIG_MAGIC_SYSRQ
+                       /* Handle the SysRq Hack */
+                       if (buf[i] == '\x0f') { /* ^O -- should support a sequence */
+                               sysrq_pressed = 1;
+                               continue;
+                       } else if (sysrq_pressed) {
+                               handle_sysrq(buf[i], NULL, tty);
+                               sysrq_pressed = 0;
+                               continue;
+                       }
+#endif /* CONFIG_MAGIC_SYSRQ */
+                       tty_insert_flip_char(tty, buf[i], 0);
+               }
+
                if (tty->flip.count)
                        tty_schedule_flip(tty);
 
-               if (hp->do_wakeup) {
-                       hp->do_wakeup = 0;
-                       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-                           && tty->ldisc.write_wakeup)
-                               (tty->ldisc.write_wakeup)(tty);
-                       wake_up_interruptible(&tty->write_wait);
+               /*
+                * Account for the total amount read in one loop, and if above
+                * 64 bytes, we do a quick schedule loop to let the tty grok the
+                * data and eventually throttle us.
+                */
+               read_total += n;
+               if (read_total >= 64) {
+                       poll_mask |= HVC_POLL_QUICK;
+                       break;
                }
        }
-
+ throttled:
+       /* Wakeup write queue if necessary */
+       if (hp->do_wakeup) {
+               hp->do_wakeup = 0;
+               tty_wakeup(tty);
+       }
+ bail:
        spin_unlock_irqrestore(&hp->lock, flags);
+
+       return poll_mask;
 }
 
 #if defined(CONFIG_XMON) && defined(CONFIG_SMP)
@@ -264,21 +572,47 @@ extern cpumask_t cpus_in_xmon;
 static const cpumask_t cpus_in_xmon = CPU_MASK_NONE;
 #endif
 
-
+/*
+ * This kthread is either polling or interrupt driven.  This is determined by
+ * calling hvc_poll() who determines whether a console adapter support
+ * interrupts.
+ */
 int khvcd(void *unused)
 {
-       int i;
-
-       daemonize("khvcd");
+       int poll_mask;
+       struct hvc_struct *hp;
 
-       for (;;) {
+       __set_current_state(TASK_RUNNING);
+       do {
+               poll_mask = 0;
+               hvc_kicked = 0;
+               wmb();
                if (cpus_empty(cpus_in_xmon)) {
-                       for (i = 0; i < MAX_NR_HVC_CONSOLES; ++i)
-                               hvc_poll(i);
+                       spin_lock(&hvc_structs_lock);
+                       list_for_each_entry(hp, &hvc_structs, next) {
+                               /*hp = list_entry(node, struct hvc_struct, * next); */
+                               poll_mask |= hvc_poll(hp);
+                       }
+                       spin_unlock(&hvc_structs_lock);
+               } else
+                       poll_mask |= HVC_POLL_READ;
+               if (hvc_kicked)
+                       continue;
+               if (poll_mask & HVC_POLL_QUICK) {
+                       yield();
+                       continue;
                }
                set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(TIMEOUT);
-       }
+               if (!hvc_kicked) {
+                       if (poll_mask == 0)
+                               schedule();
+                       else
+                               schedule_timeout(TIMEOUT);
+               }
+               __set_current_state(TASK_RUNNING);
+       } while (!kthread_should_stop());
+
+       return 0;
 }
 
 static struct tty_operations hvc_ops = {
@@ -286,19 +620,124 @@ static struct tty_operations hvc_ops = {
        .close = hvc_close,
        .write = hvc_write,
        .hangup = hvc_hangup,
+       .unthrottle = hvc_unthrottle,
        .write_room = hvc_write_room,
        .chars_in_buffer = hvc_chars_in_buffer,
 };
 
-int __init hvc_init(void)
+char hvc_driver_name[] = "hvc_console";
+
+static struct vio_device_id hvc_driver_table[] __devinitdata= {
+       {"serial", "hvterm1"},
+       { 0, }
+};
+MODULE_DEVICE_TABLE(vio, hvc_driver_table);
+
+/* callback when the kboject ref count reaches zero. */
+static void destroy_hvc_struct(struct kobject *kobj)
 {
-       int num = hvc_count(&hvc_offset);
-       int i;
+       struct hvc_struct *hp = container_of(kobj, struct hvc_struct, kobj);
+       unsigned long flags;
 
-       if (num > MAX_NR_HVC_CONSOLES)
-               num = MAX_NR_HVC_CONSOLES;
+       spin_lock(&hvc_structs_lock);
 
-       hvc_driver = alloc_tty_driver(num);
+       spin_lock_irqsave(&hp->lock, flags);
+       list_del(&(hp->next));
+       spin_unlock_irqrestore(&hp->lock, flags);
+
+       spin_unlock(&hvc_structs_lock);
+
+       kfree(hp);
+}
+
+static struct kobj_type hvc_kobj_type = {
+       .release = destroy_hvc_struct,
+};
+
+static int __devinit hvc_probe(
+               struct vio_dev *dev,
+               const struct vio_device_id *id)
+{
+       struct hvc_struct *hp;
+
+       /* probed with invalid parameters. */
+       if (!dev || !id)
+               return -EPERM;
+
+       hp = kmalloc(sizeof(*hp), GFP_KERNEL);
+       if (!hp)
+               return -ENOMEM;
+
+       memset(hp, 0x00, sizeof(*hp));
+       hp->vtermno = dev->unit_address;
+       hp->vdev = dev;
+       hp->vdev->dev.driver_data = hp;
+       hp->irq = dev->irq;
+
+       kobject_init(&hp->kobj);
+       hp->kobj.ktype = &hvc_kobj_type;
+
+       hp->lock = SPIN_LOCK_UNLOCKED;
+       spin_lock(&hvc_structs_lock);
+       hp->index = ++hvc_count;
+       list_add_tail(&(hp->next), &hvc_structs);
+       spin_unlock(&hvc_structs_lock);
+
+       return 0;
+}
+
+static int __devexit hvc_remove(struct vio_dev *dev)
+{
+       struct hvc_struct *hp = dev->dev.driver_data;
+       unsigned long flags;
+       struct kobject *kobjp;
+       struct tty_struct *tty;
+
+       spin_lock_irqsave(&hp->lock, flags);
+       tty = hp->tty;
+       kobjp = &hp->kobj;
+
+       if (hp->index < MAX_NR_HVC_CONSOLES)
+               vtermnos[hp->index] = -1;
+
+       /* Don't whack hp->irq because tty_hangup() will need to free the irq. */
+
+       spin_unlock_irqrestore(&hp->lock, flags);
+
+       /*
+        * We 'put' the instance that was grabbed when the kobject instance
+        * was intialized using kobject_init().  Let the last holder of this
+        * kobject cause it to be removed, which will probably be the tty_hangup
+        * below.
+        */
+       kobject_put(kobjp);
+
+       /*
+        * This function call will auto chain call hvc_hangup.  The tty should
+        * always be valid at this time unless a simultaneous tty close already
+        * cleaned up the hvc_struct.
+        */
+       if (tty)
+               tty_hangup(tty);
+       return 0;
+}
+
+static struct vio_driver hvc_vio_driver = {
+       .name           = hvc_driver_name,
+       .id_table       = hvc_driver_table,
+       .probe          = hvc_probe,
+       .remove         = hvc_remove,
+};
+
+/* Driver initialization.  Follow console initialization.  This is where the TTY
+ * interfaces start to become available. */
+int __init hvc_init(void)
+{
+       int rc;
+
+       /* We need more than num_vterms adapters due to hotplug additions. */
+       hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
+       /* hvc_driver = alloc_tty_driver(num_vterms); */
        if (!hvc_driver)
                return -ENOMEM;
 
@@ -312,31 +751,73 @@ int __init hvc_init(void)
        hvc_driver->init_termios = tty_std_termios;
        hvc_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(hvc_driver, &hvc_ops);
-       for (i = 0; i < num; i++) {
-               hvc_struct[i].lock = SPIN_LOCK_UNLOCKED;
-               hvc_struct[i].index = i;
-       }
 
        if (tty_register_driver(hvc_driver))
                panic("Couldn't register hvc console driver\n");
 
-       if (num > 0)
-               kernel_thread(khvcd, NULL, CLONE_KERNEL);
+       /* Always start the kthread because there can be hotplug vty adapters
+        * added later. */
+       hvc_task = kthread_run(khvcd, NULL, "khvcd");
+       if (IS_ERR(hvc_task)) {
+               panic("Couldn't create kthread for console.\n");
+               put_tty_driver(hvc_driver);
+               return -EIO;
+       }
+
+       /* Register as a vio device to receive callbacks */
+       rc = vio_register_driver(&hvc_vio_driver);
 
-       return 0;
+       return rc;
 }
 
+/* This isn't particularily necessary due to this being a console driver but it
+ * is nice to be thorough */
 static void __exit hvc_exit(void)
 {
+       kthread_stop(hvc_task);
+
+       vio_unregister_driver(&hvc_vio_driver);
+       tty_unregister_driver(hvc_driver);
+       /* return tty_struct instances allocated in hvc_init(). */
+       put_tty_driver(hvc_driver);
+}
+
+/*
+ * Console APIs, NOT TTY.  These APIs are available immediately when
+ * hvc_console_setup() finds adapters.
+ */
+
+/*
+ * hvc_instantiate() is an early console discovery method which locates consoles
+ * prior to the vio subsystem discovering them.  Hotplugged vty adapters do NOT
+ * get an hvc_instantiate() callback since the appear after early console init.
+ */
+int hvc_instantiate(uint32_t vtermno, int index)
+{
+       if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
+               return -1;
+
+       if (vtermnos[index] != -1)
+               return -1;
+
+       vtermnos[index] = vtermno;
+       return 0;
 }
 
 void hvc_console_print(struct console *co, const char *b, unsigned count)
 {
        char c[16] __ALIGNED__;
-       unsigned i, n;
+       unsigned i = 0, n = 0;
        int r, donecr = 0;
 
-       i = n = 0;
+       /* Console access attempt outside of acceptable console range. */
+       if (co->index >= MAX_NR_HVC_CONSOLES)
+               return;
+
+       /* This console adapter was removed so it is not useable. */
+       if (vtermnos[co->index] < 0)
+               return;
+
        while (count > 0 || i > 0) {
                if (count > 0 && i < sizeof(c)) {
                        if (b[n] == '\n' && !donecr) {
@@ -348,7 +829,7 @@ void hvc_console_print(struct console *co, const char *b, unsigned count)
                                --count;
                        }
                } else {
-                       r = hvc_put_chars(co->index + hvc_offset, c, i);
+                       r = hvc_put_chars(vtermnos[co->index], c, i);
                        if (r < 0) {
                                /* throw away chars on error */
                                i = 0;
@@ -369,9 +850,6 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index)
 
 static int __init hvc_console_setup(struct console *co, char *options)
 {
-       if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES
-           || co->index >= hvc_count(&hvc_offset))
-               return -1;
        return 0;
 }
 
@@ -384,8 +862,14 @@ struct console hvc_con_driver = {
        .index          = -1,
 };
 
+/* Early console initialization.  Preceeds driver initialization. */
 static int __init hvc_console_init(void)
 {
+       int i;
+
+       for (i=0; i<MAX_NR_HVC_CONSOLES; i++)
+               vtermnos[i] = -1;
+       num_vterms = hvc_find_vtys();
        register_console(&hvc_con_driver);
        return 0;
 }
index 96ca634..15b1d8c 100644 (file)
 #include <asm/vio.h>
 
 /*
- * 1.0.0 -> 1.1.0 Added kernel_thread scheduling methodology to driver to
- * replace wait_task constructs.
+ * 1.3.0 -> 1.3.1 In hvcs_open memset(..,0x00,..) instead of memset(..,0x3F,00).
+ * Removed braces around single statements following conditionals.  Removed '=
+ * 0' after static int declarations since these default to zero.  Removed
+ * list_for_each_safe() and replaced with list_for_each_entry() in
+ * hvcs_get_by_index().  The 'safe' version is un-needed now that the driver is
+ * using spinlocks.  Changed spin_lock_irqsave() to spin_lock() when locking
+ * hvcs_structs_lock and hvcs_pi_lock since these are not touched in an int
+ * handler.  Initialized hvcs_structs_lock and hvcs_pi_lock to
+ * SPIN_LOCK_UNLOCKED at declaration time rather than in hvcs_module_init().
+ * Added spin_lock around list_del() in destroy_hvcs_struct() to protect the
+ * list traversals from a deletion.  Removed '= NULL' from pointer declaration
+ * statements since they are initialized NULL by default.  Removed wmb()
+ * instances from hvcs_try_write().  They probably aren't needed with locking in
+ * place.  Added check and cleanup for hvcs_pi_buff = kmalloc() in
+ * hvcs_module_init().  Exposed hvcs_struct.index via a sysfs attribute so that
+ * the coupling between /dev/hvcs* and a vty-server can be automatically
+ * determined.  Moved kobject_put() in hvcs_open outside of the
+ * spin_unlock_irqrestore().
  *
- * 1.1.0 -> 1.2.0 Moved pi_buff initialization out of arch code into driver code
- * and added locking to share this buffer between hvcs_struct instances.  This
- * is because the page_size kmalloc can't be done with a spin_lock held.
+ * 1.3.1 -> 1.3.2 Changed method for determining hvcs_struct->index and had it
+ * align with how the tty layer always assigns the lowest index available.  This
+ * change resulted in a list of ints that denotes which indexes are available.
+ * Device additions and removals use the new hvcs_get_index() and
+ * hvcs_return_index() helper functions.  The list is created with
+ * hvsc_alloc_index_list() and it is destroyed with hvcs_free_index_list().
+ * Without these fixes hotplug vty-server adapter support goes crazy with this
+ * driver if the user removes a vty-server adapter.  Moved free_irq() outside of
+ * the hvcs_final_close() function in order to get it out of the spinlock.
+ * Rearranged hvcs_close().  Cleaned up some printks and did some housekeeping
+ * on the changelog.  Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from
+ * arch/ppc64/hvcserver.h.
  *
- * Also added sysfs attribute to manually disconnect the vty-server from the vty
- * due to stupid firmware behavior when opening the connection then sending data
- * then then quickly closing the connection would cause data loss on the
- * receiving side.  This required some reordering of the termination code.
- *
- * Fixed the hangup scenario and fixed memory leaks on module_exit.
- *
- * 1.2.0 -> 1.3.0 Moved from manual kernel thread creation & execution to
- * kthread construct which replaced in-kernel IPC for thread termination with
- * kthread_stop and kthread_should_stop.  Explicit wait_queue handling was
- * removed because kthread handles this.  Minor bug fix to postpone partner_info
- * clearing on hvcs_close until adapter removal to preserve context data for
- * printk on partner connection free.  Added lock to protect hvcs_structs so
- * that hvcs_struct instances aren't added or removed during list traversal.
- * Cleaned up comment style, added spaces after commas, and broke function
- * declaration lines to be under 80 columns.
+ * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to
+ * prevent possible lockup with realtime scheduling as similarily pointed out by
+ * akpm in hvc_console.  Changed resulted in the removal of hvcs_final_close()
+ * to reorder cleanup operations and prevent discarding of pending data during
+ * an hvcs_close().  Removed spinlock protection of hvcs_struct data members in
+ * hvcs_write_room() and hvcs_chars_in_buffer() because they aren't needed.
  */
-#define HVCS_DRIVER_VERSION "1.3.0"
+
+#define HVCS_DRIVER_VERSION "1.3.3"
 
 MODULE_AUTHOR("Ryan S. Arnold <rsa@us.ibm.com>");
 MODULE_DESCRIPTION("IBM hvcs (Hypervisor Virtual Console Server) Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(HVCS_DRIVER_VERSION);
 
+/*
+ * Wait this long per iteration while trying to push buffered data to the
+ * hypervisor before allowing the tty to complete a close operation.
+ */
+#define HVCS_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
+
 /*
  * Since the Linux TTY code does not currently (2-04-2004) support dynamic
  * addition of tty derived devices and we shouldn't allocate thousands of
@@ -138,9 +160,9 @@ MODULE_VERSION(HVCS_DRIVER_VERSION);
 
 /*
  * We let Linux assign us a major number and we start the minors at zero.  There
- * is no intuitive mapping between minor number and the target partition.  The
- * mapping of minor number is related to the order the vty-servers are exposed
- * to this driver via the hvcs_probe function.
+ * is no intuitive mapping between minor number and the target vty-server
+ * adapter except that each new vty-server adapter is always assigned to the
+ * smallest minor number available.
  */
 #define HVCS_MINOR_START       0
 
@@ -152,9 +174,6 @@ MODULE_VERSION(HVCS_DRIVER_VERSION);
  */
 #define __ALIGNED__    __attribute__((__aligned__(8)))
 
-/* Converged location code string length + 1 null terminator */
-#define CLC_LENGTH             80
-
 /*
  * How much data can firmware send with each hvc_put_chars()?  Maybe this
  * should be moved into an architecture specific area.
@@ -194,27 +213,41 @@ char hvcs_driver_string[]
        = "IBM hvcs (Hypervisor Virtual Console Server) Driver";
 
 /* Status of partner info rescan triggered via sysfs. */
-static int hvcs_rescan_status = 0;
+static int hvcs_rescan_status;
 
 static struct tty_driver *hvcs_tty_driver;
 
 /*
- * This is used to associate a vty-server, as it is exposed to this driver, with
- * a preallocated tty_struct.index.  The dev node and hvcs index numbers are not
- * re-used after device removal otherwise removing and adding a new one would
- * link a /dev/hvcs* entry to a different vty-server than it did before the
- * removal.  Incidentally, a newly exposed vty-server will always map to an
- * incrementally higher /dev/hvcs* entry than the last exposed vty-server.
+ * In order to be somewhat sane this driver always associates the hvcs_struct
+ * index element with the numerically equal tty->index.  This means that a
+ * hotplugged vty-server adapter will always map to the lowest index valued
+ * device node.  If vty-servers were hotplug removed from the system and then
+ * new ones added the new vty-server may have the largest slot number of all
+ * the vty-server adapters in the partition but it may have the lowest dev node
+ * index of all the adapters due to the hole left by the hotplug removed
+ * adapter.  There are a set of functions provided to get the lowest index for
+ * a new device as well as return the index to the list.  This list is allocated
+ * with a number of elements equal to the number of device nodes requested when
+ * the module was inserted.
+ */
+static int *hvcs_index_list;
+
+/*
+ * How large is the list?  This is kept for traversal since the list is
+ * dynamically created.
  */
-static int hvcs_struct_count = -1;
+static int hvcs_index_count;
 
 /*
  * Used by the khvcsd to pick up I/O operations when the kernel_thread is
  * already awake but potentially shifted to TASK_INTERRUPTIBLE state.
  */
-static int hvcs_kicked = 0;
+static int hvcs_kicked;
 
-/* Used the the kthread construct for task operations */
+/*
+ * Use by the kthread construct for task operations like waking the sleeping
+ * thread and stopping the kthread.
+ */
 static struct task_struct *hvcs_task;
 
 /*
@@ -223,7 +256,8 @@ static struct task_struct *hvcs_task;
  */
 static unsigned long *hvcs_pi_buff;
 
-static spinlock_t hvcs_pi_lock;
+/* Only allow one hvcs_struct to use the hvcs_pi_buff at a time. */
+static spinlock_t hvcs_pi_lock = SPIN_LOCK_UNLOCKED;
 
 /* One vty-server per hvcs_struct */
 struct hvcs_struct {
@@ -263,9 +297,9 @@ struct hvcs_struct {
         */
        struct kobject kobj; /* ref count & hvcs_struct lifetime */
        int connected; /* is the vty-server currently connected to a vty? */
-       unsigned int p_unit_address; /* partner unit address */
-       unsigned int p_partition_ID; /* partner partition ID */
-       char p_location_code[CLC_LENGTH];
+       uint32_t p_unit_address; /* partner unit address */
+       uint32_t p_partition_ID; /* partner partition ID */
+       char p_location_code[HVCS_CLC_LENGTH + 1]; /* CLC + Null Term */
        struct list_head next; /* list management */
        struct vio_dev *vdev;
 };
@@ -274,7 +308,7 @@ struct hvcs_struct {
 #define from_kobj(kobj) container_of(kobj, struct hvcs_struct, kobj)
 
 static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs);
-static spinlock_t hvcs_structs_lock;
+static spinlock_t hvcs_structs_lock = SPIN_LOCK_UNLOCKED;
 
 static void hvcs_unthrottle(struct tty_struct *tty);
 static void hvcs_throttle(struct tty_struct *tty);
@@ -297,7 +331,6 @@ static void hvcs_partner_free(struct hvcs_struct *hvcsd);
 
 static int hvcs_enable_device(struct hvcs_struct *hvcsd,
                uint32_t unit_address, unsigned int irq, struct vio_dev *dev);
-static void hvcs_final_close(struct hvcs_struct *hvcsd);
 
 static void destroy_hvcs_struct(struct kobject *kobj);
 static int hvcs_open(struct tty_struct *tty, struct file *filp);
@@ -357,12 +390,11 @@ static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance,
                struct pt_regs *regs)
 {
        struct hvcs_struct *hvcsd = dev_instance;
-       unsigned long flags;
 
-       spin_lock_irqsave(&hvcsd->lock, flags);
+       spin_lock(&hvcsd->lock);
        vio_disable_interrupts(hvcsd->vdev);
        hvcsd->todo_mask |= HVCS_SCHED_READ;
-       spin_unlock_irqrestore(&hvcsd->lock, flags);
+       spin_unlock(&hvcsd->lock);
        hvcs_kick();
 
        return IRQ_HANDLED;
@@ -371,7 +403,7 @@ static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance,
 /* This function must be called with the hvcsd->lock held */
 static void hvcs_try_write(struct hvcs_struct *hvcsd)
 {
-       unsigned int unit_address = hvcsd->vdev->unit_address;
+       uint32_t unit_address = hvcsd->vdev->unit_address;
        struct tty_struct *tty = hvcsd->tty;
        int sent;
 
@@ -382,9 +414,9 @@ static void hvcs_try_write(struct hvcs_struct *hvcsd)
                                hvcsd->chars_in_buffer );
                if (sent > 0) {
                        hvcsd->chars_in_buffer = 0;
-                       wmb();
+                       /* wmb(); */
                        hvcsd->todo_mask &= ~(HVCS_TRY_WRITE);
-                       wmb();
+                       /* wmb(); */
 
                        /*
                         * We are still obligated to deliver the data to the
@@ -393,10 +425,7 @@ static void hvcs_try_write(struct hvcs_struct *hvcsd)
                         * a non-existent tty.
                         */
                        if (tty) {
-                               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-                                               && tty->ldisc.write_wakeup)
-                                       (tty->ldisc.write_wakeup) (tty);
-                               wake_up_interruptible(&tty->write_wait);
+                               tty_wakeup(tty);
                        }
                }
        }
@@ -404,11 +433,11 @@ static void hvcs_try_write(struct hvcs_struct *hvcsd)
 
 static int hvcs_io(struct hvcs_struct *hvcsd)
 {
-       unsigned int unit_address;
+       uint32_t unit_address;
        struct tty_struct *tty;
        char buf[HVCS_BUFF_LEN] __ALIGNED__;
        unsigned long flags;
-       int got;
+       int got = 0;
        int i;
 
        spin_lock_irqsave(&hvcsd->lock, flags);
@@ -461,11 +490,8 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
 
 static int khvcsd(void *unused)
 {
-       struct hvcs_struct *hvcsd = NULL;
-       struct list_head *element;
-       struct list_head *safe_temp;
+       struct hvcs_struct *hvcsd;
        int hvcs_todo_mask;
-       unsigned long structs_flags;
 
        __set_current_state(TASK_RUNNING);
 
@@ -474,12 +500,11 @@ static int khvcsd(void *unused)
                hvcs_kicked = 0;
                wmb();
 
-               spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
-               list_for_each_safe(element, safe_temp, &hvcs_structs) {
-                       hvcsd = list_entry(element, struct hvcs_struct, next);
-                               hvcs_todo_mask |= hvcs_io(hvcsd);
+               spin_lock(&hvcs_structs_lock);
+               list_for_each_entry(hvcsd, &hvcs_structs, next) {
+                       hvcs_todo_mask |= hvcs_io(hvcsd);
                }
-               spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+               spin_unlock(&hvcs_structs_lock);
 
                /*
                 * If any of the hvcs adapters want to try a write or quick read
@@ -506,6 +531,19 @@ static struct vio_device_id hvcs_driver_table[] __devinitdata= {
 };
 MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
 
+static void hvcs_return_index(int index)
+{
+       /* Paranoia check */
+       if (!hvcs_index_list)
+               return;
+       if (index < 0 || index >= hvcs_index_count)
+               return;
+       if (hvcs_index_list[index] == -1)
+               return;
+       else
+               hvcs_index_list[index] = -1;
+}
+
 /* callback when the kboject ref count reaches zero */
 static void destroy_hvcs_struct(struct kobject *kobj)
 {
@@ -513,6 +551,7 @@ static void destroy_hvcs_struct(struct kobject *kobj)
        struct vio_dev *vdev;
        unsigned long flags;
 
+       spin_lock(&hvcs_structs_lock);
        spin_lock_irqsave(&hvcsd->lock, flags);
 
        /* the list_del poisons the pointers */
@@ -524,7 +563,7 @@ static void destroy_hvcs_struct(struct kobject *kobj)
                                " partner vty@%X:%d connection.\n",
                                hvcsd->vdev->unit_address,
                                hvcsd->p_unit_address,
-                               (unsigned int)hvcsd->p_partition_ID);
+                               (uint32_t)hvcsd->p_partition_ID);
        }
        printk(KERN_INFO "HVCS: Destroyed hvcs_struct for vty-server@%X.\n",
                        hvcsd->vdev->unit_address);
@@ -534,55 +573,60 @@ static void destroy_hvcs_struct(struct kobject *kobj)
 
        hvcsd->p_unit_address = 0;
        hvcsd->p_partition_ID = 0;
-       memset(&hvcsd->p_location_code[0], 0x00, CLC_LENGTH);
+       hvcs_return_index(hvcsd->index);
+       memset(&hvcsd->p_location_code[0], 0x00, HVCS_CLC_LENGTH + 1);
 
        spin_unlock_irqrestore(&hvcsd->lock, flags);
+       spin_unlock(&hvcs_structs_lock);
 
        hvcs_remove_device_attrs(vdev);
 
        kfree(hvcsd);
 }
 
-/* This function must be called with hvcsd->lock held. */
-static void hvcs_final_close(struct hvcs_struct *hvcsd)
-{
-       vio_disable_interrupts(hvcsd->vdev);
-       free_irq(hvcsd->vdev->irq, hvcsd);
-
-       hvcsd->todo_mask = 0;
-
-       /* These two may be redundant if the operation was a close. */
-       if (hvcsd->tty) {
-               hvcsd->tty->driver_data = NULL;
-               hvcsd->tty = NULL;
-       }
-
-       hvcsd->open_count = 0;
-
-       memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
-       hvcsd->chars_in_buffer = 0;
-}
-
 static struct kobj_type hvcs_kobj_type = {
        .release = destroy_hvcs_struct,
 };
 
+static int hvcs_get_index(void)
+{
+       int i;
+       /* Paranoia check */
+       if (!hvcs_index_list) {
+               printk(KERN_ERR "HVCS: hvcs_index_list NOT valid!.\n");
+               return -EFAULT;
+       }
+       /* Find the numerically lowest first free index. */
+       for(i = 0; i < hvcs_index_count; i++) {
+               if (hvcs_index_list[i] == -1) {
+                       hvcs_index_list[i] = 0;
+                       return i;
+               }
+       }
+       return -1;
+}
+
 static int __devinit hvcs_probe(
        struct vio_dev *dev,
        const struct vio_device_id *id)
 {
        struct hvcs_struct *hvcsd;
-       unsigned long structs_flags;
+       int index;
 
        if (!dev || !id) {
                printk(KERN_ERR "HVCS: probed with invalid parameter.\n");
                return -EPERM;
        }
 
+       /* early to avoid cleanup on failure */
+       index = hvcs_get_index();
+       if (index < 0) {
+               return -EFAULT;
+       }
+
        hvcsd = kmalloc(sizeof(*hvcsd), GFP_KERNEL);
-       if (!hvcsd) {
+       if (!hvcsd)
                return -ENODEV;
-       }
 
        /* hvcsd->tty is zeroed out with the memset */
        memset(hvcsd, 0x00, sizeof(*hvcsd));
@@ -596,7 +640,9 @@ static int __devinit hvcs_probe(
        hvcsd->vdev = dev;
        dev->dev.driver_data = hvcsd;
 
-       hvcsd->index = ++hvcs_struct_count;
+       hvcsd->index = index;
+
+       /* hvcsd->index = ++hvcs_struct_count; */
        hvcsd->chars_in_buffer = 0;
        hvcsd->todo_mask = 0;
        hvcsd->connected = 0;
@@ -617,15 +663,15 @@ static int __devinit hvcs_probe(
         * will get -ENODEV.
         */
 
-       spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
+       spin_lock(&hvcs_structs_lock);
 
        list_add_tail(&(hvcsd->next), &hvcs_structs);
 
-       spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+       spin_unlock(&hvcs_structs_lock);
 
        hvcs_create_device_attrs(hvcsd);
 
-       printk(KERN_INFO "HVCS: Added vty-server@%X.\n", dev->unit_address);
+       printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address);
 
        /*
         * DON'T enable interrupts here because there is no user to receive the
@@ -688,8 +734,8 @@ static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd)
        hvcsd->p_unit_address = pi->unit_address;
        hvcsd->p_partition_ID  = pi->partition_ID;
        clclength = strlen(&pi->location_code[0]);
-       if (clclength > CLC_LENGTH - 1)
-               clclength = CLC_LENGTH - 1;
+       if (clclength > HVCS_CLC_LENGTH)
+               clclength = HVCS_CLC_LENGTH;
 
        /* copy the null-term char too */
        strncpy(&hvcsd->p_location_code[0],
@@ -711,20 +757,18 @@ static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd)
  */
 static int hvcs_get_pi(struct hvcs_struct *hvcsd)
 {
-       /* struct hvcs_partner_info *head_pi = NULL; */
-       struct hvcs_partner_info *pi = NULL;
-       unsigned int unit_address = hvcsd->vdev->unit_address;
+       struct hvcs_partner_info *pi;
+       uint32_t unit_address = hvcsd->vdev->unit_address;
        struct list_head head;
-       unsigned long flags;
        int retval;
 
-       spin_lock_irqsave(&hvcs_pi_lock, flags);
+       spin_lock(&hvcs_pi_lock);
        if (!hvcs_pi_buff) {
-               spin_unlock_irqrestore(&hvcs_pi_lock, flags);
+               spin_unlock(&hvcs_pi_lock);
                return -EFAULT;
        }
        retval = hvcs_get_partner_info(unit_address, &head, hvcs_pi_buff);
-       spin_unlock_irqrestore(&hvcs_pi_lock, flags);
+       spin_unlock(&hvcs_pi_lock);
        if (retval) {
                printk(KERN_ERR "HVCS: Failed to fetch partner"
                        " info for vty-server@%x.\n", unit_address);
@@ -748,11 +792,10 @@ static int hvcs_get_pi(struct hvcs_struct *hvcsd)
  */
 static int hvcs_rescan_devices_list(void)
 {
-       struct hvcs_struct *hvcsd = NULL;
+       struct hvcs_struct *hvcsd;
        unsigned long flags;
-       unsigned long structs_flags;
 
-       spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
+       spin_lock(&hvcs_structs_lock);
 
        list_for_each_entry(hvcsd, &hvcs_structs, next) {
                spin_lock_irqsave(&hvcsd->lock, flags);
@@ -760,7 +803,7 @@ static int hvcs_rescan_devices_list(void)
                spin_unlock_irqrestore(&hvcsd->lock, flags);
        }
 
-       spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+       spin_unlock(&hvcs_structs_lock);
 
        return 0;
 }
@@ -848,13 +891,14 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
                unsigned int irq, struct vio_dev *vdev)
 {
        unsigned long flags;
+       int rc;
 
        /*
         * It is possible that the vty-server was removed between the time that
         * the conn was registered and now.
         */
-       if (!request_irq(irq, &hvcs_handle_interrupt,
-                               SA_INTERRUPT, "ibmhvcs", hvcsd)) {
+       if (!(rc = request_irq(irq, &hvcs_handle_interrupt,
+                               SA_INTERRUPT, "ibmhvcs", hvcsd))) {
                /*
                 * It is possible the vty-server was removed after the irq was
                 * requested but before we have time to enable interrupts.
@@ -874,7 +918,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
        hvcs_partner_free(hvcsd);
        spin_unlock_irqrestore(&hvcsd->lock, flags);
 
-       return -ENODEV;
+       return rc;
 
 }
 
@@ -888,22 +932,17 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
 struct hvcs_struct *hvcs_get_by_index(int index)
 {
        struct hvcs_struct *hvcsd = NULL;
-       struct list_head *element;
-       struct list_head *safe_temp;
        unsigned long flags;
-       unsigned long structs_flags;
 
-       spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
+       spin_lock(&hvcs_structs_lock);
        /* We can immediately discard OOB requests */
        if (index >= 0 && index < HVCS_MAX_SERVER_ADAPTERS) {
-               list_for_each_safe(element, safe_temp, &hvcs_structs) {
-                       hvcsd = list_entry(element, struct hvcs_struct, next);
+               list_for_each_entry(hvcsd, &hvcs_structs, next) {
                        spin_lock_irqsave(&hvcsd->lock, flags);
                        if (hvcsd->index == index) {
                                kobject_get(&hvcsd->kobj);
                                spin_unlock_irqrestore(&hvcsd->lock, flags);
-                               spin_unlock_irqrestore(&hvcs_structs_lock,
-                                               structs_flags);
+                               spin_unlock(&hvcs_structs_lock);
                                return hvcsd;
                        }
                        spin_unlock_irqrestore(&hvcsd->lock, flags);
@@ -911,7 +950,7 @@ struct hvcs_struct *hvcs_get_by_index(int index)
                hvcsd = NULL;
        }
 
-       spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+       spin_unlock(&hvcs_structs_lock);
        return hvcsd;
 }
 
@@ -921,12 +960,13 @@ struct hvcs_struct *hvcs_get_by_index(int index)
  */
 static int hvcs_open(struct tty_struct *tty, struct file *filp)
 {
-       struct hvcs_struct *hvcsd = NULL;
-       int retval = 0;
+       struct hvcs_struct *hvcsd;
+       int rc, retval = 0;
        unsigned long flags;
        unsigned int irq;
        struct vio_dev *vdev;
        unsigned long unit_address;
+       struct kobject *kobjp;
 
        if (tty->driver_data)
                goto fast_open;
@@ -936,7 +976,8 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
         * This function increments the kobject index.
         */
        if (!(hvcsd = hvcs_get_by_index(tty->index))) {
-               printk(KERN_WARNING "HVCS: open failed, no index.\n");
+               printk(KERN_WARNING "HVCS: open failed, no device associated"
+                               " with tty->index %d.\n", tty->index);
                return -ENODEV;
        }
 
@@ -959,7 +1000,7 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
         */
        tty->low_latency = 1;
 
-       memset(&hvcsd->buffer[0], 0x3F, HVCS_BUFF_LEN);
+       memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
 
        /*
         * Save these in the spinlock for the enable operations that need them
@@ -974,12 +1015,12 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
 
        /*
         * This must be done outside of the spinlock because it requests irqs
-        * and will grab the spinlcok and free the connection if it fails.
+        * and will grab the spinlock and free the connection if it fails.
         */
-       if ((hvcs_enable_device(hvcsd, unit_address, irq, vdev))) {
+       if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
                kobject_put(&hvcsd->kobj);
                printk(KERN_WARNING "HVCS: enable device failed.\n");
-               return -ENODEV;
+               return rc;
        }
 
        goto open_success;
@@ -1002,16 +1043,17 @@ fast_open:
 open_success:
        hvcs_kick();
 
-       printk(KERN_INFO "HVCS: vty-server@%X opened.\n",
+       printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
                hvcsd->vdev->unit_address );
 
        return 0;
 
 error_release:
+       kobjp = &hvcsd->kobj;
        spin_unlock_irqrestore(&hvcsd->lock, flags);
        kobject_put(&hvcsd->kobj);
 
-       printk(KERN_WARNING "HVCS: HVCS partner connect failed.\n");
+       printk(KERN_WARNING "HVCS: partner connect failed.\n");
        return retval;
 }
 
@@ -1020,6 +1062,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
        struct hvcs_struct *hvcsd;
        unsigned long flags;
        struct kobject *kobjp;
+       int irq = NO_IRQ;
 
        /*
         * Is someone trying to close the file associated with this device after
@@ -1039,14 +1082,10 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
        hvcsd = tty->driver_data;
 
        spin_lock_irqsave(&hvcsd->lock, flags);
+       kobjp = &hvcsd->kobj;
        if (--hvcsd->open_count == 0) {
 
-               /*
-                * This line is important because it tells hvcs_open that this
-                * device needs to be re-configured the next time hvcs_open is
-                * called.
-                */
-               hvcsd->tty->driver_data = NULL;
+               vio_disable_interrupts(hvcsd->vdev);
 
                /*
                 * NULL this early so that the kernel_thread doesn't try to
@@ -1055,34 +1094,28 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
                 */
                hvcsd->tty = NULL;
 
-               /*
-                * Block the close until all the buffered data has been
-                * delivered.
-                */
-               while(hvcsd->chars_in_buffer) {
-                       spin_unlock_irqrestore(&hvcsd->lock, flags);
+               irq = hvcsd->vdev->irq;
+               spin_unlock_irqrestore(&hvcsd->lock, flags);
 
-                       /*
-                        * Give the kernel thread the hvcs_struct so that it can
-                        * try to deliver the remaining data but block the close
-                        * operation by spinning in this function so that other
-                        * tty operations have to wait.
-                        */
-                       yield();
-                       spin_lock_irqsave(&hvcsd->lock, flags);
-               }
+               tty_wait_until_sent(tty, HVCS_CLOSE_WAIT);
 
-               hvcs_final_close(hvcsd);
+               /*
+                * This line is important because it tells hvcs_open that this
+                * device needs to be re-configured the next time hvcs_open is
+                * called.
+                */
+               tty->driver_data = NULL;
 
+               free_irq(irq, hvcsd);
+               kobject_put(kobjp);
+               return;
        } else if (hvcsd->open_count < 0) {
                printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
                                " is missmanaged.\n",
-                       hvcsd->vdev->unit_address, hvcsd->open_count);
+               hvcsd->vdev->unit_address, hvcsd->open_count);
        }
-       kobjp = &hvcsd->kobj;
 
        spin_unlock_irqrestore(&hvcsd->lock, flags);
-
        kobject_put(kobjp);
 }
 
@@ -1092,6 +1125,7 @@ static void hvcs_hangup(struct tty_struct * tty)
        unsigned long flags;
        int temp_open_count;
        struct kobject *kobjp;
+       int irq = NO_IRQ;
 
        spin_lock_irqsave(&hvcsd->lock, flags);
        /* Preserve this so that we know how many kobject refs to put */
@@ -1101,15 +1135,31 @@ static void hvcs_hangup(struct tty_struct * tty)
         * Don't kobject put inside the spinlock because the destruction
         * callback may use the spinlock and it may get called before the
         * spinlock has been released.  Get a pointer to the kobject and
-        * kobject_put on that instead.
+        * kobject_put on that after releasing the spinlock.
         */
        kobjp = &hvcsd->kobj;
 
-       /* Calling this will drop any buffered data on the floor. */
-       hvcs_final_close(hvcsd);
+       vio_disable_interrupts(hvcsd->vdev);
+
+       hvcsd->todo_mask = 0;
+
+       /* I don't think the tty needs the hvcs_struct pointer after a hangup */
+       hvcsd->tty->driver_data = NULL;
+       hvcsd->tty = NULL;
+
+       hvcsd->open_count = 0;
+
+       /* This will drop any buffered data on the floor which is OK in a hangup
+        * scenario. */
+       memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
+       hvcsd->chars_in_buffer = 0;
+
+       irq = hvcsd->vdev->irq;
 
        spin_unlock_irqrestore(&hvcsd->lock, flags);
 
+       free_irq(irq, hvcsd);
+
        /*
         * We need to kobject_put() for every open_count we have since the
         * tty_hangup() function doesn't invoke a close per open connection on a
@@ -1259,28 +1309,18 @@ static int hvcs_write(struct tty_struct *tty, int from_user,
 static int hvcs_write_room(struct tty_struct *tty)
 {
        struct hvcs_struct *hvcsd = tty->driver_data;
-       unsigned long flags;
-       int retval;
 
        if (!hvcsd || hvcsd->open_count <= 0)
                return 0;
 
-       spin_lock_irqsave(&hvcsd->lock, flags);
-       retval = HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
-       spin_unlock_irqrestore(&hvcsd->lock, flags);
-       return retval;
+       return HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
 }
 
 static int hvcs_chars_in_buffer(struct tty_struct *tty)
 {
        struct hvcs_struct *hvcsd = tty->driver_data;
-       unsigned long flags;
-       int retval;
 
-       spin_lock_irqsave(&hvcsd->lock, flags);
-       retval = hvcsd->chars_in_buffer;
-       spin_unlock_irqrestore(&hvcsd->lock, flags);
-       return retval;
+       return hvcsd->chars_in_buffer;
 }
 
 static struct tty_operations hvcs_ops = {
@@ -1294,6 +1334,28 @@ static struct tty_operations hvcs_ops = {
        .throttle = hvcs_throttle,
 };
 
+static int hvcs_alloc_index_list(int n)
+{
+       int i;
+       hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL);
+       if (!hvcs_index_list)
+               return -ENOMEM;
+       hvcs_index_count = n;
+       for(i = 0; i < hvcs_index_count; i++)
+               hvcs_index_list[i] = -1;
+       return 0;
+}
+
+static void hvcs_free_index_list(void)
+{
+       /* Paranoia check to be thorough. */
+       if (hvcs_index_list) {
+               kfree(hvcs_index_list);
+               hvcs_index_list = NULL;
+               hvcs_index_count = 0;
+       }
+}
+
 static int __init hvcs_module_init(void)
 {
        int rc;
@@ -1312,6 +1374,9 @@ static int __init hvcs_module_init(void)
        if (!hvcs_tty_driver)
                return -ENOMEM;
 
+       if (hvcs_alloc_index_list(num_ttys_to_alloc))
+               return -ENOMEM;
+
        hvcs_tty_driver->owner = THIS_MODULE;
 
        hvcs_tty_driver->driver_name = hvcs_driver_name;
@@ -1342,19 +1407,25 @@ static int __init hvcs_module_init(void)
        if (tty_register_driver(hvcs_tty_driver)) {
                printk(KERN_ERR "HVCS: registration "
                        " as a tty driver failed.\n");
+               hvcs_free_index_list();
                put_tty_driver(hvcs_tty_driver);
-               return rc;
+               return -EIO;
        }
 
-       hvcs_structs_lock = SPIN_LOCK_UNLOCKED;
-
-       hvcs_pi_lock = SPIN_LOCK_UNLOCKED;
        hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!hvcs_pi_buff) {
+               tty_unregister_driver(hvcs_tty_driver);
+               hvcs_free_index_list();
+               put_tty_driver(hvcs_tty_driver);
+               return -ENOMEM;
+       }
 
        hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
        if (IS_ERR(hvcs_task)) {
-               printk("khvcsd creation failed.  Driver not loaded.\n");
+               printk(KERN_ERR "HVCS: khvcsd creation failed.  Driver not loaded.\n");
                kfree(hvcs_pi_buff);
+               tty_unregister_driver(hvcs_tty_driver);
+               hvcs_free_index_list();
                put_tty_driver(hvcs_tty_driver);
                return -EIO;
        }
@@ -1374,8 +1445,6 @@ static int __init hvcs_module_init(void)
 
 static void __exit hvcs_module_exit(void)
 {
-       unsigned long flags;
-
        /*
         * This driver receives hvcs_remove callbacks for each device upon
         * module removal.
@@ -1387,10 +1456,10 @@ static void __exit hvcs_module_exit(void)
         */
        kthread_stop(hvcs_task);
 
-       spin_lock_irqsave(&hvcs_pi_lock, flags);
+       spin_lock(&hvcs_pi_lock);
        kfree(hvcs_pi_buff);
        hvcs_pi_buff = NULL;
-       spin_unlock_irqrestore(&hvcs_pi_lock, flags);
+       spin_unlock(&hvcs_pi_lock);
 
        hvcs_remove_driver_attrs();
 
@@ -1398,6 +1467,8 @@ static void __exit hvcs_module_exit(void)
 
        tty_unregister_driver(hvcs_tty_driver);
 
+       hvcs_free_index_list();
+
        put_tty_driver(hvcs_tty_driver);
 
        printk(KERN_INFO "HVCS: driver module removed.\n");
@@ -1499,7 +1570,7 @@ static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
                        " partner vty@%X:%d connection.\n",
                        hvcsd->vdev->unit_address,
                        hvcsd->p_unit_address,
-                       (unsigned int)hvcsd->p_partition_ID);
+                       (uint32_t)hvcsd->p_partition_ID);
 
        spin_unlock_irqrestore(&hvcsd->lock, flags);
        return count;
@@ -1520,11 +1591,27 @@ static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
 static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
                hvcs_vterm_state_show, hvcs_vterm_state_store);
 
+static ssize_t hvcs_index_show(struct device *dev, char *buf)
+{
+       struct vio_dev *viod = to_vio_dev(dev);
+       struct hvcs_struct *hvcsd = from_vio_dev(viod);
+       unsigned long flags;
+       int retval;
+
+       spin_lock_irqsave(&hvcsd->lock, flags);
+       retval = sprintf(buf, "%d\n", hvcsd->index);
+       spin_unlock_irqrestore(&hvcsd->lock, flags);
+       return retval;
+}
+
+static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);
+
 static struct attribute *hvcs_attrs[] = {
        &dev_attr_partner_vtys.attr,
        &dev_attr_partner_clcs.attr,
        &dev_attr_current_vty.attr,
        &dev_attr_vterm_state.attr,
+       &dev_attr_index.attr,
        NULL,
 };
 
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
new file mode 100644 (file)
index 0000000..595079c
--- /dev/null
@@ -0,0 +1,1319 @@
+/*
+ * Copyright (C) 2004 Hollis Blanchard <hollisb@us.ibm.com>, IBM
+ *
+ * This program is free software; you can redistribute 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
+ */
+
+/* Host Virtual Serial Interface (HVSI) is a protocol between the hosted OS
+ * and the service processor on IBM pSeries servers. On these servers, there
+ * are no serial ports under the OS's control, and sometimes there is no other
+ * console available either. However, the service processor has two standard
+ * serial ports, so this over-complicated protocol allows the OS to control
+ * those ports by proxy.
+ *
+ * Besides data, the procotol supports the reading/writing of the serial
+ * port's DTR line, and the reading of the CD line. This is to allow the OS to
+ * control a modem attached to the service processor's serial port. Note that
+ * the OS cannot change the speed of the port through this protocol.
+ */
+
+/* TODO:
+ * test FSP reset
+ * add udbg support for xmon/kdb
+ */
+
+#undef DEBUG
+
+#include <linux/console.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/major.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <asm/hvcall.h>
+#include <asm/hvconsole.h>
+#include <asm/prom.h>
+#include <asm/uaccess.h>
+#include <asm/vio.h>
+
+#define HVSI_MAJOR     229
+#define HVSI_MINOR     128
+#define MAX_NR_HVSI_CONSOLES 4
+
+#define HVSI_TIMEOUT (5*HZ)
+#define HVSI_VERSION 1
+#define HVSI_MAX_PACKET 256
+#define HVSI_MAX_READ 16
+#define HVSI_MAX_OUTGOING_DATA 12
+#define N_OUTBUF 12
+
+/*
+ * we pass data via two 8-byte registers, so we would like our char arrays
+ * properly aligned for those loads.
+ */
+#define __ALIGNED__    __attribute__((__aligned__(sizeof(long))))
+
+struct hvsi_struct {
+       struct work_struct writer;
+       wait_queue_head_t emptyq; /* woken when outbuf is emptied */
+       wait_queue_head_t stateq; /* woken when HVSI state changes */
+       spinlock_t lock;
+       int index;
+       struct tty_struct *tty;
+       unsigned int count;
+       uint8_t throttle_buf[128];
+       uint8_t outbuf[N_OUTBUF]; /* to implement write_room and chars_in_buffer */
+       /* inbuf is for packet reassembly. leave a little room for leftovers. */
+       uint8_t inbuf[HVSI_MAX_PACKET + HVSI_MAX_READ];
+       uint8_t *inbuf_end;
+       int n_throttle;
+       int n_outbuf;
+       uint32_t vtermno;
+       uint32_t virq;
+       atomic_t seqno; /* HVSI packet sequence number */
+       uint16_t mctrl;
+       uint8_t state;  /* HVSI protocol state */
+       uint8_t flags;
+#ifdef CONFIG_MAGIC_SYSRQ
+       uint8_t sysrq;
+#endif /* CONFIG_MAGIC_SYSRQ */
+};
+static struct hvsi_struct hvsi_ports[MAX_NR_HVSI_CONSOLES];
+
+static struct tty_driver *hvsi_driver;
+static int hvsi_count;
+static int (*hvsi_wait)(struct hvsi_struct *hp, int state);
+
+enum HVSI_PROTOCOL_STATE {
+       HVSI_CLOSED,
+       HVSI_WAIT_FOR_VER_RESPONSE,
+       HVSI_WAIT_FOR_VER_QUERY,
+       HVSI_OPEN,
+       HVSI_WAIT_FOR_MCTRL_RESPONSE,
+};
+#define HVSI_CONSOLE 0x1
+
+#define VS_DATA_PACKET_HEADER           0xff
+#define VS_CONTROL_PACKET_HEADER        0xfe
+#define VS_QUERY_PACKET_HEADER          0xfd
+#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc
+
+/* control verbs */
+#define VSV_SET_MODEM_CTL    1 /* to service processor only */
+#define VSV_MODEM_CTL_UPDATE 2 /* from service processor only */
+#define VSV_CLOSE_PROTOCOL   3
+
+/* query verbs */
+#define VSV_SEND_VERSION_NUMBER 1
+#define VSV_SEND_MODEM_CTL_STATUS 2
+
+/* yes, these masks are not consecutive. */
+#define HVSI_TSDTR 0x01
+#define HVSI_TSCD  0x20
+
+struct hvsi_header {
+       uint8_t  type;
+       uint8_t  len;
+       uint16_t seqno;
+} __attribute__((packed));
+
+struct hvsi_data {
+       uint8_t  type;
+       uint8_t  len;
+       uint16_t seqno;
+       uint8_t  data[HVSI_MAX_OUTGOING_DATA];
+} __attribute__((packed));
+
+struct hvsi_control {
+       uint8_t  type;
+       uint8_t  len;
+       uint16_t seqno;
+       uint16_t verb;
+       /* optional depending on verb: */
+       uint32_t word;
+       uint32_t mask;
+} __attribute__((packed));
+
+struct hvsi_query {
+       uint8_t  type;
+       uint8_t  len;
+       uint16_t seqno;
+       uint16_t verb;
+} __attribute__((packed));
+
+struct hvsi_query_response {
+       uint8_t  type;
+       uint8_t  len;
+       uint16_t seqno;
+       uint16_t verb;
+       uint16_t query_seqno;
+       union {
+               uint8_t  version;
+               uint32_t mctrl_word;
+       } u;
+} __attribute__((packed));
+
+static inline int is_open(struct hvsi_struct *hp)
+{
+       /* if we're waiting for an mctrl then we're already open */
+       return (hp->state == HVSI_OPEN)
+                       || (hp->state == HVSI_WAIT_FOR_MCTRL_RESPONSE);
+}
+
+static inline void print_state(struct hvsi_struct *hp)
+{
+#ifdef DEBUG
+       static const char *state_names[] = {
+               "HVSI_CLOSED",
+               "HVSI_WAIT_FOR_VER_RESPONSE",
+               "HVSI_WAIT_FOR_VER_QUERY",
+               "HVSI_OPEN",
+               "HVSI_WAIT_FOR_MCTRL_RESPONSE",
+       };
+       const char *name = state_names[hp->state];
+
+       if (hp->state > (sizeof(state_names)/sizeof(char*)))
+               name = "UNKNOWN";
+
+       pr_debug("hvsi%i: state = %s\n", hp->index, name);
+#endif /* DEBUG */
+}
+
+static inline void __set_state(struct hvsi_struct *hp, int state)
+{
+       hp->state = state;
+       print_state(hp);
+       wake_up_all(&hp->stateq);
+}
+
+static inline void set_state(struct hvsi_struct *hp, int state)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hp->lock, flags);
+       __set_state(hp, state);
+       spin_unlock_irqrestore(&hp->lock, flags);
+}
+
+static inline int len_packet(const uint8_t *packet)
+{
+       return (int)((struct hvsi_header *)packet)->len;
+}
+
+static inline int is_header(const uint8_t *packet)
+{
+       struct hvsi_header *header = (struct hvsi_header *)packet;
+       return header->type >= VS_QUERY_RESPONSE_PACKET_HEADER;
+}
+
+static inline int got_packet(const struct hvsi_struct *hp, uint8_t *packet)
+{
+       if (hp->inbuf_end < packet + sizeof(struct hvsi_header))
+               return 0; /* don't even have the packet header */
+
+       if (hp->inbuf_end < (packet + len_packet(packet)))
+               return 0; /* don't have the rest of the packet */
+
+       return 1;
+}
+
+/* shift remaining bytes in packetbuf down */
+static void compact_inbuf(struct hvsi_struct *hp, uint8_t *read_to)
+{
+       int remaining = (int)(hp->inbuf_end - read_to);
+
+       pr_debug("%s: %i chars remain\n", __FUNCTION__, remaining);
+
+       if (read_to != hp->inbuf)
+               memmove(hp->inbuf, read_to, remaining);
+
+       hp->inbuf_end = hp->inbuf + remaining;
+}
+
+#ifdef DEBUG
+#define dbg_dump_packet(packet) dump_packet(packet)
+#define dbg_dump_hex(data, len) dump_hex(data, len)
+#else
+#define dbg_dump_packet(packet) do { } while (0)
+#define dbg_dump_hex(data, len) do { } while (0)
+#endif
+
+static void dump_hex(const uint8_t *data, int len)
+{
+       int i;
+
+       printk("    ");
+       for (i=0; i < len; i++)
+               printk("%.2x", data[i]);
+
+       printk("\n    ");
+       for (i=0; i < len; i++) {
+               if (isprint(data[i]))
+                       printk("%c", data[i]);
+               else
+                       printk(".");
+       }
+       printk("\n");
+}
+
+static void dump_packet(uint8_t *packet)
+{
+       struct hvsi_header *header = (struct hvsi_header *)packet;
+
+       printk("type 0x%x, len %i, seqno %i:\n", header->type, header->len,
+                       header->seqno);
+
+       dump_hex(packet, header->len);
+}
+
+/* can't use hvc_get_chars because that strips CRs */
+static int hvsi_read(struct hvsi_struct *hp, char *buf, int count)
+{
+       unsigned long got;
+
+       if (plpar_hcall(H_GET_TERM_CHAR, hp->vtermno, 0, 0, 0, &got,
+                       (unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
+               return got;
+       return 0;
+}
+
+/*
+ * we can't call tty_hangup() directly here because we need to call that
+ * outside of our lock
+ */
+static struct tty_struct *hvsi_recv_control(struct hvsi_struct *hp,
+               uint8_t *packet)
+{
+       struct tty_struct *to_hangup = NULL;
+       struct hvsi_control *header = (struct hvsi_control *)packet;
+
+       switch (header->verb) {
+               case VSV_MODEM_CTL_UPDATE:
+                       if ((header->word & HVSI_TSCD) == 0) {
+                               /* CD went away; no more connection */
+                               pr_debug("hvsi%i: CD dropped\n", hp->index);
+                               hp->mctrl &= TIOCM_CD;
+                               if (!(hp->tty->flags & CLOCAL))
+                                       to_hangup = hp->tty;
+                       }
+                       break;
+               case VSV_CLOSE_PROTOCOL:
+                       printk(KERN_DEBUG
+                               "hvsi%i: service processor closed connection!\n", hp->index);
+                       __set_state(hp, HVSI_CLOSED);
+                       to_hangup = hp->tty;
+                       hp->tty = NULL;
+                       break;
+               default:
+                       printk(KERN_WARNING "hvsi%i: unknown HVSI control packet: ",
+                               hp->index);
+                       dump_packet(packet);
+                       break;
+       }
+
+       return to_hangup;
+}
+
+static void hvsi_recv_response(struct hvsi_struct *hp, uint8_t *packet)
+{
+       struct hvsi_query_response *resp = (struct hvsi_query_response *)packet;
+
+       switch (hp->state) {
+               case HVSI_WAIT_FOR_VER_RESPONSE:
+                       __set_state(hp, HVSI_WAIT_FOR_VER_QUERY);
+                       break;
+               case HVSI_WAIT_FOR_MCTRL_RESPONSE:
+                       hp->mctrl = 0;
+                       if (resp->u.mctrl_word & HVSI_TSDTR)
+                               hp->mctrl |= TIOCM_DTR;
+                       if (resp->u.mctrl_word & HVSI_TSCD)
+                               hp->mctrl |= TIOCM_CD;
+                       __set_state(hp, HVSI_OPEN);
+                       break;
+               default:
+                       printk(KERN_ERR "hvsi%i: unexpected query response: ", hp->index);
+                       dump_packet(packet);
+                       break;
+       }
+}
+
+/* respond to service processor's version query */
+static int hvsi_version_respond(struct hvsi_struct *hp, uint16_t query_seqno)
+{
+       struct hvsi_query_response packet __ALIGNED__;
+       int wrote;
+
+       packet.type = VS_QUERY_RESPONSE_PACKET_HEADER;
+       packet.len = sizeof(struct hvsi_query_response);
+       packet.seqno = atomic_inc_return(&hp->seqno);
+       packet.verb = VSV_SEND_VERSION_NUMBER;
+       packet.u.version = HVSI_VERSION;
+       packet.query_seqno = query_seqno+1;
+
+       pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+       dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+       wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+       if (wrote != packet.len) {
+               printk(KERN_ERR "hvsi%i: couldn't send query response!\n",
+                       hp->index);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static void hvsi_recv_query(struct hvsi_struct *hp, uint8_t *packet)
+{
+       struct hvsi_query *query = (struct hvsi_query *)packet;
+
+       switch (hp->state) {
+               case HVSI_WAIT_FOR_VER_QUERY:
+                       __set_state(hp, HVSI_OPEN);
+                       hvsi_version_respond(hp, query->seqno);
+                       break;
+               default:
+                       printk(KERN_ERR "hvsi%i: unexpected query: ", hp->index);
+                       dump_packet(packet);
+                       break;
+       }
+}
+
+static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len)
+{
+       int i;
+
+       for (i=0; i < len; i++) {
+               char c = buf[i];
+#ifdef CONFIG_MAGIC_SYSRQ
+               if (c == '\0') {
+                       hp->sysrq = 1;
+                       continue;
+               } else if (hp->sysrq) {
+                       handle_sysrq(c, NULL, hp->tty);
+                       hp->sysrq = 0;
+                       continue;
+               }
+#endif /* CONFIG_MAGIC_SYSRQ */
+               tty_insert_flip_char(hp->tty, c, 0);
+       }
+}
+
+/*
+ * We could get 252 bytes of data at once here. But the tty layer only
+ * throttles us at TTY_THRESHOLD_THROTTLE (128) bytes, so we could overflow
+ * it. Accordingly we won't send more than 128 bytes at a time to the flip
+ * buffer, which will give the tty buffer a chance to throttle us. Should the
+ * value of TTY_THRESHOLD_THROTTLE change in n_tty.c, this code should be
+ * revisited.
+ */
+#define TTY_THRESHOLD_THROTTLE 128
+static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp,
+               const uint8_t *packet)
+{
+       const struct hvsi_header *header = (const struct hvsi_header *)packet;
+       const uint8_t *data = packet + sizeof(struct hvsi_header);
+       int datalen = header->len - sizeof(struct hvsi_header);
+       int overflow = datalen - TTY_THRESHOLD_THROTTLE;
+
+       pr_debug("queueing %i chars '%.*s'\n", datalen, datalen, data);
+
+       if (datalen == 0)
+               return NULL;
+
+       if (overflow > 0) {
+               pr_debug("%s: got >TTY_THRESHOLD_THROTTLE bytes\n", __FUNCTION__);
+               datalen = TTY_THRESHOLD_THROTTLE;
+       }
+
+       hvsi_insert_chars(hp, data, datalen);
+
+       if (overflow > 0) {
+               /*
+                * we still have more data to deliver, so we need to save off the
+                * overflow and send it later
+                */
+               pr_debug("%s: deferring overflow\n", __FUNCTION__);
+               memcpy(hp->throttle_buf, data + TTY_THRESHOLD_THROTTLE, overflow);
+               hp->n_throttle = overflow;
+       }
+
+       return hp->tty;
+}
+
+/*
+ * Returns true/false indicating data successfully read from hypervisor.
+ * Used both to get packets for tty connections and to advance the state
+ * machine during console handshaking (in which case tty = NULL and we ignore
+ * incoming data).
+ */
+static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
+               struct tty_struct **hangup)
+{
+       uint8_t *packet = hp->inbuf;
+       int chunklen;
+
+       *flip = NULL;
+       *hangup = NULL;
+
+       chunklen = hvsi_read(hp, hp->inbuf_end, HVSI_MAX_READ);
+       if (chunklen == 0)
+               return 0;
+
+       pr_debug("%s: got %i bytes\n", __FUNCTION__, chunklen);
+       dbg_dump_hex(hp->inbuf_end, chunklen);
+
+       hp->inbuf_end += chunklen;
+
+       /* handle all completed packets */
+       while ((packet < hp->inbuf_end) && got_packet(hp, packet)) {
+               struct hvsi_header *header = (struct hvsi_header *)packet;
+
+               if (!is_header(packet)) {
+                       printk(KERN_ERR "hvsi%i: got malformed packet\n", hp->index);
+                       /* skip bytes until we find a header or run out of data */
+                       while ((packet < hp->inbuf_end) && (!is_header(packet)))
+                               packet++;
+                       continue;
+               }
+
+               pr_debug("%s: handling %i-byte packet\n", __FUNCTION__,
+                               len_packet(packet));
+               dbg_dump_packet(packet);
+
+               switch (header->type) {
+                       case VS_DATA_PACKET_HEADER:
+                               if (!is_open(hp))
+                                       break;
+                               if (hp->tty == NULL)
+                                       break; /* no tty buffer to put data in */
+                               *flip = hvsi_recv_data(hp, packet);
+                               break;
+                       case VS_CONTROL_PACKET_HEADER:
+                               *hangup = hvsi_recv_control(hp, packet);
+                               break;
+                       case VS_QUERY_RESPONSE_PACKET_HEADER:
+                               hvsi_recv_response(hp, packet);
+                               break;
+                       case VS_QUERY_PACKET_HEADER:
+                               hvsi_recv_query(hp, packet);
+                               break;
+                       default:
+                               printk(KERN_ERR "hvsi%i: unknown HVSI packet type 0x%x\n",
+                                               hp->index, header->type);
+                               dump_packet(packet);
+                               break;
+               }
+
+               packet += len_packet(packet);
+
+               if (*hangup) {
+                       pr_debug("%s: hangup\n", __FUNCTION__);
+                       /*
+                        * we need to send the hangup now before receiving any more data.
+                        * If we get "data, hangup, data", we can't deliver the second
+                        * data before the hangup.
+                        */
+                       break;
+               }
+       }
+
+       compact_inbuf(hp, packet);
+
+       return 1;
+}
+
+static void hvsi_send_overflow(struct hvsi_struct *hp)
+{
+       pr_debug("%s: delivering %i bytes overflow\n", __FUNCTION__,
+                       hp->n_throttle);
+
+       hvsi_insert_chars(hp, hp->throttle_buf, hp->n_throttle);
+       hp->n_throttle = 0;
+}
+
+/*
+ * must get all pending data because we only get an irq on empty->non-empty
+ * transition
+ */
+static irqreturn_t hvsi_interrupt(int irq, void *arg, struct pt_regs *regs)
+{
+       struct hvsi_struct *hp = (struct hvsi_struct *)arg;
+       struct tty_struct *flip;
+       struct tty_struct *hangup;
+       unsigned long flags;
+       irqreturn_t handled = IRQ_NONE;
+       int again = 1;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       while (again) {
+               spin_lock_irqsave(&hp->lock, flags);
+               again = hvsi_load_chunk(hp, &flip, &hangup);
+               handled = IRQ_HANDLED;
+               spin_unlock_irqrestore(&hp->lock, flags);
+
+               /*
+                * we have to call tty_flip_buffer_push() and tty_hangup() outside our
+                * spinlock. But we also have to keep going until we've read all the
+                * available data.
+                */
+
+               if (flip) {
+                       /* there was data put in the tty flip buffer */
+                       tty_flip_buffer_push(flip);
+                       flip = NULL;
+               }
+
+               if (hangup) {
+                       tty_hangup(hangup);
+               }
+       }
+
+       spin_lock_irqsave(&hp->lock, flags);
+       if (hp->tty && hp->n_throttle
+                       && (!test_bit(TTY_THROTTLED, &hp->tty->flags))) {
+               /* we weren't hung up and we weren't throttled, so we can deliver the
+                * rest now */
+               flip = hp->tty;
+               hvsi_send_overflow(hp);
+       }
+       spin_unlock_irqrestore(&hp->lock, flags);
+
+       if (flip) {
+               tty_flip_buffer_push(flip);
+       }
+
+       return handled;
+}
+
+/* for boot console, before the irq handler is running */
+static int __init poll_for_state(struct hvsi_struct *hp, int state)
+{
+       unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
+
+       for (;;) {
+               hvsi_interrupt(hp->virq, (void *)hp, NULL); /* get pending data */
+
+               if (hp->state == state)
+                       return 0;
+
+               mdelay(5);
+               if (time_after(jiffies, end_jiffies))
+                       return -EIO;
+       }
+}
+
+/* wait for irq handler to change our state */
+static int wait_for_state(struct hvsi_struct *hp, int state)
+{
+       unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
+       unsigned long timeout;
+       int ret = 0;
+
+       DECLARE_WAITQUEUE(myself, current);
+       set_current_state(TASK_INTERRUPTIBLE);
+       add_wait_queue(&hp->stateq, &myself);
+
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (hp->state == state)
+                       break;
+               timeout = end_jiffies - jiffies;
+               if (time_after(jiffies, end_jiffies)) {
+                       ret = -EIO;
+                       break;
+               }
+               schedule_timeout(timeout);
+       }
+       remove_wait_queue(&hp->stateq, &myself);
+       set_current_state(TASK_RUNNING);
+
+       return ret;
+}
+
+static int hvsi_query(struct hvsi_struct *hp, uint16_t verb)
+{
+       struct hvsi_query packet __ALIGNED__;
+       int wrote;
+
+       packet.type = VS_QUERY_PACKET_HEADER;
+       packet.len = sizeof(struct hvsi_query);
+       packet.seqno = atomic_inc_return(&hp->seqno);
+       packet.verb = verb;
+
+       pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+       dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+       wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+       if (wrote != packet.len) {
+               printk(KERN_ERR "hvsi%i: couldn't send query (%i)!\n", hp->index,
+                       wrote);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int hvsi_get_mctrl(struct hvsi_struct *hp)
+{
+       int ret;
+
+       set_state(hp, HVSI_WAIT_FOR_MCTRL_RESPONSE);
+       hvsi_query(hp, VSV_SEND_MODEM_CTL_STATUS);
+
+       ret = hvsi_wait(hp, HVSI_OPEN);
+       if (ret < 0) {
+               printk(KERN_ERR "hvsi%i: didn't get modem flags\n", hp->index);
+               set_state(hp, HVSI_OPEN);
+               return ret;
+       }
+
+       pr_debug("%s: mctrl 0x%x\n", __FUNCTION__, hp->mctrl);
+
+       return 0;
+}
+
+/* note that we can only set DTR */
+static int hvsi_set_mctrl(struct hvsi_struct *hp, uint16_t mctrl)
+{
+       struct hvsi_control packet __ALIGNED__;
+       int wrote;
+
+       packet.type = VS_CONTROL_PACKET_HEADER,
+       packet.seqno = atomic_inc_return(&hp->seqno);
+       packet.len = sizeof(struct hvsi_control);
+       packet.verb = VSV_SET_MODEM_CTL;
+       packet.mask = HVSI_TSDTR;
+
+       if (mctrl & TIOCM_DTR)
+               packet.word = HVSI_TSDTR;
+
+       pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+       dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+       wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+       if (wrote != packet.len) {
+               printk(KERN_ERR "hvsi%i: couldn't set DTR!\n", hp->index);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static void hvsi_drain_input(struct hvsi_struct *hp)
+{
+       uint8_t buf[HVSI_MAX_READ] __ALIGNED__;
+       unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
+
+       while (time_before(end_jiffies, jiffies))
+               if (0 == hvsi_read(hp, buf, HVSI_MAX_READ))
+                       break;
+}
+
+static int hvsi_handshake(struct hvsi_struct *hp)
+{
+       int ret;
+
+       /*
+        * We could have a CLOSE or other data waiting for us before we even try
+        * to open; try to throw it all away so we don't get confused. (CLOSE
+        * is the first message sent up the pipe when the FSP comes online. We
+        * need to distinguish between "it came up a while ago and we're the first
+        * user" and "it was just reset before it saw our handshake packet".)
+        */
+       hvsi_drain_input(hp);
+
+       set_state(hp, HVSI_WAIT_FOR_VER_RESPONSE);
+       ret = hvsi_query(hp, VSV_SEND_VERSION_NUMBER);
+       if (ret < 0) {
+               printk(KERN_ERR "hvsi%i: couldn't send version query\n", hp->index);
+               return ret;
+       }
+
+       ret = hvsi_wait(hp, HVSI_OPEN);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int hvsi_put_chars(struct hvsi_struct *hp, const char *buf, int count)
+{
+       struct hvsi_data packet __ALIGNED__;
+       int ret;
+
+       BUG_ON(count > HVSI_MAX_OUTGOING_DATA);
+
+       packet.type = VS_DATA_PACKET_HEADER;
+       packet.seqno = atomic_inc_return(&hp->seqno);
+       packet.len = count + sizeof(struct hvsi_header);
+       memcpy(&packet.data, buf, count);
+
+       ret = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+       if (ret == packet.len) {
+               /* return the number of chars written, not the packet length */
+               return count;
+       }
+       return ret; /* return any errors */
+}
+
+static void hvsi_close_protocol(struct hvsi_struct *hp)
+{
+       struct hvsi_control packet __ALIGNED__;
+
+       packet.type = VS_CONTROL_PACKET_HEADER;
+       packet.seqno = atomic_inc_return(&hp->seqno);
+       packet.len = 6;
+       packet.verb = VSV_CLOSE_PROTOCOL;
+
+       pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+       dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+       hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+}
+
+static int hvsi_open(struct tty_struct *tty, struct file *filp)
+{
+       struct hvsi_struct *hp;
+       unsigned long flags;
+       int line = tty->index;
+       int ret;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       if (line < 0 || line >= hvsi_count)
+               return -ENODEV;
+       hp = &hvsi_ports[line];
+
+       tty->driver_data = hp;
+       tty->low_latency = 1; /* avoid throttle/tty_flip_buffer_push race */
+
+       spin_lock_irqsave(&hp->lock, flags);
+       hp->tty = tty;
+       hp->count++;
+       atomic_set(&hp->seqno, 0);
+       h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
+       spin_unlock_irqrestore(&hp->lock, flags);
+
+       if (hp->flags & HVSI_CONSOLE)
+               return 0; /* this has already been handshaked as the console */
+
+       ret = hvsi_handshake(hp);
+       if (ret < 0) {
+               printk(KERN_ERR "%s: HVSI handshaking failed\n", tty->name);
+               return ret;
+       }
+
+       ret = hvsi_get_mctrl(hp);
+       if (ret < 0) {
+               printk(KERN_ERR "%s: couldn't get initial modem flags\n", tty->name);
+               return ret;
+       }
+
+       ret = hvsi_set_mctrl(hp, hp->mctrl | TIOCM_DTR);
+       if (ret < 0) {
+               printk(KERN_ERR "%s: couldn't set DTR\n", tty->name);
+               return ret;
+       }
+
+       return 0;
+}
+
+/* wait for hvsi_write_worker to empty hp->outbuf */
+static void hvsi_flush_output(struct hvsi_struct *hp)
+{
+       unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
+       unsigned long timeout;
+
+       DECLARE_WAITQUEUE(myself, current);
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       add_wait_queue(&hp->emptyq, &myself);
+
+       for (;;) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               if (hp->n_outbuf <= 0)
+                       break;
+               timeout = end_jiffies - jiffies;
+               if (time_after(jiffies, end_jiffies))
+                       break;
+               schedule_timeout(timeout);
+       }
+       remove_wait_queue(&hp->emptyq, &myself);
+       set_current_state(TASK_RUNNING);
+
+       /* 'writer' could still be pending if it didn't see n_outbuf = 0 yet */
+       cancel_delayed_work(&hp->writer);
+       flush_scheduled_work();
+
+       /*
+        * it's also possible that our timeout expired and hvsi_write_worker
+        * didn't manage to push outbuf. poof.
+        */
+       hp->n_outbuf = 0;
+}
+
+static void hvsi_close(struct tty_struct *tty, struct file *filp)
+{
+       struct hvsi_struct *hp = tty->driver_data;
+       unsigned long flags;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       if (tty_hung_up_p(filp))
+               return;
+
+       spin_lock_irqsave(&hp->lock, flags);
+
+       if (--hp->count == 0) {
+               hp->tty = NULL;
+               hp->inbuf_end = hp->inbuf; /* discard remaining partial packets */
+
+               /* only close down connection if it is not the console */
+               if (!(hp->flags & HVSI_CONSOLE)) {
+                       h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE); /* no more irqs */
+                       __set_state(hp, HVSI_CLOSED);
+                       /*
+                        * any data delivered to the tty layer after this will be
+                        * discarded (except for XON/XOFF)
+                        */
+                       tty->closing = 1;
+
+                       spin_unlock_irqrestore(&hp->lock, flags);
+
+                       /* let any existing irq handlers finish. no more will start. */
+                       synchronize_irq(hp->virq);
+
+                       /* hvsi_write_worker will re-schedule until outbuf is empty. */
+                       hvsi_flush_output(hp);
+
+                       /* tell FSP to stop sending data */
+                       hvsi_close_protocol(hp);
+
+                       /*
+                        * drain anything FSP is still in the middle of sending, and let
+                        * hvsi_handshake drain the rest on the next open.
+                        */
+                       hvsi_drain_input(hp);
+
+                       spin_lock_irqsave(&hp->lock, flags);
+               }
+       } else if (hp->count < 0)
+               printk(KERN_ERR "hvsi_close %lu: oops, count is %d\n",
+                      hp - hvsi_ports, hp->count);
+
+       spin_unlock_irqrestore(&hp->lock, flags);
+}
+
+static void hvsi_hangup(struct tty_struct *tty)
+{
+       struct hvsi_struct *hp = tty->driver_data;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       hp->count = 0;
+       hp->tty = NULL;
+}
+
+/* called with hp->lock held */
+static void hvsi_push(struct hvsi_struct *hp)
+{
+       int n;
+
+       if (hp->n_outbuf <= 0)
+               return;
+
+       n = hvsi_put_chars(hp, hp->outbuf, hp->n_outbuf);
+       if (n != 0) {
+               /*
+                * either all data was sent or there was an error, and we throw away
+                * data on error.
+                */
+               hp->n_outbuf = 0;
+       }
+}
+
+/* hvsi_write_worker will keep rescheduling itself until outbuf is empty */
+static void hvsi_write_worker(void *arg)
+{
+       struct hvsi_struct *hp = (struct hvsi_struct *)arg;
+       unsigned long flags;
+#ifdef DEBUG
+       static long start_j = 0;
+
+       if (start_j == 0)
+               start_j = jiffies;
+#endif /* DEBUG */
+
+       spin_lock_irqsave(&hp->lock, flags);
+
+       hvsi_push(hp);
+       if (hp->n_outbuf > 0)
+               schedule_delayed_work(&hp->writer, 10);
+       else {
+#ifdef DEBUG
+               pr_debug("%s: outbuf emptied after %li jiffies\n", __FUNCTION__,
+                               jiffies - start_j);
+               start_j = 0;
+#endif /* DEBUG */
+               wake_up_all(&hp->emptyq);
+               if (test_bit(TTY_DO_WRITE_WAKEUP, &hp->tty->flags)
+                               && hp->tty->ldisc.write_wakeup)
+                       hp->tty->ldisc.write_wakeup(hp->tty);
+               wake_up_interruptible(&hp->tty->write_wait);
+       }
+
+       spin_unlock_irqrestore(&hp->lock, flags);
+}
+
+static int hvsi_write_room(struct tty_struct *tty)
+{
+       struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+
+       return N_OUTBUF - hp->n_outbuf;
+}
+
+static int hvsi_chars_in_buffer(struct tty_struct *tty)
+{
+       struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+
+       return hp->n_outbuf;
+}
+
+static int hvsi_write(struct tty_struct *tty, int from_user,
+                    const unsigned char *buf, int count)
+{
+       struct hvsi_struct *hp = tty->driver_data;
+       const char *source = buf;
+       char *kbuf = NULL;
+       unsigned long flags;
+       int total = 0;
+       int origcount = count;
+
+       if (from_user) {
+               kbuf = kmalloc(count, GFP_KERNEL);
+               if (kbuf == NULL)
+                       return -ENOMEM;
+               if (copy_from_user(kbuf, buf, count)) {
+                       kfree(kbuf);
+                       return -EFAULT;
+               }
+               source = kbuf;
+       }
+
+       spin_lock_irqsave(&hp->lock, flags);
+
+       if (!is_open(hp)) {
+               /* we're either closing or not yet open; don't accept data */
+               pr_debug("%s: not open\n", __FUNCTION__);
+               goto out;
+       }
+
+       /*
+        * when the hypervisor buffer (16K) fills, data will stay in hp->outbuf
+        * and hvsi_write_worker will be scheduled. subsequent hvsi_write() calls
+        * will see there is no room in outbuf and return.
+        */
+       while ((count > 0) && (hvsi_write_room(hp->tty) > 0)) {
+               int chunksize = min(count, hvsi_write_room(hp->tty));
+
+               BUG_ON(hp->n_outbuf < 0);
+               memcpy(hp->outbuf + hp->n_outbuf, source, chunksize);
+               hp->n_outbuf += chunksize;
+
+               total += chunksize;
+               source += chunksize;
+               count -= chunksize;
+               hvsi_push(hp);
+       }
+
+       if (hp->n_outbuf > 0) {
+               /*
+                * we weren't able to write it all to the hypervisor.
+                * schedule another push attempt.
+                */
+               schedule_delayed_work(&hp->writer, 10);
+       }
+
+out:
+       spin_unlock_irqrestore(&hp->lock, flags);
+
+       if (from_user)
+               kfree(kbuf);
+
+       if (total != origcount)
+               pr_debug("%s: wanted %i, only wrote %i\n", __FUNCTION__, origcount,
+                       total);
+
+       return total;
+}
+
+/*
+ * I have never seen throttle or unthrottle called, so this little throttle
+ * buffering scheme may or may not work.
+ */
+static void hvsi_throttle(struct tty_struct *tty)
+{
+       struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE);
+}
+
+static void hvsi_unthrottle(struct tty_struct *tty)
+{
+       struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+       unsigned long flags;
+       int shouldflip = 0;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       spin_lock_irqsave(&hp->lock, flags);
+       if (hp->n_throttle) {
+               hvsi_send_overflow(hp);
+               shouldflip = 1;
+       }
+       spin_unlock_irqrestore(&hp->lock, flags);
+
+       if (shouldflip)
+               tty_flip_buffer_push(hp->tty);
+
+       h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
+}
+
+static int hvsi_tiocmget(struct tty_struct *tty, struct file *file)
+{
+       struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+
+       hvsi_get_mctrl(hp);
+       return hp->mctrl;
+}
+
+static int hvsi_tiocmset(struct tty_struct *tty, struct file *file,
+               unsigned int set, unsigned int clear)
+{
+       struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+       unsigned long flags;
+       uint16_t new_mctrl;
+
+       /* we can only alter DTR */
+       clear &= TIOCM_DTR;
+       set &= TIOCM_DTR;
+
+       spin_lock_irqsave(&hp->lock, flags);
+
+       new_mctrl = (hp->mctrl & ~clear) | set;
+
+       if (hp->mctrl != new_mctrl) {
+               hvsi_set_mctrl(hp, new_mctrl);
+               hp->mctrl = new_mctrl;
+       }
+       spin_unlock_irqrestore(&hp->lock, flags);
+
+       return 0;
+}
+
+
+static struct tty_operations hvsi_ops = {
+       .open = hvsi_open,
+       .close = hvsi_close,
+       .write = hvsi_write,
+       .hangup = hvsi_hangup,
+       .write_room = hvsi_write_room,
+       .chars_in_buffer = hvsi_chars_in_buffer,
+       .throttle = hvsi_throttle,
+       .unthrottle = hvsi_unthrottle,
+       .tiocmget = hvsi_tiocmget,
+       .tiocmset = hvsi_tiocmset,
+};
+
+static int __init hvsi_init(void)
+{
+       int i;
+
+       hvsi_driver = alloc_tty_driver(hvsi_count);
+       if (!hvsi_driver)
+               return -ENOMEM;
+
+       hvsi_driver->owner = THIS_MODULE;
+       hvsi_driver->devfs_name = "hvsi/";
+       hvsi_driver->driver_name = "hvsi";
+       hvsi_driver->name = "hvsi";
+       hvsi_driver->major = HVSI_MAJOR;
+       hvsi_driver->minor_start = HVSI_MINOR;
+       hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM;
+       hvsi_driver->init_termios = tty_std_termios;
+       hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+       hvsi_driver->flags = TTY_DRIVER_REAL_RAW;
+       tty_set_operations(hvsi_driver, &hvsi_ops);
+
+       for (i=0; i < hvsi_count; i++) {
+               struct hvsi_struct *hp = &hvsi_ports[i];
+               int ret = 1;
+
+               ret = request_irq(hp->virq, hvsi_interrupt, SA_INTERRUPT, "hvsi", hp);
+               if (ret)
+                       printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n",
+                               hp->virq, ret);
+       }
+       hvsi_wait = wait_for_state; /* irqs active now */
+
+       if (tty_register_driver(hvsi_driver))
+               panic("Couldn't register hvsi console driver\n");
+
+       printk(KERN_INFO "HVSI: registered %i devices\n", hvsi_count);
+
+       return 0;
+}
+device_initcall(hvsi_init);
+
+/***** console (not tty) code: *****/
+
+static void hvsi_console_print(struct console *console, const char *buf,
+               unsigned int count)
+{
+       struct hvsi_struct *hp = &hvsi_ports[console->index];
+       char c[HVSI_MAX_OUTGOING_DATA] __ALIGNED__;
+       unsigned int i = 0, n = 0;
+       int ret, donecr = 0;
+
+       mb();
+       if (!is_open(hp))
+               return;
+
+       /*
+        * ugh, we have to translate LF -> CRLF ourselves, in place.
+        * copied from hvc_console.c:
+        */
+       while (count > 0 || i > 0) {
+               if (count > 0 && i < sizeof(c)) {
+                       if (buf[n] == '\n' && !donecr) {
+                               c[i++] = '\r';
+                               donecr = 1;
+                       } else {
+                               c[i++] = buf[n++];
+                               donecr = 0;
+                               --count;
+                       }
+               } else {
+                       ret = hvsi_put_chars(hp, c, i);
+                       if (ret < 0)
+                               i = 0;
+                       i -= ret;
+               }
+       }
+}
+
+static struct tty_driver *hvsi_console_device(struct console *console,
+       int *index)
+{
+       *index = console->index;
+       return hvsi_driver;
+}
+
+static int __init hvsi_console_setup(struct console *console, char *options)
+{
+       struct hvsi_struct *hp = &hvsi_ports[console->index];
+       int ret;
+
+       if (console->index < 0 || console->index >= hvsi_count)
+               return -1;
+
+       /* give the FSP a chance to change the baud rate when we re-open */
+       hvsi_close_protocol(hp);
+
+       ret = hvsi_handshake(hp);
+       if (ret < 0)
+               return ret;
+
+       ret = hvsi_get_mctrl(hp);
+       if (ret < 0)
+               return ret;
+
+       ret = hvsi_set_mctrl(hp, hp->mctrl | TIOCM_DTR);
+       if (ret < 0)
+               return ret;
+
+       hp->flags |= HVSI_CONSOLE;
+
+       return 0;
+}
+
+static struct console hvsi_con_driver = {
+       .name           = "hvsi",
+       .write          = hvsi_console_print,
+       .device         = hvsi_console_device,
+       .setup          = hvsi_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = -1,
+};
+
+static int __init hvsi_console_init(void)
+{
+       struct device_node *vty;
+
+       hvsi_wait = poll_for_state; /* no irqs yet; must poll */
+
+       /* search device tree for vty nodes */
+       for (vty = of_find_compatible_node(NULL, "serial", "hvterm-protocol");
+                       vty != NULL;
+                       vty = of_find_compatible_node(vty, "serial", "hvterm-protocol")) {
+               struct hvsi_struct *hp;
+               uint32_t *vtermno;
+               uint32_t *irq;
+
+               vtermno = (uint32_t *)get_property(vty, "reg", NULL);
+               irq = (uint32_t *)get_property(vty, "interrupts", NULL);
+               if (!vtermno || !irq)
+                       continue;
+
+               if (hvsi_count >= MAX_NR_HVSI_CONSOLES) {
+                       of_node_put(vty);
+                       break;
+               }
+
+               hp = &hvsi_ports[hvsi_count];
+               INIT_WORK(&hp->writer, hvsi_write_worker, hp);
+               init_waitqueue_head(&hp->emptyq);
+               init_waitqueue_head(&hp->stateq);
+               hp->lock = SPIN_LOCK_UNLOCKED;
+               hp->index = hvsi_count;
+               hp->inbuf_end = hp->inbuf;
+               hp->state = HVSI_CLOSED;
+               hp->vtermno = *vtermno;
+               hp->virq = virt_irq_create_mapping(irq[0]);
+               if (hp->virq == NO_IRQ) {
+                       printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
+                               __FUNCTION__, hp->virq);
+                       continue;
+               } else
+                       hp->virq = irq_offset_up(hp->virq);
+
+               hvsi_count++;
+       }
+
+       if (hvsi_count)
+               register_console(&hvsi_con_driver);
+       return 0;
+}
+console_initcall(hvsi_console_init);
index 8d2b379..9d67b26 100644 (file)
@@ -49,6 +49,9 @@ typedef struct
        short irq[IP2_MAX_BOARDS]; 
        unsigned short addr[IP2_MAX_BOARDS];
        int type[IP2_MAX_BOARDS];
+#ifdef CONFIG_PCI
+       struct pci_dev *pci_dev[IP2_MAX_BOARDS];
+#endif
 } ip2config_t;
 
 #endif
index b632538..655a172 100644 (file)
@@ -57,4 +57,11 @@ config IPMI_WATCHDOG
        help
          This enables the IPMI watchdog timer.
 
+config IPMI_POWEROFF
+       tristate 'IPMI Poweroff'
+       depends on IPMI_HANDLER
+       help
+         This enables a function to power off the system with IPMI if
+        the IPMI management controller is capable of this.
+
 endmenu
index b7d8230..553f0a4 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o
 obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
 obj-$(CONFIG_IPMI_SI) += ipmi_si.o
 obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
+obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o
 
 ipmi_si.o:     $(ipmi_si-objs)
        $(LD) -r -o $@ $(ipmi_si-objs)
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
new file mode 100644 (file)
index 0000000..ade8729
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * ipmi_poweroff.c
+ *
+ * MontaVista IPMI Poweroff extension to sys_reboot
+ *
+ * Author: MontaVista Software, Inc.
+ *         Steven Dake <sdake@mvista.com>
+ *         Corey Minyard <cminyard@mvista.com>
+ *         source@mvista.com
+ *
+ * Copyright 2002,2004 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 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 <asm/semaphore.h>
+#include <linux/kdev_t.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/ipmi.h>
+#include <linux/ipmi_smi.h>
+
+#define PFX "IPMI poweroff: "
+#define IPMI_POWEROFF_VERSION  "v33"
+
+/* Where to we insert our poweroff function? */
+extern void (*pm_power_off)(void);
+
+/* Stuff from the get device id command. */
+unsigned int mfg_id;
+unsigned int prod_id;
+unsigned char capabilities;
+
+/* We use our own messages for this operation, we don't let the system
+   allocate them, since we may be in a panic situation.  The whole
+   thing is single-threaded, anyway, so multiple messages are not
+   required. */
+static void dummy_smi_free(struct ipmi_smi_msg *msg)
+{
+}
+static void dummy_recv_free(struct ipmi_recv_msg *msg)
+{
+}
+static struct ipmi_smi_msg halt_smi_msg =
+{
+       .done = dummy_smi_free
+};
+static struct ipmi_recv_msg halt_recv_msg =
+{
+       .done = dummy_recv_free
+};
+
+
+/*
+ * Code to send a message and wait for the reponse.
+ */
+
+static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
+{
+       struct semaphore *sem = recv_msg->user_msg_data;
+
+       if (sem)
+               up(sem);
+}
+
+static struct ipmi_user_hndl ipmi_poweroff_handler =
+{
+       .ipmi_recv_hndl = receive_handler
+};
+
+
+static int ipmi_request_wait_for_response(ipmi_user_t            user,
+                                         struct ipmi_addr       *addr,
+                                         struct kernel_ipmi_msg *send_msg)
+{
+       int              rv;
+       struct semaphore sem;
+
+       sema_init (&sem, 0);
+
+       rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &sem,
+                                     &halt_smi_msg, &halt_recv_msg, 0);
+       if (rv)
+               return rv;
+
+       down (&sem);
+
+       return halt_recv_msg.msg.data[0];
+}
+
+/* We are in run-to-completion mode, no semaphore is desired. */
+static int ipmi_request_in_rc_mode(ipmi_user_t            user,
+                                  struct ipmi_addr       *addr,
+                                  struct kernel_ipmi_msg *send_msg)
+{
+       int              rv;
+
+       rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
+                                     &halt_smi_msg, &halt_recv_msg, 0);
+       if (rv)
+               return rv;
+
+       return halt_recv_msg.msg.data[0];
+}
+
+/*
+ * ATCA Support
+ */
+
+#define IPMI_NETFN_ATCA                        0x2c
+#define IPMI_ATCA_SET_POWER_CMD                0x11
+#define IPMI_ATCA_GET_ADDR_INFO_CMD    0x01
+#define IPMI_PICMG_ID                  0
+
+static int ipmi_atca_detect (ipmi_user_t user)
+{
+       struct ipmi_system_interface_addr smi_addr;
+       struct kernel_ipmi_msg            send_msg;
+       int                               rv;
+       unsigned char                     data[1];
+
+        /*
+         * Configure IPMI address for local access
+         */
+        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        smi_addr.channel = IPMI_BMC_CHANNEL;
+        smi_addr.lun = 0;
+
+       /*
+        * Use get address info to check and see if we are ATCA
+        */
+       send_msg.netfn = IPMI_NETFN_ATCA;
+       send_msg.cmd = IPMI_ATCA_GET_ADDR_INFO_CMD;
+       data[0] = IPMI_PICMG_ID;
+       send_msg.data = data;
+       send_msg.data_len = sizeof(data);
+       rv = ipmi_request_wait_for_response(user,
+                                           (struct ipmi_addr *) &smi_addr,
+                                           &send_msg);
+       return !rv;
+}
+
+static void ipmi_poweroff_atca (ipmi_user_t user)
+{
+       struct ipmi_system_interface_addr smi_addr;
+       struct kernel_ipmi_msg            send_msg;
+       int                               rv;
+       unsigned char                     data[4];
+
+        /*
+         * Configure IPMI address for local access
+         */
+        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        smi_addr.channel = IPMI_BMC_CHANNEL;
+        smi_addr.lun = 0;
+
+       printk(KERN_INFO PFX "Powering down via ATCA power command\n");
+
+       /*
+        * Power down
+        */
+       send_msg.netfn = IPMI_NETFN_ATCA;
+       send_msg.cmd = IPMI_ATCA_SET_POWER_CMD;
+       data[0] = IPMI_PICMG_ID;
+       data[1] = 0; /* FRU id */
+       data[2] = 0; /* Power Level */
+       data[3] = 0; /* Don't change saved presets */
+       send_msg.data = data;
+       send_msg.data_len = sizeof (data);
+       rv = ipmi_request_in_rc_mode(user,
+                                    (struct ipmi_addr *) &smi_addr,
+                                    &send_msg);
+       if (rv) {
+               printk(KERN_ERR PFX "Unable to send ATCA powerdown message,"
+                      " IPMI error 0x%x\n", rv);
+               goto out;
+       }
+
+ out:
+       return;
+}
+
+/*
+ * CPI1 Support
+ */
+
+#define IPMI_NETFN_OEM_1                               0xf8
+#define OEM_GRP_CMD_SET_RESET_STATE            0x84
+#define OEM_GRP_CMD_SET_POWER_STATE            0x82
+#define IPMI_NETFN_OEM_8                               0xf8
+#define OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL       0x80
+#define OEM_GRP_CMD_GET_SLOT_GA                        0xa3
+#define IPMI_NETFN_SENSOR_EVT                  0x10
+#define IPMI_CMD_GET_EVENT_RECEIVER            0x01
+
+#define IPMI_CPI1_PRODUCT_ID           0x000157
+#define IPMI_CPI1_MANUFACTURER_ID      0x0108
+
+static int ipmi_cpi1_detect (ipmi_user_t user)
+{
+       return ((mfg_id == IPMI_CPI1_MANUFACTURER_ID)
+               && (prod_id == IPMI_CPI1_PRODUCT_ID));
+}
+
+static void ipmi_poweroff_cpi1 (ipmi_user_t user)
+{
+       struct ipmi_system_interface_addr smi_addr;
+       struct ipmi_ipmb_addr             ipmb_addr;
+       struct kernel_ipmi_msg            send_msg;
+       int                               rv;
+       unsigned char                     data[1];
+       int                               slot;
+       unsigned char                     hotswap_ipmb;
+       unsigned char                     aer_addr;
+       unsigned char                     aer_lun;
+
+        /*
+         * Configure IPMI address for local access
+         */
+        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        smi_addr.channel = IPMI_BMC_CHANNEL;
+        smi_addr.lun = 0;
+
+       printk(KERN_INFO PFX "Powering down via CPI1 power command\n");
+
+       /*
+        * Get IPMI ipmb address
+        */
+       send_msg.netfn = IPMI_NETFN_OEM_8 >> 2;
+       send_msg.cmd = OEM_GRP_CMD_GET_SLOT_GA;
+       send_msg.data = NULL;
+       send_msg.data_len = 0;
+       rv = ipmi_request_in_rc_mode(user,
+                                    (struct ipmi_addr *) &smi_addr,
+                                    &send_msg);
+       if (rv)
+               goto out;
+       slot = halt_recv_msg.msg.data[1];
+       hotswap_ipmb = (slot > 9) ? (0xb0 + 2 * slot) : (0xae + 2 * slot);
+
+       /*
+        * Get active event receiver
+        */
+       send_msg.netfn = IPMI_NETFN_SENSOR_EVT >> 2;
+       send_msg.cmd = IPMI_CMD_GET_EVENT_RECEIVER;
+       send_msg.data = NULL;
+       send_msg.data_len = 0;
+       rv = ipmi_request_in_rc_mode(user,
+                                    (struct ipmi_addr *) &smi_addr,
+                                    &send_msg);
+       if (rv)
+               goto out;
+       aer_addr = halt_recv_msg.msg.data[1];
+       aer_lun = halt_recv_msg.msg.data[2];
+
+       /*
+        * Setup IPMB address target instead of local target
+        */
+       ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE;
+       ipmb_addr.channel = 0;
+       ipmb_addr.slave_addr = aer_addr;
+       ipmb_addr.lun = aer_lun;
+
+       /*
+        * Send request hotswap control to remove blade from dpv
+        */
+       send_msg.netfn = IPMI_NETFN_OEM_8 >> 2;
+       send_msg.cmd = OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL;
+       send_msg.data = &hotswap_ipmb;
+       send_msg.data_len = 1;
+       ipmi_request_in_rc_mode(user,
+                               (struct ipmi_addr *) &ipmb_addr,
+                               &send_msg);
+
+       /*
+        * Set reset asserted
+        */
+       send_msg.netfn = IPMI_NETFN_OEM_1 >> 2;
+       send_msg.cmd = OEM_GRP_CMD_SET_RESET_STATE;
+       send_msg.data = data;
+       data[0] = 1; /* Reset asserted state */
+       send_msg.data_len = 1;
+       rv = ipmi_request_in_rc_mode(user,
+                                    (struct ipmi_addr *) &smi_addr,
+                                    &send_msg);
+       if (rv)
+               goto out;
+
+       /*
+        * Power down
+        */
+       send_msg.netfn = IPMI_NETFN_OEM_1 >> 2;
+       send_msg.cmd = OEM_GRP_CMD_SET_POWER_STATE;
+       send_msg.data = data;
+       data[0] = 1; /* Power down state */
+       send_msg.data_len = 1;
+       rv = ipmi_request_in_rc_mode(user,
+                                    (struct ipmi_addr *) &smi_addr,
+                                    &send_msg);
+       if (rv)
+               goto out;
+
+ out:
+       return;
+}
+
+/*
+ * Standard chassis support
+ */
+
+#define IPMI_NETFN_CHASSIS_REQUEST     0
+#define IPMI_CHASSIS_CONTROL_CMD       0x02
+
+static int ipmi_chassis_detect (ipmi_user_t user)
+{
+       /* Chassis support, use it. */
+       return (capabilities & 0x80);
+}
+
+static void ipmi_poweroff_chassis (ipmi_user_t user)
+{
+       struct ipmi_system_interface_addr smi_addr;
+       struct kernel_ipmi_msg            send_msg;
+       int                               rv;
+       unsigned char                     data[1];
+
+        /*
+         * Configure IPMI address for local access
+         */
+        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        smi_addr.channel = IPMI_BMC_CHANNEL;
+        smi_addr.lun = 0;
+
+       printk(KERN_INFO PFX "Powering down via IPMI chassis control command\n");
+
+       /*
+        * Power down
+        */
+       send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
+       send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
+       data[0] = 0; /* Power down */
+       send_msg.data = data;
+       send_msg.data_len = sizeof(data);
+       rv = ipmi_request_in_rc_mode(user,
+                                    (struct ipmi_addr *) &smi_addr,
+                                    &send_msg);
+       if (rv) {
+               printk(KERN_ERR PFX "Unable to send chassis powerdown message,"
+                      " IPMI error 0x%x\n", rv);
+               goto out;
+       }
+
+ out:
+       return;
+}
+
+
+/* Table of possible power off functions. */
+struct poweroff_function {
+       char *platform_type;
+       int  (*detect)(ipmi_user_t user);
+       void (*poweroff_func)(ipmi_user_t user);
+};
+
+static struct poweroff_function poweroff_functions[] = {
+       { "ATCA",    ipmi_atca_detect, ipmi_poweroff_atca },
+       { "CPI1",    ipmi_cpi1_detect, ipmi_poweroff_cpi1 },
+       /* Chassis should generally be last, other things should override
+          it. */
+       { "chassis", ipmi_chassis_detect, ipmi_poweroff_chassis },
+};
+#define NUM_PO_FUNCS (sizeof(poweroff_functions) \
+                     / sizeof(struct poweroff_function))
+
+
+/* Our local state. */
+static int ready = 0;
+static ipmi_user_t ipmi_user;
+static void (*specific_poweroff_func)(ipmi_user_t user) = NULL;
+
+/* Holds the old poweroff function so we can restore it on removal. */
+static void (*old_poweroff_func)(void);
+
+
+/* Called on a powerdown request. */
+static void ipmi_poweroff_function (void)
+{
+       if (!ready)
+               return;
+
+       /* Use run-to-completion mode, since interrupts may be off. */
+       ipmi_user_set_run_to_completion(ipmi_user, 1);
+       specific_poweroff_func(ipmi_user);
+       ipmi_user_set_run_to_completion(ipmi_user, 0);
+}
+
+/* Wait for an IPMI interface to be installed, the first one installed
+   will be grabbed by this code and used to perform the powerdown. */
+static void ipmi_po_new_smi(int if_num)
+{
+       struct ipmi_system_interface_addr smi_addr;
+       struct kernel_ipmi_msg            send_msg;
+       int                               rv;
+       int                               i;
+
+       if (ready)
+               return;
+
+       rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, &ipmi_user);
+       if (rv) {
+               printk(KERN_ERR PFX "could not create IPMI user, error %d\n",
+                      rv);
+               return;
+       }
+
+        /*
+         * Do a get device ide and store some results, since this is
+        * used by several functions.
+         */
+        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        smi_addr.channel = IPMI_BMC_CHANNEL;
+        smi_addr.lun = 0;
+
+       send_msg.netfn = IPMI_NETFN_APP_REQUEST;
+       send_msg.cmd = IPMI_GET_DEVICE_ID_CMD;
+       send_msg.data = NULL;
+       send_msg.data_len = 0;
+       rv = ipmi_request_wait_for_response(ipmi_user,
+                                           (struct ipmi_addr *) &smi_addr,
+                                           &send_msg);
+       if (rv) {
+               printk(KERN_ERR PFX "Unable to send IPMI get device id info,"
+                      " IPMI error 0x%x\n", rv);
+               goto out_err;
+       }
+
+       if (halt_recv_msg.msg.data_len < 12) {
+               printk(KERN_ERR PFX "(chassis) IPMI get device id info too,"
+                      " short, was %d bytes, needed %d bytes\n",
+                      halt_recv_msg.msg.data_len, 12);
+               goto out_err;
+       }
+
+       mfg_id = (halt_recv_msg.msg.data[7]
+                 | (halt_recv_msg.msg.data[8] << 8)
+                 | (halt_recv_msg.msg.data[9] << 16));
+       prod_id = (halt_recv_msg.msg.data[10]
+                  | (halt_recv_msg.msg.data[11] << 8));
+       capabilities = halt_recv_msg.msg.data[6];
+
+
+       /* Scan for a poweroff method */
+       for (i=0; i<NUM_PO_FUNCS; i++) {
+               if (poweroff_functions[i].detect(ipmi_user))
+                       goto found;
+       }
+
+ out_err:
+       printk(KERN_ERR PFX "Unable to find a poweroff function that"
+              " will work, giving up\n");
+       ipmi_destroy_user(ipmi_user);
+       return;
+
+ found:
+       printk(KERN_INFO PFX "Found a %s style poweroff function\n",
+              poweroff_functions[i].platform_type);
+       specific_poweroff_func = poweroff_functions[i].poweroff_func;
+       old_poweroff_func = pm_power_off;
+       pm_power_off = ipmi_poweroff_function;
+       ready = 1;
+}
+
+static void ipmi_po_smi_gone(int if_num)
+{
+       /* This can never be called, because once poweroff driver is
+          registered, the interface can't go away until the power
+          driver is unregistered. */
+}
+
+static struct ipmi_smi_watcher smi_watcher =
+{
+       .owner    = THIS_MODULE,
+       .new_smi  = ipmi_po_new_smi,
+       .smi_gone = ipmi_po_smi_gone
+};
+
+
+/*
+ * Startup and shutdown functions.
+ */
+static int ipmi_poweroff_init (void)
+{
+       int rv;
+
+       printk ("Copyright (C) 2004 MontaVista Software -"
+               " IPMI Powerdown via sys_reboot version "
+               IPMI_POWEROFF_VERSION ".\n");
+
+       rv = ipmi_smi_watcher_register(&smi_watcher);
+       if (rv)
+               printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
+
+       return rv;
+}
+
+#ifdef MODULE
+static __exit void ipmi_poweroff_cleanup(void)
+{
+       int rv;
+
+       ipmi_smi_watcher_unregister(&smi_watcher);
+
+       if (ready) {
+               rv = ipmi_destroy_user(ipmi_user);
+               if (rv)
+                       printk(KERN_ERR PFX "could not cleanup the IPMI"
+                              " user: 0x%x\n", rv);
+               pm_power_off = old_poweroff_func;
+       }
+}
+module_exit(ipmi_poweroff_cleanup);
+#endif
+
+module_init(ipmi_poweroff_init);
+MODULE_LICENSE("GPL");
index f350655..a0212b0 100644 (file)
@@ -52,6 +52,9 @@ struct si_sm_io
            state machine shouldn't touch these. */
        void *info;
        void *addr;
+       int  regspacing;
+       int  regsize;
+       int  regshift;
 };
 
 /* Results of SMI events. */
index e865044..b454bf2 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/miscdevice.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
+#include <linux/delay.h>
 #include <linux/ioport.h>
 
 #include <asm/uaccess.h>
@@ -389,7 +390,7 @@ static void isicom_tx(unsigned long _data)
                
                tty = port->tty;
                save_flags(flags); cli();
-               txcount = MIN(TX_SIZE, port->xmit_cnt);
+               txcount = min_t(short, TX_SIZE, port->xmit_cnt);
                if ((txcount <= 0) || tty->stopped || tty->hw_stopped) {
                        restore_flags(flags);
                        continue;
@@ -421,7 +422,7 @@ static void isicom_tx(unsigned long _data)
                residue = NO;
                wrd = 0;                        
                while (1) {
-                       cnt = MIN(txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
+                       cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
                        if (residue == YES) {
                                residue = NO;
                                if (cnt > 0) {
@@ -484,10 +485,8 @@ static void isicom_bottomhalf(void * data)
        
        if (!tty)
                return;
-       
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+
+       tty_wakeup(tty);        
        wake_up_interruptible(&tty->write_wait);
 }              
                
@@ -650,7 +649,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id,
                }        
        }
        else {                          /* Data   Packet */
-               count = MIN(byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
+               count = min_t(unsigned short, byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
 #ifdef ISICOM_DEBUG
                printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n", 
                                        count, byte_count);
@@ -1119,8 +1118,8 @@ static void isicom_close(struct tty_struct * tty, struct file * filp)
        isicom_shutdown_port(port);
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+               
+       tty_ldisc_flush(tty);
        tty->closing = 0;
        port->tty = NULL;
        if (port->blocked_open) {
@@ -1163,8 +1162,8 @@ static int isicom_write(struct tty_struct * tty, int from_user,
        save_flags(flags);
        while(1) {      
                cli();
-               cnt = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-                       SERIAL_XMIT_SIZE - port->xmit_head));
+               cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                                           SERIAL_XMIT_SIZE - port->xmit_head));
                if (cnt <= 0) 
                        break;
                
@@ -1180,8 +1179,8 @@ static int isicom_write(struct tty_struct * tty, int from_user,
                                return -EFAULT;
                        }
                        cli();
-                       cnt = MIN(cnt, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-                       SERIAL_XMIT_SIZE - port->xmit_head));
+                       cnt = min_t(int, cnt, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                                                 SERIAL_XMIT_SIZE - port->xmit_head));
                        memcpy(port->xmit_buf + port->xmit_head, tmp_buf, cnt);
                }       
                else
@@ -1563,9 +1562,7 @@ static void isicom_flush_buffer(struct tty_struct * tty)
        restore_flags(flags);
        
        wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
 }
 
 
@@ -1906,8 +1903,7 @@ int init_module(void)
 void cleanup_module(void)
 {
        re_schedule = 0;
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout(HZ);
+       msleep(1000);
 
 #ifdef ISICOM_DEBUG    
        printk("ISICOM: isicom_tx tx_count = %ld.\n", tx_count);
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
new file mode 100644 (file)
index 0000000..20aa170
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Intel Multimedia Timer device implementation for SGI SN platforms.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2001-2004 Silicon Graphics, Inc.  All rights reserved.
+ *
+ * This driver exports an API that should be supportable by any HPET or IA-PC
+ * multimedia timer.  The code below is currently specific to the SGI Altix
+ * SHub RTC, however.
+ *
+ * 11/01/01 - jbarnes - initial revision
+ * 9/10/04 - Christoph Lameter - remove interrupt support for kernel inclusion
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/ioctl.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/mmtimer.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/clksupport.h>
+
+MODULE_AUTHOR("Jesse Barnes <jbarnes@sgi.com>");
+MODULE_DESCRIPTION("Multimedia timer support");
+MODULE_LICENSE("GPL");
+
+/* name of the device, usually in /dev */
+#define MMTIMER_NAME "mmtimer"
+#define MMTIMER_DESC "IA-PC Multimedia Timer"
+#define MMTIMER_VERSION "1.0"
+
+#define RTC_BITS 55 /* 55 bits for this implementation */
+
+static int mmtimer_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg);
+static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
+
+/*
+ * Period in femtoseconds (10^-15 s)
+ */
+static unsigned long mmtimer_femtoperiod = 0;
+
+static struct file_operations mmtimer_fops = {
+       .owner =        THIS_MODULE,
+       .mmap =         mmtimer_mmap,
+       .ioctl =        mmtimer_ioctl,
+};
+
+/**
+ * mmtimer_ioctl - ioctl interface for /dev/mmtimer
+ * @inode: inode of the device
+ * @file: file structure for the device
+ * @cmd: command to execute
+ * @arg: optional argument to command
+ *
+ * Executes the command specified by @cmd.  Returns 0 for success, < 0 for
+ * failure.
+ *
+ * Valid commands:
+ *
+ * %MMTIMER_GETOFFSET - Should return the offset (relative to the start
+ * of the page where the registers are mapped) for the counter in question.
+ *
+ * %MMTIMER_GETRES - Returns the resolution of the clock in femto (10^-15)
+ * seconds
+ *
+ * %MMTIMER_GETFREQ - Copies the frequency of the clock in Hz to the address
+ * specified by @arg
+ *
+ * %MMTIMER_GETBITS - Returns the number of bits in the clock's counter
+ *
+ * %MMTIMER_MMAPAVAIL - Returns 1 if the registers can be mmap'd into userspace
+ *
+ * %MMTIMER_GETCOUNTER - Gets the current value in the counter and places it
+ * in the address specified by @arg.
+ */
+static int mmtimer_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+       int ret = 0;
+
+       switch (cmd) {
+       case MMTIMER_GETOFFSET: /* offset of the counter */
+               /*
+                * SN RTC registers are on their own 64k page
+                */
+               if(PAGE_SIZE <= (1 << 16))
+                       ret = (((long)RTC_COUNTER_ADDR) & (PAGE_SIZE-1)) / 8;
+               else
+                       ret = -ENOSYS;
+               break;
+
+       case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */
+               if(copy_to_user((unsigned long *)arg, &mmtimer_femtoperiod,
+                               sizeof(unsigned long)))
+                       return -EFAULT;
+               break;
+
+       case MMTIMER_GETFREQ: /* frequency in Hz */
+               if(copy_to_user((unsigned long *)arg,
+                               &sn_rtc_cycles_per_second,
+                               sizeof(unsigned long)))
+                       return -EFAULT;
+               ret = 0;
+               break;
+
+       case MMTIMER_GETBITS: /* number of bits in the clock */
+               ret = RTC_BITS;
+               break;
+
+       case MMTIMER_MMAPAVAIL: /* can we mmap the clock into userspace? */
+               ret = (PAGE_SIZE <= (1 << 16)) ? 1 : 0;
+               break;
+
+       case MMTIMER_GETCOUNTER:
+               if(copy_to_user((unsigned long *)arg, RTC_COUNTER_ADDR,
+                               sizeof(unsigned long)))
+                       return -EFAULT;
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+
+       return ret;
+}
+
+/**
+ * mmtimer_mmap - maps the clock's registers into userspace
+ * @file: file structure for the device
+ * @vma: VMA to map the registers into
+ *
+ * Calls remap_page_range() to map the clock's registers into
+ * the calling process' address space.
+ */
+static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       unsigned long mmtimer_addr;
+
+       if (vma->vm_end - vma->vm_start != PAGE_SIZE)
+               return -EINVAL;
+
+       if (vma->vm_flags & VM_WRITE)
+               return -EPERM;
+
+       if (PAGE_SIZE > (1 << 16))
+               return -ENOSYS;
+
+       vma->vm_flags |= (VM_IO | VM_SHM | VM_LOCKED );
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+       mmtimer_addr = __pa(RTC_COUNTER_ADDR);
+       mmtimer_addr &= ~(PAGE_SIZE - 1);
+       mmtimer_addr &= 0xfffffffffffffffUL;
+
+       if (remap_page_range(vma, vma->vm_start, mmtimer_addr, PAGE_SIZE,
+                            vma->vm_page_prot)) {
+               printk(KERN_ERR "remap_page_range failed in mmtimer.c\n");
+               return -EAGAIN;
+       }
+
+       return 0;
+}
+
+static struct miscdevice mmtimer_miscdev = {
+       SGI_MMTIMER,
+       MMTIMER_NAME,
+       &mmtimer_fops
+};
+
+/**
+ * mmtimer_init - device initialization routine
+ *
+ * Does initial setup for the mmtimer device.
+ */
+static int __init mmtimer_init(void)
+{
+       if (!ia64_platform_is("sn2"))
+               return -1;
+
+       /*
+        * Sanity check the cycles/sec variable
+        */
+       if (sn_rtc_cycles_per_second < 100000) {
+               printk(KERN_ERR "%s: unable to determine clock frequency\n",
+                      MMTIMER_NAME);
+               return -1;
+       }
+
+       mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second /
+                              2) / sn_rtc_cycles_per_second;
+
+       strcpy(mmtimer_miscdev.devfs_name, MMTIMER_NAME);
+       if (misc_register(&mmtimer_miscdev)) {
+               printk(KERN_ERR "%s: failed to register device\n",
+                      MMTIMER_NAME);
+               return -1;
+       }
+
+       printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION,
+              sn_rtc_cycles_per_second/(unsigned long)1E6);
+
+       return 0;
+}
+
+module_init(mmtimer_init);
+
index 0e75a0d..d45d381 100644 (file)
@@ -618,8 +618,8 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
 
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+       tty_ldisc_flush(tty);
+                       
        tty->closing = 0;
        ch->event = 0;
        ch->tty = NULL;
@@ -693,9 +693,7 @@ static void moxa_flush_buffer(struct tty_struct *tty)
        if (ch == NULL)
                return;
        MoxaPortFlushData(ch->port, 1);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup) (tty);
+       tty_wakeup(tty);
        wake_up_interruptible(&tty->write_wait);
 }
 
@@ -954,9 +952,7 @@ static void moxa_poll(unsigned long ignored)
                                if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
                                        if (!tp->stopped) {
                                                ch->statusflags &= ~LOWWAIT;
-                                               if ((tp->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                                                 tp->ldisc.write_wakeup)
-                                                       (tp->ldisc.write_wakeup) (tp);
+                                               tty_wakeup(tp);
                                                wake_up_interruptible(&tp->write_wait);
                                        }
                                }
@@ -1123,9 +1119,7 @@ static void check_xmit_empty(unsigned long data)
        if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
                if (MoxaPortTxQueue(ch->port) == 0) {
                        ch->statusflags &= ~EMPTYWAIT;
-                       if ((ch->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                           ch->tty->ldisc.write_wakeup)
-                               (ch->tty->ldisc.write_wakeup) (ch->tty);
+                       tty_wakeup(ch->tty);
                        wake_up_interruptible(&ch->tty->write_wait);
                        return;
                }
index e75381e..f344ed3 100644 (file)
@@ -60,15 +60,6 @@ static DECLARE_MUTEX(nwflash_sem);
 
 extern spinlock_t gpio_lock;
 
-/*
- * the delay routine - it is often required to let the flash "breeze"...
- */
-void flash_wait(int timeout)
-{
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(timeout);
-}
-
 static int get_flash_id(void)
 {
        volatile unsigned int c1, c2;
@@ -401,7 +392,7 @@ static int erase_block(int nBlock)
        /*
         * wait 10 ms
         */
-       flash_wait(HZ / 100);
+       msleep(10);
 
        /*
         * wait while erasing in process (up to 10 sec)
@@ -409,7 +400,7 @@ static int erase_block(int nBlock)
        timeout = jiffies + 10 * HZ;
        c1 = 0;
        while (!(c1 & 0x80) && time_before(jiffies, timeout)) {
-               flash_wait(HZ / 100);
+               msleep(10);
                /*
                 * read any address
                 */
@@ -440,7 +431,7 @@ static int erase_block(int nBlock)
        /*
         * just to make sure - verify if erased OK...
         */
-       flash_wait(HZ / 100);
+       msleep(10);
 
        pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + (nBlock << 16)));
 
@@ -587,7 +578,7 @@ static int write_block(unsigned long p, const char __user *buf, int count)
                                /*
                                 * wait couple ms
                                 */
-                               flash_wait(HZ / 100);
+                               msleep(10);
                                /*
                                 * red LED == write
                                 */
@@ -612,7 +603,7 @@ static int write_block(unsigned long p, const char __user *buf, int count)
        leds_event(led_amber_off);
        leds_event(led_green_on);
 
-       flash_wait(HZ / 100);
+       msleep(10);
 
        pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));
 
index e804fdc..061237b 100644 (file)
@@ -130,7 +130,6 @@ static struct channel    *digi_channels;
 int pcxx_ncook=sizeof(pcxx_cook);
 int pcxx_nbios=sizeof(pcxx_bios);
 
-#define MIN(a,b)       ((a) < (b) ? (a) : (b))
 #define pcxxassert(x, msg)  if(!(x)) pcxx_error(__LINE__, msg)
 
 #define FEPTIMEOUT 200000  
@@ -206,7 +205,7 @@ static void __exit pcxe_cleanup(void)
 {
 
        unsigned long   flags;
-       int e1, e2;
+       int e1;
 
        printk(KERN_NOTICE "Unloading PC/Xx version %s\n", VERSION);
 
@@ -223,12 +222,6 @@ static void __exit pcxe_cleanup(void)
        restore_flags(flags);
 }
 
-/*
- * pcxe_init() is our init_module():
- */
-module_init(pcxe_init);
-module_cleanup(pcxe_cleanup);
-
 static inline struct channel *chan(register struct tty_struct *tty)
 {
        if (tty) {
@@ -538,28 +531,11 @@ static void pcxe_close(struct tty_struct * tty, struct file * filp)
        
                if(tty->driver->flush_buffer)
                        tty->driver->flush_buffer(tty);
-               if(tty->ldisc.flush_buffer)
-                       tty->ldisc.flush_buffer(tty);
+               tty_ldisc_flush(tty);
                shutdown(info);
                tty->closing = 0;
                info->event = 0;
                info->tty = NULL;
-#ifndef MODULE
-/* ldiscs[] is not available in a MODULE
-** worth noting that while I'm not sure what this hunk of code is supposed
-** to do, it is not present in the serial.c driver.  Hmmm.  If you know,
-** please send me a note.  brian@ilinx.com
-** Don't know either what this is supposed to do christoph@lameter.com.
-*/
-               if(tty->ldisc.num != ldiscs[N_TTY].num) {
-                       if(tty->ldisc.close)
-                               (tty->ldisc.close)(tty);
-                       tty->ldisc = ldiscs[N_TTY];
-                       tty->termios->c_line = N_TTY;
-                       if(tty->ldisc.open)
-                               (tty->ldisc.open)(tty);
-               }
-#endif
                if(info->blocked_open) {
                        if(info->close_delay) {
                                current->state = TASK_INTERRUPTIBLE;
@@ -626,7 +602,7 @@ static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha
                
                tail &= (size - 1);
                stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1);
-               count = MIN(stlen, count);
+               count = min(stlen, count);
                memoff(ch);
                restore_flags(flags);
 
@@ -658,11 +634,11 @@ static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha
                remain = tail - head - 1;
                stlen = remain;
        }
-       count = MIN(remain, count);
+       count = min(remain, count);
 
        txwinon(ch);
        while (count > 0) {
-               stlen = MIN(count, stlen);
+               stlen = min(count, stlen);
                memcpy(ch->txptr + head, buf, stlen);
                buf += stlen;
                count -= stlen;
@@ -800,9 +776,7 @@ static void pcxe_flush_buffer(struct tty_struct *tty)
        memoff(ch);
        restore_flags(flags);
 
-       wake_up_interruptible(&tty->write_wait);
-       if((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
 }
 
 static void pcxe_flush_chars(struct tty_struct *tty)
@@ -1013,9 +987,6 @@ void __init pcxx_setup(char *str, int *ints)
 }
 #endif
 
-module_init(pcxe_init)
-module_exit(pcxe_exit)
-
 static struct tty_operations pcxe_ops = {
        .open = pcxe_open,
        .close = pcxe_close,
@@ -1561,6 +1532,8 @@ cleanup_boards:
        return ret;
 }
 
+module_init(pcxe_init)
+module_exit(pcxe_cleanup)
 
 static void pcxxpoll(unsigned long dummy)
 {
@@ -1675,10 +1648,7 @@ static void doevent(int crd)
                        if (event & LOWTX_IND) {
                                if (ch->statusflags & LOWWAIT) {
                                        ch->statusflags &= ~LOWWAIT;
-                                       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                                               tty->ldisc.write_wakeup)
-                                               (tty->ldisc.write_wakeup)(tty);
-                                       wake_up_interruptible(&tty->write_wait);
+                                       tty_wakeup(tty);
                                }
                        }
 
@@ -1686,10 +1656,7 @@ static void doevent(int crd)
                                ch->statusflags &= ~TXBUSY;
                                if (ch->statusflags & EMPTYWAIT) {
                                        ch->statusflags &= ~EMPTYWAIT;
-                                       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                                               tty->ldisc.write_wakeup)
-                                               (tty->ldisc.write_wakeup)(tty);
-                                       wake_up_interruptible(&tty->write_wait);
+                                       tty_wakeup(tty);
                                }
                        }
                }
@@ -1995,6 +1962,7 @@ static int pcxe_tiocmget(struct tty_struct *tty, struct file *file)
        volatile struct board_chan *bc;
        unsigned long flags;
        int mflag = 0;
+       int mstat;
 
        if(ch)
                bc = ch->brdchan;
@@ -2069,6 +2037,7 @@ static int pcxe_tiocmset(struct tty_struct *tty, struct file *file,
        pcxxparam(tty,ch);
        memoff(ch);
        restore_flags(flags);
+       return 0;
 }
 
 
@@ -2165,8 +2134,7 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file,
                                tty_wait_until_sent(tty, 0);
                        }
                        else {
-                               if(tty->ldisc.flush_buffer)
-                                       tty->ldisc.flush_buffer(tty);
+                               tty_ldisc_flush(tty);
                        }
 
                        /* Fall Thru */
index 26063cb..d53843a 100644 (file)
@@ -16,7 +16,7 @@
  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <asm/hardirq.h>
+#include <linux/interrupt.h>
 
 
 #define disable(oldspl) save_flags (oldspl)
index a11fafb..0cc0237 100644 (file)
@@ -1138,8 +1138,8 @@ static int __init rio_init(void)
       hp->Ivec = pdev->irq;
       if (((1 << hp->Ivec) & rio_irqmask) == 0)
               hp->Ivec = 0;
-      hp->CardP        = (struct DpRam *)
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->CardP        = (struct DpRam *) hp->Caddr;
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy; 
       hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
@@ -1196,8 +1196,8 @@ static int __init rio_init(void)
       if (((1 << hp->Ivec) & rio_irqmask) == 0) 
        hp->Ivec = 0;
       hp->Ivec |= 0x8000; /* Mark as non-sharable */
-      hp->CardP        = (struct DpRam *)
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->CardP        = (struct DpRam *) hp->Caddr;
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy;
       hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
@@ -1242,8 +1242,8 @@ static int __init rio_init(void)
     hp->PaddrP = rio_probe_addrs[i];
     /* There was something about the IRQs of these cards. 'Forget what.--REW */
     hp->Ivec = 0;
-    hp->CardP = (struct DpRam *)
     hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+    hp->CardP = (struct DpRam *) hp->Caddr;
     hp->Type = RIO_AT;
     hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
                              * -- YES! this is now a normal copy. Only the 
index 69108ce..a35ea03 100644 (file)
         ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
         ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
 
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
 #define RS_EVENT_WRITE_WAKEUP  0
 
 static struct riscom_board * IRQ_to_board[16];
@@ -107,7 +103,7 @@ static struct riscom_board rc_board[RC_NBOARD] =  {
 };
 
 static struct riscom_port rc_port[RC_NBOARD * RC_NPORT];
-               
+
 /* RISCom/8 I/O ports addresses (without address translation) */
 static unsigned short rc_ioport[] =  {
 #if 1  
@@ -483,7 +479,7 @@ static inline void rc_transmit(struct riscom_board const * bp)
                                rc_out(bp, CD180_TDR, CD180_C_SBRK);
                                port->COR2 &= ~COR2_ETC;
                        }
-                       count = MIN(port->break_length, 0xff);
+                       count = min_t(int, port->break_length, 0xff);
                        rc_out(bp, CD180_TDR, CD180_C_ESC);
                        rc_out(bp, CD180_TDR, CD180_C_DELAY);
                        rc_out(bp, CD180_TDR, count);
@@ -1127,8 +1123,8 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
        rc_shutdown_port(bp, port);
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+       tty_ldisc_flush(tty);
+
        tty->closing = 0;
        port->event = 0;
        port->tty = NULL;
@@ -1165,8 +1161,8 @@ static int rc_write(struct tty_struct * tty, int from_user,
                down(&tmp_buf_sem);
                while (1) {
                        cli();          
-                       c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-                                          SERIAL_XMIT_SIZE - port->xmit_head));
+                       c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                                                 SERIAL_XMIT_SIZE - port->xmit_head));
                        if (c <= 0)
                                break;
 
@@ -1178,8 +1174,8 @@ static int rc_write(struct tty_struct * tty, int from_user,
                        }
 
                        cli();
-                       c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-                                      SERIAL_XMIT_SIZE - port->xmit_head));
+                       c = min_t(int, c, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                                        SERIAL_XMIT_SIZE - port->xmit_head));
                        memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
                        port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
                        port->xmit_cnt += c;
@@ -1193,8 +1189,8 @@ static int rc_write(struct tty_struct * tty, int from_user,
        } else {
                while (1) {
                        cli();          
-                       c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-                                          SERIAL_XMIT_SIZE - port->xmit_head));
+                       c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                                                 SERIAL_XMIT_SIZE - port->xmit_head));
                        if (c <= 0) {
                                restore_flags(flags);
                                break;
@@ -1301,9 +1297,7 @@ static void rc_flush_buffer(struct tty_struct *tty)
        restore_flags(flags);
        
        wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
 }
 
 static int rc_tiocmget(struct tty_struct *tty, struct file *file)
@@ -1644,9 +1638,7 @@ static void do_softint(void *private_)
                return;
 
        if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   tty->ldisc.write_wakeup)
-                       (tty->ldisc.write_wakeup)(tty);
+               tty_wakeup(tty);
                wake_up_interruptible(&tty->write_wait);
        }
 }
index 9380ff5..8026872 100644 (file)
@@ -1241,10 +1241,6 @@ struct r_port {
 #define TTY_ROCKET_MAJOR       46
 #define CUA_ROCKET_MAJOR       47
 
-#ifndef MIN
-#define MIN(a,b)       ((a) < (b) ? (a) : (b))
-#endif
-
 #ifdef PCI_VENDOR_ID_RP
 #undef PCI_VENDOR_ID_RP
 #undef PCI_DEVICE_ID_RP8OCTA
index f0b9668..6b4e9d1 100644 (file)
@@ -599,10 +599,7 @@ int ch, err, n, p;
                                        
                                /* WakeUp if output buffer runs low */
                                if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
-                                       if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && port->gs.tty->ldisc.write_wakeup){
-                                               (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
-                                       }
-                                       wake_up_interruptible(&port->gs.tty->write_wait);
+                                       tty_wakeup(port->gs.tty);
                                }
                        } // if the port is used
                } // for every port on the board
index 1b51eec..885621e 100644 (file)
 #undef  CYCLOM_16Y_HACK
 #define  CYCLOM_ENABLE_MONITORING
 
-#ifndef MIN
-#define MIN(a,b)       ((a) < (b) ? (a) : (b))
-#endif
-
 #define WAKEUP_CHARS 256
 
 #define STD_COM_FLAGS (0)
@@ -760,11 +756,7 @@ do_softint(void *private_)
        wake_up_interruptible(&info->open_wait);
     }
     if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
-       if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
-       && tty->ldisc.write_wakeup){
-           (tty->ldisc.write_wakeup)(tty);
-       }
-       wake_up_interruptible(&tty->write_wait);
+       tty_wakeup(tty);
     }
 } /* do_softint */
 
@@ -1238,8 +1230,8 @@ cy_write(struct tty_struct * tty, int from_user,
     if (from_user) {
            down(&tmp_buf_sem);
            while (1) {
-                   c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-                                      SERIAL_XMIT_SIZE - info->xmit_head));
+                   c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                                             SERIAL_XMIT_SIZE - info->xmit_head));
                    if (c <= 0)
                            break;
 
@@ -1251,8 +1243,8 @@ cy_write(struct tty_struct * tty, int from_user,
                    }
 
                    local_irq_save(flags);
-                   c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-                                  SERIAL_XMIT_SIZE - info->xmit_head));
+                   c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                                         SERIAL_XMIT_SIZE - info->xmit_head));
                    memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
                    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
                    info->xmit_cnt += c;
@@ -1266,8 +1258,8 @@ cy_write(struct tty_struct * tty, int from_user,
     } else {
            while (1) {
                    local_irq_save(flags);
-                   c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-                                      SERIAL_XMIT_SIZE - info->xmit_head));
+                   c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                                             SERIAL_XMIT_SIZE - info->xmit_head));
                    if (c <= 0) {
                            local_irq_restore(flags);
                            break;
@@ -1343,10 +1335,7 @@ cy_flush_buffer(struct tty_struct *tty)
     local_irq_save(flags);
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
     local_irq_restore(flags);
-    wake_up_interruptible(&tty->write_wait);
-    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-    && tty->ldisc.write_wakeup)
-       (tty->ldisc.write_wakeup)(tty);
+    tty_wakeup(tty);
 } /* cy_flush_buffer */
 
 
@@ -1846,18 +1835,9 @@ cy_close(struct tty_struct * tty, struct file * filp)
     shutdown(info);
     if (tty->driver->flush_buffer)
        tty->driver->flush_buffer(tty);
-    if (tty->ldisc.flush_buffer)
-       tty->ldisc.flush_buffer(tty);
+    tty_ldisc_flush(tty);
     info->event = 0;
     info->tty = 0;
-    if (tty->ldisc.num != ldiscs[N_TTY].num) {
-       if (tty->ldisc.close)
-           (tty->ldisc.close)(tty);
-       tty->ldisc = ldiscs[N_TTY];
-       tty->termios->c_line = N_TTY;
-       if (tty->ldisc.open)
-           (tty->ldisc.open)(tty);
-    }
     if (info->blocked_open) {
        if (info->close_delay) {
            current->state = TASK_INTERRUPTIBLE;
@@ -2379,7 +2359,7 @@ scrn[1] = '\0';
                                        | CyPARITY| CyFRAME| CyOVERRUN;
                /* info->timeout */
 
-               printk("ttyS%1d ", info->line);
+               printk("ttyS%d ", info->line);
                port_num++;info++;
                if(!(port_num & 7)){
                    printk("\n               ");
index 39717ed..50ed6df 100644 (file)
@@ -191,12 +191,9 @@ static inline void transmit_char_pio(struct rs_port *port)
        }
        
         if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
-                if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                    port->gs.tty->ldisc.write_wakeup)
-                        (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
+               tty_wakeup(port->gs.tty);
                 rs_dprintk (TX3912_UART_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
                             port->gs.wakeup_chars); 
-                wake_up_interruptible(&port->gs.tty->write_wait);
                }       
 }
 
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
new file mode 100644 (file)
index 0000000..25917e0
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * SN Platform system controller communication 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.
+ *
+ * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/*
+ * System controller communication driver
+ *
+ * This driver allows a user process to communicate with the system
+ * controller (a.k.a. "IRouter") network in an SGI SN system.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/nodepda.h>
+#include "snsc.h"
+
+#define SYSCTL_BASENAME        "snsc"
+
+#define SCDRV_BUFSZ    2048
+#define SCDRV_TIMEOUT  1000
+
+static irqreturn_t
+scdrv_interrupt(int irq, void *subch_data, struct pt_regs *regs)
+{
+       struct subch_data_s *sd = subch_data;
+       unsigned long flags;
+       int status;
+
+       spin_lock_irqsave(&sd->sd_rlock, flags);
+       spin_lock(&sd->sd_wlock);
+       status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
+
+       if (status > 0) {
+               if (status & SAL_IROUTER_INTR_RECV) {
+                       wake_up(&sd->sd_rq);
+               }
+               if (status & SAL_IROUTER_INTR_XMIT) {
+                       ia64_sn_irtr_intr_disable
+                           (sd->sd_nasid, sd->sd_subch,
+                            SAL_IROUTER_INTR_XMIT);
+                       wake_up(&sd->sd_wq);
+               }
+       }
+       spin_unlock(&sd->sd_wlock);
+       spin_unlock_irqrestore(&sd->sd_rlock, flags);
+       return IRQ_HANDLED;
+}
+
+/*
+ * scdrv_open
+ *
+ * Reserve a subchannel for system controller communication.
+ */
+
+static int
+scdrv_open(struct inode *inode, struct file *file)
+{
+       struct sysctl_data_s *scd;
+       struct subch_data_s *sd;
+       int rv;
+
+       /* look up device info for this device file */
+       scd = container_of(inode->i_cdev, struct sysctl_data_s, scd_cdev);
+
+       /* allocate memory for subchannel data */
+       sd = kmalloc(sizeof (struct subch_data_s), GFP_KERNEL);
+       if (sd == NULL) {
+               printk("%s: couldn't allocate subchannel data\n",
+                      __FUNCTION__);
+               return -ENOMEM;
+       }
+
+       /* initialize subch_data_s fields */
+       memset(sd, 0, sizeof (struct subch_data_s));
+       sd->sd_nasid = scd->scd_nasid;
+       sd->sd_subch = ia64_sn_irtr_open(scd->scd_nasid);
+
+       if (sd->sd_subch < 0) {
+               kfree(sd);
+               printk("%s: couldn't allocate subchannel\n", __FUNCTION__);
+               return -EBUSY;
+       }
+
+       spin_lock_init(&sd->sd_rlock);
+       spin_lock_init(&sd->sd_wlock);
+       init_waitqueue_head(&sd->sd_rq);
+       init_waitqueue_head(&sd->sd_wq);
+       sema_init(&sd->sd_rbs, 1);
+       sema_init(&sd->sd_wbs, 1);
+
+       file->private_data = sd;
+
+       /* hook this subchannel up to the system controller interrupt */
+       rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
+                        SA_SHIRQ | SA_INTERRUPT,
+                        SYSCTL_BASENAME, sd);
+       if (rv) {
+               ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
+               kfree(sd);
+               printk("%s: irq request failed (%d)\n", __FUNCTION__, rv);
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+/*
+ * scdrv_release
+ *
+ * Release a previously-reserved subchannel.
+ */
+
+static int
+scdrv_release(struct inode *inode, struct file *file)
+{
+       struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
+       int rv;
+
+       /* free the interrupt */
+       free_irq(SGI_UART_VECTOR, sd);
+
+       /* ask SAL to close the subchannel */
+       rv = ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
+
+       kfree(sd);
+       return rv;
+}
+
+/*
+ * scdrv_read
+ *
+ * Called to read bytes from the open IRouter pipe.
+ *
+ */
+
+static inline int
+read_status_check(struct subch_data_s *sd, int *len)
+{
+       return ia64_sn_irtr_recv(sd->sd_nasid, sd->sd_subch, sd->sd_rb, len);
+}
+
+static ssize_t
+scdrv_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
+{
+       int status;
+       int len;
+       unsigned long flags;
+       struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
+
+       /* try to get control of the read buffer */
+       if (down_trylock(&sd->sd_rbs)) {
+               /* somebody else has it now;
+                * if we're non-blocking, then exit...
+                */
+               if (file->f_flags & O_NONBLOCK) {
+                       return -EAGAIN;
+               }
+               /* ...or if we want to block, then do so here */
+               if (down_interruptible(&sd->sd_rbs)) {
+                       /* something went wrong with wait */
+                       return -ERESTARTSYS;
+               }
+       }
+
+       /* anything to read? */
+       len = CHUNKSIZE;
+       spin_lock_irqsave(&sd->sd_rlock, flags);
+       status = read_status_check(sd, &len);
+
+       /* if not, and we're blocking I/O, loop */
+       while (status < 0) {
+               DECLARE_WAITQUEUE(wait, current);
+
+               if (file->f_flags & O_NONBLOCK) {
+                       spin_unlock_irqrestore(&sd->sd_rlock, flags);
+                       up(&sd->sd_rbs);
+                       return -EAGAIN;
+               }
+
+               len = CHUNKSIZE;
+               add_wait_queue(&sd->sd_rq, &wait);
+               set_current_state(TASK_INTERRUPTIBLE);
+               spin_unlock_irqrestore(&sd->sd_rlock, flags);
+
+               schedule_timeout(SCDRV_TIMEOUT);
+
+               remove_wait_queue(&sd->sd_rq, &wait);
+               if (signal_pending(current)) {
+                       /* wait was interrupted */
+                       up(&sd->sd_rbs);
+                       return -ERESTARTSYS;
+               }
+
+               spin_lock_irqsave(&sd->sd_rlock, flags);
+               status = read_status_check(sd, &len);
+       }
+       spin_unlock_irqrestore(&sd->sd_rlock, flags);
+
+       if (len > 0) {
+               /* we read something in the last read_status_check(); copy
+                * it out to user space
+                */
+               if (count < len) {
+                       pr_debug("%s: only accepting %d of %d bytes\n",
+                                __FUNCTION__, (int) count, len);
+               }
+               len = min((int) count, len);
+               if (copy_to_user(buf, sd->sd_rb, len))
+                       len = -EFAULT;
+       }
+
+       /* release the read buffer and wake anyone who might be
+        * waiting for it
+        */
+       up(&sd->sd_rbs);
+
+       /* return the number of characters read in */
+       return len;
+}
+
+/*
+ * scdrv_write
+ *
+ * Writes a chunk of an IRouter packet (or other system controller data)
+ * to the system controller.
+ *
+ */
+static inline int
+write_status_check(struct subch_data_s *sd, int count)
+{
+       return ia64_sn_irtr_send(sd->sd_nasid, sd->sd_subch, sd->sd_wb, count);
+}
+
+static ssize_t
+scdrv_write(struct file *file, const char __user *buf,
+           size_t count, loff_t *f_pos)
+{
+       unsigned long flags;
+       int status;
+       struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
+
+       /* try to get control of the write buffer */
+       if (down_trylock(&sd->sd_wbs)) {
+               /* somebody else has it now;
+                * if we're non-blocking, then exit...
+                */
+               if (file->f_flags & O_NONBLOCK) {
+                       return -EAGAIN;
+               }
+               /* ...or if we want to block, then do so here */
+               if (down_interruptible(&sd->sd_wbs)) {
+                       /* something went wrong with wait */
+                       return -ERESTARTSYS;
+               }
+       }
+
+       count = min((int) count, CHUNKSIZE);
+       if (copy_from_user(sd->sd_wb, buf, count)) {
+               up(&sd->sd_wbs);
+               return -EFAULT;
+       }
+
+       /* try to send the buffer */
+       spin_lock_irqsave(&sd->sd_wlock, flags);
+       status = write_status_check(sd, count);
+
+       /* if we failed, and we want to block, then loop */
+       while (status <= 0) {
+               DECLARE_WAITQUEUE(wait, current);
+
+               if (file->f_flags & O_NONBLOCK) {
+                       spin_unlock(&sd->sd_wlock);
+                       up(&sd->sd_wbs);
+                       return -EAGAIN;
+               }
+
+               add_wait_queue(&sd->sd_wq, &wait);
+               set_current_state(TASK_INTERRUPTIBLE);
+               spin_unlock_irqrestore(&sd->sd_wlock, flags);
+
+               schedule_timeout(SCDRV_TIMEOUT);
+
+               remove_wait_queue(&sd->sd_wq, &wait);
+               if (signal_pending(current)) {
+                       /* wait was interrupted */
+                       up(&sd->sd_wbs);
+                       return -ERESTARTSYS;
+               }
+
+               spin_lock_irqsave(&sd->sd_wlock, flags);
+               status = write_status_check(sd, count);
+       }
+       spin_unlock_irqrestore(&sd->sd_wlock, flags);
+
+       /* release the write buffer and wake anyone who's waiting for it */
+       up(&sd->sd_wbs);
+
+       /* return the number of characters accepted (should be the complete
+        * "chunk" as requested)
+        */
+       if ((status >= 0) && (status < count)) {
+               pr_debug("Didn't accept the full chunk; %d of %d\n",
+                        status, (int) count);
+       }
+       return status;
+}
+
+static unsigned int
+scdrv_poll(struct file *file, struct poll_table_struct *wait)
+{
+       unsigned int mask = 0;
+       int status = 0;
+       struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
+       unsigned long flags;
+
+       poll_wait(file, &sd->sd_rq, wait);
+       poll_wait(file, &sd->sd_wq, wait);
+
+       spin_lock_irqsave(&sd->sd_rlock, flags);
+       spin_lock(&sd->sd_wlock);
+       status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
+       spin_unlock(&sd->sd_wlock);
+       spin_unlock_irqrestore(&sd->sd_rlock, flags);
+
+       if (status > 0) {
+               if (status & SAL_IROUTER_INTR_RECV) {
+                       mask |= POLLIN | POLLRDNORM;
+               }
+               if (status & SAL_IROUTER_INTR_XMIT) {
+                       mask |= POLLOUT | POLLWRNORM;
+               }
+       }
+
+       return mask;
+}
+
+static struct file_operations scdrv_fops = {
+       .owner =        THIS_MODULE,
+       .read =         scdrv_read,
+       .write =        scdrv_write,
+       .poll =         scdrv_poll,
+       .open =         scdrv_open,
+       .release =      scdrv_release,
+};
+
+/*
+ * scdrv_init
+ *
+ * Called at boot time to initialize the system controller communication
+ * facility.
+ */
+int __init
+scdrv_init(void)
+{
+       geoid_t geoid;
+       cmoduleid_t cmod;
+       int i;
+       char devname[32];
+       char *devnamep;
+       module_t *m;
+       struct sysctl_data_s *scd;
+       void *salbuf;
+       struct class_simple *snsc_class;
+       dev_t first_dev, dev;
+
+       if (alloc_chrdev_region(&first_dev, 0, (MAX_SLABS*nummodules),
+                               SYSCTL_BASENAME) < 0) {
+               printk("%s: failed to register SN system controller device\n",
+                      __FUNCTION__);
+               return -ENODEV;
+       }
+       snsc_class = class_simple_create(THIS_MODULE, SYSCTL_BASENAME);
+
+       for (cmod = 0; cmod < nummodules; cmod++) {
+               m = sn_modules[cmod];
+               for (i = 0; i <= MAX_SLABS; i++) {
+
+                       if (m->nodes[i] == -1) {
+                               /* node is not alive in module */
+                               continue;
+                       }
+
+                       geoid = m->geoid[i];
+                       devnamep = devname;
+                       format_module_id(devnamep, geo_module(geoid),
+                                        MODULE_FORMAT_BRIEF);
+                       devnamep = devname + strlen(devname);
+                       sprintf(devnamep, "#%d", geo_slab(geoid));
+
+                       /* allocate sysctl device data */
+                       scd = kmalloc(sizeof (struct sysctl_data_s),
+                                     GFP_KERNEL);
+                       if (!scd) {
+                               printk("%s: failed to allocate device info"
+                                      "for %s/%s\n", __FUNCTION__,
+                                      SYSCTL_BASENAME, devname);
+                               continue;
+                       }
+                       memset(scd, 0, sizeof (struct sysctl_data_s));
+
+                       /* initialize sysctl device data fields */
+                       scd->scd_nasid = cnodeid_to_nasid(m->nodes[i]);
+                       if (!(salbuf = kmalloc(SCDRV_BUFSZ, GFP_KERNEL))) {
+                               printk("%s: failed to allocate driver buffer"
+                                      "(%s%s)\n", __FUNCTION__,
+                                      SYSCTL_BASENAME, devname);
+                               kfree(scd);
+                               continue;
+                       }
+
+                       if (ia64_sn_irtr_init(scd->scd_nasid, salbuf,
+                                             SCDRV_BUFSZ) < 0) {
+                               printk
+                                   ("%s: failed to initialize SAL for"
+                                    " system controller communication"
+                                    " (%s/%s): outdated PROM?\n",
+                                    __FUNCTION__, SYSCTL_BASENAME, devname);
+                               kfree(scd);
+                               kfree(salbuf);
+                               continue;
+                       }
+
+                       dev = first_dev + m->nodes[i];
+                       cdev_init(&scd->scd_cdev, &scdrv_fops);
+                       if (cdev_add(&scd->scd_cdev, dev, 1)) {
+                               printk("%s: failed to register system"
+                                      " controller device (%s%s)\n",
+                                      __FUNCTION__, SYSCTL_BASENAME, devname);
+                               kfree(scd);
+                               kfree(salbuf);
+                               continue;
+                       }
+
+                       class_simple_device_add(snsc_class, dev, NULL,
+                                               "%s", devname);
+
+                       ia64_sn_irtr_intr_enable(scd->scd_nasid,
+                                                0 /*ignored */ ,
+                                                SAL_IROUTER_INTR_RECV);
+               }
+       }
+       return 0;
+}
+
+module_init(scdrv_init);
diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h
new file mode 100644 (file)
index 0000000..c22c6c5
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * SN Platform system controller communication 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.
+ *
+ * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/*
+ * This file contains macros and data types for communication with the
+ * system controllers in SGI SN systems.
+ */
+
+#ifndef _SN_SYSCTL_H_
+#define _SN_SYSCTL_H_
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/kobject.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <asm/sn/types.h>
+#include <asm/semaphore.h>
+
+#define CHUNKSIZE 127
+
+/* This structure is used to track an open subchannel. */
+struct subch_data_s {
+       nasid_t sd_nasid;       /* node on which the subchannel was opened */
+       int sd_subch;           /* subchannel number */
+       spinlock_t sd_rlock;    /* monitor lock for rsv */
+       spinlock_t sd_wlock;    /* monitor lock for wsv */
+       wait_queue_head_t sd_rq;        /* wait queue for readers */
+       wait_queue_head_t sd_wq;        /* wait queue for writers */
+       struct semaphore sd_rbs;        /* semaphore for read buffer */
+       struct semaphore sd_wbs;        /* semaphore for write buffer */
+
+       char sd_rb[CHUNKSIZE];  /* read buffer */
+       char sd_wb[CHUNKSIZE];  /* write buffer */
+};
+
+struct sysctl_data_s {
+       struct cdev scd_cdev;   /* Character device info */
+       nasid_t scd_nasid;      /* Node on which subchannels are opened. */
+};
+
+#endif /* _SN_SYSCTL_H_ */
index 0d3763d..bf82f06 100644 (file)
         ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
         ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
 
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
 #undef RS_EVENT_WRITE_WAKEUP
 #define RS_EVENT_WRITE_WAKEUP  0
 
@@ -159,7 +155,7 @@ static struct specialix_board sx_board[SX_NBOARD] =  {
 };
 
 static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
-               
+
 
 #ifdef SPECIALIX_TIMER
 static struct timer_list missed_irq_timer;
@@ -715,7 +711,7 @@ static inline void sx_transmit(struct specialix_board * bp)
                                sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
                                port->COR2 &= ~COR2_ETC;
                        }
-                       count = MIN(port->break_length, 0xff);
+                       count = min_t(int, port->break_length, 0xff);
                        sx_out(bp, CD186x_TDR, CD186x_C_ESC);
                        sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
                        sx_out(bp, CD186x_TDR, count);
@@ -1468,8 +1464,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
        sx_shutdown_port(bp, port);
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+       tty_ldisc_flush(tty);
        tty->closing = 0;
        port->event = 0;
        port->tty = NULL;
@@ -1506,7 +1501,7 @@ static int sx_write(struct tty_struct * tty, int from_user,
        if (from_user) {
                down(&tmp_buf_sem);
                while (1) {
-                       c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                       c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
                                           SERIAL_XMIT_SIZE - port->xmit_head));
                        if (c <= 0)
                                break;
@@ -1519,7 +1514,7 @@ static int sx_write(struct tty_struct * tty, int from_user,
                        }
 
                        cli();
-                       c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                       c = min_t(int, c, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
                                       SERIAL_XMIT_SIZE - port->xmit_head));
                        memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
                        port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
@@ -1534,7 +1529,7 @@ static int sx_write(struct tty_struct * tty, int from_user,
        } else {
                while (1) {
                        cli();
-                       c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                       c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
                                           SERIAL_XMIT_SIZE - port->xmit_head));
                        if (c <= 0) {
                                restore_flags(flags);
@@ -1646,10 +1641,8 @@ static void sx_flush_buffer(struct tty_struct *tty)
        port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
        restore_flags(flags);
        
+       tty_wakeup(tty);
        wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
 }
 
 
@@ -2052,12 +2045,8 @@ static void do_softint(void *private_)
        if(!(tty = port->tty)) 
                return;
 
-       if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   tty->ldisc.write_wakeup)
-                       (tty->ldisc.write_wakeup)(tty);
-               wake_up_interruptible(&tty->write_wait);
-       }
+       if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event))
+               tty_wakeup(tty);
 }
 
 static struct tty_operations sx_ops = {
index 1ca3d25..a990eb7 100644 (file)
@@ -1046,12 +1046,9 @@ static void sx_transmit_chars (struct sx_port *port)
        }
 
        if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
-               if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   port->gs.tty->ldisc.write_wakeup)
-                       (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
+               tty_wakeup(port->gs.tty);
                sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
                            port->gs.wakeup_chars); 
-               wake_up_interruptible(&port->gs.tty->write_wait);
        }
 
        clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks);
index 78d4efe..0a1cc1d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink.c
  *
- * $Id: synclink.c,v 4.24 2004/06/03 14:50:09 paulkf Exp $
+ * $Id: synclink.c,v 4.28 2004/08/11 19:30:01 paulkf Exp $
  *
  * Device driver for Microgate SyncLink ISA and PCI
  * high speed multiprotocol serial adapters.
 #include <asm/types.h>
 #include <linux/termios.h>
 #include <linux/workqueue.h>
+#include <linux/hdlc.h>
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
-#define CONFIG_SYNCLINK_SYNCPPP 1
-#endif
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#include <net/syncppp.h>
+#ifdef CONFIG_HDLC_MODULE
+#define CONFIG_HDLC 1
 #endif
 
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -187,7 +184,6 @@ struct tx_holding_buffer {
  */
  
 struct mgsl_struct {
-       void *if_ptr;   /* General purpose pointer (used by SPPP) */
        int                     magic;
        int                     flags;
        int                     count;          /* count of opens */
@@ -318,15 +314,13 @@ struct mgsl_struct {
        
        struct  _input_signal_events    input_signal_events;
 
-       /* SPPP/Cisco HDLC device parts */
+       /* generic HDLC device parts */
        int netcount;
        int dosyncppp;
        spinlock_t netlock;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-       struct ppp_device pppdev;
-       char netname[10];
+
+#ifdef CONFIG_HDLC
        struct net_device *netdev;
-       struct net_device_stats netstats;
 #endif
 };
 
@@ -734,18 +728,12 @@ int usc_loopmode_send_active( struct mgsl_struct * info );
 
 int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* SPPP/HDLC stuff */
-static void mgsl_sppp_init(struct mgsl_struct *info);
-static void mgsl_sppp_delete(struct mgsl_struct *info);
-int mgsl_sppp_open(struct net_device *d);
-int mgsl_sppp_close(struct net_device *d);
-void mgsl_sppp_tx_timeout(struct net_device *d);
-int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *d);
-void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size);
-void mgsl_sppp_tx_done(struct mgsl_struct *info);
-int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-struct net_device_stats *mgsl_net_stats(struct net_device *dev);
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(struct mgsl_struct *info);
+static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size);
+static int  hdlcdev_init(struct mgsl_struct *info);
+static void hdlcdev_exit(struct mgsl_struct *info);
 #endif
 
 /*
@@ -863,8 +851,6 @@ static int mgsl_rxenable(struct mgsl_struct * info, int enable);
 static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask);
 static int mgsl_loopmode_send_done( struct mgsl_struct * info );
 
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
-
 /* set non-zero on successful registration with PCI subsystem */
 static int pci_registered;
 
@@ -911,7 +897,7 @@ MODULE_PARM(txdmabufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 
 static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.24 $";
+static char *driver_version = "$Revision: 4.28 $";
 
 static int synclink_init_one (struct pci_dev *dev,
                                     const struct pci_device_id *ent);
@@ -942,10 +928,6 @@ static struct tty_driver *serial_driver;
 static void mgsl_change_params(struct mgsl_struct *info);
 static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout);
 
-#ifndef MIN
-#define MIN(a,b)       ((a) < (b) ? (a) : (b))
-#endif
-
 /*
  * 1st function defined in .text section. Calling this function in
  * init_module() followed by a breakpoint allows a remote debugger
@@ -993,6 +975,29 @@ static inline int mgsl_paranoia_check(struct mgsl_struct *info,
        return 0;
 }
 
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf  - pass receive data to line discipline
+ */
+
+static void ldisc_receive_buf(struct tty_struct *tty,
+                             const __u8 *data, char *flags, int count)
+{
+       struct tty_ldisc *ld;
+       if (!tty)
+               return;
+       ld = tty_ldisc_ref(tty);
+       if (ld) {
+               if (ld->receive_buf)
+                       ld->receive_buf(tty, data, flags, count);
+               tty_ldisc_deref(ld);
+       }
+}
+
 /* mgsl_stop()         throttle (stop) transmitter
  *     
  * Arguments:          tty     pointer to tty info structure
@@ -1153,13 +1158,7 @@ void mgsl_bh_transmit(struct mgsl_struct *info)
                        __FILE__,__LINE__,info->device_name);
 
        if (tty) {
-               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   tty->ldisc.write_wakeup) {
-                       if ( debug_level >= DEBUG_LEVEL_BH )
-                               printk( "%s(%d):calling ldisc.write_wakeup on %s\n",
-                                       __FILE__,__LINE__,info->device_name);
-                       (tty->ldisc.write_wakeup)(tty);
-               }
+               tty_wakeup(tty);
                wake_up_interruptible(&tty->write_wait);
        }
 
@@ -1289,9 +1288,9 @@ void mgsl_isr_transmit_status( struct mgsl_struct *info )
                info->drop_rts_on_tx_done = 0;
        }
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP 
+#ifdef CONFIG_HDLC
        if (info->netcount)
-               mgsl_sppp_tx_done(info);
+               hdlcdev_tx_done(info);
        else 
 #endif
        {
@@ -1352,12 +1351,12 @@ void mgsl_isr_io_pin( struct mgsl_struct *info )
                        icount->dcd++;
                        if (status & MISCSTATUS_DCD) {
                                info->input_signal_events.dcd_up++;
-#ifdef CONFIG_SYNCLINK_SYNCPPP 
-                               if (info->netcount)
-                                       sppp_reopen(info->netdev);
-#endif
                        } else
                                info->input_signal_events.dcd_down++;
+#ifdef CONFIG_HDLC
+                       if (info->netcount)
+                               hdlc_set_carrier(status & MISCSTATUS_DCD, info->netdev);
+#endif
                }
                if (status & MISCSTATUS_CTS_LATCHED)
                {
@@ -2258,8 +2257,8 @@ static int mgsl_write(struct tty_struct * tty, int from_user,
                if (from_user) {
                        down(&tmp_buf_sem);
                        while (1) {
-                               c = MIN(count,
-                                       MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                               c = min_t(int, count,
+                                       min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
                                            SERIAL_XMIT_SIZE - info->xmit_head));
                                if (c <= 0)
                                        break;
@@ -2272,7 +2271,7 @@ static int mgsl_write(struct tty_struct * tty, int from_user,
                                        break;
                                }
                                spin_lock_irqsave(&info->irq_spinlock,flags);
-                               c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                               c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
                                               SERIAL_XMIT_SIZE - info->xmit_head));
                                memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
                                info->xmit_head = ((info->xmit_head + c) &
@@ -2287,8 +2286,8 @@ static int mgsl_write(struct tty_struct * tty, int from_user,
                } else {
                        while (1) {
                                spin_lock_irqsave(&info->irq_spinlock,flags);
-                               c = MIN(count,
-                                       MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                               c = min_t(int, count,
+                                       min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
                                            SERIAL_XMIT_SIZE - info->xmit_head));
                                if (c <= 0) {
                                        spin_unlock_irqrestore(&info->irq_spinlock,flags);
@@ -2415,11 +2414,8 @@ static void mgsl_flush_buffer(struct tty_struct *tty)
        spin_unlock_irqrestore(&info->irq_spinlock,flags);
        
        wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
-               
-}      /* end of mgsl_flush_buffer() */
+       tty_wakeup(tty);
+}
 
 /* mgsl_send_xchar()
  *
@@ -3253,9 +3249,8 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp)
 
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-               
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+
+       tty_ldisc_flush(tty);
                
        shutdown(info);
        
@@ -3326,7 +3321,7 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
                char_time = 1;
                
        if (timeout)
-               char_time = MIN(char_time, timeout);
+               char_time = min_t(unsigned long, char_time, timeout);
                
        if ( info->params.mode == MGSL_MODE_HDLC ||
                info->params.mode == MGSL_MODE_RAW ) {
@@ -3592,7 +3587,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
 cleanup:                       
        if (retval) {
                if (tty->count == 1)
-                       info->tty = NULL;/* tty layer will release tty struct */
+                       info->tty = NULL; /* tty layer will release tty struct */
                if(info->count)
                        info->count--;
        }
@@ -4187,7 +4182,7 @@ int load_next_tx_holding_buffer(struct mgsl_struct *info)
                                info->get_tx_holding_index=0;
 
                        /* restart transmit timer */
-                       mod_timer(&info->tx_timer, jiffies + jiffies_from_ms(5000));
+                       mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000));
 
                        ret = 1;
                }
@@ -4415,12 +4410,10 @@ void mgsl_add_device( struct mgsl_struct *info )
                        info->max_frame_size );
        }
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#ifdef MODULE
-       if (info->dosyncppp)
-#endif
-               mgsl_sppp_init(info);
+#ifdef CONFIG_HDLC
+       hdlcdev_init(info);
 #endif
+
 }      /* end of mgsl_add_device() */
 
 /* mgsl_allocate_device()
@@ -4575,9 +4568,8 @@ static void synclink_cleanup(void)
 
        info = mgsl_device_list;
        while(info) {
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-               if (info->dosyncppp)
-                       mgsl_sppp_delete(info);
+#ifdef CONFIG_HDLC
+               hdlcdev_exit(info);
 #endif
                mgsl_release_resources(info);
                tmp = info;
@@ -5819,7 +5811,7 @@ void usc_start_transmitter( struct mgsl_struct *info )
                        
                        usc_TCmd( info, TCmd_SendFrame );
                        
-                       info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
+                       info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
                        add_timer(&info->tx_timer);     
                }
                info->tx_active = 1;
@@ -6750,9 +6742,12 @@ int mgsl_get_rx_frame(struct mgsl_struct *info)
                                return_frame = 1;
                }
                framesize = 0;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-               info->netstats.rx_errors++;
-               info->netstats.rx_frame_errors++;
+#ifdef CONFIG_HDLC
+               {
+                       struct net_device_stats *stats = hdlc_stats(info->netdev);
+                       stats->rx_errors++;
+                       stats->rx_frame_errors++;
+               }
 #endif
        } else
                return_frame = 1;
@@ -6779,7 +6774,7 @@ int mgsl_get_rx_frame(struct mgsl_struct *info)
                        
        if ( debug_level >= DEBUG_LEVEL_DATA )
                mgsl_trace_block(info,info->rx_buffer_list[StartIndex].virt_addr,
-                       MIN(framesize,DMABUFFERSIZE),0);        
+                       min_t(int, framesize, DMABUFFERSIZE),0);
                
        if (framesize) {
                if ( ( (info->params.crc_type & HDLC_CRC_RETURN_EX) &&
@@ -6823,18 +6818,12 @@ int mgsl_get_rx_frame(struct mgsl_struct *info)
                                                *ptmp);
                        }
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-                       if (info->netcount) {
-                               /* pass frame to syncppp device */
-                               mgsl_sppp_rx_done(info,info->intermediate_rxbuffer,framesize);
-                       } 
+#ifdef CONFIG_HDLC
+                       if (info->netcount)
+                               hdlcdev_rx(info,info->intermediate_rxbuffer,framesize);
                        else
 #endif
-                       {
-                               /* Call the line discipline receive callback directly. */
-                               if ( tty && tty->ldisc.receive_buf )
-                               tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
-                       }
+                               ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
                }
        }
        /* Free the buffers used by this frame. */
@@ -6996,7 +6985,7 @@ int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
 
                if ( debug_level >= DEBUG_LEVEL_DATA )
                        mgsl_trace_block(info,info->rx_buffer_list[CurrentIndex].virt_addr,
-                               MIN(framesize,DMABUFFERSIZE),0);
+                               min_t(int, framesize, DMABUFFERSIZE),0);
 
                if (framesize) {
                        /* copy dma buffer(s) to contiguous intermediate buffer */
@@ -7006,9 +6995,7 @@ int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
                        memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize);
                        info->icount.rxok++;
 
-                       /* Call the line discipline receive callback directly. */
-                       if ( tty && tty->ldisc.receive_buf )
-                               tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
+                       ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
                }
 
                /* Free the buffers used by this frame. */
@@ -7056,7 +7043,7 @@ void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, const char *Buffer,
        DMABUFFERENTRY *pBufEntry;
        
        if ( debug_level >= DEBUG_LEVEL_DATA )
-               mgsl_trace_block(info,Buffer, MIN(BufferSize,DMABUFFERSIZE), 1);        
+               mgsl_trace_block(info,Buffer, min_t(int, BufferSize, DMABUFFERSIZE), 1);
 
        if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
                /* set CMR:13 to start transmit when
@@ -7214,7 +7201,7 @@ BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
        EndTime=100;
        while( EndTime-- && !info->irq_occurred ) {
                set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(jiffies_from_ms(10));
+               schedule_timeout(msecs_to_jiffies(10));
        }
        
        spin_lock_irqsave(&info->irq_spinlock,flags);
@@ -7353,7 +7340,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
        /*************************************************************/
 
        /* Wait 100ms for interrupt. */
-       EndTime = jiffies + jiffies_from_ms(100);
+       EndTime = jiffies + msecs_to_jiffies(100);
 
        for(;;) {
                if (time_after(jiffies, EndTime)) {
@@ -7409,7 +7396,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
        /**********************************/
        
        /* Wait 100ms */
-       EndTime = jiffies + jiffies_from_ms(100);
+       EndTime = jiffies + msecs_to_jiffies(100);
 
        for(;;) {
                if (time_after(jiffies, EndTime)) {
@@ -7451,7 +7438,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
                /******************************/
 
                /* Wait 100ms */
-               EndTime = jiffies + jiffies_from_ms(100);
+               EndTime = jiffies + msecs_to_jiffies(100);
 
                /* While timer not expired wait for transmit complete */
 
@@ -7482,7 +7469,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
                /* WAIT FOR RECEIVE COMPLETE */
 
                /* Wait 100ms */
-               EndTime = jiffies + jiffies_from_ms(100);
+               EndTime = jiffies + msecs_to_jiffies(100);
 
                /* Wait for 16C32 to write receive status to buffer entry. */
                status=info->rx_buffer_list[0].status;
@@ -7736,9 +7723,9 @@ void mgsl_tx_timeout(unsigned long context)
 
        spin_unlock_irqrestore(&info->irq_spinlock,flags);
        
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
        if (info->netcount)
-               mgsl_sppp_tx_done(info);
+               hdlcdev_tx_done(info);
        else
 #endif
                mgsl_bh_transmit(info);
@@ -7819,79 +7806,125 @@ int usc_loopmode_send_active( struct mgsl_struct * info )
        return usc_InReg( info, CCSR ) & BIT6 ? 1 : 0 ;
 }                        
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* syncppp net device routines
- */
-static void mgsl_setup(struct net_device *dev)
-{
-       dev->open = mgsl_sppp_open;
-       dev->stop = mgsl_sppp_close;
-       dev->hard_start_xmit = mgsl_sppp_tx;
-       dev->do_ioctl = mgsl_sppp_ioctl;
-       dev->get_stats = mgsl_net_stats;
-       dev->tx_timeout = mgsl_sppp_tx_timeout;
-       dev->watchdog_timeo = 10*HZ;
-}
+#ifdef CONFIG_HDLC
 
-static void mgsl_sppp_init(struct mgsl_struct *info)
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev       pointer to network device structure
+ * encoding  serial encoding setting
+ * parity    FCS setting
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+                         unsigned short parity)
 {
-       struct net_device *d;
+       struct mgsl_struct *info = dev_to_port(dev);
+       unsigned char  new_encoding;
+       unsigned short new_crctype;
 
-       sprintf(info->netname,"mgsl%d",info->line);
+       /* return error if TTY interface open */
+       if (info->count)
+               return -EBUSY;
 
-       d = alloc_netdev(0, info->netname, mgsl_setup);
-       if (!d) {
-               printk(KERN_WARNING "%s: alloc_netdev failed.\n",
-                                               info->netname);
-               return;
+       switch (encoding)
+       {
+       case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
+       case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+       case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+       case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+       case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+       default: return -EINVAL;
        }
 
-       info->if_ptr = &info->pppdev;
-       info->netdev = info->pppdev.dev = d;
-
-       d->base_addr = info->io_base;
-       d->irq = info->irq_level;
-       d->dma = info->dma_level;
-       d->priv = info;
+       switch (parity)
+       {
+       case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
+       case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+       case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+       default: return -EINVAL;
+       }
 
-       sppp_attach(&info->pppdev);
-       mgsl_setup(d);
+       info->params.encoding = new_encoding;
+       info->params.crc_type = new_crctype;;
 
-       if (register_netdev(d)) {
-               printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
-               sppp_detach(info->netdev);
-               info->netdev = NULL;
-               free_netdev(d);
-               return;
-       }
+       /* if network interface up, reprogram hardware */
+       if (info->netcount)
+               mgsl_program_hw(info);
 
-       if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("mgsl_sppp_init()\n");   
+       return 0;
 }
 
-void mgsl_sppp_delete(struct mgsl_struct *info)
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb  socket buffer containing HDLC frame
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+       struct mgsl_struct *info = dev_to_port(dev);
+       struct net_device_stats *stats = hdlc_stats(dev);
+       unsigned long flags;
+
        if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("mgsl_sppp_delete(%s)\n",info->netname); 
-       unregister_netdev(info->netdev);
-       sppp_detach(info->netdev);
-       free_netdev(info->netdev);
-       info->netdev = NULL;
-       info->pppdev.dev = NULL;
+               printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
+
+       /* stop sending until this frame completes */
+       netif_stop_queue(dev);
+
+       /* copy data to device buffers */
+       info->xmit_cnt = skb->len;
+       mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
+
+       /* update network statistics */
+       stats->tx_packets++;
+       stats->tx_bytes += skb->len;
+
+       /* done with socket buffer, so free it */
+       dev_kfree_skb(skb);
+
+       /* save start time for transmit timeout detection */
+       dev->trans_start = jiffies;
+
+       /* start hardware transmitter if necessary */
+       spin_lock_irqsave(&info->irq_spinlock,flags);
+       if (!info->tx_active)
+               usc_start_transmitter(info);
+       spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+       return 0;
 }
 
-int mgsl_sppp_open(struct net_device *d)
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
 {
-       struct mgsl_struct *info = d->priv;
-       int err;
+       struct mgsl_struct *info = dev_to_port(dev);
+       int rc;
        unsigned long flags;
 
        if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("mgsl_sppp_open(%s)\n",info->netname);   
+               printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
 
+       /* generic HDLC layer open processing */
+       if ((rc = hdlc_open(dev)))
+               return rc;
+
+       /* arbitrate between network and tty opens */
        spin_lock_irqsave(&info->netlock, flags);
        if (info->count != 0 || info->netcount != 0) {
-               printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname);
+               printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
                spin_unlock_irqrestore(&info->netlock, flags);
                return -EBUSY;
        }
@@ -7899,141 +7932,301 @@ int mgsl_sppp_open(struct net_device *d)
        spin_unlock_irqrestore(&info->netlock, flags);
 
        /* claim resources and init adapter */
-       if ((err = startup(info)) != 0)
-               goto open_fail;
-
-       /* allow syncppp module to do open processing */
-       if ((err = sppp_open(d)) != 0) {
-               shutdown(info);
-               goto open_fail;
+       if ((rc = startup(info)) != 0) {
+               spin_lock_irqsave(&info->netlock, flags);
+               info->netcount=0;
+               spin_unlock_irqrestore(&info->netlock, flags);
+               return rc;
        }
 
+       /* assert DTR and RTS, apply hardware settings */
        info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
        mgsl_program_hw(info);
 
-       d->trans_start = jiffies;
-       netif_start_queue(d);
-       return 0;
+       /* enable network layer transmit */
+       dev->trans_start = jiffies;
+       netif_start_queue(dev);
 
-open_fail:
-       spin_lock_irqsave(&info->netlock, flags);
-       info->netcount=0;
-       spin_unlock_irqrestore(&info->netlock, flags);
-       return err;
+       /* inform generic HDLC layer of current DCD status */
+       spin_lock_irqsave(&info->irq_spinlock, flags);
+       usc_get_serial_signals(info);
+       spin_unlock_irqrestore(&info->irq_spinlock, flags);
+       hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
+
+       return 0;
 }
 
-void mgsl_sppp_tx_timeout(struct net_device *dev)
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
 {
-       struct mgsl_struct *info = dev->priv;
+       struct mgsl_struct *info = dev_to_port(dev);
        unsigned long flags;
 
        if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("mgsl_sppp_tx_timeout(%s)\n",info->netname);     
+               printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
 
-       info->netstats.tx_errors++;
-       info->netstats.tx_aborted_errors++;
+       netif_stop_queue(dev);
 
-       spin_lock_irqsave(&info->irq_spinlock,flags);
-       usc_stop_transmitter(info);
-       spin_unlock_irqrestore(&info->irq_spinlock,flags);
+       /* shutdown adapter and release resources */
+       shutdown(info);
 
-       netif_wake_queue(dev);
+       hdlc_close(dev);
+
+       spin_lock_irqsave(&info->netlock, flags);
+       info->netcount=0;
+       spin_unlock_irqrestore(&info->netlock, flags);
+
+       return 0;
 }
 
-int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *dev)
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev  pointer to network device structure
+ * ifr  pointer to network interface request structure
+ * cmd  IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-       struct mgsl_struct *info = dev->priv;
-       unsigned long flags;
+       const size_t size = sizeof(sync_serial_settings);
+       sync_serial_settings new_line;
+       sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+       struct mgsl_struct *info = dev_to_port(dev);
+       unsigned int flags;
 
        if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("mgsl_sppp_tx(%s)\n",info->netname);     
+               printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
 
-       netif_stop_queue(dev);
+       /* return error if TTY interface open */
+       if (info->count)
+               return -EBUSY;
 
-       info->xmit_cnt = skb->len;
-       mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
-       info->netstats.tx_packets++;
-       info->netstats.tx_bytes += skb->len;
-       dev_kfree_skb(skb);
+       if (cmd != SIOCWANDEV)
+               return hdlc_ioctl(dev, ifr, cmd);
 
-       dev->trans_start = jiffies;
+       switch(ifr->ifr_settings.type) {
+       case IF_GET_IFACE: /* return current sync_serial_settings */
 
-       spin_lock_irqsave(&info->irq_spinlock,flags);
-       if (!info->tx_active)
-               usc_start_transmitter(info);
-       spin_unlock_irqrestore(&info->irq_spinlock,flags);
+               ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+               if (ifr->ifr_settings.size < size) {
+                       ifr->ifr_settings.size = size; /* data size wanted */
+                       return -ENOBUFS;
+               }
 
-       return 0;
+               flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+                                             HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+                                             HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+                                             HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+
+               switch (flags){
+               case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+               case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
+               case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
+               case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+               default: new_line.clock_type = CLOCK_DEFAULT;
+               }
+
+               new_line.clock_rate = info->params.clock_speed;
+               new_line.loopback   = info->params.loopback ? 1:0;
+
+               if (copy_to_user(line, &new_line, size))
+                       return -EFAULT;
+               return 0;
+
+       case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+               if(!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               if (copy_from_user(&new_line, line, size))
+                       return -EFAULT;
+
+               switch (new_line.clock_type)
+               {
+               case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+               case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+               case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
+               case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
+               case CLOCK_DEFAULT:  flags = info->params.flags &
+                                            (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+                                             HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+                                             HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+                                             HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
+               default: return -EINVAL;
+               }
+
+               if (new_line.loopback != 0 && new_line.loopback != 1)
+                       return -EINVAL;
+
+               info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+                                       HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+                                       HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+                                       HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+               info->params.flags |= flags;
+
+               info->params.loopback = new_line.loopback;
+
+               if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+                       info->params.clock_speed = new_line.clock_rate;
+               else
+                       info->params.clock_speed = 0;
+
+               /* if network interface up, reprogram hardware */
+               if (info->netcount)
+                       mgsl_program_hw(info);
+               return 0;
+
+       default:
+               return hdlc_ioctl(dev, ifr, cmd);
+       }
 }
 
-int mgsl_sppp_close(struct net_device *d)
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev  pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
 {
-       struct mgsl_struct *info = d->priv;
+       struct mgsl_struct *info = dev_to_port(dev);
+       struct net_device_stats *stats = hdlc_stats(dev);
        unsigned long flags;
 
        if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("mgsl_sppp_close(%s)\n",info->netname);  
+               printk("hdlcdev_tx_timeout(%s)\n",dev->name);
 
-       /* shutdown adapter and release resources */
-       shutdown(info);
+       stats->tx_errors++;
+       stats->tx_aborted_errors++;
 
-       /* allow syncppp to do close processing */
-       sppp_close(d);
-       netif_stop_queue(d);
+       spin_lock_irqsave(&info->irq_spinlock,flags);
+       usc_stop_transmitter(info);
+       spin_unlock_irqrestore(&info->irq_spinlock,flags);
 
-       spin_lock_irqsave(&info->netlock, flags);
-       info->netcount=0;
-       spin_unlock_irqrestore(&info->netlock, flags);
-       return 0;
+       netif_wake_queue(dev);
+}
+
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_tx_done(struct mgsl_struct *info)
+{
+       if (netif_queue_stopped(info->netdev))
+               netif_wake_queue(info->netdev);
 }
 
-void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size)
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info  pointer to device instance information
+ * buf   pointer to buffer contianing frame data
+ * size  count of data bytes in buf
+ */
+static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size)
 {
        struct sk_buff *skb = dev_alloc_skb(size);
+       struct net_device *dev = info->netdev;
+       struct net_device_stats *stats = hdlc_stats(dev);
+
        if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("mgsl_sppp_rx_done(%s)\n",info->netname);        
+               printk("hdlcdev_rx(%s)\n",dev->name);
+
        if (skb == NULL) {
-               printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
-                       info->netname);
-               info->netstats.rx_dropped++;
+               printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name);
+               stats->rx_dropped++;
                return;
        }
 
        memcpy(skb_put(skb, size),buf,size);
 
-       skb->protocol = htons(ETH_P_WAN_PPP);
-       skb->dev = info->netdev;
-       skb->mac.raw = skb->data;
-       info->netstats.rx_packets++;
-       info->netstats.rx_bytes += size;
+       skb->dev      = info->netdev;
+       skb->mac.raw  = skb->data;
+       skb->protocol = hdlc_type_trans(skb, skb->dev);
+
+       stats->rx_packets++;
+       stats->rx_bytes += size;
+
        netif_rx(skb);
-       info->netdev->trans_start = jiffies;
-}
 
-void mgsl_sppp_tx_done(struct mgsl_struct *info)
-{
-       if (netif_queue_stopped(info->netdev))
-           netif_wake_queue(info->netdev);
+       info->netdev->last_rx = jiffies;
 }
 
-struct net_device_stats *mgsl_net_stats(struct net_device *dev)
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info  pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(struct mgsl_struct *info)
 {
-       struct mgsl_struct *info = dev->priv;
-       if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("mgsl_net_stats(%s)\n",info->netname);   
-       return &info->netstats;
+       int rc;
+       struct net_device *dev;
+       hdlc_device *hdlc;
+
+       /* allocate and initialize network and HDLC layer objects */
+
+       if (!(dev = alloc_hdlcdev(info))) {
+               printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
+               return -ENOMEM;
+       }
+
+       /* for network layer reporting purposes only */
+       dev->base_addr = info->io_base;
+       dev->irq       = info->irq_level;
+       dev->dma       = info->dma_level;
+
+       /* network layer callbacks and settings */
+       dev->do_ioctl       = hdlcdev_ioctl;
+       dev->open           = hdlcdev_open;
+       dev->stop           = hdlcdev_close;
+       dev->tx_timeout     = hdlcdev_tx_timeout;
+       dev->watchdog_timeo = 10*HZ;
+       dev->tx_queue_len   = 50;
+
+       /* generic HDLC layer callbacks and settings */
+       hdlc         = dev_to_hdlc(dev);
+       hdlc->attach = hdlcdev_attach;
+       hdlc->xmit   = hdlcdev_xmit;
+
+       /* register objects with HDLC layer */
+       if ((rc = register_hdlc_device(dev))) {
+               printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+               free_netdev(dev);
+               return rc;
+       }
+
+       info->netdev = dev;
+       return 0;
 }
 
-int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_exit(struct mgsl_struct *info)
 {
-       struct mgsl_struct *info = dev->priv;
-       if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
-                       info->netname, cmd );
-       return sppp_do_ioctl(dev, ifr, cmd);
+       unregister_hdlc_device(info->netdev);
+       free_netdev(info->netdev);
+       info->netdev = NULL;
 }
 
-#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */
+#endif /* CONFIG_HDLC */
+
 
 static int __devinit synclink_init_one (struct pci_dev *dev,
                                        const struct pci_device_id *ent)
index df9d4de..dcfcef4 100644 (file)
@@ -422,10 +422,7 @@ static void send_buffers(struct port_info *pi)
                        pi->overflowMessage = 0;
 
                if (pi->tty) {
-                       if ((pi->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                           (pi->tty->ldisc.write_wakeup))
-                               (pi->tty->ldisc.write_wakeup)(pi->tty);
-                       wake_up_interruptible(&pi->tty->write_wait);
+                       tty_wakeup(pi->tty);
                }
        }
 
index 6f78334..19ba836 100644 (file)
@@ -544,12 +544,8 @@ static irqreturn_t scc_tx_int(int irq, void *data, struct pt_regs *fp)
                SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
                port->gs.flags &= ~GS_TX_INTEN;
        }
-       if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) {
-               if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                               port->gs.tty->ldisc.write_wakeup)
-                       (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
-               wake_up_interruptible(&port->gs.tty->write_wait);
-       }
+       if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars)
+               tty_wakeup(port->gs.tty);
 
        SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
        return IRQ_HANDLED;
index b8e3d91..a6781de 100644 (file)
@@ -170,6 +170,7 @@ ixp4xx_wdt_release(struct inode *inode, struct file *file)
 static struct file_operations ixp4xx_wdt_fops =
 {
        .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
        .write          = ixp4xx_wdt_write,
        .ioctl          = ixp4xx_wdt_ioctl,
        .open           = ixp4xx_wdt_open,
diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c
new file mode 100644 (file)
index 0000000..56d62ba
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * mpc8xx_wdt.c - MPC8xx watchdog userspace interface
+ *
+ * Author: Florian Schirmer <jolt@tuxbox.org>
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> 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.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <asm/8xx_immap.h>
+#include <asm/uaccess.h>
+#include <syslib/m8xx_wdt.h>
+
+static unsigned long wdt_opened;
+static int wdt_status;
+
+static void mpc8xx_wdt_handler_disable(void)
+{
+       volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+
+       imap->im_sit.sit_piscr &= ~(PISCR_PIE | PISCR_PTE);
+
+       printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
+}
+
+static void mpc8xx_wdt_handler_enable(void)
+{
+       volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+
+       imap->im_sit.sit_piscr |= PISCR_PIE | PISCR_PTE;
+
+       printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
+}
+
+static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &wdt_opened))
+               return -EBUSY;
+
+       m8xx_wdt_reset();
+       mpc8xx_wdt_handler_disable();
+
+       return 0;
+}
+
+static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
+{
+       m8xx_wdt_reset();
+
+#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
+       mpc8xx_wdt_handler_enable();
+#endif
+
+       clear_bit(0, &wdt_opened);
+
+       return 0;
+}
+
+static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len,
+                               loff_t * ppos)
+{
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       if (len)
+               m8xx_wdt_reset();
+
+       return len;
+}
+
+static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file,
+                           unsigned int cmd, unsigned long arg)
+{
+       int timeout;
+       static struct watchdog_info info = {
+               .options = WDIOF_KEEPALIVEPING,
+               .firmware_version = 0,
+               .identity = "MPC8xx watchdog",
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user((void *)arg, &info, sizeof(info)))
+                       return -EFAULT;
+               break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               if (put_user(wdt_status, (int *)arg))
+                       return -EFAULT;
+               wdt_status &= ~WDIOF_KEEPALIVEPING;
+               break;
+
+       case WDIOC_GETTEMP:
+               return -EOPNOTSUPP;
+
+       case WDIOC_SETOPTIONS:
+               return -EOPNOTSUPP;
+
+       case WDIOC_KEEPALIVE:
+               m8xx_wdt_reset();
+               wdt_status |= WDIOF_KEEPALIVEPING;
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               return -EOPNOTSUPP;
+
+       case WDIOC_GETTIMEOUT:
+               timeout = m8xx_wdt_get_timeout();
+               if (put_user(timeout, (int *)arg))
+                       return -EFAULT;
+               break;
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       return 0;
+}
+
+static struct file_operations mpc8xx_wdt_fops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .write = mpc8xx_wdt_write,
+       .ioctl = mpc8xx_wdt_ioctl,
+       .open = mpc8xx_wdt_open,
+       .release = mpc8xx_wdt_release,
+};
+
+static struct miscdevice mpc8xx_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &mpc8xx_wdt_fops,
+};
+
+static int __init mpc8xx_wdt_init(void)
+{
+       return misc_register(&mpc8xx_wdt_miscdev);
+}
+
+static void __exit mpc8xx_wdt_exit(void)
+{
+       misc_deregister(&mpc8xx_wdt_miscdev);
+
+       m8xx_wdt_reset();
+       mpc8xx_wdt_handler_enable();
+}
+
+module_init(mpc8xx_wdt_init);
+module_exit(mpc8xx_wdt_exit);
+
+MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
+MODULE_DESCRIPTION("MPC8xx watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
index 88bdbda..592dca1 100644 (file)
@@ -859,8 +859,7 @@ static int __init pcwd_checkcard(int base_addr)
                /* Not an 'ff' from a floating bus, so must be a card! */
                for (i = 0; i < 4; ++i) {
 
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(HZ / 2);
+                       msleep(500);
 
                        last_port0 = port0;
                        last_port1 = port1;
index d3fced3..52825a1 100644 (file)
@@ -180,6 +180,7 @@ watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 static struct file_operations watchdog_fops = {
        .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
        .write          = watchdog_write,
        .ioctl          = watchdog_ioctl,
        .open           = watchdog_open,
index 388c548..072e9b2 100644 (file)
@@ -392,6 +392,7 @@ static int wdt977_notify_sys(struct notifier_block *this, unsigned long code,
 static struct file_operations wdt977_fops=
 {
        .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
        .write          = wdt977_write,
        .ioctl          = wdt977_ioctl,
        .open           = wdt977_open,
index 331b515..889f243 100644 (file)
@@ -69,6 +69,21 @@ config CPU_FREQ_GOV_USERSPACE
 
          If in doubt, say Y.
 
+config CPU_FREQ_GOV_ONDEMAND
+       tristate "'ondemand' cpufreq policy governor"
+       depends on CPU_FREQ
+       help
+         'ondemand' - This driver adds a dynamic cpufreq policy governor.
+         The governor does a periodic polling and 
+         changes frequency based on the CPU utilization.
+         The support for this governor depends on CPU capability to
+         do fast frequency switching (i.e, very low latency frequency
+         transitions). 
+
+         For details, take a look at linux/Documentation/cpu-freq.
+
+         If in doubt, say N.
+
 config CPU_FREQ_24_API
        bool "/proc/sys/cpu/ interface (2.4. / OLD)"
        depends on CPU_FREQ && SYSCTL && CPU_FREQ_GOV_USERSPACE
index 1eebf3c..50291ab 100644 (file)
@@ -5,6 +5,7 @@ obj-$(CONFIG_CPU_FREQ)                  += cpufreq.o
 obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o
 obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE)   += cpufreq_powersave.o
 obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE)   += cpufreq_userspace.o
+obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)    += cpufreq_ondemand.o
 
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)           += freq_table.o
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
new file mode 100644 (file)
index 0000000..a9320ae
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ *  drivers/cpufreq/cpufreq_ondemand.c
+ *
+ *  Copyright (C)  2001 Russell King
+ *            (C)  2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ *                      Jun Nakajima <jun.nakajima@intel.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/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ctype.h>
+#include <linux/cpufreq.h>
+#include <linux/sysctl.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/sysfs.h>
+#include <linux/sched.h>
+#include <linux/kmod.h>
+#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <linux/config.h>
+#include <linux/kernel_stat.h>
+#include <linux/percpu.h>
+
+/*
+ * dbs is used in this file as a shortform for demandbased switching
+ * It helps to keep variable names smaller, simpler
+ */
+
+#define DEF_FREQUENCY_UP_THRESHOLD             (80)
+#define MIN_FREQUENCY_UP_THRESHOLD             (0)
+#define MAX_FREQUENCY_UP_THRESHOLD             (100)
+
+#define DEF_FREQUENCY_DOWN_THRESHOLD           (20)
+#define MIN_FREQUENCY_DOWN_THRESHOLD           (0)
+#define MAX_FREQUENCY_DOWN_THRESHOLD           (100)
+
+/* 
+ * The polling frequency of this governor depends on the capability of 
+ * the processor. Default polling frequency is 1000 times the transition
+ * latency of the processor. The governor will work on any processor with 
+ * transition latency <= 10mS, using appropriate sampling 
+ * rate.
+ * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
+ * this governor will not work.
+ * All times here are in uS.
+ */
+static unsigned int                            def_sampling_rate;
+#define MIN_SAMPLING_RATE                      (def_sampling_rate / 2)
+#define MAX_SAMPLING_RATE                      (500 * def_sampling_rate)
+#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER   (1000)
+#define DEF_SAMPLING_DOWN_FACTOR               (10)
+#define TRANSITION_LATENCY_LIMIT               (10 * 1000)
+#define sampling_rate_in_HZ(x)                 (((x * HZ) < (1000 * 1000))?1:((x * HZ) / (1000 * 1000)))
+
+static void do_dbs_timer(void *data);
+
+struct cpu_dbs_info_s {
+       struct cpufreq_policy   *cur_policy;
+       unsigned int            prev_cpu_idle_up;
+       unsigned int            prev_cpu_idle_down;
+       unsigned int            enable;
+};
+static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
+
+static unsigned int dbs_enable;        /* number of CPUs using this policy */
+
+static DECLARE_MUTEX   (dbs_sem);
+static DECLARE_WORK    (dbs_work, do_dbs_timer, NULL);
+
+struct dbs_tuners {
+       unsigned int            sampling_rate;
+       unsigned int            sampling_down_factor;
+       unsigned int            up_threshold;
+       unsigned int            down_threshold;
+};
+
+struct dbs_tuners dbs_tuners_ins = {
+       .up_threshold           = DEF_FREQUENCY_UP_THRESHOLD,
+       .down_threshold         = DEF_FREQUENCY_DOWN_THRESHOLD,
+       .sampling_down_factor   = DEF_SAMPLING_DOWN_FACTOR,
+};
+
+/************************** sysfs interface ************************/
+static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
+{
+       return sprintf (buf, "%u\n", MAX_SAMPLING_RATE);
+}
+
+static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
+{
+       return sprintf (buf, "%u\n", MIN_SAMPLING_RATE);
+}
+
+#define define_one_ro(_name)                                   \
+static struct freq_attr _name = {                              \
+       .attr = { .name = __stringify(_name), .mode = 0444 },   \
+       .show = show_##_name,                                   \
+}
+
+define_one_ro(sampling_rate_max);
+define_one_ro(sampling_rate_min);
+
+/* cpufreq_ondemand Governor Tunables */
+#define show_one(file_name, object)                                    \
+static ssize_t show_##file_name                                                \
+(struct cpufreq_policy *unused, char *buf)                             \
+{                                                                      \
+       return sprintf(buf, "%u\n", dbs_tuners_ins.object);             \
+}
+show_one(sampling_rate, sampling_rate);
+show_one(sampling_down_factor, sampling_down_factor);
+show_one(up_threshold, up_threshold);
+show_one(down_threshold, down_threshold);
+
+static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, 
+               const char *buf, size_t count)
+{
+       unsigned int input;
+       int ret;
+       ret = sscanf (buf, "%u", &input);
+       down(&dbs_sem);
+       if (ret != 1 )
+               goto out;
+
+       dbs_tuners_ins.sampling_down_factor = input;
+out:
+       up(&dbs_sem);
+       return count;
+}
+
+static ssize_t store_sampling_rate(struct cpufreq_policy *unused, 
+               const char *buf, size_t count)
+{
+       unsigned int input;
+       int ret;
+       ret = sscanf (buf, "%u", &input);
+       down(&dbs_sem);
+       if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE)
+               goto out;
+
+       dbs_tuners_ins.sampling_rate = input;
+out:
+       up(&dbs_sem);
+       return count;
+}
+
+static ssize_t store_up_threshold(struct cpufreq_policy *unused, 
+               const char *buf, size_t count)
+{
+       unsigned int input;
+       int ret;
+       ret = sscanf (buf, "%u", &input);
+       down(&dbs_sem);
+       if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || 
+                       input < MIN_FREQUENCY_UP_THRESHOLD ||
+                       input <= dbs_tuners_ins.down_threshold)
+               goto out;
+
+       dbs_tuners_ins.up_threshold = input;
+out:
+       up(&dbs_sem);
+       return count;
+}
+
+static ssize_t store_down_threshold(struct cpufreq_policy *unused, 
+               const char *buf, size_t count)
+{
+       unsigned int input;
+       int ret;
+       ret = sscanf (buf, "%u", &input);
+       down(&dbs_sem);
+       if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD || 
+                       input < MIN_FREQUENCY_DOWN_THRESHOLD ||
+                       input >= dbs_tuners_ins.up_threshold)
+               goto out;
+
+       dbs_tuners_ins.down_threshold = input;
+out:
+       up(&dbs_sem);
+       return count;
+}
+
+#define define_one_rw(_name)                                   \
+static struct freq_attr _name = {                              \
+       .attr = { .name = __stringify(_name), .mode = 0644 },   \
+       .show = show_##_name,                                   \
+       .store = store_##_name,                                 \
+}
+
+define_one_rw(sampling_rate);
+define_one_rw(sampling_down_factor);
+define_one_rw(up_threshold);
+define_one_rw(down_threshold);
+
+static struct attribute * dbs_attributes[] = {
+       &sampling_rate_max.attr,
+       &sampling_rate_min.attr,
+       &sampling_rate.attr,
+       &sampling_down_factor.attr,
+       &up_threshold.attr,
+       &down_threshold.attr,
+       NULL
+};
+
+static struct attribute_group dbs_attr_group = {
+       .attrs = dbs_attributes,
+       .name = "ondemand",
+};
+
+/************************** sysfs end ************************/
+
+static void dbs_check_cpu(int cpu)
+{
+       unsigned int idle_ticks, up_idle_ticks, down_idle_ticks;
+       unsigned int total_idle_ticks;
+       unsigned int freq_down_step;
+       unsigned int freq_down_sampling_rate;
+       static int down_skip[NR_CPUS];
+       struct cpu_dbs_info_s *this_dbs_info;
+
+       this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
+       if (!this_dbs_info->enable)
+               return;
+
+       /* 
+        * The default safe range is 20% to 80% 
+        * Every sampling_rate, we check
+        *      - If current idle time is less than 20%, then we try to 
+        *        increase frequency
+        * Every sampling_rate*sampling_down_factor, we check
+        *      - If current idle time is more than 80%, then we try to
+        *        decrease frequency
+        *
+        * Any frequency increase takes it to the maximum frequency. 
+        * Frequency reduction happens at minimum steps of 
+        * 5% of max_frequency 
+        */
+       /* Check for frequency increase */
+       total_idle_ticks = kstat_cpu(cpu).cpustat.idle +
+               kstat_cpu(cpu).cpustat.iowait;
+       idle_ticks = total_idle_ticks -
+               this_dbs_info->prev_cpu_idle_up;
+       this_dbs_info->prev_cpu_idle_up = total_idle_ticks;
+
+       /* Scale idle ticks by 100 and compare with up and down ticks */
+       idle_ticks *= 100;
+       up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) *
+                       sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate);
+
+       if (idle_ticks < up_idle_ticks) {
+               __cpufreq_driver_target(this_dbs_info->cur_policy,
+                       this_dbs_info->cur_policy->max, 
+                       CPUFREQ_RELATION_H);
+               down_skip[cpu] = 0;
+               this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
+               return;
+       }
+
+       /* Check for frequency decrease */
+       down_skip[cpu]++;
+       if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor)
+               return;
+
+       idle_ticks = total_idle_ticks -
+               this_dbs_info->prev_cpu_idle_down;
+       /* Scale idle ticks by 100 and compare with up and down ticks */
+       idle_ticks *= 100;
+       down_skip[cpu] = 0;
+       this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
+
+       freq_down_sampling_rate = dbs_tuners_ins.sampling_rate *
+               dbs_tuners_ins.sampling_down_factor;
+       down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) *
+                       sampling_rate_in_HZ(freq_down_sampling_rate);
+
+       if (idle_ticks > down_idle_ticks ) {
+               freq_down_step = (5 * this_dbs_info->cur_policy->max) / 100;
+
+               /* max freq cannot be less than 100. But who knows.... */
+               if (unlikely(freq_down_step == 0))
+                       freq_down_step = 5;
+
+               __cpufreq_driver_target(this_dbs_info->cur_policy,
+                       this_dbs_info->cur_policy->cur - freq_down_step, 
+                       CPUFREQ_RELATION_H);
+               return;
+       }
+}
+
+static void do_dbs_timer(void *data)
+{ 
+       int i;
+       down(&dbs_sem);
+       for (i = 0; i < NR_CPUS; i++)
+               if (cpu_online(i))
+                       dbs_check_cpu(i);
+       schedule_delayed_work(&dbs_work, 
+                       sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate));
+       up(&dbs_sem);
+} 
+
+static inline void dbs_timer_init(void)
+{
+       INIT_WORK(&dbs_work, do_dbs_timer, NULL);
+       schedule_work(&dbs_work);
+       return;
+}
+
+static inline void dbs_timer_exit(void)
+{
+       cancel_delayed_work(&dbs_work);
+       return;
+}
+
+static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
+                                  unsigned int event)
+{
+       unsigned int cpu = policy->cpu;
+       struct cpu_dbs_info_s *this_dbs_info;
+
+       this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
+
+       switch (event) {
+       case CPUFREQ_GOV_START:
+               if ((!cpu_online(cpu)) || 
+                   (!policy->cur))
+                       return -EINVAL;
+
+               if (policy->cpuinfo.transition_latency >
+                               (TRANSITION_LATENCY_LIMIT * 1000))
+                       return -EINVAL;
+               if (this_dbs_info->enable) /* Already enabled */
+                       break;
+                
+               down(&dbs_sem);
+               this_dbs_info->cur_policy = policy;
+               
+               this_dbs_info->prev_cpu_idle_up = 
+                               kstat_cpu(cpu).cpustat.idle +
+                               kstat_cpu(cpu).cpustat.iowait;
+               this_dbs_info->prev_cpu_idle_down = 
+                               kstat_cpu(cpu).cpustat.idle +
+                               kstat_cpu(cpu).cpustat.iowait;
+               this_dbs_info->enable = 1;
+               sysfs_create_group(&policy->kobj, &dbs_attr_group);
+               dbs_enable++;
+               /*
+                * Start the timerschedule work, when this governor
+                * is used for first time
+                */
+               if (dbs_enable == 1) {
+                       unsigned int latency;
+                       /* policy latency is in nS. Convert it to uS first */
+
+                       latency = policy->cpuinfo.transition_latency;
+                       if (latency < 1000)
+                               latency = 1000;
+
+                       def_sampling_rate = (latency / 1000) *
+                                       DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
+                       dbs_tuners_ins.sampling_rate = def_sampling_rate;
+
+                       dbs_timer_init();
+               }
+               
+               up(&dbs_sem);
+               break;
+
+       case CPUFREQ_GOV_STOP:
+               down(&dbs_sem);
+               this_dbs_info->enable = 0;
+               sysfs_remove_group(&policy->kobj, &dbs_attr_group);
+               dbs_enable--;
+               /*
+                * Stop the timerschedule work, when this governor
+                * is used for first time
+                */
+               if (dbs_enable == 0) 
+                       dbs_timer_exit();
+               
+               up(&dbs_sem);
+
+               break;
+
+       case CPUFREQ_GOV_LIMITS:
+               down(&dbs_sem);
+               if (policy->max < this_dbs_info->cur_policy->cur)
+                       __cpufreq_driver_target(
+                                       this_dbs_info->cur_policy,
+                                       policy->max, CPUFREQ_RELATION_H);
+               else if (policy->min > this_dbs_info->cur_policy->cur)
+                       __cpufreq_driver_target(
+                                       this_dbs_info->cur_policy,
+                                       policy->min, CPUFREQ_RELATION_L);
+               up(&dbs_sem);
+               break;
+       }
+       return 0;
+}
+
+struct cpufreq_governor cpufreq_gov_dbs = {
+       .name           = "ondemand",
+       .governor       = cpufreq_governor_dbs,
+       .owner          = THIS_MODULE,
+};
+EXPORT_SYMBOL(cpufreq_gov_dbs);
+
+static int __init cpufreq_gov_dbs_init(void)
+{
+       return cpufreq_register_governor(&cpufreq_gov_dbs);
+}
+
+static void __exit cpufreq_gov_dbs_exit(void)
+{
+       /* Make sure that the scheduled work is indeed not running */
+       flush_scheduled_work();
+
+       cpufreq_unregister_governor(&cpufreq_gov_dbs);
+}
+
+
+MODULE_AUTHOR ("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>");
+MODULE_DESCRIPTION ("'cpufreq_ondemand' - A dynamic cpufreq governor for "
+               "Low Latency Frequency Transition capable processors");
+MODULE_LICENSE ("GPL");
+
+module_init(cpufreq_gov_dbs_init);
+module_exit(cpufreq_gov_dbs_exit);
index a0eaf6f..6739778 100644 (file)
 #include <linux/proc_fs.h>
 #include <asm/uaccess.h>
 
+#warning This module will be removed from the 2.6. kernel series soon after 2005-01-01
 
 #define CPUFREQ_ALL_CPUS               ((NR_CPUS))
 
+static unsigned int warning_print = 0;
+
 /**
  * cpufreq_parse_policy - parse a policy string
  * @input_string: the string to parse.
@@ -110,6 +113,13 @@ static int cpufreq_proc_read (
        if (off != 0)
                goto end;
 
+       if (!warning_print) {
+               warning_print++;
+               printk(KERN_INFO "Access to /proc/cpufreq is deprecated and "
+                       "will be removed from (new) 2.6. kernels soon "
+                       "after 2005-01-01\n");
+       }
+
        p += sprintf(p, "          minimum CPU frequency  -  maximum CPU frequency  -  policy\n");
        for (i=0;i<NR_CPUS;i++) {
                if (!cpu_online(i))
@@ -179,6 +189,13 @@ static int cpufreq_proc_write (
        
        if (copy_from_user(proc_string, buffer, count))
                return -EFAULT;
+
+       if (!warning_print) {
+               warning_print++;
+               printk(KERN_INFO "Access to /proc/cpufreq is deprecated and "
+                       "will be removed from (new) 2.6. kernels soon "
+                       "after 2005-01-01\n");
+       }
        
        proc_string[count] = '\0';
 
index 7015eb7..a48a087 100644 (file)
@@ -81,29 +81,29 @@ do {        (s)->imask = (i); \
  * That's why here are the following inline functions...
  */
  
-typedef unsigned long xram_p;
+typedef void __iomem *xram_p;
 
 /* Get 32bit number from XRAM */
-static inline u32 xram_get_32 (xram_p x)
+static inline u32 xram_get_32(xram_p x)
 {
        return ((sbus_readw(x + 0x00UL) << 16) |
                (sbus_readw(x + 0x02UL)));
 }
 
 /* Like the above, but when we don't care about the high 16 bits */
-static inline u32 xram_get_32low (xram_p x)
+static inline u32 xram_get_32low(xram_p x)
 {
        return (u32) sbus_readw(x + 0x02UL);
 }
 
-static inline u16 xram_get_16 (xram_p x)
+static inline u16 xram_get_16(xram_p x)
 {
        return sbus_readw(x);
 }
 
-static inline u8 xram_get_8 (xram_p x)
+static inline u8 xram_get_8(xram_p x)
 {
-       if (x & (xram_p)0x1) {
+       if ((unsigned long)x & 0x1UL) {
                x = x - 1;
                return (u8) sbus_readw(x);
        } else {
@@ -111,7 +111,7 @@ static inline u8 xram_get_8 (xram_p x)
        }
 }
 
-static inline void xram_copy_from (void *p, xram_p x, int len)
+static inline void xram_copy_from(void *p, xram_p x, int len)
 {
        for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
                u32 val, *p32 = p;
@@ -123,7 +123,7 @@ static inline void xram_copy_from (void *p, xram_p x, int len)
        }
 }
 
-static inline void xram_copy_to (xram_p x, void *p, int len)
+static inline void xram_copy_to(xram_p x, void *p, int len)
 {
        for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
                u32 tmp, *p32 = p;
@@ -135,7 +135,7 @@ static inline void xram_copy_to (xram_p x, void *p, int len)
        }
 }
 
-static inline void xram_bzero (xram_p x, int len)
+static inline void xram_bzero(xram_p x, int len)
 {
        for (len >>= 1; len > 0; len--, x += sizeof(u16))
                sbus_writew(0, x);
@@ -274,7 +274,7 @@ struct soc {
        soc_cq                  req[2]; /* Request CQs */
        soc_cq                  rsp[2]; /* Response CQs */
        int                     soc_no;
-       unsigned long           regs;
+       void __iomem            *regs;
        xram_p                  xram;
        fc_wwn                  wwn;
        u32                     imask;  /* Our copy of regs->imask */
index e158d7d..5ee4dda 100644 (file)
@@ -60,7 +60,7 @@ static char *version =
 #define for_each_socal(s) for (s = socals; s; s = s->next)
 struct socal *socals = NULL;
 
-static void socal_copy_from_xram(void *d, unsigned long xram, long size)
+static void socal_copy_from_xram(void *d, void __iomem *xram, long size)
 {
        u32 *dp = (u32 *) d;
        while (size) {
@@ -70,7 +70,7 @@ static void socal_copy_from_xram(void *d, unsigned long xram, long size)
        }
 }
 
-static void socal_copy_to_xram(unsigned long xram, void *s, long size)
+static void socal_copy_to_xram(void __iomem *xram, void *s, long size)
 {
        u32 *sp = (u32 *) s;
        while (size) {
index a853fad..2ff386b 100644 (file)
@@ -295,9 +295,9 @@ struct socal {
        socal_cq                req[4]; /* Request CQs */
        socal_cq                rsp[4]; /* Response CQs */
        int                     socal_no;
-       unsigned long           regs;
-       unsigned long           xram;
-       unsigned long           eeprom;
+       void __iomem            *regs;
+       void __iomem            *xram;
+       void __iomem            *eeprom;
        fc_wwn                  wwn;
        u32                     imask;  /* Our copy of regs->imask */
        u32                     cfg;    /* Our copy of regs->cfg */
index 2b48079..cd17039 100644 (file)
@@ -7,6 +7,9 @@ obj-$(CONFIG_I2C_CHARDEV)       += i2c-dev.o
 obj-$(CONFIG_I2C_SENSOR)       += i2c-sensor.o
 obj-y                          += busses/ chips/ algos/
 
+i2c-sensor-objs := i2c-sensor-detect.o i2c-sensor-vid.o
+
+
 ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
index 88982cd..cf9832b 100644 (file)
@@ -27,6 +27,17 @@ config I2C_ALGOPCF
          This support is also available as a module.  If so, the module 
          will be called i2c-algo-pcf.
 
+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
+         Y to the specific driver for you adapter below.
+
+         This support is also available as a module.  If so, the module 
+         will be called i2c-algo-pca.
+
 config I2C_ALGOITE
        tristate "ITE I2C Algorithm"
        depends on MIPS_ITE8172 && I2C
index df88f3f..3545644 100644 (file)
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_I2C_ALGOBIT)      += i2c-algo-bit.o
 obj-$(CONFIG_I2C_ALGOPCF)      += i2c-algo-pcf.o
+obj-$(CONFIG_I2C_ALGOPCA)      += i2c-algo-pca.o
 obj-$(CONFIG_I2C_ALGOITE)      += i2c-algo-ite.o
 
 ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
index acc7ab6..7405aac 100644 (file)
 #define        PM_IBSR         IT8172_PCI_IO_BASE + IT_PM_DSR + 0x04 
 #define GPIO_CCR       IT8172_PCI_IO_BASE + IT_GPCCR
 
-/* ----- global defines ----------------------------------------------- */
-#define DEB(x) if (i2c_debug>=1) x
 #define DEB2(x) if (i2c_debug>=2) x
 #define DEB3(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 */
 #define DEF_TIMEOUT 16
 
 
-/* ----- global variables ---------------------------------------------        */
-
 /* module parameters:
  */
-static int i2c_debug=1;
-static int iic_test=0; /* see if the line-setting functions work       */
+static int i2c_debug;
+static int iic_test;   /* see if the line-setting functions work       */
 
 /* --- setting states on the bus with the right timing: ---------------        */
 
@@ -804,8 +798,8 @@ MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
 MODULE_DESCRIPTION("ITE iic algorithm");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(iic_test, "i");
-MODULE_PARM(i2c_debug,"i");
+module_param(iic_test, bool, 0);
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
 
 MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available");
 MODULE_PARM_DESC(i2c_debug,
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
new file mode 100644 (file)
index 0000000..38092b7
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ *  i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters                
+ *    Copyright (C) 2004 Arcom Control Systems
+ *
+ *  This program is free software; you can redistribute 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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-pca.h>
+#include "i2c-algo-pca.h"
+
+#define DRIVER "i2c-algo-pca"
+
+#define DEB1(fmt, args...) do { if (i2c_debug>=1) printk(fmt, ## args); } while(0)
+#define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
+#define DEB3(fmt, args...) do { if (i2c_debug>=3) printk(fmt, ## args); } while(0)
+
+static int i2c_debug=0;
+
+#define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
+#define pca_inw(adap, reg) adap->read_byte(adap, reg)
+
+#define pca_status(adap) pca_inw(adap, I2C_PCA_STA)
+#define pca_clock(adap) adap->get_clock(adap)
+#define pca_own(adap) adap->get_own(adap)
+#define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
+#define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
+#define pca_wait(adap) adap->wait_for_interrupt(adap)
+
+/*
+ * Generate a start condition on the i2c bus.
+ *
+ * returns after the start condition has occured
+ */
+static void pca_start(struct i2c_algo_pca_data *adap)
+{
+       int sta = pca_get_con(adap);
+       DEB2("=== START\n");
+       sta |= I2C_PCA_CON_STA;
+       sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI);
+       pca_set_con(adap, sta);
+       pca_wait(adap);
+}
+
+/*
+ * Generate a repeated start condition on the i2c bus 
+ *
+ * return after the repeated start condition has occured
+ */
+static void pca_repeated_start(struct i2c_algo_pca_data *adap)
+{
+       int sta = pca_get_con(adap);
+       DEB2("=== REPEATED START\n");
+       sta |= I2C_PCA_CON_STA;
+       sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI);
+       pca_set_con(adap, sta);
+       pca_wait(adap);
+}
+
+/*
+ * Generate a stop condition on the i2c bus
+ *
+ * returns after the stop condition has been generated
+ *
+ * STOPs do not generate an interrupt or set the SI flag, since the
+ * part returns the the idle state (0xf8). Hence we don't need to
+ * pca_wait here.
+ */
+static void pca_stop(struct i2c_algo_pca_data *adap)
+{
+       int sta = pca_get_con(adap);
+       DEB2("=== STOP\n");
+       sta |= I2C_PCA_CON_STO;
+       sta &= ~(I2C_PCA_CON_STA|I2C_PCA_CON_SI);
+       pca_set_con(adap, sta);
+}
+
+/*
+ * Send the slave address and R/W bit
+ *
+ * returns after the address has been sent
+ */
+static void pca_address(struct i2c_algo_pca_data *adap, 
+                       struct i2c_msg *msg)
+{
+       int sta = pca_get_con(adap);
+       int addr;
+
+       addr = ( (0x7f & msg->addr) << 1 );
+       if (msg->flags & I2C_M_RD )
+               addr |= 1;
+       DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n", 
+            msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr);
+       
+       pca_outw(adap, I2C_PCA_DAT, addr);
+
+       sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
+       pca_set_con(adap, sta);
+
+       pca_wait(adap);
+}
+
+/*
+ * Transmit a byte.
+ *
+ * Returns after the byte has been transmitted
+ */
+static void pca_tx_byte(struct i2c_algo_pca_data *adap, 
+                       __u8 b)
+{
+       int sta = pca_get_con(adap);
+       DEB2("=== WRITE %#04x\n", b);
+       pca_outw(adap, I2C_PCA_DAT, b);
+
+       sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
+       pca_set_con(adap, sta);
+
+       pca_wait(adap);
+}
+
+/*
+ * Receive a byte
+ *
+ * returns immediately.
+ */
+static void pca_rx_byte(struct i2c_algo_pca_data *adap, 
+                       __u8 *b, int ack)
+{
+       *b = pca_inw(adap, I2C_PCA_DAT);
+       DEB2("=== READ %#04x %s\n", *b, ack ? "ACK" : "NACK");
+}
+
+/* 
+ * Setup ACK or NACK for next received byte and wait for it to arrive.
+ *
+ * Returns after next byte has arrived.
+ */
+static void pca_rx_ack(struct i2c_algo_pca_data *adap, 
+                      int ack)
+{
+       int sta = pca_get_con(adap);
+
+       sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI|I2C_PCA_CON_AA);
+
+       if ( ack )
+               sta |= I2C_PCA_CON_AA;
+
+       pca_set_con(adap, sta);
+       pca_wait(adap);
+}
+
+/* 
+ * Reset the i2c bus / SIO 
+ */
+static void pca_reset(struct i2c_algo_pca_data *adap)
+{
+       /* apparently only an external reset will do it. not a lot can be done */
+       printk(KERN_ERR DRIVER ": Haven't figured out how to do a reset yet\n");
+}
+
+static int pca_xfer(struct i2c_adapter *i2c_adap,
+                    struct i2c_msg msgs[],
+                    int num)
+{
+        struct i2c_algo_pca_data *adap = i2c_adap->algo_data;
+        struct i2c_msg *msg = NULL;
+        int curmsg;
+       int numbytes = 0;
+       int state;
+
+       state = pca_status(adap);
+       if ( state != 0xF8 ) {
+               printk(KERN_ERR DRIVER ": bus is not idle. status is %#04x\n", state );
+               /* FIXME: what to do. Force stop ? */
+               return -EREMOTEIO;
+       }
+
+       DEB1("{{{ XFER %d messages\n", num);
+
+       if (i2c_debug>=2) {
+               for (curmsg = 0; curmsg < num; curmsg++) {
+                       int addr, i;
+                       msg = &msgs[curmsg];
+                       
+                       addr = (0x7f & msg->addr) ;
+               
+                       if (msg->flags & I2C_M_RD )
+                               printk(KERN_INFO "    [%02d] RD %d bytes from %#02x [%#02x, ...]\n", 
+                                      curmsg, msg->len, addr, (addr<<1) | 1);
+                       else {
+                               printk(KERN_INFO "    [%02d] WR %d bytes to %#02x [%#02x%s", 
+                                      curmsg, msg->len, addr, addr<<1,
+                                      msg->len == 0 ? "" : ", ");
+                               for(i=0; i < msg->len; i++)
+                                       printk("%#04x%s", msg->buf[i], i == msg->len - 1 ? "" : ", ");
+                               printk("]\n");
+                       }
+               }
+       }
+
+       curmsg = 0;
+       while (curmsg < num) {
+               state = pca_status(adap);
+
+               DEB3("STATE is 0x%02x\n", state);
+               msg = &msgs[curmsg];
+
+               switch (state) {
+               case 0xf8: /* On reset or stop the bus is idle */
+                       pca_start(adap);
+                       break;
+
+               case 0x08: /* A START condition has been transmitted */
+               case 0x10: /* A repeated start condition has been transmitted */
+                       pca_address(adap, msg);
+                       break;
+                       
+               case 0x18: /* SLA+W has been transmitted; ACK has been received */
+               case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */
+                       if (numbytes < msg->len) {
+                               pca_tx_byte(adap, msg->buf[numbytes]);
+                               numbytes++;
+                               break;
+                       }
+                       curmsg++; numbytes = 0;
+                       if (curmsg == num)
+                               pca_stop(adap);
+                       else
+                               pca_repeated_start(adap);
+                       break;
+
+               case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */
+                       DEB2("NOT ACK recieved after SLA+W\n");
+                       pca_stop(adap);
+                       return -EREMOTEIO;
+
+               case 0x40: /* SLA+R has been transmitted; ACK has been received */
+                       pca_rx_ack(adap, msg->len > 1);
+                       break;
+
+               case 0x50: /* Data bytes has been received; ACK has been returned */
+                       if (numbytes < msg->len) {
+                               pca_rx_byte(adap, &msg->buf[numbytes], 1);
+                               numbytes++;
+                               pca_rx_ack(adap, numbytes < msg->len - 1);
+                               break;
+                       } 
+                       curmsg++; numbytes = 0;
+                       if (curmsg == num)
+                               pca_stop(adap);
+                       else
+                               pca_repeated_start(adap);
+                       break;
+
+               case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */
+                       DEB2("NOT ACK received after SLA+R\n");
+                       pca_stop(adap);
+                       return -EREMOTEIO;
+
+               case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */
+                       DEB2("NOT ACK recieved after data byte\n");
+                       return -EREMOTEIO;
+
+               case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */
+                       DEB2("Arbitration lost\n");
+                       return -EREMOTEIO;
+                       
+               case 0x58: /* Data byte has been received; NOT ACK has been returned */
+                       if ( numbytes == msg->len - 1 ) {
+                               pca_rx_byte(adap, &msg->buf[numbytes], 0);
+                               curmsg++; numbytes = 0;
+                               if (curmsg == num)
+                                       pca_stop(adap);
+                               else
+                                       pca_repeated_start(adap);
+                       } else {
+                               DEB2("NOT ACK sent after data byte received. "
+                                    "Not final byte. numbytes %d. len %d\n",
+                                    numbytes, msg->len);
+                               pca_stop(adap);
+                               return -EREMOTEIO;
+                       }
+                       break;
+               case 0x70: /* Bus error - SDA stuck low */
+                       DEB2("BUS ERROR - SDA Stuck low\n");
+                       pca_reset(adap);
+                       return -EREMOTEIO;
+               case 0x90: /* Bus error - SCL stuck low */
+                       DEB2("BUS ERROR - SCL Stuck low\n");
+                       pca_reset(adap);
+                       return -EREMOTEIO;
+               case 0x00: /* Bus error during master or slave mode due to illegal START or STOP condition */
+                       DEB2("BUS ERROR - Illegal START or STOP\n");
+                       pca_reset(adap);
+                       return -EREMOTEIO;
+               default:
+                       printk(KERN_ERR DRIVER ": unhandled SIO state 0x%02x\n", state);
+                       break;
+               }
+               
+       }
+
+       DEB1(KERN_CRIT "}}} transfered %d messages. "
+            "status is %#04x. control is %#04x\n", 
+            num, pca_status(adap),
+            pca_get_con(adap));
+       return curmsg;
+}
+
+static u32 pca_func(struct i2c_adapter *adap)
+{
+        return I2C_FUNC_SMBUS_EMUL;
+}
+
+static int pca_init(struct i2c_algo_pca_data *adap)
+{
+       static int freqs[] = {330,288,217,146,88,59,44,36};
+       int own, clock;
+
+       own = pca_own(adap);
+       clock = pca_clock(adap);
+       DEB1(KERN_INFO DRIVER ": own address is %#04x\n", own);
+       DEB1(KERN_INFO DRIVER ": clock freqeuncy is %dkHz\n", freqs[clock]);
+
+       pca_outw(adap, I2C_PCA_ADR, own << 1);
+
+       pca_set_con(adap, I2C_PCA_CON_ENSIO | clock);
+       udelay(500); /* 500 Âµs for oscilator to stabilise */
+
+       return 0;
+}
+
+static struct i2c_algorithm pca_algo = {
+       .name           = "PCA9564 algorithm",
+       .id             = I2C_ALGO_PCA,
+       .master_xfer    = pca_xfer,
+       .functionality  = pca_func,
+};
+
+/* 
+ * registering functions to load algorithms at runtime 
+ */
+int i2c_pca_add_bus(struct i2c_adapter *adap)
+{
+       struct i2c_algo_pca_data *pca_adap = adap->algo_data;
+       int rval;
+
+       /* register new adapter to i2c module... */
+
+       adap->id |= pca_algo.id;
+       adap->algo = &pca_algo;
+
+       adap->timeout = 100;            /* default values, should       */
+       adap->retries = 3;              /* be replaced by defines       */
+
+       rval = pca_init(pca_adap);
+
+       if (!rval)
+               i2c_add_adapter(adap);
+
+       return rval;
+}
+
+int i2c_pca_del_bus(struct i2c_adapter *adap)
+{
+       return i2c_del_adapter(adap);
+}
+
+EXPORT_SYMBOL(i2c_pca_add_bus);
+EXPORT_SYMBOL(i2c_pca_del_bus);
+
+MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
+MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
+MODULE_LICENSE("GPL");
+
+module_param(i2c_debug, int, 0);
diff --git a/drivers/i2c/algos/i2c-algo-pca.h b/drivers/i2c/algos/i2c-algo-pca.h
new file mode 100644 (file)
index 0000000..2fee07e
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef I2C_PCA9564_H
+#define I2C_PCA9564_H 1
+
+#define I2C_PCA_STA            0x00 /* STATUS  Read Only  */
+#define I2C_PCA_TO             0x00 /* TIMEOUT Write Only */
+#define I2C_PCA_DAT            0x01 /* DATA    Read/Write */
+#define I2C_PCA_ADR            0x02 /* OWN ADR Read/Write */
+#define I2C_PCA_CON            0x03 /* CONTROL Read/Write */
+
+#define I2C_PCA_CON_AA         0x80 /* Assert Acknowledge */
+#define I2C_PCA_CON_ENSIO      0x40 /* Enable */
+#define I2C_PCA_CON_STA                0x20 /* Start */
+#define I2C_PCA_CON_STO                0x10 /* Stop */
+#define I2C_PCA_CON_SI         0x08 /* Serial Interrupt */
+#define I2C_PCA_CON_CR         0x07 /* Clock Rate (MASK) */
+
+#define I2C_PCA_CON_330kHz     0x00
+#define I2C_PCA_CON_288kHz     0x01
+#define I2C_PCA_CON_217kHz     0x02
+#define I2C_PCA_CON_146kHz     0x03
+#define I2C_PCA_CON_88kHz      0x04
+#define I2C_PCA_CON_59kHz      0x05
+#define I2C_PCA_CON_44kHz      0x06
+#define I2C_PCA_CON_36kHz      0x07
+
+#endif /* I2C_PCA9564_H */
index b53f65a..6dc807a 100644 (file)
@@ -38,8 +38,6 @@
 #include "i2c-algo-pcf.h"
 
 
-/* ----- global defines ----------------------------------------------- */
-#define DEB(x) if (i2c_debug>=1) x
 #define DEB2(x) if (i2c_debug>=2) x
 #define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/
 #define DEBPROTO(x) if (i2c_debug>=9) x;
@@ -48,7 +46,7 @@
 
 /* module parameters:
  */
-static int i2c_debug=0;
+static int i2c_debug;
 
 /* --- setting states on the bus with the right timing: ---------------        */
 
@@ -101,12 +99,6 @@ static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
 }
 
 
-static inline void pcf_sleep(unsigned long timeout)
-{
-       schedule_timeout( timeout * HZ);
-}
-
-
 static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
 
        int timeout = DEF_TIMEOUT;
@@ -472,6 +464,6 @@ MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
 MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(i2c_debug,"i");
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(i2c_debug,
         "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
index 7d6d691..275da79 100644 (file)
@@ -158,7 +158,7 @@ static void __devexit hydra_remove(struct pci_dev *dev)
 
 
 static struct pci_driver hydra_driver = {
-       .name           = "hydra smbus",
+       .name           = "hydra_smbus",
        .id_table       = hydra_ids,
        .probe          = hydra_probe,
        .remove         = __devexit_p(hydra_remove),
index fd11366..46bd566 100644 (file)
@@ -231,7 +231,7 @@ static void __devexit i810_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver i810_driver = {
-       .name           = "i810 smbus",
+       .name           = "i810_smbus",
        .id_table       = i810_ids,
        .probe          = i810_probe,
        .remove         = __devexit_p(i810_remove),
index 917759c..da926a6 100644 (file)
 #define DEFAULT_CLOCK 0x1b0e   /* default 16MHz/(27+14) = 400KHz */
 #define DEFAULT_OWN   0x55
 
-static int base  = 0;
-static int irq   = 0;
-static int clock = 0;
-static int own   = 0;
+static int base;
+static int irq;
+static int clock;
+static int own;
 
 static struct iic_ite gpi;
 static wait_queue_head_t iic_wait;
@@ -102,14 +102,6 @@ static int iic_ite_getclock(void *data)
 }
 
 
-#if 0
-static void iic_ite_sleep(unsigned long timeout)
-{
-       schedule_timeout( timeout * HZ);
-}
-#endif
-
-
 /* Put this process to sleep.  We will wake up when the
  * IIC controller interrupts.
  */
@@ -254,10 +246,10 @@ MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
 MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(base, "i");
-MODULE_PARM(irq, "i");
-MODULE_PARM(clock, "i");
-MODULE_PARM(own, "i");
+module_param(base, int, 0);
+module_param(irq, int, 0);
+module_param(clock, int, 0);
+module_param(own, int, 0);
 
 
 /* Called when module is loaded or when kernel is initialized.
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
new file mode 100644 (file)
index 0000000..21cd54d
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * drivers/i2c/busses/i2c-ixp2000.c
+ *
+ * I2C adapter for IXP2000 systems using GPIOs for I2C bus
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ * Based on IXDP2400 code by: Naeem M. Afzal <naeem.m.afzal@intel.com>
+ * Made generic by: Jeff Daly <jeffrey.daly@intel.com>
+ *
+ * Copyright (c) 2003-2004 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.
+ *
+ * From Jeff Daly:
+ *
+ * I2C adapter driver for Intel IXDP2xxx platforms. This should work for any
+ * IXP2000 platform if it uses the HW GPIO in the same manner.  Basically, 
+ * SDA and SCL GPIOs have external pullups.  Setting the respective GPIO to 
+ * an input will make the signal a '1' via the pullup.  Setting them to 
+ * outputs will pull them down. 
+ *
+ * The GPIOs are open drain signals and are used as configuration strap inputs
+ * during power-up so there's generally a buffer on the board that needs to be 
+ * 'enabled' to drive the GPIOs.
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_I2C_DEBUG_BUS
+#define DEBUG  1
+#endif
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/hardware.h>      /* Pick up IXP42000-specific bits */
+
+static inline int ixp2000_scl_pin(void *data)
+{
+       return ((struct ixp2000_i2c_pins*)data)->scl_pin;
+}
+
+static inline int ixp2000_sda_pin(void *data)
+{
+       return ((struct ixp2000_i2c_pins*)data)->sda_pin;
+}
+
+
+static void ixp2000_bit_setscl(void *data, int val)
+{
+       int i = 5000;
+
+       if (val) {
+               gpio_line_config(ixp2000_scl_pin(data), GPIO_IN);
+               while(!gpio_line_get(ixp2000_scl_pin(data)) && i--);
+       } else {
+               gpio_line_config(ixp2000_scl_pin(data), GPIO_OUT);
+       }
+}
+
+static void ixp2000_bit_setsda(void *data, int val)
+{
+       if (val) {
+               gpio_line_config(ixp2000_sda_pin(data), GPIO_IN);
+       } else {
+               gpio_line_config(ixp2000_sda_pin(data), GPIO_OUT);
+       }
+}
+
+static int ixp2000_bit_getscl(void *data)
+{
+       return gpio_line_get(ixp2000_scl_pin(data));
+}
+
+static int ixp2000_bit_getsda(void *data)
+{
+       return gpio_line_get(ixp2000_sda_pin(data));
+}
+
+struct ixp2000_i2c_data {
+       struct ixp2000_i2c_pins *gpio_pins;
+       struct i2c_adapter adapter;
+       struct i2c_algo_bit_data algo_data;
+};
+
+static int ixp2000_i2c_remove(struct device *dev)
+{
+       struct platform_device *plat_dev = to_platform_device(dev);
+       struct ixp2000_i2c_data *drv_data = dev_get_drvdata(&plat_dev->dev);
+
+       dev_set_drvdata(&plat_dev->dev, NULL);
+
+       i2c_bit_del_bus(&drv_data->adapter);
+
+       kfree(drv_data);
+
+       return 0;
+}
+
+static int ixp2000_i2c_probe(struct device *dev)
+{
+       int err;
+       struct platform_device *plat_dev = to_platform_device(dev);
+       struct ixp2000_i2c_pins *gpio = plat_dev->dev.platform_data;
+       struct ixp2000_i2c_data *drv_data = 
+               kmalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
+
+       if (!drv_data)
+               return -ENOMEM;
+       memzero(drv_data, sizeof(*drv_data));
+       drv_data->gpio_pins = gpio;
+
+       drv_data->algo_data.data = gpio;
+       drv_data->algo_data.setsda = ixp2000_bit_setsda;
+       drv_data->algo_data.setscl = ixp2000_bit_setscl;
+       drv_data->algo_data.getsda = ixp2000_bit_getsda;
+       drv_data->algo_data.getscl = ixp2000_bit_getscl;
+       drv_data->algo_data.udelay = 6;
+       drv_data->algo_data.mdelay = 6;
+       drv_data->algo_data.timeout = 100;
+
+       drv_data->adapter.id = I2C_HW_B_IXP2000,
+       drv_data->adapter.algo_data = &drv_data->algo_data,
+
+       drv_data->adapter.dev.parent = &plat_dev->dev;
+
+       gpio_line_config(gpio->sda_pin, GPIO_IN);
+       gpio_line_config(gpio->scl_pin, GPIO_IN);
+       gpio_line_set(gpio->scl_pin, 0);
+       gpio_line_set(gpio->sda_pin, 0);
+
+       if ((err = i2c_bit_add_bus(&drv_data->adapter)) != 0) {
+               dev_err(dev, "Could not install, error %d\n", err);
+               kfree(drv_data);
+               return err;
+       } 
+
+       dev_set_drvdata(&plat_dev->dev, drv_data);
+
+       return 0;
+}
+
+static struct device_driver ixp2000_i2c_driver = {
+       .name           = "IXP2000-I2C",
+       .bus            = &platform_bus_type,
+       .probe          = ixp2000_i2c_probe,
+       .remove         = ixp2000_i2c_remove,
+};
+
+static int __init ixp2000_i2c_init(void)
+{
+       return driver_register(&ixp2000_i2c_driver);
+}
+
+static void __exit ixp2000_i2c_exit(void)
+{
+       driver_unregister(&ixp2000_i2c_driver);
+}
+
+module_init(ixp2000_i2c_init);
+module_exit(ixp2000_i2c_exit);
+
+MODULE_AUTHOR ("Deepak Saxena <dsaxena@plexity.net>");
+MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
new file mode 100644 (file)
index 0000000..f77245e
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * (C) Copyright 2003-2004
+ * Humboldt Solutions Ltd, adrian@humboldt.co.uk.
+ * This is a combined i2c adapter and algorithm driver for the
+ * MPC107/Tsi107 PowerPC northbridge and processors that include
+ * the same I2C unit (8240, 8245, 85xx). 
+ *
+ * Release 0.6
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/ocp.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+
+#define MPC_I2C_ADDR  0x00
+#define MPC_I2C_FDR    0x04
+#define MPC_I2C_CR     0x08
+#define MPC_I2C_SR     0x0c
+#define MPC_I2C_DR     0x10
+#define MPC_I2C_DFSRR 0x14
+#define MPC_I2C_REGION 0x20
+
+#define CCR_MEN  0x80
+#define CCR_MIEN 0x40
+#define CCR_MSTA 0x20
+#define CCR_MTX  0x10
+#define CCR_TXAK 0x08
+#define CCR_RSTA 0x04
+
+#define CSR_MCF  0x80
+#define CSR_MAAS 0x40
+#define CSR_MBB  0x20
+#define CSR_MAL  0x10
+#define CSR_SRW  0x04
+#define CSR_MIF  0x02
+#define CSR_RXAK 0x01
+
+struct mpc_i2c {
+       char *base;
+       struct ocp_def *ocpdef;
+       u32 interrupt;
+       wait_queue_head_t queue;
+       struct i2c_adapter adap;
+};
+
+static __inline__ void writeccr(struct mpc_i2c *i2c, u32 x)
+{
+       writeb(x, i2c->base + MPC_I2C_CR);
+}
+
+static irqreturn_t mpc_i2c_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct mpc_i2c *i2c = dev_id;
+       if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) {
+               /* Read again to allow register to stabilise */
+               i2c->interrupt = readb(i2c->base + MPC_I2C_SR);
+               writeb(0, i2c->base + MPC_I2C_SR);
+               wake_up_interruptible(&i2c->queue);
+       }
+       return IRQ_HANDLED;
+}
+
+static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       unsigned long orig_jiffies = jiffies;
+       u32 x;
+       int result = 0;
+
+       if (i2c->ocpdef->irq == OCP_IRQ_NA) {
+               while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) {
+                       schedule();
+                       if (time_after(jiffies, orig_jiffies + timeout)) {
+                               pr_debug("I2C: timeout\n");
+                               result = -EIO;
+                               break;
+                       }
+               }
+               x = readb(i2c->base + MPC_I2C_SR);
+               writeb(0, i2c->base + MPC_I2C_SR);
+       } else {
+               add_wait_queue(&i2c->queue, &wait);
+               while (!(i2c->interrupt & CSR_MIF)) {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       if (signal_pending(current)) {
+                               pr_debug("I2C: Interrupted\n");
+                               result = -EINTR;
+                               break;
+                       }
+                       if (time_after(jiffies, orig_jiffies + timeout)) {
+                               pr_debug("I2C: timeout\n");
+                               result = -EIO;
+                               break;
+                       }
+                       schedule_timeout(timeout);
+               }
+               current->state = TASK_RUNNING;
+               remove_wait_queue(&i2c->queue, &wait);
+               x = i2c->interrupt;
+               i2c->interrupt = 0;
+       }
+
+       if (result < -0)
+               return result;
+
+       if (!(x & CSR_MCF)) {
+               pr_debug("I2C: unfinished\n");
+               return -EIO;
+       }
+
+       if (x & CSR_MAL) {
+               pr_debug("I2C: MAL\n");
+               return -EIO;
+       }
+
+       if (writing && (x & CSR_RXAK)) {
+               pr_debug("I2C: No RXAK\n");
+               /* generate stop */
+               writeccr(i2c, CCR_MEN);
+               return -EIO;
+       }
+       return 0;
+}
+
+static void mpc_i2c_setclock(struct mpc_i2c *i2c)
+{
+       struct ocp_fs_i2c_data *i2c_data = i2c->ocpdef->additions;
+       /* Set clock and filters */
+       if (i2c_data && (i2c_data->flags & FS_I2C_SEPARATE_DFSRR)) {
+               writeb(0x31, i2c->base + MPC_I2C_FDR);
+               writeb(0x10, i2c->base + MPC_I2C_DFSRR);
+       } else if (i2c_data && (i2c_data->flags & FS_I2C_CLOCK_5200))
+               writeb(0x3f, i2c->base + MPC_I2C_FDR);
+       else
+               writel(0x1031, i2c->base + MPC_I2C_FDR);
+}
+
+static void mpc_i2c_start(struct mpc_i2c *i2c)
+{
+       /* Clear arbitration */
+       writeb(0, i2c->base + MPC_I2C_SR);
+       /* Start with MEN */
+       writeccr(i2c, CCR_MEN);
+}
+
+static void mpc_i2c_stop(struct mpc_i2c *i2c)
+{
+       writeccr(i2c, CCR_MEN);
+}
+
+static int mpc_write(struct mpc_i2c *i2c, int target,
+                    const u8 * data, int length, int restart)
+{
+       int i;
+       unsigned timeout = HZ;
+       u32 flags = restart ? CCR_RSTA : 0;
+
+       /* Start with MEN */
+       if (!restart)
+               writeccr(i2c, CCR_MEN);
+       /* Start as master */
+       writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
+       /* Write target byte */
+       writeb((target << 1), i2c->base + MPC_I2C_DR);
+
+       if (i2c_wait(i2c, timeout, 1) < 0)
+               return -1;
+
+       for (i = 0; i < length; i++) {
+               /* Write data byte */
+               writeb(data[i], i2c->base + MPC_I2C_DR);
+
+               if (i2c_wait(i2c, timeout, 1) < 0)
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int mpc_read(struct mpc_i2c *i2c, int target,
+                   u8 * data, int length, int restart)
+{
+       unsigned timeout = HZ;
+       int i;
+       u32 flags = restart ? CCR_RSTA : 0;
+
+       /* Start with MEN */
+       if (!restart)
+               writeccr(i2c, CCR_MEN);
+       /* Switch to read - restart */
+       writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
+       /* Write target address byte - this time with the read flag set */
+       writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
+
+       if (i2c_wait(i2c, timeout, 1) < 0)
+               return -1;
+
+       if (length) {
+               if (length == 1)
+                       writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
+               else
+                       writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA);
+               /* Dummy read */
+               readb(i2c->base + MPC_I2C_DR);
+       }
+
+       for (i = 0; i < length; i++) {
+               if (i2c_wait(i2c, timeout, 0) < 0)
+                       return -1;
+
+               /* Generate txack on next to last byte */
+               if (i == length - 2)
+                       writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
+               /* Generate stop on last byte */
+               if (i == length - 1)
+                       writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
+               data[i] = readb(i2c->base + MPC_I2C_DR);
+       }
+
+       return length;
+}
+
+static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+       struct i2c_msg *pmsg;
+       int i;
+       int ret = 0;
+       unsigned long orig_jiffies = jiffies;
+       struct mpc_i2c *i2c = i2c_get_adapdata(adap);
+
+       mpc_i2c_start(i2c);
+
+       /* Allow bus up to 1s to become not busy */
+       while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) {
+               if (signal_pending(current)) {
+                       pr_debug("I2C: Interrupted\n");
+                       return -EINTR;
+               }
+               if (time_after(jiffies, orig_jiffies + HZ)) {
+                       pr_debug("I2C: timeout\n");
+                       return -EIO;
+               }
+               schedule();
+       }
+
+       for (i = 0; ret >= 0 && i < num; i++) {
+               pmsg = &msgs[i];
+               pr_debug("Doing %s %d bytes to 0x%02x - %d of %d messages\n",
+                        pmsg->flags & I2C_M_RD ? "read" : "write",
+                        pmsg->len, pmsg->addr, i + 1, num);
+               if (pmsg->flags & I2C_M_RD)
+                       ret =
+                           mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
+               else
+                       ret =
+                           mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
+       }
+       mpc_i2c_stop(i2c);
+       return (ret < 0) ? ret : num;
+}
+
+static u32 mpc_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm mpc_algo = {
+       .name = "MPC algorithm",
+       .id = I2C_ALGO_MPC107,
+       .master_xfer = mpc_xfer,
+       .functionality = mpc_functionality,
+};
+
+static struct i2c_adapter mpc_ops = {
+       .owner = THIS_MODULE,
+       .name = "MPC adapter",
+       .id = I2C_ALGO_MPC107 | I2C_HW_MPC107,
+       .algo = &mpc_algo,
+       .class = I2C_CLASS_HWMON,
+       .timeout = 1,
+       .retries = 1
+};
+
+static int __devinit mpc_i2c_probe(struct ocp_device *ocp)
+{
+       int result = 0;
+       struct mpc_i2c *i2c;
+
+       if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
+               return -ENOMEM;
+       }
+       i2c->ocpdef = ocp->def;
+       init_waitqueue_head(&i2c->queue);
+
+       if (!request_mem_region(ocp->def->paddr, MPC_I2C_REGION, "i2c-mpc")) {
+               printk(KERN_ERR "i2c-mpc - resource unavailable\n");
+               return -ENODEV;
+       }
+
+       i2c->base = ioremap(ocp->def->paddr, MPC_I2C_REGION);
+
+       if (!i2c->base) {
+               printk(KERN_ERR "i2c-mpc - failed to map controller\n");
+               result = -ENOMEM;
+               goto fail_map;
+       }
+
+       if (ocp->def->irq != OCP_IRQ_NA)
+               if ((result = request_irq(ocp->def->irq, mpc_i2c_isr,
+                                         0, "i2c-mpc", i2c)) < 0) {
+                       printk(KERN_ERR
+                              "i2c-mpc - failed to attach interrupt\n");
+                       goto fail_irq;
+               }
+
+       i2c->adap = mpc_ops;
+       i2c_set_adapdata(&i2c->adap, i2c);
+       if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
+               printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
+               goto fail_add;
+       }
+
+       mpc_i2c_setclock(i2c);
+       ocp_set_drvdata(ocp, i2c);
+       return result;
+
+      fail_add:
+       if (ocp->def->irq != OCP_IRQ_NA)
+               free_irq(ocp->def->irq, 0);
+      fail_irq:
+       iounmap(i2c->base);
+      fail_map:
+       release_mem_region(ocp->def->paddr, MPC_I2C_REGION);
+       kfree(i2c);
+       return result;
+}
+static void __devexit mpc_i2c_remove(struct ocp_device *ocp)
+{
+       struct mpc_i2c *i2c = ocp_get_drvdata(ocp);
+       ocp_set_drvdata(ocp, NULL);
+       i2c_del_adapter(&i2c->adap);
+
+       if (ocp->def->irq != OCP_IRQ_NA)
+               free_irq(i2c->ocpdef->irq, i2c);
+       iounmap(i2c->base);
+       release_mem_region(i2c->ocpdef->paddr, MPC_I2C_REGION);
+       kfree(i2c);
+}
+
+static struct ocp_device_id mpc_iic_ids[] __devinitdata = {
+       {.vendor = OCP_VENDOR_FREESCALE,.function = OCP_FUNC_IIC},
+       {.vendor = OCP_VENDOR_INVALID}
+};
+
+MODULE_DEVICE_TABLE(ocp, mpc_iic_ids);
+
+static struct ocp_driver mpc_iic_driver = {
+       .name = "iic",
+       .id_table = mpc_iic_ids,
+       .probe = mpc_i2c_probe,
+       .remove = __devexit_p(mpc_i2c_remove)
+};
+
+static int __init iic_init(void)
+{
+       return ocp_register_driver(&mpc_iic_driver);
+}
+
+static void __exit iic_exit(void)
+{
+       ocp_unregister_driver(&mpc_iic_driver);
+}
+
+module_init(iic_init);
+module_exit(iic_exit);
+
+MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
+MODULE_DESCRIPTION
+    ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
new file mode 100644 (file)
index 0000000..9c61113
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ *  i2c-pca-isa.c driver for PCA9564 on ISA boards
+ *    Copyright (C) 2004 Arcom Control Systems
+ *
+ *  This program is free software; you can redistribute 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/config.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/wait.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-pca.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "../algos/i2c-algo-pca.h"
+
+#define IO_SIZE 4
+
+#undef DEBUG_IO
+//#define DEBUG_IO
+
+static unsigned long base   = 0x330;
+static int irq           = 10;
+
+/* Data sheet recommends 59kHz for 100kHz operation due to variation
+ * in the actual clock rate */
+static int clock  = I2C_PCA_CON_59kHz;
+
+static int own    = 0x55;
+
+static wait_queue_head_t pca_wait;
+
+static int pca_isa_getown(struct i2c_algo_pca_data *adap)
+{
+       return (own);
+}
+
+static int pca_isa_getclock(struct i2c_algo_pca_data *adap)
+{
+       return (clock);
+}
+
+static void
+pca_isa_writebyte(struct i2c_algo_pca_data *adap, int reg, int val)
+{
+#ifdef DEBUG_IO
+       static char *names[] = { "T/O", "DAT", "ADR", "CON" };
+       printk("*** write %s at %#lx <= %#04x\n", names[reg], base+reg, val);
+#endif
+       outb(val, base+reg);
+}
+
+static int
+pca_isa_readbyte(struct i2c_algo_pca_data *adap, int reg)
+{
+       int res = inb(base+reg);
+#ifdef DEBUG_IO
+       {
+               static char *names[] = { "STA", "DAT", "ADR", "CON" };  
+               printk("*** read  %s => %#04x\n", names[reg], res);
+       }
+#endif
+       return res;
+}
+
+static int pca_isa_waitforinterrupt(struct i2c_algo_pca_data *adap)
+{
+       int ret = 0;
+
+       if (irq > -1) {
+               ret = wait_event_interruptible(pca_wait,
+                                              pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI);
+       } else {
+               while ((pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) 
+                       udelay(100);
+       }
+       return ret;
+}
+
+static irqreturn_t pca_handler(int this_irq, void *dev_id, struct pt_regs *regs) {
+       wake_up_interruptible(&pca_wait);
+       return IRQ_HANDLED;
+}
+
+static struct i2c_algo_pca_data pca_isa_data = {
+       .get_own                = pca_isa_getown,
+       .get_clock              = pca_isa_getclock,
+       .write_byte             = pca_isa_writebyte,
+       .read_byte              = pca_isa_readbyte,
+       .wait_for_interrupt     = pca_isa_waitforinterrupt,
+};
+
+static struct i2c_adapter pca_isa_ops = {
+       .owner          = THIS_MODULE,
+       .id             = I2C_HW_A_ISA,
+       .algo_data      = &pca_isa_data,
+       .name           = "PCA9564 ISA Adapter",
+};
+
+static int __init pca_isa_init(void)
+{
+
+       init_waitqueue_head(&pca_wait);
+
+       printk(KERN_INFO "i2c-pca-isa: 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);
+               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);
+                       goto out_region;
+               }
+       }
+
+       if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
+               printk(KERN_ERR "i2c-pca-isa: Failed to add i2c bus\n");
+               goto out_irq;
+       }
+
+       return 0;
+
+ out_irq:
+       if (irq > -1)
+               free_irq(irq, &pca_isa_ops);
+ out_region:
+       release_region(base, IO_SIZE);
+ out:
+       return -ENODEV;
+}
+
+static void pca_isa_exit(void)
+{
+       i2c_pca_del_bus(&pca_isa_ops);
+
+       if (irq > 0) {
+               disable_irq(irq);
+               free_irq(irq, &pca_isa_ops);
+       }
+       release_region(base, IO_SIZE);
+}
+
+MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
+MODULE_DESCRIPTION("ISA base PCA9564 driver");
+MODULE_LICENSE("GPL");
+
+module_param(base, ulong, 0);
+MODULE_PARM_DESC(base, "I/O base address");
+
+module_param(irq, int, 0);
+MODULE_PARM_DESC(irq, "IRQ");
+module_param(clock, int, 0);
+MODULE_PARM_DESC(clock, "Clock rate as described in table 1 of PCA9564 datasheet");
+
+module_param(own, int, 0); /* the driver can't do slave mode, so there's no real point in this */
+
+module_init(pca_isa_init);
+module_exit(pca_isa_exit);
index 0aabe49..9552e53 100644 (file)
@@ -314,7 +314,7 @@ static struct pci_device_id prosavage_pci_tbl[] = {
 };
 
 static struct pci_driver prosavage_driver = {
-       .name           =       "prosavage-smbus",
+       .name           =       "prosavage_smbus",
        .id_table       =       prosavage_pci_tbl,
        .probe          =       prosavage_probe,
        .remove         =       prosavage_remove,
index 33972a7..52d5194 100644 (file)
@@ -178,7 +178,7 @@ static void __devexit savage4_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver savage4_driver = {
-       .name           = "savage4 smbus",
+       .name           = "savage4_smbus",
        .id_table       = savage4_ids,
        .probe          = savage4_probe,
        .remove         = __devexit_p(savage4_remove),
index d38336f..711eaa2 100644 (file)
@@ -455,7 +455,7 @@ static void adm1025_init_client(struct i2c_client *client)
        struct adm1025_data *data = i2c_get_clientdata(client);
        int i;
 
-       data->vrm = 82;
+       data->vrm = i2c_which_vrm();
 
        /*
         * Set high limits
index bf3e214..3aa7298 100644 (file)
@@ -37,7 +37,7 @@ static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
 /* Insmod parameters */
 SENSORS_INSMOD_1(ds1621);
 static int polarity = -1;
-MODULE_PARM(polarity, "i");
+module_param(polarity, int, 0);
 MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low");
 
 /* Many DS1621 constants specified below */
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
new file mode 100644 (file)
index 0000000..11d0df3
--- /dev/null
@@ -0,0 +1,1660 @@
+/*
+ * isp1301_omap - ISP 1301 USB transceiver, talking to OMAP OTG controller
+ *
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004 David Brownell
+ *
+ * This program is free software; you can redistribute 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.
+ */
+#undef DEBUG
+#undef VERBOSE
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+#include <linux/usb.h>
+#include <linux/usb_otg.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+#include <asm/irq.h>
+#include <asm/arch/usb.h>
+
+
+#ifndef        DEBUG
+#undef VERBOSE
+#endif
+
+
+#define        DRIVER_VERSION  "24 August 2004"
+#define        DRIVER_NAME     (isp1301_driver.name)
+
+MODULE_DESCRIPTION("ISP1301 USB OTG Transceiver Driver");
+MODULE_LICENSE("GPL");
+
+struct isp1301 {
+       struct otg_transceiver  otg;
+       struct i2c_client       client;
+       void                    (*i2c_release)(struct device *dev);
+
+       int                     irq;
+
+       u32                     last_otg_ctrl;
+       unsigned                working:1;
+
+       struct timer_list       timer;
+
+       /* use keventd context to change the state for us */
+       struct work_struct      work;
+       
+       unsigned long           todo;
+#              define WORK_UPDATE_ISP  0       /* update ISP from OTG */
+#              define WORK_UPDATE_OTG  1       /* update OTG from ISP */
+#              define WORK_HOST_RESUME 4       /* resume host */
+#              define WORK_TIMER       6       /* timer fired */
+#              define WORK_STOP        7       /* don't resubmit */
+};
+
+
+/* bits in OTG_CTRL_REG */
+
+#define        OTG_XCEIV_OUTPUTS \
+       (OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
+#define        OTG_XCEIV_INPUTS \
+       (OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID)
+#define        OTG_CTRL_BITS \
+       (OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|OTG_B_HNPEN|OTG_BUSDROP)
+       /* and OTG_PULLUP is sometimes written */
+
+#define        OTG_CTRL_MASK   (OTG_DRIVER_SEL| \
+       OTG_XCEIV_OUTPUTS|OTG_XCEIV_INPUTS| \
+       OTG_CTRL_BITS)
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_MACH_OMAP_H2
+
+/* board-specific PM hooks */
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/mach-types.h>
+
+
+#if    defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
+
+#include <asm/arch/tps65010.h>
+
+#else
+
+static inline int tps65010_set_vbus_draw(unsigned mA)
+{
+       pr_debug("tps65010: draw %d mA (STUB)\n", mA);
+       return 0;
+}
+
+#endif
+
+static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
+{
+       int status = tps65010_set_vbus_draw(mA);
+       if (status < 0)
+               pr_debug("  VBUS %d mA error %d\n", mA, status);
+}
+
+static void enable_vbus_source(struct isp1301 *isp)
+{
+       /* this board won't supply more than 8mA vbus power.
+        * some boards can switch a 100ma "unit load" (or more).
+        */
+}
+
+
+/* products will deliver OTG messages with LEDs, GUI, etc */
+static inline void notresponding(struct isp1301 *isp)
+{
+       printk(KERN_NOTICE "OTG device not responding.\n");
+}
+
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* only two addresses possible */
+#define        ISP_BASE                0x2c
+static unsigned short normal_i2c[] = {
+       ISP_BASE, ISP_BASE + 1,
+       I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver isp1301_driver;
+
+/* smbus apis are used for portability */
+
+static inline u8
+isp1301_get_u8(struct isp1301 *isp, u8 reg)
+{
+       return i2c_smbus_read_byte_data(&isp->client, reg + 0);
+}
+
+static inline int
+isp1301_get_u16(struct isp1301 *isp, u8 reg)
+{
+       return i2c_smbus_read_word_data(&isp->client, reg);
+}
+
+static inline int
+isp1301_set_bits(struct isp1301 *isp, u8 reg, u8 bits)
+{
+       return i2c_smbus_write_byte_data(&isp->client, reg + 0, bits);
+}
+
+static inline int
+isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits)
+{
+       return i2c_smbus_write_byte_data(&isp->client, reg + 1, bits);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* identification */
+#define        ISP1301_VENDOR_ID               0x00    /* u16 read */
+#define        ISP1301_PRODUCT_ID              0x02    /* u16 read */
+#define        ISP1301_BCD_DEVICE              0x14    /* u16 read */
+
+#define        I2C_VENDOR_ID_PHILIPS           0x04cc
+#define        I2C_PRODUCT_ID_PHILIPS_1301     0x1301
+
+/* operational registers */
+#define        ISP1301_MODE_CONTROL_1          0x04    /* u8 read, set, +1 clear */
+#      define  MC1_SPEED_REG           (1 << 0)
+#      define  MC1_SUSPEND_REG         (1 << 1)
+#      define  MC1_DAT_SE0             (1 << 2)
+#      define  MC1_TRANSPARENT         (1 << 3)
+#      define  MC1_BDIS_ACON_EN        (1 << 4)
+#      define  MC1_OE_INT_EN           (1 << 5)
+#      define  MC1_UART_EN             (1 << 6)
+#      define  MC1_MASK                0x7f
+#define        ISP1301_MODE_CONTROL_2          0x12    /* u8 read, set, +1 clear */
+#      define  MC2_GLOBAL_PWR_DN       (1 << 0)
+#      define  MC2_SPD_SUSP_CTRL       (1 << 1)
+#      define  MC2_BI_DI               (1 << 2)
+#      define  MC2_TRANSP_BDIR0        (1 << 3)
+#      define  MC2_TRANSP_BDIR1        (1 << 4)
+#      define  MC2_AUDIO_EN            (1 << 5)
+#      define  MC2_PSW_EN              (1 << 6)
+#      define  MC2_EN2V7               (1 << 7)
+#define        ISP1301_OTG_CONTROL_1           0x06    /* u8 read, set, +1 clear */
+#      define  OTG1_DP_PULLUP          (1 << 0)
+#      define  OTG1_DM_PULLUP          (1 << 1)
+#      define  OTG1_DP_PULLDOWN        (1 << 2)
+#      define  OTG1_DM_PULLDOWN        (1 << 3)
+#      define  OTG1_ID_PULLDOWN        (1 << 4)
+#      define  OTG1_VBUS_DRV           (1 << 5)
+#      define  OTG1_VBUS_DISCHRG       (1 << 6)
+#      define  OTG1_VBUS_CHRG          (1 << 7)
+#define        ISP1301_OTG_STATUS              0x10    /* u8 readonly */
+#      define  OTG_B_SESS_END          (1 << 6)
+#      define  OTG_B_SESS_VLD          (1 << 7)
+
+#define        ISP1301_INTERRUPT_SOURCE        0x08    /* u8 read */
+#define        ISP1301_INTERRUPT_LATCH         0x0A    /* u8 read, set, +1 clear */
+
+#define        ISP1301_INTERRUPT_FALLING       0x0C    /* u8 read, set, +1 clear */
+#define        ISP1301_INTERRUPT_RISING        0x0E    /* u8 read, set, +1 clear */
+
+/* same bitfields in all interrupt registers */
+#      define  INTR_VBUS_VLD           (1 << 0)
+#      define  INTR_SESS_VLD           (1 << 1)
+#      define  INTR_DP_HI              (1 << 2)
+#      define  INTR_ID_GND             (1 << 3)
+#      define  INTR_DM_HI              (1 << 4)
+#      define  INTR_ID_FLOAT           (1 << 5)
+#      define  INTR_BDIS_ACON          (1 << 6)
+#      define  INTR_CR_INT             (1 << 7)
+
+/*-------------------------------------------------------------------------*/
+
+static const char *state_string(enum usb_otg_state state)
+{
+       switch (state) {
+       case OTG_STATE_A_IDLE:          return "a_idle";
+       case OTG_STATE_A_WAIT_VRISE:    return "a_wait_vrise";
+       case OTG_STATE_A_WAIT_BCON:     return "a_wait_bcon";
+       case OTG_STATE_A_HOST:          return "a_host";
+       case OTG_STATE_A_SUSPEND:       return "a_suspend";
+       case OTG_STATE_A_PERIPHERAL:    return "a_peripheral";
+       case OTG_STATE_A_WAIT_VFALL:    return "a_wait_vfall";
+       case OTG_STATE_A_VBUS_ERR:      return "a_vbus_err";
+       case OTG_STATE_B_IDLE:          return "b_idle";
+       case OTG_STATE_B_SRP_INIT:      return "b_srp_init";
+       case OTG_STATE_B_PERIPHERAL:    return "b_peripheral";
+       case OTG_STATE_B_WAIT_ACON:     return "b_wait_acon";
+       case OTG_STATE_B_HOST:          return "b_host";
+       default:                        return "UNDEFINED";
+       }
+}
+
+static inline const char *state_name(struct isp1301 *isp)
+{
+       return state_string(isp->otg.state);
+}
+
+#ifdef VERBOSE
+#define        dev_vdbg                        dev_dbg
+#else
+#define        dev_vdbg(dev, fmt, arg...)      do{}while(0)
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* NOTE:  some of this ISP1301 setup is specific to H2 boards;
+ * not everything is guarded by board-specific checks, or even using
+ * omap_usb_config data to deduce MC1_DAT_SE0 and MC2_BI_DI.
+ *
+ * ALSO:  this currently doesn't use ISP1301 low-power modes
+ * while OTG is running.
+ */
+
+static void power_down(struct isp1301 *isp)
+{
+       isp->otg.state = OTG_STATE_UNDEFINED;
+
+       // isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
+       isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND_REG);
+
+       isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_ID_PULLDOWN);
+       isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+}
+
+static void power_up(struct isp1301 *isp)
+{
+       // isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
+       isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND_REG);
+       
+       /* do this only when cpu is driving transceiver,
+        * so host won't see a low speed device...
+        */
+       isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+}
+
+#define        NO_HOST_SUSPEND
+
+static int host_suspend(struct isp1301 *isp)
+{
+#ifdef NO_HOST_SUSPEND
+       return 0;
+#else
+       struct device   *dev;
+
+       if (!isp->otg.host)
+               return -ENODEV;
+
+       /* Currently ASSUMES only the OTG port matters;
+        * other ports could be active...
+        */
+       dev = isp->otg.host->controller;
+       return dev->driver->suspend(dev, 3, 0);
+#endif
+}
+
+static int host_resume(struct isp1301 *isp)
+{
+#ifdef NO_HOST_SUSPEND
+       return 0;
+#else
+       struct device   *dev;
+
+       if (!isp->otg.host)
+               return -ENODEV;
+
+       dev = isp->otg.host->controller;
+       return dev->driver->resume(dev, 0);
+#endif
+}
+
+static int gadget_suspend(struct isp1301 *isp)
+{
+       isp->otg.gadget->b_hnp_enable = 0;
+       isp->otg.gadget->a_hnp_support = 0;
+       isp->otg.gadget->a_alt_hnp_support = 0;
+       return usb_gadget_vbus_disconnect(isp->otg.gadget);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define        TIMER_MINUTES   10
+#define        TIMER_JIFFIES   (TIMER_MINUTES * 60 * HZ)
+
+/* Almost all our I2C messaging comes from a work queue's task context.
+ * NOTE: guaranteeing certain response times might mean we shouldn't
+ * share keventd's work queue; a realtime task might be safest.
+ */
+void
+isp1301_defer_work(struct isp1301 *isp, int work)
+{
+       int status;
+
+       if (isp && !test_and_set_bit(work, &isp->todo)) {
+               (void) get_device(&isp->client.dev);
+               status = schedule_work(&isp->work);
+               if (!status && !isp->working)
+                       dev_vdbg(&isp->client.dev,
+                               "work item %d may be lost\n", work);
+       }
+}
+
+/* called from irq handlers */
+static void a_idle(struct isp1301 *isp, const char *tag)
+{
+       if (isp->otg.state == OTG_STATE_A_IDLE)
+               return;
+
+       isp->otg.default_a = 1;
+       if (isp->otg.host) {
+               isp->otg.host->is_b_host = 0;
+               host_suspend(isp);
+       }
+       if (isp->otg.gadget) {
+               isp->otg.gadget->is_a_peripheral = 1;
+               gadget_suspend(isp);
+       }
+       isp->otg.state = OTG_STATE_A_IDLE;
+       isp->last_otg_ctrl = OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
+       pr_debug("  --> %s/%s\n", state_name(isp), tag);
+}
+
+/* called from irq handlers */
+static void b_idle(struct isp1301 *isp, const char *tag)
+{
+       if (isp->otg.state == OTG_STATE_B_IDLE)
+               return;
+
+       isp->otg.default_a = 0;
+       if (isp->otg.host) {
+               isp->otg.host->is_b_host = 1;
+               host_suspend(isp);
+       }
+       if (isp->otg.gadget) {
+               isp->otg.gadget->is_a_peripheral = 0;
+               gadget_suspend(isp);
+       }
+       isp->otg.state = OTG_STATE_B_IDLE;
+       isp->last_otg_ctrl = OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
+       pr_debug("  --> %s/%s\n", state_name(isp), tag);
+}
+
+static void
+dump_regs(struct isp1301 *isp, const char *label)
+{
+#ifdef DEBUG
+       u8      ctrl = isp1301_get_u8(isp, ISP1301_OTG_CONTROL_1);
+       u8      status = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
+       u8      src = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
+
+       pr_debug("otg: %06x, %s %s, otg/%02x stat/%02x.%02x\n",
+               OTG_CTRL_REG, label, state_name(isp),
+               ctrl, status, src);
+       /* mode control and irq enables don't change much */
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_USB_OTG
+
+/*
+ * The OMAP OTG controller handles most of the OTG state transitions.
+ *
+ * We translate isp1301 outputs (mostly voltage comparator status) into
+ * OTG inputs; OTG outputs (mostly pullup/pulldown controls) and HNP state
+ * flags into isp1301 inputs ... and infer state transitions.
+ */
+
+#ifdef VERBOSE
+
+static void check_state(struct isp1301 *isp, const char *tag)
+{
+       enum usb_otg_state      state = OTG_STATE_UNDEFINED;
+       u8                      fsm = OTG_TEST_REG & 0x0ff;
+       unsigned                extra = 0;
+
+       switch (fsm) {
+
+       /* default-b */
+       case 0x0:
+               state = OTG_STATE_B_IDLE;
+               break;
+       case 0x3:
+       case 0x7:
+               extra = 1;
+       case 0x1:
+               state = OTG_STATE_B_PERIPHERAL;
+               break;
+       case 0x11:
+               state = OTG_STATE_B_SRP_INIT;
+               break;
+
+       /* extra dual-role default-b states */
+       case 0x12:
+       case 0x13:
+       case 0x16:
+               extra = 1;
+       case 0x17:
+               state = OTG_STATE_B_WAIT_ACON;
+               break;
+       case 0x34:
+               state = OTG_STATE_B_HOST;
+               break;
+
+       /* default-a */
+       case 0x36:
+               state = OTG_STATE_A_IDLE;
+               break;
+       case 0x3c:
+               state = OTG_STATE_A_WAIT_VFALL;
+               break;
+       case 0x7d:
+               state = OTG_STATE_A_VBUS_ERR;
+               break;
+       case 0x9e:
+       case 0x9f:
+               extra = 1;
+       case 0x89:
+               state = OTG_STATE_A_PERIPHERAL;
+               break;
+       case 0xb7:
+               state = OTG_STATE_A_WAIT_VRISE;
+               break;
+       case 0xb8:
+               state = OTG_STATE_A_WAIT_BCON;
+               break;
+       case 0xb9:
+               state = OTG_STATE_A_HOST;
+               break;
+       case 0xba:
+               state = OTG_STATE_A_SUSPEND;
+               break;
+       default:
+               break;
+       }
+       if (isp->otg.state == state && !extra)
+               return;
+       pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag,
+               state_string(state), fsm, state_name(isp), OTG_CTRL_REG);
+}
+
+#else
+
+static inline void check_state(struct isp1301 *isp, const char *tag) { }
+
+#endif
+
+/* outputs from ISP1301_INTERRUPT_SOURCE */
+static void update_otg1(struct isp1301 *isp, u8 int_src)
+{
+       u32     otg_ctrl;
+
+       otg_ctrl = OTG_CTRL_REG
+                       & OTG_CTRL_MASK
+                       & ~OTG_XCEIV_INPUTS
+                       & ~(OTG_ID|OTG_ASESSVLD|OTG_VBUSVLD);
+       if (int_src & INTR_SESS_VLD)
+               otg_ctrl |= OTG_ASESSVLD;
+       else if (isp->otg.state == OTG_STATE_A_WAIT_VFALL) {
+               a_idle(isp, "vfall");
+               otg_ctrl &= ~OTG_CTRL_BITS;
+       }
+       if (int_src & INTR_VBUS_VLD)
+               otg_ctrl |= OTG_VBUSVLD;
+       if (int_src & INTR_ID_GND) {            /* default-A */
+               if (isp->otg.state == OTG_STATE_B_IDLE
+                               || isp->otg.state == OTG_STATE_UNDEFINED) {
+                       a_idle(isp, "init");
+                       return;
+               }
+       } else {                                /* default-B */
+               otg_ctrl |= OTG_ID;
+               if (isp->otg.state == OTG_STATE_A_IDLE
+                               || isp->otg.state == OTG_STATE_UNDEFINED) {
+                       b_idle(isp, "init");
+                       return;
+               }
+       }
+       OTG_CTRL_REG = otg_ctrl;
+}
+
+/* outputs from ISP1301_OTG_STATUS */
+static void update_otg2(struct isp1301 *isp, u8 otg_status)
+{
+       u32     otg_ctrl;
+
+       otg_ctrl = OTG_CTRL_REG
+                       & OTG_CTRL_MASK
+                       & ~OTG_XCEIV_INPUTS
+                       & ~(OTG_BSESSVLD|OTG_BSESSEND);
+       if (otg_status & OTG_B_SESS_VLD)
+               otg_ctrl |= OTG_BSESSVLD;
+       else if (otg_status & OTG_B_SESS_END)
+               otg_ctrl |= OTG_BSESSEND;
+       OTG_CTRL_REG = otg_ctrl;
+}
+
+/* inputs going to ISP1301 */
+static void otg_update_isp(struct isp1301 *isp)
+{
+       u32     otg_ctrl, otg_change;
+       u8      set = OTG1_DM_PULLDOWN, clr = OTG1_DM_PULLUP;
+
+       otg_ctrl = OTG_CTRL_REG;
+       otg_change = otg_ctrl ^ isp->last_otg_ctrl;
+       isp->last_otg_ctrl = otg_ctrl;
+       otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS;
+
+       switch (isp->otg.state) {
+       case OTG_STATE_B_IDLE:
+       case OTG_STATE_B_PERIPHERAL:
+       case OTG_STATE_B_SRP_INIT:
+               if (!(otg_ctrl & OTG_PULLUP)) {
+                       // if (otg_ctrl & OTG_B_HNPEN) {
+                       if (isp->otg.gadget->b_hnp_enable) {
+                               isp->otg.state = OTG_STATE_B_WAIT_ACON;
+                               pr_debug("  --> b_wait_acon\n");
+                       }
+                       goto pulldown;
+               }
+pullup:
+               set |= OTG1_DP_PULLUP;
+               clr |= OTG1_DP_PULLDOWN;
+               break;
+       case OTG_STATE_A_SUSPEND:
+       case OTG_STATE_A_PERIPHERAL:
+               if (otg_ctrl & OTG_PULLUP)
+                       goto pullup;
+               /* FALLTHROUGH */
+       // case OTG_STATE_B_WAIT_ACON:
+       default:
+pulldown:
+               set |= OTG1_DP_PULLDOWN;
+               clr |= OTG1_DP_PULLUP;
+               break;
+       }
+
+#      define toggle(OTG,ISP) do { \
+               if (otg_ctrl & OTG) set |= ISP; \
+               else clr |= ISP; \
+               } while (0)
+
+       if (!(isp->otg.host))
+               otg_ctrl &= ~OTG_DRV_VBUS;
+
+       switch (isp->otg.state) {
+       case OTG_STATE_A_SUSPEND:
+               if (otg_ctrl & OTG_DRV_VBUS) {
+                       set |= OTG1_VBUS_DRV;
+                       break;
+               }
+               /* HNP failed for some reason (A_AIDL_BDIS timeout) */
+               notresponding(isp);
+
+               /* FALLTHROUGH */
+       case OTG_STATE_A_VBUS_ERR:
+               isp->otg.state = OTG_STATE_A_WAIT_VFALL;
+               pr_debug("  --> a_wait_vfall\n");
+               /* FALLTHROUGH */
+       case OTG_STATE_A_WAIT_VFALL:
+               /* FIXME usbcore thinks port power is still on ... */
+               clr |= OTG1_VBUS_DRV;
+               break;
+       case OTG_STATE_A_IDLE:
+               if (otg_ctrl & OTG_DRV_VBUS) {
+                       isp->otg.state = OTG_STATE_A_WAIT_VRISE;
+                       pr_debug("  --> a_wait_vrise\n");
+               }
+               /* FALLTHROUGH */
+       default:
+               toggle(OTG_DRV_VBUS, OTG1_VBUS_DRV);
+       }
+
+       toggle(OTG_PU_VBUS, OTG1_VBUS_CHRG);
+       toggle(OTG_PD_VBUS, OTG1_VBUS_DISCHRG);
+
+#      undef toggle
+
+       isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, set);
+       isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, clr);
+
+       /* HNP switch to host or peripheral; and SRP */
+       if (otg_change & OTG_PULLUP) {
+               switch (isp->otg.state) {
+               case OTG_STATE_B_IDLE:
+                       if (clr & OTG1_DP_PULLUP)
+                               break;
+                       isp->otg.state = OTG_STATE_B_PERIPHERAL;
+                       pr_debug("  --> b_peripheral\n");
+                       break;
+               case OTG_STATE_A_SUSPEND:
+                       if (clr & OTG1_DP_PULLUP)
+                               break;
+                       isp->otg.state = OTG_STATE_A_PERIPHERAL;
+                       pr_debug("  --> a_peripheral\n");
+                       break;
+               default:
+                       break;
+               }
+               OTG_CTRL_REG |= OTG_PULLUP;
+       }
+
+       check_state(isp, __FUNCTION__);
+       dump_regs(isp, "otg->isp1301");
+}
+
+static irqreturn_t omap_otg_irq(int irq, void *_isp, struct pt_regs *regs)
+{
+       u16             otg_irq = OTG_IRQ_SRC_REG;
+       u32             otg_ctrl;
+       int             ret = IRQ_NONE;
+       struct isp1301  *isp = _isp;
+
+       /* update ISP1301 transciever from OTG controller */
+       if (otg_irq & OPRT_CHG) {
+               OTG_IRQ_SRC_REG = OPRT_CHG;
+               isp1301_defer_work(isp, WORK_UPDATE_ISP);
+               ret = IRQ_HANDLED;
+
+       /* SRP to become b_peripheral failed */
+       } else if (otg_irq & B_SRP_TMROUT) {
+               pr_debug("otg: B_SRP_TIMEOUT, %06x\n", OTG_CTRL_REG);
+               notresponding(isp);
+
+               /* gadget drivers that care should monitor all kinds of
+                * remote wakeup (SRP, normal) using their own timer
+                * to give "check cable and A-device" messages.
+                */
+               if (isp->otg.state == OTG_STATE_B_SRP_INIT)
+                       b_idle(isp, "srp_timeout");
+
+               OTG_IRQ_SRC_REG = B_SRP_TMROUT;
+               ret = IRQ_HANDLED;
+
+       /* HNP to become b_host failed */
+       } else if (otg_irq & B_HNP_FAIL) {
+               pr_debug("otg: %s B_HNP_FAIL, %06x\n",
+                               state_name(isp), OTG_CTRL_REG);
+               notresponding(isp);
+
+               otg_ctrl = OTG_CTRL_REG;
+               otg_ctrl |= OTG_BUSDROP;
+               otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+               OTG_CTRL_REG = otg_ctrl;
+
+               /* subset of b_peripheral()... */
+               isp->otg.state = OTG_STATE_B_PERIPHERAL;
+               pr_debug("  --> b_peripheral\n");
+
+               OTG_IRQ_SRC_REG = B_HNP_FAIL;
+               ret = IRQ_HANDLED;
+
+       /* detect SRP from B-device ... */
+       } else if (otg_irq & A_SRP_DETECT) {
+               pr_debug("otg: %s SRP_DETECT, %06x\n",
+                               state_name(isp), OTG_CTRL_REG);
+
+               isp1301_defer_work(isp, WORK_UPDATE_OTG);
+               switch (isp->otg.state) {
+               case OTG_STATE_A_IDLE:
+                       if (!isp->otg.host)
+                               break;
+                       isp1301_defer_work(isp, WORK_HOST_RESUME);
+                       otg_ctrl = OTG_CTRL_REG;
+                       otg_ctrl |= OTG_A_BUSREQ;
+                       otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ)
+                                       & ~OTG_XCEIV_INPUTS
+                                       & OTG_CTRL_MASK;
+                       OTG_CTRL_REG = otg_ctrl;
+                       break;
+               default:
+                       break;
+               }
+
+               OTG_IRQ_SRC_REG = A_SRP_DETECT;
+               ret = IRQ_HANDLED;
+
+       /* timer expired:  T(a_wait_bcon) and maybe T(a_wait_vrise)
+        * we don't track them separately
+        */
+       } else if (otg_irq & A_REQ_TMROUT) {
+               otg_ctrl = OTG_CTRL_REG;
+               pr_info("otg: BCON_TMOUT from %s, %06x\n",
+                               state_name(isp), otg_ctrl);
+               notresponding(isp);
+
+               otg_ctrl |= OTG_BUSDROP;
+               otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+               OTG_CTRL_REG = otg_ctrl;
+               isp->otg.state = OTG_STATE_A_WAIT_VFALL;
+
+               OTG_IRQ_SRC_REG = A_REQ_TMROUT;
+               ret = IRQ_HANDLED;
+
+       /* A-supplied voltage fell too low; overcurrent */
+       } else if (otg_irq & A_VBUS_ERR) {
+               otg_ctrl = OTG_CTRL_REG;
+               printk(KERN_ERR "otg: %s, VBUS_ERR %04x ctrl %06x\n",
+                       state_name(isp), otg_irq, otg_ctrl);
+
+               otg_ctrl |= OTG_BUSDROP;
+               otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+               OTG_CTRL_REG = otg_ctrl;
+               isp->otg.state = OTG_STATE_A_VBUS_ERR;
+
+               OTG_IRQ_SRC_REG = A_VBUS_ERR;
+               ret = IRQ_HANDLED;
+
+       /* switch driver; the transciever code activates it,
+        * ungating the udc clock or resuming OHCI.
+        */
+       } else if (otg_irq & DRIVER_SWITCH) {
+               int     kick = 0;
+
+               otg_ctrl = OTG_CTRL_REG;
+               printk(KERN_NOTICE "otg: %s, SWITCH to %s, ctrl %06x\n",
+                               state_name(isp),
+                               (otg_ctrl & OTG_DRIVER_SEL)
+                                       ? "gadget" : "host",
+                               otg_ctrl);
+               isp1301_defer_work(isp, WORK_UPDATE_ISP);
+
+               /* role is peripheral */
+               if (otg_ctrl & OTG_DRIVER_SEL) {
+                       switch (isp->otg.state) {
+                       case OTG_STATE_A_IDLE:
+                               b_idle(isp, __FUNCTION__);
+                               break;
+                       default:
+                               break;
+                       }
+                       isp1301_defer_work(isp, WORK_UPDATE_ISP);
+
+               /* role is host */
+               } else {
+                       if (!(otg_ctrl & OTG_ID)) {
+                               otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+                               OTG_CTRL_REG = otg_ctrl | OTG_A_BUSREQ;
+                       }
+
+                       if (isp->otg.host) {
+                               switch (isp->otg.state) {
+                               case OTG_STATE_B_WAIT_ACON:
+                                       isp->otg.state = OTG_STATE_B_HOST;
+                                       pr_debug("  --> b_host\n");
+                                       kick = 1;
+                                       break;
+                               case OTG_STATE_A_WAIT_BCON:
+                                       isp->otg.state = OTG_STATE_A_HOST;
+                                       pr_debug("  --> a_host\n");
+                                       break;
+                               case OTG_STATE_A_PERIPHERAL:
+                                       isp->otg.state = OTG_STATE_A_WAIT_BCON;
+                                       pr_debug("  --> a_wait_bcon\n");
+                                       break;
+                               default:
+                                       break;
+                               }
+                               isp1301_defer_work(isp, WORK_HOST_RESUME);
+                       }
+               }
+
+               OTG_IRQ_SRC_REG = DRIVER_SWITCH;
+               ret = IRQ_HANDLED;
+
+               if (kick)
+                       usb_bus_start_enum(isp->otg.host,
+                                               isp->otg.host->otg_port);
+       }
+
+       check_state(isp, __FUNCTION__);
+       return ret;
+}
+
+static struct platform_device *otg_dev;
+
+static int otg_init(struct isp1301 *isp)
+{
+       if (!otg_dev)
+               return -ENODEV;
+
+       dump_regs(isp, __FUNCTION__);
+       /* some of these values are board-specific... */
+       OTG_SYSCON_2_REG |= OTG_EN
+               /* for B-device: */
+               | SRP_GPDATA            /* 9msec Bdev D+ pulse */
+               | SRP_GPDVBUS           /* discharge after VBUS pulse */
+               // | (3 << 24)          /* 2msec VBUS pulse */
+               /* for A-device: */
+               | (0 << 20)             /* 200ms nominal A_WAIT_VRISE timer */
+               | SRP_DPW               /* detect 167+ns SRP pulses */
+               | SRP_DATA | SRP_VBUS   /* accept both kinds of SRP pulse */
+               ;
+
+       update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
+       update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
+
+       check_state(isp, __FUNCTION__);
+       pr_debug("otg: %s, %s %06x\n",
+                       state_name(isp), __FUNCTION__, OTG_CTRL_REG);
+
+       OTG_IRQ_EN_REG = DRIVER_SWITCH | OPRT_CHG
+                       | B_SRP_TMROUT | B_HNP_FAIL
+                       | A_VBUS_ERR | A_SRP_DETECT | A_REQ_TMROUT;
+       OTG_SYSCON_2_REG |= OTG_EN;
+
+       return 0;
+}
+
+static int otg_probe(struct device *dev)
+{
+       // struct omap_usb_config *config = dev->platform_data;
+
+       otg_dev = to_platform_device(dev);
+       return 0;
+}
+
+static int otg_remove(struct device *dev)
+{
+       otg_dev = 0;
+       return 0;
+}
+
+struct device_driver omap_otg_driver = {
+       .name           = "omap_otg",
+       .bus            = &platform_bus_type,
+       .probe          = otg_probe,
+       .remove         = otg_remove,   
+};
+
+static int otg_bind(struct isp1301 *isp)
+{
+       int     status;
+
+       if (otg_dev)
+               return -EBUSY;
+
+       status = driver_register(&omap_otg_driver);
+       if (status < 0)
+               return status;
+
+       if (otg_dev)
+               status = request_irq(otg_dev->resource[1].start, omap_otg_irq,
+                               SA_INTERRUPT, DRIVER_NAME, isp);
+       else
+               status = -ENODEV;
+
+       if (status < 0)
+               driver_unregister(&omap_otg_driver);
+       return status;
+}
+
+static void otg_unbind(struct isp1301 *isp)
+{
+       if (!otg_dev)
+               return;
+       free_irq(otg_dev->resource[1].start, isp);
+}
+
+#else
+
+/* OTG controller isn't clocked */
+
+#endif /* CONFIG_USB_OTG */
+
+/*-------------------------------------------------------------------------*/
+
+static void b_peripheral(struct isp1301 *isp)
+{
+       enable_vbus_draw(isp, 8);
+       OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
+       usb_gadget_vbus_connect(isp->otg.gadget);
+
+#ifdef CONFIG_USB_OTG
+       otg_update_isp(isp);
+#else
+       /* UDC driver just set OTG_BSESSVLD */
+       isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP);
+       isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN);
+       isp->otg.state = OTG_STATE_B_PERIPHERAL;
+       pr_debug("  --> b_peripheral\n");
+       dump_regs(isp, "2periph");
+#endif
+}
+
+static int isp_update_otg(struct isp1301 *isp, u8 stat)
+{
+       u8                      isp_stat, isp_bstat;
+       enum usb_otg_state      state = isp->otg.state;
+
+       if (stat & INTR_BDIS_ACON)
+               pr_debug("OTG:  BDIS_ACON, %s\n", state_name(isp));
+
+       /* start certain state transitions right away */
+       isp_stat = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
+       if (isp_stat & INTR_ID_GND) {
+               if (isp->otg.default_a) {
+                       switch (state) {
+                       case OTG_STATE_B_IDLE:
+                               a_idle(isp, "idle");
+                               /* FALLTHROUGH */
+                       case OTG_STATE_A_IDLE:
+                               enable_vbus_source(isp);
+                               /* FALLTHROUGH */
+                       case OTG_STATE_A_WAIT_VRISE:
+                               /* we skip over OTG_STATE_A_WAIT_BCON, since
+                                * the HC will transition to A_HOST (or
+                                * A_SUSPEND!) without our noticing except
+                                * when HNP is used.
+                                */
+                               if (isp_stat & INTR_VBUS_VLD)
+                                       isp->otg.state = OTG_STATE_A_HOST;
+                               break;
+                       case OTG_STATE_A_WAIT_VFALL:
+                               if (!(isp_stat & INTR_SESS_VLD))
+                                       a_idle(isp, "vfell");
+                               break;
+                       default:
+                               if (!(isp_stat & INTR_VBUS_VLD))
+                                       isp->otg.state = OTG_STATE_A_VBUS_ERR;
+                               break;
+                       }
+                       isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
+               } else {
+                       switch (state) {
+                       case OTG_STATE_B_PERIPHERAL:
+                       case OTG_STATE_B_HOST:
+                       case OTG_STATE_B_WAIT_ACON:
+                               usb_gadget_vbus_disconnect(isp->otg.gadget);
+                               break;
+                       default:
+                               break;
+                       }
+                       if (state != OTG_STATE_A_IDLE)
+                               a_idle(isp, "id");
+                       if (isp->otg.host && state == OTG_STATE_A_IDLE)
+                               isp1301_defer_work(isp, WORK_HOST_RESUME);
+                       isp_bstat = 0;
+               }
+       } else {
+               /* if user unplugged mini-A end of cable,
+                * don't bypass A_WAIT_VFALL.
+                */
+               if (isp->otg.default_a) {
+                       switch (state) {
+                       default:
+                               isp->otg.state = OTG_STATE_A_WAIT_VFALL;
+                               break;
+                       case OTG_STATE_A_WAIT_VFALL:
+                               state = OTG_STATE_A_IDLE;
+                               /* khubd may take a while to notice and
+                                * handle this disconnect, so don't go
+                                * to B_IDLE quite yet.
+                                */
+                               break;
+                       case OTG_STATE_A_IDLE:
+                               host_suspend(isp);
+                               isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1,
+                                               MC1_BDIS_ACON_EN);
+                               isp->otg.state = OTG_STATE_B_IDLE;
+                               OTG_CTRL_REG &= OTG_CTRL_REG & OTG_CTRL_MASK
+                                               & ~OTG_CTRL_BITS;
+                               break;
+                       case OTG_STATE_B_IDLE:
+                               break;
+                       }
+               }
+               isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
+
+               switch (isp->otg.state) {
+               case OTG_STATE_B_PERIPHERAL:
+               case OTG_STATE_B_WAIT_ACON:
+               case OTG_STATE_B_HOST:
+                       if (likely(isp_bstat & OTG_B_SESS_VLD))
+                               break;
+                       enable_vbus_draw(isp, 0);
+#ifndef        CONFIG_USB_OTG
+                       /* UDC driver will clear OTG_BSESSVLD */
+                       isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
+                                               OTG1_DP_PULLDOWN);
+                       isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
+                                               OTG1_DP_PULLUP);
+                       dump_regs(isp, __FUNCTION__);
+#endif
+                       /* FALLTHROUGH */
+               case OTG_STATE_B_SRP_INIT:
+                       b_idle(isp, __FUNCTION__);
+                       OTG_CTRL_REG &= OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
+                       /* FALLTHROUGH */
+               case OTG_STATE_B_IDLE:
+                       if (isp->otg.gadget && (isp_bstat & OTG_B_SESS_VLD)) {
+#ifdef CONFIG_USB_OTG
+                               update_otg1(isp, isp_stat);
+                               update_otg2(isp, isp_bstat);
+#endif
+                               b_peripheral(isp);
+                       } else if (!(isp_stat & (INTR_VBUS_VLD|INTR_SESS_VLD)))
+                               isp_bstat |= OTG_B_SESS_END;
+                       break;
+               case OTG_STATE_A_WAIT_VFALL:
+                       break;
+               default:
+                       pr_debug("otg: unsupported b-device %s\n",
+                               state_name(isp));
+                       break;
+               }
+       }
+
+       if (state != isp->otg.state)
+               pr_debug("  isp, %s -> %s\n",
+                               state_string(state), state_name(isp));
+
+#ifdef CONFIG_USB_OTG
+       /* update the OTG controller state to match the isp1301; may
+        * trigger OPRT_CHG irqs for changes going to the isp1301.
+        */
+       update_otg1(isp, isp_stat);
+       update_otg2(isp, isp_bstat);
+       check_state(isp, __FUNCTION__);
+#endif
+
+       dump_regs(isp, "isp1301->otg");
+}
+
+/*-------------------------------------------------------------------------*/
+
+static u8 isp1301_clear_latch(struct isp1301 *isp)
+{
+       u8 latch = isp1301_get_u8(isp, ISP1301_INTERRUPT_LATCH);
+       isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, latch);
+       return latch;
+}
+
+static void
+isp1301_work(void *data)
+{
+       struct isp1301  *isp = data;
+       int             stop;
+
+       /* implicit lock:  we're the only task using this device */
+       isp->working = 1;
+       do {
+               stop = test_bit(WORK_STOP, &isp->todo);
+
+#ifdef CONFIG_USB_OTG
+               /* transfer state from otg engine to isp1301 */
+               if (test_and_clear_bit(WORK_UPDATE_ISP, &isp->todo)) {
+                       otg_update_isp(isp);
+                       put_device(&isp->client.dev);
+               }
+#endif
+               /* transfer state from isp1301 to otg engine */
+               if (test_and_clear_bit(WORK_UPDATE_OTG, &isp->todo)) {
+                       u8              stat = isp1301_clear_latch(isp);
+
+                       isp_update_otg(isp, stat);
+                       put_device(&isp->client.dev);
+               }
+
+               if (test_and_clear_bit(WORK_HOST_RESUME, &isp->todo)) {
+                       u32     otg_ctrl;
+
+                       /*
+                        * skip A_WAIT_VRISE; hc transitions invisibly
+                        * skip A_WAIT_BCON; same.
+                        */
+                       switch (isp->otg.state) {
+                       case OTG_STATE_A_WAIT_BCON:
+                       case OTG_STATE_A_WAIT_VRISE:
+                               isp->otg.state = OTG_STATE_A_HOST;
+                               pr_debug("  --> a_host\n");
+                               otg_ctrl = OTG_CTRL_REG;
+                               otg_ctrl |= OTG_A_BUSREQ;
+                               otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ)
+                                               & OTG_CTRL_MASK;
+                               OTG_CTRL_REG = otg_ctrl;
+                               break;
+                       case OTG_STATE_B_WAIT_ACON:
+                               isp->otg.state = OTG_STATE_B_HOST;
+                               pr_debug("  --> b_host (acon)\n");
+                               break;
+                       case OTG_STATE_B_HOST:
+                       case OTG_STATE_B_IDLE:
+                       case OTG_STATE_A_IDLE:
+                               break;
+                       default:
+                               pr_debug("  host resume in %s\n",
+                                               state_name(isp));
+                       }
+                       host_resume(isp);
+                       // mdelay(10);
+                       put_device(&isp->client.dev);
+               }
+
+               if (test_and_clear_bit(WORK_TIMER, &isp->todo)) {
+#ifdef VERBOSE
+                       dump_regs(isp, "timer");
+                       if (!stop)
+                               mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
+#endif
+                       put_device(&isp->client.dev);
+               }
+
+               if (isp->todo)
+                       dev_vdbg(&isp->client.dev,
+                               "work done, todo = 0x%lx\n",
+                               isp->todo);
+               if (stop) {
+                       dev_dbg(&isp->client.dev, "stop\n");
+                       break;
+               }
+       } while (isp->todo);
+       isp->working = 0;
+}
+
+static irqreturn_t isp1301_irq(int irq, void *isp, struct pt_regs *regs)
+{
+       isp1301_defer_work(isp, WORK_UPDATE_OTG);
+       return IRQ_HANDLED;
+}
+
+static void isp1301_timer(unsigned long _isp)
+{
+       isp1301_defer_work((void *)_isp, WORK_TIMER);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void isp1301_release(struct device *dev)
+{
+       struct isp1301  *isp;
+
+       isp = container_of(dev, struct isp1301, client.dev);
+
+       /* ugly -- i2c hijacks our memory hook to wait_for_completion() */
+       if (isp->i2c_release)
+               isp->i2c_release(dev);
+       kfree (isp);
+}
+
+static struct isp1301 *the_transceiver;
+
+static int isp1301_detach_client(struct i2c_client *i2c)
+{
+       struct isp1301  *isp;
+
+       isp = container_of(i2c, struct isp1301, client);
+
+       isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
+       isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
+       free_irq(isp->irq, isp);
+#ifdef CONFIG_USB_OTG
+       otg_unbind(isp);
+#endif
+       if (machine_is_omap_h2())
+               omap_free_gpio(2);
+
+       isp->timer.data = 0;
+       set_bit(WORK_STOP, &isp->todo);
+       del_timer_sync(&isp->timer);
+       flush_scheduled_work();
+
+       put_device(&i2c->dev);
+       the_transceiver = 0;
+
+       return i2c_detach_client(i2c);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* NOTE:  three modes are possible here, only one of which
+ * will be standards-conformant on any given system:
+ *
+ *  - OTG mode (dual-role), required if there's a Mini-AB connector
+ *  - HOST mode, for when there's one or more A (host) connectors
+ *  - DEVICE mode, for when there's a B/Mini-B (device) connector
+ *
+ * As a rule, you won't have an isp1301 chip unless it's there to
+ * support the OTG mode.  Other modes help testing USB controllers 
+ * in isolation from (full) OTG support, or maybe so later board
+ * revisions can help to support those feature.
+ */
+
+#ifdef CONFIG_USB_OTG
+
+static int isp1301_otg_enable(struct isp1301 *isp)
+{
+       power_up(isp);
+       otg_init(isp);
+
+       /* NOTE:  since we don't change this, this provides
+        * a few more interrupts than are strictly needed.
+        */
+       isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
+               INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
+       isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
+               INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
+
+       dev_info(&isp->client.dev, "ready for dual-role USB ...\n");
+
+       return 0;
+}
+
+#endif
+
+/* add or disable the host device+driver */
+static int
+isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+{
+       struct isp1301  *isp = container_of(otg, struct isp1301, otg);
+
+       if (!otg || isp != the_transceiver)
+               return -ENODEV;
+
+       if (!host) {
+               OTG_IRQ_EN_REG = 0;
+               power_down(isp);
+               isp->otg.host = 0;
+               return 0;
+       }
+
+#ifdef CONFIG_USB_OTG
+       isp->otg.host = host;
+       dev_dbg(&isp->client.dev, "registered host\n");
+       host_suspend(isp);
+       if (isp->otg.gadget)
+               return isp1301_otg_enable(isp);
+       return 0;
+
+#elif  !defined(CONFIG_USB_GADGET_OMAP)
+       // FIXME update its refcount
+       isp->otg.host = host;
+
+       power_up(isp);
+
+       if (machine_is_omap_h2())
+               isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+
+       dev_info(&isp->client.dev, "A-Host sessions ok\n");
+       isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
+               INTR_ID_GND);
+       isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
+               INTR_ID_GND);
+
+       /* If this has a Mini-AB connector, this mode is highly
+        * nonstandard ... but can be handy for testing, especially with
+        * the Mini-A end of an OTG cable.  (Or something nonstandard
+        * like MiniB-to-StandardB, maybe built with a gender mender.)
+        */
+       isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_VBUS_DRV);
+
+       dump_regs(isp, __FUNCTION__);
+
+       return 0;
+
+#else
+       dev_dbg(&isp->client.dev, "host sessions not allowed\n");
+       return -EINVAL;
+#endif
+
+}
+
+static int
+isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
+{
+       struct isp1301  *isp = container_of(otg, struct isp1301, otg);
+
+       if (!otg || isp != the_transceiver)
+               return -ENODEV;
+
+       if (!gadget) {
+               OTG_IRQ_EN_REG = 0;
+               if (!isp->otg.default_a)
+                       enable_vbus_draw(isp, 0);
+               usb_gadget_vbus_disconnect(isp->otg.gadget);
+               isp->otg.gadget = 0;
+               power_down(isp);
+               return 0;
+       }
+
+#ifdef CONFIG_USB_OTG
+       isp->otg.gadget = gadget;
+       dev_dbg(&isp->client.dev, "registered gadget\n");
+       /* gadget driver may be suspended until vbus_connect () */
+       if (isp->otg.host)
+               return isp1301_otg_enable(isp);
+       return 0;
+
+#elif  !defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE)
+       isp->otg.gadget = gadget;
+       // FIXME update its refcount
+
+       OTG_CTRL_REG = (OTG_CTRL_REG & OTG_CTRL_MASK
+                               & ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS))
+                       | OTG_ID;
+       power_up(isp);
+       isp->otg.state = OTG_STATE_B_IDLE;
+
+       if (machine_is_omap_h2())
+               isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+
+       isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
+               INTR_SESS_VLD);
+       isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
+               INTR_VBUS_VLD);
+       dev_info(&isp->client.dev, "B-Peripheral sessions ok\n");
+       dump_regs(isp, __FUNCTION__);
+
+       /* If this has a Mini-AB connector, this mode is highly
+        * nonstandard ... but can be handy for testing, so long
+        * as you don't plug a Mini-A cable into the jack.
+        */
+       if (isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE) & INTR_VBUS_VLD)
+               b_peripheral(isp);
+
+       return 0;
+
+#else
+       dev_dbg(&isp->client.dev, "peripheral sessions not allowed\n");
+       return -EINVAL;
+#endif
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static int
+isp1301_set_power(struct otg_transceiver *dev, unsigned mA)
+{
+       if (!the_transceiver)
+               return -ENODEV;
+       if (dev->state == OTG_STATE_B_PERIPHERAL)
+               enable_vbus_draw(the_transceiver, mA);
+       return 0;
+}
+
+static int
+isp1301_start_srp(struct otg_transceiver *dev)
+{
+       struct isp1301  *isp = container_of(dev, struct isp1301, otg);
+       u32             otg_ctrl;
+
+       if (!dev || isp != the_transceiver
+                       || isp->otg.state != OTG_STATE_B_IDLE)
+               return -ENODEV;
+
+       otg_ctrl = OTG_CTRL_REG;
+       if (!(otg_ctrl & OTG_BSESSEND))
+               return -EINVAL;
+
+       otg_ctrl |= OTG_B_BUSREQ;
+       otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK;
+       OTG_CTRL_REG = otg_ctrl;
+       isp->otg.state = OTG_STATE_B_SRP_INIT;
+
+       pr_debug("otg: SRP, %s ... %06x\n", state_name(isp), OTG_CTRL_REG);
+#ifdef CONFIG_USB_OTG
+       check_state(isp, __FUNCTION__);
+#endif
+       return 0;
+}
+
+static int
+isp1301_start_hnp(struct otg_transceiver *dev)
+{
+#ifdef CONFIG_USB_OTG
+       struct isp1301  *isp = container_of(dev, struct isp1301, otg);
+
+       if (!dev || isp != the_transceiver)
+               return -ENODEV;
+       if (isp->otg.default_a && (isp->otg.host == NULL
+                       || !isp->otg.host->b_hnp_enable))
+               return -ENOTCONN;
+       if (!isp->otg.default_a && (isp->otg.gadget == NULL
+                       || !isp->otg.gadget->b_hnp_enable))
+               return -ENOTCONN;
+
+       /* We want hardware to manage most HNP protocol timings.
+        * So do this part as early as possible...
+        */
+       switch (isp->otg.state) {
+       case OTG_STATE_B_HOST:
+               isp->otg.state = OTG_STATE_B_PERIPHERAL;
+               /* caller will suspend next */
+               break;
+       case OTG_STATE_A_HOST:
+#if 0
+               /* autoconnect mode avoids irq latency bugs */
+               isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
+                               MC1_BDIS_ACON_EN);
+#endif
+               /* caller must suspend then clear A_BUSREQ */
+               usb_gadget_vbus_connect(isp->otg.gadget);
+               OTG_CTRL_REG |= OTG_A_SETB_HNPEN;
+
+               break;
+       case OTG_STATE_A_PERIPHERAL:
+               /* initiated by B-Host suspend */
+               break;
+       default:
+               return -EILSEQ;
+       }
+       pr_debug("otg: HNP %s, %06x ...\n",
+               state_name(isp), OTG_CTRL_REG);
+       check_state(isp, __FUNCTION__);
+       return 0;
+#else
+       /* srp-only */
+       return -EINVAL;
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* no error returns, they'd just make bus scanning stop */
+static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
+{
+       int                     status;
+       struct isp1301          *isp;
+       struct i2c_client       *i2c;
+
+       if (the_transceiver)
+               return 0;
+
+       isp = kmalloc(sizeof *isp, GFP_KERNEL);
+       if (!isp)
+               return 0;
+
+       memset(isp, 0, sizeof *isp);
+
+       INIT_WORK(&isp->work, isp1301_work, isp);
+       init_timer(&isp->timer);
+       isp->timer.function = isp1301_timer;
+       isp->timer.data = (unsigned long) isp;
+
+       isp->irq = -1;
+       isp->client.addr = address;
+       i2c_set_clientdata(&isp->client, isp);
+       isp->client.adapter = bus;
+       isp->client.id = 1301;
+       isp->client.driver = &isp1301_driver;
+       strlcpy(isp->client.name, DRIVER_NAME, I2C_NAME_SIZE);
+       i2c = &isp->client;
+
+       /* if this is a true probe, verify the chip ... */
+       if (kind < 0) {
+               status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
+               if (status != I2C_VENDOR_ID_PHILIPS) {
+                       dev_dbg(&bus->dev, "addr %d not philips id: %d\n",
+                               address, status);
+                       goto fail1;
+               }
+               status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
+               if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
+                       dev_dbg(&bus->dev, "%d not isp1301, %d\n",
+                               address, status);
+                       goto fail1;
+               }
+       }
+
+       status = i2c_attach_client(i2c);
+       if (status < 0) {
+               dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n",
+                               DRIVER_NAME, address, status);
+fail1:
+               kfree(isp);
+               return 0;
+       }
+       isp->i2c_release = i2c->dev.release;
+       i2c->dev.release = isp1301_release;
+
+       /* initial development used chiprev 2.00 */
+       status = i2c_smbus_read_word_data(i2c, ISP1301_BCD_DEVICE);
+       dev_info(&i2c->dev, "chiprev %x.%02x, driver " DRIVER_VERSION "\n",
+               status >> 8, status & 0xff);
+
+       /* make like power-on reset */
+       isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_MASK);
+
+       isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_BI_DI);
+       isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, ~MC2_BI_DI);
+
+       isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
+                               OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN);
+       isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
+                               ~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
+
+       isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, ~0);
+       isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
+       isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
+
+#ifdef CONFIG_USB_OTG
+       status = otg_bind(isp);
+       if (status < 0) {
+               dev_dbg(&i2c->dev, "can't bind OTG\n");
+               goto fail2;
+       }
+#endif
+
+       if (machine_is_omap_h2()) {
+               /* full speed signaling by default */
+               isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
+                       MC1_SPEED_REG);
+               isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2,
+                       MC2_SPD_SUSP_CTRL);
+
+               /* IRQ wired at M14 */
+               omap_cfg_reg(M14_1510_GPIO2);
+               isp->irq = OMAP_GPIO_IRQ(2);
+               omap_request_gpio(2);
+               omap_set_gpio_direction(2, 1);
+               omap_set_gpio_edge_ctrl(2, OMAP_GPIO_FALLING_EDGE);
+       }
+
+       status = request_irq(isp->irq, isp1301_irq,
+                       SA_SAMPLE_RANDOM, DRIVER_NAME, isp);
+       if (status < 0) {
+               dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n",
+                               isp->irq, status);
+#ifdef CONFIG_USB_OTG
+fail2:
+#endif
+               i2c_detach_client(i2c);
+               goto fail1;
+       }
+
+       isp->otg.dev = &isp->client.dev;
+       isp->otg.label = DRIVER_NAME;
+
+       isp->otg.set_host = isp1301_set_host,
+       isp->otg.set_peripheral = isp1301_set_peripheral,
+       isp->otg.set_power = isp1301_set_power,
+       isp->otg.start_srp = isp1301_start_srp,
+       isp->otg.start_hnp = isp1301_start_hnp,
+
+       enable_vbus_draw(isp, 0);
+       power_down(isp);
+       the_transceiver = isp;
+
+#ifdef CONFIG_USB_OTG
+       update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
+       update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
+#endif
+
+       dump_regs(isp, __FUNCTION__);
+
+#ifdef VERBOSE
+       mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
+       dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
+#endif
+
+       status = otg_set_transceiver(&isp->otg);
+       if (status < 0)
+               dev_err(&i2c->dev, "can't register transceiver, %d\n",
+                       status);
+
+       return 0;
+}
+
+static int isp1301_scan_bus(struct i2c_adapter *bus)
+{
+       if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA
+                       | I2C_FUNC_SMBUS_READ_WORD_DATA))
+               return -EINVAL;
+       return i2c_probe(bus, &addr_data, isp1301_probe);
+}
+
+static struct i2c_driver isp1301_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "isp1301_omap",
+       .id             = 1301,         /* FIXME "official", i2c-ids.h */
+       .class          = I2C_CLASS_HWMON,
+       .flags          = I2C_DF_NOTIFY,
+       .attach_adapter = isp1301_scan_bus,
+       .detach_client  = isp1301_detach_client,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init isp_init(void)
+{
+       return i2c_add_driver(&isp1301_driver);
+}
+module_init(isp_init);
+
+static void __exit isp_exit(void)
+{
+       if (the_transceiver)
+               otg_set_transceiver(0);
+       i2c_del_driver(&isp1301_driver);
+}
+module_exit(isp_exit);
+
index 87ad9b9..d63e06d 100644 (file)
@@ -36,7 +36,7 @@ static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
 SENSORS_INSMOD_1(pcf8591);
 
 static int input_mode;
-MODULE_PARM(input_mode, "i");
+module_param(input_mode, int, 0);
 MODULE_PARM_DESC(input_mode,
        "Analog input mode:\n"
        " 0 = four single ended inputs\n"
index 0fa55d4..acfd3f8 100644 (file)
@@ -56,8 +56,8 @@ static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
 #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
 #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
 
-static int debug = 0;
-MODULE_PARM(debug, "i");
+static int debug;;
+module_param(debug, int, S_IRUGO | S_IWUSR);
 
 static struct i2c_driver rtc8564_driver;
 
diff --git a/drivers/i2c/chips/smsc47m1.c b/drivers/i2c/chips/smsc47m1.c
new file mode 100644 (file)
index 0000000..078c65f
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+    smsc47m1.c - Part of lm_sensors, Linux kernel modules
+                 for hardware monitoring
+
+    Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x and LPC47M14x
+    Super-I/O chips.
+
+    Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+    Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
+    Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com>
+                        and Jean Delvare
+
+    This program is free software; you can redistribute 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/module.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+/* Address is autodetected, there is no default value */
+static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
+static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
+static struct i2c_force_data forces[] = {{NULL}};
+
+enum chips { any_chip, smsc47m1 };
+static struct i2c_address_data addr_data = {
+       .normal_i2c             = normal_i2c,
+       .normal_i2c_range       = normal_i2c_range,
+       .normal_isa             = normal_isa,
+       .normal_isa_range       = normal_isa_range,
+       .probe                  = normal_i2c,           /* cheat */
+       .probe_range            = normal_i2c_range,     /* cheat */
+       .ignore                 = normal_i2c,           /* cheat */
+       .ignore_range           = normal_i2c_range,     /* cheat */
+       .forces                 = forces,
+};
+
+/* Super-I/0 registers and commands */
+
+#define        REG     0x2e    /* The register to read/write */
+#define        VAL     0x2f    /* The value to read/write */
+
+static inline void
+superio_outb(int reg, int val)
+{
+       outb(reg, REG);
+       outb(val, VAL);
+}
+
+static inline int
+superio_inb(int reg)
+{
+       outb(reg, REG);
+       return inb(VAL);
+}
+
+/* logical device for fans is 0x0A */
+#define superio_select() superio_outb(0x07, 0x0A)
+
+static inline void
+superio_enter(void)
+{
+       outb(0x55, REG);
+}
+
+static inline void
+superio_exit(void)
+{
+       outb(0xAA, REG);
+}
+
+#define SUPERIO_REG_ACT                0x30
+#define SUPERIO_REG_BASE       0x60
+#define SUPERIO_REG_DEVID      0x20
+
+/* Logical device registers */
+
+#define SMSC_EXTENT            0x80
+
+/* nr is 0 or 1 in the macros below */
+#define SMSC47M1_REG_ALARM             0x04
+#define SMSC47M1_REG_TPIN(nr)          (0x34 - (nr))
+#define SMSC47M1_REG_PPIN(nr)          (0x36 - (nr))
+#define SMSC47M1_REG_PWM(nr)           (0x56 + (nr))
+#define SMSC47M1_REG_FANDIV            0x58
+#define SMSC47M1_REG_FAN(nr)           (0x59 + (nr))
+#define SMSC47M1_REG_FAN_PRELOAD(nr)   (0x5B + (nr))
+
+#define MIN_FROM_REG(reg,div)          ((reg)>=192 ? 0 : \
+                                        983040/((192-(reg))*(div)))
+#define FAN_FROM_REG(reg,div,preload)  ((reg)<=(preload) || (reg)==255 ? 0 : \
+                                        983040/(((reg)-(preload))*(div)))
+#define DIV_FROM_REG(reg)              (1 << (reg))
+#define PWM_FROM_REG(reg)              (((reg) & 0x7E) << 1)
+#define PWM_EN_FROM_REG(reg)           ((~(reg)) & 0x01)
+#define PWM_TO_REG(reg)                        (((reg) >> 1) & 0x7E)
+
+struct smsc47m1_data {
+       struct i2c_client client;
+       struct semaphore lock;
+       int sysctl_id;
+
+       struct semaphore update_lock;
+       unsigned long last_updated;     /* In jiffies */
+
+       u8 fan[2];              /* Register value */
+       u8 fan_preload[2];      /* Register value */
+       u8 fan_div[2];          /* Register encoding, shifted right */
+       u8 alarms;              /* Register encoding */
+       u8 pwm[2];              /* Register value (bit 7 is enable) */
+};
+
+
+static int smsc47m1_attach_adapter(struct i2c_adapter *adapter);
+static int smsc47m1_find(int *address);
+static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind);
+static int smsc47m1_detach_client(struct i2c_client *client);
+
+static int smsc47m1_read_value(struct i2c_client *client, u8 reg);
+static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value);
+
+static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
+               int init);
+
+
+static int smsc47m1_id;
+
+static struct i2c_driver smsc47m1_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "smsc47m1",
+       .id             = I2C_DRIVERID_SMSC47M1,
+       .flags          = I2C_DF_NOTIFY,
+       .attach_adapter = smsc47m1_attach_adapter,
+       .detach_client  = smsc47m1_detach_client,
+};
+
+/* nr is 0 or 1 in the callback functions below */
+
+static ssize_t get_fan(struct device *dev, char *buf, int nr)
+{
+       struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+       /* This chip (stupidly) stops monitoring fan speed if PWM is
+          enabled and duty cycle is 0%. This is fine if the monitoring
+          and control concern the same fan, but troublesome if they are
+          not (which could as well happen). */
+       int rpm = (data->pwm[nr] & 0x7F) == 0x00 ? 0 :
+                 FAN_FROM_REG(data->fan[nr],
+                              DIV_FROM_REG(data->fan_div[nr]),
+                              data->fan_preload[nr]);
+       return sprintf(buf, "%d\n", rpm);
+}
+
+static ssize_t get_fan_min(struct device *dev, char *buf, int nr)
+{
+       struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+       int rpm = MIN_FROM_REG(data->fan_preload[nr],
+                              DIV_FROM_REG(data->fan_div[nr]));
+       return sprintf(buf, "%d\n", rpm);
+}
+
+static ssize_t get_fan_div(struct device *dev, char *buf, int nr)
+{
+       struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+       return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
+}
+
+static ssize_t get_fan_pwm(struct device *dev, char *buf, int nr)
+{
+       struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+       return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
+}
+
+static ssize_t get_fan_pwm_en(struct device *dev, char *buf, int nr)
+{
+       struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+       return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[nr]));
+}
+
+static ssize_t get_alarms(struct device *dev, char *buf)
+{
+       struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+       return sprintf(buf, "%d\n", data->alarms);
+}
+
+static ssize_t set_fan_min(struct device *dev, const char *buf,
+               size_t count, int nr)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m1_data *data = i2c_get_clientdata(client);
+
+       long rpmdiv = simple_strtol(buf, NULL, 10)
+                   * DIV_FROM_REG(data->fan_div[nr]);
+
+       if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040)
+               return -EINVAL;
+
+       data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv);
+       smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
+                            data->fan_preload[nr]);
+
+       return count;
+}
+
+/* Note: we save and restore the fan minimum here, because its value is
+   determined in part by the fan clock divider.  This follows the principle
+   of least suprise; the user doesn't expect the fan minimum to change just
+   because the divider changed. */
+static ssize_t set_fan_div(struct device *dev, const char *buf,
+               size_t count, int nr)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m1_data *data = i2c_get_clientdata(client);
+
+       long new_div = simple_strtol(buf, NULL, 10), tmp;
+       u8 old_div = DIV_FROM_REG(data->fan_div[nr]);
+
+       if (new_div == old_div) /* No change */
+               return count;
+       switch (new_div) {
+       case 1: data->fan_div[nr] = 0; break;
+       case 2: data->fan_div[nr] = 1; break;
+       case 4: data->fan_div[nr] = 2; break;
+       case 8: data->fan_div[nr] = 3; break;
+       default: return -EINVAL;
+       }
+
+       tmp = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV) & 0x0F;
+       tmp |= (data->fan_div[0] << 4) | (data->fan_div[1] << 6);
+       smsc47m1_write_value(client, SMSC47M1_REG_FANDIV, tmp);
+
+       /* Preserve fan min */
+       tmp = 192 - (old_div * (192 - data->fan_preload[nr])
+                    + new_div / 2) / new_div;
+       data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191);
+       smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
+                            data->fan_preload[nr]);
+
+       return count;
+}
+
+static ssize_t set_fan_pwm(struct device *dev, const char *buf,
+               size_t count, int nr)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m1_data *data = i2c_get_clientdata(client);
+
+       long val = simple_strtol(buf, NULL, 10);
+
+       if (val < 0 || val > 255)
+               return -EINVAL;
+
+       data->pwm[nr] &= 0x81; /* Preserve additional bits */
+       data->pwm[nr] |= PWM_TO_REG(val);
+
+       smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
+                            data->pwm[nr]);
+       return count;
+}
+
+static ssize_t set_fan_pwm_en(struct device *dev, const char *buf,
+               size_t count, int nr)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m1_data *data = i2c_get_clientdata(client);
+
+       long val = simple_strtol(buf, NULL, 10);
+       
+       if (val != 0 && val != 1)
+               return -EINVAL;
+
+       data->pwm[nr] &= 0xFE; /* preserve the other bits */
+       data->pwm[nr] |= !val;
+
+       smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
+                            data->pwm[nr]);
+
+       return count;
+}
+
+#define fan_present(offset)                                            \
+static ssize_t get_fan##offset (struct device *dev, char *buf)         \
+{                                                                      \
+       return get_fan(dev, buf, 0x##offset - 1);                       \
+}                                                                      \
+static ssize_t get_fan##offset##_min (struct device *dev, char *buf)   \
+{                                                                      \
+       return get_fan_min(dev, buf, 0x##offset - 1);                   \
+}                                                                      \
+static ssize_t set_fan##offset##_min (struct device *dev,              \
+               const char *buf, size_t count)                          \
+{                                                                      \
+       return set_fan_min(dev, buf, count, 0x##offset - 1);            \
+}                                                                      \
+static ssize_t get_fan##offset##_div (struct device *dev, char *buf)   \
+{                                                                      \
+       return get_fan_div(dev, buf, 0x##offset - 1);                   \
+}                                                                      \
+static ssize_t set_fan##offset##_div (struct device *dev,              \
+               const char *buf, size_t count)                          \
+{                                                                      \
+       return set_fan_div(dev, buf, count, 0x##offset - 1);            \
+}                                                                      \
+static ssize_t get_fan##offset##_pwm (struct device *dev, char *buf)   \
+{                                                                      \
+       return get_fan_pwm(dev, buf, 0x##offset - 1);                   \
+}                                                                      \
+static ssize_t set_fan##offset##_pwm (struct device *dev,              \
+               const char *buf, size_t count)                          \
+{                                                                      \
+       return set_fan_pwm(dev, buf, count, 0x##offset - 1);            \
+}                                                                      \
+static ssize_t get_fan##offset##_pwm_en (struct device *dev, char *buf)        \
+{                                                                      \
+       return get_fan_pwm_en(dev, buf, 0x##offset - 1);                \
+}                                                                      \
+static ssize_t set_fan##offset##_pwm_en (struct device *dev,           \
+               const char *buf, size_t count)                          \
+{                                                                      \
+       return set_fan_pwm_en(dev, buf, count, 0x##offset - 1);         \
+}                                                                      \
+static DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan##offset,      \
+               NULL);                                                  \
+static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,               \
+               get_fan##offset##_min, set_fan##offset##_min);          \
+static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,               \
+               get_fan##offset##_div, set_fan##offset##_div);          \
+static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR,               \
+               get_fan##offset##_pwm, set_fan##offset##_pwm);          \
+static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO | S_IWUSR,                \
+               get_fan##offset##_pwm_en, set_fan##offset##_pwm_en);
+
+fan_present(1);
+fan_present(2);
+
+static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
+
+static int smsc47m1_attach_adapter(struct i2c_adapter *adapter)
+{
+       if (!(adapter->class & I2C_CLASS_HWMON))
+               return 0;
+       return i2c_detect(adapter, &addr_data, smsc47m1_detect);
+}
+
+static int smsc47m1_find(int *address)
+{
+       u8 val;
+
+       superio_enter();
+       val = superio_inb(SUPERIO_REG_DEVID);
+
+       /*
+        * SMSC LPC47M10x/LPC47M13x (device id 0x59), LPC47M14x (device id
+        * 0x5F) and LPC47B27x (device id 0x51) have fan control.
+        * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
+        * can do much more besides (device id 0x60, unsupported).
+        */
+       if (val == 0x51)
+               printk(KERN_INFO "smsc47m1: Found SMSC47B27x\n");
+       else if (val == 0x59)
+               printk(KERN_INFO "smsc47m1: Found SMSC47M10x/SMSC47M13x\n");
+       else if (val == 0x5F)
+               printk(KERN_INFO "smsc47m1: Found SMSC47M14x\n");
+       else {
+               superio_exit();
+               return -ENODEV;
+       }
+
+       superio_select();
+       *address = (superio_inb(SUPERIO_REG_BASE) << 8)
+                |  superio_inb(SUPERIO_REG_BASE + 1);
+       val = superio_inb(SUPERIO_REG_ACT);
+       if (*address == 0 || (val & 0x01) == 0) {
+               printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
+               superio_exit();
+               return -ENODEV;
+       }
+
+       superio_exit();
+       return 0;
+}
+
+static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client *new_client;
+       struct smsc47m1_data *data;
+       int err = 0;
+
+       if (!i2c_is_isa_adapter(adapter)) {
+               return 0;
+       }
+
+       if (!request_region(address, SMSC_EXTENT, "smsc47m1")) {
+               dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
+               return -EBUSY;
+       }
+
+       if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto error_release;
+       }
+       memset(data, 0x00, sizeof(struct smsc47m1_data));
+
+       new_client = &data->client;
+       i2c_set_clientdata(new_client, data);
+       new_client->addr = address;
+       init_MUTEX(&data->lock);
+       new_client->adapter = adapter;
+       new_client->driver = &smsc47m1_driver;
+       new_client->flags = 0;
+
+       strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE);
+
+       new_client->id = smsc47m1_id++;
+       init_MUTEX(&data->update_lock);
+
+       if ((err = i2c_attach_client(new_client)))
+               goto error_free;
+
+       /* Some values (fan min, clock dividers, pwm registers) may be
+          needed before any update is triggered, so we better read them
+          at least once here. We don't usually do it that way, but in
+          this particular case, manually reading 5 registers out of 8
+          doesn't make much sense and we're better using the existing
+          function. */
+       smsc47m1_update_device(&new_client->dev, 1);
+
+       if ((smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(0)) & 0x05)
+           == 0x05) {
+               device_create_file(&new_client->dev, &dev_attr_fan1_input);
+               device_create_file(&new_client->dev, &dev_attr_fan1_min);
+               device_create_file(&new_client->dev, &dev_attr_fan1_div);
+       } else
+               dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, "
+                       "skipping\n");
+
+       if ((smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(1)) & 0x05)
+           == 0x05) {
+               device_create_file(&new_client->dev, &dev_attr_fan2_input);
+               device_create_file(&new_client->dev, &dev_attr_fan2_min);
+               device_create_file(&new_client->dev, &dev_attr_fan2_div);
+       } else
+               dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, "
+                       "skipping\n");
+
+       if ((smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(0)) & 0x05)
+           == 0x04) {
+               device_create_file(&new_client->dev, &dev_attr_fan1_pwm);
+               device_create_file(&new_client->dev, &dev_attr_fan1_pwm_enable);
+       } else
+               dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, "
+                       "skipping\n");
+       if ((smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05)
+           == 0x04) {
+               device_create_file(&new_client->dev, &dev_attr_fan2_pwm);
+               device_create_file(&new_client->dev, &dev_attr_fan2_pwm_enable);
+       } else
+               dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, "
+                       "skipping\n");
+
+       device_create_file(&new_client->dev, &dev_attr_alarms);
+
+       return 0;
+
+error_free:
+       kfree(new_client);
+error_release:
+       release_region(address, SMSC_EXTENT);
+       return err;
+}
+
+static int smsc47m1_detach_client(struct i2c_client *client)
+{
+       int err;
+
+       if ((err = i2c_detach_client(client))) {
+               dev_err(&client->dev, "Client deregistration failed, "
+                       "client not detached.\n");
+               return err;
+       }
+
+       release_region(client->addr, SMSC_EXTENT);
+       kfree(i2c_get_clientdata(client));
+
+       return 0;
+}
+
+static int smsc47m1_read_value(struct i2c_client *client, u8 reg)
+{
+       int res;
+
+       down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
+       res = inb_p(client->addr + reg);
+       up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
+       return res;
+}
+
+static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+       down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
+       outb_p(value, client->addr + reg);
+       up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
+}
+
+static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
+               int init)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m1_data *data = i2c_get_clientdata(client);
+
+       down(&data->update_lock);
+
+       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
+           (jiffies < data->last_updated) || init) {
+               int i;
+
+               for (i = 0; i < 2; i++) {
+                       data->fan[i] = smsc47m1_read_value(client,
+                                      SMSC47M1_REG_FAN(i));
+                       data->fan_preload[i] = smsc47m1_read_value(client,
+                                              SMSC47M1_REG_FAN_PRELOAD(i));
+                       data->pwm[i] = smsc47m1_read_value(client,
+                                      SMSC47M1_REG_PWM(i));
+               }
+
+               i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV);
+               data->fan_div[0] = (i >> 4) & 0x03;
+               data->fan_div[1] = i >> 6;
+
+               data->alarms = smsc47m1_read_value(client,
+                              SMSC47M1_REG_ALARM) >> 6;
+               /* Clear alarms if needed */
+               if (data->alarms)
+                       smsc47m1_write_value(client, SMSC47M1_REG_ALARM, 0xC0);
+
+               data->last_updated = jiffies;
+       }
+
+       up(&data->update_lock);
+       return data;
+}
+
+static int __init sm_smsc47m1_init(void)
+{
+       if (smsc47m1_find(normal_isa)) {
+               return -ENODEV;
+       }
+
+       return i2c_add_driver(&smsc47m1_driver);
+}
+
+static void __exit sm_smsc47m1_exit(void)
+{
+       i2c_del_driver(&smsc47m1_driver);
+}
+
+MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
+MODULE_DESCRIPTION("SMSC LPC47M1xx fan sensors driver");
+MODULE_LICENSE("GPL");
+
+module_init(sm_smsc47m1_init);
+module_exit(sm_smsc47m1_exit);
diff --git a/drivers/i2c/i2c-sensor-detect.c b/drivers/i2c/i2c-sensor-detect.c
new file mode 100644 (file)
index 0000000..70e82f2
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+    i2c-sensor-detect.c - Part of lm_sensors, Linux kernel modules for hardware
+                         monitoring
+    Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl> and
+    Mark D. Studebaker <mdsxyz123@yahoo.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/sysctl.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <asm/uaccess.h>
+
+
+/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
+int i2c_detect(struct i2c_adapter *adapter,
+              struct i2c_address_data *address_data,
+              int (*found_proc) (struct i2c_adapter *, int, int))
+{
+       int addr, i, found, j, err;
+       struct i2c_force_data *this_force;
+       int is_isa = i2c_is_isa_adapter(adapter);
+       int adapter_id =
+           is_isa ? ANY_I2C_ISA_BUS : i2c_adapter_id(adapter);
+
+       /* Forget it if we can't probe using SMBUS_QUICK */
+       if ((!is_isa) &&
+           !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK))
+               return -1;
+
+       for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
+               if (!is_isa && i2c_check_addr(adapter, addr))
+                       continue;
+
+               /* If it is in one of the force entries, we don't do any
+                  detection at all */
+               found = 0;
+               for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) {
+                       for (j = 0; !found && (this_force->force[j] != I2C_CLIENT_END); j += 2) {
+                               if ( ((adapter_id == this_force->force[j]) ||
+                                     ((this_force->force[j] == ANY_I2C_BUS) && !is_isa)) &&
+                                     (addr == this_force->force[j + 1]) ) {
+                                       dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
+                                       if ((err = found_proc(adapter, addr, this_force->kind)))
+                                               return err;
+                                       found = 1;
+                               }
+                       }
+               }
+               if (found)
+                       continue;
+
+               /* If this address is in one of the ignores, we can forget about it
+                  right now */
+               for (i = 0; !found && (address_data->ignore[i] != I2C_CLIENT_END); i += 2) {
+                       if ( ((adapter_id == address_data->ignore[i]) ||
+                             ((address_data->ignore[i] == ANY_I2C_BUS) &&
+                              !is_isa)) &&
+                             (addr == address_data->ignore[i + 1])) {
+                               dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr);
+                               found = 1;
+                       }
+               }
+               for (i = 0; !found && (address_data->ignore_range[i] != I2C_CLIENT_END); i += 3) {
+                       if ( ((adapter_id == address_data->ignore_range[i]) ||
+                             ((address_data-> ignore_range[i] == ANY_I2C_BUS) & 
+                              !is_isa)) &&
+                            (addr >= address_data->ignore_range[i + 1]) &&
+                            (addr <= address_data->ignore_range[i + 2])) {
+                               dev_dbg(&adapter->dev,  "found ignore_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
+                               found = 1;
+                       }
+               }
+               if (found)
+                       continue;
+
+               /* Now, we will do a detection, but only if it is in the normal or 
+                  probe entries */
+               if (is_isa) {
+                       for (i = 0; !found && (address_data->normal_isa[i] != I2C_CLIENT_ISA_END); i += 1) {
+                               if (addr == address_data->normal_isa[i]) {
+                                       dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr);
+                                       found = 1;
+                               }
+                       }
+                       for (i = 0; !found && (address_data->normal_isa_range[i] != I2C_CLIENT_ISA_END); i += 3) {
+                               if ((addr >= address_data->normal_isa_range[i]) &&
+                                   (addr <= address_data->normal_isa_range[i + 1]) &&
+                                   ((addr - address_data->normal_isa_range[i]) % address_data->normal_isa_range[i + 2] == 0)) {
+                                       dev_dbg(&adapter->dev, "found normal isa_range entry for adapter %d, addr %04x", adapter_id, addr);
+                                       found = 1;
+                               }
+                       }
+               } else {
+                       for (i = 0; !found && (address_data->normal_i2c[i] != I2C_CLIENT_END); i += 1) {
+                               if (addr == address_data->normal_i2c[i]) {
+                                       found = 1;
+                                       dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x", adapter_id, addr);
+                               }
+                       }
+                       for (i = 0; !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END); i += 2) {
+                               if ((addr >= address_data->normal_i2c_range[i]) &&
+                                   (addr <= address_data->normal_i2c_range[i + 1])) {
+                                       dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, addr %04x\n", adapter_id, addr);
+                                       found = 1;
+                               }
+                       }
+               }
+
+               for (i = 0;
+                    !found && (address_data->probe[i] != I2C_CLIENT_END);
+                    i += 2) {
+                       if (((adapter_id == address_data->probe[i]) ||
+                            ((address_data->
+                              probe[i] == ANY_I2C_BUS) && !is_isa))
+                           && (addr == address_data->probe[i + 1])) {
+                               dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
+                               found = 1;
+                       }
+               }
+               for (i = 0; !found && (address_data->probe_range[i] != I2C_CLIENT_END); i += 3) {
+                       if ( ((adapter_id == address_data->probe_range[i]) ||
+                             ((address_data->probe_range[i] == ANY_I2C_BUS) && !is_isa)) &&
+                            (addr >= address_data->probe_range[i + 1]) &&
+                            (addr <= address_data->probe_range[i + 2])) {
+                               found = 1;
+                               dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
+                       }
+               }
+               if (!found)
+                       continue;
+
+               /* OK, so we really should examine this address. First check
+                  whether there is some client here at all! */
+               if (is_isa ||
+                   (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
+                       if ((err = found_proc(adapter, addr, -1)))
+                               return err;
+       }
+       return 0;
+}
+
+EXPORT_SYMBOL(i2c_detect);
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
+             "Rudolf Marek <r.marek@sh.cvut.cz>");
+
+MODULE_DESCRIPTION("i2c-sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/i2c-sensor-vid.c b/drivers/i2c/i2c-sensor-vid.c
new file mode 100644 (file)
index 0000000..017dcc5
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+    i2c-sensor-vid.c -  Part of lm_sensors, Linux kernel modules for hardware
+                       monitoring
+
+    Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.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.
+
+    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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+struct vrm_model {
+       u8 vendor;
+       u8 eff_family;
+       u8 eff_model;
+       int vrm_type;
+};
+
+#define ANY 0xFF
+
+#ifdef CONFIG_X86
+
+static struct vrm_model vrm_models[] = {
+       {X86_VENDOR_AMD, 0x6, ANY, 90},         /* Athlon Duron etc */
+       {X86_VENDOR_AMD, 0xF, 0x4, 90},         /* Athlon 64 */
+       {X86_VENDOR_AMD, 0xF, 0x5, 24},         /* Opteron */
+       {X86_VENDOR_INTEL, 0x6, 0x9, 85},       /* 0.13um too */
+       {X86_VENDOR_INTEL, 0x6, 0xB, 85},       /* 0xB Tualatin */
+       {X86_VENDOR_INTEL, 0x6, ANY, 82},       /* any P6 */
+       {X86_VENDOR_INTEL, 0x7, ANY, 0},        /* Itanium */
+       {X86_VENDOR_INTEL, 0xF, 0x3, 100},      /* P4 Prescott */
+       {X86_VENDOR_INTEL, 0xF, ANY, 90},       /* P4 before Prescott */
+       {X86_VENDOR_INTEL, 0x10,ANY, 0},        /* Itanium 2 */
+       {X86_VENDOR_UNKNOWN, ANY, ANY, 0}       /* stop here */
+       };
+
+static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
+{
+       int i = 0;
+
+       while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
+               if (vrm_models[i].vendor==vendor)
+                       if ((vrm_models[i].eff_family==eff_family)&& \
+                       ((vrm_models[i].eff_model==eff_model)|| \
+                       (vrm_models[i].eff_model==ANY)))
+                               return vrm_models[i].vrm_type;
+               i++;
+       }
+
+       return 0;
+}
+
+int i2c_which_vrm(void)
+{
+       struct cpuinfo_x86 *c = cpu_data;
+       u32 eax;
+       u8 eff_family, eff_model;
+       int vrm_ret;
+
+       if (c->x86 < 6) return 0;       /* any CPU with familly lower than 6
+                                       dont have VID and/or CPUID */
+       eax = cpuid_eax(1);
+       eff_family = ((eax & 0x00000F00)>>8);
+       eff_model  = ((eax & 0x000000F0)>>4);
+       if (eff_family == 0xF) {        /* use extended model & family */
+               eff_family += ((eax & 0x00F00000)>>20);
+               eff_model += ((eax & 0x000F0000)>>16)<<4;
+       }
+       vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
+       if (vrm_ret == 0)
+               printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your"
+               " x86 CPU\n");
+       return vrm_ret;
+}
+
+/* and now something completely different for Non-x86 world*/
+#else
+int i2c_which_vrm(void)
+{
+       printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your CPU\n");
+       return 0;
+}
+#endif
+
+EXPORT_SYMBOL(i2c_which_vrm);
index ba89749..6a78f07 100644 (file)
@@ -1,5 +1,6 @@
 
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)       += icside.o
 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)       += rapide.o
+obj-$(CONFIG_BLK_DEV_IDE_BAST)         += bast-ide.o
 
 EXTRA_CFLAGS   := -Idrivers/ide
diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c
new file mode 100644 (file)
index 0000000..9d474e5
--- /dev/null
@@ -0,0 +1,71 @@
+/* linux/drivers/ide/arm/bast-ide.c
+ *
+ * Copyright (c) 2003-2004 Simtec Electronics
+ *  Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/errno.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/arch/map.h>
+#include <asm/arch/bast-map.h>
+#include <asm/arch/bast-irq.h>
+
+/* list of registered interfaces */
+static ide_hwif_t *ifs[2];
+
+static int __init
+bastide_register(unsigned int base, unsigned int aux, int irq,
+                ide_hwif_t **hwif)
+{
+       hw_regs_t hw;
+       int i;
+
+       memset(&hw, 0, sizeof(hw));
+
+       base += BAST_IDE_CS;
+       aux  += BAST_IDE_CS;
+
+       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+               hw.io_ports[i] = (unsigned long)base;
+               base += 0x20;
+       }
+
+       hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20);
+       hw.irq = irq;
+
+       ide_register_hw(&hw, hwif);
+
+       return 0;
+}
+
+static int __init bastide_init(void)
+{
+       /* we can treat the VR1000 and the BAST the same */
+
+       if (!(machine_is_bast() || machine_is_vr1000()))
+               return 0;
+
+       printk("BAST: IDE driver, (c) 2003-2004 Simtec Electronics\n");
+
+       bastide_register(BAST_VA_IDEPRI, BAST_VA_IDEPRIAUX, IRQ_IDE0, &ifs[0]);
+       bastide_register(BAST_VA_IDESEC, BAST_VA_IDESECAUX, IRQ_IDE1, &ifs[1]);
+       return 0;
+}
+
+module_init(bastide_init);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Simtec BAST / Thorcom VR1000 IDE driver");
index f40a613..edc9de7 100644 (file)
@@ -215,8 +215,6 @@ static void icside_build_sglist(ide_drive_t *drive, struct request *rq)
        struct scatterlist *sg = hwif->sg_table;
        int nents;
 
-       BUG_ON(hwif->sg_dma_active);
-
        if (rq->flags & REQ_DRIVE_TASKFILE) {
                ide_task_t *args = rq->special;
 
@@ -401,8 +399,6 @@ static int icside_dma_end(ide_drive_t *drive)
        dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents,
                     hwif->sg_dma_direction);
 
-       hwif->sg_dma_active = 0;
-
        return get_dma_residue(hwif->hw.dma) != 0;
 }
 
@@ -454,7 +450,6 @@ icside_dma_common(ide_drive_t *drive, struct request *rq,
        /*
         * We can not enable DMA on both channels.
         */
-       BUG_ON(hwif->sg_dma_active);
        BUG_ON(dma_channel_active(hwif->hw.dma));
 
        icside_build_sglist(drive, rq);
index 073c3fb..b2fa5ec 100644 (file)
@@ -465,7 +465,6 @@ byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat)
        status.all = stat;
        local_irq_set(flags);
        printk("%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
        printk(" { ");
        if (status.b.bsy)
                printk("Busy ");
@@ -479,19 +478,16 @@ byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat)
                if (status.b.check)     printk("Error ");
        }
        printk("}");
-#endif /* FANCY_STATUS_DUMPS */
        printk("\n");
        if ((status.all & (status.b.bsy|status.b.check)) == status.b.check) {
                error.all = HWIF(drive)->INB(IDE_ERROR_REG);
                printk("%s: %s: error=0x%02x", drive->name, msg, error.all);
-#if FANCY_STATUS_DUMPS
                if (error.b.ili)        printk("IllegalLengthIndication ");
                if (error.b.eom)        printk("EndOfMedia ");
                if (error.b.abrt)       printk("Aborted Command ");
                if (error.b.mcr)        printk("MediaChangeRequested ");
                if (error.b.sense_key)  printk("LastFailedSense 0x%02x ",
                                                error.b.sense_key);
-#endif /* FANCY_STATUS_DUMPS */
                printk("\n");
        }
        local_irq_restore(flags);
index ad8ae32..c0f353e 100644 (file)
@@ -10,6 +10,5 @@ obj-$(CONFIG_BLK_DEV_IDECS)           += ide-cs.o
 
 # Last of all
 obj-$(CONFIG_BLK_DEV_HD)               += hd.o
-obj-$(CONFIG_BLK_DEV_HD98)             += hd98.o
 
 EXTRA_CFLAGS   := -Idrivers/ide
index 1557a47..603018e 100644 (file)
 /* Drive specific timing taken from DOS driver v3.7 */
 
 struct qd65xx_timing_s {
-       char    offset;   /* ofset from the beginning of Model Number" */
+       s8      offset;   /* ofset from the beginning of Model Number" */
        char    model[4];    /* 4 chars from Model number, no conversion */
-       short   active;   /* active time */
-       short   recovery; /* recovery time */
+       s16     active;   /* active time */
+       s16     recovery; /* recovery time */
 } qd65xx_timing [] = {
        { 30, "2040", 110, 225 },  /* Conner CP30204                    */
        { 30, "2045", 135, 225 },  /* Conner CP30254                    */
index 2a34367..82a449d 100644 (file)
@@ -752,8 +752,8 @@ static void __init init_hwif_common_ali15x3 (ide_hwif_t *hwif)
        hwif->tuneproc = &ali15x3_tune_drive;
        hwif->speedproc = &ali15x3_tune_chipset;
 
-       /* Don't use LBA48 on ALi devices before rev 0xC5 */
-       hwif->no_lba48 = (m5229_revision <= 0xC4) ? 1 : 0;
+       /* don't use LBA48 DMA on ALi devices before rev 0xC5 */
+       hwif->no_lba48_dma = (m5229_revision <= 0xC4) ? 1 : 0;
 
        if (!hwif->dma_base) {
                hwif->drives[0].autotune = 1;
@@ -893,7 +893,7 @@ static struct pci_device_id alim15x3_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
 
 static struct pci_driver driver = {
-       .name           = "ALI15x3 IDE",
+       .name           = "ALI15x3_IDE",
        .id_table       = alim15x3_pci_tbl,
        .probe          = alim15x3_init_one,
 };
index 0eac8ee..92a2b7c 100644 (file)
 #undef REALLY_SLOW_IO          /* most systems can safely undef this */
 #define CMD640_PREFETCH_MASKS 1
 
+//#define CMD640_DUMP_REGS
+
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -748,7 +750,7 @@ int __init ide_probe_for_cmd640x (void)
        put_cmd640_reg(0x5b, 0);
 
 #ifdef CMD640_DUMP_REGS
-       CMD640_DUMP_REGS;
+       cmd640_dump_regs();
 #endif
 
        /*
@@ -870,7 +872,7 @@ int __init ide_probe_for_cmd640x (void)
        }
 
 #ifdef CMD640_DUMP_REGS
-       CMD640_DUMP_REGS;
+       cmd640_dump_regs();
 #endif
        return 1;
 }
index fe840cb..83bfe92 100644 (file)
@@ -444,7 +444,7 @@ static struct pci_device_id cy82c693_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
 
 static struct pci_driver driver = {
-       .name           = "Cypress IDE",
+       .name           = "Cypress_IDE",
        .id_table       = cy82c693_pci_tbl,
        .probe          = cy82c693_init_one,
 };
index f9c9ab6..8eb72f4 100644 (file)
 
 #include "hpt34x.h"
 
-#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 hpt34x_proc = 0;
-
-#define HPT34X_MAX_DEVS                8
-static struct pci_dev *hpt34x_devs[HPT34X_MAX_DEVS];
-static int n_hpt34x_devs;
-
-static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-       char *p = buffer;
-       int i, len;
-
-       p += sprintf(p, "\n                             "
-                       "HPT34X Chipset.\n");
-       for (i = 0; i < n_hpt34x_devs; i++) {
-               struct pci_dev *dev = hpt34x_devs[i];
-               unsigned long bibma = pci_resource_start(dev, 4);
-               u8  c0 = 0, c1 = 0;
-
-               /*
-                * at that point bibma+0x2 et bibma+0xa are byte registers
-                * to investigate:
-                */
-               c0 = inb_p((u16)bibma + 0x02);
-               c1 = inb_p((u16)bibma + 0x0a);
-               p += sprintf(p, "\nController: %d\n", i);
-               p += sprintf(p, "--------------- Primary Channel "
-                               "---------------- Secondary Channel "
-                               "-------------\n");
-               p += sprintf(p, "                %sabled "
-                               "                        %sabled\n",
-                               (c0&0x80) ? "dis" : " en",
-                               (c1&0x80) ? "dis" : " en");
-               p += sprintf(p, "--------------- drive0 --------- drive1 "
-                               "-------- drive0 ---------- drive1 ------\n");
-               p += sprintf(p, "DMA enabled:    %s              %s"
-                               "             %s               %s\n",
-                               (c0&0x20) ? "yes" : "no ",
-                               (c0&0x40) ? "yes" : "no ",
-                               (c1&0x20) ? "yes" : "no ",
-                               (c1&0x40) ? "yes" : "no " );
-
-               p += sprintf(p, "UDMA\n");
-               p += sprintf(p, "DMA\n");
-               p += sprintf(p, "PIO\n");
-       }
-       p += sprintf(p, "\n");
-
-       /* p - buffer must be less than 4k! */
-       len = (p - buffer) - offset;
-       *addr = buffer + offset;
-       
-       return len > count ? count : len;
-}
-#endif  /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static u8 hpt34x_ratemask (ide_drive_t *drive)
 {
        return 1;
@@ -277,15 +218,6 @@ static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const cha
 
        local_irq_restore(flags);
 
-#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS)
-       hpt34x_devs[n_hpt34x_devs++] = dev;
-
-       if (!hpt34x_proc) {
-               hpt34x_proc = 1;
-               ide_pci_create_host_proc("hpt34x", hpt34x_get_info);
-       }
-#endif /* DISPLAY_HPT34X_TIMINGS && CONFIG_PROC_FS */
-
        return dev->irq;
 }
 
@@ -339,7 +271,7 @@ static struct pci_device_id hpt34x_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl);
 
 static struct pci_driver driver = {
-       .name           = "HPT34x IDE",
+       .name           = "HPT34x_IDE",
        .id_table       = hpt34x_pci_tbl,
        .probe          = hpt34x_init_one,
 };
index 7030168..3625e38 100644 (file)
@@ -62,10 +62,10 @@ typedef struct pmac_ide_hwif {
        int                             irq;
        int                             kind;
        int                             aapl_bus_id;
-       int                             cable_80 : 1;
-       int                             mediabay : 1;
-       int                             broken_dma : 1;
-       int                             broken_dma_warn : 1;
+       unsigned                        cable_80 : 1;
+       unsigned                        mediabay : 1;
+       unsigned                        broken_dma : 1;
+       unsigned                        broken_dma_warn : 1;
        struct device_node*             node;
        struct macio_dev                *mdev;
        u32                             timings[4];
@@ -75,7 +75,7 @@ typedef struct pmac_ide_hwif {
         * beeing done by the generic code about the kind of dma controller
         * and format of the dma table. This will have to be fixed though.
         */
-       volatile struct dbdma_regs    dma_regs;
+       volatile struct dbdma_regs __iomem *    dma_regs;
        struct dbdma_cmd*               dma_table_cpu;
        dma_addr_t                      dma_table_dma;
        struct scatterlist*             sg_table;
@@ -497,6 +497,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
                *irq = pmac_ide[ix].irq;
 }
 
+#define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x)))
+
 /*
  * Apply the timings of the proper unit (master/slave) to the shared
  * timing register when selecting that unit. This version is for
@@ -511,12 +513,10 @@ pmac_ide_selectproc(ide_drive_t *drive)
                return;
 
        if (drive->select.b.unit & 0x01)
-               writel(pmif->timings[1],
-                       (unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
+               writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG));
        else
-               writel(pmif->timings[0],
-                       (unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
-       (void)readl((unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
+               writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG));
+       (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
 }
 
 /*
@@ -533,17 +533,13 @@ pmac_ide_kauai_selectproc(ide_drive_t *drive)
                return;
 
        if (drive->select.b.unit & 0x01) {
-               writel(pmif->timings[1],
-                      (unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG));
-               writel(pmif->timings[3],
-                      (unsigned *)(IDE_DATA_REG + IDE_KAUAI_ULTRA_CONFIG));
+               writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
+               writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
        } else {
-               writel(pmif->timings[0],
-                      (unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG));
-               writel(pmif->timings[2],
-                      (unsigned *)(IDE_DATA_REG + IDE_KAUAI_ULTRA_CONFIG));
+               writel(pmif->timings[0], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
+               writel(pmif->timings[2], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
        }
-       (void)readl((unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG));
+       (void)readl(PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
 }
 
 /*
@@ -568,8 +564,8 @@ pmac_outbsync(ide_drive_t *drive, u8 value, unsigned long port)
 {
        u32 tmp;
        
-       writeb(value, port);    
-       tmp = readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG));
+       writeb(value, (void __iomem *) port);
+       tmp = readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
 }
 
 /*
@@ -792,7 +788,7 @@ static int __pmac
 set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
                        u8 speed, int drive_cycle_time)
 {
-       int cycleTime, accessTime, recTime;
+       int cycleTime, accessTime = 0, recTime = 0;
        unsigned accessTicks, recTicks;
        struct mdma_timings_t* tm = NULL;
        int i;
@@ -1281,7 +1277,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
 static int __devinit
 pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
 {
-       unsigned long base, regbase;
+       void __iomem *base;
+       unsigned long regbase;
        int irq;
        ide_hwif_t *hwif;
        pmac_ide_hwif_t *pmif;
@@ -1324,8 +1321,8 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
        } else
                irq = macio_irq(mdev, 0);
 
-       base =  (unsigned long)ioremap(macio_resource_start(mdev, 0), 0x400);
-       regbase = base;
+       base = ioremap(macio_resource_start(mdev, 0), 0x400);
+       regbase = (unsigned long) base;
 
        hwif->pci_dev = mdev->bus->pdev;
        hwif->gendev.parent = &mdev->ofdev.dev;
@@ -1339,8 +1336,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
                if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
                        printk(KERN_WARNING "ide%d: can't request DMA resource !\n", i);
                else
-                       pmif->dma_regs = (volatile struct dbdma_regs*)
-                               ioremap(macio_resource_start(mdev, 1), 0x1000);
+                       pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000);
        } else
                pmif->dma_regs = NULL;
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
@@ -1350,9 +1346,9 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
        if (rc != 0) {
                /* The inteface is released to the common IDE layer */
                dev_set_drvdata(&mdev->ofdev.dev, NULL);
-               iounmap((void *)base);
+               iounmap(base);
                if (pmif->dma_regs)
-                       iounmap((void *)pmif->dma_regs);
+                       iounmap(pmif->dma_regs);
                memset(pmif, 0, sizeof(*pmif));
                macio_release_resource(mdev, 0);
                if (pmif->dma_regs)
@@ -1401,7 +1397,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        ide_hwif_t *hwif;
        struct device_node *np;
        pmac_ide_hwif_t *pmif;
-       unsigned long base;
+       void __iomem *base;
        unsigned long rbase, rlen;
        int i, rc;
 
@@ -1444,10 +1440,10 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        rbase = pci_resource_start(pdev, 0);
        rlen = pci_resource_len(pdev, 0);
 
-       base = (unsigned long) ioremap(rbase, rlen);
-       pmif->regbase = base + 0x2000;
+       base = ioremap(rbase, rlen);
+       pmif->regbase = (unsigned long) base + 0x2000;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-       pmif->dma_regs = (volatile struct dbdma_regs*)(base + 0x1000);
+       pmif->dma_regs = base + 0x1000;
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */        
 
        /* We use the OF node irq mapping */
@@ -1462,7 +1458,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        if (rc != 0) {
                /* The inteface is released to the common IDE layer */
                pci_set_drvdata(pdev, NULL);
-               iounmap((void *)base);
+               iounmap(base);
                memset(pmif, 0, sizeof(*pmif));
                pci_release_regions(pdev);
        }
@@ -1578,9 +1574,6 @@ pmac_ide_build_sglist(ide_drive_t *drive, struct request *rq)
        struct scatterlist *sg = pmif->sg_table;
        int nents;
 
-       if (hwif->sg_dma_active)
-               BUG();
-               
        nents = blk_rq_map_sg(drive->queue, rq, sg);
                
        if (rq_data_dir(rq) == READ)
@@ -1639,7 +1632,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
        int i, count = 0;
        ide_hwif_t *hwif = HWIF(drive);
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-       volatile struct dbdma_regs *dma = pmif->dma_regs;
+       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
        struct scatterlist *sg;
        int wr = (rq_data_dir(rq) == WRITE);
 
@@ -1715,7 +1708,6 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
                     pmif->sg_table,
                     pmif->sg_nents,
                     pmif->sg_dma_direction);
-       hwif->sg_dma_active = 0;
        return 0; /* revert to PIO for this request */
 }
 
@@ -1731,7 +1723,6 @@ pmac_ide_destroy_dmatable (ide_drive_t *drive)
        if (nents) {
                pci_unmap_sg(dev, sg, nents, pmif->sg_dma_direction);
                pmif->sg_nents = 0;
-               HWIF(drive)->sg_dma_active = 0;
        }
 }
 
@@ -1912,8 +1903,8 @@ pmac_ide_dma_start(ide_drive_t *drive, int reading)
        /* Apple adds 60ns to wrDataSetup on reads */
        if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) {
                writel(pmif->timings[unit] + (reading ? 0x00800000UL : 0),
-                       (unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
-               (void)readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG));
+                       PMAC_IDE_REG(IDE_TIMING_CONFIG));
+               (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
        }
 
        drive->waiting_for_dma = 1;
@@ -1992,7 +1983,7 @@ static int __pmac
 pmac_ide_dma_begin (ide_drive_t *drive)
 {
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-       volatile struct dbdma_regs *dma;
+       volatile struct dbdma_regs __iomem *dma;
 
        if (pmif == NULL)
                return 1;
@@ -2011,7 +2002,7 @@ static int __pmac
 pmac_ide_dma_end (ide_drive_t *drive)
 {
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-       volatile struct dbdma_regs *dma;
+       volatile struct dbdma_regs __iomem *dma;
        u32 dstat;
        
        if (pmif == NULL)
@@ -2039,7 +2030,7 @@ static int __pmac
 pmac_ide_dma_test_irq (ide_drive_t *drive)
 {
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-       volatile struct dbdma_regs *dma;
+       volatile struct dbdma_regs __iomem *dma;
        unsigned long status, timeout;
 
        if (pmif == NULL)
@@ -2107,7 +2098,7 @@ static int __pmac
 pmac_ide_dma_lostirq (ide_drive_t *drive)
 {
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-       volatile struct dbdma_regs *dma;
+       volatile struct dbdma_regs __iomem *dma;
        unsigned long status;
 
        if (pmif == NULL)
index 015f817..ed8f1c4 100644 (file)
@@ -81,7 +81,14 @@ struct eth1394hdr {
        unsigned short  h_proto;                /* packet type ID field */
 }  __attribute__((packed));
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
 
+static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb)
+{
+       return (struct eth1394hdr *)skb->mac.raw;
+}
+#endif
 
 typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
 
index e2e6194..d1758d4 100644 (file)
@@ -163,7 +163,7 @@ struct ti_ohci {
        } init_state;
 
         /* remapped memory spaces */
-        void *registers;
+        void __iomem *registers;
 
        /* dma buffer for self-id packets */
         quadlet_t *selfid_buf_cpu;
index 71fcad1..8459e05 100644 (file)
@@ -312,7 +312,7 @@ static void __devexit cs461x_pci_remove(struct pci_dev *pdev)
 }
 
 static struct pci_driver cs461x_pci_driver = {
-        .name =         "CS461x Gameport",
+        .name =         "CS461x_gameport",
         .id_table =     cs461x_pci_tbl,
         .probe =        cs461x_pci_probe,
         .remove =       __devexit_p(cs461x_pci_remove),
index 89d4693..8f1461a 100644 (file)
@@ -50,8 +50,11 @@ struct emu {
 };
 
 static struct pci_device_id emu_tbl[] = {
        { 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */
        { 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */
+       { 0x1102, 0x7004, PCI_ANY_ID, PCI_ANY_ID }, /* Dell SB Live */
+       { 0x1102, 0x7005, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy LS gameport */
        { 0, }
 };
 
@@ -109,7 +112,7 @@ static void __devexit emu_remove(struct pci_dev *pdev)
 }
 
 static struct pci_driver emu_driver = {
-        .name =         "Emu10k1 Gameport",
+        .name =         "Emu10k1_gameport",
         .id_table =     emu_tbl,
         .probe =        emu_probe,
         .remove =       __devexit_p(emu_remove),
index ff3b620..93849a6 100644 (file)
@@ -137,7 +137,7 @@ static struct pci_device_id fm801_gp_id_table[] = {
 };
 
 static struct pci_driver fm801_gp_driver = {
-       .name =         "FM801 GP",
+       .name =         "FM801_gameport",
        .id_table =     fm801_gp_id_table,
        .probe =        fm801_gp_probe,
        .remove =       __devexit_p(fm801_gp_remove),
index 7d506f1..8f62f70 100644 (file)
@@ -247,9 +247,9 @@ config JOYSTICK_AMIGA
          To compile this driver as a module, choose M here: the
          module will be called amijoy.
 
-config INPUT_JOYDUMP
+config JOYSTICK_JOYDUMP
        tristate "Gameport data dumper"
-       depends on INPUT && INPUT_JOYSTICK
+       depends on INPUT && INPUT_JOYSTICK && GAMEPORT
        help
          Say Y here if you want to dump data from your joystick into the system
          log for debugging purposes. Say N if you are making a production
index 555fb36..46326b7 100644 (file)
@@ -1,17 +1,14 @@
 /*
- * $Id: gamecon.c,v 1.22 2002/07/01 15:42:25 vojtech Exp $
+ * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
  *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
+ *  Copyright (c) 1999-2004    Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2004                 Peter Nelson <rufus-kernel@hackish.org>
  *
  *  Based on the work of:
  *     Andree Borrmann         John Dahlstrom
  *     David Kuder             Nathan Hand
  */
 
-/*
- * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
- */
-
 /*
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -72,8 +69,9 @@ __obsolete_setup("gc_3=");
 #define GC_MULTI2      5
 #define GC_N64         6
 #define GC_PSX         7
+#define GC_DDR         8
 
-#define GC_MAX         7
+#define GC_MAX         8
 
 #define GC_REFRESH_TIME        HZ/100
 
@@ -91,7 +89,8 @@ static struct gc *gc_base[3];
 static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
 
 static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
-                               "Multisystem 2-button joystick", "N64 controller", "PSX controller" };
+                               "Multisystem 2-button joystick", "N64 controller", "PSX controller"
+                               "PSX DDR controller" };
 /*
  * N64 support.
  */
@@ -237,7 +236,7 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
 #define GC_PSX_RUMBLE  7               /* Rumble in Red mode */
 
 #define GC_PSX_CLOCK   0x04            /* Pin 4 */
-#define GC_PSX_COMMAND 0x01            /* Pin 1 */
+#define GC_PSX_COMMAND 0x01            /* Pin 2 */
 #define GC_PSX_POWER   0xf8            /* Pins 5-9 */
 #define GC_PSX_SELECT  0x02            /* Pin 3 */
 
@@ -253,25 +252,29 @@ __obsolete_setup("gc_psx_delay=");
 static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
 static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
                                BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
+static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 };
 
 /*
  * gc_psx_command() writes 8bit command and reads 8bit data from
  * the psx pad.
  */
 
-static int gc_psx_command(struct gc *gc, int b)
+static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_PSX_LENGTH])
 {
-       int i, cmd, data = 0;
+       int i, j, cmd, read;
+       for (i = 0; i < 5; i++)
+               data[i] = 0;
 
        for (i = 0; i < 8; i++, b >>= 1) {
                cmd = (b & 1) ? GC_PSX_COMMAND : 0;
                parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
                udelay(gc_psx_delay);
-               data |= ((parport_read_status(gc->pd->port) ^ 0x80) & gc->pads[GC_PSX]) ? (1 << i) : 0;
+               read = parport_read_status(gc->pd->port) ^ 0x80;
+               for (j = 0; j < 5; j++)
+                       data[j] |= (read & gc_status_bit[j] & gc->pads[GC_PSX]) ? (1 << i) : 0;
                parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
                udelay(gc_psx_delay);
        }
-       return data;
 }
 
 /*
@@ -279,30 +282,39 @@ static int gc_psx_command(struct gc *gc, int b)
  * device identifier code.
  */
 
-static int gc_psx_read_packet(struct gc *gc, unsigned char *data)
+static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_LENGTH], unsigned char id[5])
 {
-       int i, id;
+       int i, j, max_len = 0;
        unsigned long flags;
+       unsigned char data2[5];
 
        parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);  /* Select pad */
-       udelay(gc_psx_delay * 2);
+       udelay(gc_psx_delay);
        parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER);                  /* Deselect, begin command */
-       udelay(gc_psx_delay * 2);
+       udelay(gc_psx_delay);
 
        local_irq_save(flags);
 
-       gc_psx_command(gc, 0x01);                                                       /* Access pad */
-       id = gc_psx_command(gc, 0x42);                                                  /* Get device id */
-       if (gc_psx_command(gc, 0) == 0x5a) {                                            /* Okay? */
-               for (i = 0; i < GC_PSX_LEN(id) * 2; i++)
-                       data[i] = gc_psx_command(gc, 0);
-       } else id = 0;
+       gc_psx_command(gc, 0x01, data2);                                                /* Access pad */
+       gc_psx_command(gc, 0x42, id);                                                   /* Get device ids */
+       gc_psx_command(gc, 0, data2);                                                   /* Dump status */
+
+       for (i =0; i < 5; i++)                                                          /* Find the longest pad */
+               if((gc_status_bit[i] & gc->pads[GC_PSX]) && (GC_PSX_LEN(id[i]) > max_len))
+                       max_len = GC_PSX_LEN(id[i]);
+
+       for (i = 0; i < max_len * 2; i++) {                                             /* Read in all the data */
+               gc_psx_command(gc, 0, data2);
+               for (j = 0; j < 5; j++)
+                       data[j][i] = data2[j];
+       }
 
        local_irq_restore(flags);
 
        parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
 
-       return GC_PSX_ID(id);
+       for(i = 0; i < 5; i++)                                                          /* Set id's to the real value */
+               id[i] = GC_PSX_ID(id[i]);
 }
 
 /*
@@ -316,6 +328,7 @@ static void gc_timer(unsigned long private)
        struct gc *gc = (void *) private;
        struct input_dev *dev = gc->dev;
        unsigned char data[GC_MAX_LENGTH];
+       unsigned char data_psx[5][GC_PSX_LENGTH];
        int i, j, s;
 
 /*
@@ -412,53 +425,72 @@ static void gc_timer(unsigned long private)
  * PSX controllers
  */
 
-       if (gc->pads[GC_PSX]) {
+       if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) {
 
-               for (i = 0; i < 5; i++)
-                       if (gc->pads[GC_PSX] & gc_status_bit[i])
-                               break;
+               gc_psx_read_packet(gc, data_psx, data);
 
-               switch (gc_psx_read_packet(gc, data)) {
+               for (i = 0; i < 5; i++) {
+                       switch (data[i]) {
 
-                       case GC_PSX_RUMBLE:
+                               case GC_PSX_RUMBLE:
 
-                               input_report_key(dev + i, BTN_THUMBL, ~data[0] & 0x04);
-                               input_report_key(dev + i, BTN_THUMBR, ~data[0] & 0x02);
-                               input_sync(dev + i);
+                                       input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04);
+                                       input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02);
 
-                       case GC_PSX_NEGCON:
-                       case GC_PSX_ANALOG:
+                               case GC_PSX_NEGCON:
+                               case GC_PSX_ANALOG:
 
-                               for (j = 0; j < 4; j++)
-                                       input_report_abs(dev + i, gc_psx_abs[j], data[j + 2]);
+                                       if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+                                               for(j = 0; j < 4; j++)
+                                                       input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+                                       } else {
+                                               for (j = 0; j < 4; j++)
+                                                       input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]);
 
-                               input_report_abs(dev + i, ABS_HAT0X, !(data[0] & 0x20) - !(data[0] & 0x80));
-                               input_report_abs(dev + i, ABS_HAT0Y, !(data[0] & 0x40) - !(data[0] & 0x10));
+                                               input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+                                               input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
+                                       }
 
-                               for (j = 0; j < 8; j++)
-                                       input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
+                                       for (j = 0; j < 8; j++)
+                                               input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
 
-                               input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
-                               input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
+                                       input_report_key(dev + i, BTN_START,  ~data_psx[i][0] & 0x08);
+                                       input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
 
-                               input_sync(dev + i);
+                                       input_sync(dev + i);
 
-                               break;
+                                       break;
 
-                       case GC_PSX_NORMAL:
+                               case GC_PSX_NORMAL:
+                                       if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+                                               for(j = 0; j < 4; j++)
+                                                       input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+                                       } else {
+                                               input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+                                               input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
 
-                               input_report_abs(dev + i, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128);
-                               input_report_abs(dev + i, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128);
+                                               /* for some reason if the extra axes are left unset they drift */
+                                               /* for (j = 0; j < 4; j++)
+                                                       input_report_abs(dev + i, gc_psx_abs[j+2], 128);
+                                                * This needs to be debugged properly,
+                                                * maybe fuzz processing needs to be done in input_sync()
+                                                *                               --vojtech
+                                                */
+                                       }
 
-                               for (j = 0; j < 8; j++)
-                                       input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
+                                       for (j = 0; j < 8; j++)
+                                               input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
 
-                               input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
-                               input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
+                                       input_report_key(dev + i, BTN_START,  ~data_psx[i][0] & 0x08);
+                                       input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
 
-                               input_sync(dev + i);
+                                       input_sync(dev + i);
 
-                               break;
+                                       break;
+
+                               case 0: /* not a pad, ignore */
+                                       break;
+                       }
                }
        }
 
@@ -490,8 +522,7 @@ static struct gc __init *gc_probe(int *config, int nargs)
 {
        struct gc *gc;
        struct parport *pp;
-       int i, j, psx;
-       unsigned char data[32];
+       int i, j;
 
        if (config[0] < 0)
                return NULL;
@@ -588,43 +619,22 @@ static struct gc __init *gc_probe(int *config, int nargs)
                                break;
 
                        case GC_PSX:
-
-                               psx = gc_psx_read_packet(gc, data);
-
-                               switch(psx) {
-                                       case GC_PSX_NEGCON:
-                                       case GC_PSX_NORMAL:
-                                       case GC_PSX_ANALOG:
-                                       case GC_PSX_RUMBLE:
-
-                                               for (j = 0; j < 6; j++) {
-                                                       psx = gc_psx_abs[j];
-                                                       set_bit(psx, gc->dev[i].absbit);
-                                                       if (j < 4) {
-                                                               gc->dev[i].absmin[psx] = 4;
-                                                               gc->dev[i].absmax[psx] = 252;
-                                                               gc->dev[i].absflat[psx] = 2;
-                                                       } else {
-                                                               gc->dev[i].absmin[psx] = -1;
-                                                               gc->dev[i].absmax[psx] = 1;
-                                                       }
-                                               }
-
-                                               for (j = 0; j < 12; j++)
-                                                       set_bit(gc_psx_btn[j], gc->dev[i].keybit);
-
-                                               break;
-
-                                       case 0:
-                                               gc->pads[GC_PSX] &= ~gc_status_bit[i];
-                                               printk(KERN_ERR "gamecon.c: No PSX controller found.\n");
-                                               break;
-
-                                       default:
-                                               gc->pads[GC_PSX] &= ~gc_status_bit[i];
-                                               printk(KERN_WARNING "gamecon.c: Unsupported PSX controller %#x,"
-                                                       " please report to <vojtech@ucw.cz>.\n", psx);
+                       case GC_DDR:
+                               if(config[i + 1] == GC_DDR) {
+                                       for (j = 0; j < 4; j++)
+                                               set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit);
+                               } else {
+                                       for (j = 0; j < 6; j++) {
+                                               set_bit(gc_psx_abs[j], gc->dev[i].absbit);
+                                               gc->dev[i].absmin[gc_psx_abs[j]] = 4;
+                                               gc->dev[i].absmax[gc_psx_abs[j]] = 252;
+                                               gc->dev[i].absflat[gc_psx_abs[j]] = 2;
+                                       }
                                }
+
+                               for (j = 0; j < 12; j++)
+                                       set_bit(gc_psx_btn[j], gc->dev[i].keybit);
+
                                break;
                }
 
index 71cb7db..cf815c7 100644 (file)
@@ -524,7 +524,7 @@ static int __init iforce_init(void)
        usb_register(&iforce_usb_driver);
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
-       serio_register_device(&iforce_serio_dev);
+       serio_register_driver(&iforce_serio_drv);
 #endif
        return 0;
 }
@@ -535,7 +535,7 @@ static void __exit iforce_exit(void)
        usb_deregister(&iforce_usb_driver);
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
-       serio_unregister_device(&iforce_serio_dev);
+       serio_unregister_driver(&iforce_serio_drv);
 #endif
 }
 
index 0665b54..9422407 100644 (file)
@@ -124,7 +124,7 @@ out:
        return IRQ_HANDLED;
 }
 
-static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev)
+static void iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct iforce *iforce;
        if (serio->type != (SERIO_RS232 | SERIO_IFORCE))
@@ -137,7 +137,7 @@ static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev)
        iforce->serio = serio;
        serio->private = iforce;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(iforce);
                return;
        }
@@ -158,9 +158,13 @@ static void iforce_serio_disconnect(struct serio *serio)
        kfree(iforce);
 }
 
-struct serio_dev iforce_serio_dev = {
-       .write_wakeup = iforce_serio_write_wakeup,
-       .interrupt =    iforce_serio_irq,
-       .connect =      iforce_serio_connect,
-       .disconnect =   iforce_serio_disconnect,
+struct serio_driver iforce_serio_drv = {
+       .driver         = {
+               .name   = "iforce",
+       },
+       .description    = "RS232 I-Force joysticks and wheels driver",
+       .write_wakeup   = iforce_serio_write_wakeup,
+       .interrupt      = iforce_serio_irq,
+       .connect        = iforce_serio_connect,
+       .disconnect     = iforce_serio_disconnect,
 };
index a8586ab..bce247b 100644 (file)
@@ -187,5 +187,5 @@ int iforce_upload_constant(struct iforce*, struct ff_effect*, int is_update);
 int iforce_upload_condition(struct iforce*, struct ff_effect*, int is_update);
 
 /* Public variables */
-extern struct serio_dev iforce_serio_dev;
+extern struct serio_driver iforce_serio_drv;
 extern struct usb_driver iforce_usb_driver;
index f326299..2b303ba 100644 (file)
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC    "Magellan and SpaceMouse 6dof controller driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Magellan and SpaceMouse 6dof controller driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -146,7 +148,7 @@ static void magellan_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void magellan_connect(struct serio *serio, struct serio_dev *dev)
+static void magellan_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct magellan *magellan;
        int i, t;
@@ -184,7 +186,7 @@ static void magellan_connect(struct serio *serio, struct serio_dev *dev)
 
        serio->private = magellan;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(magellan);
                return;
        }
@@ -199,10 +201,14 @@ static void magellan_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev magellan_dev = {
-       .interrupt =    magellan_interrupt,
-       .connect =      magellan_connect,
-       .disconnect =   magellan_disconnect,
+static struct serio_driver magellan_drv = {
+       .driver         = {
+               .name   = "magellan",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = magellan_interrupt,
+       .connect        = magellan_connect,
+       .disconnect     = magellan_disconnect,
 };
 
 /*
@@ -211,13 +217,13 @@ static struct serio_dev magellan_dev = {
 
 int __init magellan_init(void)
 {
-       serio_register_device(&magellan_dev);
+       serio_register_driver(&magellan_drv);
        return 0;
 }
 
 void __exit magellan_exit(void)
 {
-       serio_unregister_device(&magellan_dev);
+       serio_unregister_driver(&magellan_drv);
 }
 
 module_init(magellan_init);
index eb5b6f7..4041252 100644 (file)
 #include <linux/input.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC    "SpaceTec SpaceBall 2003/3003/4000 FLX driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("SpaceTec SpaceBall 2003/3003/4000 FLX driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -201,7 +203,7 @@ static void spaceball_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
+static void spaceball_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct spaceball *spaceball;
        int i, t, id;
@@ -254,7 +256,7 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
 
        serio->private = spaceball;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(spaceball);
                return;
        }
@@ -269,10 +271,14 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev spaceball_dev = {
-       .interrupt =    spaceball_interrupt,
-       .connect =      spaceball_connect,
-       .disconnect =   spaceball_disconnect,
+static struct serio_driver spaceball_drv = {
+       .driver         = {
+               .name   = "spaceball",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = spaceball_interrupt,
+       .connect        = spaceball_connect,
+       .disconnect     = spaceball_disconnect,
 };
 
 /*
@@ -281,13 +287,13 @@ static struct serio_dev spaceball_dev = {
 
 int __init spaceball_init(void)
 {
-       serio_register_device(&spaceball_dev);
+       serio_register_driver(&spaceball_drv);
        return 0;
 }
 
 void __exit spaceball_exit(void)
 {
-       serio_unregister_device(&spaceball_dev);
+       serio_unregister_driver(&spaceball_drv);
 }
 
 module_init(spaceball_init);
index 00da66c..c20091a 100644 (file)
 #include <linux/input.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC    "SpaceTec SpaceOrb 360 and Avenger 6dof controller driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("SpaceTec SpaceOrb 360 and Avenger 6dof controller driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -162,7 +164,7 @@ static void spaceorb_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
+static void spaceorb_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct spaceorb *spaceorb;
        int i, t;
@@ -201,7 +203,7 @@ static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
 
        serio->private = spaceorb;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(spaceorb);
                return;
        }
@@ -213,10 +215,14 @@ static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev spaceorb_dev = {
-       .interrupt =    spaceorb_interrupt,
-       .connect =      spaceorb_connect,
-       .disconnect =   spaceorb_disconnect,
+static struct serio_driver spaceorb_drv = {
+       .driver         = {
+               .name   = "spaceorb",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = spaceorb_interrupt,
+       .connect        = spaceorb_connect,
+       .disconnect     = spaceorb_disconnect,
 };
 
 /*
@@ -225,13 +231,13 @@ static struct serio_dev spaceorb_dev = {
 
 int __init spaceorb_init(void)
 {
-       serio_register_device(&spaceorb_dev);
+       serio_register_driver(&spaceorb_drv);
        return 0;
 }
 
 void __exit spaceorb_exit(void)
 {
-       serio_unregister_device(&spaceorb_dev);
+       serio_unregister_driver(&spaceorb_drv);
 }
 
 module_init(spaceorb_init);
index ce9be45..580e323 100644 (file)
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC    "Gravis Stinger gamepad driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Gravis Stinger gamepad driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -134,7 +136,7 @@ static void stinger_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void stinger_connect(struct serio *serio, struct serio_dev *dev)
+static void stinger_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct stinger *stinger;
        int i;
@@ -172,7 +174,7 @@ static void stinger_connect(struct serio *serio, struct serio_dev *dev)
        stinger->dev.private = stinger;
        serio->private = stinger;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(stinger);
                return;
        }
@@ -187,10 +189,14 @@ static void stinger_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev stinger_dev = {
-       .interrupt =    stinger_interrupt,
-       .connect =      stinger_connect,
-       .disconnect =   stinger_disconnect,
+static struct serio_driver stinger_drv = {
+       .driver         = {
+               .name   = "stinger",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = stinger_interrupt,
+       .connect        = stinger_connect,
+       .disconnect     = stinger_disconnect,
 };
 
 /*
@@ -199,13 +205,13 @@ static struct serio_dev stinger_dev = {
 
 int __init stinger_init(void)
 {
-       serio_register_device(&stinger_dev);
+       serio_register_driver(&stinger_drv);
        return 0;
 }
 
 void __exit stinger_exit(void)
 {
-       serio_unregister_device(&stinger_dev);
+       serio_unregister_driver(&stinger_drv);
 }
 
 module_init(stinger_init);
index 6ed46ec..e11d291 100644 (file)
@@ -322,7 +322,7 @@ static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev)
                        tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
                        for (i = 0; i < models[m].abs && i < TMDC_ABS; i++) {
-                               if (tmdc->abs[i] < 0) continue;
+                               if (tmdc->abs[j][i] < 0) continue;
                                set_bit(tmdc->abs[j][i], tmdc->dev[j].absbit);
                                tmdc->dev[j].absmin[tmdc->abs[j][i]] = 8;
                                tmdc->dev[j].absmax[tmdc->abs[j][i]] = 248;
index eb5c935..909b6b5 100644 (file)
@@ -187,7 +187,7 @@ static void twidjoy_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
+static void twidjoy_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct twidjoy_button_spec *bp;
        struct twidjoy *twidjoy;
@@ -232,7 +232,7 @@ static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
        twidjoy->dev.private = twidjoy;
        serio->private = twidjoy;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(twidjoy);
                return;
        }
@@ -246,10 +246,14 @@ static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev twidjoy_dev = {
-       .interrupt =    twidjoy_interrupt,
-       .connect =      twidjoy_connect,
-       .disconnect =   twidjoy_disconnect,
+static struct serio_driver twidjoy_drv = {
+       .driver         = {
+               .name   = "twidjoy",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = twidjoy_interrupt,
+       .connect        = twidjoy_connect,
+       .disconnect     = twidjoy_disconnect,
 };
 
 /*
@@ -258,13 +262,13 @@ static struct serio_dev twidjoy_dev = {
 
 int __init twidjoy_init(void)
 {
-       serio_register_device(&twidjoy_dev);
+       serio_register_driver(&twidjoy_drv);
        return 0;
 }
 
 void __exit twidjoy_exit(void)
 {
-       serio_unregister_device(&twidjoy_dev);
+       serio_unregister_driver(&twidjoy_drv);
 }
 
 module_init(twidjoy_init);
index 32ec90e..5f19b2a 100644 (file)
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC    "Logitech WingMan Warrior joystick driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Logitech WingMan Warrior joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -139,7 +141,7 @@ static void warrior_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void warrior_connect(struct serio *serio, struct serio_dev *dev)
+static void warrior_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct warrior *warrior;
        int i;
@@ -185,7 +187,7 @@ static void warrior_connect(struct serio *serio, struct serio_dev *dev)
 
        serio->private = warrior;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(warrior);
                return;
        }
@@ -199,10 +201,14 @@ static void warrior_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev warrior_dev = {
-       .interrupt =    warrior_interrupt,
-       .connect =      warrior_connect,
-       .disconnect =   warrior_disconnect,
+static struct serio_driver warrior_drv = {
+       .driver         = {
+               .name   = "warrior",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = warrior_interrupt,
+       .connect        = warrior_connect,
+       .disconnect     = warrior_disconnect,
 };
 
 /*
@@ -211,13 +217,13 @@ static struct serio_dev warrior_dev = {
 
 int __init warrior_init(void)
 {
-       serio_register_device(&warrior_dev);
+       serio_register_driver(&warrior_drv);
        return 0;
 }
 
 void __exit warrior_exit(void)
 {
-       serio_unregister_device(&warrior_dev);
+       serio_unregister_driver(&warrior_drv);
 }
 
 module_init(warrior_init);
index 8dc51e2..a04cf3e 100644 (file)
 #include <linux/serio.h>
 #include <linux/workqueue.h>
 
+#define DRIVER_DESC    "LK keyboard driver"
+
 MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
-MODULE_DESCRIPTION ("LK keyboard driver");
+MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE ("GPL");
 
 /*
@@ -622,7 +624,7 @@ lkkbd_reinit (void *data)
  * lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
  */
 static void
-lkkbd_connect (struct serio *serio, struct serio_dev *dev)
+lkkbd_connect (struct serio *serio, struct serio_driver *drv)
 {
        struct lkkbd *lk;
        int i;
@@ -665,7 +667,7 @@ lkkbd_connect (struct serio *serio, struct serio_dev *dev)
 
        serio->private = lk;
 
-       if (serio_open (serio, dev)) {
+       if (serio_open (serio, drv)) {
                kfree (lk);
                return;
        }
@@ -703,10 +705,14 @@ lkkbd_disconnect (struct serio *serio)
        kfree (lk);
 }
 
-static struct serio_dev lkkbd_dev = {
-       .connect = lkkbd_connect,
-       .disconnect = lkkbd_disconnect,
-       .interrupt = lkkbd_interrupt,
+static struct serio_driver lkkbd_drv = {
+       .driver         = {
+               .name   = "lkkbd",
+       },
+       .description    = DRIVER_DESC,
+       .connect        = lkkbd_connect,
+       .disconnect     = lkkbd_disconnect,
+       .interrupt      = lkkbd_interrupt,
 };
 
 /*
@@ -715,14 +721,14 @@ static struct serio_dev lkkbd_dev = {
 int __init
 lkkbd_init (void)
 {
-       serio_register_device (&lkkbd_dev);
+       serio_register_driver(&lkkbd_drv);
        return 0;
 }
 
 void __exit
 lkkbd_exit (void)
 {
-       serio_unregister_device (&lkkbd_dev);
+       serio_unregister_driver(&lkkbd_drv);
 }
 
 module_init (lkkbd_init);
index dc47acb..caa92dd 100644 (file)
 #include <linux/init.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC    "Newton keyboard driver"
+
 MODULE_AUTHOR("Justin Cormack <j.cormack@doc.ic.ac.uk>");
-MODULE_DESCRIPTION("Newton keyboard driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define NKBD_KEY       0x7f
@@ -82,7 +84,7 @@ irqreturn_t nkbd_interrupt(struct serio *serio,
 
 }
 
-void nkbd_connect(struct serio *serio, struct serio_dev *dev)
+void nkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct nkbd *nkbd;
        int i;
@@ -106,7 +108,7 @@ void nkbd_connect(struct serio *serio, struct serio_dev *dev)
        nkbd->dev.private = nkbd;
        serio->private = nkbd;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(nkbd);
                return;
        }
@@ -138,21 +140,25 @@ void nkbd_disconnect(struct serio *serio)
        kfree(nkbd);
 }
 
-struct serio_dev nkbd_dev = {
-       .interrupt =    nkbd_interrupt,
-       .connect =      nkbd_connect,
-       .disconnect =   nkbd_disconnect
+struct serio_driver nkbd_drv = {
+       .driver         = {
+               .name   = "newtonkbd",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = nkbd_interrupt,
+       .connect        = nkbd_connect,
+       .disconnect     = nkbd_disconnect,
 };
 
 int __init nkbd_init(void)
 {
-       serio_register_device(&nkbd_dev);
+       serio_register_driver(&nkbd_drv);
        return 0;
 }
 
 void __exit nkbd_exit(void)
 {
-       serio_unregister_device(&nkbd_dev);
+       serio_unregister_driver(&nkbd_drv);
 }
 
 module_init(nkbd_init);
index c281e72..7f0342c 100644 (file)
 #include <linux/serio.h>
 #include <linux/workqueue.h>
 
+#define DRIVER_DESC    "Sun keyboard driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Sun keyboard driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static unsigned char sunkbd_keycode[128] = {
@@ -221,7 +223,7 @@ static void sunkbd_reinit(void *data)
  * sunkbd_connect() probes for a Sun keyboard and fills the necessary structures.
  */
 
-static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
+static void sunkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct sunkbd *sunkbd;
        int i;
@@ -257,7 +259,7 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
 
        serio->private = sunkbd;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(sunkbd);
                return;
        }
@@ -301,10 +303,14 @@ static void sunkbd_disconnect(struct serio *serio)
        kfree(sunkbd);
 }
 
-static struct serio_dev sunkbd_dev = {
-       .interrupt =    sunkbd_interrupt,
-       .connect =      sunkbd_connect,
-       .disconnect =   sunkbd_disconnect
+static struct serio_driver sunkbd_drv = {
+       .driver         = {
+               .name   = "sunkbd",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = sunkbd_interrupt,
+       .connect        = sunkbd_connect,
+       .disconnect     = sunkbd_disconnect,
 };
 
 /*
@@ -313,13 +319,13 @@ static struct serio_dev sunkbd_dev = {
 
 int __init sunkbd_init(void)
 {
-       serio_register_device(&sunkbd_dev);
+       serio_register_driver(&sunkbd_drv);
        return 0;
 }
 
 void __exit sunkbd_exit(void)
 {
-       serio_unregister_device(&sunkbd_dev);
+       serio_unregister_driver(&sunkbd_drv);
 }
 
 module_init(sunkbd_init);
index 56adfa1..eb8a9b7 100644 (file)
 #include <linux/init.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC    "XT keyboard driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("XT keyboard driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define XTKBD_EMUL0    0xe0
@@ -86,7 +88,7 @@ irqreturn_t xtkbd_interrupt(struct serio *serio,
        return IRQ_HANDLED;
 }
 
-void xtkbd_connect(struct serio *serio, struct serio_dev *dev)
+void xtkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct xtkbd *xtkbd;
        int i;
@@ -111,7 +113,7 @@ void xtkbd_connect(struct serio *serio, struct serio_dev *dev)
 
        serio->private = xtkbd;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(xtkbd);
                return;
        }
@@ -143,21 +145,25 @@ void xtkbd_disconnect(struct serio *serio)
        kfree(xtkbd);
 }
 
-struct serio_dev xtkbd_dev = {
-       .interrupt =    xtkbd_interrupt,
-       .connect =      xtkbd_connect,
-       .disconnect =   xtkbd_disconnect
+struct serio_driver xtkbd_drv = {
+       .driver         = {
+               .name   = "xtkbd",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = xtkbd_interrupt,
+       .connect        = xtkbd_connect,
+       .disconnect     = xtkbd_disconnect,
 };
 
 int __init xtkbd_init(void)
 {
-       serio_register_device(&xtkbd_dev);
+       serio_register_driver(&xtkbd_drv);
        return 0;
 }
 
 void __exit xtkbd_exit(void)
 {
-       serio_unregister_device(&xtkbd_dev);
+       serio_unregister_driver(&xtkbd_drv);
 }
 
 module_init(xtkbd_init);
index 0063af0..6af1455 100644 (file)
@@ -277,7 +277,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
                                protocol = PSMOUSE_PS2TPP;
                        }
 
-               } else if (get_model_info(model) != NULL) {
+               } else if (model_info != NULL) {
 
                        param[0] = param[1] = param[2] = 0;
                        ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */
index 526a11e..fa8cff3 100644 (file)
@@ -109,9 +109,9 @@ static int pc110pad_open(struct input_dev *dev)
 
 static int __init pc110pad_init(void)
 {
-       if (request_region(pc110pad_io, 4, "pc110pad"))
-       {
-               printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", pc110pad_io, pc110pad_io + 4);
+       if (!request_region(pc110pad_io, 4, "pc110pad")) {
+               printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n",
+                               pc110pad_io, pc110pad_io + 4);
                return -EBUSY;
        }
 
index 0b38267..7fbd926 100644 (file)
 #include "synaptics.h"
 #include "logips2pp.h"
 
+#define DRIVER_DESC    "PS/2 mouse driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("PS/2 mouse driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static char *psmouse_proto;
@@ -142,37 +144,67 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
                        printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
                                flags & SERIO_TIMEOUT ? " timeout" : "",
                                flags & SERIO_PARITY ? " bad parity" : "");
-               if (psmouse->acking) {
-                       psmouse->ack = -1;
-                       psmouse->acking = 0;
-               }
-               psmouse->pktcnt = 0;
+               psmouse->nak = 1;
+               clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
+               clear_bit(PSMOUSE_FLAG_CMD,  &psmouse->flags);
+               wake_up_interruptible(&psmouse->wait);
                goto out;
        }
 
-       if (psmouse->acking) {
+       if (test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags)) {
                switch (data) {
                        case PSMOUSE_RET_ACK:
-                               psmouse->ack = 1;
+                               psmouse->nak = 0;
                                break;
+
                        case PSMOUSE_RET_NAK:
-                               psmouse->ack = -1;
+                               psmouse->nak = 1;
                                break;
+
+                       /*
+                        * Workaround for mice which don't ACK the Get ID command.
+                        * These are valid mouse IDs that we recognize.
+                        */
+                       case 0x00:
+                       case 0x03:
+                       case 0x04:
+                               if (test_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags)) {
+                                       psmouse->nak = 0;
+                                       break;
+                               }
+                               /* Fall through */
                        default:
-                               psmouse->ack = 1;       /* Workaround for mice which don't ACK the Get ID command */
-                               if (psmouse->cmdcnt)
-                                       psmouse->cmdbuf[--psmouse->cmdcnt] = data;
-                               break;
+                               goto out;
                }
-               psmouse->acking = 0;
-               goto out;
+
+               if (!psmouse->nak && psmouse->cmdcnt) {
+                       set_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+                       set_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags);
+               }
+               clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
+               wake_up_interruptible(&psmouse->wait);
+
+               if (data == PSMOUSE_RET_ACK || data == PSMOUSE_RET_NAK)
+                       goto out;
        }
 
-       if (psmouse->cmdcnt) {
-               psmouse->cmdbuf[--psmouse->cmdcnt] = data;
+       if (test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags)) {
+               if (psmouse->cmdcnt)
+                       psmouse->cmdbuf[--psmouse->cmdcnt] = data;
+
+               if (test_and_clear_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags) && psmouse->cmdcnt)
+                       wake_up_interruptible(&psmouse->wait);
+
+               if (!psmouse->cmdcnt) {
+                       clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+                       wake_up_interruptible(&psmouse->wait);
+               }
                goto out;
        }
 
+       if (psmouse->state == PSMOUSE_INITIALIZING)
+               goto out;
+
        if (psmouse->state == PSMOUSE_ACTIVATED &&
            psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
                printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
@@ -238,78 +270,96 @@ out:
  * psmouse_sendbyte() sends a byte to the mouse, and waits for acknowledge.
  * It doesn't handle retransmission, though it could - because when there would
  * be need for retransmissions, the mouse has to be replaced anyway.
+ *
+ * psmouse_sendbyte() can only be called from a process context
  */
 
 static int psmouse_sendbyte(struct psmouse *psmouse, unsigned char byte)
 {
-       int timeout = 10000; /* 100 msec */
-       psmouse->ack = 0;
-       psmouse->acking = 1;
-
-       if (serio_write(psmouse->serio, byte)) {
-               psmouse->acking = 0;
-               return -1;
-       }
+       psmouse->nak = 1;
+       set_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
 
-       while (!psmouse->ack && timeout--) udelay(10);
+       if (serio_write(psmouse->serio, byte) == 0)
+               wait_event_interruptible_timeout(psmouse->wait,
+                               !test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags),
+                               msecs_to_jiffies(200));
 
-       return -(psmouse->ack <= 0);
+       clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
+       return -psmouse->nak;
 }
 
 /*
  * psmouse_command() sends a command and its parameters to the mouse,
  * then waits for the response and puts it in the param array.
+ *
+ * psmouse_command() can only be called from a process context
  */
 
 int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
 {
-       int timeout = 500000; /* 500 msec */
+       int timeout;
        int send = (command >> 12) & 0xf;
        int receive = (command >> 8) & 0xf;
+       int rc = -1;
        int i;
 
-       psmouse->cmdcnt = receive;
+       timeout = msecs_to_jiffies(command == PSMOUSE_CMD_RESET_BAT ? 4000 : 500);
 
-       if (command == PSMOUSE_CMD_RESET_BAT)
-                timeout = 4000000; /* 4 sec */
+       clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+       if (command == PSMOUSE_CMD_GETID)
+               set_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags);
 
-       /* initialize cmdbuf with preset values from param */
-       if (receive)
-          for (i = 0; i < receive; i++)
-               psmouse->cmdbuf[(receive - 1) - i] = param[i];
+       if (receive && param)
+               for (i = 0; i < receive; i++)
+                       psmouse->cmdbuf[(receive - 1) - i] = param[i];
+
+       psmouse->cmdcnt = receive;
 
        if (command & 0xff)
                if (psmouse_sendbyte(psmouse, command & 0xff))
-                       return (psmouse->cmdcnt = 0) - 1;
+                       goto out;
 
        for (i = 0; i < send; i++)
                if (psmouse_sendbyte(psmouse, param[i]))
-                       return (psmouse->cmdcnt = 0) - 1;
-
-       while (psmouse->cmdcnt && timeout--) {
-
-               if (psmouse->cmdcnt == 1 && command == PSMOUSE_CMD_RESET_BAT &&
-                               timeout > 100000) /* do not run in a endless loop */
-                       timeout = 100000; /* 1 sec */
+                       goto out;
 
-               if (psmouse->cmdcnt == 1 && command == PSMOUSE_CMD_GETID &&
-                   psmouse->cmdbuf[1] != 0xab && psmouse->cmdbuf[1] != 0xac) {
+       timeout = wait_event_interruptible_timeout(psmouse->wait,
+                               !test_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags), timeout);
+
+       if (psmouse->cmdcnt && timeout > 0) {
+               if (command == PSMOUSE_CMD_RESET_BAT && jiffies_to_msecs(timeout) > 100)
+                       timeout = msecs_to_jiffies(100);
+
+               if (command == PSMOUSE_CMD_GETID &&
+                   psmouse->cmdbuf[receive - 1] != 0xab && psmouse->cmdbuf[receive - 1] != 0xac) {
+                       /*
+                        * Device behind the port is not a keyboard
+                        * so we don't need to wait for the 2nd byte
+                        * of ID response.
+                        */
+                       clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
                        psmouse->cmdcnt = 0;
-                       break;
                }
 
-               udelay(1);
+               wait_event_interruptible_timeout(psmouse->wait,
+                               !test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags), timeout);
        }
 
-       for (i = 0; i < receive; i++)
-               param[i] = psmouse->cmdbuf[(receive - 1) - i];
+       if (param)
+               for (i = 0; i < receive; i++)
+                       param[i] = psmouse->cmdbuf[(receive - 1) - i];
 
-       if (psmouse->cmdcnt)
-               return (psmouse->cmdcnt = 0) - 1;
+       if (psmouse->cmdcnt && (command != PSMOUSE_CMD_RESET_BAT || psmouse->cmdcnt != 1))
+               goto out;
 
-       return 0;
-}
+       rc = 0;
 
+out:
+       clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+       clear_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags);
+       clear_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags);
+       return rc;
+}
 
 /*
  * psmouse_sliced_command() sends an extended PS/2 command to the mouse
@@ -394,6 +444,8 @@ static int im_explorer_detect(struct psmouse *psmouse)
 {
        unsigned char param[2];
 
+       intellimouse_detect(psmouse);
+
        param[0] = 200;
        psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
        param[0] = 200;
@@ -597,6 +649,21 @@ static void psmouse_initialize(struct psmouse *psmouse)
        psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM);
 }
 
+/*
+ * psmouse_set_state() sets new psmouse state and resets all flags and
+ * counters while holding serio lock so fighting with interrupt handler
+ * is not a concern.
+ */
+
+static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
+{
+       serio_pause_rx(psmouse->serio);
+       psmouse->state = new_state;
+       psmouse->pktcnt = psmouse->cmdcnt = psmouse->out_of_sync = 0;
+       psmouse->flags = 0;
+       serio_continue_rx(psmouse->serio);
+}
+
 /*
  * psmouse_activate() enables the mouse so that we get motion reports from it.
  */
@@ -606,9 +673,24 @@ static void psmouse_activate(struct psmouse *psmouse)
        if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE))
                printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", psmouse->serio->phys);
 
-       psmouse->state = PSMOUSE_ACTIVATED;
+       psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
+}
+
+
+/*
+ * psmouse_deactivate() puts the mouse into poll mode so that we don't get motion
+ * reports from it unless we explicitely request it.
+ */
+
+static void psmouse_deactivate(struct psmouse *psmouse)
+{
+       if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE))
+               printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n", psmouse->serio->phys);
+
+       psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 }
 
+
 /*
  * psmouse_cleanup() resets the mouse into power-on state.
  */
@@ -626,22 +708,21 @@ static void psmouse_cleanup(struct serio *serio)
 
 static void psmouse_disconnect(struct serio *serio)
 {
-       struct psmouse *psmouse = serio->private;
+       struct psmouse *psmouse, *parent;
 
-       psmouse->state = PSMOUSE_CMD_MODE;
+       psmouse = serio->private;
+       psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 
-       if (psmouse->ptport) {
-               if (psmouse->ptport->deactivate)
-                       psmouse->ptport->deactivate(psmouse);
-               __serio_unregister_port(&psmouse->ptport->serio); /* we have serio_sem */
-               kfree(psmouse->ptport);
-               psmouse->ptport = NULL;
+       if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
+               parent = serio->parent->private;
+               if (parent->pt_deactivate)
+                       parent->pt_deactivate(parent);
        }
 
        if (psmouse->disconnect)
                psmouse->disconnect(psmouse);
 
-       psmouse->state = PSMOUSE_IGNORE;
+       psmouse_set_state(psmouse, PSMOUSE_IGNORE);
 
        input_unregister_device(&psmouse->dev);
        serio_close(serio);
@@ -652,39 +733,49 @@ static void psmouse_disconnect(struct serio *serio)
  * psmouse_connect() is a callback from the serio module when
  * an unhandled serio port is found.
  */
-static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
+static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
 {
-       struct psmouse *psmouse;
+       struct psmouse *psmouse, *parent = NULL;
 
        if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
            (serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU)
                return;
 
+       /*
+        * If this is a pass-through port deactivate parent so the device
+        * connected to this port can be successfully identified
+        */
+       if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
+               parent = serio->parent->private;
+               psmouse_deactivate(parent);
+       }
+
        if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL)))
-               return;
+               goto out;
 
        memset(psmouse, 0, sizeof(struct psmouse));
 
+       init_waitqueue_head(&psmouse->wait);
        init_input_dev(&psmouse->dev);
        psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
        psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
        psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
-       psmouse->state = PSMOUSE_CMD_MODE;
        psmouse->serio = serio;
        psmouse->dev.private = psmouse;
+       psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
 
        serio->private = psmouse;
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(psmouse);
                serio->private = NULL;
-               return;
+               goto out;
        }
 
        if (psmouse_probe(psmouse) < 0) {
                serio_close(serio);
                kfree(psmouse);
                serio->private = NULL;
-               return;
+               goto out;
        }
 
        psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
@@ -711,63 +802,88 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
 
        printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
 
+       psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+
        psmouse_initialize(psmouse);
 
-       if (psmouse->ptport) {
-               printk(KERN_INFO "serio: %s port at %s\n", psmouse->ptport->serio.name, psmouse->phys);
-               __serio_register_port(&psmouse->ptport->serio); /* we have serio_sem */
-               if (psmouse->ptport->activate)
-                       psmouse->ptport->activate(psmouse);
+       if (parent && parent->pt_activate)
+               parent->pt_activate(parent);
+
+       if (serio->child) {
+               /*
+                * Nothing to be done here, serio core will detect that
+                * the driver set serio->child and will register it for us.
+                */
+               printk(KERN_INFO "serio: %s port at %s\n", serio->child->name, psmouse->phys);
        }
 
        psmouse_activate(psmouse);
+
+out:
+       /* If this is a pass-through port the parent awaits to be activated */
+       if (parent)
+               psmouse_activate(parent);
 }
 
 
 static int psmouse_reconnect(struct serio *serio)
 {
        struct psmouse *psmouse = serio->private;
-       struct serio_dev *dev = serio->dev;
+       struct psmouse *parent = NULL;
+       struct serio_driver *drv = serio->drv;
+       int rc = -1;
 
-       if (!dev || !psmouse) {
+       if (!drv || !psmouse) {
                printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
                return -1;
        }
 
-       psmouse->state = PSMOUSE_CMD_MODE;
-       psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = psmouse->out_of_sync = 0;
+       if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
+               parent = serio->parent->private;
+               psmouse_deactivate(parent);
+       }
+
+       psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+
        if (psmouse->reconnect) {
               if (psmouse->reconnect(psmouse))
-                       return -1;
+                       goto out;
        } else if (psmouse_probe(psmouse) < 0 ||
                   psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0))
-               return -1;
+               goto out;
 
        /* ok, the device type (and capabilities) match the old one,
         * we can continue using it, complete intialization
         */
+       psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+
        psmouse_initialize(psmouse);
 
-       if (psmouse->ptport) {
-                       if (psmouse_reconnect(&psmouse->ptport->serio)) {
-                       __serio_unregister_port(&psmouse->ptport->serio);
-                       __serio_register_port(&psmouse->ptport->serio);
-                       if (psmouse->ptport->activate)
-                               psmouse->ptport->activate(psmouse);
-               }
-       }
+       if (parent && parent->pt_activate)
+               parent->pt_activate(parent);
 
        psmouse_activate(psmouse);
-       return 0;
+       rc = 0;
+
+out:
+       /* If this is a pass-through port the parent waits to be activated */
+       if (parent)
+               psmouse_activate(parent);
+
+       return rc;
 }
 
 
-static struct serio_dev psmouse_dev = {
-       .interrupt =    psmouse_interrupt,
-       .connect =      psmouse_connect,
-       .reconnect =    psmouse_reconnect,
-       .disconnect =   psmouse_disconnect,
-       .cleanup =      psmouse_cleanup,
+static struct serio_driver psmouse_drv = {
+       .driver         = {
+               .name   = "psmouse",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = psmouse_interrupt,
+       .connect        = psmouse_connect,
+       .reconnect      = psmouse_reconnect,
+       .disconnect     = psmouse_disconnect,
+       .cleanup        = psmouse_cleanup,
 };
 
 static inline void psmouse_parse_proto(void)
@@ -787,13 +903,13 @@ static inline void psmouse_parse_proto(void)
 int __init psmouse_init(void)
 {
        psmouse_parse_proto();
-       serio_register_device(&psmouse_dev);
+       serio_register_driver(&psmouse_drv);
        return 0;
 }
 
 void __exit psmouse_exit(void)
 {
-       serio_unregister_device(&psmouse_dev);
+       serio_unregister_driver(&psmouse_drv);
 }
 
 module_init(psmouse_init);
index 47fbc48..20bbab4 100644 (file)
@@ -9,6 +9,7 @@
 #define PSMOUSE_CMD_GETID      0x02f2
 #define PSMOUSE_CMD_SETRATE    0x10f3
 #define PSMOUSE_CMD_ENABLE     0x00f4
+#define PSMOUSE_CMD_DISABLE    0x00f5
 #define PSMOUSE_CMD_RESET_DIS  0x00f6
 #define PSMOUSE_CMD_RESET_BAT  0x02ff
 
 #define PSMOUSE_RET_ACK                0xfa
 #define PSMOUSE_RET_NAK                0xfe
 
-/* psmouse states */
-#define PSMOUSE_CMD_MODE       0
-#define PSMOUSE_ACTIVATED      1
-#define PSMOUSE_IGNORE         2
+#define PSMOUSE_FLAG_ACK       0       /* Waiting for ACK/NAK */
+#define PSMOUSE_FLAG_CMD       1       /* Waiting for command to finish */
+#define PSMOUSE_FLAG_CMD1      2       /* Waiting for the first byte of command response */
+#define PSMOUSE_FLAG_WAITID    3       /* Command execiting is GET ID */
+
+enum psmouse_state {
+       PSMOUSE_IGNORE,
+       PSMOUSE_INITIALIZING,
+       PSMOUSE_CMD_MODE,
+       PSMOUSE_ACTIVATED,
+};
 
 /* psmouse protocol handler return codes */
 typedef enum {
@@ -29,20 +37,10 @@ typedef enum {
        PSMOUSE_FULL_PACKET
 } psmouse_ret_t;
 
-struct psmouse;
-
-struct psmouse_ptport {
-       struct serio serio;
-
-       void (*activate)(struct psmouse *parent);
-       void (*deactivate)(struct psmouse *parent);
-};
-
 struct psmouse {
        void *private;
        struct input_dev dev;
        struct serio *serio;
-       struct psmouse_ptport *ptport;
        char *vendor;
        char *name;
        unsigned char cmdbuf[8];
@@ -53,16 +51,22 @@ struct psmouse {
        unsigned char model;
        unsigned long last;
        unsigned long out_of_sync;
-       unsigned char state;
-       char acking;
-       volatile char ack;
+       enum psmouse_state state;
+       unsigned char nak;
        char error;
        char devname[64];
        char phys[32];
+       unsigned long flags;
 
-       psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); 
+       /* Used to signal completion from interrupt handler */
+       wait_queue_head_t wait;
+
+       psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
        int (*reconnect)(struct psmouse *psmouse);
        void (*disconnect)(struct psmouse *psmouse);
+
+       void (*pt_activate)(struct psmouse *psmouse);
+       void (*pt_deactivate)(struct psmouse *psmouse);
 };
 
 #define PSMOUSE_PS2            1
index 9c97a0a..e1db6e0 100644 (file)
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC    "Serial mouse driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Serial mouse driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
@@ -237,7 +239,7 @@ static void sermouse_disconnect(struct serio *serio)
  * an unhandled serio port is found.
  */
 
-static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
+static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct sermouse *sermouse;
        unsigned char c;
@@ -279,7 +281,7 @@ static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
        sermouse->dev.id.product = c;
        sermouse->dev.id.version = 0x0100;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(sermouse);
                return;
        }
@@ -289,21 +291,25 @@ static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
        printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
 }
 
-static struct serio_dev sermouse_dev = {
-       .interrupt =    sermouse_interrupt,
-       .connect =      sermouse_connect,
-       .disconnect =   sermouse_disconnect
+static struct serio_driver sermouse_drv = {
+       .driver         = {
+               .name   = "sermouse",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = sermouse_interrupt,
+       .connect        = sermouse_connect,
+       .disconnect     = sermouse_disconnect,
 };
 
 int __init sermouse_init(void)
 {
-       serio_register_device(&sermouse_dev);
+       serio_register_driver(&sermouse_drv);
        return 0;
 }
 
 void __exit sermouse_exit(void)
 {
-       serio_unregister_device(&sermouse_dev);
+       serio_unregister_driver(&sermouse_drv);
 }
 
 module_init(sermouse_init);
index 2bd152f..101b809 100644 (file)
@@ -212,9 +212,9 @@ static int synaptics_set_mode(struct psmouse *psmouse, int mode)
 /*****************************************************************************
  *     Synaptics pass-through PS/2 port support
  ****************************************************************************/
-static int synaptics_pt_write(struct serio *port, unsigned char c)
+static int synaptics_pt_write(struct serio *serio, unsigned char c)
 {
-       struct psmouse *parent = port->driver;
+       struct psmouse *parent = serio->parent->private;
        char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
 
        if (psmouse_sliced_command(parent, c))
@@ -233,22 +233,19 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
 {
        struct psmouse *child = ptport->private;
 
-       if (child) {
-               if (child->state == PSMOUSE_ACTIVATED) {
-                       serio_interrupt(ptport, packet[1], 0, NULL);
-                       serio_interrupt(ptport, packet[4], 0, NULL);
-                       serio_interrupt(ptport, packet[5], 0, NULL);
-                       if (child->type >= PSMOUSE_GENPS)
-                               serio_interrupt(ptport, packet[2], 0, NULL);
-               } else if (child->state != PSMOUSE_IGNORE) {
-                       serio_interrupt(ptport, packet[1], 0, NULL);
-               }
-       }
+       if (child && child->state == PSMOUSE_ACTIVATED) {
+               serio_interrupt(ptport, packet[1], 0, NULL);
+               serio_interrupt(ptport, packet[4], 0, NULL);
+               serio_interrupt(ptport, packet[5], 0, NULL);
+               if (child->type >= PSMOUSE_GENPS)
+                       serio_interrupt(ptport, packet[2], 0, NULL);
+       } else
+               serio_interrupt(ptport, packet[1], 0, NULL);
 }
 
 static void synaptics_pt_activate(struct psmouse *psmouse)
 {
-       struct psmouse *child = psmouse->ptport->serio.private;
+       struct psmouse *child = psmouse->serio->child->private;
 
        /* adjust the touchpad to child's choice of protocol */
        if (child && child->type >= PSMOUSE_GENPS) {
@@ -259,23 +256,25 @@ static void synaptics_pt_activate(struct psmouse *psmouse)
 
 static void synaptics_pt_create(struct psmouse *psmouse)
 {
-       struct psmouse_ptport *port;
+       struct serio *serio;
 
-       psmouse->ptport = port = kmalloc(sizeof(struct psmouse_ptport), GFP_KERNEL);
-       if (!port) {
+       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+       if (!serio) {
                printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
                return;
        }
 
-       memset(port, 0, sizeof(struct psmouse_ptport));
+       memset(serio, 0, sizeof(struct serio));
+
+       serio->type = SERIO_PS_PSTHRU;
+       strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
+       strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
+       serio->write = synaptics_pt_write;
+       serio->parent = psmouse->serio;
 
-       port->serio.type = SERIO_PS_PSTHRU;
-       port->serio.name = "Synaptics pass-through";
-       port->serio.phys = "synaptics-pt/serio0";
-       port->serio.write = synaptics_pt_write;
-       port->serio.driver = psmouse;
+       psmouse->pt_activate = synaptics_pt_activate;
 
-       port->activate = synaptics_pt_activate;
+       psmouse->serio->child = serio;
 }
 
 /*****************************************************************************
@@ -470,9 +469,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_r
                if (unlikely(priv->pkt_type == SYN_NEWABS))
                        priv->pkt_type = synaptics_detect_pkt_type(psmouse);
 
-               if (psmouse->ptport && psmouse->ptport->serio.dev && synaptics_is_pt_packet(psmouse->packet))
-                       synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet);
-               else
+               if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) {
+                       if (psmouse->serio->child)
+                               synaptics_pass_pt_packet(psmouse->serio->child, psmouse->packet);
+               } else
                        synaptics_process_packet(psmouse);
 
                return PSMOUSE_FULL_PACKET;
index c26d907..3845ca4 100644 (file)
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC    "Serial DEC VSXXX-AA/GA mouse / DEC tablet driver"
+
 MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
-MODULE_DESCRIPTION ("Serial DEC VSXXX-AA/GA mouse / DEC tablet driver");
+MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE ("GPL");
 
 #undef VSXXXAA_DEBUG
@@ -482,7 +484,7 @@ vsxxxaa_disconnect (struct serio *serio)
 }
 
 static void
-vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
+vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
 {
        struct vsxxxaa *mouse;
 
@@ -524,7 +526,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
        mouse->dev.id.bustype = BUS_RS232;
        mouse->serio = serio;
 
-       if (serio_open (serio, dev)) {
+       if (serio_open (serio, drv)) {
                kfree (mouse);
                return;
        }
@@ -540,23 +542,27 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
        printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
 }
 
-static struct serio_dev vsxxxaa_dev = {
-       .connect = vsxxxaa_connect,
-       .interrupt = vsxxxaa_interrupt,
-       .disconnect = vsxxxaa_disconnect,
+static struct serio_driver vsxxxaa_drv = {
+       .driver         = {
+               .name   = "vsxxxaa",
+       },
+       .description    = DRIVER_DESC,
+       .connect        = vsxxxaa_connect,
+       .interrupt      = vsxxxaa_interrupt,
+       .disconnect     = vsxxxaa_disconnect,
 };
 
 int __init
 vsxxxaa_init (void)
 {
-       serio_register_device (&vsxxxaa_dev);
+       serio_register_driver(&vsxxxaa_drv);
        return 0;
 }
 
 void __exit
 vsxxxaa_exit (void)
 {
-       serio_unregister_device (&vsxxxaa_dev);
+       serio_unregister_driver(&vsxxxaa_drv);
 }
 
 module_init (vsxxxaa_init);
index a47dec2..cf52b61 100644 (file)
@@ -17,3 +17,4 @@ obj-$(CONFIG_SERIO_98KBD)     += 98kbd-io.o
 obj-$(CONFIG_SERIO_GSCPS2)     += gscps2.o
 obj-$(CONFIG_SERIO_PCIPS2)     += pcips2.o
 obj-$(CONFIG_SERIO_MACEPS2)    += maceps2.o
+obj-$(CONFIG_SERIO_RAW)                += serio_raw.o
index 2234ff3..ee78546 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/interrupt.h>
 #include <linux/serio.h>
 #include <linux/errno.h>
+#include <linux/err.h>
 
 #include <asm/io.h>
 
@@ -43,9 +44,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("82C710 C&T mouse port chip driver");
 MODULE_LICENSE("GPL");
 
-static char ct82c710_name[] = "C&T 82c710 mouse port";
-static char ct82c710_phys[16];
-
 /*
  * ct82c710 interface
  */
@@ -61,10 +59,22 @@ static char ct82c710_phys[16];
 
 #define CT82C710_IRQ          12
 
-static int ct82c710_data;
-static int ct82c710_status;
+#define CT82C710_DATA         ct82c710_iores.start
+#define CT82C710_STATUS       (ct82c710_iores.start + 1)
+
+static struct serio *ct82c710_port;
+static struct platform_device *ct82c710_device;
+static struct resource ct82c710_iores;
+
+/*
+ * Interrupt handler for the 82C710 mouse port. A character
+ * is waiting in the 82C710.
+ */
 
-static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs);
+static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
+{
+       return serio_interrupt(ct82c710_port, inb(CT82C710_DATA), 0, regs);
+}
 
 /*
  * Wait for device to send output char and flush any input char.
@@ -74,10 +84,10 @@ static int ct82c170_wait(void)
 {
        int timeout = 60000;
 
-       while ((inb(ct82c710_status) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE))
+       while ((inb(CT82C710_STATUS) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE))
                       != (CT82C710_DEV_IDLE | CT82C710_TX_IDLE) && timeout) {
 
-               if (inb_p(ct82c710_status) & CT82C710_RX_FULL) inb_p(ct82c710_data);
+               if (inb_p(CT82C710_STATUS) & CT82C710_RX_FULL) inb_p(CT82C710_DATA);
 
                udelay(1);
                timeout--;
@@ -91,7 +101,7 @@ static void ct82c710_close(struct serio *serio)
        if (ct82c170_wait())
                printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
 
-       outb_p(inb_p(ct82c710_status) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), ct82c710_status);
+       outb_p(inb_p(CT82C710_STATUS) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), CT82C710_STATUS);
 
        if (ct82c170_wait())
                printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
@@ -106,21 +116,21 @@ static int ct82c710_open(struct serio *serio)
        if (request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL))
                return -1;
 
-       status = inb_p(ct82c710_status);
+       status = inb_p(CT82C710_STATUS);
 
        status |= (CT82C710_ENABLE | CT82C710_RESET);
-       outb_p(status, ct82c710_status);
+       outb_p(status, CT82C710_STATUS);
 
        status &= ~(CT82C710_RESET);
-       outb_p(status, ct82c710_status);
+       outb_p(status, CT82C710_STATUS);
 
        status |= CT82C710_INTS_ON;
-       outb_p(status, ct82c710_status);        /* Enable interrupts */
+       outb_p(status, CT82C710_STATUS);        /* Enable interrupts */
 
        while (ct82c170_wait()) {
                printk(KERN_ERR "ct82c710: Device busy in open()\n");
                status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON);
-               outb_p(status, ct82c710_status);
+               outb_p(status, CT82C710_STATUS);
                free_irq(CT82C710_IRQ, NULL);
                return -1;
        }
@@ -135,30 +145,10 @@ static int ct82c710_open(struct serio *serio)
 static int ct82c710_write(struct serio *port, unsigned char c)
 {
        if (ct82c170_wait()) return -1;
-       outb_p(c, ct82c710_data);
+       outb_p(c, CT82C710_DATA);
        return 0;
 }
 
-static struct serio ct82c710_port =
-{
-       .type   = SERIO_8042,
-       .name   = ct82c710_name,
-       .phys   = ct82c710_phys,
-       .write  = ct82c710_write,
-       .open   = ct82c710_open,
-       .close  = ct82c710_close,
-};
-
-/*
- * Interrupt handler for the 82C710 mouse port. A character
- * is waiting in the 82C710.
- */
-
-static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
-{
-       return serio_interrupt(&ct82c710_port, inb(ct82c710_data), 0, regs);
-}
-
 /*
  * See if we can find a 82C710 device. Read mouse address.
  */
@@ -175,36 +165,60 @@ static int __init ct82c710_probe(void)
                return -1;                              /* No: no 82C710 here */
 
        outb_p(0x0d, 0x390);                            /* Write index */
-       ct82c710_data = inb_p(0x391) << 2;              /* Get mouse I/O address */
-       ct82c710_status = ct82c710_data + 1;
+       ct82c710_iores.start = inb_p(0x391) << 2;       /* Get mouse I/O address */
+       ct82c710_iores.end = ct82c710_iores.start + 1;
+       ct82c710_iores.flags = IORESOURCE_IO;
        outb_p(0x0f, 0x390);
        outb_p(0x0f, 0x391);                            /* Close config mode */
 
        return 0;
 }
 
+static struct serio * __init ct82c710_allocate_port(void)
+{
+       struct serio *serio;
+
+       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+       if (serio) {
+               memset(serio, 0, sizeof(struct serio));
+               serio->type = SERIO_8042;
+               serio->open = ct82c710_open;
+               serio->close = ct82c710_close;
+               serio->write = ct82c710_write;
+               serio->dev.parent = &ct82c710_device->dev;
+               strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name));
+               snprintf(serio->phys, sizeof(serio->phys), "isa%04lx/serio0", CT82C710_DATA);
+       }
+
+       return serio;
+}
+
 int __init ct82c710_init(void)
 {
        if (ct82c710_probe())
                return -ENODEV;
 
-       if (request_region(ct82c710_data, 2, "ct82c710"))
-               return -EBUSY;
+       ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1);
+       if (IS_ERR(ct82c710_device))
+               return PTR_ERR(ct82c710_device);
 
-       sprintf(ct82c710_phys, "isa%04x/serio0", ct82c710_data);
+       if (!(ct82c710_port = ct82c710_allocate_port())) {
+               platform_device_unregister(ct82c710_device);
+               return -ENOMEM;
+       }
 
-       serio_register_port(&ct82c710_port);
+       serio_register_port(ct82c710_port);
 
-       printk(KERN_INFO "serio: C&T 82c710 mouse port at %#x irq %d\n",
-               ct82c710_data, CT82C710_IRQ);
+       printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n",
+               CT82C710_DATA, CT82C710_IRQ);
 
        return 0;
 }
 
 void __exit ct82c710_exit(void)
 {
-       serio_unregister_port(&ct82c710_port);
-       release_region(ct82c710_data, 2);
+       serio_unregister_port(ct82c710_port);
+       platform_device_unregister(ct82c710_device);
 }
 
 module_init(ct82c710_init);
index 48a0ad5..cd9f987 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
  *
  * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
- *     Copyright (c) 1999 Alex deVries <adevries@thepuffingroup.com>
+ *     Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca>
  *     Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
  *     Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
  *     Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
@@ -91,7 +91,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs);
 struct gscps2port {
        struct list_head node;
        struct parisc_device *padev;
-       struct serio port;
+       struct serio *port;
        spinlock_t lock;
        char *addr;
        u8 act, append; /* position in buffer[] */
@@ -100,7 +100,6 @@ struct gscps2port {
                u8 str;
        } buffer[BUFFER_SIZE+1];
        int id;
-       char name[32];
 };
 
 /*
@@ -272,7 +271,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
            rxflags =   ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) |
                        ((status & GSC_STAT_PERR) ? SERIO_PARITY  : 0 );
 
-           serio_interrupt(&ps2port->port, data, rxflags, regs);
+           serio_interrupt(ps2port->port, data, rxflags, regs);
 
          } /* while() */
 
@@ -288,7 +287,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
 
 static int gscps2_write(struct serio *port, unsigned char data)
 {
-       struct gscps2port *ps2port = port->driver;
+       struct gscps2port *ps2port = port->port_data;
 
        if (!gscps2_writeb_output(ps2port, data)) {
                printk(KERN_DEBUG PFX "sending byte %#x failed.\n", data);
@@ -304,7 +303,7 @@ static int gscps2_write(struct serio *port, unsigned char data)
 
 static int gscps2_open(struct serio *port)
 {
-       struct gscps2port *ps2port = port->driver;
+       struct gscps2port *ps2port = port->port_data;
 
        gscps2_reset(ps2port);
 
@@ -319,7 +318,7 @@ static int gscps2_open(struct serio *port)
 
 static void gscps2_close(struct serio *port)
 {
-       struct gscps2port *ps2port = port->driver;
+       struct gscps2port *ps2port = port->port_data;
        gscps2_enable(ps2port, DISABLE);
 }
 
@@ -343,7 +342,8 @@ static struct serio gscps2_serio_port =
 
 static int __init gscps2_probe(struct parisc_device *dev)
 {
-        struct gscps2port *ps2port;
+       struct gscps2port *ps2port;
+       struct serio *serio;
        unsigned long hpa = dev->hpa;
        int ret;
 
@@ -355,34 +355,45 @@ static int __init gscps2_probe(struct parisc_device *dev)
                hpa += GSC_DINO_OFFSET;
 
        ps2port = kmalloc(sizeof(struct gscps2port), GFP_KERNEL);
-       if (!ps2port)
-               return -ENOMEM;
+       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+       if (!ps2port || !serio) {
+               ret = -ENOMEM;
+               goto fail_nomem;
+       }
 
        dev_set_drvdata(&dev->dev, ps2port);
 
        memset(ps2port, 0, sizeof(struct gscps2port));
+       memset(serio, 0, sizeof(struct serio));
+       ps2port->port = serio;
        ps2port->padev = dev;
        ps2port->addr = ioremap(hpa, GSC_STATUS + 4);
        spin_lock_init(&ps2port->lock);
 
        gscps2_reset(ps2port);
-       ps2port->id = readb(ps2port->addr+GSC_ID) & 0x0f;
-       snprintf(ps2port->name, sizeof(ps2port->name)-1, "%s %s",
-               gscps2_serio_port.name,
-               (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse" );
-
-       memcpy(&ps2port->port, &gscps2_serio_port, sizeof(gscps2_serio_port));
-       ps2port->port.driver = ps2port;
-       ps2port->port.name = ps2port->name;
-       ps2port->port.phys = dev->dev.bus_id;
+       ps2port->id = readb(ps2port->addr + GSC_ID) & 0x0f;
+
+       snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s",
+                (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
+       strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
+       serio->idbus            = BUS_GSC;
+       serio->idvendor         = PCI_VENDOR_ID_HP;
+       serio->idproduct        = 0x0001;
+       serio->idversion        = 0x0010;
+       serio->type             = SERIO_8042;
+       serio->write            = gscps2_write;
+       serio->open             = gscps2_open;
+       serio->close            = gscps2_close;
+       serio->port_data        = ps2port;
+       serio->dev.parent       = &dev->dev;
 
        list_add_tail(&ps2port->node, &ps2port_list);
 
        ret = -EBUSY;
-       if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->name, ps2port))
+       if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->port->name, ps2port))
                goto fail_miserably;
 
-       if ( (ps2port->id != GSC_ID_KEYBOARD) && (ps2port->id != GSC_ID_MOUSE) ) {
+       if (ps2port->id != GSC_ID_KEYBOARD && ps2port->id != GSC_ID_MOUSE) {
                printk(KERN_WARNING PFX "Unsupported PS/2 port at 0x%08lx (id=%d) ignored\n",
                                hpa, ps2port->id);
                ret = -ENODEV;
@@ -395,12 +406,12 @@ static int __init gscps2_probe(struct parisc_device *dev)
 #endif
 
        printk(KERN_INFO "serio: %s port at 0x%p irq %d @ %s\n",
-               ps2port->name,
+               ps2port->port->name,
                ps2port->addr,
                ps2port->padev->irq,
-               ps2port->port.phys);
+               ps2port->port->phys);
 
-       serio_register_port(&ps2port->port);
+       serio_register_port(ps2port->port);
 
        return 0;
 
@@ -411,7 +422,10 @@ fail_miserably:
        list_del(&ps2port->node);
        iounmap(ps2port->addr);
        release_mem_region(dev->hpa, GSC_STATUS + 4);
+
+fail_nomem:
        kfree(ps2port);
+       kfree(serio);
        return ret;
 }
 
@@ -424,7 +438,7 @@ static int __devexit gscps2_remove(struct parisc_device *dev)
 {
        struct gscps2port *ps2port = dev_get_drvdata(&dev->dev);
 
-       serio_unregister_port(&ps2port->port);
+       serio_unregister_port(ps2port->port);
        free_irq(dev->irq, ps2port);
        gscps2_flush(ps2port);
        list_del(&ps2port->node);
index e0b8f32..da2a198 100644 (file)
@@ -18,7 +18,7 @@ static int i8042_aux_irq = -1;
 #define I8042_AUX_PHYS_DESC "sparcps2/serio1"
 #define I8042_MUX_PHYS_DESC "sparcps2/serio%d"
 
-static unsigned long kbd_iobase;
+static void __iomem *kbd_iobase;
 
 #define I8042_COMMAND_REG      (kbd_iobase + 0x64UL)
 #define I8042_DATA_REG         (kbd_iobase + 0x60UL)
@@ -64,7 +64,7 @@ static int i8042_platform_init(void)
        if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
                /* Hardcoded values for MrCoffee.  */
                i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
-               kbd_iobase = (unsigned long) ioremap(0x71300060, 8);
+               kbd_iobase = ioremap(0x71300060, 8);
                if (!kbd_iobase)
                        return -1;
        } else {
@@ -85,7 +85,7 @@ static int i8042_platform_init(void)
                        if (!strcmp(child->prom_name, OBP_PS2KBD_NAME1) ||
                            !strcmp(child->prom_name, OBP_PS2KBD_NAME2)) {
                                i8042_kbd_irq = child->irqs[0];
-                               kbd_iobase = (unsigned long)
+                               kbd_iobase =
                                        ioremap(child->resource[0].start, 8);
                        }
                        if (!strcmp(child->prom_name, OBP_PS2MS_NAME1) ||
@@ -109,7 +109,7 @@ static int i8042_platform_init(void)
 static inline void i8042_platform_exit(void)
 {
 #ifdef CONFIG_PCI
-       iounmap((void *)kbd_iobase);
+       iounmap(kbd_iobase);
 #endif
 }
 
index f0f6374..cea2403 100644 (file)
 
 #define I8042_BUFFER_SIZE      32
 
+/*
+ * Number of AUX ports on controllers supporting active multiplexing
+ * specification
+ */
+
+#define I8042_NUM_MUX_PORTS    4
+
 /*
  * Debug.
  */
index c7db1de..78f4d9b 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/err.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -46,15 +47,18 @@ MODULE_LICENSE("GPL");
 #define PS2_CONTROL_RX_CLOCK_ENABLE  BIT(4) /* pause reception if set to 0 */
 #define PS2_CONTROL_RESET            BIT(5) /* reset */
 
-
 struct maceps2_data {
        struct mace_ps2port *port;
        int irq;
 };
 
+static struct maceps2_data port_data[2];
+static struct serio *maceps2_port[2];
+static struct platform_device *maceps2_device;
+
 static int maceps2_write(struct serio *dev, unsigned char val)
 {
-       struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port;
+       struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
        unsigned int timeout = MACE_PS2_TIMEOUT;
 
        do {
@@ -68,11 +72,10 @@ static int maceps2_write(struct serio *dev, unsigned char val)
        return -1;
 }
 
-static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
-                                    struct pt_regs *regs)
+static irqreturn_t maceps2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct serio *dev = dev_id;
-       struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port;
+       struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
        unsigned int byte;
 
        if (mace_read(port->status) & PS2_STATUS_RX_FULL) {
@@ -85,7 +88,7 @@ static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
 
 static int maceps2_open(struct serio *dev)
 {
-       struct maceps2_data *data = (struct maceps2_data *)dev->driver;
+       struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
 
        if (request_irq(data->irq, maceps2_interrupt, 0, "PS/2 port", dev)) {
                printk(KERN_ERR "Could not allocate PS/2 IRQ\n");
@@ -106,7 +109,7 @@ static int maceps2_open(struct serio *dev)
 
 static void maceps2_close(struct serio *dev)
 {
-       struct maceps2_data *data = (struct maceps2_data *)dev->driver;
+       struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
 
        mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET,
                   data->port->control);
@@ -114,46 +117,59 @@ static void maceps2_close(struct serio *dev)
        free_irq(data->irq, dev);
 }
 
-static struct maceps2_data port0_data, port1_data;
 
-static struct serio maceps2_port0 =
+static struct serio * __init maceps2_allocate_port(int idx)
 {
-       .type   = SERIO_8042,
-       .open   = maceps2_open,
-       .close  = maceps2_close,
-       .write  = maceps2_write,
-       .name   = "MACE PS/2 port0",
-       .phys   = "mace/serio0",
-       .driver = &port0_data,
-};
+       struct serio *serio;
+
+       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+       if (serio) {
+               memset(serio, 0, sizeof(struct serio));
+               serio->type             = SERIO_8042;
+               serio->write            = maceps2_write;
+               serio->open             = maceps2_open;
+               serio->close            = maceps2_close;
+               snprintf(serio->name, sizeof(serio->name), "MACE PS/2 port%d", idx);
+               snprintf(serio->phys, sizeof(serio->phys), "mace/serio%d", idx);
+               serio->port_data        = &port_data[idx];
+               serio->dev.parent       = &maceps2_device->dev;
+       }
+
+       return serio;
+}
 
-static struct serio maceps2_port1 =
-{
-       .type   = SERIO_8042,
-       .open   = maceps2_open,
-       .close  = maceps2_close,
-       .write  = maceps2_write,
-       .name   = "MACE PS/2 port1",
-       .phys   = "mace/serio1",
-       .driver = &port1_data,
-};
 
 static int __init maceps2_init(void)
 {
-       port0_data.port = &mace->perif.ps2.keyb;
-       port0_data.irq  = MACEISA_KEYB_IRQ;
-       port1_data.port = &mace->perif.ps2.mouse;
-       port1_data.irq  = MACEISA_MOUSE_IRQ;
-       serio_register_port(&maceps2_port0);
-       serio_register_port(&maceps2_port1);
+       maceps2_device = platform_device_register_simple("maceps2", -1, NULL, 0);
+       if (IS_ERR(maceps2_device))
+               return PTR_ERR(maceps2_device);
+
+       port_data[0].port = &mace->perif.ps2.keyb;
+       port_data[0].irq  = MACEISA_KEYB_IRQ;
+       port_data[1].port = &mace->perif.ps2.mouse;
+       port_data[1].irq  = MACEISA_MOUSE_IRQ;
+
+       maceps2_port[0] = maceps2_allocate_port(0);
+       maceps2_port[1] = maceps2_allocate_port(1);
+       if (!maceps2_port[0] || !maceps2_port[1]) {
+               kfree(maceps2_port[0]);
+               kfree(maceps2_port[1]);
+               platform_device_unregister(maceps2_device);
+               return -ENOMEM;
+       }
+
+       serio_register_port(maceps2_port[0]);
+       serio_register_port(maceps2_port[1]);
 
        return 0;
 }
 
 static void __exit maceps2_exit(void)
 {
-       serio_unregister_port(&maceps2_port0);
-       serio_unregister_port(&maceps2_port1);
+       serio_unregister_port(maceps2_port[0]);
+       serio_unregister_port(maceps2_port[1]);
+       platform_device_unregister(maceps2_device);
 }
 
 module_init(maceps2_init);
index 5f25b21..a859df6 100644 (file)
@@ -53,9 +53,7 @@ static int parkbd_writing;
 static unsigned long parkbd_start;
 
 static struct pardevice *parkbd_dev;
-
-static char parkbd_name[] = "PARKBD AT/XT keyboard adapter";
-static char parkbd_phys[32];
+static struct serio *parkbd_port;
 
 static int parkbd_readlines(void)
 {
@@ -86,13 +84,6 @@ static int parkbd_write(struct serio *port, unsigned char c)
        return 0;
 }
 
-static struct serio parkbd_port =
-{
-       .write  = parkbd_write,
-       .name   = parkbd_name,
-       .phys   = parkbd_phys,
-};
-
 static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 
@@ -125,7 +116,7 @@ static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++;
 
                if (parkbd_counter == parkbd_mode + 10)
-                       serio_interrupt(&parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
+                       serio_interrupt(parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
        }
 
        parkbd_last = jiffies;
@@ -163,16 +154,39 @@ static int parkbd_getport(void)
        return 0;
 }
 
+static struct serio * __init parkbd_allocate_serio(void)
+{
+       struct serio *serio;
+
+       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+       if (serio) {
+               memset(serio, 0, sizeof(struct serio));
+               serio->type = parkbd_mode;
+               serio->write = parkbd_write,
+               strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
+               snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
+       }
+
+       return serio;
+}
 
 int __init parkbd_init(void)
 {
-       if (parkbd_getport()) return -1;
-       parkbd_writelines(3);
-       parkbd_port.type = parkbd_mode;
+       int err;
+
+       err = parkbd_getport();
+       if (err)
+               return err;
 
-       sprintf(parkbd_phys, "%s/serio0", parkbd_dev->port->name);
+       parkbd_port = parkbd_allocate_serio();
+       if (!parkbd_port) {
+               parport_release(parkbd_dev);
+               return -ENOMEM;
+       }
+
+       parkbd_writelines(3);
 
-       serio_register_port(&parkbd_port);
+       serio_register_port(parkbd_port);
 
        printk(KERN_INFO "serio: PARKBD %s adapter on %s\n",
                         parkbd_mode ? "AT" : "XT", parkbd_dev->port->name);
@@ -183,7 +197,7 @@ int __init parkbd_init(void)
 void __exit parkbd_exit(void)
 {
        parport_release(parkbd_dev);
-       serio_unregister_port(&parkbd_port);
+       serio_unregister_port(parkbd_port);
        parport_unregister_device(parkbd_dev);
 }
 
index 2b4acac..489749e 100644 (file)
 #define PS2_STAT_TXEMPTY       (1<<7)
 
 struct pcips2_data {
-       struct serio    io;
+       struct serio    *io;
        unsigned int    base;
        struct pci_dev  *dev;
 };
 
 static int pcips2_write(struct serio *io, unsigned char val)
 {
-       struct pcips2_data *ps2if = io->driver;
+       struct pcips2_data *ps2if = io->port_data;
        unsigned int stat;
 
        do {
@@ -80,7 +80,7 @@ static irqreturn_t pcips2_interrupt(int irq, void *devid, struct pt_regs *regs)
                if (hweight8(scancode) & 1)
                        flag ^= SERIO_PARITY;
 
-               serio_interrupt(&ps2if->io, scancode, flag, regs);
+               serio_interrupt(ps2if->io, scancode, flag, regs);
        } while (1);
        return IRQ_RETVAL(handled);
 }
@@ -101,7 +101,7 @@ static void pcips2_flush_input(struct pcips2_data *ps2if)
 
 static int pcips2_open(struct serio *io)
 {
-       struct pcips2_data *ps2if = io->driver;
+       struct pcips2_data *ps2if = io->port_data;
        int ret, val = 0;
 
        outb(PS2_CTRL_ENABLE, ps2if->base);
@@ -119,7 +119,7 @@ static int pcips2_open(struct serio *io)
 
 static void pcips2_close(struct serio *io)
 {
-       struct pcips2_data *ps2if = io->driver;
+       struct pcips2_data *ps2if = io->port_data;
 
        outb(0, ps2if->base);
 
@@ -129,46 +129,51 @@ static void pcips2_close(struct serio *io)
 static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct pcips2_data *ps2if;
+       struct serio *serio;
        int ret;
 
        ret = pci_enable_device(dev);
        if (ret)
-               return ret;
+               goto out;
 
-       if (!request_region(pci_resource_start(dev, 0),
-                           pci_resource_len(dev, 0), "pcips2")) {
-               ret = -EBUSY;
+       ret = pci_request_regions(dev, "pcips2");
+       if (ret)
                goto disable;
-       }
 
        ps2if = kmalloc(sizeof(struct pcips2_data), GFP_KERNEL);
-       if (!ps2if) {
+       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+       if (!ps2if || !serio) {
                ret = -ENOMEM;
                goto release;
        }
 
        memset(ps2if, 0, sizeof(struct pcips2_data));
-
-       ps2if->io.type          = SERIO_8042;
-       ps2if->io.write         = pcips2_write;
-       ps2if->io.open          = pcips2_open;
-       ps2if->io.close         = pcips2_close;
-       ps2if->io.name          = pci_name(dev);
-       ps2if->io.phys          = dev->dev.bus_id;
-       ps2if->io.driver        = ps2if;
+       memset(serio, 0, sizeof(struct serio));
+
+       serio->type             = SERIO_8042;
+       serio->write            = pcips2_write;
+       serio->open             = pcips2_open;
+       serio->close            = pcips2_close;
+       strlcpy(serio->name, pci_name(dev), sizeof(serio->name));
+       strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
+       serio->port_data        = ps2if;
+       serio->dev.parent       = &dev->dev;
+       ps2if->io               = serio;
        ps2if->dev              = dev;
        ps2if->base             = pci_resource_start(dev, 0);
 
        pci_set_drvdata(dev, ps2if);
 
-       serio_register_port(&ps2if->io);
+       serio_register_port(ps2if->io);
        return 0;
 
  release:
-       release_region(pci_resource_start(dev, 0),
-                      pci_resource_len(dev, 0));
+       kfree(ps2if);
+       kfree(serio);
+       pci_release_regions(dev);
  disable:
        pci_disable_device(dev);
+ out:
        return ret;
 }
 
@@ -176,11 +181,10 @@ static void __devexit pcips2_remove(struct pci_dev *dev)
 {
        struct pcips2_data *ps2if = pci_get_drvdata(dev);
 
-       serio_unregister_port(&ps2if->io);
-       release_region(pci_resource_start(dev, 0),
-                      pci_resource_len(dev, 0));
+       serio_unregister_port(ps2if->io);
        pci_set_drvdata(dev, NULL);
        kfree(ps2if);
+       pci_release_regions(dev);
        pci_disable_device(dev);
 }
 
index 7f4a262..7d5ecce 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/serio.h>
 #include <linux/interrupt.h>
+#include <linux/err.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -47,43 +48,106 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver");
 MODULE_LICENSE("GPL");
 
-static struct serio q40kbd_port =
-{
-       .type   = SERIO_8042,
-       .name   = "Q40 kbd port",
-       .phys   = "Q40",
-       .write  = NULL,
-};
-
-static irqreturn_t q40kbd_interrupt(int irq, void *dev_id,
-                                   struct pt_regs *regs)
+spinlock_t q40kbd_lock = SPIN_LOCK_UNLOCKED;
+static struct serio *q40kbd_port;
+static struct platform_device *q40kbd_device;
+
+static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&q40kbd_lock, flags);
+
        if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))
-               serio_interrupt(&q40kbd_port, master_inb(KEYCODE_REG), 0, regs);
+               serio_interrupt(q40kbd_port, master_inb(KEYCODE_REG), 0, regs);
 
        master_outb(-1, KEYBOARD_UNLOCK_REG);
+
+       spin_unlock_irqrestore(&q40kbd_lock, flags);
+
        return IRQ_HANDLED;
 }
 
-static int __init q40kbd_init(void)
+/*
+ * q40kbd_flush() flushes all data that may be in the keyboard buffers
+ */
+
+static void q40kbd_flush(void)
+{
+       int maxread = 100;
+       unsigned long flags;
+
+       spin_lock_irqsave(&q40kbd_lock, flags);
+
+       while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
+               master_inb(KEYCODE_REG);
+
+       spin_unlock_irqrestore(&q40kbd_lock, flags);
+}
+
+/*
+ * q40kbd_open() is called when a port is open by the higher layer.
+ * It allocates the interrupt and enables in in the chip.
+ */
+
+static int q40kbd_open(struct serio *port)
 {
-       int maxread = 100;
+       q40kbd_flush();
 
+       if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) {
+               printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
+               return -1;
+       }
+
+       /* off we go */
+       master_outb(-1, KEYBOARD_UNLOCK_REG);
+       master_outb(1, KEY_IRQ_ENABLE_REG);
+
+       return 0;
+}
+
+static void q40kbd_close(struct serio *port)
+{
+       master_outb(0, KEY_IRQ_ENABLE_REG);
+       master_outb(-1, KEYBOARD_UNLOCK_REG);
+       free_irq(Q40_IRQ_KEYBOARD, NULL);
+
+       q40kbd_flush();
+}
+
+static struct serio * __init q40kbd_allocate_port(void)
+{
+       struct serio *serio;
+
+       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+       if (serio) {
+               memset(serio, 0, sizeof(struct serio));
+               serio->type             = SERIO_8042;
+               serio->open             = q40kbd_open;
+               serio->close            = q40kbd_close;
+               serio->dev.parent       = &q40kbd_device->dev;
+               strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name));
+               strlcpy(serio->phys, "Q40", sizeof(serio->phys));
+       }
+
+       return serio;
+}
+
+static int __init q40kbd_init(void)
+{
        if (!MACH_IS_Q40)
                return -EIO;
 
-       /* allocate the IRQ */
-       request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL);
-
-       /* flush any pending input */
-       while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
-               master_inb(KEYCODE_REG);
+       q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0);
+       if (IS_ERR(q40kbd_device))
+               return PTR_ERR(q40kbd_device);
 
-       /* off we go */
-       master_outb(-1,KEYBOARD_UNLOCK_REG);
-       master_outb(1,KEY_IRQ_ENABLE_REG);
+       if (!(q40kbd_port = q40kbd_allocate_port())) {
+               platform_device_unregister(q40kbd_device);
+               return -ENOMEM;
+       }
 
-       serio_register_port(&q40kbd_port);
+       serio_register_port(q40kbd_port);
        printk(KERN_INFO "serio: Q40 kbd registered\n");
 
        return 0;
@@ -91,11 +155,8 @@ static int __init q40kbd_init(void)
 
 static void __exit q40kbd_exit(void)
 {
-       master_outb(0,KEY_IRQ_ENABLE_REG);
-       master_outb(-1,KEYBOARD_UNLOCK_REG);
-
-       serio_unregister_port(&q40kbd_port);
-       free_irq(Q40_IRQ_KEYBOARD, NULL);
+       serio_unregister_port(q40kbd_port);
+       platform_device_unregister(q40kbd_device);
 }
 
 module_init(q40kbd_init);
index a2e4be7..b25d2e3 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/serio.h>
+#include <linux/err.h>
 
 #include <asm/irq.h>
 #include <asm/hardware.h>
@@ -44,6 +45,9 @@ MODULE_AUTHOR("Vojtech Pavlik, Russell King");
 MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
 MODULE_LICENSE("GPL");
 
+static struct serio *rpckbd_port;
+static struct platform_device *rpckbd_device;
+
 static int rpckbd_write(struct serio *port, unsigned char val)
 {
        while (!(iomd_readb(IOMD_KCTRL) & (1 << 7)))
@@ -101,25 +105,49 @@ static void rpckbd_close(struct serio *port)
        free_irq(IRQ_KEYBOARDTX, port);
 }
 
-static struct serio rpckbd_port =
+/*
+ * Allocate and initialize serio structure for subsequent registration
+ * with serio core.
+ */
+
+static struct serio * __init rpckbd_allocate_port(void)
 {
-       .type   = SERIO_8042,
-       .open   = rpckbd_open,
-       .close  = rpckbd_close,
-       .write  = rpckbd_write,
-       .name   = "RiscPC PS/2 kbd port",
-       .phys   = "rpckbd/serio0",
-};
+       struct serio *serio;
+
+       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+       if (serio) {
+               memset(serio, 0, sizeof(struct serio));
+               serio->type             = SERIO_8042;
+               serio->write            = rpckbd_write;
+               serio->open             = rpckbd_open;
+               serio->close            = rpckbd_close;
+               serio->dev.parent       = &rpckbd_device->dev;
+               strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name));
+               strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys));
+       }
+
+       return serio;
+}
 
 static int __init rpckbd_init(void)
 {
-       serio_register_port(&rpckbd_port);
+       rpckbd_device = platform_device_register_simple("rpckbd", -1, NULL, 0);
+       if (IS_ERR(rpckbd_device))
+               return PTR_ERR(rpckbd_device);
+
+       if (!(rpckbd_port = rpckbd_allocate_port())) {
+               platform_device_unregister(rpckbd_device);
+               return -ENOMEM;
+       }
+
+       serio_register_port(rpckbd_port);
        return 0;
 }
 
 static void __exit rpckbd_exit(void)
 {
-       serio_unregister_port(&rpckbd_port);
+       serio_unregister_port(rpckbd_port);
+       platform_device_unregister(rpckbd_device);
 }
 
 module_init(rpckbd_init);
index 6f00319..268ca1d 100644 (file)
@@ -1,11 +1,9 @@
-/*
- * $Id: serio.c,v 1.15 2002/01/22 21:12:03 vojtech Exp $
- *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- */
-
 /*
  *  The Serio abstraction module
+ *
+ *  Copyright (c) 1999-2004 Vojtech Pavlik
+ *  Copyright (c) 2004 Dmitry Torokhov
+ *  Copyright (c) 2003 Daniele Bellucci
  */
 
 /*
  * 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
- *
- * Changes:
- * 20 Jul. 2003    Daniele Bellucci <bellucda@tiscali.it>
- *                 Minor cleanups.
  */
 
 #include <linux/stddef.h>
@@ -50,100 +44,178 @@ MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(serio_interrupt);
 EXPORT_SYMBOL(serio_register_port);
 EXPORT_SYMBOL(serio_register_port_delayed);
-EXPORT_SYMBOL(__serio_register_port);
 EXPORT_SYMBOL(serio_unregister_port);
 EXPORT_SYMBOL(serio_unregister_port_delayed);
-EXPORT_SYMBOL(__serio_unregister_port);
-EXPORT_SYMBOL(serio_register_device);
-EXPORT_SYMBOL(serio_unregister_device);
+EXPORT_SYMBOL(serio_register_driver);
+EXPORT_SYMBOL(serio_unregister_driver);
 EXPORT_SYMBOL(serio_open);
 EXPORT_SYMBOL(serio_close);
 EXPORT_SYMBOL(serio_rescan);
 EXPORT_SYMBOL(serio_reconnect);
 
+static DECLARE_MUTEX(serio_sem);       /* protects serio_list and serio_diriver_list */
+static LIST_HEAD(serio_list);
+static LIST_HEAD(serio_driver_list);
+static unsigned int serio_no;
+
+struct bus_type serio_bus = {
+       .name = "serio",
+};
+
+static void serio_find_driver(struct serio *serio);
+static void serio_create_port(struct serio *serio);
+static void serio_destroy_port(struct serio *serio);
+static void serio_connect_port(struct serio *serio, struct serio_driver *drv);
+static void serio_reconnect_port(struct serio *serio);
+static void serio_disconnect_port(struct serio *serio);
+
+static int serio_bind_driver(struct serio *serio, struct serio_driver *drv)
+{
+       get_driver(&drv->driver);
+
+       drv->connect(serio, drv);
+       if (serio->drv) {
+               down_write(&serio_bus.subsys.rwsem);
+               serio->dev.driver = &drv->driver;
+               device_bind_driver(&serio->dev);
+               up_write(&serio_bus.subsys.rwsem);
+               return 1;
+       }
+
+       put_driver(&drv->driver);
+       return 0;
+}
+
+/* serio_find_driver() must be called with serio_sem down.  */
+static void serio_find_driver(struct serio *serio)
+{
+       struct serio_driver *drv;
+
+       list_for_each_entry(drv, &serio_driver_list, node)
+               if (!drv->manual_bind)
+                       if (serio_bind_driver(serio, drv))
+                               break;
+}
+
+/*
+ * Serio event processing.
+ */
+
 struct serio_event {
        int type;
        struct serio *serio;
        struct list_head node;
 };
 
-static DECLARE_MUTEX(serio_sem);
-static LIST_HEAD(serio_list);
-static LIST_HEAD(serio_dev_list);
+enum serio_event_type {
+       SERIO_RESCAN,
+       SERIO_RECONNECT,
+       SERIO_REGISTER_PORT,
+       SERIO_UNREGISTER_PORT,
+};
+
+static spinlock_t serio_event_lock = SPIN_LOCK_UNLOCKED;       /* protects serio_event_list */
 static LIST_HEAD(serio_event_list);
+static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
+static DECLARE_COMPLETION(serio_exited);
 static int serio_pid;
 
-static void serio_find_dev(struct serio *serio)
+static void serio_queue_event(struct serio *serio, int event_type)
 {
-       struct serio_dev *dev;
+       unsigned long flags;
+       struct serio_event *event;
 
-       list_for_each_entry(dev, &serio_dev_list, node) {
-               if (serio->dev)
-                       break;
-               if (dev->connect)
-                       dev->connect(serio, dev);
-       }
-}
+       spin_lock_irqsave(&serio_event_lock, flags);
 
-#define SERIO_RESCAN           1
-#define SERIO_RECONNECT                2
-#define SERIO_REGISTER_PORT    3
-#define SERIO_UNREGISTER_PORT  4
+       if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
+               event->type = event_type;
+               event->serio = serio;
 
-static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
-static DECLARE_COMPLETION(serio_exited);
+               list_add_tail(&event->node, &serio_event_list);
+               wake_up(&serio_wait);
+       }
+
+       spin_unlock_irqrestore(&serio_event_lock, flags);
+}
 
-static void serio_invalidate_pending_events(struct serio *serio)
+static struct serio_event *serio_get_event(void)
 {
        struct serio_event *event;
+       struct list_head *node;
+       unsigned long flags;
+
+       spin_lock_irqsave(&serio_event_lock, flags);
+
+       if (list_empty(&serio_event_list)) {
+               spin_unlock_irqrestore(&serio_event_lock, flags);
+               return NULL;
+       }
+
+       node = serio_event_list.next;
+       event = container_of(node, struct serio_event, node);
+       list_del_init(node);
+
+       spin_unlock_irqrestore(&serio_event_lock, flags);
 
-       list_for_each_entry(event, &serio_event_list, node)
-               if (event->serio == serio)
-                       event->serio = NULL;
+       return event;
 }
 
-void serio_handle_events(void)
+static void serio_handle_events(void)
 {
-       struct list_head *node, *next;
        struct serio_event *event;
 
-       list_for_each_safe(node, next, &serio_event_list) {
-               event = container_of(node, struct serio_event, node);
+       while ((event = serio_get_event())) {
 
                down(&serio_sem);
-               if (event->serio == NULL)
-                       goto event_done;
 
                switch (event->type) {
                        case SERIO_REGISTER_PORT :
-                               __serio_register_port(event->serio);
+                               serio_create_port(event->serio);
+                               serio_connect_port(event->serio, NULL);
                                break;
 
                        case SERIO_UNREGISTER_PORT :
-                               __serio_unregister_port(event->serio);
+                               serio_disconnect_port(event->serio);
+                               serio_destroy_port(event->serio);
                                break;
 
                        case SERIO_RECONNECT :
-                               if (event->serio->dev && event->serio->dev->reconnect)
-                                       if (event->serio->dev->reconnect(event->serio) == 0)
-                                               break;
-                               /* reconnect failed - fall through to rescan */
+                               serio_reconnect_port(event->serio);
+                               break;
 
                        case SERIO_RESCAN :
-                               if (event->serio->dev && event->serio->dev->disconnect)
-                                       event->serio->dev->disconnect(event->serio);
-                               serio_find_dev(event->serio);
+                               serio_disconnect_port(event->serio);
+                               serio_connect_port(event->serio, NULL);
                                break;
                        default:
                                break;
                }
-event_done:
+
                up(&serio_sem);
-               list_del_init(node);
                kfree(event);
        }
 }
 
+static void serio_remove_pending_events(struct serio *serio)
+{
+       struct list_head *node, *next;
+       struct serio_event *event;
+       unsigned long flags;
+
+       spin_lock_irqsave(&serio_event_lock, flags);
+
+       list_for_each_safe(node, next, &serio_event_list) {
+               event = container_of(node, struct serio_event, node);
+               if (event->serio == serio) {
+                       list_del_init(node);
+                       kfree(event);
+               }
+       }
+
+       spin_unlock_irqrestore(&serio_event_lock, flags);
+}
+
+
 static int serio_thread(void *nothing)
 {
        lock_kernel();
@@ -163,52 +235,239 @@ static int serio_thread(void *nothing)
        complete_and_exit(&serio_exited, 0);
 }
 
-static void serio_queue_event(struct serio *serio, int event_type)
+
+/*
+ * Serio port operations
+ */
+
+static ssize_t serio_show_description(struct device *dev, char *buf)
 {
-       struct serio_event *event;
+       struct serio *serio = to_serio_port(dev);
+       return sprintf(buf, "%s\n", serio->name);
+}
 
-       if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
-               event->type = event_type;
-               event->serio = serio;
+static ssize_t serio_show_driver(struct device *dev, char *buf)
+{
+       return sprintf(buf, "%s\n", dev->driver ? dev->driver->name : "(none)");
+}
 
-               list_add_tail(&event->node, &serio_event_list);
-               wake_up(&serio_wait);
+static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
+{
+       struct serio *serio = to_serio_port(dev);
+       struct device_driver *drv;
+       int retval;
+
+       retval = down_interruptible(&serio_sem);
+       if (retval)
+               return retval;
+
+       retval = count;
+       if (!strncmp(buf, "none", count)) {
+               serio_disconnect_port(serio);
+       } else if (!strncmp(buf, "reconnect", count)) {
+               serio_reconnect_port(serio);
+       } else if (!strncmp(buf, "rescan", count)) {
+               serio_disconnect_port(serio);
+               serio_connect_port(serio, NULL);
+       } else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
+               serio_disconnect_port(serio);
+               serio_connect_port(serio, to_serio_driver(drv));
+               put_driver(drv);
+       } else {
+               retval = -EINVAL;
        }
+
+       up(&serio_sem);
+
+       return retval;
 }
 
-void serio_rescan(struct serio *serio)
+static ssize_t serio_show_bind_mode(struct device *dev, char *buf)
 {
-       serio_queue_event(serio, SERIO_RESCAN);
+       struct serio *serio = to_serio_port(dev);
+       return sprintf(buf, "%s\n", serio->manual_bind ? "manual" : "auto");
 }
 
-void serio_reconnect(struct serio *serio)
+static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t count)
 {
-       serio_queue_event(serio, SERIO_RECONNECT);
+       struct serio *serio = to_serio_port(dev);
+       int retval;
+
+       retval = count;
+       if (!strncmp(buf, "manual", count)) {
+               serio->manual_bind = 1;
+       } else if (!strncmp(buf, "auto", count)) {
+               serio->manual_bind = 0;
+       } else {
+               retval = -EINVAL;
+       }
+
+       return retval;
 }
 
-irqreturn_t serio_interrupt(struct serio *serio,
-               unsigned char data, unsigned int flags, struct pt_regs *regs)
+static struct device_attribute serio_device_attrs[] = {
+       __ATTR(description, S_IRUGO, serio_show_description, NULL),
+       __ATTR(driver, S_IWUSR | S_IRUGO, serio_show_driver, serio_rebind_driver),
+       __ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
+       __ATTR_NULL
+};
+
+
+static void serio_release_port(struct device *dev)
 {
-       irqreturn_t ret = IRQ_NONE;
+       struct serio *serio = to_serio_port(dev);
 
-        if (serio->dev && serio->dev->interrupt) {
-                ret = serio->dev->interrupt(serio, data, flags, regs);
-       } else {
-               if (!flags) {
-                       if ((serio->type == SERIO_8042 ||
-                               serio->type == SERIO_8042_XL) && (data != 0xaa))
-                                       return ret;
-                       serio_rescan(serio);
-                       ret = IRQ_HANDLED;
+       kfree(serio);
+       module_put(THIS_MODULE);
+}
+
+static void serio_create_port(struct serio *serio)
+{
+       try_module_get(THIS_MODULE);
+
+       spin_lock_init(&serio->lock);
+       list_add_tail(&serio->node, &serio_list);
+       snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), "serio%d", serio_no++);
+       serio->dev.bus = &serio_bus;
+       serio->dev.release = serio_release_port;
+       if (serio->parent)
+               serio->dev.parent = &serio->parent->dev;
+       device_register(&serio->dev);
+}
+
+/*
+ * serio_destroy_port() completes deregistration process and removes
+ * port from the system
+ */
+static void serio_destroy_port(struct serio *serio)
+{
+       struct serio_driver *drv = serio->drv;
+       unsigned long flags;
+
+       serio_remove_pending_events(serio);
+       list_del_init(&serio->node);
+
+       if (drv) {
+               drv->disconnect(serio);
+               down_write(&serio_bus.subsys.rwsem);
+               device_release_driver(&serio->dev);
+               up_write(&serio_bus.subsys.rwsem);
+               put_driver(&drv->driver);
+       }
+
+       if (serio->parent) {
+               spin_lock_irqsave(&serio->parent->lock, flags);
+               serio->parent->child = NULL;
+               spin_unlock_irqrestore(&serio->parent->lock, flags);
+       }
+
+       device_unregister(&serio->dev);
+}
+
+/*
+ * serio_connect_port() tries to bind the port and possible all its
+ * children to appropriate drivers. If driver passed in the function will not
+ * try otehr drivers when binding parent port.
+ */
+static void serio_connect_port(struct serio *serio, struct serio_driver *drv)
+{
+       WARN_ON(serio->drv);
+       WARN_ON(serio->child);
+
+       if (drv)
+               serio_bind_driver(serio, drv);
+       else if (!serio->manual_bind)
+               serio_find_driver(serio);
+
+       /* Ok, now bind children, if any */
+       while (serio->child) {
+               serio = serio->child;
+
+               WARN_ON(serio->drv);
+               WARN_ON(serio->child);
+
+               serio_create_port(serio);
+
+               if (!serio->manual_bind) {
+                       /*
+                        * With children we just _prefer_ passed in driver,
+                        * but we will try other options in case preferred
+                        * is not the one
+                        */
+                       if (!drv || !serio_bind_driver(serio, drv))
+                               serio_find_driver(serio);
                }
        }
-       return ret;
+}
+
+/*
+ *
+ */
+static void serio_reconnect_port(struct serio *serio)
+{
+       do {
+               if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
+                       serio_disconnect_port(serio);
+                       serio_connect_port(serio, NULL);
+                       /* Ok, old children are now gone, we are done */
+                       break;
+               }
+               serio = serio->child;
+       } while (serio);
+}
+
+/*
+ * serio_disconnect_port() unbinds a port from its driver. As a side effect
+ * all child ports are unbound and destroyed.
+ */
+static void serio_disconnect_port(struct serio *serio)
+{
+       struct serio_driver *drv = serio->drv;
+       struct serio *s;
+
+       if (serio->child) {
+               /*
+                * Children ports should be disconnected and destroyed
+                * first, staring with the leaf one, since we don't want
+                * to do recursion
+                */
+               do {
+                       s = serio->child;
+               } while (s->child);
+
+               while (s != serio) {
+                       s = s->parent;
+                       serio_destroy_port(s->child);
+               }
+       }
+
+       /*
+        * Ok, no children left, now disconnect this port
+        */
+       if (drv) {
+               drv->disconnect(serio);
+               down_write(&serio_bus.subsys.rwsem);
+               device_release_driver(&serio->dev);
+               up_write(&serio_bus.subsys.rwsem);
+               put_driver(&drv->driver);
+       }
+}
+
+void serio_rescan(struct serio *serio)
+{
+       serio_queue_event(serio, SERIO_RESCAN);
+}
+
+void serio_reconnect(struct serio *serio)
+{
+       serio_queue_event(serio, SERIO_RECONNECT);
 }
 
 void serio_register_port(struct serio *serio)
 {
        down(&serio_sem);
-       __serio_register_port(serio);
+       serio_create_port(serio);
+       serio_connect_port(serio, NULL);
        up(&serio_sem);
 }
 
@@ -222,21 +481,11 @@ void serio_register_port_delayed(struct serio *serio)
        serio_queue_event(serio, SERIO_REGISTER_PORT);
 }
 
-/*
- * Should only be called directly if serio_sem has already been taken,
- * for example when unregistering a serio from other input device's
- * connect() function.
- */
-void __serio_register_port(struct serio *serio)
-{
-       list_add_tail(&serio->node, &serio_list);
-       serio_find_dev(serio);
-}
-
 void serio_unregister_port(struct serio *serio)
 {
        down(&serio_sem);
-       __serio_unregister_port(serio);
+       serio_disconnect_port(serio);
+       serio_destroy_port(serio);
        up(&serio_sem);
 }
 
@@ -250,82 +499,171 @@ void serio_unregister_port_delayed(struct serio *serio)
        serio_queue_event(serio, SERIO_UNREGISTER_PORT);
 }
 
+
 /*
- * Should only be called directly if serio_sem has already been taken,
- * for example when unregistering a serio from other input device's
- * disconnect() function.
+ * Serio driver operations
  */
-void __serio_unregister_port(struct serio *serio)
+
+static ssize_t serio_driver_show_description(struct device_driver *drv, char *buf)
 {
-       serio_invalidate_pending_events(serio);
-       list_del_init(&serio->node);
-       if (serio->dev && serio->dev->disconnect)
-               serio->dev->disconnect(serio);
+       struct serio_driver *driver = to_serio_driver(drv);
+       return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
+}
+
+static ssize_t serio_driver_show_bind_mode(struct device_driver *drv, char *buf)
+{
+       struct serio_driver *serio_drv = to_serio_driver(drv);
+       return sprintf(buf, "%s\n", serio_drv->manual_bind ? "manual" : "auto");
 }
 
-void serio_register_device(struct serio_dev *dev)
+static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char *buf, size_t count)
+{
+       struct serio_driver *serio_drv = to_serio_driver(drv);
+       int retval;
+
+       retval = count;
+       if (!strncmp(buf, "manual", count)) {
+               serio_drv->manual_bind = 1;
+       } else if (!strncmp(buf, "auto", count)) {
+               serio_drv->manual_bind = 0;
+       } else {
+               retval = -EINVAL;
+       }
+
+       return retval;
+}
+
+
+static struct driver_attribute serio_driver_attrs[] = {
+       __ATTR(description, S_IRUGO, serio_driver_show_description, NULL),
+       __ATTR(bind_mode, S_IWUSR | S_IRUGO,
+               serio_driver_show_bind_mode, serio_driver_set_bind_mode),
+       __ATTR_NULL
+};
+
+void serio_register_driver(struct serio_driver *drv)
 {
        struct serio *serio;
+
        down(&serio_sem);
-       list_add_tail(&dev->node, &serio_dev_list);
-       list_for_each_entry(serio, &serio_list, node)
-               if (!serio->dev && dev->connect)
-                       dev->connect(serio, dev);
+
+       list_add_tail(&drv->node, &serio_driver_list);
+
+       drv->driver.bus = &serio_bus;
+       driver_register(&drv->driver);
+
+       if (drv->manual_bind)
+               goto out;
+
+start_over:
+       list_for_each_entry(serio, &serio_list, node) {
+               if (!serio->drv) {
+                       serio_connect_port(serio, drv);
+                       /*
+                        * if new child appeared then the list is changed,
+                        * we need to start over
+                        */
+                       if (serio->child)
+                               goto start_over;
+               }
+       }
+
+out:
        up(&serio_sem);
 }
 
-void serio_unregister_device(struct serio_dev *dev)
+void serio_unregister_driver(struct serio_driver *drv)
 {
        struct serio *serio;
 
        down(&serio_sem);
-       list_del_init(&dev->node);
 
+       list_del_init(&drv->node);
+
+start_over:
        list_for_each_entry(serio, &serio_list, node) {
-               if (serio->dev == dev && dev->disconnect)
-                       dev->disconnect(serio);
-               serio_find_dev(serio);
+               if (serio->drv == drv) {
+                       serio_disconnect_port(serio);
+                       serio_connect_port(serio, NULL);
+                       /* we could've deleted some ports, restart */
+                       goto start_over;
+               }
        }
+
+       driver_unregister(&drv->driver);
+
        up(&serio_sem);
 }
 
-/* called from serio_dev->connect/disconnect methods under serio_sem */
-int serio_open(struct serio *serio, struct serio_dev *dev)
+/* called from serio_driver->connect/disconnect methods under serio_sem */
+int serio_open(struct serio *serio, struct serio_driver *drv)
 {
-       serio->dev = dev;
+       serio_pause_rx(serio);
+       serio->drv = drv;
+       serio_continue_rx(serio);
+
        if (serio->open && serio->open(serio)) {
-               serio->dev = NULL;
+               serio_pause_rx(serio);
+               serio->drv = NULL;
+               serio_continue_rx(serio);
                return -1;
        }
        return 0;
 }
 
-/* called from serio_dev->connect/disconnect methods under serio_sem */
+/* called from serio_driver->connect/disconnect methods under serio_sem */
 void serio_close(struct serio *serio)
 {
        if (serio->close)
                serio->close(serio);
-       serio->dev = NULL;
+
+       serio_pause_rx(serio);
+       serio->drv = NULL;
+       serio_continue_rx(serio);
 }
 
-static int __init serio_init(void)
+irqreturn_t serio_interrupt(struct serio *serio,
+               unsigned char data, unsigned int dfl, struct pt_regs *regs)
 {
-       int pid;
+       unsigned long flags;
+       irqreturn_t ret = IRQ_NONE;
+
+       spin_lock_irqsave(&serio->lock, flags);
+
+        if (likely(serio->drv)) {
+                ret = serio->drv->interrupt(serio, data, dfl, regs);
+       } else {
+               if (!dfl) {
+                       if ((serio->type != SERIO_8042 &&
+                            serio->type != SERIO_8042_XL) || (data == 0xaa)) {
+                               serio_rescan(serio);
+                               ret = IRQ_HANDLED;
+                       }
+               }
+       }
+
+       spin_unlock_irqrestore(&serio->lock, flags);
 
-       pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL);
+       return ret;
+}
 
-       if (!pid) {
+static int __init serio_init(void)
+{
+       if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) {
                printk(KERN_WARNING "serio: Failed to start kseriod\n");
                return -1;
        }
 
-       serio_pid = pid;
+       serio_bus.dev_attrs = serio_device_attrs;
+       serio_bus.drv_attrs = serio_driver_attrs;
+       bus_register(&serio_bus);
 
        return 0;
 }
 
 static void __exit serio_exit(void)
 {
+       bus_unregister(&serio_bus);
        kill_proc(serio_pid, SIGTERM, 1);
        wait_for_completion(&serio_exited);
 }
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
new file mode 100644 (file)
index 0000000..f424fdf
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ * Raw serio device providing access to a raw byte stream from underlying
+ * serio port. Closely emulates behavior of pre-2.6 /dev/psaux device
+ *
+ * Copyright (c) 2004 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/slab.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/device.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/wait.h>
+
+#define DRIVER_DESC    "Raw serio driver"
+
+MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+#define SERIO_RAW_QUEUE_LEN    64
+struct serio_raw {
+       unsigned char queue[SERIO_RAW_QUEUE_LEN];
+       unsigned int tail, head;
+
+       char name[16];
+       unsigned int refcnt;
+       struct serio *serio;
+       struct miscdevice dev;
+       wait_queue_head_t wait;
+       struct list_head list;
+       struct list_head node;
+};
+
+struct serio_raw_list {
+       struct fasync_struct *fasync;
+       struct serio_raw *serio_raw;
+       struct list_head node;
+};
+
+static DECLARE_MUTEX(serio_raw_sem);
+static LIST_HEAD(serio_raw_list);
+static unsigned int serio_raw_no;
+
+/*********************************************************************
+ *             Interface with userspace (file operations)            *
+ *********************************************************************/
+
+static int serio_raw_fasync(int fd, struct file *file, int on)
+{
+       struct serio_raw_list *list = file->private_data;
+       int retval;
+
+       retval = fasync_helper(fd, file, on, &list->fasync);
+       return retval < 0 ? retval : 0;
+}
+
+static struct serio_raw *serio_raw_locate(int minor)
+{
+       struct serio_raw *serio_raw;
+
+       list_for_each_entry(serio_raw, &serio_raw_list, node) {
+               if (serio_raw->dev.minor == minor)
+                       return serio_raw;
+       }
+
+       return NULL;
+}
+
+static int serio_raw_open(struct inode *inode, struct file *file)
+{
+       struct serio_raw *serio_raw;
+       struct serio_raw_list *list;
+       int retval = 0;
+
+       retval = down_interruptible(&serio_raw_sem);
+       if (retval)
+               return retval;
+
+       if (!(serio_raw = serio_raw_locate(iminor(inode)))) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       if (!serio_raw->serio) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       if (!(list = kmalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
+               retval = -ENOMEM;
+               goto out;
+       }
+
+       memset(list, 0, sizeof(struct serio_raw_list));
+       list->serio_raw = serio_raw;
+       file->private_data = list;
+
+       serio_raw->refcnt++;
+       list_add_tail(&list->node, &serio_raw->list);
+
+out:
+       up(&serio_raw_sem);
+       return retval;
+}
+
+static int serio_raw_cleanup(struct serio_raw *serio_raw)
+{
+       if (--serio_raw->refcnt == 0) {
+               misc_deregister(&serio_raw->dev);
+               list_del_init(&serio_raw->node);
+               kfree(serio_raw);
+
+               return 1;
+       }
+
+       return 0;
+}
+
+static int serio_raw_release(struct inode *inode, struct file *file)
+{
+       struct serio_raw_list *list = file->private_data;
+       struct serio_raw *serio_raw = list->serio_raw;
+
+       down(&serio_raw_sem);
+
+       serio_raw_fasync(-1, file, 0);
+       serio_raw_cleanup(serio_raw);
+
+       up(&serio_raw_sem);
+       return 0;
+}
+
+static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
+{
+       unsigned long flags;
+       int empty;
+
+       spin_lock_irqsave(&serio_raw->serio->lock, flags);
+
+       empty = serio_raw->head == serio_raw->tail;
+       if (!empty) {
+               *c = serio_raw->queue[serio_raw->tail];
+               serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
+       }
+
+       spin_unlock_irqrestore(&serio_raw->serio->lock, flags);
+
+       return !empty;
+}
+
+static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+{
+       struct serio_raw_list *list = file->private_data;
+       struct serio_raw *serio_raw = list->serio_raw;
+       char c;
+       ssize_t retval = 0;
+
+       if (!serio_raw->serio)
+               return -ENODEV;
+
+       if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
+               return -EAGAIN;
+
+       retval = wait_event_interruptible(list->serio_raw->wait,
+                                         serio_raw->head != serio_raw->tail || !serio_raw->serio);
+       if (retval)
+               return retval;
+
+       if (!serio_raw->serio)
+               return -ENODEV;
+
+       while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
+               if (put_user(c, buffer++))
+                       return -EFAULT;
+               retval++;
+       }
+
+       return retval;
+}
+
+static ssize_t serio_raw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+{
+       struct serio_raw_list *list = file->private_data;
+       ssize_t written = 0;
+       int retval;
+       unsigned char c;
+
+       retval = down_interruptible(&serio_raw_sem);
+       if (retval)
+               return retval;
+
+       if (!list->serio_raw->serio) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       if (count > 32)
+               count = 32;
+
+       while (count--) {
+               if (get_user(c, buffer++)) {
+                       retval = -EFAULT;
+                       goto out;
+               }
+               if (serio_write(list->serio_raw->serio, c)) {
+                       retval = -EIO;
+                       goto out;
+               }
+               written++;
+       };
+
+out:
+       up(&serio_raw_sem);
+       return written;
+}
+
+static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
+{
+       struct serio_raw_list *list = file->private_data;
+
+       poll_wait(file, &list->serio_raw->wait, wait);
+
+       if (list->serio_raw->head != list->serio_raw->tail)
+               return POLLIN | POLLRDNORM;
+
+       return 0;
+}
+
+struct file_operations serio_raw_fops = {
+       .owner =        THIS_MODULE,
+       .open =         serio_raw_open,
+       .release =      serio_raw_release,
+       .read =         serio_raw_read,
+       .write =        serio_raw_write,
+       .poll =         serio_raw_poll,
+       .fasync =       serio_raw_fasync,
+};
+
+
+/*********************************************************************
+ *                   Interface with serio port                      *
+ *********************************************************************/
+
+static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
+                                       unsigned int dfl, struct pt_regs *regs)
+{
+       struct serio_raw *serio_raw = serio->private;
+       struct serio_raw_list *list;
+       unsigned int head = serio_raw->head;
+
+       /* we are holding serio->lock here so we are prootected */
+       serio_raw->queue[head] = data;
+       head = (head + 1) % SERIO_RAW_QUEUE_LEN;
+       if (likely(head != serio_raw->tail)) {
+               serio_raw->head = head;
+               list_for_each_entry(list, &serio_raw->list, node)
+                       kill_fasync(&list->fasync, SIGIO, POLL_IN);
+               wake_up_interruptible(&serio_raw->wait);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void serio_raw_connect(struct serio *serio, struct serio_driver *drv)
+{
+       struct serio_raw *serio_raw;
+       int err;
+
+       if ((serio->type & SERIO_TYPE) != SERIO_8042)
+               return;
+
+       if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
+               printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
+               return;
+       }
+
+       down(&serio_raw_sem);
+
+       memset(serio_raw, 0, sizeof(struct serio_raw));
+       snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
+       serio_raw->refcnt = 1;
+       serio_raw->serio = serio;
+       INIT_LIST_HEAD(&serio_raw->list);
+       init_waitqueue_head(&serio_raw->wait);
+
+       serio->private = serio_raw;
+       if (serio_open(serio, drv))
+               goto out_free;
+
+       list_add_tail(&serio_raw->node, &serio_raw_list);
+
+       serio_raw->dev.minor = PSMOUSE_MINOR;
+       serio_raw->dev.name = serio_raw->name;
+       serio_raw->dev.fops = &serio_raw_fops;
+
+       err = misc_register(&serio_raw->dev);
+       if (err) {
+               serio_raw->dev.minor = MISC_DYNAMIC_MINOR;
+               err = misc_register(&serio_raw->dev);
+       }
+
+       if (err) {
+               printk(KERN_INFO "serio_raw: failed to register raw access device for %s\n",
+                       serio->phys);
+               goto out_close;
+       }
+
+       printk(KERN_INFO "serio_raw: raw access enabled on %s (%s, minor %d)\n",
+               serio->phys, serio_raw->name, serio_raw->dev.minor);
+       goto out;
+
+out_close:
+       serio_close(serio);
+       list_del_init(&serio_raw->node);
+out_free:
+       serio->private = NULL;
+       kfree(serio_raw);
+out:
+       up(&serio_raw_sem);
+}
+
+static int serio_raw_reconnect(struct serio *serio)
+{
+       struct serio_raw *serio_raw = serio->private;
+       struct serio_driver *drv = serio->drv;
+
+       if (!drv || !serio_raw) {
+               printk(KERN_DEBUG "serio_raw: reconnect request, but serio is disconnected, ignoring...\n");
+               return -1;
+       }
+
+       /*
+        * Nothing needs to be done here, we just need this method to
+        * keep the same device.
+        */
+       return 0;
+}
+
+static void serio_raw_disconnect(struct serio *serio)
+{
+       struct serio_raw *serio_raw;
+
+       down(&serio_raw_sem);
+
+       serio_raw = serio->private;
+
+       serio_close(serio);
+       serio->private = NULL;
+
+       serio_raw->serio = NULL;
+       if (!serio_raw_cleanup(serio_raw))
+               wake_up_interruptible(&serio_raw->wait);
+
+       up(&serio_raw_sem);
+}
+
+static struct serio_driver serio_raw_drv = {
+       .driver         = {
+               .name   = "serio_raw",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = serio_raw_interrupt,
+       .connect        = serio_raw_connect,
+       .reconnect      = serio_raw_reconnect,
+       .disconnect     = serio_raw_disconnect,
+       .manual_bind    = 1,
+};
+
+int __init serio_raw_init(void)
+{
+       serio_register_driver(&serio_raw_drv);
+       return 0;
+}
+
+void __exit serio_raw_exit(void)
+{
+       serio_unregister_driver(&serio_raw_drv);
+}
+
+module_init(serio_raw_init);
+module_exit(serio_raw_exit);
index 7759149..e5e38dd 100644 (file)
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC    "Gunze AHL-51S touchscreen driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Gunze AHL-51S touchscreen driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -111,7 +113,7 @@ static void gunze_disconnect(struct serio *serio)
  * and if yes, registers it as an input device.
  */
 
-static void gunze_connect(struct serio *serio, struct serio_dev *dev)
+static void gunze_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct gunze *gunze;
 
@@ -142,7 +144,7 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev)
        gunze->dev.id.product = 0x0051;
        gunze->dev.id.version = 0x0100;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                kfree(gunze);
                return;
        }
@@ -156,10 +158,14 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev gunze_dev = {
-       .interrupt =    gunze_interrupt,
-       .connect =      gunze_connect,
-       .disconnect =   gunze_disconnect,
+static struct serio_driver gunze_drv = {
+       .driver         = {
+               .name   = "gunze",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = gunze_interrupt,
+       .connect        = gunze_connect,
+       .disconnect     = gunze_disconnect,
 };
 
 /*
@@ -168,13 +174,13 @@ static struct serio_dev gunze_dev = {
 
 int __init gunze_init(void)
 {
-       serio_register_device(&gunze_dev);
+       serio_register_driver(&gunze_drv);
        return 0;
 }
 
 void __exit gunze_exit(void)
 {
-       serio_unregister_device(&gunze_dev);
+       serio_unregister_driver(&gunze_drv);
 }
 
 module_init(gunze_init);
index 7b4c16d..5d71967 100644 (file)
 #include <asm/arch/hardware.h>
 #include <asm/arch/irqs.h>
 
+#define DRIVER_DESC    "H3600 touchscreen driver"
+
 MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
-MODULE_DESCRIPTION("H3600 touchscreen driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -373,7 +375,7 @@ static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
  * new serio device. It looks whether it was registered as a H3600 touchscreen
  * and if yes, registers it as an input device.
  */
-static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
+static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct h3600_dev *ts;
 
@@ -441,7 +443,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
        ts->dev.id.product = 0x0666;  /* FIXME !!! We can ask the hardware */
        ts->dev.id.version = 0x0100;
 
-       if (serio_open(serio, dev)) {
+       if (serio_open(serio, drv)) {
                free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts);
                free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts);
                kfree(ts);
@@ -478,10 +480,14 @@ static void h3600ts_disconnect(struct serio *serio)
  * The serio device structure.
  */
 
-static struct serio_dev h3600ts_dev = {
-       .interrupt =    h3600ts_interrupt,
-       .connect =      h3600ts_connect,
-       .disconnect =   h3600ts_disconnect,
+static struct serio_driver h3600ts_drv = {
+       .driver         = {
+               .name   = "h3600ts",
+       },
+       .description    = DRIVER_DESC,
+       .interrupt      = h3600ts_interrupt,
+       .connect        = h3600ts_connect,
+       .disconnect     = h3600ts_disconnect,
 };
 
 /*
@@ -490,13 +496,13 @@ static struct serio_dev h3600ts_dev = {
 
 static int __init h3600ts_init(void)
 {
-       serio_register_device(&h3600ts_dev);
+       serio_register_driver(&h3600ts_drv);
        return 0;
 }
 
 static void __exit h3600ts_exit(void)
 {
-       serio_unregister_device(&h3600ts_dev);
+       serio_unregister_driver(&h3600ts_drv);
 }
 
 module_init(h3600ts_init);
index c87516a..0c7061d 100644 (file)
@@ -389,7 +389,7 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
                                             CAPIMSG_NCCI(skb->data),
                                             CAPIMSG_MSGID(skb->data));
                if (retval != CAPI_NOERROR) 
-                       goto out;
+                       return retval;
 
                dlen = CAPIMSG_DATALEN(skb->data);
 
@@ -399,16 +399,14 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
                b1_put_slice(port, skb->data + len, dlen);
                spin_unlock_irqrestore(&card->lock, flags);
        } else {
-               retval = CAPI_NOERROR;
-
                spin_lock_irqsave(&card->lock, flags);
                b1_put_byte(port, SEND_MESSAGE);
                b1_put_slice(port, skb->data, len);
                spin_unlock_irqrestore(&card->lock, flags);
        }
- out:
+
        dev_kfree_skb_any(skb);
-       return retval;
+       return CAPI_NOERROR;
 }
 
 /* ------------------------------------------------------------- */
index d2c69b7..55bed00 100644 (file)
@@ -839,8 +839,6 @@ u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
        }
        if (retval == CAPI_NOERROR) 
                b1dma_queue_tx(card, skb);
-       else
-               dev_kfree_skb_any(skb);
 
        return retval;
 }
index 9e1285c..72b57d4 100644 (file)
@@ -1029,8 +1029,6 @@ static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
                spin_lock_irqsave(&card->lock, flags);
                c4_dispatch_tx(card);
                spin_unlock_irqrestore(&card->lock, flags);
-       } else {
-               dev_kfree_skb_any(skb);
        }
        return retval;
 }
index 9d777eb..cb9d9ce 100644 (file)
@@ -472,7 +472,7 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
                                             CAPIMSG_NCCI(skb->data),
                                             CAPIMSG_MSGID(skb->data));
                if (retval != CAPI_NOERROR) 
-                       goto out;
+                       return retval;
 
                dlen = CAPIMSG_DATALEN(skb->data);
 
@@ -482,16 +482,15 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
                t1_put_slice(port, skb->data + len, dlen);
                spin_unlock_irqrestore(&card->lock, flags);
        } else {
-               retval = CAPI_NOERROR;
 
                spin_lock_irqsave(&card->lock, flags);
                b1_put_byte(port, SEND_MESSAGE);
                t1_put_slice(port, skb->data, len);
                spin_unlock_irqrestore(&card->lock, flags);
        }
- out:
+
        dev_kfree_skb_any(skb);
-       return retval;
+       return CAPI_NOERROR;
 }
 /* ------------------------------------------------------------- */
 
index 13f6ad2..bd256f2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: capifunc.h,v 1.11 2004/03/20 17:19:58 armin Exp $
+/* $Id: capifunc.h,v 1.11.4.1 2004/08/28 20:03:53 armin Exp $
  *
  * ISDN interface module for Eicon active cards DIVA.
  * CAPI Interface common functions
@@ -13,8 +13,6 @@
 #ifndef __CAPIFUNC_H__
 #define __CAPIFUNC_H__
 
-#define MAX_DESCRIPTORS  32
-
 #define DRRELMAJOR  2
 #define DRRELMINOR  0
 #define DRRELEXTRA  ""
index 0136eea..4db739d 100644 (file)
@@ -57,12 +57,18 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d);
 void diva_mnt_add_xdi_adapter    (const DESCRIPTOR* d);
 int diva_mnt_shutdown_xdi_adapters (void);
 
+#define DIVA_MAX_SELECTIVE_FILTER_LENGTH 127
+int diva_set_trace_filter (int filter_length, const char* filter);
+int diva_get_trace_filter (int max_length,    char*       filter);
+
 
 #define DITRACE_CMD_GET_DRIVER_INFO   1
 #define DITRACE_READ_DRIVER_DBG_MASK  2
 #define DITRACE_WRITE_DRIVER_DBG_MASK 3
 #define DITRACE_READ_TRACE_ENTRY      4
 #define DITRACE_READ_TRACE_ENTRYS     5
+#define DITRACE_WRITE_SELECTIVE_TRACE_FILTER 6
+#define DITRACE_READ_SELECTIVE_TRACE_FILTER  7
 
 /*
   Trace lavels for debug via management interface
index 516d2bd..11b3b9e 100644 (file)
@@ -232,7 +232,7 @@ typedef struct _DbgHandle_ *pDbgHandle ;
 typedef void ( * DbgEnd) (pDbgHandle) ;
 typedef void ( * DbgLog) (unsigned short, int, char *, va_list) ;
 typedef void ( * DbgOld) (unsigned short, char *, va_list) ;
-typedef void ( * DbgEv)  (unsigned short, unsigned int, va_list) ;
+typedef void ( * DbgEv)  (unsigned short, unsigned long, va_list) ;
 typedef void ( * DbgIrq) (unsigned short, int, char *, va_list) ;
 typedef struct _DbgHandle_
 { char    Registered ; /* driver successfull registered */
@@ -259,7 +259,7 @@ typedef struct _DbgHandle_
  void      *pReserved3 ;
 } _DbgHandle_ ;
 extern _DbgHandle_ myDriverDebugHandle ;
-typedef struct
+typedef struct _OldDbgHandle_
 { struct _OldDbgHandle_ *next ;
  void                *pIrp ;
  long    regTime[2] ;
@@ -310,7 +310,7 @@ typedef struct
             unsigned long   B_ChannelMask;
             unsigned long   LogBufferSize;
         } CardTrace;
-    } u1;     
+    }Data;     
 } _DbgExtendedInfo_;
 #ifndef DIVA_NO_DEBUGLIB
 /* -------------------------------------------------------------
index 0afd015..48b3f15 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: diva_didd.c,v 1.13 2003/08/27 10:11:21 schindler Exp $
+/* $Id: diva_didd.c,v 1.13.6.1 2004/08/28 20:03:53 armin Exp $
  *
  * DIDD Interface module for Eicon active cards.
  * 
@@ -23,7 +23,7 @@
 #include "divasync.h"
 #include "did_vers.h"
 
-static char *main_revision = "$Revision: 1.13 $";
+static char *main_revision = "$Revision: 1.13.6.1 $";
 
 static char *DRIVERNAME =
     "Eicon DIVA - DIDD table (http://www.melware.net)";
@@ -37,8 +37,6 @@ MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
 MODULE_SUPPORTED_DEVICE("Eicon diva drivers");
 MODULE_LICENSE("GPL");
 
-#define MAX_DESCRIPTORS  32
-
 #define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
 #define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
 
@@ -50,8 +48,8 @@ extern void DIVA_DIDD_Read(void *, int);
 static struct proc_dir_entry *proc_didd;
 struct proc_dir_entry *proc_net_eicon = NULL;
 
-EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Read);
-EXPORT_SYMBOL_NOVERS(proc_net_eicon);
+EXPORT_SYMBOL(DIVA_DIDD_Read);
+EXPORT_SYMBOL(proc_net_eicon);
 
 static char *getrev(const char *revision)
 {
index 81c4448..0a5be7f 100644 (file)
 #define IDI_SYNC_REQ_SET_POSTCALL       0x03
 #define IDI_SYNC_REQ_GET_XLOG           0x04
 #define IDI_SYNC_REQ_GET_FEATURES       0x05
-/* Added for DIVA USB support */
 #define IDI_SYNC_REQ_USB_REGISTER       0x06
 #define IDI_SYNC_REQ_USB_RELEASE        0x07
 #define IDI_SYNC_REQ_USB_ADD_DEVICE     0x08
 #define IDI_SYNC_REQ_USB_START_DEVICE   0x09
 #define IDI_SYNC_REQ_USB_STOP_DEVICE    0x0A
 #define IDI_SYNC_REQ_USB_REMOVE_DEVICE  0x0B
-/* Added for Diva Server Monitor */
 #define IDI_SYNC_REQ_GET_CARDTYPE       0x0C
 #define IDI_SYNC_REQ_GET_DBG_XLOG       0x0D
-#define IDI_SYNC_REQ_GET_LINE_IDX   0x0E
 #define DIVA_USB
 #define DIVA_USB_REQ                    0xAC
 #define DIVA_USB_TEST                   0xAB
 #define DIVA_USB_ADD_ADAPTER            0xAC
 #define DIVA_USB_REMOVE_ADAPTER         0xAD
-/******************************************************************************/
 #define IDI_SYNC_REQ_SERIAL_HOOK        0x80
 #define IDI_SYNC_REQ_XCHANGE_STATUS     0x81
 #define IDI_SYNC_REQ_USB_HOOK           0x82
 #define IDI_SYNC_REQ_PORTDRV_HOOK       0x83
-#define IDI_SYNC_REQ_SLI           (0x84)   /*  SLI request from 3signal modem drivers */
+#define IDI_SYNC_REQ_SLI                0x84   /*  SLI request from 3signal modem drivers */
 #define IDI_SYNC_REQ_RECONFIGURE        0x85
 #define IDI_SYNC_REQ_RESET              0x86
+#define IDI_SYNC_REQ_GET_85X_DEVICE_DATA     0x87
 #define IDI_SYNC_REQ_LOCK_85X                   0x88
+#define IDI_SYNC_REQ_DIVA_85X_USB_DATA_EXCHANGE 0x99
+#define IDI_SYNC_REQ_DIPORT_EXCHANGE_REQ   0x98
 #define IDI_SYNC_REQ_GET_85X_EXT_PORT_TYPE      0xA0
-#define IDI_SYNC_REQ_DIPORT_GET_85X_TX_CTRL_FN  0x98
 /******************************************************************************/
 #define IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES  0x92
 /*
@@ -87,6 +85,8 @@ typedef struct _diva_xdi_get_extended_xdi_features {
 #define DIVA_XDI_EXTENDED_FEATURE_CAPI_PRMS       0x08
 #define DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC    0x10
 #define DIVA_XDI_EXTENDED_FEATURE_RX_DMA          0x20
+#define DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA  0x40
+#define DIVA_XDI_EXTENDED_FEATURE_WIDE_ID         0x80
 #define DIVA_XDI_EXTENDED_FEATURES_MAX_SZ    1
 /******************************************************************************/
 #define IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR   0x93
@@ -115,6 +115,7 @@ typedef struct _diva_xdi_get_capi_parameters {
 typedef struct _diva_xdi_get_logical_adapter_number {
   dword logical_adapter_number;
   dword controller;
+  dword total_controllers;
 } diva_xdi_get_logical_adapter_number_s_t;
 /******************************************************************************/
 #define IDI_SYNC_REQ_UP1DM_OPERATION   0x96
@@ -134,6 +135,7 @@ typedef struct _diva_xdi_dma_descriptor_operation {
 #define IDI_SYNC_REQ_DIDD_ADD_ADAPTER               0x03
 #define IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER            0x04
 #define IDI_SYNC_REQ_DIDD_READ_ADAPTER_ARRAY        0x05
+#define IDI_SYNC_REQ_DIDD_GET_CFG_LIB_IFC           0x10
 typedef struct _diva_didd_adapter_notify {
  dword handle; /* Notification handle */
  void   * callback;
@@ -149,6 +151,9 @@ typedef struct _diva_didd_read_adapter_array {
  void   * buffer;
  dword length;
 } diva_didd_read_adapter_array_t;
+typedef struct _diva_didd_get_cfg_lib_ifc {
+ void* ifc;
+} diva_didd_get_cfg_lib_ifc_t;
 /******************************************************************************/
 #define IDI_SYNC_REQ_XDI_GET_STREAM    0x91
 #define DIVA_XDI_SYNCHRONOUS_SERVICE   0x01
@@ -466,6 +471,10 @@ typedef union
   ENTITY             e;
   diva_didd_read_adapter_array_t info;
  } didd_read_adapter_array;
+ struct {
+  ENTITY             e;
+  diva_didd_get_cfg_lib_ifc_t     info;
+ } didd_get_cfg_lib_ifc;
   struct {
     unsigned char Req;
     unsigned char Rc;
index 6f94ee9..15bb9c6 100644 (file)
@@ -77,6 +77,7 @@ static byte extended_xdi_features[DIVA_XDI_EXTENDED_FEATURES_MAX_SZ+1] = {
 #if defined(DIVA_IDI_RX_DMA)
   DIVA_XDI_EXTENDED_FEATURE_CMA          |
   DIVA_XDI_EXTENDED_FEATURE_RX_DMA       |
+  DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA |
 #endif
   DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC),
  0
@@ -226,8 +227,10 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
         if (pI->descriptor_number >= 0) {
           dword dma_magic;
           void* local_addr;
+#if 0
           DBG_TRC(("A(%d) dma_alloc(%d)",
                    IoAdapter->ANum, pI->descriptor_number))
+#endif
           diva_get_dma_map_entry (\
                                (struct _diva_dma_map_entry*)IoAdapter->dma_map,
                                pI->descriptor_number,
@@ -240,7 +243,9 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
         }
       } else if ((pI->operation == IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE) &&
                  (pI->descriptor_number >= 0)) {
+#if 0
         DBG_TRC(("A(%d) dma_free(%d)", IoAdapter->ANum, pI->descriptor_number))
+#endif
         diva_free_dma_map_entry((struct _diva_dma_map_entry*)IoAdapter->dma_map,
                                 pI->descriptor_number);
         pI->descriptor_number = -1;
@@ -257,6 +262,7 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
                                      &syncReq->xdi_logical_adapter_number.info;
       pI->logical_adapter_number = IoAdapter->ANum;
       pI->controller = IoAdapter->ControllerNumber;
+      pI->total_controllers = IoAdapter->Properties.Adapters;
     } return;
     case IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS: {
        diva_xdi_get_capi_parameters_t prms, *pI = &syncReq->xdi_capi_prms.info;
@@ -318,6 +324,16 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
    }
    syncReq->GetSerial.serial = 0 ;
    break ;
+  case IDI_SYNC_REQ_GET_CARDTYPE:
+   if ( IoAdapter )
+   {
+    syncReq->GetCardType.cardtype = IoAdapter->cardType ;
+    DBG_TRC(("xdi: Adapter %d / CardType %ld",
+             IoAdapter->ANum, IoAdapter->cardType))
+    return ;
+   }
+   syncReq->GetCardType.cardtype = 0 ;
+   break ;
   case IDI_SYNC_REQ_GET_XLOG:
    if ( IoAdapter )
    {
@@ -326,6 +342,14 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
    }
    e->Ind = 0 ;
    break ;
+  case IDI_SYNC_REQ_GET_DBG_XLOG:
+   if ( IoAdapter )
+   {
+    pcm_req (IoAdapter, e) ;
+    return ;
+   }
+   e->Ind = 0 ;
+   break ;
   case IDI_SYNC_REQ_GET_FEATURES:
    if ( IoAdapter )
    {
@@ -345,7 +369,9 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
   }
   if ( IoAdapter )
   {
+#if 0
    DBG_FTL(("xdi: unknown Req 0 / Rc %d !", e->Rc))
+#endif
    return ;
   }
  }
@@ -496,7 +522,7 @@ pcm_req (PISDN_ADAPTER IoAdapter, ENTITY *e)
   diva_os_enter_spin_lock (&IoAdapter->data_spin_lock,
                &OldIrql,
                "data_pcm_1");
-  IoAdapter->pcm_data = (unsigned long)pcm;
+  IoAdapter->pcm_data = (void *)pcm;
   IoAdapter->pcm_pending = 1;
   diva_os_schedule_soft_isr (&IoAdapter->req_soft_isr);
   diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
@@ -510,7 +536,7 @@ pcm_req (PISDN_ADAPTER IoAdapter, ENTITY *e)
                  &OldIrql,
                  "data_pcm_3");
     IoAdapter->pcm_pending = 0;
-    IoAdapter->pcm_data   = 0;
+    IoAdapter->pcm_data    = NULL ;
     diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
                  &OldIrql,
                  "data_pcm_3");
@@ -528,7 +554,7 @@ pcm_req (PISDN_ADAPTER IoAdapter, ENTITY *e)
                &OldIrql,
                "data_pcm_4");
   IoAdapter->pcm_pending = 0;
-  IoAdapter->pcm_data   = 0;
+  IoAdapter->pcm_data    = NULL ;
   diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
                &OldIrql,
                "data_pcm_4");
@@ -668,7 +694,7 @@ word io_inw(ADAPTER * a, void * adr)
 void io_in_buffer(ADAPTER * a, void * adr, void * buffer, word len)
 {
   byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
- byte* P = (byte*)buffer;
 byte* P = (byte*)buffer;
   if ((long)adr & 1) {
     outppw(Port+4, (word)(unsigned long)adr);
     *P = inpp(Port);
@@ -678,7 +704,7 @@ void io_in_buffer(ADAPTER * a, void * adr, void * buffer, word len)
     if (!len) {
        DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
        return;
-  }
+    }
   }
   outppw(Port+4, (word)(unsigned long)adr);
   inppw_buffer (Port, P, len+1);
@@ -710,7 +736,7 @@ void io_outw(ADAPTER * a, void * adr, word data)
 void io_out_buffer(ADAPTER * a, void * adr, void * buffer, word len)
 {
   byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
- byte* P = (byte*)buffer;
 byte* P = (byte*)buffer;
   if ((long)adr & 1) {
     outppw(Port+4, (word)(unsigned long)adr);
     outpp(Port, *P);
@@ -839,21 +865,21 @@ void CALLBACK(ADAPTER * a, ENTITY * e)
 /* --------------------------------------------------------------------------
   routines for aligned reading and writing on RISC
   -------------------------------------------------------------------------- */
-void outp_words_from_buffer (word* adr, byte* P, word len)
+void outp_words_from_buffer (word* adr, byte* P, dword len)
 {
-  word i = 0;
+  dword i = 0;
   word w;
-  while (i < (len & 0xfffe)) {
+  while (i < (len & 0xfffffffe)) {
     w = P[i++];
     w += (P[i++])<<8;
     outppw (adr, w);
   }
 }
-void inp_words_to_buffer (word* adr, byte* P, word len)
+void inp_words_to_buffer (word* adr, byte* P, dword len)
 {
-  word i = 0;
+  dword i = 0;
   word w;
-  while (i < (len & 0xfffe)) {
+  while (i < (len & 0xfffffffe)) {
     w = inppw (adr);
     P[i++] = (byte)(w);
     P[i++] = (byte)(w>>8);
index 3e54039..32ce17d 100644 (file)
@@ -39,6 +39,14 @@ typedef struct {
  DEVICE_NAME   DeviceName[4] ;
  PISDN_ADAPTER QuadroAdapter[4] ;
 } ADAPTER_LIST_ENTRY, *PADAPTER_LIST_ENTRY ;
+/* --------------------------------------------------------------------------
+  Special OS memory support structures
+  -------------------------------------------------------------------------- */
+#define MAX_MAPPED_ENTRIES 8
+typedef struct {
+ void  * Address;
+ dword    Length;
+} ADAPTER_MEMORY ;
 /* --------------------------------------------------------------------------
   Configuration of XDI clients carried by XDI
   -------------------------------------------------------------------------- */
@@ -52,6 +60,7 @@ typedef struct _diva_xdi_capi_cfg {
   -------------------------------------------------------------------------- */
 struct _ISDN_ADAPTER {
  void             (* DIRequest)(PISDN_ADAPTER, ENTITY *) ;
+ int                 State ; /* from NT4 1.srv, a good idea, but  a poor achievment */
  int                 Initialized ;
  int         RegisteredWithDidd ;
  int                 Unavailable ;  /* callback function possible? */
@@ -63,6 +72,7 @@ struct _ISDN_ADAPTER {
  /*
   remember mapped memory areas
  */
+ ADAPTER_MEMORY     MappedMemory[MAX_MAPPED_ENTRIES] ;
  CARD_PROPERTIES     Properties ;
  dword               cardType ;
  dword               protocol_id ;       /* configured protocol identifier */
@@ -87,15 +97,15 @@ struct _ISDN_ADAPTER {
  dword               downloadAddrTable[4] ; /* add. for MultiMaster */
  dword               MemoryBase ;
  dword               MemorySize ;
- byte       *Address ;
+ byte                *Address ;
  byte                *Config ;
  byte                *Control ;
- byte       *reset ;
- byte       *port ;
- byte       *ram ;
- byte       *cfg ;
- byte       *prom ;
- byte       *ctlReg ;
+ byte                *reset ;
+ byte                *port ;
+ byte                *ram ;
+ byte                *cfg ;
+ byte                *prom ;
+ byte                *ctlReg ;
  struct pc_maint  *pcm ;
  diva_os_dependent_devica_name_t os_name;
  byte                Name[32] ;
@@ -105,6 +115,7 @@ struct _ISDN_ADAPTER {
  char               *ProtocolSuffix ; /* internal protocolfile table */
  char                Archive[32] ;
  char                Protocol[32] ;
+ char                AddDownload[32] ; /* Dsp- or other additional download files */
  char                Oad1[ISDN_MAX_NUM_LEN] ;
  char                Osa1[ISDN_MAX_NUM_LEN] ;
  char                Oad2[ISDN_MAX_NUM_LEN] ;
@@ -153,8 +164,26 @@ struct _ISDN_ADAPTER {
  byte                ModemCarrierWaitTimeSec;
  byte                ModemCarrierLossWaitTimeTenthSec;
  byte                PiafsLinkTurnaroundInFrames;
+ byte                DiscAfterProgress;
+ byte                AniDniLimiter[3];
+ byte                TxAttenuation;  /* PRI/E1 only: attenuate TX signal */
  word                QsigFeatures;
  dword               GenerateRingtone ;
+ dword               SupplementaryServicesFeatures;
+ dword               R2Dialect;
+ dword               R2CasOptions;
+ dword               FaxV34Options;
+ dword               DisabledDspMask;
+ dword               AdapterTestMask;
+ dword               DspImageLength;
+ word                AlertToIn20mSecTicks;
+ word                ModemEyeSetup;
+ byte                R2CtryLength;
+ byte                CCBSRelTimer;
+ byte               *PcCfgBufferFile;/* flexible parameter via file */
+ byte               *PcCfgBuffer ; /* flexible parameter via multistring */
+ diva_os_dump_file_t dump_file; /* dump memory to file at lowest irq level */
+ diva_os_board_trace_t board_trace ; /* traces from the board */
  diva_os_spin_lock_t isr_spin_lock;
  diva_os_spin_lock_t data_spin_lock;
  diva_os_soft_isr_t req_soft_isr;
@@ -180,15 +209,21 @@ struct _ISDN_ADAPTER {
  void        (* stop)(PISDN_ADAPTER) ;
  void        (* rstFnc)(PISDN_ADAPTER) ;
  void        (* trapFnc)(PISDN_ADAPTER) ;
+ dword            (* DetectDsps)(PISDN_ADAPTER) ;
  void        (* os_trap_nfy_Fnc)(PISDN_ADAPTER, dword) ;
  diva_os_isr_callback_t diva_isr_handler;
- dword               sdram_bar;
+ dword               sdram_bar;  /* must be 32 bit */
  dword               fpga_features;
  volatile int        pcm_pending;
- volatile unsigned long      pcm_data;
+ volatile void *     pcm_data;
  diva_xdi_capi_cfg_t capi_cfg;
  dword               tasks;
- void*               dma_map;
+ void               *dma_map;
+ int             (*DivaAdapterTestProc)(PISDN_ADAPTER);
+ void               *AdapterTestMemoryStart;
+ dword               AdapterTestMemoryLength;
+ const byte* cfg_lib_memory_init;
+ dword       cfg_lib_memory_init_length;
 };
 /* ---------------------------------------------------------------------
   Entity table
@@ -219,8 +254,8 @@ struct s_load {
 /* ---------------------------------------------------------------------
   Functions for port io
    --------------------------------------------------------------------- */
-void outp_words_from_buffer (word* adr, byte* P, word len);
-void inp_words_to_buffer  (word* adr, byte* P, word len);
+void outp_words_from_buffer (word* adr, byte* P, dword len);
+void inp_words_to_buffer    (word* adr, byte* P, dword len);
 /* ---------------------------------------------------------------------
   platform specific conversions
    --------------------------------------------------------------------- */
@@ -240,6 +275,10 @@ void io_out(ADAPTER * a, void * adr, byte data);
 void io_outw(ADAPTER * a, void * adr, word data);
 void io_out_buffer(ADAPTER * a, void * adr, void * P, word length);
 void io_inc(ADAPTER * a, void * adr);
+void bri_in_buffer (PISDN_ADAPTER IoAdapter, dword Pos,
+                    void *Buf, dword Len);
+int bri_out_buffer (PISDN_ADAPTER IoAdapter, dword Pos,
+                    void *Buf, dword Len, int Verify);
 /* ---------------------------------------------------------------------
   ram access functions for memory mapped cards
    --------------------------------------------------------------------- */
index 184142c..4f06294 100644 (file)
@@ -49,6 +49,8 @@ typedef struct _diva_strace_path2action {
        void*                                                    variable; /* Variable that will receive value */
 } diva_strace_path2action_t;
 
+#define DIVA_MAX_MANAGEMENT_TRANSFER_SIZE 4096
+
 typedef struct _diva_strace_context {
        diva_strace_library_interface_t instance;
 
@@ -62,7 +64,7 @@ typedef struct _diva_strace_context {
   IDI_CALL request;
   BUFFERS  XData;
   BUFFERS  RData;
-       byte buffer[2048+512+1];
+       byte buffer[DIVA_MAX_MANAGEMENT_TRANSFER_SIZE + 1];
   int removal_state;
   int general_b_ch_event;
   int general_fax_event;
index a655506..1c69457 100644 (file)
@@ -143,6 +143,7 @@ struct dual
 #define N_DATA_ACK      12      /* data ack ind for D-bit procedure */
 #define N_EDATA_ACK     13      /* data ack ind for INTERRUPT       */
 #define N_XON           15      /* clear RNR state */
+#define N_COMBI_IND     N_XON   /* combined indication              */
 #define N_Q_BIT         0x10    /* Q-bit for req/ind                */
 #define N_M_BIT         0x20    /* M-bit for req/ind                */
 #define N_D_BIT         0x40    /* D-bit for req/ind                */
@@ -228,6 +229,10 @@ struct dual
 #define VSWITCH_IND 66        /* capifunctions for D-CH-switching   */
 #define MWI_POLL 67     /* Message Waiting Status Request fkt */
 #define CALL_PEND_NOTIFY 68 /* notify capi to set new listen        */
+#define DO_NOTHING 69       /* dont do somethin if you get this     */
+#define INT_CT_REJ 70       /* ECT rejected internal command        */
+#define CALL_HOLD_COMPLETE 71 /* In NT Mode indicate hold complete  */
+#define CALL_RETRIEVE_COMPLETE 72 /* In NT Mode indicate retrieve complete  */
 /*------------------------------------------------------------------*/
 /* management service primitives                                    */
 /*------------------------------------------------------------------*/
@@ -241,6 +246,7 @@ struct dual
 #define MAN_INFO_IND    2
 #define MAN_EVENT_IND   3
 #define MAN_TRACE_IND   4
+#define MAN_COMBI_IND   9
 #define MAN_ESC         0x80
 /*------------------------------------------------------------------*/
 /* return code coding                                               */
@@ -265,6 +271,7 @@ struct dual
 /*------------------------------------------------------------------*/
 #define SHIFT 0x90              /* codeset shift                    */
 #define MORE 0xa0               /* more data                        */
+#define SDNCMPL 0xa1            /* sending complete                 */
 #define CL 0xb0                 /* congestion level                 */
         /* codeset 0                                                */
 #define SMSG 0x00               /* segmented message                */
@@ -288,6 +295,8 @@ struct dual
 #define RDX 0x73                /* redirecting number extended      */
 #define RDN 0x74                /* redirecting number               */
 #define RIN 0x76                /* redirection number               */
+#define IUP 0x76                /* VN6 rerouter->PCS (codeset 6)    */
+#define IPU 0x77                /* VN6 PCS->rerouter (codeset 6)    */
 #define RI  0x79                /* restart indicator                */
 #define MIE 0x7a                /* management info element          */
 #define LLC 0x7c                /* low layer compatibility          */
@@ -296,6 +305,8 @@ struct dual
 #define ESC 0x7f                /* escape extension                 */
 #define DLC 0x20                /* data link layer configuration    */
 #define NLC 0x21                /* network layer configuration      */
+#define REDIRECT_IE     0x22    /* redirection request/indication data */
+#define REDIRECT_NET_IE 0x23    /* redirection network override data   */
         /* codeset 6                                                */
 #define SIN 0x01                /* service indicator                */
 #define CIF 0x02                /* charging information             */
@@ -306,6 +317,7 @@ struct dual
 /*------------------------------------------------------------------*/
 #define MSGTYPEIE        0x7a   /* Messagetype info element         */
 #define CRIE             0x7b   /* INFO info element                */
+#define CODESET6IE       0xec   /* Tunnel for Codeset 6 IEs         */
 #define VSWITCHIE        0xed   /* VSwitch info element             */
 #define SSEXTIE          0xee   /* Supplem. Service info element    */
 #define PROFILEIE        0xef   /* Profile info element             */
@@ -344,6 +356,13 @@ struct dual
 #define CCBS_REQUEST              0x32
 #define CCBS_DEACTIVATE           0x33
 #define CCBS_INTERROGATE          0x34
+#define CCBS_STATUS               0x35
+#define CCBS_ERASE                0x36
+#define CCBS_B_FREE               0x37
+#define CCNR_INFO_RETAIN          0x38
+#define CCBS_REMOTE_USER_FREE     0x39
+#define CCNR_REQUEST              0x3a
+#define CCNR_INTERROGATE          0x3b
 #define GET_SUPPORTED_SERVICES    0xff
 #define DIVERSION_PROCEDURE_CFU     0x70
 #define DIVERSION_PROCEDURE_CFB     0x71
@@ -362,6 +381,7 @@ struct dual
 #define SMASK_3PTY                 0x00000008
 #define SMASK_CALL_FORWARDING      0x00000010
 #define SMASK_CALL_DEFLECTION      0x00000020
+#define SMASK_MCID                 0x00000040
 #define SMASK_CCBS                 0x00000080
 #define SMASK_MWI                  0x00000100
 #define SMASK_CCNR                 0x00000200
@@ -406,6 +426,8 @@ struct dual
 #define RTPL2_IN       13       /* RTP layer-2 protocol, incomming  */
 #define RTPL2          14       /* RTP layer-2 protocol             */
 #define V120_V42BIS    15       /* V.120 asynchronous mode supporting V.42bis compression */
+#define LISTENER       27       /* Layer 2 to listen line */
+#define MTP2           28       /* MTP2 Layer 2 */
 #define PIAFS_CRC      29       /* PIAFS Layer 2 with CRC calculation at L2 */
 /* ------------------------------------------------------
    PIAFS DLC DEFINITIONS
@@ -506,6 +528,22 @@ Byte | 8 7 6 5 4 3 2 1
 |                     |      |                        data transfer.   |
 +---------------------+------+-----------------------------------------+
 */
+/* ------------------------------------------------------
+   LISTENER DLC DEFINITIONS
+   ------------------------------------------------------ */
+#define LISTENER_FEATURE_MASK_CUMMULATIVE            0x0001
+/* ------------------------------------------------------
+   LISTENER META-FRAME CODE/PRIMITIVE DEFINITIONS
+   ------------------------------------------------------ */
+#define META_CODE_LL_UDATA_RX 0x01
+#define META_CODE_LL_UDATA_TX 0x02
+#define META_CODE_LL_DATA_RX  0x03
+#define META_CODE_LL_DATA_TX  0x04
+#define META_CODE_LL_MDATA_RX 0x05
+#define META_CODE_LL_MDATA_TX 0x06
+#define META_CODE_EMPTY       0x10
+#define META_CODE_LOST_FRAMES 0x11
+#define META_FLAG_TRUNCATED   0x0001
 /*------------------------------------------------------------------*/
 /* CAPI-like profile to indicate features on LAW_REQ                */
 /*------------------------------------------------------------------*/
@@ -577,6 +615,14 @@ Byte | 8 7 6 5 4 3 2 1
 #define MANUFACTURER_FEATURE_DMACONNECT           0x04000000L
 #define MANUFACTURER_FEATURE_AUDIO_TAP            0x08000000L
 #define MANUFACTURER_FEATURE_FAX_NONSTANDARD      0x10000000L
+#define MANUFACTURER_FEATURE_SS7                  0x20000000L
+#define MANUFACTURER_FEATURE_MADAPTER             0x40000000L
+#define MANUFACTURER_FEATURE_MEASURE              0x80000000L
+#define MANUFACTURER_FEATURE2_LISTENING           0x00000001L
+#define MANUFACTURER_FEATURE2_SS_DIFFCONTPOSSIBLE 0x00000002L
+#define MANUFACTURER_FEATURE2_GENERIC_TONE        0x00000004L
+#define MANUFACTURER_FEATURE2_COLOR_FAX           0x00000008L
+#define MANUFACTURER_FEATURE2_SS_ECT_DIFFCONTPOSSIBLE 0x00000010L
 #define RTP_PRIM_PAYLOAD_PCMU_8000     0
 #define RTP_PRIM_PAYLOAD_1016_8000     1
 #define RTP_PRIM_PAYLOAD_G726_32_8000  2
@@ -624,6 +670,15 @@ Byte | 8 7 6 5 4 3 2 1
 #define VSINVOKEID    4
 #define VSCLMRKS       5
 #define VSTBCTIDENT    6
+#define VSETSILINKID   7
+#define VSSAMECONTROLLER 8
+/* Errorcodes for VSETSILINKID begin */
+#define VSETSILINKIDRRWC      1
+#define VSETSILINKIDREJECT    2
+#define VSETSILINKIDTIMEOUT   3
+#define VSETSILINKIDFAILCOUNT 4
+#define VSETSILINKIDERROR     5
+/* Errorcodes for VSETSILINKID end */
 /* -----------------------------------------------------------**
 ** The PROTOCOL_FEATURE_STRING in feature.h (included         **
 ** in prstart.sx and astart.sx) defines capabilities and      **
@@ -647,5 +702,37 @@ Byte | 8 7 6 5 4 3 2 1
 #define PROTCAP_FREE13    0x2000  /* not used                            */
 #define PROTCAP_FREE14    0x4000  /* not used                            */
 #define PROTCAP_EXTENSION 0x8000  /* used for future extentions          */
+/* -----------------------------------------------------------* */
+/* Onhook data transmission ETS30065901 */
+/* Message Type */
+/*#define RESERVED4                 0x4*/
+#define CALL_SETUP                0x80
+#define MESSAGE_WAITING_INDICATOR 0x82
+/*#define RESERVED84                0x84*/
+/*#define RESERVED85                0x85*/
+#define ADVICE_OF_CHARGE          0x86
+/*1111 0001
+to
+1111 1111
+F1H - Reserved for network operator use
+to
+FFH*/
+/* Parameter Types */
+#define DATE_AND_TIME                                           1
+#define CLI_PARAMETER_TYPE                                      2
+#define CALLED_DIRECTORY_NUMBER_PARAMETER_TYPE                  3
+#define REASON_FOR_ABSENCE_OF_CLI_PARAMETER_TYPE                4
+#define NAME_PARAMETER_TYPE                                     7
+#define REASON_FOR_ABSENCE_OF_CALLING_PARTY_NAME_PARAMETER_TYPE 8
+#define VISUAL_INDICATOR_PARAMETER_TYPE                         0xb
+#define COMPLEMENTARY_CLI_PARAMETER_TYPE                        0x10
+#define CALL_TYPE_PARAMETER_TYPE                                0x11
+#define FIRST_CALLED_LINE_DIRECTORY_NUMBER_PARAMETER_TYPE       0x12
+#define NETWORK_MESSAGE_SYSTEM_STATUS_PARAMETER_TYPE            0x13
+#define FORWARDED_CALL_TYPE_PARAMETER_TYPE                      0x15
+#define TYPE_OF_CALLING_USER_PARAMETER_TYPE                     0x16
+#define REDIRECTING_NUMBER_PARAMETER_TYPE                       0x1a
+#define EXTENSION_FOR_NETWORK_OPERATOR_USE_PARAMETER_TYPE       0xe0
+/* -----------------------------------------------------------* */
 #else
 #endif /* PC_H_INCLUDED  } */
index 31299fe..0457682 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: platform.h,v 1.37.4.1 2004/07/28 14:47:21 armin Exp $
+/* $Id: platform.h,v 1.37.4.2 2004/08/28 20:03:53 armin Exp $
  *
  * platform.h
  * 
@@ -269,20 +269,6 @@ static __inline__ void diva_os_leave_spin_lock (diva_os_spin_lock_t* a, \
                               diva_os_spin_lock_magic_t* old_irql, \
                               void* dbg) { spin_unlock_bh(a); }
 
-static __inline__ void diva_os_enter_spin_lock_hard (diva_os_spin_lock_t* a, \
-                                   diva_os_spin_lock_magic_t* old_irql, \
-                                   void* dbg) { \
-  unsigned long flags; \
-  spin_lock_irqsave (a, flags); \
-  *old_irql = (diva_os_spin_lock_magic_t)flags; \
-}
-static __inline__ void diva_os_leave_spin_lock_hard (diva_os_spin_lock_t* a, \
-                                   diva_os_spin_lock_magic_t* old_irql, \
-                                   void* dbg) { \
-  unsigned long flags = (unsigned long)*old_irql; \
-       spin_unlock_irqrestore (a, flags); \
-}
-
 #define diva_os_destroy_spin_lock(a,b) do { } while(0)
 
 /*
@@ -347,12 +333,18 @@ diva_os_atomic_decrement(diva_os_atomic_t* pv)
 
 #define DIVA_IDI_RX_DMA 1
 
+/*
+** endian macros
+*/
 #define READ_WORD(addr)   readw(addr)
 #define READ_DWORD(addr)  readl(addr)
 
 #define WRITE_WORD(addr,v)  writew(v,addr)
 #define WRITE_DWORD(addr,v) writel(v,addr)
 
+/*
+** 32/64 bit macors
+*/
 #ifdef BITS_PER_LONG
  #if BITS_PER_LONG > 32 
   #define PLATFORM_GT_32BIT
@@ -360,8 +352,23 @@ diva_os_atomic_decrement(diva_os_atomic_t* pv)
  #endif
 #endif
 
+/*
+** undef os definitions of macros we use
+*/
 #undef ID_MASK
 #undef N_DATA
 #undef ADDR
 
+/*
+** dump file
+*/
+#define diva_os_dump_file_t char
+#define diva_os_board_trace_t char
+#define diva_os_dump_file(__x__) do { } while(0)
+
+/*
+** size of internal arrays
+*/
+#define MAX_DESCRIPTORS 64
+
 #endif /* __PLATFORM_H__ */
index 235f28a..3a6acde 100644 (file)
@@ -752,70 +752,70 @@ setup_avm_pcipnp(struct IsdnCard *card)
                cs->hw.avm.cfg_reg = card->para[1];
                cs->irq = card->para[0];
                cs->subtyp = AVM_FRITZ_PNP;
-       } else {
+               goto ready;
+       }
 #ifdef __ISAPNP__
-               if (isapnp_present()) {
-                       struct pnp_dev *pnp_avm_d = NULL;
-                       if ((pnp_avm_c = pnp_find_card(
+       if (isapnp_present()) {
+               struct pnp_dev *pnp_avm_d = NULL;
+               if ((pnp_avm_c = pnp_find_card(
+                       ISAPNP_VENDOR('A', 'V', 'M'),
+                       ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
+                       if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
                                ISAPNP_VENDOR('A', 'V', 'M'),
-                               ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
-                               if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
-                                       ISAPNP_VENDOR('A', 'V', 'M'),
-                                       ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
-                                       int err;
-
-                                       pnp_disable_dev(pnp_avm_d);
-                                       err = pnp_activate_dev(pnp_avm_d);
-                                       if (err<0) {
-                                               printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
-                                                       __FUNCTION__, err);
-                                               return(0);
-                                       }
-                                       cs->hw.avm.cfg_reg =
-                                               pnp_port_start(pnp_avm_d, 0);
-                                       cs->irq = pnp_irq(pnp_avm_d, 0);
-                                       if (!cs->irq) {
-                                               printk(KERN_ERR "FritzPnP:No IRQ\n");
-                                               return(0);
-                                       }
-                                       if (!cs->hw.avm.cfg_reg) {
-                                               printk(KERN_ERR "FritzPnP:No IO address\n");
-                                               return(0);
-                                       }
-                                       cs->subtyp = AVM_FRITZ_PNP;
-                                       goto ready;
+                               ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
+                               int err;
+
+                               pnp_disable_dev(pnp_avm_d);
+                               err = pnp_activate_dev(pnp_avm_d);
+                               if (err<0) {
+                                       printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+                                               __FUNCTION__, err);
+                                       return(0);
+                               }
+                               cs->hw.avm.cfg_reg =
+                                       pnp_port_start(pnp_avm_d, 0);
+                               cs->irq = pnp_irq(pnp_avm_d, 0);
+                               if (!cs->irq) {
+                                       printk(KERN_ERR "FritzPnP:No IRQ\n");
+                                       return(0);
                                }
+                               if (!cs->hw.avm.cfg_reg) {
+                                       printk(KERN_ERR "FritzPnP:No IO address\n");
+                                       return(0);
+                               }
+                               cs->subtyp = AVM_FRITZ_PNP;
+                               goto ready;
                        }
-               } else {
-                       printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
                }
+       } else {
+               printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
+       }
 #endif
 #ifdef CONFIG_PCI
-               if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
-                       PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
-                       cs->irq = dev_avm->irq;
-                       if (!cs->irq) {
-                               printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
-                               return(0);
-                       }
-                       if (pci_enable_device(dev_avm))
-                               return(0);
-                       cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
-                       if (!cs->hw.avm.cfg_reg) {
-                               printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
-                               return(0);
-                       }
-                       cs->subtyp = AVM_FRITZ_PCI;
-               } else {
-                       printk(KERN_WARNING "FritzPCI: No PCI card found\n");
+       if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
+               PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
+               cs->irq = dev_avm->irq;
+               if (!cs->irq) {
+                       printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
+                       return(0);
+               }
+               if (pci_enable_device(dev_avm))
+                       return(0);
+               cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
+               if (!cs->hw.avm.cfg_reg) {
+                       printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
                        return(0);
                }
-               cs->irq_flags |= SA_SHIRQ;
+               cs->subtyp = AVM_FRITZ_PCI;
+       } else {
+               printk(KERN_WARNING "FritzPCI: No PCI card found\n");
+               return(0);
+       }
+       cs->irq_flags |= SA_SHIRQ;
 #else
-               printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
-               return (0);
+       printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
+       return (0);
 #endif /* CONFIG_PCI */
-       }
 ready:
        cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
        if (!request_region(cs->hw.avm.cfg_reg, 32,
index f6a21df..f410f62 100644 (file)
@@ -265,7 +265,7 @@ setup_bkm_a4t(struct IsdnCard *card)
        char tmp[64];
        u_int pci_memaddr = 0, found = 0;
        I20_REGISTER_FILE *pI20_Regs;
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 #endif
 
        strcpy(tmp, bkm_a4t_revision);
@@ -275,7 +275,7 @@ setup_bkm_a4t(struct IsdnCard *card)
        } else
                return (0);
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
        while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
                PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
                u16 sub_sys;
index 0c32d37..94bb83c 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/pci.h>
 #include "bkm_ax.h"
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
 #define        ATTEMPT_PCI_REMAPPING   /* Required for PLX rev 1 */
 
@@ -285,7 +285,7 @@ static u_char pci_irq __initdata = 0;
 int __init
 setup_sct_quadro(struct IsdnCard *card)
 {
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
        u_char pci_rev_id;
index b336781..3b526d7 100644 (file)
@@ -1022,7 +1022,7 @@ setup_elsa(struct IsdnCard *card)
                       cs->hw.elsa.base,
                       cs->irq);
        } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
                cs->subtyp = 0;
                if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
                        PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
index a7acf9b..1cc4d11 100644 (file)
@@ -299,7 +299,7 @@ setup_enternow_pci(struct IsdnCard *card)
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
index 0d59317..24a05a4 100644 (file)
@@ -634,7 +634,7 @@ setup_gazel(struct IsdnCard *card)
                        return (0);
        } else {
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
                if (setup_gazelpci(cs))
                        return (0);
 #else
index 20042fd..3946536 100644 (file)
@@ -65,7 +65,7 @@ static const PCI_ENTRY id_list[] =
 };
 
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
 /******************************************/
 /* free hardware resources used by driver */
@@ -1655,7 +1655,7 @@ setup_hfcpci(struct IsdnCard *card)
 #endif
        strcpy(tmp, hfcpci_revision);
        printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
        cs->hw.hfcpci.int_s1 = 0;
        cs->dc.hfcpci.ph_state = 0;
        cs->hw.hfcpci.fifo = 255;
index 88cce43..cf77d83 100644 (file)
@@ -309,7 +309,7 @@ setup_niccy(struct IsdnCard *card)
                        return (0);
                }
        } else {
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
                u_int pci_ioaddr;
                cs->subtyp = 0;
                if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
index 8b5822c..fd66469 100644 (file)
@@ -167,7 +167,7 @@ setup_netjet_s(struct IsdnCard *card)
                return(0);
        test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
        for ( ;; )
        {
index efb5d8f..3d6441e 100644 (file)
@@ -137,7 +137,7 @@ setup_netjet_u(struct IsdnCard *card)
        int bytecnt;
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 #endif
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
@@ -148,7 +148,7 @@ setup_netjet_u(struct IsdnCard *card)
                return(0);
        test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
        for ( ;; )
        {
index 863bfa5..3393370 100644 (file)
@@ -618,7 +618,7 @@ setup_sedlbauer(struct IsdnCard *card)
                }
 #endif
 /* Probe for Sedlbauer speed pci */
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
                if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
                                PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
                        if (pci_enable_device(dev_sedl))
index 5e30555..7713c46 100644 (file)
@@ -300,7 +300,7 @@ setup_telespci(struct IsdnCard *card)
        printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
        if (cs->typ != ISDN_CTYPE_TELESPCI)
                return (0);
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
        if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
                if (pci_enable_device(dev_tel))
                        return(0);
index cfe8760..36cfc4a 100644 (file)
@@ -1012,7 +1012,7 @@ setup_w6692(struct IsdnCard *card)
        printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp));
        if (cs->typ != ISDN_CTYPE_W6692)
                return (0);
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
        while (id_list[id_idx].vendor_id) {
                dev_w6692 = pci_find_device(id_list[id_idx].vendor_id,
                                            id_list[id_idx].device_id,
index 91392c4..b418d37 100644 (file)
@@ -23,7 +23,7 @@
 
 /* Local functions prototypes */
 static int __devinit tpam_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit tpam_unregister_card(tpam_card *);
+static void __devexit tpam_unregister_card(struct pci_dev *, tpam_card *);
 static void __devexit tpam_remove(struct pci_dev *);
 static int __init tpam_init(void);
 static void __exit tpam_exit(void);
@@ -86,13 +86,20 @@ u32 tpam_findchannel(tpam_card *card, u32 ncoid) {
  */
 static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) {
        tpam_card *card, *c;
-       int i;
+       int i, err;
+
+       if (pci_enable_device(dev)) {
+               printk(KERN_ERR "TurboPAM: can't enable PCI device at %s\n",
+                       pci_name(dev));
+               return -ENODEV;
+       }
 
        /* allocate memory for the board structure */
        if (!(card = (tpam_card *)kmalloc(sizeof(tpam_card), GFP_KERNEL))) {
                printk(KERN_ERR "TurboPAM: tpam_register_card: "
                       "kmalloc failed!\n");
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_out_disable_dev;
        }
 
        memset((char *)card, 0, sizeof(tpam_card));
@@ -106,8 +113,8 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
                        card->interface.id, card)) {
                printk(KERN_ERR "TurboPAM: tpam_register_card: "
                       "could not request irq %d\n", card->irq);
-               kfree(card);
-               return -EIO;
+               err = -EIO;
+               goto err_out_free_card;
        }
 
        /* remap board memory */
@@ -115,9 +122,8 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
                                                   0x800000))) {
                printk(KERN_ERR "TurboPAM: tpam_register_card: "
                       "unable to remap bar0\n");
-               free_irq(card->irq, card);
-               kfree(card);
-               return -EIO;
+               err = -EIO;
+               goto err_out_free_irq;
        }
 
        /* reset the board */
@@ -150,10 +156,8 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
        if (!register_isdn(&card->interface)) {
                printk(KERN_ERR "TurboPAM: tpam_register_card: "
                       "unable to register %s\n", card->interface.id);
-               free_irq(card->irq, card);
-               iounmap((void *)card->bar0);
-               kfree(card);
-               return -EIO;
+               err = -EIO;
+               goto err_out_iounmap;
        }
        card->id = card->interface.channels;
 
@@ -195,6 +199,19 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
        pci_set_drvdata(dev, card);
 
        return 0;
+
+err_out_iounmap:
+       iounmap((void *)card->bar0);
+
+err_out_free_irq:
+       free_irq(card->irq, card);
+
+err_out_free_card:
+       kfree(card);
+
+err_out_disable_dev:
+       pci_disable_device(dev);
+       return err;
 }
 
 /*
@@ -202,7 +219,7 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
  *
  *     card: the board.
  */
-static void __devexit tpam_unregister_card(tpam_card *card) {
+static void __devexit tpam_unregister_card(struct pci_dev *pcidev, tpam_card *card) {
        isdn_ctrl cmd;
 
        /* prevent the ISDN link layer that the driver will be unloaded */
@@ -215,6 +232,8 @@ static void __devexit tpam_unregister_card(tpam_card *card) {
 
        /* release mapped memory */
        iounmap((void *)card->bar0);
+
+       pci_disable_device(pcidev);
 }
 
 /*
@@ -235,7 +254,7 @@ static void __devexit tpam_remove(struct pci_dev *pcidev) {
        }
        
        /* unregister each board */
-       tpam_unregister_card(card);
+       tpam_unregister_card(pcidev, card);
        
        /* and free the board structure itself */
        kfree(card);
index c0ab858..d3b8f81 100644 (file)
@@ -74,15 +74,135 @@ static struct notifier_block adbhid_adb_notifier = {
 #define ADB_KEY_POWER_OLD      0x7e
 #define ADB_KEY_POWER          0x7f
 
-unsigned char adb_to_linux_keycodes[128] = {
-        30, 31, 32, 33, 35, 34, 44, 45, 46, 47, 86, 48, 16, 17, 18, 19,
-        21, 20,  2,  3,  4,  5,  7,  6, 13, 10,  8, 12,  9, 11, 27, 24,
-        22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43, 51, 53, 49, 50, 52,
-        15, 57, 41, 14, 96,  1, 29,125, 42, 58, 56,105,106,108,103,  0,
-         0, 83,  0, 55,  0, 78,  0, 69,  0,  0,  0, 98, 96,  0, 74,  0,
-         0,117, 82, 79, 80, 81, 75, 76, 77, 71,  0, 72, 73,124, 89,121,
-        63, 64, 65, 61, 66, 67,123, 87,122, 99,  0, 70,  0, 68,101, 88,
-         0,119,110,102,104,111, 62,107, 60,109, 59, 54,100, 97,126,116
+u8 adb_to_linux_keycodes[128] = {
+       /* 0x00 */ KEY_A,               /*  30 */
+       /* 0x01 */ KEY_S,               /*  31 */
+       /* 0x02 */ KEY_D,               /*  32 */
+       /* 0x03 */ KEY_F,               /*  33 */
+       /* 0x04 */ KEY_H,               /*  35 */
+       /* 0x05 */ KEY_G,               /*  34 */
+       /* 0x06 */ KEY_Z,               /*  44 */
+       /* 0x07 */ KEY_X,               /*  45 */
+       /* 0x08 */ KEY_C,               /*  46 */
+       /* 0x09 */ KEY_V,               /*  47 */
+       /* 0x0a */ KEY_102ND,           /*  86 */
+       /* 0x0b */ KEY_B,               /*  48 */
+       /* 0x0c */ KEY_Q,               /*  16 */
+       /* 0x0d */ KEY_W,               /*  17 */
+       /* 0x0e */ KEY_E,               /*  18 */
+       /* 0x0f */ KEY_R,               /*  19 */
+       /* 0x10 */ KEY_Y,               /*  21 */
+       /* 0x11 */ KEY_T,               /*  20 */
+       /* 0x12 */ KEY_1,               /*   2 */
+       /* 0x13 */ KEY_2,               /*   3 */
+       /* 0x14 */ KEY_3,               /*   4 */
+       /* 0x15 */ KEY_4,               /*   5 */
+       /* 0x16 */ KEY_6,               /*   7 */
+       /* 0x17 */ KEY_5,               /*   6 */
+       /* 0x18 */ KEY_EQUAL,           /*  13 */
+       /* 0x19 */ KEY_9,               /*  10 */
+       /* 0x1a */ KEY_7,               /*   8 */
+       /* 0x1b */ KEY_MINUS,           /*  12 */
+       /* 0x1c */ KEY_8,               /*   9 */
+       /* 0x1d */ KEY_0,               /*  11 */
+       /* 0x1e */ KEY_RIGHTBRACE,      /*  27 */
+       /* 0x1f */ KEY_O,               /*  24 */
+       /* 0x20 */ KEY_U,               /*  22 */
+       /* 0x21 */ KEY_LEFTBRACE,       /*  26 */
+       /* 0x22 */ KEY_I,               /*  23 */
+       /* 0x23 */ KEY_P,               /*  25 */
+       /* 0x24 */ KEY_ENTER,           /*  28 */
+       /* 0x25 */ KEY_L,               /*  38 */
+       /* 0x26 */ KEY_J,               /*  36 */
+       /* 0x27 */ KEY_APOSTROPHE,      /*  40 */
+       /* 0x28 */ KEY_K,               /*  37 */
+       /* 0x29 */ KEY_SEMICOLON,       /*  39 */
+       /* 0x2a */ KEY_BACKSLASH,       /*  43 */
+       /* 0x2b */ KEY_COMMA,           /*  51 */
+       /* 0x2c */ KEY_SLASH,           /*  53 */
+       /* 0x2d */ KEY_N,               /*  49 */
+       /* 0x2e */ KEY_M,               /*  50 */
+       /* 0x2f */ KEY_DOT,             /*  52 */
+       /* 0x30 */ KEY_TAB,             /*  15 */
+       /* 0x31 */ KEY_SPACE,           /*  57 */
+       /* 0x32 */ KEY_GRAVE,           /*  41 */
+       /* 0x33 */ KEY_BACKSPACE,       /*  14 */
+       /* 0x34 */ KEY_KPENTER,         /*  96 */
+       /* 0x35 */ KEY_ESC,             /*   1 */
+       /* 0x36 */ KEY_LEFTCTRL,        /*  29 */
+       /* 0x37 */ KEY_LEFTMETA,        /* 125 */
+       /* 0x38 */ KEY_LEFTSHIFT,       /*  42 */
+       /* 0x39 */ KEY_CAPSLOCK,        /*  58 */
+       /* 0x3a */ KEY_LEFTALT,         /*  56 */
+       /* 0x3b */ KEY_LEFT,            /* 105 */
+       /* 0x3c */ KEY_RIGHT,           /* 106 */
+       /* 0x3d */ KEY_DOWN,            /* 108 */
+       /* 0x3e */ KEY_UP,              /* 103 */
+       /* 0x3f */ 0,
+       /* 0x40 */ 0,
+       /* 0x41 */ KEY_KPDOT,           /*  83 */
+       /* 0x42 */ 0,
+       /* 0x43 */ KEY_KPASTERISK,      /*  55 */
+       /* 0x44 */ 0,
+       /* 0x45 */ KEY_KPPLUS,          /*  78 */
+       /* 0x46 */ 0,
+       /* 0x47 */ KEY_NUMLOCK,         /*  69 */
+       /* 0x48 */ 0,
+       /* 0x49 */ 0,
+       /* 0x4a */ 0,
+       /* 0x4b */ KEY_KPSLASH,         /*  98 */
+       /* 0x4c */ KEY_KPENTER,         /*  96 */
+       /* 0x4d */ 0,
+       /* 0x4e */ KEY_KPMINUS,         /*  74 */
+       /* 0x4f */ 0,
+       /* 0x50 */ 0,
+       /* 0x51 */ KEY_KPEQUAL,         /* 117 */
+       /* 0x52 */ KEY_KP0,             /*  82 */
+       /* 0x53 */ KEY_KP1,             /*  79 */
+       /* 0x54 */ KEY_KP2,             /*  80 */
+       /* 0x55 */ KEY_KP3,             /*  81 */
+       /* 0x56 */ KEY_KP4,             /*  75 */
+       /* 0x57 */ KEY_KP5,             /*  76 */
+       /* 0x58 */ KEY_KP6,             /*  77 */
+       /* 0x59 */ KEY_KP7,             /*  71 */
+       /* 0x5a */ 0,
+       /* 0x5b */ KEY_KP8,             /*  72 */
+       /* 0x5c */ KEY_KP9,             /*  73 */
+       /* 0x5d */ KEY_YEN,             /* 124 */
+       /* 0x5e */ KEY_RO,              /*  89 */
+       /* 0x5f */ KEY_KPCOMMA,         /* 121 */
+       /* 0x60 */ KEY_F5,              /*  63 */
+       /* 0x61 */ KEY_F6,              /*  64 */
+       /* 0x62 */ KEY_F7,              /*  65 */
+       /* 0x63 */ KEY_F3,              /*  61 */
+       /* 0x64 */ KEY_F8,              /*  66 */
+       /* 0x65 */ KEY_F9,              /*  67 */
+       /* 0x66 */ KEY_HANJA,           /* 123 */
+       /* 0x67 */ KEY_F11,             /*  87 */
+       /* 0x68 */ KEY_HANGUEL,         /* 122 */
+       /* 0x69 */ KEY_SYSRQ,           /*  99 */
+       /* 0x6a */ 0,
+       /* 0x6b */ KEY_SCROLLLOCK,      /*  70 */
+       /* 0x6c */ 0,
+       /* 0x6d */ KEY_F10,             /*  68 */
+       /* 0x6e */ KEY_COMPOSE,         /* 127 */
+       /* 0x6f */ KEY_F12,             /*  88 */
+       /* 0x70 */ 0,
+       /* 0x71 */ KEY_PAUSE,           /* 119 */
+       /* 0x72 */ KEY_INSERT,          /* 110 */
+       /* 0x73 */ KEY_HOME,            /* 102 */
+       /* 0x74 */ KEY_PAGEUP,          /* 104 */
+       /* 0x75 */ KEY_DELETE,          /* 111 */
+       /* 0x76 */ KEY_F4,              /*  62 */
+       /* 0x77 */ KEY_END,             /* 107 */
+       /* 0x78 */ KEY_F2,              /*  60 */
+       /* 0x79 */ KEY_PAGEDOWN,        /* 109 */
+       /* 0x7a */ KEY_F1,              /*  59 */
+       /* 0x7b */ KEY_RIGHTSHIFT,      /*  54 */
+       /* 0x7c */ KEY_RIGHTALT,        /* 100 */
+       /* 0x7d */ KEY_RIGHTCTRL,       /*  97 */
+       /* 0x7e */ KEY_RIGHTMETA,       /* 126 */
+       /* 0x7f */ KEY_POWER,           /* 116 */
 };
 
 struct adbhid {
@@ -326,7 +446,7 @@ adbhid_mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopo
        input_report_key(&adbhid[id]->input, BTN_LEFT,   !((data[1] >> 7) & 1));
        input_report_key(&adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
 
-       if (nb >= 4)
+       if (nb >= 4 && adbhid[id]->mouse_kind != ADBMOUSE_TRACKPAD)
                input_report_key(&adbhid[id]->input, BTN_RIGHT,  !((data[3] >> 7) & 1));
 
        input_report_rel(&adbhid[id]->input, REL_X,
@@ -453,7 +573,7 @@ static spinlock_t leds_lock  = SPIN_LOCK_UNLOCKED;
 
 static void leds_done(struct adb_request *req)
 {
-       int leds, device;
+       int leds = 0, device = 0, pending = 0;
        unsigned long flags;
 
        spin_lock_irqsave(&leds_lock, flags);
@@ -464,11 +584,11 @@ static void leds_done(struct adb_request *req)
                leds_pending[device] = 0;
                pending_led_start++;
                pending_led_start = (pending_led_start < 16) ? pending_led_start : 0;
+               pending = leds_req_pending;
        } else
                leds_req_pending = 0;
-
        spin_unlock_irqrestore(&leds_lock, flags);
-       if (leds_req_pending)
+       if (pending)
                adb_request(&led_request, leds_done, 0, 3,
                            ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds);
 }
index 0e130f5..26bdcd7 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/fcntl.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/fs.h>
+
 #include <asm/uaccess.h>
 #include <asm/sections.h>
 #include <asm/prom.h>
@@ -154,7 +156,7 @@ anslcd_init(void)
        retval = misc_register(&anslcd_dev);
        if(retval < 0){
                printk(KERN_INFO "LCD: misc_register failed\n");
-               iounmap(anslcd_ptr);
+               iounmap((void *)anslcd_ptr);
                return retval;
        }
 
@@ -177,7 +179,7 @@ static void __exit
 anslcd_exit(void)
 {
        misc_deregister(&anslcd_dev);
-       iounmap(anslcd_ptr);
+       iounmap((void *)anslcd_ptr);
 }
 
 module_init(anslcd_init);
index 1d61a9a..a3a5372 100644 (file)
@@ -713,12 +713,8 @@ static void do_softint(void *private_)
        if (!tty)
                return;
 
-       if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   tty->ldisc.write_wakeup)
-                       (tty->ldisc.write_wakeup)(tty);
-               wake_up_interruptible(&tty->write_wait);
-       }
+       if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
+               tty_wakeup(tty);
 }
 
 static int startup(struct mac_serial * info)
@@ -1564,10 +1560,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
        spin_lock_irqsave(&info->lock, flags);
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
        spin_unlock_irqrestore(&info->lock, flags);
-       wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
 }
 
 /*
@@ -1994,16 +1987,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+       tty_ldisc_flush(tty);
        tty->closing = 0;
        info->event = 0;
        info->tty = 0;
 
        if (info->blocked_open) {
                if (info->close_delay) {
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(info->close_delay);
+                       msleep_interruptible(jiffies_to_msecs(info->close_delay));
                }
                wake_up_interruptible(&info->open_wait);
        }
@@ -2048,8 +2039,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
        if (timeout)
                char_time = min_t(unsigned long, char_time, timeout);
        while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(char_time);
+               msleep_interruptible(jiffies_to_msecs(char_time));
                if (signal_pending(current))
                        break;
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
index f4a1777..7dbc5cb 100644 (file)
@@ -292,8 +292,7 @@ control_loop( void *dummy )
        while( x.running ) {
                up( &x.lock );
 
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout( 8*HZ );
+               msleep_interruptible(8000);
                
                down( &x.lock );
                poll_temp();
index 27e14a7..9f4147e 100644 (file)
@@ -52,7 +52,6 @@
 #include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/pmac_feature.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -138,7 +137,6 @@ static int data_len;
 static volatile int adb_int_pending;
 static volatile int disable_poll;
 static struct adb_request bright_req_1, bright_req_2;
-static unsigned long async_req_locks;
 static struct device_node *vias;
 static int pmu_kind = PMU_UNKNOWN;
 static int pmu_fully_inited = 0;
@@ -155,6 +153,7 @@ static int drop_interrupts;
 static int option_lid_wakeup = 1;
 static int sleep_in_progress;
 static int can_sleep;
+static unsigned long async_req_locks;
 #endif /* CONFIG_PMAC_PBOOK */
 static unsigned int pmu_irq_stats[11];
 
@@ -494,12 +493,9 @@ static int __init via_pmu_dev_init(void)
        /* Create /proc/pmu */
        proc_pmu_root = proc_mkdir("pmu", NULL);
        if (proc_pmu_root) {
-               int i;
-               proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root,
-                                       proc_get_info, NULL);
-               proc_pmu_irqstats = create_proc_read_entry("interrupts", 0, proc_pmu_root,
-                                       proc_get_irqstats, NULL);
 #ifdef CONFIG_PMAC_PBOOK
+               int i;
+
                for (i=0; i<pmu_battery_count; i++) {
                        char title[16];
                        sprintf(title, "battery_%d", i);
@@ -507,6 +503,11 @@ static int __init via_pmu_dev_init(void)
                                                proc_get_batt, (void *)i);
                }
 #endif /* CONFIG_PMAC_PBOOK */
+
+               proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root,
+                                       proc_get_info, NULL);
+               proc_pmu_irqstats = create_proc_read_entry("interrupts", 0, proc_pmu_root,
+                                       proc_get_irqstats, NULL);
                proc_pmu_options = create_proc_entry("options", 0600, proc_pmu_root);
                if (proc_pmu_options) {
                        proc_pmu_options->nlink = 1;
@@ -746,6 +747,8 @@ done_battery_state_smart(struct adb_request* req)
                pmu_power_flags &= ~PMU_PWR_AC_PRESENT;
 
 
+       capa = max = amperage = voltage = 0;
+       
        if (req->reply[1] & 0x04) {
                bat_flags |= PMU_BATT_PRESENT;
                switch(req->reply[0]) {
@@ -765,8 +768,7 @@ done_battery_state_smart(struct adb_request* req)
                                        req->reply_len, req->reply[0], req->reply[1], req->reply[2], req->reply[3]);
                                break;
                }
-       } else
-               capa = max = amperage = voltage = 0;
+       }
 
        if ((req->reply[1] & 0x01) && (amperage > 0))
                bat_flags |= PMU_BATT_CHARGING;
@@ -1445,7 +1447,7 @@ static struct adb_request* __pmac
 pmu_sr_intr(struct pt_regs *regs)
 {
        struct adb_request *req;
-       int bite;
+       int bite = 0;
 
        if (via[B] & TREQ) {
                printk(KERN_ERR "PMU: spurious SR intr (%x)\n", via[B]);
index 7a1c77d..43a1228 100644 (file)
@@ -140,6 +140,13 @@ struct log_c {
 
        int sync_search;
 
+       /* Resync flag */
+       enum sync {
+               DEFAULTSYNC,    /* Synchronize if necessary */
+               NOSYNC,         /* Devices known to be already in sync */
+               FORCESYNC,      /* Force a sync to happen */
+       } sync;
+
        /*
         * Disk log fields
         */
@@ -205,7 +212,8 @@ static int read_header(struct log_c *log)
 
        header_from_disk(&log->header, log->disk_header);
 
-       if (log->header.magic != MIRROR_MAGIC) {
+       /* New log required? */
+       if (log->sync != DEFAULTSYNC || log->header.magic != MIRROR_MAGIC) {
                log->header.magic = MIRROR_MAGIC;
                log->header.version = MIRROR_DISK_VERSION;
                log->header.nr_regions = 0;
@@ -273,22 +281,38 @@ static int write_bits(struct log_c *log)
 }
 
 /*----------------------------------------------------------------
- * constructor/destructor
+ * core log constructor/destructor
+ *
+ * argv contains region_size followed optionally by [no]sync
  *--------------------------------------------------------------*/
 #define BYTE_SHIFT 3
 static int core_ctr(struct dirty_log *log, struct dm_target *ti,
                    unsigned int argc, char **argv)
 {
+       enum sync sync = DEFAULTSYNC;
+
        struct log_c *lc;
        sector_t region_size;
        unsigned int region_count;
        size_t bitset_size;
 
-       if (argc != 1) {
-               DMWARN("wrong number of arguments to log_c");
+       if (argc < 1 || argc > 2) {
+               DMWARN("wrong number of arguments to mirror log");
                return -EINVAL;
        }
 
+       if (argc > 1) {
+               if (!strcmp(argv[1], "sync"))
+                       sync = FORCESYNC;
+               else if (!strcmp(argv[1], "nosync"))
+                       sync = NOSYNC;
+               else {
+                       DMWARN("unrecognised sync argument to mirror log: %s",
+                              argv[1]);
+                       return -EINVAL;
+               }
+       }
+
        if (sscanf(argv[0], SECTOR_FORMAT, &region_size) != 1) {
                DMWARN("invalid region size string");
                return -EINVAL;
@@ -306,6 +330,7 @@ static int core_ctr(struct dirty_log *log, struct dm_target *ti,
        lc->touched = 0;
        lc->region_size = region_size;
        lc->region_count = region_count;
+       lc->sync = sync;
 
        /*
         * Work out how many words we need to hold the bitset.
@@ -330,8 +355,8 @@ static int core_ctr(struct dirty_log *log, struct dm_target *ti,
                kfree(lc);
                return -ENOMEM;
        }
-       memset(lc->sync_bits, 0, bitset_size);
-        lc->sync_count = 0;
+       memset(lc->sync_bits, (sync == NOSYNC) ? -1 : 0, bitset_size);
+       lc->sync_count = (sync == NOSYNC) ? region_count : 0;
 
        lc->recovering_bits = vmalloc(bitset_size);
        if (!lc->recovering_bits) {
@@ -356,6 +381,11 @@ static void core_dtr(struct dirty_log *log)
        kfree(lc);
 }
 
+/*----------------------------------------------------------------
+ * disk log constructor/destructor
+ *
+ * argv contains log_device region_size followed optionally by [no]sync
+ *--------------------------------------------------------------*/
 static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
                    unsigned int argc, char **argv)
 {
@@ -364,8 +394,8 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
        struct log_c *lc;
        struct dm_dev *dev;
 
-       if (argc != 2) {
-               DMWARN("wrong number of arguments to log_d");
+       if (argc < 2 || argc > 3) {
+               DMWARN("wrong number of arguments to disk mirror log");
                return -EINVAL;
        }
 
@@ -452,10 +482,15 @@ static int disk_resume(struct dirty_log *log)
        if (r)
                return r;
 
-       /* zero any new bits if the mirror has grown */
-       for (i = lc->header.nr_regions; i < lc->region_count; i++)
-               /* FIXME: amazingly inefficient */
-               log_clear_bit(lc, lc->clean_bits, i);
+       /* set or clear any new bits */
+       if (lc->sync == NOSYNC)
+               for (i = lc->header.nr_regions; i < lc->region_count; i++)
+                       /* FIXME: amazingly inefficient */
+                       log_set_bit(lc, lc->clean_bits, i);
+       else
+               for (i = lc->header.nr_regions; i < lc->region_count; i++)
+                       /* FIXME: amazingly inefficient */
+                       log_clear_bit(lc, lc->clean_bits, i);
 
        /* copy clean across to sync */
        memcpy(lc->sync_bits, lc->clean_bits, size);
@@ -566,6 +601,51 @@ static region_t core_get_sync_count(struct dirty_log *log)
         return lc->sync_count;
 }
 
+#define        DMEMIT_SYNC \
+       if (lc->sync != DEFAULTSYNC) \
+               DMEMIT("%ssync ", lc->sync == NOSYNC ? "no" : "")
+
+static int core_status(struct dirty_log *log, status_type_t status,
+                      char *result, unsigned int maxlen)
+{
+       int sz = 0;
+       struct log_c *lc = log->context;
+
+       switch(status) {
+       case STATUSTYPE_INFO:
+               break;
+
+       case STATUSTYPE_TABLE:
+               DMEMIT("%s %u " SECTOR_FORMAT " ", log->type->name,
+                      lc->sync == DEFAULTSYNC ? 1 : 2, lc->region_size);
+               DMEMIT_SYNC;
+       }
+
+       return sz;
+}
+
+static int disk_status(struct dirty_log *log, status_type_t status,
+                      char *result, unsigned int maxlen)
+{
+       int sz = 0;
+       char buffer[16];
+       struct log_c *lc = log->context;
+
+       switch(status) {
+       case STATUSTYPE_INFO:
+               break;
+
+       case STATUSTYPE_TABLE:
+               format_dev_t(buffer, lc->log_dev->bdev->bd_dev);
+               DMEMIT("%s %u %s " SECTOR_FORMAT " ", log->type->name,
+                      lc->sync == DEFAULTSYNC ? 2 : 3, buffer,
+                      lc->region_size);
+               DMEMIT_SYNC;
+       }
+
+       return sz;
+}
+
 static struct dirty_log_type _core_type = {
        .name = "core",
        .module = THIS_MODULE,
@@ -579,7 +659,8 @@ static struct dirty_log_type _core_type = {
        .clear_region = core_clear_region,
        .get_resync_work = core_get_resync_work,
        .complete_resync_work = core_complete_resync_work,
-        .get_sync_count = core_get_sync_count
+       .get_sync_count = core_get_sync_count,
+       .status = core_status,
 };
 
 static struct dirty_log_type _disk_type = {
@@ -597,7 +678,8 @@ static struct dirty_log_type _disk_type = {
        .clear_region = core_clear_region,
        .get_resync_work = core_get_resync_work,
        .complete_resync_work = core_complete_resync_work,
-        .get_sync_count = core_get_sync_count
+       .get_sync_count = core_get_sync_count,
+       .status = disk_status,
 };
 
 int __init dm_dirty_log_init(void)
index ced4eba..05ef594 100644 (file)
@@ -101,6 +101,12 @@ struct dirty_log_type {
         * Returns the number of regions that are in sync.
          */
         region_t (*get_sync_count)(struct dirty_log *log);
+
+       /*
+        * Support function for mirror status requests.
+        */
+       int (*status)(struct dirty_log *log, status_type_t status_type,
+                     char *result, unsigned int maxlen);
 };
 
 int dm_register_dirty_log_type(struct dirty_log_type *type);
index 92792bb..abab265 100644 (file)
@@ -1009,8 +1009,8 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti,
  * log_type #log_params <log_params>
  * #mirrors [mirror_path offset]{2,}
  *
- * For now, #log_params = 1, log_type = "core"
- *
+ * log_type is "core" or "disk"
+ * #log_params is between 1 and 3
  */
 #define DM_IO_PAGES 64
 static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
@@ -1182,35 +1182,30 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
                         char *result, unsigned int maxlen)
 {
        char buffer[32];
-       unsigned int m, sz = 0;
+       unsigned int m, sz;
        struct mirror_set *ms = (struct mirror_set *) ti->private;
 
-#define EMIT(x...) sz += ((sz >= maxlen) ? \
-                         0 : scnprintf(result + sz, maxlen - sz, x))
+       sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen);
 
        switch (type) {
        case STATUSTYPE_INFO:
-               EMIT("%d ", ms->nr_mirrors);
-
+               DMEMIT("%d ", ms->nr_mirrors);
                for (m = 0; m < ms->nr_mirrors; m++) {
                        format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
-                       EMIT("%s ", buffer);
+                       DMEMIT("%s ", buffer);
                }
 
-               EMIT(SECTOR_FORMAT "/" SECTOR_FORMAT,
-                    ms->rh.log->type->get_sync_count(ms->rh.log),
-                    ms->nr_regions);
+               DMEMIT(SECTOR_FORMAT "/" SECTOR_FORMAT,
+                      ms->rh.log->type->get_sync_count(ms->rh.log),
+                      ms->nr_regions);
                break;
 
        case STATUSTYPE_TABLE:
-               EMIT("%s 1 " SECTOR_FORMAT " %d ",
-                    ms->rh.log->type->name, ms->rh.region_size,
-                    ms->nr_mirrors);
-
+               DMEMIT("%d ", ms->nr_mirrors);
                for (m = 0; m < ms->nr_mirrors; m++) {
                        format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
-                       EMIT("%s " SECTOR_FORMAT " ",
-                            buffer, ms->mirror[m].offset);
+                       DMEMIT("%s " SECTOR_FORMAT " ",
+                              buffer, ms->mirror[m].offset);
                }
        }
 
index b5bacd7..6a3b945 100644 (file)
@@ -191,20 +191,17 @@ static int stripe_status(struct dm_target *ti,
        unsigned int i;
        char buffer[32];
 
-#define EMIT(x...) sz += ((sz >= maxlen) ? \
-                         0 : scnprintf(result + sz, maxlen - sz, x))
-
        switch (type) {
        case STATUSTYPE_INFO:
                result[0] = '\0';
                break;
 
        case STATUSTYPE_TABLE:
-               EMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1);
+               DMEMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1);
                for (i = 0; i < sc->stripes; i++) {
                        format_dev_t(buffer, sc->stripe[i].dev->bdev->bd_dev);
-                       EMIT(" %s " SECTOR_FORMAT, buffer,
-                            sc->stripe[i].physical_start);
+                       DMEMIT(" %s " SECTOR_FORMAT, buffer,
+                              sc->stripe[i].physical_start);
                }
                break;
        }
index e0aa017..0f57e5e 100644 (file)
@@ -47,7 +47,6 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
                return hash->dev0;
 }
 
-
 /**
  *     linear_mergeable_bvec -- tell bio layer if a two requests can be merged
  *     @q: request queue
@@ -93,6 +92,27 @@ static void linear_unplug(request_queue_t *q)
        }
 }
 
+static int linear_issue_flush(request_queue_t *q, struct gendisk *disk,
+                             sector_t *error_sector)
+{
+       mddev_t *mddev = q->queuedata;
+       linear_conf_t *conf = mddev_to_conf(mddev);
+       int i, ret = 0;
+
+       for (i=0; i < mddev->raid_disks; i++) {
+               struct block_device *bdev = conf->disks[i].rdev->bdev;
+               request_queue_t *r_queue = bdev_get_queue(bdev);
+
+               if (!r_queue->issue_flush_fn) {
+                       ret = -EOPNOTSUPP;
+                       break;
+               }
+               ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+               if (ret)
+                       break;
+       }
+       return ret;
+}
 
 static int linear_run (mddev_t *mddev)
 {
@@ -137,7 +157,7 @@ static int linear_run (mddev_t *mddev)
                 */
                if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
                    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-                       mddev->queue->max_sectors = (PAGE_SIZE>>9);
+                       blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
                disk->size = rdev->size;
                mddev->array_size += rdev->size;
@@ -200,6 +220,7 @@ static int linear_run (mddev_t *mddev)
 
        blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
        mddev->queue->unplug_fn = linear_unplug;
+       mddev->queue->issue_flush_fn = linear_issue_flush;
        return 0;
 
 out:
index 5f4b8bf..ae45ae9 100644 (file)
@@ -40,6 +40,31 @@ static void raid0_unplug(request_queue_t *q)
        }
 }
 
+static int raid0_issue_flush(request_queue_t *q, struct gendisk *disk,
+                            sector_t *error_sector)
+{
+       mddev_t *mddev = q->queuedata;
+       raid0_conf_t *conf = mddev_to_conf(mddev);
+       mdk_rdev_t **devlist = conf->strip_zone[0].dev;
+       int i, ret = 0;
+
+       for (i=0; i<mddev->raid_disks; i++) {
+               struct block_device *bdev = devlist[i]->bdev;
+               request_queue_t *r_queue = bdev_get_queue(bdev);
+
+               if (!r_queue->issue_flush_fn) {
+                       ret = -EOPNOTSUPP;
+                       break;
+               }
+
+               ret =r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+               if (ret)
+                       break;
+       }
+       return ret;
+}
+
+
 static int create_strip_zones (mddev_t *mddev)
 {
        int i, c, j;
@@ -137,7 +162,7 @@ static int create_strip_zones (mddev_t *mddev)
 
                if (rdev1->bdev->bd_disk->queue->merge_bvec_fn &&
                    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-                       mddev->queue->max_sectors = (PAGE_SIZE>>9);
+                       blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
                if (!smallest || (rdev1->size <smallest->size))
                        smallest = rdev1;
@@ -219,6 +244,8 @@ static int create_strip_zones (mddev_t *mddev)
 
        mddev->queue->unplug_fn = raid0_unplug;
 
+       mddev->queue->issue_flush_fn = raid0_issue_flush;
+
        printk("raid0: done.\n");
        return 0;
  abort:
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
new file mode 100644 (file)
index 0000000..6c3fde9
--- /dev/null
@@ -0,0 +1,1780 @@
+/*
+ * raid10.c : Multiple Devices driver for Linux
+ *
+ * Copyright (C) 2000-2004 Neil Brown
+ *
+ * RAID-10 support for md.
+ *
+ * Base on code in raid1.c.  See raid1.c for futher copyright information.
+ *
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example /usr/src/linux/COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/raid/raid10.h>
+
+/*
+ * RAID10 provides a combination of RAID0 and RAID1 functionality.
+ * The layout of data is defined by
+ *    chunk_size
+ *    raid_disks
+ *    near_copies (stored in low byte of layout)
+ *    far_copies (stored in second byte of layout)
+ *
+ * The data to be stored is divided into chunks using chunksize.
+ * Each device is divided into far_copies sections.
+ * In each section, chunks are laid out in a style similar to raid0, but
+ * near_copies copies of each chunk is stored (each on a different drive).
+ * The starting device for each section is offset near_copies from the starting
+ * device of the previous section.
+ * Thus there are (near_copies*far_copies) of each chunk, and each is on a different
+ * drive.
+ * near_copies and far_copies must be at least one, and there product is at most
+ * raid_disks.
+ */
+
+/*
+ * Number of guaranteed r10bios in case of extreme VM load:
+ */
+#define        NR_RAID10_BIOS 256
+
+static void unplug_slaves(mddev_t *mddev);
+
+static void * r10bio_pool_alloc(int gfp_flags, void *data)
+{
+       conf_t *conf = data;
+       r10bio_t *r10_bio;
+       int size = offsetof(struct r10bio_s, devs[conf->copies]);
+
+       /* allocate a r10bio with room for raid_disks entries in the bios array */
+       r10_bio = kmalloc(size, gfp_flags);
+       if (r10_bio)
+               memset(r10_bio, 0, size);
+       else
+               unplug_slaves(conf->mddev);
+
+       return r10_bio;
+}
+
+static void r10bio_pool_free(void *r10_bio, void *data)
+{
+       kfree(r10_bio);
+}
+
+#define RESYNC_BLOCK_SIZE (64*1024)
+//#define RESYNC_BLOCK_SIZE PAGE_SIZE
+#define RESYNC_SECTORS (RESYNC_BLOCK_SIZE >> 9)
+#define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE)
+#define RESYNC_WINDOW (2048*1024)
+
+/*
+ * When performing a resync, we need to read and compare, so
+ * we need as many pages are there are copies.
+ * When performing a recovery, we need 2 bios, one for read,
+ * one for write (we recover only one drive per r10buf)
+ *
+ */
+static void * r10buf_pool_alloc(int gfp_flags, void *data)
+{
+       conf_t *conf = data;
+       struct page *page;
+       r10bio_t *r10_bio;
+       struct bio *bio;
+       int i, j;
+       int nalloc;
+
+       r10_bio = r10bio_pool_alloc(gfp_flags, conf);
+       if (!r10_bio) {
+               unplug_slaves(conf->mddev);
+               return NULL;
+       }
+
+       if (test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
+               nalloc = conf->copies; /* resync */
+       else
+               nalloc = 2; /* recovery */
+
+       /*
+        * Allocate bios.
+        */
+       for (j = nalloc ; j-- ; ) {
+               bio = bio_alloc(gfp_flags, RESYNC_PAGES);
+               if (!bio)
+                       goto out_free_bio;
+               r10_bio->devs[j].bio = bio;
+       }
+       /*
+        * Allocate RESYNC_PAGES data pages and attach them
+        * where needed.
+        */
+       for (j = 0 ; j < nalloc; j++) {
+               bio = r10_bio->devs[j].bio;
+               for (i = 0; i < RESYNC_PAGES; i++) {
+                       page = alloc_page(gfp_flags);
+                       if (unlikely(!page))
+                               goto out_free_pages;
+
+                       bio->bi_io_vec[i].bv_page = page;
+               }
+       }
+
+       return r10_bio;
+
+out_free_pages:
+       for ( ; i > 0 ; i--)
+               __free_page(bio->bi_io_vec[i-1].bv_page);
+       while (j--)
+               for (i = 0; i < RESYNC_PAGES ; i++)
+                       __free_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
+       j = -1;
+out_free_bio:
+       while ( ++j < nalloc )
+               bio_put(r10_bio->devs[j].bio);
+       r10bio_pool_free(r10_bio, conf);
+       return NULL;
+}
+
+static void r10buf_pool_free(void *__r10_bio, void *data)
+{
+       int i;
+       conf_t *conf = data;
+       r10bio_t *r10bio = __r10_bio;
+       int j;
+
+       for (j=0; j < conf->copies; j++) {
+               struct bio *bio = r10bio->devs[j].bio;
+               if (bio) {
+                       for (i = 0; i < RESYNC_PAGES; i++) {
+                               __free_page(bio->bi_io_vec[i].bv_page);
+                               bio->bi_io_vec[i].bv_page = NULL;
+                       }
+                       bio_put(bio);
+               }
+       }
+       r10bio_pool_free(r10bio, conf);
+}
+
+static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
+{
+       int i;
+
+       for (i = 0; i < conf->copies; i++) {
+               struct bio **bio = & r10_bio->devs[i].bio;
+               if (*bio)
+                       bio_put(*bio);
+               *bio = NULL;
+       }
+}
+
+static inline void free_r10bio(r10bio_t *r10_bio)
+{
+       unsigned long flags;
+
+       conf_t *conf = mddev_to_conf(r10_bio->mddev);
+
+       /*
+        * Wake up any possible resync thread that waits for the device
+        * to go idle.
+        */
+       spin_lock_irqsave(&conf->resync_lock, flags);
+       if (!--conf->nr_pending) {
+               wake_up(&conf->wait_idle);
+               wake_up(&conf->wait_resume);
+       }
+       spin_unlock_irqrestore(&conf->resync_lock, flags);
+
+       put_all_bios(conf, r10_bio);
+       mempool_free(r10_bio, conf->r10bio_pool);
+}
+
+static inline void put_buf(r10bio_t *r10_bio)
+{
+       conf_t *conf = mddev_to_conf(r10_bio->mddev);
+       unsigned long flags;
+
+       mempool_free(r10_bio, conf->r10buf_pool);
+
+       spin_lock_irqsave(&conf->resync_lock, flags);
+       if (!conf->barrier)
+               BUG();
+       --conf->barrier;
+       wake_up(&conf->wait_resume);
+       wake_up(&conf->wait_idle);
+
+       if (!--conf->nr_pending) {
+               wake_up(&conf->wait_idle);
+               wake_up(&conf->wait_resume);
+       }
+       spin_unlock_irqrestore(&conf->resync_lock, flags);
+}
+
+static void reschedule_retry(r10bio_t *r10_bio)
+{
+       unsigned long flags;
+       mddev_t *mddev = r10_bio->mddev;
+       conf_t *conf = mddev_to_conf(mddev);
+
+       spin_lock_irqsave(&conf->device_lock, flags);
+       list_add(&r10_bio->retry_list, &conf->retry_list);
+       spin_unlock_irqrestore(&conf->device_lock, flags);
+
+       md_wakeup_thread(mddev->thread);
+}
+
+/*
+ * raid_end_bio_io() is called when we have finished servicing a mirrored
+ * operation and are ready to return a success/failure code to the buffer
+ * cache layer.
+ */
+static void raid_end_bio_io(r10bio_t *r10_bio)
+{
+       struct bio *bio = r10_bio->master_bio;
+
+       bio_endio(bio, bio->bi_size,
+               test_bit(R10BIO_Uptodate, &r10_bio->state) ? 0 : -EIO);
+       free_r10bio(r10_bio);
+}
+
+/*
+ * Update disk head position estimator based on IRQ completion info.
+ */
+static inline void update_head_pos(int slot, r10bio_t *r10_bio)
+{
+       conf_t *conf = mddev_to_conf(r10_bio->mddev);
+
+       conf->mirrors[r10_bio->devs[slot].devnum].head_position =
+               r10_bio->devs[slot].addr + (r10_bio->sectors);
+}
+
+static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int error)
+{
+       int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+       r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+       int slot, dev;
+       conf_t *conf = mddev_to_conf(r10_bio->mddev);
+
+       if (bio->bi_size)
+               return 1;
+
+       slot = r10_bio->read_slot;
+       dev = r10_bio->devs[slot].devnum;
+       /*
+        * this branch is our 'one mirror IO has finished' event handler:
+        */
+       if (!uptodate)
+               md_error(r10_bio->mddev, conf->mirrors[dev].rdev);
+       else
+               /*
+                * Set R10BIO_Uptodate in our master bio, so that
+                * we will return a good error code to the higher
+                * levels even if IO on some other mirrored buffer fails.
+                *
+                * The 'master' represents the composite IO operation to
+                * user-side. So if something waits for IO, then it will
+                * wait for the 'master' bio.
+                */
+               set_bit(R10BIO_Uptodate, &r10_bio->state);
+
+       update_head_pos(slot, r10_bio);
+
+       /*
+        * we have only one bio on the read side
+        */
+       if (uptodate)
+               raid_end_bio_io(r10_bio);
+       else {
+               /*
+                * oops, read error:
+                */
+               char b[BDEVNAME_SIZE];
+               if (printk_ratelimit())
+                       printk(KERN_ERR "raid10: %s: rescheduling sector %llu\n",
+                              bdevname(conf->mirrors[dev].rdev->bdev,b), (unsigned long long)r10_bio->sector);
+               reschedule_retry(r10_bio);
+       }
+
+       rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
+       return 0;
+}
+
+static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, int error)
+{
+       int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+       r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+       int slot, dev;
+       conf_t *conf = mddev_to_conf(r10_bio->mddev);
+
+       if (bio->bi_size)
+               return 1;
+
+       for (slot = 0; slot < conf->copies; slot++)
+               if (r10_bio->devs[slot].bio == bio)
+                       break;
+       dev = r10_bio->devs[slot].devnum;
+
+       /*
+        * this branch is our 'one mirror IO has finished' event handler:
+        */
+       if (!uptodate)
+               md_error(r10_bio->mddev, conf->mirrors[dev].rdev);
+       else
+               /*
+                * Set R10BIO_Uptodate in our master bio, so that
+                * we will return a good error code for to the higher
+                * levels even if IO on some other mirrored buffer fails.
+                *
+                * The 'master' represents the composite IO operation to
+                * user-side. So if something waits for IO, then it will
+                * wait for the 'master' bio.
+                */
+               set_bit(R10BIO_Uptodate, &r10_bio->state);
+
+       update_head_pos(slot, r10_bio);
+
+       /*
+        *
+        * Let's see if all mirrored write operations have finished
+        * already.
+        */
+       if (atomic_dec_and_test(&r10_bio->remaining)) {
+               md_write_end(r10_bio->mddev);
+               raid_end_bio_io(r10_bio);
+       }
+
+       rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
+       return 0;
+}
+
+
+/*
+ * RAID10 layout manager
+ * Aswell as the chunksize and raid_disks count, there are two
+ * parameters: near_copies and far_copies.
+ * near_copies * far_copies must be <= raid_disks.
+ * Normally one of these will be 1.
+ * If both are 1, we get raid0.
+ * If near_copies == raid_disks, we get raid1.
+ *
+ * Chunks are layed out in raid0 style with near_copies copies of the
+ * first chunk, followed by near_copies copies of the next chunk and
+ * so on.
+ * If far_copies > 1, then after 1/far_copies of the array has been assigned
+ * as described above, we start again with a device offset of near_copies.
+ * So we effectively have another copy of the whole array further down all
+ * the drives, but with blocks on different drives.
+ * With this layout, and block is never stored twice on the one device.
+ *
+ * raid10_find_phys finds the sector offset of a given virtual sector
+ * on each device that it is on. If a block isn't on a device,
+ * that entry in the array is set to MaxSector.
+ *
+ * raid10_find_virt does the reverse mapping, from a device and a
+ * sector offset to a virtual address
+ */
+
+static void raid10_find_phys(conf_t *conf, r10bio_t *r10bio)
+{
+       int n,f;
+       sector_t sector;
+       sector_t chunk;
+       sector_t stripe;
+       int dev;
+
+       int slot = 0;
+
+       /* now calculate first sector/dev */
+       chunk = r10bio->sector >> conf->chunk_shift;
+       sector = r10bio->sector & conf->chunk_mask;
+
+       chunk *= conf->near_copies;
+       stripe = chunk;
+       dev = sector_div(stripe, conf->raid_disks);
+
+       sector += stripe << conf->chunk_shift;
+
+       /* and calculate all the others */
+       for (n=0; n < conf->near_copies; n++) {
+               int d = dev;
+               sector_t s = sector;
+               r10bio->devs[slot].addr = sector;
+               r10bio->devs[slot].devnum = d;
+               slot++;
+
+               for (f = 1; f < conf->far_copies; f++) {
+                       d += conf->near_copies;
+                       if (d >= conf->raid_disks)
+                               d -= conf->raid_disks;
+                       s += conf->stride;
+                       r10bio->devs[slot].devnum = d;
+                       r10bio->devs[slot].addr = s;
+                       slot++;
+               }
+               dev++;
+               if (dev >= conf->raid_disks) {
+                       dev = 0;
+                       sector += (conf->chunk_mask + 1);
+               }
+       }
+       BUG_ON(slot != conf->copies);
+}
+
+static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev)
+{
+       sector_t offset, chunk, vchunk;
+
+       while (sector > conf->stride) {
+               sector -= conf->stride;
+               if (dev < conf->near_copies)
+                       dev += conf->raid_disks - conf->near_copies;
+               else
+                       dev -= conf->near_copies;
+       }
+
+       offset = sector & conf->chunk_mask;
+       chunk = sector >> conf->chunk_shift;
+       vchunk = chunk * conf->raid_disks + dev;
+       sector_div(vchunk, conf->near_copies);
+       return (vchunk << conf->chunk_shift) + offset;
+}
+
+/**
+ *     raid10_mergeable_bvec -- tell bio layer if a two requests can be merged
+ *     @q: request queue
+ *     @bio: the buffer head that's been built up so far
+ *     @biovec: the request that could be merged to it.
+ *
+ *     Return amount of bytes we can accept at this offset
+ *      If near_copies == raid_disk, there are no striping issues,
+ *      but in that case, the function isn't called at all.
+ */
+static int raid10_mergeable_bvec(request_queue_t *q, struct bio *bio,
+                               struct bio_vec *bio_vec)
+{
+       mddev_t *mddev = q->queuedata;
+       sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+       int max;
+       unsigned int chunk_sectors = mddev->chunk_size >> 9;
+       unsigned int bio_sectors = bio->bi_size >> 9;
+
+       max =  (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
+       if (max < 0) max = 0; /* bio_add cannot handle a negative return */
+       if (max <= bio_vec->bv_len && bio_sectors == 0)
+               return bio_vec->bv_len;
+       else
+               return max;
+}
+
+/*
+ * This routine returns the disk from which the requested read should
+ * be done. There is a per-array 'next expected sequential IO' sector
+ * number - if this matches on the next IO then we use the last disk.
+ * There is also a per-disk 'last know head position' sector that is
+ * maintained from IRQ contexts, both the normal and the resync IO
+ * completion handlers update this position correctly. If there is no
+ * perfect sequential match then we pick the disk whose head is closest.
+ *
+ * If there are 2 mirrors in the same 2 devices, performance degrades
+ * because position is mirror, not device based.
+ *
+ * The rdev for the device selected will have nr_pending incremented.
+ */
+
+/*
+ * FIXME: possibly should rethink readbalancing and do it differently
+ * depending on near_copies / far_copies geometry.
+ */
+static int read_balance(conf_t *conf, r10bio_t *r10_bio)
+{
+       const unsigned long this_sector = r10_bio->sector;
+       int disk, slot, nslot;
+       const int sectors = r10_bio->sectors;
+       sector_t new_distance, current_distance;
+
+       raid10_find_phys(conf, r10_bio);
+       spin_lock_irq(&conf->device_lock);
+       /*
+        * Check if we can balance. We can balance on the whole
+        * device if no resync is going on, or below the resync window.
+        * We take the first readable disk when above the resync window.
+        */
+       if (conf->mddev->recovery_cp < MaxSector
+           && (this_sector + sectors >= conf->next_resync)) {
+               /* make sure that disk is operational */
+               slot = 0;
+               disk = r10_bio->devs[slot].devnum;
+
+               while (!conf->mirrors[disk].rdev ||
+                      !conf->mirrors[disk].rdev->in_sync) {
+                       slot++;
+                       if (slot == conf->copies) {
+                               slot = 0;
+                               disk = -1;
+                               break;
+                       }
+                       disk = r10_bio->devs[slot].devnum;
+               }
+               goto rb_out;
+       }
+
+
+       /* make sure the disk is operational */
+       slot = 0;
+       disk = r10_bio->devs[slot].devnum;
+       while (!conf->mirrors[disk].rdev ||
+              !conf->mirrors[disk].rdev->in_sync) {
+               slot ++;
+               if (slot == conf->copies) {
+                       disk = -1;
+                       goto rb_out;
+               }
+               disk = r10_bio->devs[slot].devnum;
+       }
+
+
+       current_distance = abs(this_sector - conf->mirrors[disk].head_position);
+
+       /* Find the disk whose head is closest */
+
+       for (nslot = slot; nslot < conf->copies; nslot++) {
+               int ndisk = r10_bio->devs[nslot].devnum;
+
+
+               if (!conf->mirrors[ndisk].rdev ||
+                   !conf->mirrors[ndisk].rdev->in_sync)
+                       continue;
+
+               if (!atomic_read(&conf->mirrors[ndisk].rdev->nr_pending)) {
+                       disk = ndisk;
+                       slot = nslot;
+                       break;
+               }
+               new_distance = abs(r10_bio->devs[nslot].addr -
+                                  conf->mirrors[ndisk].head_position);
+               if (new_distance < current_distance) {
+                       current_distance = new_distance;
+                       disk = ndisk;
+                       slot = nslot;
+               }
+       }
+
+rb_out:
+       r10_bio->read_slot = slot;
+/*     conf->next_seq_sect = this_sector + sectors;*/
+
+       if (disk >= 0 && conf->mirrors[disk].rdev)
+               atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
+       spin_unlock_irq(&conf->device_lock);
+
+       return disk;
+}
+
+static void unplug_slaves(mddev_t *mddev)
+{
+       conf_t *conf = mddev_to_conf(mddev);
+       int i;
+       unsigned long flags;
+
+       spin_lock_irqsave(&conf->device_lock, flags);
+       for (i=0; i<mddev->raid_disks; i++) {
+               mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+               if (rdev && atomic_read(&rdev->nr_pending)) {
+                       request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
+
+                       atomic_inc(&rdev->nr_pending);
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
+
+                       if (r_queue->unplug_fn)
+                               r_queue->unplug_fn(r_queue);
+
+                       spin_lock_irqsave(&conf->device_lock, flags);
+                       atomic_dec(&rdev->nr_pending);
+               }
+       }
+       spin_unlock_irqrestore(&conf->device_lock, flags);
+}
+static void raid10_unplug(request_queue_t *q)
+{
+       unplug_slaves(q->queuedata);
+}
+
+static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk,
+                            sector_t *error_sector)
+{
+       mddev_t *mddev = q->queuedata;
+       conf_t *conf = mddev_to_conf(mddev);
+       unsigned long flags;
+       int i, ret = 0;
+
+       spin_lock_irqsave(&conf->device_lock, flags);
+       for (i=0; i<mddev->raid_disks; i++) {
+               mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+               if (rdev && !rdev->faulty) {
+                       struct block_device *bdev = rdev->bdev;
+                       request_queue_t *r_queue = bdev_get_queue(bdev);
+
+                       if (r_queue->issue_flush_fn) {
+                               ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+                               if (ret)
+                                       break;
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&conf->device_lock, flags);
+       return ret;
+}
+
+/*
+ * Throttle resync depth, so that we can both get proper overlapping of
+ * requests, but are still able to handle normal requests quickly.
+ */
+#define RESYNC_DEPTH 32
+
+static void device_barrier(conf_t *conf, sector_t sect)
+{
+       spin_lock_irq(&conf->resync_lock);
+       wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
+                           conf->resync_lock, unplug_slaves(conf->mddev));
+
+       if (!conf->barrier++) {
+               wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
+                                   conf->resync_lock, unplug_slaves(conf->mddev));
+               if (conf->nr_pending)
+                       BUG();
+       }
+       wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
+                           conf->resync_lock, unplug_slaves(conf->mddev));
+       conf->next_resync = sect;
+       spin_unlock_irq(&conf->resync_lock);
+}
+
+static int make_request(request_queue_t *q, struct bio * bio)
+{
+       mddev_t *mddev = q->queuedata;
+       conf_t *conf = mddev_to_conf(mddev);
+       mirror_info_t *mirror;
+       r10bio_t *r10_bio;
+       struct bio *read_bio;
+       int i;
+       int chunk_sects = conf->chunk_mask + 1;
+
+       /* If this request crosses a chunk boundary, we need to
+        * split it.  This will only happen for 1 PAGE (or less) requests.
+        */
+       if (unlikely( (bio->bi_sector & conf->chunk_mask) + (bio->bi_size >> 9)
+                     > chunk_sects &&
+                   conf->near_copies < conf->raid_disks)) {
+               struct bio_pair *bp;
+               /* Sanity check -- queue functions should prevent this happening */
+               if (bio->bi_vcnt != 1 ||
+                   bio->bi_idx != 0)
+                       goto bad_map;
+               /* This is a one page bio that upper layers
+                * refuse to split for us, so we need to split it.
+                */
+               bp = bio_split(bio, bio_split_pool,
+                              chunk_sects - (bio->bi_sector & (chunk_sects - 1)) );
+               if (make_request(q, &bp->bio1))
+                       generic_make_request(&bp->bio1);
+               if (make_request(q, &bp->bio2))
+                       generic_make_request(&bp->bio2);
+
+               bio_pair_release(bp);
+               return 0;
+       bad_map:
+               printk("raid10_make_request bug: can't convert block across chunks"
+                      " or bigger than %dk %llu %d\n", chunk_sects/2,
+                      (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
+
+               bio_io_error(bio, bio->bi_size);
+               return 0;
+       }
+
+       /*
+        * Register the new request and wait if the reconstruction
+        * thread has put up a bar for new requests.
+        * Continue immediately if no resync is active currently.
+        */
+       spin_lock_irq(&conf->resync_lock);
+       wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
+       conf->nr_pending++;
+       spin_unlock_irq(&conf->resync_lock);
+
+       if (bio_data_dir(bio)==WRITE) {
+               disk_stat_inc(mddev->gendisk, writes);
+               disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
+       } else {
+               disk_stat_inc(mddev->gendisk, reads);
+               disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bio));
+       }
+
+       r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
+
+       r10_bio->master_bio = bio;
+       r10_bio->sectors = bio->bi_size >> 9;
+
+       r10_bio->mddev = mddev;
+       r10_bio->sector = bio->bi_sector;
+
+       if (bio_data_dir(bio) == READ) {
+               /*
+                * read balancing logic:
+                */
+               int disk = read_balance(conf, r10_bio);
+               int slot = r10_bio->read_slot;
+               if (disk < 0) {
+                       raid_end_bio_io(r10_bio);
+                       return 0;
+               }
+               mirror = conf->mirrors + disk;
+
+               read_bio = bio_clone(bio, GFP_NOIO);
+
+               r10_bio->devs[slot].bio = read_bio;
+
+               read_bio->bi_sector = r10_bio->devs[slot].addr +
+                       mirror->rdev->data_offset;
+               read_bio->bi_bdev = mirror->rdev->bdev;
+               read_bio->bi_end_io = raid10_end_read_request;
+               read_bio->bi_rw = READ;
+               read_bio->bi_private = r10_bio;
+
+               generic_make_request(read_bio);
+               return 0;
+       }
+
+       /*
+        * WRITE:
+        */
+       /* first select target devices under spinlock and
+        * inc refcount on their rdev.  Record them by setting
+        * bios[x] to bio
+        */
+       raid10_find_phys(conf, r10_bio);
+       spin_lock_irq(&conf->device_lock);
+       for (i = 0;  i < conf->copies; i++) {
+               int d = r10_bio->devs[i].devnum;
+               if (conf->mirrors[d].rdev &&
+                   !conf->mirrors[d].rdev->faulty) {
+                       atomic_inc(&conf->mirrors[d].rdev->nr_pending);
+                       r10_bio->devs[i].bio = bio;
+               } else
+                       r10_bio->devs[i].bio = NULL;
+       }
+       spin_unlock_irq(&conf->device_lock);
+
+       atomic_set(&r10_bio->remaining, 1);
+       md_write_start(mddev);
+       for (i = 0; i < conf->copies; i++) {
+               struct bio *mbio;
+               int d = r10_bio->devs[i].devnum;
+               if (!r10_bio->devs[i].bio)
+                       continue;
+
+               mbio = bio_clone(bio, GFP_NOIO);
+               r10_bio->devs[i].bio = mbio;
+
+               mbio->bi_sector = r10_bio->devs[i].addr+
+                       conf->mirrors[d].rdev->data_offset;
+               mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
+               mbio->bi_end_io = raid10_end_write_request;
+               mbio->bi_rw = WRITE;
+               mbio->bi_private = r10_bio;
+
+               atomic_inc(&r10_bio->remaining);
+               generic_make_request(mbio);
+       }
+
+       if (atomic_dec_and_test(&r10_bio->remaining)) {
+               md_write_end(mddev);
+               raid_end_bio_io(r10_bio);
+       }
+
+       return 0;
+}
+
+static void status(struct seq_file *seq, mddev_t *mddev)
+{
+       conf_t *conf = mddev_to_conf(mddev);
+       int i;
+
+       if (conf->near_copies < conf->raid_disks)
+               seq_printf(seq, " %dK chunks", mddev->chunk_size/1024);
+       if (conf->near_copies > 1)
+               seq_printf(seq, " %d near-copies", conf->near_copies);
+       if (conf->far_copies > 1)
+               seq_printf(seq, " %d far-copies", conf->far_copies);
+
+       seq_printf(seq, " [%d/%d] [", conf->raid_disks,
+                                               conf->working_disks);
+       for (i = 0; i < conf->raid_disks; i++)
+               seq_printf(seq, "%s",
+                             conf->mirrors[i].rdev &&
+                             conf->mirrors[i].rdev->in_sync ? "U" : "_");
+       seq_printf(seq, "]");
+}
+
+static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+       char b[BDEVNAME_SIZE];
+       conf_t *conf = mddev_to_conf(mddev);
+
+       /*
+        * If it is not operational, then we have already marked it as dead
+        * else if it is the last working disks, ignore the error, let the
+        * next level up know.
+        * else mark the drive as failed
+        */
+       if (rdev->in_sync
+           && conf->working_disks == 1)
+               /*
+                * Don't fail the drive, just return an IO error.
+                * The test should really be more sophisticated than
+                * "working_disks == 1", but it isn't critical, and
+                * can wait until we do more sophisticated "is the drive
+                * really dead" tests...
+                */
+               return;
+       if (rdev->in_sync) {
+               mddev->degraded++;
+               conf->working_disks--;
+               /*
+                * if recovery is running, make sure it aborts.
+                */
+               set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+       }
+       rdev->in_sync = 0;
+       rdev->faulty = 1;
+       mddev->sb_dirty = 1;
+       printk(KERN_ALERT "raid10: Disk failure on %s, disabling device. \n"
+               "       Operation continuing on %d devices\n",
+               bdevname(rdev->bdev,b), conf->working_disks);
+}
+
+static void print_conf(conf_t *conf)
+{
+       int i;
+       mirror_info_t *tmp;
+
+       printk("RAID10 conf printout:\n");
+       if (!conf) {
+               printk("(!conf)\n");
+               return;
+       }
+       printk(" --- wd:%d rd:%d\n", conf->working_disks,
+               conf->raid_disks);
+
+       for (i = 0; i < conf->raid_disks; i++) {
+               char b[BDEVNAME_SIZE];
+               tmp = conf->mirrors + i;
+               if (tmp->rdev)
+                       printk(" disk %d, wo:%d, o:%d, dev:%s\n",
+                               i, !tmp->rdev->in_sync, !tmp->rdev->faulty,
+                               bdevname(tmp->rdev->bdev,b));
+       }
+}
+
+static void close_sync(conf_t *conf)
+{
+       spin_lock_irq(&conf->resync_lock);
+       wait_event_lock_irq(conf->wait_resume, !conf->barrier,
+                           conf->resync_lock,  unplug_slaves(conf->mddev));
+       spin_unlock_irq(&conf->resync_lock);
+
+       if (conf->barrier) BUG();
+       if (waitqueue_active(&conf->wait_idle)) BUG();
+
+       mempool_destroy(conf->r10buf_pool);
+       conf->r10buf_pool = NULL;
+}
+
+static int raid10_spare_active(mddev_t *mddev)
+{
+       int i;
+       conf_t *conf = mddev->private;
+       mirror_info_t *tmp;
+
+       spin_lock_irq(&conf->device_lock);
+       /*
+        * Find all non-in_sync disks within the RAID10 configuration
+        * and mark them in_sync
+        */
+       for (i = 0; i < conf->raid_disks; i++) {
+               tmp = conf->mirrors + i;
+               if (tmp->rdev
+                   && !tmp->rdev->faulty
+                   && !tmp->rdev->in_sync) {
+                       conf->working_disks++;
+                       mddev->degraded--;
+                       tmp->rdev->in_sync = 1;
+               }
+       }
+       spin_unlock_irq(&conf->device_lock);
+
+       print_conf(conf);
+       return 0;
+}
+
+
+static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+       conf_t *conf = mddev->private;
+       int found = 0;
+       int mirror;
+       mirror_info_t *p;
+
+       if (mddev->recovery_cp < MaxSector)
+               /* only hot-add to in-sync arrays, as recovery is
+                * very different from resync
+                */
+               return 0;
+       spin_lock_irq(&conf->device_lock);
+       for (mirror=0; mirror < mddev->raid_disks; mirror++)
+               if ( !(p=conf->mirrors+mirror)->rdev) {
+                       p->rdev = rdev;
+
+                       blk_queue_stack_limits(mddev->queue,
+                                              rdev->bdev->bd_disk->queue);
+                       /* as we don't honour merge_bvec_fn, we must never risk
+                        * violating it, so limit ->max_sector to one PAGE, as
+                        * a one page request is never in violation.
+                        */
+                       if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+                           mddev->queue->max_sectors > (PAGE_SIZE>>9))
+                               mddev->queue->max_sectors = (PAGE_SIZE>>9);
+
+                       p->head_position = 0;
+                       rdev->raid_disk = mirror;
+                       found = 1;
+                       break;
+               }
+       spin_unlock_irq(&conf->device_lock);
+
+       print_conf(conf);
+       return found;
+}
+
+static int raid10_remove_disk(mddev_t *mddev, int number)
+{
+       conf_t *conf = mddev->private;
+       int err = 1;
+       mirror_info_t *p = conf->mirrors+ number;
+
+       print_conf(conf);
+       spin_lock_irq(&conf->device_lock);
+       if (p->rdev) {
+               if (p->rdev->in_sync ||
+                   atomic_read(&p->rdev->nr_pending)) {
+                       err = -EBUSY;
+                       goto abort;
+               }
+               p->rdev = NULL;
+               err = 0;
+       }
+       if (err)
+               MD_BUG();
+abort:
+       spin_unlock_irq(&conf->device_lock);
+
+       print_conf(conf);
+       return err;
+}
+
+
+static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
+{
+       int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+       r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+       conf_t *conf = mddev_to_conf(r10_bio->mddev);
+       int i,d;
+
+       if (bio->bi_size)
+               return 1;
+
+       for (i=0; i<conf->copies; i++)
+               if (r10_bio->devs[i].bio == bio)
+                       break;
+       if (i == conf->copies)
+               BUG();
+       update_head_pos(i, r10_bio);
+       d = r10_bio->devs[i].devnum;
+       if (!uptodate)
+               md_error(r10_bio->mddev,
+                        conf->mirrors[d].rdev);
+
+       /* for reconstruct, we always reschedule after a read.
+        * for resync, only after all reads
+        */
+       if (test_bit(R10BIO_IsRecover, &r10_bio->state) ||
+           atomic_dec_and_test(&r10_bio->remaining)) {
+               /* we have read all the blocks,
+                * do the comparison in process context in raid10d
+                */
+               reschedule_retry(r10_bio);
+       }
+       rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev);
+       return 0;
+}
+
+static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
+{
+       int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+       r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+       mddev_t *mddev = r10_bio->mddev;
+       conf_t *conf = mddev_to_conf(mddev);
+       int i,d;
+
+       if (bio->bi_size)
+               return 1;
+
+       for (i = 0; i < conf->copies; i++)
+               if (r10_bio->devs[i].bio == bio)
+                       break;
+       d = r10_bio->devs[i].devnum;
+
+       if (!uptodate)
+               md_error(mddev, conf->mirrors[d].rdev);
+       update_head_pos(i, r10_bio);
+
+       while (atomic_dec_and_test(&r10_bio->remaining)) {
+               if (r10_bio->master_bio == NULL) {
+                       /* the primary of several recovery bios */
+                       md_done_sync(mddev, r10_bio->sectors, 1);
+                       put_buf(r10_bio);
+                       break;
+               } else {
+                       r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio;
+                       put_buf(r10_bio);
+                       r10_bio = r10_bio2;
+               }
+       }
+       rdev_dec_pending(conf->mirrors[d].rdev, mddev);
+       return 0;
+}
+
+/*
+ * Note: sync and recover and handled very differently for raid10
+ * This code is for resync.
+ * For resync, we read through virtual addresses and read all blocks.
+ * If there is any error, we schedule a write.  The lowest numbered
+ * drive is authoritative.
+ * However requests come for physical address, so we need to map.
+ * For every physical address there are raid_disks/copies virtual addresses,
+ * which is always are least one, but is not necessarly an integer.
+ * This means that a physical address can span multiple chunks, so we may
+ * have to submit multiple io requests for a single sync request.
+ */
+/*
+ * We check if all blocks are in-sync and only write to blocks that
+ * aren't in sync
+ */
+static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
+{
+       conf_t *conf = mddev_to_conf(mddev);
+       int i, first;
+       struct bio *tbio, *fbio;
+
+       atomic_set(&r10_bio->remaining, 1);
+
+       /* find the first device with a block */
+       for (i=0; i<conf->copies; i++)
+               if (test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags))
+                       break;
+
+       if (i == conf->copies)
+               goto done;
+
+       first = i;
+       fbio = r10_bio->devs[i].bio;
+
+       /* now find blocks with errors */
+       for (i=first+1 ; i < conf->copies ; i++) {
+               int vcnt, j, d;
+
+               if (!test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags))
+                       continue;
+               /* We know that the bi_io_vec layout is the same for
+                * both 'first' and 'i', so we just compare them.
+                * All vec entries are PAGE_SIZE;
+                */
+               tbio = r10_bio->devs[i].bio;
+               vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
+               for (j = 0; j < vcnt; j++)
+                       if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
+                                  page_address(tbio->bi_io_vec[j].bv_page),
+                                  PAGE_SIZE))
+                               break;
+               if (j == vcnt)
+                       continue;
+               /* Ok, we need to write this bio
+                * First we need to fixup bv_offset, bv_len and
+                * bi_vecs, as the read request might have corrupted these
+                */
+               tbio->bi_vcnt = vcnt;
+               tbio->bi_size = r10_bio->sectors << 9;
+               tbio->bi_idx = 0;
+               tbio->bi_phys_segments = 0;
+               tbio->bi_hw_segments = 0;
+               tbio->bi_hw_front_size = 0;
+               tbio->bi_hw_back_size = 0;
+               tbio->bi_flags &= ~(BIO_POOL_MASK - 1);
+               tbio->bi_flags |= 1 << BIO_UPTODATE;
+               tbio->bi_next = NULL;
+               tbio->bi_rw = WRITE;
+               tbio->bi_private = r10_bio;
+               tbio->bi_sector = r10_bio->devs[i].addr;
+
+               for (j=0; j < vcnt ; j++) {
+                       tbio->bi_io_vec[j].bv_offset = 0;
+                       tbio->bi_io_vec[j].bv_len = PAGE_SIZE;
+
+                       memcpy(page_address(tbio->bi_io_vec[j].bv_page),
+                              page_address(fbio->bi_io_vec[j].bv_page),
+                              PAGE_SIZE);
+               }
+               tbio->bi_end_io = end_sync_write;
+
+               d = r10_bio->devs[i].devnum;
+               atomic_inc(&conf->mirrors[d].rdev->nr_pending);
+               atomic_inc(&r10_bio->remaining);
+               md_sync_acct(conf->mirrors[d].rdev->bdev, tbio->bi_size >> 9);
+
+               generic_make_request(tbio);
+       }
+
+done:
+       if (atomic_dec_and_test(&r10_bio->remaining)) {
+               md_done_sync(mddev, r10_bio->sectors, 1);
+               put_buf(r10_bio);
+       }
+}
+
+/*
+ * Now for the recovery code.
+ * Recovery happens across physical sectors.
+ * We recover all non-is_sync drives by finding the virtual address of
+ * each, and then choose a working drive that also has that virt address.
+ * There is a separate r10_bio for each non-in_sync drive.
+ * Only the first two slots are in use. The first for reading,
+ * The second for writing.
+ *
+ */
+
+static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
+{
+       conf_t *conf = mddev_to_conf(mddev);
+       int i, d;
+       struct bio *bio, *wbio;
+
+
+       /* move the pages across to the second bio
+        * and submit the write request
+        */
+       bio = r10_bio->devs[0].bio;
+       wbio = r10_bio->devs[1].bio;
+       for (i=0; i < wbio->bi_vcnt; i++) {
+               struct page *p = bio->bi_io_vec[i].bv_page;
+               bio->bi_io_vec[i].bv_page = wbio->bi_io_vec[i].bv_page;
+               wbio->bi_io_vec[i].bv_page = p;
+       }
+       d = r10_bio->devs[1].devnum;
+
+       atomic_inc(&conf->mirrors[d].rdev->nr_pending);
+       md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9);
+       generic_make_request(wbio);
+}
+
+
+/*
+ * This is a kernel thread which:
+ *
+ *     1.      Retries failed read operations on working mirrors.
+ *     2.      Updates the raid superblock when problems encounter.
+ *     3.      Performs writes following reads for array syncronising.
+ */
+
+static void raid10d(mddev_t *mddev)
+{
+       r10bio_t *r10_bio;
+       struct bio *bio;
+       unsigned long flags;
+       conf_t *conf = mddev_to_conf(mddev);
+       struct list_head *head = &conf->retry_list;
+       int unplug=0;
+       mdk_rdev_t *rdev;
+
+       md_check_recovery(mddev);
+       md_handle_safemode(mddev);
+
+       for (;;) {
+               char b[BDEVNAME_SIZE];
+               spin_lock_irqsave(&conf->device_lock, flags);
+               if (list_empty(head))
+                       break;
+               r10_bio = list_entry(head->prev, r10bio_t, retry_list);
+               list_del(head->prev);
+               spin_unlock_irqrestore(&conf->device_lock, flags);
+
+               mddev = r10_bio->mddev;
+               conf = mddev_to_conf(mddev);
+               if (test_bit(R10BIO_IsSync, &r10_bio->state)) {
+                       sync_request_write(mddev, r10_bio);
+                       unplug = 1;
+               } else  if (test_bit(R10BIO_IsRecover, &r10_bio->state)) {
+                       recovery_request_write(mddev, r10_bio);
+                       unplug = 1;
+               } else {
+                       int mirror;
+                       bio = r10_bio->devs[r10_bio->read_slot].bio;
+                       r10_bio->devs[r10_bio->read_slot].bio = NULL;
+                       mirror = read_balance(conf, r10_bio);
+                       r10_bio->devs[r10_bio->read_slot].bio = bio;
+                       if (mirror == -1) {
+                               printk(KERN_ALERT "raid10: %s: unrecoverable I/O"
+                                      " read error for block %llu\n",
+                                      bdevname(bio->bi_bdev,b),
+                                      (unsigned long long)r10_bio->sector);
+                               raid_end_bio_io(r10_bio);
+                       } else {
+                               rdev = conf->mirrors[mirror].rdev;
+                               if (printk_ratelimit())
+                                       printk(KERN_ERR "raid10: %s: redirecting sector %llu to"
+                                              " another mirror\n",
+                                              bdevname(rdev->bdev,b),
+                                              (unsigned long long)r10_bio->sector);
+                               bio->bi_bdev = rdev->bdev;
+                               bio->bi_sector = r10_bio->devs[r10_bio->read_slot].addr
+                                       + rdev->data_offset;
+                               bio->bi_next = NULL;
+                               bio->bi_flags &= (1<<BIO_CLONED);
+                               bio->bi_flags |= 1 << BIO_UPTODATE;
+                               bio->bi_idx = 0;
+                               bio->bi_size = r10_bio->sectors << 9;
+                               bio->bi_rw = READ;
+                               unplug = 1;
+                               generic_make_request(bio);
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&conf->device_lock, flags);
+       if (unplug)
+               unplug_slaves(mddev);
+}
+
+
+static int init_resync(conf_t *conf)
+{
+       int buffs;
+
+       buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
+       if (conf->r10buf_pool)
+               BUG();
+       conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf);
+       if (!conf->r10buf_pool)
+               return -ENOMEM;
+       conf->next_resync = 0;
+       return 0;
+}
+
+/*
+ * perform a "sync" on one "block"
+ *
+ * We need to make sure that no normal I/O request - particularly write
+ * requests - conflict with active sync requests.
+ *
+ * This is achieved by tracking pending requests and a 'barrier' concept
+ * that can be installed to exclude normal IO requests.
+ *
+ * Resync and recovery are handled very differently.
+ * We differentiate by looking at MD_RECOVERY_SYNC in mddev->recovery.
+ *
+ * For resync, we iterate over virtual addresses, read all copies,
+ * and update if there are differences.  If only one copy is live,
+ * skip it.
+ * For recovery, we iterate over physical addresses, read a good
+ * value for each non-in_sync drive, and over-write.
+ *
+ * So, for recovery we may have several outstanding complex requests for a
+ * given address, one for each out-of-sync device.  We model this by allocating
+ * a number of r10_bio structures, one for each out-of-sync device.
+ * As we setup these structures, we collect all bio's together into a list
+ * which we then process collectively to add pages, and then process again
+ * to pass to generic_make_request.
+ *
+ * The r10_bio structures are linked using a borrowed master_bio pointer.
+ * This link is counted in ->remaining.  When the r10_bio that points to NULL
+ * has its remaining count decremented to 0, the whole complex operation
+ * is complete.
+ *
+ */
+
+static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+{
+       conf_t *conf = mddev_to_conf(mddev);
+       r10bio_t *r10_bio;
+       struct bio *biolist = NULL, *bio;
+       sector_t max_sector, nr_sectors;
+       int disk;
+       int i;
+
+       sector_t sectors_skipped = 0;
+       int chunks_skipped = 0;
+
+       if (!conf->r10buf_pool)
+               if (init_resync(conf))
+                       return -ENOMEM;
+
+ skipped:
+       max_sector = mddev->size << 1;
+       if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+               max_sector = mddev->resync_max_sectors;
+       if (sector_nr >= max_sector) {
+               close_sync(conf);
+               return sectors_skipped;
+       }
+       if (chunks_skipped >= conf->raid_disks) {
+               /* if there has been nothing to do on any drive,
+                * then there is nothing to do at all..
+                */
+               sector_t sec = max_sector - sector_nr;
+               md_done_sync(mddev, sec, 1);
+               return sec + sectors_skipped;
+       }
+
+       /* make sure whole request will fit in a chunk - if chunks
+        * are meaningful
+        */
+       if (conf->near_copies < conf->raid_disks &&
+           max_sector > (sector_nr | conf->chunk_mask))
+               max_sector = (sector_nr | conf->chunk_mask) + 1;
+       /*
+        * If there is non-resync activity waiting for us then
+        * put in a delay to throttle resync.
+        */
+       if (!go_faster && waitqueue_active(&conf->wait_resume))
+               schedule_timeout(HZ);
+       device_barrier(conf, sector_nr + RESYNC_SECTORS);
+
+       /* Again, very different code for resync and recovery.
+        * Both must result in an r10bio with a list of bios that
+        * have bi_end_io, bi_sector, bi_bdev set,
+        * and bi_private set to the r10bio.
+        * For recovery, we may actually create several r10bios
+        * with 2 bios in each, that correspond to the bios in the main one.
+        * In this case, the subordinate r10bios link back through a
+        * borrowed master_bio pointer, and the counter in the master
+        * includes a ref from each subordinate.
+        */
+       /* First, we decide what to do and set ->bi_end_io
+        * To end_sync_read if we want to read, and
+        * end_sync_write if we will want to write.
+        */
+
+       if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+               /* recovery... the complicated one */
+               int i, j, k;
+               r10_bio = NULL;
+
+               for (i=0 ; i<conf->raid_disks; i++)
+                       if (conf->mirrors[i].rdev &&
+                           !conf->mirrors[i].rdev->in_sync) {
+                               /* want to reconstruct this device */
+                               r10bio_t *rb2 = r10_bio;
+
+                               r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+                               spin_lock_irq(&conf->resync_lock);
+                               conf->nr_pending++;
+                               if (rb2) conf->barrier++;
+                               spin_unlock_irq(&conf->resync_lock);
+                               atomic_set(&r10_bio->remaining, 0);
+
+                               r10_bio->master_bio = (struct bio*)rb2;
+                               if (rb2)
+                                       atomic_inc(&rb2->remaining);
+                               r10_bio->mddev = mddev;
+                               set_bit(R10BIO_IsRecover, &r10_bio->state);
+                               r10_bio->sector = raid10_find_virt(conf, sector_nr, i);
+                               raid10_find_phys(conf, r10_bio);
+                               for (j=0; j<conf->copies;j++) {
+                                       int d = r10_bio->devs[j].devnum;
+                                       if (conf->mirrors[d].rdev &&
+                                           conf->mirrors[d].rdev->in_sync) {
+                                               /* This is where we read from */
+                                               bio = r10_bio->devs[0].bio;
+                                               bio->bi_next = biolist;
+                                               biolist = bio;
+                                               bio->bi_private = r10_bio;
+                                               bio->bi_end_io = end_sync_read;
+                                               bio->bi_rw = 0;
+                                               bio->bi_sector = r10_bio->devs[j].addr +
+                                                       conf->mirrors[d].rdev->data_offset;
+                                               bio->bi_bdev = conf->mirrors[d].rdev->bdev;
+                                               atomic_inc(&conf->mirrors[d].rdev->nr_pending);
+                                               atomic_inc(&r10_bio->remaining);
+                                               /* and we write to 'i' */
+
+                                               for (k=0; k<conf->copies; k++)
+                                                       if (r10_bio->devs[k].devnum == i)
+                                                               break;
+                                               bio = r10_bio->devs[1].bio;
+                                               bio->bi_next = biolist;
+                                               biolist = bio;
+                                               bio->bi_private = r10_bio;
+                                               bio->bi_end_io = end_sync_write;
+                                               bio->bi_rw = 1;
+                                               bio->bi_sector = r10_bio->devs[k].addr +
+                                                       conf->mirrors[i].rdev->data_offset;
+                                               bio->bi_bdev = conf->mirrors[i].rdev->bdev;
+
+                                               r10_bio->devs[0].devnum = d;
+                                               r10_bio->devs[1].devnum = i;
+
+                                               break;
+                                       }
+                               }
+                               if (j == conf->copies) {
+                                       BUG();
+                               }
+                       }
+               if (biolist == NULL) {
+                       while (r10_bio) {
+                               r10bio_t *rb2 = r10_bio;
+                               r10_bio = (r10bio_t*) rb2->master_bio;
+                               rb2->master_bio = NULL;
+                               put_buf(rb2);
+                       }
+                       goto giveup;
+               }
+       } else {
+               /* resync. Schedule a read for every block at this virt offset */
+               int count = 0;
+               r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+
+               spin_lock_irq(&conf->resync_lock);
+               conf->nr_pending++;
+               spin_unlock_irq(&conf->resync_lock);
+
+               r10_bio->mddev = mddev;
+               atomic_set(&r10_bio->remaining, 0);
+
+               r10_bio->master_bio = NULL;
+               r10_bio->sector = sector_nr;
+               set_bit(R10BIO_IsSync, &r10_bio->state);
+               raid10_find_phys(conf, r10_bio);
+               r10_bio->sectors = (sector_nr | conf->chunk_mask) - sector_nr +1;
+               spin_lock_irq(&conf->device_lock);
+               for (i=0; i<conf->copies; i++) {
+                       int d = r10_bio->devs[i].devnum;
+                       bio = r10_bio->devs[i].bio;
+                       bio->bi_end_io = NULL;
+                       if (conf->mirrors[d].rdev == NULL ||
+                           conf->mirrors[d].rdev->faulty)
+                               continue;
+                       atomic_inc(&conf->mirrors[d].rdev->nr_pending);
+                       atomic_inc(&r10_bio->remaining);
+                       bio->bi_next = biolist;
+                       biolist = bio;
+                       bio->bi_private = r10_bio;
+                       bio->bi_end_io = end_sync_read;
+                       bio->bi_rw = 0;
+                       bio->bi_sector = r10_bio->devs[i].addr +
+                               conf->mirrors[d].rdev->data_offset;
+                       bio->bi_bdev = conf->mirrors[d].rdev->bdev;
+                       count++;
+               }
+               spin_unlock_irq(&conf->device_lock);
+               if (count < 2) {
+                       for (i=0; i<conf->copies; i++) {
+                               int d = r10_bio->devs[i].devnum;
+                               if (r10_bio->devs[i].bio->bi_end_io)
+                                       atomic_dec(&conf->mirrors[d].rdev->nr_pending);
+                       }
+                       put_buf(r10_bio);
+                       goto giveup;
+               }
+       }
+
+       for (bio = biolist; bio ; bio=bio->bi_next) {
+
+               bio->bi_flags &= ~(BIO_POOL_MASK - 1);
+               if (bio->bi_end_io)
+                       bio->bi_flags |= 1 << BIO_UPTODATE;
+               bio->bi_vcnt = 0;
+               bio->bi_idx = 0;
+               bio->bi_phys_segments = 0;
+               bio->bi_hw_segments = 0;
+               bio->bi_size = 0;
+       }
+
+       nr_sectors = 0;
+       do {
+               struct page *page;
+               int len = PAGE_SIZE;
+               disk = 0;
+               if (sector_nr + (len>>9) > max_sector)
+                       len = (max_sector - sector_nr) << 9;
+               if (len == 0)
+                       break;
+               for (bio= biolist ; bio ; bio=bio->bi_next) {
+                       page = bio->bi_io_vec[bio->bi_vcnt].bv_page;
+                       if (bio_add_page(bio, page, len, 0) == 0) {
+                               /* stop here */
+                               struct bio *bio2;
+                               bio->bi_io_vec[bio->bi_vcnt].bv_page = page;
+                               for (bio2 = biolist; bio2 && bio2 != bio; bio2 = bio2->bi_next) {
+                                       /* remove last page from this bio */
+                                       bio2->bi_vcnt--;
+                                       bio2->bi_size -= len;
+                                       bio2->bi_flags &= ~(1<< BIO_SEG_VALID);
+                               }
+                               goto bio_full;
+                       }
+                       disk = i;
+               }
+               nr_sectors += len>>9;
+               sector_nr += len>>9;
+       } while (biolist->bi_vcnt < RESYNC_PAGES);
+ bio_full:
+       r10_bio->sectors = nr_sectors;
+
+       while (biolist) {
+               bio = biolist;
+               biolist = biolist->bi_next;
+
+               bio->bi_next = NULL;
+               r10_bio = bio->bi_private;
+               r10_bio->sectors = nr_sectors;
+
+               if (bio->bi_end_io == end_sync_read) {
+                       md_sync_acct(bio->bi_bdev, nr_sectors);
+                       generic_make_request(bio);
+               }
+       }
+
+       return nr_sectors;
+ giveup:
+       /* There is nowhere to write, so all non-sync
+        * drives must be failed, so try the next chunk...
+        */
+       {
+       int sec = max_sector - sector_nr;
+       sectors_skipped += sec;
+       chunks_skipped ++;
+       sector_nr = max_sector;
+       md_done_sync(mddev, sec, 1);
+       goto skipped;
+       }
+}
+
+static int run(mddev_t *mddev)
+{
+       conf_t *conf;
+       int i, disk_idx;
+       mirror_info_t *disk;
+       mdk_rdev_t *rdev;
+       struct list_head *tmp;
+       int nc, fc;
+       sector_t stride, size;
+
+       if (mddev->level != 10) {
+               printk(KERN_ERR "raid10: %s: raid level not set correctly... (%d)\n",
+                      mdname(mddev), mddev->level);
+               goto out;
+       }
+       nc = mddev->layout & 255;
+       fc = (mddev->layout >> 8) & 255;
+       if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
+           (mddev->layout >> 16)) {
+               printk(KERN_ERR "raid10: %s: unsupported raid10 layout: 0x%8x\n",
+                      mdname(mddev), mddev->layout);
+               goto out;
+       }
+       /*
+        * copy the already verified devices into our private RAID10
+        * bookkeeping area. [whatever we allocate in run(),
+        * should be freed in stop()]
+        */
+       conf = kmalloc(sizeof(conf_t), GFP_KERNEL);
+       mddev->private = conf;
+       if (!conf) {
+               printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
+                       mdname(mddev));
+               goto out;
+       }
+       memset(conf, 0, sizeof(*conf));
+       conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks,
+                                GFP_KERNEL);
+       if (!conf->mirrors) {
+               printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
+                      mdname(mddev));
+               goto out_free_conf;
+       }
+       memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks);
+
+       conf->near_copies = nc;
+       conf->far_copies = fc;
+       conf->copies = nc*fc;
+       conf->chunk_mask = (sector_t)(mddev->chunk_size>>9)-1;
+       conf->chunk_shift = ffz(~mddev->chunk_size) - 9;
+       stride = mddev->size >> (conf->chunk_shift-1);
+       sector_div(stride, fc);
+       conf->stride = stride << conf->chunk_shift;
+
+       conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
+                                               r10bio_pool_free, conf);
+       if (!conf->r10bio_pool) {
+               printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
+                       mdname(mddev));
+               goto out_free_conf;
+       }
+       mddev->queue->unplug_fn = raid10_unplug;
+
+       mddev->queue->issue_flush_fn = raid10_issue_flush;
+
+       ITERATE_RDEV(mddev, rdev, tmp) {
+               disk_idx = rdev->raid_disk;
+               if (disk_idx >= mddev->raid_disks
+                   || disk_idx < 0)
+                       continue;
+               disk = conf->mirrors + disk_idx;
+
+               disk->rdev = rdev;
+
+               blk_queue_stack_limits(mddev->queue,
+                                      rdev->bdev->bd_disk->queue);
+               /* as we don't honour merge_bvec_fn, we must never risk
+                * violating it, so limit ->max_sector to one PAGE, as
+                * a one page request is never in violation.
+                */
+               if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+                   mddev->queue->max_sectors > (PAGE_SIZE>>9))
+                       mddev->queue->max_sectors = (PAGE_SIZE>>9);
+
+               disk->head_position = 0;
+               if (!rdev->faulty && rdev->in_sync)
+                       conf->working_disks++;
+       }
+       conf->raid_disks = mddev->raid_disks;
+       conf->mddev = mddev;
+       conf->device_lock = SPIN_LOCK_UNLOCKED;
+       INIT_LIST_HEAD(&conf->retry_list);
+
+       conf->resync_lock = SPIN_LOCK_UNLOCKED;
+       init_waitqueue_head(&conf->wait_idle);
+       init_waitqueue_head(&conf->wait_resume);
+
+       if (!conf->working_disks) {
+               printk(KERN_ERR "raid10: no operational mirrors for %s\n",
+                       mdname(mddev));
+               goto out_free_conf;
+       }
+
+       mddev->degraded = 0;
+       for (i = 0; i < conf->raid_disks; i++) {
+
+               disk = conf->mirrors + i;
+
+               if (!disk->rdev) {
+                       disk->head_position = 0;
+                       mddev->degraded++;
+               }
+       }
+
+
+       mddev->thread = md_register_thread(raid10d, mddev, "%s_raid10");
+       if (!mddev->thread) {
+               printk(KERN_ERR
+                      "raid10: couldn't allocate thread for %s\n",
+                      mdname(mddev));
+               goto out_free_conf;
+       }
+
+       printk(KERN_INFO
+               "raid10: raid set %s active with %d out of %d devices\n",
+               mdname(mddev), mddev->raid_disks - mddev->degraded,
+               mddev->raid_disks);
+       /*
+        * Ok, everything is just fine now
+        */
+       size = conf->stride * conf->raid_disks;
+       sector_div(size, conf->near_copies);
+       mddev->array_size = size/2;
+       mddev->resync_max_sectors = size;
+
+       /* Calculate max read-ahead size.
+        * We need to readahead at least twice a whole stripe....
+        * maybe...
+        */
+       {
+               int stripe = conf->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE;
+               stripe /= conf->near_copies;
+               if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
+                       mddev->queue->backing_dev_info.ra_pages = 2* stripe;
+       }
+
+       if (conf->near_copies < mddev->raid_disks)
+               blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec);
+       return 0;
+
+out_free_conf:
+       if (conf->r10bio_pool)
+               mempool_destroy(conf->r10bio_pool);
+       if (conf->mirrors)
+               kfree(conf->mirrors);
+       kfree(conf);
+       mddev->private = NULL;
+out:
+       return -EIO;
+}
+
+static int stop(mddev_t *mddev)
+{
+       conf_t *conf = mddev_to_conf(mddev);
+
+       md_unregister_thread(mddev->thread);
+       mddev->thread = NULL;
+       if (conf->r10bio_pool)
+               mempool_destroy(conf->r10bio_pool);
+       if (conf->mirrors)
+               kfree(conf->mirrors);
+       kfree(conf);
+       mddev->private = NULL;
+       return 0;
+}
+
+
+static mdk_personality_t raid10_personality =
+{
+       .name           = "raid10",
+       .owner          = THIS_MODULE,
+       .make_request   = make_request,
+       .run            = run,
+       .stop           = stop,
+       .status         = status,
+       .error_handler  = error,
+       .hot_add_disk   = raid10_add_disk,
+       .hot_remove_disk= raid10_remove_disk,
+       .spare_active   = raid10_spare_active,
+       .sync_request   = sync_request,
+};
+
+static int __init raid_init(void)
+{
+       return register_md_personality(RAID10, &raid10_personality);
+}
+
+static void raid_exit(void)
+{
+       unregister_md_personality(RAID10);
+}
+
+module_init(raid_init);
+module_exit(raid_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("md-personality-9"); /* RAID10 */
index 18bc5b6..118cace 100644 (file)
@@ -1,13 +1,6 @@
 #include <linux/version.h>
 #include <media/saa7146_vv.h>
 
-/* helper function */
-static void my_wait(struct saa7146_dev *dev, long ms)
-{
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout((((ms+10)/10)*HZ)/1000);
-}
-
 u32 saa7146_i2c_func(struct i2c_adapter *adapter)
 {
 //fm   DEB_I2C(("'%s'.\n", adapter->name));
@@ -136,12 +129,12 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
                /* set "ABORT-OPERATION"-bit (bit 7)*/
                saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-               my_wait(dev,SAA7146_I2C_DELAY);
+               msleep(SAA7146_I2C_DELAY);
 
                /* clear all error-bits pending; this is needed because p.123, note 1 */
                saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-               my_wait(dev,SAA7146_I2C_DELAY);
+               msleep(SAA7146_I2C_DELAY);
        }
 
        /* check if any error is (still) present. (this can be necessary because p.123, note 1) */
@@ -155,18 +148,18 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
                   after serious protocol errors caused by e.g. the SAA7740 */
                saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-               my_wait(dev,SAA7146_I2C_DELAY);
+               msleep(SAA7146_I2C_DELAY);
 
                /* clear all error-bits pending */
                saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-               my_wait(dev,SAA7146_I2C_DELAY);
+               msleep(SAA7146_I2C_DELAY);
 
                /* the data sheet says it might be necessary to clear the status
                   twice after an abort */
                saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-               my_wait(dev,SAA7146_I2C_DELAY);
+               msleep(SAA7146_I2C_DELAY);
        }
 
        /* if any error is still present, a fatal error has occured ... */
@@ -243,7 +236,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                        if ((++trial < 20) && short_delay)
                                udelay(10);
                        else
-                       my_wait(dev,1);
+                       msleep(1);
                }
        }
 
@@ -345,7 +338,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i
                }
                
                /* delay a bit before retrying */
-               my_wait(dev, 10);
+               msleep(10);
                
        } while (err != num && retries--);
 
index 1619f4c..7f7ec33 100644 (file)
@@ -417,6 +417,8 @@ static int __devinit bt878_probe(struct pci_dev *dev,
 
        printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
               bt878_num);
+       if (pci_enable_device(dev))
+               return -EIO;
 
        bt = &bt878[bt878_num];
        bt->dev = dev;
@@ -426,11 +428,10 @@ static int __devinit bt878_probe(struct pci_dev *dev,
        bt->id = dev->device;
        bt->irq = dev->irq;
        bt->bt878_adr = pci_resource_start(dev, 0);
-       if (pci_enable_device(dev))
-               return -EIO;
        if (!request_mem_region(pci_resource_start(dev, 0),
                                pci_resource_len(dev, 0), "bt878")) {
-               return -EBUSY;
+               result = -EBUSY;
+               goto fail0;
        }
 
        pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
@@ -501,6 +502,8 @@ static int __devinit bt878_probe(struct pci_dev *dev,
       fail1:
        release_mem_region(pci_resource_start(bt->dev, 0),
                           pci_resource_len(bt->dev, 0));
+      fail0:
+       pci_disable_device(dev);
        return result;
 }
 
@@ -517,7 +520,7 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev)
 
        /* first disable interrupts before unmapping the memory! */
        btwrite(0, BT878_AINT_MASK);
-       btwrite(~0x0UL, BT878_AINT_STAT);
+       btwrite(~0U, BT878_AINT_STAT);
 
        /* disable PCI bus-mastering */
        pci_read_config_byte(bt->dev, PCI_COMMAND, &command);
@@ -540,6 +543,7 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev)
        bt878_mem_free(bt);
 
        pci_set_drvdata(pci_dev, NULL);
+       pci_disable_device(pci_dev);
        return;
 }
 
index cf165f2..8ca5b02 100644 (file)
@@ -54,9 +54,6 @@ static int debug = 0;
 /* starting point for firmware in file 'Sc_main.mc' */
 #define SP8870_FIRMWARE_OFFSET 0x0A
 
-
-static int errno;
-
 static struct dvb_frontend_info tdlb7_info = {
        .name                   = "Alps TDLB7",
        .type                   = FE_OFDM,
index 431ea92..4834db9 100644 (file)
@@ -1145,8 +1145,8 @@ static int dst_attach (struct dvb_i2c_bus *i2c, void **data)
        }
 
        dst_init (dst);
-       dprintk("%s: register dst %8.8x bt %8.8x i2c %8.8x\n", __FUNCTION__, 
-                       (u32)dst, (u32)(dst->bt), (u32)(dst->i2c));
+       dprintk("%s: register dst %p bt %p i2c %p\n", __FUNCTION__, 
+                       dst, dst->bt, dst->i2c);
 
        info = &dst_info_sat;
        if (dst->dst_type == DST_TYPE_IS_TERR)
@@ -1162,7 +1162,7 @@ static int dst_attach (struct dvb_i2c_bus *i2c, void **data)
 static void dst_detach (struct dvb_i2c_bus *i2c, void *data)
 {
        dvb_unregister_frontend (dst_ioctl, i2c);
-       dprintk("%s: unregister dst %8.8x\n", __FUNCTION__, (u32)(data));
+       dprintk("%s: unregister dst %p\n", __FUNCTION__, data);
        if (data)
                kfree(data);
 }
index 53ebf4a..0aeb812 100644 (file)
@@ -67,8 +67,6 @@ struct dvb_frontend_info sp887x_info = {
                 FE_CAN_RECOVER
 };
 
-static int errno;
-
 static
 int i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len)
 {
index 99647b5..a5ff5ec 100644 (file)
@@ -1,6 +1,6 @@
 config DVB_AV7110
        tristate "AV7110 cards"
-       depends on DVB_CORE
+       depends on DVB_CORE && PCI
        select FW_LOADER
        select VIDEO_DEV
        select VIDEO_SAA7146_VV
@@ -45,7 +45,7 @@ config DVB_AV7110_OSD
 
 config DVB_BUDGET
        tristate "Budget cards"
-       depends on DVB_CORE
+       depends on DVB_CORE && PCI
        select VIDEO_SAA7146
        help
          Support for simple SAA7146 based DVB cards
@@ -59,7 +59,7 @@ config DVB_BUDGET
 
 config DVB_BUDGET_CI
        tristate "Budget cards with onboard CI connector"
-       depends on DVB_CORE
+       depends on DVB_CORE && PCI
        select VIDEO_SAA7146
        help
          Support for simple SAA7146 based DVB cards
@@ -76,7 +76,7 @@ config DVB_BUDGET_CI
 
 config DVB_BUDGET_AV
        tristate "Budget cards with analog video inputs"
-       depends on DVB_CORE
+       depends on DVB_CORE && PCI
        select VIDEO_DEV
        select VIDEO_SAA7146_VV
        help
index 2e8403b..043468a 100644 (file)
@@ -13,7 +13,7 @@ obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o
 
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
 
-host-progs     := fdump
+hostprogs-y    := fdump
 
 ifdef CONFIG_DVB_AV7110_FIRMWARE
 $(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h 
index c6e6487..7aab2ed 100644 (file)
@@ -63,12 +63,7 @@ static void sleep_delay(long n)
        if(!d)
                udelay(n);
        else
-       {
-               /* Yield CPU time */
-               unsigned long x=jiffies;
-               while((jiffies-x)<=d)
-                       schedule();
-       }
+               msleep(jiffies_to_msecs(d));
 }
 
 static void rt_decvol(void)
index 6a18c00..b226aa4 100644 (file)
@@ -93,27 +93,6 @@ static struct radio_device
        struct  semaphore lock;
 } radio_unit = {0, 0, 0, 0, };
 
-static void sleep_125ms(void)
-{
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(HZ >> 3);
-}
-
-static void udelay2(void)
-{
-       udelay(2);
-}
-
-static void udelay4(void)
-{
-       udelay(4);
-}
-
-static void udelay16(void)
-{
-       udelay(16);
-}
-
 static __u32 radio_bits_get(struct radio_device *dev)
 {
        register __u16 io=dev->io, l, rdata;
@@ -122,14 +101,15 @@ static __u32 radio_bits_get(struct radio_device *dev)
        omask = inw(io + IO_MASK);
        outw(~(STR_CLK | STR_WREN), io + IO_MASK);
        outw(0, io);
-       udelay16();
+       udelay(16);
+
        for (l=24;l--;) {
                outw(STR_CLK, io);              /* HI state */
-               udelay2();
+               udelay(2);
                if(!l) 
                        dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff;
                outw(0, io);                    /* LO state */
-               udelay2();
+               udelay(2);
                data <<= 1;                     /* shift data */
                rdata = inw(io);
                if(!l)
@@ -138,11 +118,11 @@ static __u32 radio_bits_get(struct radio_device *dev)
                else
                        if(rdata & STR_DATA)
                                data++;
-               udelay2();
+               udelay(2);
        }
        if(dev->muted)
                outw(STR_WREN, io);
-       udelay4();
+       udelay(4);
        outw(omask, io + IO_MASK);
        return data & 0x3ffe;
 }
@@ -155,23 +135,23 @@ static void radio_bits_set(struct radio_device *dev, __u32 data)
        odir  = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
        outw(odir | STR_DATA, io + IO_DIR);
        outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK);
-       udelay16();
+       udelay(16);
        for (l=25;l;l--) {
                bits = ((data >> 18) & STR_DATA) | STR_WREN ;
                data <<= 1;                     /* shift data */
                outw(bits, io);                 /* start strobe */
-               udelay2();
+               udelay(2);
                outw(bits | STR_CLK, io);       /* HI level */
-               udelay2();   
+               udelay(2);
                outw(bits, io);                 /* LO level */
-               udelay4();
+               udelay(4);
        }
        if(!dev->muted)
                outw(0, io);
-       udelay4();
+       udelay(4);
        outw(omask, io + IO_MASK);
        outw(odir, io + IO_DIR);
-       sleep_125ms();
+       msleep(125);
 }
 
 inline static int radio_function(struct inode *inode, struct file *file,
@@ -238,9 +218,9 @@ inline static int radio_function(struct inode *inode, struct file *file,
                                outw(~STR_WREN, io + IO_MASK);
                                outw((card->muted = v->flags & VIDEO_AUDIO_MUTE)
                                     ? STR_WREN : 0, io);
-                               udelay4();
+                               udelay(4);
                                outw(omask, io + IO_MASK);
-                               sleep_125ms();
+                               msleep(125);
                                return 0;
                        }
                }
@@ -270,7 +250,7 @@ static int radio_ioctl(struct inode *inode, struct file *file,
        return ret;
 }
 
-inline static __u16 radio_install(struct pci_dev *pcidev);
+static __u16 radio_install(struct pci_dev *pcidev);
 
 MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
 MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
@@ -315,7 +295,7 @@ inline static __u16 radio_power_on(struct radio_device *dev)
        outw(odir, io + IO_DIR);
        outw(~(STR_WREN | STR_CLK), io + IO_MASK);
        outw(dev->muted ? 0 : STR_WREN, io);
-       udelay16();
+       udelay(16);
        outw(omask, io + IO_MASK);
        ofreq = radio_bits_get(dev);
        if((ofreq<FREQ2BITS(FREQ_LO)) || (ofreq>FREQ2BITS(FREQ_HI)))
@@ -324,7 +304,7 @@ inline static __u16 radio_power_on(struct radio_device *dev)
        return (ofreq == radio_bits_get(dev));
 }
 
-inline static __u16 radio_install(struct pci_dev *pcidev)
+static __u16 radio_install(struct pci_dev *pcidev)
 {
        if(((pcidev->class >> 8) & 0xffff) != PCI_CLASS_MULTIMEDIA_AUDIO)
                return 0;
index c2fa20d..c3c6209 100644 (file)
@@ -104,13 +104,6 @@ static struct radio_device
 } radio_unit = {0, 0, 0, 0, };
 
 
-static void sleep_125ms(void)
-{
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(HZ >> 3);
-}
-
-
 static void outbit(unsigned long bit, __u16 io)
 {
        if(bit != 0)
@@ -228,7 +221,7 @@ inline static int radio_function(struct inode *inode, struct file *file,
                                return -EINVAL;
                        card->freq = *freq;
                        set_freq(card->io, FREQ2BITS(card->freq));
-                       sleep_125ms();
+                       msleep(125);
                        return 0;
                }
                case VIDIOCGAUDIO: {    
index 9962c43..f0575fb 100644 (file)
@@ -89,8 +89,7 @@ static inline int fmi_setfreq(struct fmi_device *dev)
 
        outbits(16, RSF16_ENCODE(freq), myport);
        outbits(8, 0xC0, myport);
-       current->state = TASK_UNINTERRUPTIBLE;
-       schedule_timeout(HZ/7);
+       msleep(143);            /* was schedule_timeout(HZ/7) */
        up(&lock);
        if (dev->curvol) fmi_unmute(myport);
        return 0;
@@ -107,8 +106,7 @@ static inline int fmi_getsigstr(struct fmi_device *dev)
        val = dev->curvol ? 0x08 : 0x00;        /* unmute/mute */
        outb(val, myport);
        outb(val | 0x10, myport);
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(HZ/7);
+       msleep(143);            /* was schedule_timeout(HZ/7) */
        res = (int)inb(myport+1);
        outb(val, myport);
        
index aa49c8e..7e980d1 100644 (file)
@@ -55,19 +55,6 @@ static int radio_nr = -1;
 #define RSF16_MINFREQ 87*16000
 #define RSF16_MAXFREQ 108*16000
 
-/* from radio-aimslab */
-static void sleep_delay(unsigned long n)
-{
-       unsigned d=n/(1000000U/HZ);
-       if (!d)
-               udelay(n);
-       else
-       {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(d);
-       }
-}
-
 static inline void wait(int n,int port)
 {
        for (;n;--n) inb(port);
@@ -153,7 +140,7 @@ static int fmr2_setfreq(struct fmr2_device *dev)
        fmr2_unmute(port);
 
        /* wait 0.11 sec */
-       sleep_delay(110000LU);
+       msleep(110);
 
        /* NOTE if mute this stop radio
           you must set freq on unmute */
index 16bfdb9..74fefc2 100644 (file)
@@ -156,6 +156,22 @@ adv7175_write_block (struct i2c_client *client,
        return ret;
 }
 
+static void
+set_subcarrier_freq (struct i2c_client *client,
+                    int                pass_through)
+{
+       /* for some reason pass_through NTSC needs
+        * a different sub-carrier freq to remain stable. */
+       if(pass_through)
+               adv7175_write(client, 0x02, 0x00);
+       else
+               adv7175_write(client, 0x02, 0x55);
+
+       adv7175_write(client, 0x03, 0x55);
+       adv7175_write(client, 0x04, 0x55);
+       adv7175_write(client, 0x05, 0x25);
+}
+
 #ifdef ENCODER_DUMP
 static void
 dump (struct i2c_client *client)
@@ -322,6 +338,10 @@ adv7175_command (struct i2c_client *client,
 
                case 0:
                        adv7175_write(client, 0x01, 0x00);
+
+                       if (encoder->norm == VIDEO_MODE_NTSC)
+                               set_subcarrier_freq(client, 1);
+
                        adv7175_write(client, 0x0c, TR1CAPT);   /* TR1 */
                        if (encoder->norm == VIDEO_MODE_SECAM)
                                adv7175_write(client, 0x0d, 0x49);      // Disable genlock
@@ -334,6 +354,10 @@ adv7175_command (struct i2c_client *client,
 
                case 1:
                        adv7175_write(client, 0x01, 0x00);
+
+                       if (encoder->norm == VIDEO_MODE_NTSC)
+                               set_subcarrier_freq(client, 0);
+
                        adv7175_write(client, 0x0c, TR1PLAY);   /* TR1 */
                        adv7175_write(client, 0x0d, 0x49);
                        adv7175_write(client, 0x07, TR0MODE | TR0RST);
@@ -343,6 +367,10 @@ adv7175_command (struct i2c_client *client,
 
                case 2:
                        adv7175_write(client, 0x01, 0x80);
+
+                       if (encoder->norm == VIDEO_MODE_NTSC)
+                               set_subcarrier_freq(client, 0);
+
                        adv7175_write(client, 0x0d, 0x49);
                        adv7175_write(client, 0x07, TR0MODE | TR0RST);
                        adv7175_write(client, 0x07, TR0MODE);
index 01ce7bc..585f67d 100644 (file)
@@ -106,6 +106,20 @@ void bttv_gpio_irq(struct bttv_core *core)
        }
 }
 
+void bttv_i2c_info(struct bttv_core *core, struct i2c_client *client, int attach)
+{
+       struct bttv_sub_driver *drv;
+       struct bttv_sub_device *dev;
+       struct list_head *item;
+
+       list_for_each(item,&core->subs) {
+               dev = list_entry(item,struct bttv_sub_device,list);
+               drv = to_bttv_sub_drv(dev->dev.driver);
+               if (drv && drv->i2c_info)
+                       drv->i2c_info(dev,client,attach);
+       }
+}
+
 /* ----------------------------------------------------------------------- */
 /* external: sub-driver register/unregister                                */
 
index 705cff8..a35d518 100644 (file)
@@ -1105,8 +1105,7 @@ zr36057_enable_jpg (struct zoran          *zr,
                        ZR36057_ISR);
                btand(~ZR36057_JMC_Go_en, ZR36057_JMC); // \Go_en
 
-               current->state = TASK_UNINTERRUPTIBLE;
-               schedule_timeout(HZ / 20);
+               msleep(50);
 
                set_videobus_dir(zr, 0);
                set_frame(zr, 1);       // /FRAME
index b709839..f6fdcaa 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the LSI Logic Fusion MPT (Message Passing Technology) drivers.
 #
 # Note! If you want to turn on various debug defines for an extended period of
-# time but don't want them lingering around in the Makefile when you pass it on 
+# time but don't want them lingering around in the Makefile when you pass it on
 # to someone else, use the MPT_CFLAGS env variable (thanks Steve). -nromer
 
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-{ LSI_LOGIC
@@ -48,6 +48,5 @@ EXTRA_CFLAGS += ${MPT_CFLAGS}
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
 
 obj-$(CONFIG_FUSION)           += mptbase.o mptscsih.o
-obj-$(CONFIG_FUSION_ISENSE)    += isense.o
 obj-$(CONFIG_FUSION_CTL)       += mptctl.o
 obj-$(CONFIG_FUSION_LAN)       += mptlan.o
diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c
new file mode 100644 (file)
index 0000000..7227a8a
--- /dev/null
@@ -0,0 +1,571 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/i2o.h>
+
+static int verbose;
+extern struct i2o_driver **i2o_drivers;
+extern unsigned int i2o_max_drivers;
+static void i2o_report_util_cmd(u8 cmd);
+static void i2o_report_exec_cmd(u8 cmd);
+void i2o_report_fail_status(u8 req_status, u32 * msg);
+void i2o_report_common_status(u8 req_status);
+static void i2o_report_common_dsc(u16 detailed_status);
+
+void i2o_dump_status_block(i2o_status_block * sb)
+{
+       pr_debug("Organization ID: %d\n", sb->org_id);
+       pr_debug("IOP ID:          %d\n", sb->iop_id);
+       pr_debug("Host Unit ID:    %d\n", sb->host_unit_id);
+       pr_debug("Segment Number:  %d\n", sb->segment_number);
+       pr_debug("I2O Version:     %d\n", sb->i2o_version);
+       pr_debug("IOP State:       %d\n", sb->iop_state);
+       pr_debug("Messanger Type:  %d\n", sb->msg_type);
+       pr_debug("Inbound Frame Size:      %d\n", sb->inbound_frame_size);
+       pr_debug("Init Code:               %d\n", sb->init_code);
+       pr_debug("Max Inbound MFrames:     %d\n", sb->max_inbound_frames);
+       pr_debug("Current Inbound MFrames: %d\n", sb->cur_inbound_frames);
+       pr_debug("Max Outbound MFrames:    %d\n", sb->max_outbound_frames);
+       pr_debug("Product ID String: %s\n", sb->product_id);
+       pr_debug("Expected LCT Size: %d\n", sb->expected_lct_size);
+       pr_debug("IOP Capabilities:  %d\n", sb->iop_capabilities);
+       pr_debug("Desired Private MemSize: %d\n", sb->desired_mem_size);
+       pr_debug("Current Private MemSize: %d\n", sb->current_mem_size);
+       pr_debug("Current Private MemBase: %d\n", sb->current_mem_base);
+       pr_debug("Desired Private IO Size: %d\n", sb->desired_io_size);
+       pr_debug("Current Private IO Size: %d\n", sb->current_io_size);
+       pr_debug("Current Private IO Base: %d\n", sb->current_io_base);
+};
+
+/*
+ * Used for error reporting/debugging purposes.
+ * Report Cmd name, Request status, Detailed Status.
+ */
+void i2o_report_status(const char *severity, const char *str,
+                      struct i2o_message *m)
+{
+       u32 *msg = (u32 *) m;
+       u8 cmd = (msg[1] >> 24) & 0xFF;
+       u8 req_status = (msg[4] >> 24) & 0xFF;
+       u16 detailed_status = msg[4] & 0xFFFF;
+       //struct i2o_driver *h = i2o_drivers[msg[2] & (i2o_max_drivers-1)];
+
+       if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
+               return;         // No status in this reply
+
+       printk("%s%s: ", severity, str);
+
+       if (cmd < 0x1F)         // Utility cmd
+               i2o_report_util_cmd(cmd);
+
+       else if (cmd >= 0xA0 && cmd <= 0xEF)    // Executive cmd
+               i2o_report_exec_cmd(cmd);
+       else
+               printk("Cmd = %0#2x, ", cmd);   // Other cmds
+
+       if (msg[0] & MSG_FAIL) {
+               i2o_report_fail_status(req_status, msg);
+               return;
+       }
+
+       i2o_report_common_status(req_status);
+
+       if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF))
+               i2o_report_common_dsc(detailed_status);
+       else
+               printk(" / DetailedStatus = %0#4x.\n", detailed_status);
+}
+
+/* Used to dump a message to syslog during debugging */
+void i2o_dump_message(struct i2o_message *m)
+{
+#ifdef DEBUG
+       u32 *msg = (u32 *) m;
+       int i;
+       printk(KERN_INFO "Dumping I2O message size %d @ %p\n",
+              msg[0] >> 16 & 0xffff, msg);
+       for (i = 0; i < ((msg[0] >> 16) & 0xffff); i++)
+               printk(KERN_INFO "  msg[%d] = %0#10x\n", i, msg[i]);
+#endif
+}
+
+/**
+ *     i2o_report_controller_unit - print information about a tid
+ *     @c: controller
+ *     @d: device
+ *
+ *     Dump an information block associated with a given unit (TID). The
+ *     tables are read and a block of text is output to printk that is
+ *     formatted intended for the user.
+ */
+
+void i2o_report_controller_unit(struct i2o_controller *c, struct i2o_device *d)
+{
+       char buf[64];
+       char str[22];
+       int ret;
+
+       if (verbose == 0)
+               return;
+
+       printk(KERN_INFO "Target ID %03x.\n", d->lct_data.tid);
+       if ((ret = i2o_parm_field_get(d, 0xF100, 3, buf, 16)) >= 0) {
+               buf[16] = 0;
+               printk(KERN_INFO "     Vendor: %s\n", buf);
+       }
+       if ((ret = i2o_parm_field_get(d, 0xF100, 4, buf, 16)) >= 0) {
+               buf[16] = 0;
+               printk(KERN_INFO "     Device: %s\n", buf);
+       }
+       if (i2o_parm_field_get(d, 0xF100, 5, buf, 16) >= 0) {
+               buf[16] = 0;
+               printk(KERN_INFO "     Description: %s\n", buf);
+       }
+       if ((ret = i2o_parm_field_get(d, 0xF100, 6, buf, 8)) >= 0) {
+               buf[8] = 0;
+               printk(KERN_INFO "        Rev: %s\n", buf);
+       }
+
+       printk(KERN_INFO "    Class: ");
+       //sprintf(str, "%-21s", i2o_get_class_name(d->lct_data.class_id));
+       printk("%s\n", str);
+
+       printk(KERN_INFO "  Subclass: 0x%04X\n", d->lct_data.sub_class);
+       printk(KERN_INFO "     Flags: ");
+
+       if (d->lct_data.device_flags & (1 << 0))
+               printk("C");    // ConfigDialog requested
+       if (d->lct_data.device_flags & (1 << 1))
+               printk("U");    // Multi-user capable
+       if (!(d->lct_data.device_flags & (1 << 4)))
+               printk("P");    // Peer service enabled!
+       if (!(d->lct_data.device_flags & (1 << 5)))
+               printk("M");    // Mgmt service enabled!
+       printk("\n");
+}
+
+/*
+MODULE_PARM(verbose, "i");
+MODULE_PARM_DESC(verbose, "Verbose diagnostics");
+*/
+/*
+ * Used for error reporting/debugging purposes.
+ * Following fail status are common to all classes.
+ * The preserved message must be handled in the reply handler.
+ */
+void i2o_report_fail_status(u8 req_status, u32 * msg)
+{
+       static char *FAIL_STATUS[] = {
+               "0x80",         /* not used */
+               "SERVICE_SUSPENDED",    /* 0x81 */
+               "SERVICE_TERMINATED",   /* 0x82 */
+               "CONGESTION",
+               "FAILURE",
+               "STATE_ERROR",
+               "TIME_OUT",
+               "ROUTING_FAILURE",
+               "INVALID_VERSION",
+               "INVALID_OFFSET",
+               "INVALID_MSG_FLAGS",
+               "FRAME_TOO_SMALL",
+               "FRAME_TOO_LARGE",
+               "INVALID_TARGET_ID",
+               "INVALID_INITIATOR_ID",
+               "INVALID_INITIATOR_CONTEX",     /* 0x8F */
+               "UNKNOWN_FAILURE"       /* 0xFF */
+       };
+
+       if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE)
+               printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x)\n.", req_status);
+       else
+               printk("TRANSPORT_%s.\n", FAIL_STATUS[req_status & 0x0F]);
+
+       /* Dump some details */
+
+       printk(KERN_ERR "  InitiatorId = %d, TargetId = %d\n",
+              (msg[1] >> 12) & 0xFFF, msg[1] & 0xFFF);
+       printk(KERN_ERR "  LowestVersion = 0x%02X, HighestVersion = 0x%02X\n",
+              (msg[4] >> 8) & 0xFF, msg[4] & 0xFF);
+       printk(KERN_ERR "  FailingHostUnit = 0x%04X,  FailingIOP = 0x%03X\n",
+              msg[5] >> 16, msg[5] & 0xFFF);
+
+       printk(KERN_ERR "  Severity:  0x%02X ", (msg[4] >> 16) & 0xFF);
+       if (msg[4] & (1 << 16))
+               printk("(FormatError), "
+                      "this msg can never be delivered/processed.\n");
+       if (msg[4] & (1 << 17))
+               printk("(PathError), "
+                      "this msg can no longer be delivered/processed.\n");
+       if (msg[4] & (1 << 18))
+               printk("(PathState), "
+                      "the system state does not allow delivery.\n");
+       if (msg[4] & (1 << 19))
+               printk("(Congestion), resources temporarily not available;"
+                      "do not retry immediately.\n");
+}
+
+/*
+ * Used for error reporting/debugging purposes.
+ * Following reply status are common to all classes.
+ */
+void i2o_report_common_status(u8 req_status)
+{
+       static char *REPLY_STATUS[] = {
+               "SUCCESS",
+               "ABORT_DIRTY",
+               "ABORT_NO_DATA_TRANSFER",
+               "ABORT_PARTIAL_TRANSFER",
+               "ERROR_DIRTY",
+               "ERROR_NO_DATA_TRANSFER",
+               "ERROR_PARTIAL_TRANSFER",
+               "PROCESS_ABORT_DIRTY",
+               "PROCESS_ABORT_NO_DATA_TRANSFER",
+               "PROCESS_ABORT_PARTIAL_TRANSFER",
+               "TRANSACTION_ERROR",
+               "PROGRESS_REPORT"
+       };
+
+       if (req_status >= ARRAY_SIZE(REPLY_STATUS))
+               printk("RequestStatus = %0#2x", req_status);
+       else
+               printk("%s", REPLY_STATUS[req_status]);
+}
+
+/*
+ * Used for error reporting/debugging purposes.
+ * Following detailed status are valid  for executive class,
+ * utility class, DDM class and for transaction error replies.
+ */
+static void i2o_report_common_dsc(u16 detailed_status)
+{
+       static char *COMMON_DSC[] = {
+               "SUCCESS",
+               "0x01",         // not used
+               "BAD_KEY",
+               "TCL_ERROR",
+               "REPLY_BUFFER_FULL",
+               "NO_SUCH_PAGE",
+               "INSUFFICIENT_RESOURCE_SOFT",
+               "INSUFFICIENT_RESOURCE_HARD",
+               "0x08",         // not used
+               "CHAIN_BUFFER_TOO_LARGE",
+               "UNSUPPORTED_FUNCTION",
+               "DEVICE_LOCKED",
+               "DEVICE_RESET",
+               "INAPPROPRIATE_FUNCTION",
+               "INVALID_INITIATOR_ADDRESS",
+               "INVALID_MESSAGE_FLAGS",
+               "INVALID_OFFSET",
+               "INVALID_PARAMETER",
+               "INVALID_REQUEST",
+               "INVALID_TARGET_ADDRESS",
+               "MESSAGE_TOO_LARGE",
+               "MESSAGE_TOO_SMALL",
+               "MISSING_PARAMETER",
+               "TIMEOUT",
+               "UNKNOWN_ERROR",
+               "UNKNOWN_FUNCTION",
+               "UNSUPPORTED_VERSION",
+               "DEVICE_BUSY",
+               "DEVICE_NOT_AVAILABLE"
+       };
+
+       if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE)
+               printk(" / DetailedStatus = %0#4x.\n", detailed_status);
+       else
+               printk(" / %s.\n", COMMON_DSC[detailed_status]);
+}
+
+/*
+ * Used for error reporting/debugging purposes
+ */
+static void i2o_report_util_cmd(u8 cmd)
+{
+       switch (cmd) {
+       case I2O_CMD_UTIL_NOP:
+               printk("UTIL_NOP, ");
+               break;
+       case I2O_CMD_UTIL_ABORT:
+               printk("UTIL_ABORT, ");
+               break;
+       case I2O_CMD_UTIL_CLAIM:
+               printk("UTIL_CLAIM, ");
+               break;
+       case I2O_CMD_UTIL_RELEASE:
+               printk("UTIL_CLAIM_RELEASE, ");
+               break;
+       case I2O_CMD_UTIL_CONFIG_DIALOG:
+               printk("UTIL_CONFIG_DIALOG, ");
+               break;
+       case I2O_CMD_UTIL_DEVICE_RESERVE:
+               printk("UTIL_DEVICE_RESERVE, ");
+               break;
+       case I2O_CMD_UTIL_DEVICE_RELEASE:
+               printk("UTIL_DEVICE_RELEASE, ");
+               break;
+       case I2O_CMD_UTIL_EVT_ACK:
+               printk("UTIL_EVENT_ACKNOWLEDGE, ");
+               break;
+       case I2O_CMD_UTIL_EVT_REGISTER:
+               printk("UTIL_EVENT_REGISTER, ");
+               break;
+       case I2O_CMD_UTIL_LOCK:
+               printk("UTIL_LOCK, ");
+               break;
+       case I2O_CMD_UTIL_LOCK_RELEASE:
+               printk("UTIL_LOCK_RELEASE, ");
+               break;
+       case I2O_CMD_UTIL_PARAMS_GET:
+               printk("UTIL_PARAMS_GET, ");
+               break;
+       case I2O_CMD_UTIL_PARAMS_SET:
+               printk("UTIL_PARAMS_SET, ");
+               break;
+       case I2O_CMD_UTIL_REPLY_FAULT_NOTIFY:
+               printk("UTIL_REPLY_FAULT_NOTIFY, ");
+               break;
+       default:
+               printk("Cmd = %0#2x, ", cmd);
+       }
+}
+
+/*
+ * Used for error reporting/debugging purposes
+ */
+static void i2o_report_exec_cmd(u8 cmd)
+{
+       switch (cmd) {
+       case I2O_CMD_ADAPTER_ASSIGN:
+               printk("EXEC_ADAPTER_ASSIGN, ");
+               break;
+       case I2O_CMD_ADAPTER_READ:
+               printk("EXEC_ADAPTER_READ, ");
+               break;
+       case I2O_CMD_ADAPTER_RELEASE:
+               printk("EXEC_ADAPTER_RELEASE, ");
+               break;
+       case I2O_CMD_BIOS_INFO_SET:
+               printk("EXEC_BIOS_INFO_SET, ");
+               break;
+       case I2O_CMD_BOOT_DEVICE_SET:
+               printk("EXEC_BOOT_DEVICE_SET, ");
+               break;
+       case I2O_CMD_CONFIG_VALIDATE:
+               printk("EXEC_CONFIG_VALIDATE, ");
+               break;
+       case I2O_CMD_CONN_SETUP:
+               printk("EXEC_CONN_SETUP, ");
+               break;
+       case I2O_CMD_DDM_DESTROY:
+               printk("EXEC_DDM_DESTROY, ");
+               break;
+       case I2O_CMD_DDM_ENABLE:
+               printk("EXEC_DDM_ENABLE, ");
+               break;
+       case I2O_CMD_DDM_QUIESCE:
+               printk("EXEC_DDM_QUIESCE, ");
+               break;
+       case I2O_CMD_DDM_RESET:
+               printk("EXEC_DDM_RESET, ");
+               break;
+       case I2O_CMD_DDM_SUSPEND:
+               printk("EXEC_DDM_SUSPEND, ");
+               break;
+       case I2O_CMD_DEVICE_ASSIGN:
+               printk("EXEC_DEVICE_ASSIGN, ");
+               break;
+       case I2O_CMD_DEVICE_RELEASE:
+               printk("EXEC_DEVICE_RELEASE, ");
+               break;
+       case I2O_CMD_HRT_GET:
+               printk("EXEC_HRT_GET, ");
+               break;
+       case I2O_CMD_ADAPTER_CLEAR:
+               printk("EXEC_IOP_CLEAR, ");
+               break;
+       case I2O_CMD_ADAPTER_CONNECT:
+               printk("EXEC_IOP_CONNECT, ");
+               break;
+       case I2O_CMD_ADAPTER_RESET:
+               printk("EXEC_IOP_RESET, ");
+               break;
+       case I2O_CMD_LCT_NOTIFY:
+               printk("EXEC_LCT_NOTIFY, ");
+               break;
+       case I2O_CMD_OUTBOUND_INIT:
+               printk("EXEC_OUTBOUND_INIT, ");
+               break;
+       case I2O_CMD_PATH_ENABLE:
+               printk("EXEC_PATH_ENABLE, ");
+               break;
+       case I2O_CMD_PATH_QUIESCE:
+               printk("EXEC_PATH_QUIESCE, ");
+               break;
+       case I2O_CMD_PATH_RESET:
+               printk("EXEC_PATH_RESET, ");
+               break;
+       case I2O_CMD_STATIC_MF_CREATE:
+               printk("EXEC_STATIC_MF_CREATE, ");
+               break;
+       case I2O_CMD_STATIC_MF_RELEASE:
+               printk("EXEC_STATIC_MF_RELEASE, ");
+               break;
+       case I2O_CMD_STATUS_GET:
+               printk("EXEC_STATUS_GET, ");
+               break;
+       case I2O_CMD_SW_DOWNLOAD:
+               printk("EXEC_SW_DOWNLOAD, ");
+               break;
+       case I2O_CMD_SW_UPLOAD:
+               printk("EXEC_SW_UPLOAD, ");
+               break;
+       case I2O_CMD_SW_REMOVE:
+               printk("EXEC_SW_REMOVE, ");
+               break;
+       case I2O_CMD_SYS_ENABLE:
+               printk("EXEC_SYS_ENABLE, ");
+               break;
+       case I2O_CMD_SYS_MODIFY:
+               printk("EXEC_SYS_MODIFY, ");
+               break;
+       case I2O_CMD_SYS_QUIESCE:
+               printk("EXEC_SYS_QUIESCE, ");
+               break;
+       case I2O_CMD_SYS_TAB_SET:
+               printk("EXEC_SYS_TAB_SET, ");
+               break;
+       default:
+               printk("Cmd = %#02x, ", cmd);
+       }
+}
+
+void i2o_debug_state(struct i2o_controller *c)
+{
+       printk(KERN_INFO "%s: State = ", c->name);
+       switch (((i2o_status_block *) c->status_block.virt)->iop_state) {
+       case 0x01:
+               printk("INIT\n");
+               break;
+       case 0x02:
+               printk("RESET\n");
+               break;
+       case 0x04:
+               printk("HOLD\n");
+               break;
+       case 0x05:
+               printk("READY\n");
+               break;
+       case 0x08:
+               printk("OPERATIONAL\n");
+               break;
+       case 0x10:
+               printk("FAILED\n");
+               break;
+       case 0x11:
+               printk("FAULTED\n");
+               break;
+       default:
+               printk("%x (unknown !!)\n",
+                      ((i2o_status_block *) c->status_block.virt)->iop_state);
+       }
+};
+
+void i2o_systab_debug(struct i2o_sys_tbl *sys_tbl)
+{
+       u32 *table;
+       int count;
+       u32 size;
+
+       table = (u32 *) sys_tbl;
+       size = sizeof(struct i2o_sys_tbl) + sys_tbl->num_entries
+           * sizeof(struct i2o_sys_tbl_entry);
+
+       for (count = 0; count < (size >> 2); count++)
+               printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", count, table[count]);
+}
+
+void i2o_dump_hrt(struct i2o_controller *c)
+{
+       u32 *rows = (u32 *) c->hrt.virt;
+       u8 *p = (u8 *) c->hrt.virt;
+       u8 *d;
+       int count;
+       int length;
+       int i;
+       int state;
+
+       if (p[3] != 0) {
+               printk(KERN_ERR
+                      "%s: HRT table for controller is too new a version.\n",
+                      c->name);
+               return;
+       }
+
+       count = p[0] | (p[1] << 8);
+       length = p[2];
+
+       printk(KERN_INFO "%s: HRT has %d entries of %d bytes each.\n",
+              c->name, count, length << 2);
+
+       rows += 2;
+
+       for (i = 0; i < count; i++) {
+               printk(KERN_INFO "Adapter %08X: ", rows[0]);
+               p = (u8 *) (rows + 1);
+               d = (u8 *) (rows + 2);
+               state = p[1] << 8 | p[0];
+
+               printk("TID %04X:[", state & 0xFFF);
+               state >>= 12;
+               if (state & (1 << 0))
+                       printk("H");    /* Hidden */
+               if (state & (1 << 2)) {
+                       printk("P");    /* Present */
+                       if (state & (1 << 1))
+                               printk("C");    /* Controlled */
+               }
+               if (state > 9)
+                       printk("*");    /* Hard */
+
+               printk("]:");
+
+               switch (p[3] & 0xFFFF) {
+               case 0:
+                       /* Adapter private bus - easy */
+                       printk("Local bus %d: I/O at 0x%04X Mem 0x%08X",
+                              p[2], d[1] << 8 | d[0], *(u32 *) (d + 4));
+                       break;
+               case 1:
+                       /* ISA bus */
+                       printk("ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X",
+                              p[2], d[2], d[1] << 8 | d[0], *(u32 *) (d + 4));
+                       break;
+
+               case 2: /* EISA bus */
+                       printk("EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X",
+                              p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4));
+                       break;
+
+               case 3: /* MCA bus */
+                       printk("MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X",
+                              p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4));
+                       break;
+
+               case 4: /* PCI bus */
+                       printk("PCI %d: Bus %d Device %d Function %d",
+                              p[2], d[2], d[1], d[0]);
+                       break;
+
+               case 0x80:      /* Other */
+               default:
+                       printk("Unsupported bus type.");
+                       break;
+               }
+               printk("\n");
+               rows += length;
+       }
+}
+
+EXPORT_SYMBOL(i2o_dump_status_block);
+EXPORT_SYMBOL(i2o_dump_message);
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
new file mode 100644 (file)
index 0000000..ff4822e
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+ *     Functions to handle I2O devices
+ *
+ *     Copyright (C) 2004      Markus Lidel <Markus.Lidel@shadowconnect.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.
+ *
+ *     Fixes/additions:
+ *             Markus Lidel <Markus.Lidel@shadowconnect.com>
+ *                     initial version.
+ */
+
+#include <linux/module.h>
+#include <linux/i2o.h>
+
+/* Exec OSM functions */
+extern struct bus_type i2o_bus_type;
+
+/**
+ *     i2o_device_issue_claim - claim or release a device
+ *     @dev: I2O device to claim or release
+ *     @cmd: claim or release command
+ *     @type: type of claim
+ *
+ *     Issue I2O UTIL_CLAIM or UTIL_RELEASE messages. The message to be sent
+ *     is set by cmd. dev is the I2O device which should be claim or
+ *     released and the type is the claim type (see the I2O spec).
+ *
+ *     Returs 0 on success or negative error code on failure.
+ */
+static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd,
+                                        u32 type)
+{
+       struct i2o_message *msg;
+       u32 m;
+
+       m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+       if (m == I2O_QUEUE_EMPTY)
+               return -ETIMEDOUT;
+
+       writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+       writel(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid, &msg->u.head[1]);
+       writel(type, &msg->body[0]);
+
+       return i2o_msg_post_wait(dev->iop, m, 60);
+};
+
+/**
+ *     i2o_device_claim - claim a device for use by an OSM
+ *     @dev: I2O device to claim
+ *     @drv: I2O driver which wants to claim the device
+ *
+ *     Do the leg work to assign a device to a given OSM. If the claim succeed
+ *     the owner of the rimary. If the attempt fails a negative errno code
+ *     is returned. On success zero is returned.
+ */
+int i2o_device_claim(struct i2o_device *dev)
+{
+       int rc = 0;
+
+       down(&dev->lock);
+
+       rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY);
+       if (!rc)
+               pr_debug("claim of device %d succeded\n", dev->lct_data.tid);
+       else
+               pr_debug("claim of device %d failed %d\n", dev->lct_data.tid,
+                        rc);
+
+       up(&dev->lock);
+
+       return rc;
+};
+
+/**
+ *     i2o_device_claim_release - release a device that the OSM is using
+ *     @dev: device to release
+ *     @drv: driver which claimed the device
+ *
+ *     Drop a claim by an OSM on a given I2O device.
+ *
+ *     AC - some devices seem to want to refuse an unclaim until they have
+ *     finished internal processing. It makes sense since you don't want a
+ *     new device to go reconfiguring the entire system until you are done.
+ *     Thus we are prepared to wait briefly.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+int i2o_device_claim_release(struct i2o_device *dev)
+{
+       int tries;
+       int rc = 0;
+
+       down(&dev->lock);
+
+       /*
+        *      If the controller takes a nonblocking approach to
+        *      releases we have to sleep/poll for a few times.
+        */
+       for (tries = 0; tries < 10; tries++) {
+               rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_RELEASE,
+                                           I2O_CLAIM_PRIMARY);
+               if (!rc)
+                       break;
+
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(HZ);
+       }
+
+       if (!rc)
+               pr_debug("claim release of device %d succeded\n",
+                        dev->lct_data.tid);
+       else
+               pr_debug("claim release of device %d failed %d\n",
+                        dev->lct_data.tid, rc);
+
+       up(&dev->lock);
+
+       return rc;
+};
+
+/**
+ *     i2o_device_release - release the memory for a I2O device
+ *     @dev: I2O device which should be released
+ *
+ *     Release the allocated memory. This function is called if refcount of
+ *     device reaches 0 automatically.
+ */
+static void i2o_device_release(struct device *dev)
+{
+       struct i2o_device *i2o_dev = to_i2o_device(dev);
+
+       pr_debug("Release I2O device %s\n", dev->bus_id);
+
+       kfree(i2o_dev);
+};
+
+/**
+ *     i2o_device_class_release - Remove I2O device attributes
+ *     @cd: I2O class device which is added to the I2O device class
+ *
+ *     Removes attributes from the I2O device again. Also search each device
+ *     on the controller for I2O devices which refert to this device as parent
+ *     or user and remove this links also.
+ */
+static void i2o_device_class_release(struct class_device *cd)
+{
+       struct i2o_device *i2o_dev, *tmp;
+       struct i2o_controller *c;
+
+       i2o_dev = to_i2o_device(cd->dev);
+       c = i2o_dev->iop;
+
+       sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+       sysfs_remove_link(&i2o_dev->device.kobj, "user");
+
+       list_for_each_entry(tmp, &c->devices, list) {
+               if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+                       sysfs_remove_link(&tmp->device.kobj, "parent");
+               if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+                       sysfs_remove_link(&tmp->device.kobj, "user");
+       }
+};
+
+/* I2O device class */
+static struct class i2o_device_class = {
+       .name = "i2o_device",
+       .release = i2o_device_class_release
+};
+
+/**
+ *     i2o_device_alloc - Allocate a I2O device and initialize it
+ *
+ *     Allocate the memory for a I2O device and initialize locks and lists
+ *
+ *     Returns the allocated I2O device or a negative error code if the device
+ *     could not be allocated.
+ */
+static struct i2o_device *i2o_device_alloc(void)
+{
+       struct i2o_device *dev;
+
+       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       memset(dev, 0, sizeof(*dev));
+
+       INIT_LIST_HEAD(&dev->list);
+       init_MUTEX(&dev->lock);
+
+       dev->device.bus = &i2o_bus_type;
+       dev->device.release = &i2o_device_release;
+       dev->classdev.class = &i2o_device_class;
+       dev->classdev.dev = &dev->device;
+
+       return dev;
+};
+
+/**
+ *     i2o_device_add - allocate a new I2O device and add it to the IOP
+ *     @iop: I2O controller where the device is on
+ *     @entry: LCT entry of the I2O device
+ *
+ *     Allocate a new I2O device and initialize it with the LCT entry. The
+ *     device is appended to the device list of the controller.
+ *
+ *     Returns a pointer to the I2O device on success or negative error code
+ *     on failure.
+ */
+struct i2o_device *i2o_device_add(struct i2o_controller *c,
+                                 i2o_lct_entry * entry)
+{
+       struct i2o_device *dev;
+
+       dev = i2o_device_alloc();
+       if (IS_ERR(dev)) {
+               printk(KERN_ERR "i2o: unable to allocate i2o device\n");
+               return dev;
+       }
+
+       dev->lct_data = *entry;
+
+       snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
+                dev->lct_data.tid);
+
+       snprintf(dev->classdev.class_id, BUS_ID_SIZE, "%d:%03x", c->unit,
+                dev->lct_data.tid);
+
+       dev->iop = c;
+       dev->device.parent = &c->device;
+
+       device_register(&dev->device);
+
+       list_add_tail(&dev->list, &c->devices);
+
+       class_device_register(&dev->classdev);
+
+       i2o_driver_notify_device_add_all(dev);
+
+       pr_debug("I2O device %s added\n", dev->device.bus_id);
+
+       return dev;
+};
+
+/**
+ *     i2o_device_remove - remove an I2O device from the I2O core
+ *     @dev: I2O device which should be released
+ *
+ *     Is used on I2O controller removal or LCT modification, when the device
+ *     is removed from the system. Note that the device could still hang
+ *     around until the refcount reaches 0.
+ */
+void i2o_device_remove(struct i2o_device *i2o_dev)
+{
+       i2o_driver_notify_device_remove_all(i2o_dev);
+       class_device_unregister(&i2o_dev->classdev);
+       list_del(&i2o_dev->list);
+       device_unregister(&i2o_dev->device);
+};
+
+/**
+ *     i2o_device_parse_lct - Parse a previously fetched LCT and create devices
+ *     @c: I2O controller from which the LCT should be parsed.
+ *
+ *     The Logical Configuration Table tells us what we can talk to on the
+ *     board. For every entry we create an I2O device, which is registered in
+ *     the I2O core.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+int i2o_device_parse_lct(struct i2o_controller *c)
+{
+       struct i2o_device *dev, *tmp;
+       i2o_lct *lct;
+       int i;
+       int max;
+
+       down(&c->lct_lock);
+
+       if (c->lct)
+               kfree(c->lct);
+
+       lct = c->dlct.virt;
+
+       c->lct = kmalloc(lct->table_size * 4, GFP_KERNEL);
+       if (!c->lct) {
+               up(&c->lct_lock);
+               return -ENOMEM;
+       }
+
+       if (lct->table_size * 4 > c->dlct.len) {
+               memcpy_fromio(c->lct, c->dlct.virt, c->dlct.len);
+               up(&c->lct_lock);
+               return -EAGAIN;
+       }
+
+       memcpy_fromio(c->lct, c->dlct.virt, lct->table_size * 4);
+
+       lct = c->lct;
+
+       max = (lct->table_size - 3) / 9;
+
+       pr_debug("LCT has %d entries (LCT size: %d)\n", max, lct->table_size);
+
+       /* remove devices, which are not in the LCT anymore */
+       list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+               int found = 0;
+
+               for (i = 0; i < max; i++) {
+                       if (lct->lct_entry[i].tid == dev->lct_data.tid) {
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (!found)
+                       i2o_device_remove(dev);
+       }
+
+       /* add new devices, which are new in the LCT */
+       for (i = 0; i < max; i++) {
+               int found = 0;
+
+               list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+                       if (lct->lct_entry[i].tid == dev->lct_data.tid) {
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (!found)
+                       i2o_device_add(c, &lct->lct_entry[i]);
+       }
+       up(&c->lct_lock);
+
+       return 0;
+};
+
+/**
+ *     i2o_device_class_show_class_id - Displays class id of I2O device
+ *     @cd: class device of which the class id should be displayed
+ *     @buf: buffer into which the class id should be printed
+ *
+ *     Returns the number of bytes which are printed into the buffer.
+ */
+static ssize_t i2o_device_class_show_class_id(struct class_device *cd,
+                                             char *buf)
+{
+       struct i2o_device *dev = to_i2o_device(cd->dev);
+
+       sprintf(buf, "%03x\n", dev->lct_data.class_id);
+       return strlen(buf) + 1;
+};
+
+/**
+ *     i2o_device_class_show_tid - Displays TID of I2O device
+ *     @cd: class device of which the TID should be displayed
+ *     @buf: buffer into which the class id should be printed
+ *
+ *     Returns the number of bytes which are printed into the buffer.
+ */
+static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf)
+{
+       struct i2o_device *dev = to_i2o_device(cd->dev);
+
+       sprintf(buf, "%03x\n", dev->lct_data.tid);
+       return strlen(buf) + 1;
+};
+
+/* I2O device class attributes */
+static CLASS_DEVICE_ATTR(class_id, S_IRUGO, i2o_device_class_show_class_id,
+                        NULL);
+static CLASS_DEVICE_ATTR(tid, S_IRUGO, i2o_device_class_show_tid, NULL);
+
+/**
+ *     i2o_device_class_add - Adds attributes to the I2O device
+ *     @cd: I2O class device which is added to the I2O device class
+ *
+ *     This function get called when a I2O device is added to the class. It
+ *     creates the attributes for each device and creates user/parent symlink
+ *     if necessary.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+static int i2o_device_class_add(struct class_device *cd)
+{
+       struct i2o_device *i2o_dev, *tmp;
+       struct i2o_controller *c;
+
+       i2o_dev = to_i2o_device(cd->dev);
+       c = i2o_dev->iop;
+
+       class_device_create_file(cd, &class_device_attr_class_id);
+       class_device_create_file(cd, &class_device_attr_tid);
+
+       /* create user entries for this device */
+       tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
+       if (tmp)
+               sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
+                                 "user");
+
+       /* create user entries refering to this device */
+       list_for_each_entry(tmp, &c->devices, list)
+           if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+               sysfs_create_link(&tmp->device.kobj,
+                                 &i2o_dev->device.kobj, "user");
+
+       /* create parent entries for this device */
+       tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
+       if (tmp)
+               sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
+                                 "parent");
+
+       /* create parent entries refering to this device */
+       list_for_each_entry(tmp, &c->devices, list)
+           if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+               sysfs_create_link(&tmp->device.kobj,
+                                 &i2o_dev->device.kobj, "parent");
+
+       return 0;
+};
+
+/* I2O device class interface */
+static struct class_interface i2o_device_class_interface = {
+       .class = &i2o_device_class,
+       .add = i2o_device_class_add
+};
+
+/*
+ *     Run time support routines
+ */
+
+/*     Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
+ *
+ *     This function can be used for all UtilParamsGet/Set operations.
+ *     The OperationList is given in oplist-buffer,
+ *     and results are returned in reslist-buffer.
+ *     Note that the minimum sized reslist is 8 bytes and contains
+ *     ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
+ */
+
+int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
+                  int oplen, void *reslist, int reslen)
+{
+       struct i2o_message *msg;
+       u32 m;
+       u32 *res32 = (u32 *) reslist;
+       u32 *restmp = (u32 *) reslist;
+       int len = 0;
+       int i = 0;
+       int rc;
+       struct i2o_dma res;
+       struct i2o_controller *c = i2o_dev->iop;
+       struct device *dev = &c->pdev->dev;
+
+       res.virt = NULL;
+
+       if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL))
+               return -ENOMEM;
+
+       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+       if (m == I2O_QUEUE_EMPTY) {
+               i2o_dma_free(dev, &res);
+               return -ETIMEDOUT;
+       }
+
+       i = 0;
+       writel(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid,
+              &msg->u.head[1]);
+       writel(0, &msg->body[i++]);
+       writel(0x4C000000 | oplen, &msg->body[i++]);    /* OperationList */
+       memcpy_toio(&msg->body[i], oplist, oplen);
+       i += (oplen / 4 + (oplen % 4 ? 1 : 0));
+       writel(0xD0000000 | res.len, &msg->body[i++]);  /* ResultList */
+       writel(res.phys, &msg->body[i++]);
+
+       writel(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) |
+              SGL_OFFSET_5, &msg->u.head[0]);
+
+       rc = i2o_msg_post_wait_mem(c, m, 10, &res);
+
+       /* This only looks like a memory leak - don't "fix" it. */
+       if (rc == -ETIMEDOUT)
+               return rc;
+
+       memcpy_fromio(reslist, res.virt, res.len);
+       i2o_dma_free(dev, &res);
+
+       /* Query failed */
+       if (rc)
+               return rc;
+       /*
+        * Calculate number of bytes of Result LIST
+        * We need to loop through each Result BLOCK and grab the length
+        */
+       restmp = res32 + 1;
+       len = 1;
+       for (i = 0; i < (res32[0] & 0X0000FFFF); i++) {
+               if (restmp[0] & 0x00FF0000) {   /* BlockStatus != SUCCESS */
+                       printk(KERN_WARNING
+                              "%s - Error:\n  ErrorInfoSize = 0x%02x, "
+                              "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
+                              (cmd ==
+                               I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" :
+                              "PARAMS_GET", res32[1] >> 24,
+                              (res32[1] >> 16) & 0xFF, res32[1] & 0xFFFF);
+
+                       /*
+                        *      If this is the only request,than we return an error
+                        */
+                       if ((res32[0] & 0x0000FFFF) == 1) {
+                               return -((res32[1] >> 16) & 0xFF);      /* -BlockStatus */
+                       }
+               }
+               len += restmp[0] & 0x0000FFFF;  /* Length of res BLOCK */
+               restmp += restmp[0] & 0x0000FFFF;       /* Skip to next BLOCK */
+       }
+       return (len << 2);      /* bytes used by result list */
+}
+
+/*
+ *      Query one field group value or a whole scalar group.
+ */
+int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
+                      void *buf, int buflen)
+{
+       u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
+       u8 resblk[8 + buflen];  /* 8 bytes for header */
+       int size;
+
+       if (field == -1)        /* whole group */
+               opblk[4] = -1;
+
+       size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
+                             sizeof(opblk), resblk, sizeof(resblk));
+
+       memcpy(buf, resblk + 8, buflen);        /* cut off header */
+
+       if (size > buflen)
+               return buflen;
+
+       return size;
+}
+
+/*
+ *     Set a scalar group value or a whole group.
+ */
+int i2o_parm_field_set(struct i2o_device *i2o_dev, int group, int field,
+                      void *buf, int buflen)
+{
+       u16 *opblk;
+       u8 resblk[8 + buflen];  /* 8 bytes for header */
+       int size;
+
+       opblk = kmalloc(buflen + 64, GFP_KERNEL);
+       if (opblk == NULL) {
+               printk(KERN_ERR "i2o: no memory for operation buffer.\n");
+               return -ENOMEM;
+       }
+
+       opblk[0] = 1;           /* operation count */
+       opblk[1] = 0;           /* pad */
+       opblk[2] = I2O_PARAMS_FIELD_SET;
+       opblk[3] = group;
+
+       if (field == -1) {      /* whole group */
+               opblk[4] = -1;
+               memcpy(opblk + 5, buf, buflen);
+       } else {                /* single field */
+
+               opblk[4] = 1;
+               opblk[5] = field;
+               memcpy(opblk + 6, buf, buflen);
+       }
+
+       size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_SET, opblk,
+                             12 + buflen, resblk, sizeof(resblk));
+
+       kfree(opblk);
+       if (size > buflen)
+               return buflen;
+
+       return size;
+}
+
+/*
+ *     if oper == I2O_PARAMS_TABLE_GET, get from all rows
+ *             if fieldcount == -1 return all fields
+ *                     ibuf and ibuflen are unused (use NULL, 0)
+ *             else return specific fields
+ *                     ibuf contains fieldindexes
+ *
+ *     if oper == I2O_PARAMS_LIST_GET, get from specific rows
+ *             if fieldcount == -1 return all fields
+ *                     ibuf contains rowcount, keyvalues
+ *             else return specific fields
+ *                     fieldcount is # of fieldindexes
+ *                     ibuf contains fieldindexes, rowcount, keyvalues
+ *
+ *     You could also use directly function i2o_issue_params().
+ */
+int i2o_parm_table_get(struct i2o_device *dev, int oper, int group,
+                      int fieldcount, void *ibuf, int ibuflen, void *resblk,
+                      int reslen)
+{
+       u16 *opblk;
+       int size;
+
+       size = 10 + ibuflen;
+       if (size % 4)
+               size += 4 - size % 4;
+
+       opblk = kmalloc(size, GFP_KERNEL);
+       if (opblk == NULL) {
+               printk(KERN_ERR "i2o: no memory for query buffer.\n");
+               return -ENOMEM;
+       }
+
+       opblk[0] = 1;           /* operation count */
+       opblk[1] = 0;           /* pad */
+       opblk[2] = oper;
+       opblk[3] = group;
+       opblk[4] = fieldcount;
+       memcpy(opblk + 5, ibuf, ibuflen);       /* other params */
+
+       size = i2o_parm_issue(dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
+                             size, resblk, reslen);
+
+       kfree(opblk);
+       if (size > reslen)
+               return reslen;
+
+       return size;
+}
+
+/**
+ *     i2o_device_init - Initialize I2O devices
+ *
+ *     Registers the I2O device class.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+int i2o_device_init(void)
+{
+       int rc;
+
+       rc = class_register(&i2o_device_class);
+       if (rc)
+               return rc;
+
+       return class_interface_register(&i2o_device_class_interface);
+};
+
+/**
+ *     i2o_device_exit - I2O devices exit function
+ *
+ *     Unregisters the I2O device class.
+ */
+void i2o_device_exit(void)
+{
+       class_interface_register(&i2o_device_class_interface);
+       class_unregister(&i2o_device_class);
+};
+
+EXPORT_SYMBOL(i2o_device_claim);
+EXPORT_SYMBOL(i2o_device_claim_release);
+EXPORT_SYMBOL(i2o_parm_field_get);
+EXPORT_SYMBOL(i2o_parm_field_set);
+EXPORT_SYMBOL(i2o_parm_table_get);
+EXPORT_SYMBOL(i2o_parm_issue);
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
new file mode 100644 (file)
index 0000000..bc69d66
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ *     Functions to handle I2O drivers (OSMs) and I2O bus type for sysfs
+ *
+ *     Copyright (C) 2004      Markus Lidel <Markus.Lidel@shadowconnect.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.
+ *
+ *     Fixes/additions:
+ *             Markus Lidel <Markus.Lidel@shadowconnect.com>
+ *                     initial version.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/rwsem.h>
+#include <linux/i2o.h>
+
+
+/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
+unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
+module_param_named(max_drivers, i2o_max_drivers, uint, 0);
+MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support");
+
+/* I2O drivers lock and array */
+static spinlock_t i2o_drivers_lock = SPIN_LOCK_UNLOCKED;
+static struct i2o_driver **i2o_drivers;
+
+/**
+ *     i2o_bus_match - Tell if a I2O device class id match the class ids of
+ *                     the I2O driver (OSM)
+ *
+ *     @dev: device which should be verified
+ *     @drv: the driver to match against
+ *
+ *     Used by the bus to check if the driver wants to handle the device.
+ *
+ *     Returns 1 if the class ids of the driver match the class id of the
+ *     device, otherwise 0.
+ */
+static int i2o_bus_match(struct device *dev, struct device_driver *drv)
+{
+       struct i2o_device *i2o_dev = to_i2o_device(dev);
+       struct i2o_driver *i2o_drv = to_i2o_driver(drv);
+       struct i2o_class_id *ids = i2o_drv->classes;
+
+       if (ids)
+               while (ids->class_id != I2O_CLASS_END) {
+                       if (ids->class_id == i2o_dev->lct_data.class_id)
+                               return 1;
+                       ids++;
+               }
+       return 0;
+};
+
+/* I2O bus type */
+struct bus_type i2o_bus_type = {
+       .name = "i2o",
+       .match = i2o_bus_match,
+};
+
+/**
+ *     i2o_driver_register - Register a I2O driver (OSM) in the I2O core
+ *     @drv: I2O driver which should be registered
+ *
+ *     Registers the OSM drv in the I2O core and creates an event queues if
+ *     necessary.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+int i2o_driver_register(struct i2o_driver *drv)
+{
+       struct i2o_controller *c;
+       int i;
+       int rc = 0;
+       unsigned long flags;
+
+       pr_debug("Register driver %s\n", drv->name);
+
+       if (drv->event) {
+               drv->event_queue = create_workqueue(drv->name);
+               if (!drv->event_queue) {
+                       printk(KERN_ERR "i2o: Could not initialize event queue "
+                              "for driver %s\n", drv->name);
+                       return -EFAULT;
+               }
+               pr_debug("Event queue initialized for driver %s\n", drv->name);
+       } else
+               drv->event_queue = NULL;
+
+       drv->driver.name = drv->name;
+       drv->driver.bus = &i2o_bus_type;
+
+       spin_lock_irqsave(&i2o_drivers_lock, flags);
+
+       for (i = 0; i2o_drivers[i]; i++)
+               if (i >= i2o_max_drivers) {
+                       printk(KERN_ERR "i2o: too many drivers registered, "
+                              "increase max_drivers\n");
+                       spin_unlock_irqrestore(&i2o_drivers_lock, flags);
+                       return -EFAULT;
+               }
+
+       drv->context = i;
+       i2o_drivers[i] = drv;
+
+       spin_unlock_irqrestore(&i2o_drivers_lock, flags);
+
+       pr_debug("driver %s gets context id %d\n", drv->name, drv->context);
+
+       list_for_each_entry(c, &i2o_controllers, list) {
+               struct i2o_device *i2o_dev;
+
+               i2o_driver_notify_controller_add(drv, c);
+               list_for_each_entry(i2o_dev, &c->devices, list)
+                       i2o_driver_notify_device_add(drv, i2o_dev);
+       }
+
+
+       rc = driver_register(&drv->driver);
+       if (rc)
+               destroy_workqueue(drv->event_queue);
+
+       return rc;
+};
+
+/**
+ *     i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core
+ *     @drv: I2O driver which should be unregistered
+ *
+ *     Unregisters the OSM drv from the I2O core and cleanup event queues if
+ *     necessary.
+ */
+void i2o_driver_unregister(struct i2o_driver *drv)
+{
+       struct i2o_controller *c;
+       unsigned long flags;
+
+       pr_debug("unregister driver %s\n", drv->name);
+
+       driver_unregister(&drv->driver);
+
+       list_for_each_entry(c, &i2o_controllers, list) {
+               struct i2o_device *i2o_dev;
+
+               list_for_each_entry(i2o_dev, &c->devices, list)
+                       i2o_driver_notify_device_remove(drv, i2o_dev);
+
+               i2o_driver_notify_controller_remove(drv, c);
+       }
+
+       spin_lock_irqsave(&i2o_drivers_lock, flags);
+       i2o_drivers[drv->context] = NULL;
+       spin_unlock_irqrestore(&i2o_drivers_lock, flags);
+
+       if (drv->event_queue) {
+               destroy_workqueue(drv->event_queue);
+               drv->event_queue = NULL;
+               pr_debug("event queue removed for %s\n", drv->name);
+       }
+};
+
+/**
+ *     i2o_driver_dispatch - dispatch an I2O reply message
+ *     @c: I2O controller of the message
+ *     @m: I2O message number
+ *     @msg: I2O message to be delivered
+ *
+ *     The reply is delivered to the driver from which the original message
+ *     was. This function is only called from interrupt context.
+ *
+ *     Returns 0 on success and the message should not be flushed. Returns > 0
+ *     on success and if the message should be flushed afterwords. Returns
+ *     negative error code on failure (the message will be flushed too).
+ */
+int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
+                       struct i2o_message *msg)
+{
+       struct i2o_driver *drv;
+       u32 context = readl(&msg->u.s.icntxt);
+
+       if (likely(context < i2o_max_drivers)) {
+               spin_lock(&i2o_drivers_lock);
+               drv = i2o_drivers[context];
+               spin_unlock(&i2o_drivers_lock);
+
+               if (unlikely(!drv)) {
+                       printk(KERN_WARNING "i2o: Spurious reply to unknown "
+                              "driver %d\n", context);
+                       return -EIO;
+               }
+
+               if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
+                       struct i2o_device *dev, *tmp;
+                       struct i2o_event *evt;
+                       u16 size;
+                       u16 tid;
+
+                       tid = readl(&msg->u.head[1]) & 0x1fff;
+
+                       pr_debug("%s: event received from device %d\n", c->name,
+                                tid);
+
+                       /* cut of header from message size (in 32-bit words) */
+                       size = (readl(&msg->u.head[0]) >> 16) - 5;
+
+                       evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
+                       if (!evt)
+                               return -ENOMEM;
+                       memset(evt, 0, size * 4 + sizeof(*evt));
+
+                       evt->size = size;
+                       memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt,
+                                     (size + 2) * 4);
+
+                       list_for_each_entry_safe(dev, tmp, &c->devices, list)
+                           if (dev->lct_data.tid == tid) {
+                               evt->i2o_dev = dev;
+                               break;
+                       }
+
+                       INIT_WORK(&evt->work, (void (*)(void *))drv->event,
+                                 evt);
+                       queue_work(drv->event_queue, &evt->work);
+                       return 1;
+               }
+
+               if (likely(drv->reply))
+                       return drv->reply(c, m, msg);
+               else
+                       pr_debug("%s: Reply to driver %s, but no reply function"
+                                " defined!\n", c->name, drv->name);
+               return -EIO;
+       } else
+               printk(KERN_WARNING "i2o: Spurious reply to unknown driver "
+                      "%d\n", readl(&msg->u.s.icntxt));
+       return -EIO;
+}
+
+/**
+ *     i2o_driver_notify_controller_add_all - Send notify of added controller
+ *                                            to all I2O drivers
+ *
+ *     Send notifications to all registered drivers that a new controller was
+ *     added.
+ */
+void i2o_driver_notify_controller_add_all(struct i2o_controller *c) {
+       int i;
+       struct i2o_driver *drv;
+
+       for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
+               drv = i2o_drivers[i];
+
+               if(drv)
+                       i2o_driver_notify_controller_add(drv, c);
+       }
+}
+
+/**
+ *     i2o_driver_notify_controller_remove_all - Send notify of removed
+ *                                               controller to all I2O drivers
+ *
+ *     Send notifications to all registered drivers that a controller was
+ *     removed.
+ */
+void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) {
+       int i;
+       struct i2o_driver *drv;
+
+       for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
+               drv = i2o_drivers[i];
+
+               if(drv)
+                       i2o_driver_notify_controller_remove(drv, c);
+       }
+}
+
+/**
+ *     i2o_driver_notify_device_add_all - Send notify of added device to all
+ *                                        I2O drivers
+ *
+ *     Send notifications to all registered drivers that a device was added.
+ */
+void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) {
+       int i;
+       struct i2o_driver *drv;
+
+       for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
+               drv = i2o_drivers[i];
+
+               if(drv)
+                       i2o_driver_notify_device_add(drv, i2o_dev);
+       }
+}
+
+/**
+ *     i2o_driver_notify_device_remove_all - Send notify of removed device to
+ *                                           all I2O drivers
+ *
+ *     Send notifications to all registered drivers that a device was removed.
+ */
+void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) {
+       int i;
+       struct i2o_driver *drv;
+
+       for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
+               drv = i2o_drivers[i];
+
+               if(drv)
+                       i2o_driver_notify_device_remove(drv, i2o_dev);
+       }
+}
+
+/**
+ *     i2o_driver_init - initialize I2O drivers (OSMs)
+ *
+ *     Registers the I2O bus and allocate memory for the array of OSMs.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+int __init i2o_driver_init(void)
+{
+       int rc = 0;
+
+       if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
+           ((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
+            (2 * i2o_max_drivers - 1))) {
+               printk(KERN_WARNING "i2o: max_drivers set to %d, but must be "
+                      ">=2 and <= 64 and a power of 2\n", i2o_max_drivers);
+               i2o_max_drivers = I2O_MAX_DRIVERS;
+       }
+       printk(KERN_INFO "i2o: max_drivers=%d\n", i2o_max_drivers);
+
+       i2o_drivers =
+           kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
+       if (!i2o_drivers)
+               return -ENOMEM;
+
+       memset(i2o_drivers, 0, i2o_max_drivers * sizeof(*i2o_drivers));
+
+       rc = bus_register(&i2o_bus_type);
+
+       if (rc < 0)
+               kfree(i2o_drivers);
+
+       return rc;
+};
+
+/**
+ *     i2o_driver_exit - clean up I2O drivers (OSMs)
+ *
+ *     Unregisters the I2O bus and free driver array.
+ */
+void __exit i2o_driver_exit(void)
+{
+       bus_unregister(&i2o_bus_type);
+       kfree(i2o_drivers);
+};
+
+EXPORT_SYMBOL(i2o_driver_register);
+EXPORT_SYMBOL(i2o_driver_unregister);
+EXPORT_SYMBOL(i2o_driver_notify_controller_add_all);
+EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all);
+EXPORT_SYMBOL(i2o_driver_notify_device_add_all);
+EXPORT_SYMBOL(i2o_driver_notify_device_remove_all);
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
new file mode 100644 (file)
index 0000000..117f261
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+ *     Executive OSM
+ *
+ *     Copyright (C) 1999-2002 Red Hat Software
+ *
+ *     Written by Alan Cox, Building Number Three Ltd
+ *
+ *     This program is free software; you can redistribute 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.
+ *
+ *     A lot of the I2O message side code from this is taken from the Red
+ *     Creek RCPCI45 adapter driver by Red Creek Communications
+ *
+ *     Fixes/additions:
+ *             Philipp Rumpf
+ *             Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ *             Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
+ *             Deepak Saxena <deepak@plexity.net>
+ *             Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
+ *             Alan Cox <alan@redhat.com>:
+ *                     Ported to Linux 2.5.
+ *             Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *                     Minor fixes for 2.6.
+ *             Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *                     Support for sysfs included.
+ */
+
+#include <linux/module.h>
+#include <linux/i2o.h>
+
+struct i2o_driver i2o_exec_driver;
+
+/* Module internal functions from other sources */
+extern int i2o_device_parse_lct(struct i2o_controller *);
+
+/* global wait list for POST WAIT */
+static LIST_HEAD(i2o_exec_wait_list);
+
+/* Wait struct needed for POST WAIT */
+struct i2o_exec_wait {
+       wait_queue_head_t *wq;  /* Pointer to Wait queue */
+       struct i2o_dma dma;     /* DMA buffers to free on failure */
+       u32 tcntxt;             /* transaction context from reply */
+       int complete;           /* 1 if reply received otherwise 0 */
+       u32 m;                  /* message id */
+       struct i2o_message *msg;        /* pointer to the reply message */
+       struct list_head list;  /* node in global wait list */
+};
+
+/* Exec OSM class handling definition */
+static struct i2o_class_id i2o_exec_class_id[] = {
+       {I2O_CLASS_EXECUTIVE},
+       {I2O_CLASS_END}
+};
+
+/**
+ *     i2o_exec_wait_alloc - Allocate a i2o_exec_wait struct an initialize it
+ *
+ *     Allocate the i2o_exec_wait struct and initialize the wait.
+ *
+ *     Returns i2o_exec_wait pointer on success or negative error code on
+ *     failure.
+ */
+static struct i2o_exec_wait *i2o_exec_wait_alloc(void)
+{
+       struct i2o_exec_wait *wait;
+
+       wait = kmalloc(sizeof(*wait), GFP_KERNEL);
+       if (!wait)
+               return ERR_PTR(-ENOMEM);
+
+       memset(wait, 0, sizeof(*wait));
+
+       INIT_LIST_HEAD(&wait->list);
+
+       return wait;
+};
+
+/**
+ *     i2o_exec_wait_free - Free a i2o_exec_wait struct
+ *     @i2o_exec_wait: I2O wait data which should be cleaned up
+ */
+static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
+{
+       kfree(wait);
+};
+
+/**
+ *     i2o_msg_post_wait_mem - Post and wait a message with DMA buffers
+ *     @c: controller
+ *     @m: message to post
+ *     @timeout: time in seconds to wait
+ *     @dma: i2o_dma struct of the DMA buffer to free on failure
+ *
+ *     This API allows an OSM to post a message and then be told whether or
+ *     not the system received a successful reply. If the message times out
+ *     then the value '-ETIMEDOUT' is returned. This is a special case. In
+ *     this situation the message may (should) complete at an indefinite time
+ *     in the future. When it completes it will use the memory buffer
+ *     attached to the request. If -ETIMEDOUT is returned then the memory
+ *     buffer must not be freed. Instead the event completion will free them
+ *     for you. In all other cases the buffer are your problem.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
+                         timeout, struct i2o_dma *dma)
+{
+       DECLARE_WAIT_QUEUE_HEAD(wq);
+       DEFINE_WAIT(wait);
+       struct i2o_exec_wait *iwait;
+       static u32 tcntxt = 0x80000000;
+       struct i2o_message *msg = c->in_queue.virt + m;
+       int rc = 0;
+
+       iwait = i2o_exec_wait_alloc();
+       if (!iwait)
+               return -ENOMEM;
+
+       if (tcntxt == 0xffffffff)
+               tcntxt = 0x80000000;
+
+       if (dma)
+               iwait->dma = *dma;
+
+       /*
+        * Fill in the message initiator context and transaction context.
+        * We will only use transaction contexts >= 0x80000000 for POST WAIT,
+        * so we could find a POST WAIT reply easier in the reply handler.
+        */
+       writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+       iwait->tcntxt = tcntxt++;
+       writel(iwait->tcntxt, &msg->u.s.tcntxt);
+
+       /*
+        * Post the message to the controller. At some point later it will
+        * return. If we time out before it returns then complete will be zero.
+        */
+       i2o_msg_post(c, m);
+
+       if (!iwait->complete) {
+               iwait->wq = &wq;
+               /*
+                * we add elements add the head, because if a entry in the list
+                * will never be removed, we have to iterate over it every time
+                */
+               list_add(&iwait->list, &i2o_exec_wait_list);
+
+               prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
+
+               if (!iwait->complete)
+                       schedule_timeout(timeout * HZ);
+
+               finish_wait(&wq, &wait);
+
+               iwait->wq = NULL;
+       }
+
+       barrier();
+
+       if (iwait->complete) {
+               if (readl(&iwait->msg->body[0]) >> 24)
+                       rc = readl(&iwait->msg->body[0]) & 0xff;
+               i2o_flush_reply(c, iwait->m);
+               i2o_exec_wait_free(iwait);
+       } else {
+               /*
+                * We cannot remove it now. This is important. When it does
+                * terminate (which it must do if the controller has not
+                * died...) then it will otherwise scribble on stuff.
+                *
+                * FIXME: try abort message
+                */
+               if (dma)
+                       dma->virt = NULL;
+
+               rc = -ETIMEDOUT;
+       }
+
+       return rc;
+};
+
+/**
+ *     i2o_msg_post_wait_complete - Reply to a i2o_msg_post request from IOP
+ *     @c: I2O controller which answers
+ *     @m: message id
+ *     @msg: pointer to the I2O reply message
+ *
+ *     This function is called in interrupt context only. If the reply reached
+ *     before the timeout, the i2o_exec_wait struct is filled with the message
+ *     and the task will be waked up. The task is now responsible for returning
+ *     the message m back to the controller! If the message reaches us after
+ *     the timeout clean up the i2o_exec_wait struct (including allocated
+ *     DMA buffer).
+ *
+ *     Return 0 on success and if the message m should not be given back to the
+ *     I2O controller, or >0 on success and if the message should be given back
+ *     afterwords. Returns negative error code on failure. In this case the
+ *     message must also be given back to the controller.
+ */
+static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
+                                     struct i2o_message *msg)
+{
+       struct i2o_exec_wait *wait, *tmp;
+       static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+       int rc = 1;
+       u32 context;
+
+       context = readl(&msg->u.s.tcntxt);
+
+       /*
+        * We need to search through the i2o_exec_wait_list to see if the given
+        * message is still outstanding. If not, it means that the IOP took
+        * longer to respond to the message than we had allowed and timer has
+        * already expired. Not much we can do about that except log it for
+        * debug purposes, increase timeout, and recompile.
+        */
+       spin_lock(&lock);
+       list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {
+               if (wait->tcntxt == context) {
+                       list_del(&wait->list);
+
+                       wait->m = m;
+                       wait->msg = msg;
+                       wait->complete = 1;
+
+                       barrier();
+
+                       if (wait->wq) {
+                               wake_up_interruptible(wait->wq);
+                               rc = 0;
+                       } else {
+                               struct device *dev;
+
+                               dev = &c->pdev->dev;
+
+                               pr_debug("timedout reply received!\n");
+                               i2o_dma_free(dev, &wait->dma);
+                               i2o_exec_wait_free(wait);
+                               rc = -1;
+                       }
+
+                       spin_unlock(&lock);
+
+                       return rc;
+               }
+       }
+
+       spin_unlock(&lock);
+
+       pr_debug("i2o: Bogus reply in POST WAIT (tr-context: %08x)!\n",
+                context);
+
+       return -1;
+};
+
+/**
+ *     i2o_exec_probe - Called if a new I2O device (executive class) appears
+ *     @dev: I2O device which should be probed
+ *
+ *     Registers event notification for every event from Executive device. The
+ *     return is always 0, because we want all devices of class Executive.
+ *
+ *     Returns 0 on success.
+ */
+static int i2o_exec_probe(struct device *dev)
+{
+       struct i2o_device *i2o_dev = to_i2o_device(dev);
+
+       i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
+
+       i2o_dev->iop->exec = i2o_dev;
+
+       return 0;
+};
+
+/**
+ *     i2o_exec_remove - Called on I2O device removal
+ *     @dev: I2O device which was removed
+ *
+ *     Unregisters event notification from Executive I2O device.
+ *
+ *     Returns 0 on success.
+ */
+static int i2o_exec_remove(struct device *dev)
+{
+       i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0);
+
+       return 0;
+};
+
+/**
+ *     i2o_exec_lct_modified - Called on LCT NOTIFY reply
+ *     @c: I2O controller on which the LCT has modified
+ *
+ *     This function handles asynchronus LCT NOTIFY replies. It parses the
+ *     new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY
+ *     again.
+ */
+static void i2o_exec_lct_modified(struct i2o_controller *c)
+{
+       if (i2o_device_parse_lct(c) == -EAGAIN)
+               i2o_exec_lct_notify(c, 0);
+};
+
+/**
+ *     i2o_exec_reply -  I2O Executive reply handler
+ *     @c: I2O controller from which the reply comes
+ *     @m: message id
+ *     @msg: pointer to the I2O reply message
+ *
+ *     This function is always called from interrupt context. If a POST WAIT
+ *     reply was received, pass it to the complete function. If a LCT NOTIFY
+ *     reply was received, a new event is created to handle the update.
+ *
+ *     Returns 0 on success and if the reply should not be flushed or > 0
+ *     on success and if the reply should be flushed. Returns negative error
+ *     code on failure and if the reply should be flushed.
+ */
+static int i2o_exec_reply(struct i2o_controller *c, u32 m,
+                         struct i2o_message *msg)
+{
+       if (readl(&msg->u.head[0]) & MSG_FAIL) {        // Fail bit is set
+               struct i2o_message *pmsg;       /* preserved message */
+               u32 pm;
+
+               pm = readl(&msg->body[3]);
+
+               pmsg = c->in_queue.virt + pm;
+
+               i2o_report_status(KERN_INFO, "i2o_core", msg);
+
+               /* Release the preserved msg by resubmitting it as a NOP */
+               i2o_msg_nop(c, pm);
+
+               /* If reply to i2o_post_wait failed, return causes a timeout */
+               return -1;
+       }
+
+       if (readl(&msg->u.s.tcntxt) & 0x80000000)
+               return i2o_msg_post_wait_complete(c, m, msg);
+
+       if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
+               struct work_struct *work;
+
+               pr_debug("%s: LCT notify received\n", c->name);
+
+               work = kmalloc(sizeof(*work), GFP_ATOMIC);
+               if (!work)
+                       return -ENOMEM;
+
+               INIT_WORK(work, (void (*)(void *))i2o_exec_lct_modified, c);
+               queue_work(i2o_exec_driver.event_queue, work);
+               return 1;
+       }
+
+       /*
+        * If this happens, we want to dump the message to the syslog so
+        * it can be sent back to the card manufacturer by the end user
+        * to aid in debugging.
+        *
+        */
+       printk(KERN_WARNING "%s: Unsolicited message reply sent to core!"
+              "Message dumped to syslog\n", c->name);
+       i2o_dump_message(msg);
+
+       return -EFAULT;
+}
+
+/**
+ *     i2o_exec_event - Event handling function
+ *     @evt: Event which occurs
+ *
+ *     Handles events send by the Executive device. At the moment does not do
+ *     anything useful.
+ */
+static void i2o_exec_event(struct i2o_event *evt)
+{
+       printk(KERN_INFO "Event received from device: %d\n",
+              evt->i2o_dev->lct_data.tid);
+       kfree(evt);
+};
+
+/**
+ *     i2o_exec_lct_get - Get the IOP's Logical Configuration Table
+ *     @c: I2O controller from which the LCT should be fetched
+ *
+ *     Send a LCT NOTIFY request to the controller, and wait
+ *     I2O_TIMEOUT_LCT_GET seconds until arrival of response. If the LCT is
+ *     to large, retry it.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+int i2o_exec_lct_get(struct i2o_controller *c)
+{
+       struct i2o_message *msg;
+       u32 m;
+       int i = 0;
+       int rc = -EAGAIN;
+
+       for (i = 1; i <= I2O_LCT_GET_TRIES; i++) {
+               m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+               if (m == I2O_QUEUE_EMPTY)
+                       return -ETIMEDOUT;
+
+               writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
+               writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID,
+                      &msg->u.head[1]);
+               writel(0xffffffff, &msg->body[0]);
+               writel(0x00000000, &msg->body[1]);
+               writel(0xd0000000 | c->dlct.len, &msg->body[2]);
+               writel(c->dlct.phys, &msg->body[3]);
+
+               rc = i2o_msg_post_wait(c, m, I2O_TIMEOUT_LCT_GET);
+               if (rc < 0)
+                       break;
+
+               rc = i2o_device_parse_lct(c);
+               if (rc != -EAGAIN)
+                       break;
+       }
+
+       return rc;
+}
+
+/**
+ *     i2o_exec_lct_notify - Send a asynchronus LCT NOTIFY request
+ *     @c: I2O controller to which the request should be send
+ *     @change_ind: change indicator
+ *
+ *     This function sends a LCT NOTIFY request to the I2O controller with
+ *     the change indicator change_ind. If the change_ind == 0 the controller
+ *     replies immediately after the request. If change_ind > 0 the reply is
+ *     send after change indicator of the LCT is > change_ind.
+ */
+int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
+{
+       i2o_status_block *sb = c->status_block.virt;
+       struct device *dev;
+       struct i2o_message *msg;
+       u32 m;
+
+       dev = &c->pdev->dev;
+
+       if (i2o_dma_realloc(dev, &c->dlct, sb->expected_lct_size, GFP_KERNEL))
+               return -ENOMEM;
+
+       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+       if (m == I2O_QUEUE_EMPTY)
+               return -ETIMEDOUT;
+
+       writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
+       writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID,
+              &msg->u.head[1]);
+       writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+       writel(0, &msg->u.s.tcntxt);    /* FIXME */
+       writel(0xffffffff, &msg->body[0]);
+       writel(change_ind, &msg->body[1]);
+       writel(0xd0000000 | c->dlct.len, &msg->body[2]);
+       writel(c->dlct.phys, &msg->body[3]);
+
+       i2o_msg_post(c, m);
+
+       return 0;
+};
+
+/* Exec OSM driver struct */
+struct i2o_driver i2o_exec_driver = {
+       .name = "exec-osm",
+       .reply = i2o_exec_reply,
+       .event = i2o_exec_event,
+       .classes = i2o_exec_class_id,
+       .driver = {
+                  .probe = i2o_exec_probe,
+                  .remove = i2o_exec_remove,
+                  },
+};
+
+/**
+ *     i2o_exec_init - Registers the Exec OSM
+ *
+ *     Registers the Exec OSM in the I2O core.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+int __init i2o_exec_init(void)
+{
+       return i2o_driver_register(&i2o_exec_driver);
+};
+
+/**
+ *     i2o_exec_exit - Removes the Exec OSM
+ *
+ *     Unregisters the Exec OSM from the I2O core.
+ */
+void __exit i2o_exec_exit(void)
+{
+       i2o_driver_unregister(&i2o_exec_driver);
+};
+
+EXPORT_SYMBOL(i2o_msg_post_wait_mem);
+EXPORT_SYMBOL(i2o_exec_lct_get);
+EXPORT_SYMBOL(i2o_exec_lct_notify);
diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h
new file mode 100644 (file)
index 0000000..ddd9a15
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *     Block OSM structures/API
+ *
+ *     Copyright (C) 1999-2002 Red Hat Software
+ *
+ *     Written by Alan Cox, Building Number Three Ltd
+ *
+ *     This program is free software; you can redistribute 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.
+ *
+ *     For the purpose of avoiding doubt the preferred form of the work
+ *     for making modifications shall be a standards compliant form such
+ *     gzipped tar and not one requiring a proprietary or patent encumbered
+ *     tool to unpack.
+ *
+ *     Fixes/additions:
+ *             Steve Ralston:
+ *                     Multiple device handling error fixes,
+ *                     Added a queue depth.
+ *             Alan Cox:
+ *                     FC920 has an rmw bug. Dont or in the end marker.
+ *                     Removed queue walk, fixed for 64bitness.
+ *                     Rewrote much of the code over time
+ *                     Added indirect block lists
+ *                     Handle 64K limits on many controllers
+ *                     Don't use indirects on the Promise (breaks)
+ *                     Heavily chop down the queue depths
+ *             Deepak Saxena:
+ *                     Independent queues per IOP
+ *                     Support for dynamic device creation/deletion
+ *                     Code cleanup
+ *                     Support for larger I/Os through merge* functions
+ *                     (taken from DAC960 driver)
+ *             Boji T Kannanthanam:
+ *                     Set the I2O Block devices to be detected in increasing
+ *                     order of TIDs during boot.
+ *                     Search and set the I2O block device that we boot off
+ *                     from as the first device to be claimed (as /dev/i2o/hda)
+ *                     Properly attach/detach I2O gendisk structure from the
+ *                     system gendisk list. The I2O block devices now appear in
+ *                     /proc/partitions.
+ *             Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *                     Minor bugfixes for 2.6.
+ */
+
+#ifndef I2O_BLOCK_OSM_H
+#define I2O_BLOCK_OSM_H
+
+#define I2O_BLOCK_RETRY_TIME HZ/4
+#define I2O_BLOCK_MAX_OPEN_REQUESTS 50
+
+/* I2O Block OSM mempool struct */
+struct i2o_block_mempool {
+       kmem_cache_t    *slab;
+       mempool_t       *pool;
+};
+
+/* I2O Block device descriptor */
+struct i2o_block_device {
+       struct i2o_device *i2o_dev;     /* pointer to I2O device */
+       struct gendisk *gd;
+       spinlock_t lock;                /* queue lock */
+       struct list_head open_queue;    /* list of transfered, but unfinished
+                                          requests */
+       unsigned int open_queue_depth;  /* number of requests in the queue */
+
+       int rcache;                     /* read cache flags */
+       int wcache;                     /* write cache flags */
+       int flags;
+       int power;                      /* power state */
+       int media_change_flag;          /* media changed flag */
+};
+
+/* I2O Block device request */
+struct i2o_block_request
+{
+       struct list_head queue;
+       struct request *req;            /* corresponding request */
+       struct i2o_block_device *i2o_blk_dev;   /* I2O block device */
+       int sg_dma_direction;           /* direction of DMA buffer read/write */
+       int sg_nents;                   /* number of SG elements */
+       struct scatterlist sg_table[I2O_MAX_SEGMENTS]; /* SG table */
+};
+
+/* I2O Block device delayed request */
+struct i2o_block_delayed_request
+{
+       struct work_struct work;
+       struct request_queue *queue;
+};
+
+#endif
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
new file mode 100644 (file)
index 0000000..699723e
--- /dev/null
@@ -0,0 +1,1258 @@
+/*
+ *     Functions to handle I2O controllers and I2O message handling
+ *
+ *     Copyright (C) 1999-2002 Red Hat Software
+ *
+ *     Written by Alan Cox, Building Number Three Ltd
+ *
+ *     This program is free software; you can redistribute 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.
+ *
+ *     A lot of the I2O message side code from this is taken from the
+ *     Red Creek RCPCI45 adapter driver by Red Creek Communications
+ *
+ *     Fixes/additions:
+ *             Philipp Rumpf
+ *             Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ *             Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
+ *             Deepak Saxena <deepak@plexity.net>
+ *             Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
+ *             Alan Cox <alan@redhat.com>:
+ *                     Ported to Linux 2.5.
+ *             Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *                     Minor fixes for 2.6.
+ */
+
+#include <linux/module.h>
+#include <linux/i2o.h>
+
+/* global I2O controller list */
+LIST_HEAD(i2o_controllers);
+
+/*
+ * global I2O System Table. Contains information about all the IOPs in the
+ * system. Used to inform IOPs about each others existence.
+ */
+static struct i2o_dma i2o_systab;
+
+/* Module internal functions from other sources */
+extern struct i2o_driver i2o_exec_driver;
+extern int i2o_exec_lct_get(struct i2o_controller *);
+extern void i2o_device_remove(struct i2o_device *);
+
+extern int __init i2o_driver_init(void);
+extern void __exit i2o_driver_exit(void);
+extern int __init i2o_exec_init(void);
+extern void __exit i2o_exec_exit(void);
+extern int __init i2o_pci_init(void);
+extern void __exit i2o_pci_exit(void);
+extern int i2o_device_init(void);
+extern void i2o_device_exit(void);
+
+/**
+ *     i2o_msg_nop - Returns a message which is not used
+ *     @c: I2O controller from which the message was created
+ *     @m: message which should be returned
+ *
+ *     If you fetch a message via i2o_msg_get, and can't use it, you must
+ *     return the message with this function. Otherwise the message frame
+ *     is lost.
+ */
+void i2o_msg_nop(struct i2o_controller *c, u32 m)
+{
+       struct i2o_message *msg = c->in_queue.virt + m;
+
+       writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+       writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
+              &msg->u.head[1]);
+       writel(0, &msg->u.head[2]);
+       writel(0, &msg->u.head[3]);
+       i2o_msg_post(c, m);
+};
+
+/**
+ *     i2o_msg_get_wait - obtain an I2O message from the IOP
+ *     @c: I2O controller
+ *     @msg: pointer to a I2O message pointer
+ *     @wait: how long to wait until timeout
+ *
+ *     This function waits up to wait seconds for a message slot to be
+ *     available.
+ *
+ *     On a success the message is returned and the pointer to the message is
+ *     set in msg. The returned message is the physical page frame offset
+ *     address from the read port (see the i2o spec). If no message is
+ *     available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
+ */
+u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message **msg,
+                    int wait)
+{
+       unsigned long timeout = jiffies + wait * HZ;
+       u32 m;
+
+       while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) {
+               if (time_after(jiffies, timeout)) {
+                       pr_debug("%s: Timeout waiting for message frame.\n",
+                                c->name);
+                       return I2O_QUEUE_EMPTY;
+               }
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(1);
+       }
+
+       return m;
+};
+
+#if BITS_PER_LONG == 64
+/**
+ *      i2o_cntxt_list_add - Append a pointer to context list and return a id
+ *     @c: controller to which the context list belong
+ *     @ptr: pointer to add to the context list
+ *
+ *     Because the context field in I2O is only 32-bit large, on 64-bit the
+ *     pointer is to large to fit in the context field. The i2o_cntxt_list
+ *     functions therefore map pointers to context fields.
+ *
+ *     Returns context id > 0 on success or 0 on failure.
+ */
+u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr)
+{
+       struct i2o_context_list_element *entry;
+       unsigned long flags;
+
+       if (!ptr)
+               printk(KERN_ERR "NULL pointer found!\n");
+
+       entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+       if (!entry) {
+               printk(KERN_ERR "i2o: Could not allocate memory for context "
+                      "list element\n");
+               return 0;
+       }
+
+       entry->ptr = ptr;
+       entry->timestamp = jiffies;
+       INIT_LIST_HEAD(&entry->list);
+
+       spin_lock_irqsave(&c->context_list_lock, flags);
+
+       if (unlikely(atomic_inc_and_test(&c->context_list_counter)))
+               atomic_inc(&c->context_list_counter);
+
+       entry->context = atomic_read(&c->context_list_counter);
+
+       list_add(&entry->list, &c->context_list);
+
+       spin_unlock_irqrestore(&c->context_list_lock, flags);
+
+       pr_debug("Add context to list %p -> %d\n", ptr, context);
+
+       return entry->context;
+};
+
+/**
+ *      i2o_cntxt_list_remove - Remove a pointer from the context list
+ *     @c: controller to which the context list belong
+ *     @ptr: pointer which should be removed from the context list
+ *
+ *     Removes a previously added pointer from the context list and returns
+ *     the matching context id.
+ *
+ *     Returns context id on succes or 0 on failure.
+ */
+u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr)
+{
+       struct i2o_context_list_element *entry;
+       u32 context = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&c->context_list_lock, flags);
+       list_for_each_entry(entry, &c->context_list, list)
+           if (entry->ptr == ptr) {
+               list_del(&entry->list);
+               context = entry->context;
+               kfree(entry);
+               break;
+       }
+       spin_unlock_irqrestore(&c->context_list_lock, flags);
+
+       if (!context)
+               printk(KERN_WARNING "i2o: Could not remove nonexistent ptr "
+                      "%p\n", ptr);
+
+       pr_debug("remove ptr from context list %d -> %p\n", context, ptr);
+
+       return context;
+};
+
+/**
+ *      i2o_cntxt_list_get - Get a pointer from the context list and remove it
+ *     @c: controller to which the context list belong
+ *     @context: context id to which the pointer belong
+ *
+ *     Returns pointer to the matching context id on success or NULL on
+ *     failure.
+ */
+void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context)
+{
+       struct i2o_context_list_element *entry;
+       unsigned long flags;
+       void *ptr = NULL;
+
+       spin_lock_irqsave(&c->context_list_lock, flags);
+       list_for_each_entry(entry, &c->context_list, list)
+           if (entry->context == context) {
+               list_del(&entry->list);
+               ptr = entry->ptr;
+               kfree(entry);
+               break;
+       }
+       spin_unlock_irqrestore(&c->context_list_lock, flags);
+
+       if (!ptr)
+               printk(KERN_WARNING "i2o: context id %d not found\n", context);
+
+       pr_debug("get ptr from context list %d -> %p\n", context, ptr);
+
+       return ptr;
+};
+
+/**
+ *      i2o_cntxt_list_get_ptr - Get a context id from the context list
+ *     @c: controller to which the context list belong
+ *     @ptr: pointer to which the context id should be fetched
+ *
+ *     Returns context id which matches to the pointer on succes or 0 on
+ *     failure.
+ */
+u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr)
+{
+       struct i2o_context_list_element *entry;
+       u32 context = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&c->context_list_lock, flags);
+       list_for_each_entry(entry, &c->context_list, list)
+           if (entry->ptr == ptr) {
+               context = entry->context;
+               break;
+       }
+       spin_unlock_irqrestore(&c->context_list_lock, flags);
+
+       if (!context)
+               printk(KERN_WARNING "i2o: Could not find nonexistent ptr "
+                      "%p\n", ptr);
+
+       pr_debug("get context id from context list %p -> %d\n", ptr, context);
+
+       return context;
+};
+#endif
+
+/**
+ *     i2o_iop_find - Find an I2O controller by id
+ *     @unit: unit number of the I2O controller to search for
+ *
+ *     Lookup the I2O controller on the controller list.
+ *
+ *     Returns pointer to the I2O controller on success or NULL if not found.
+ */
+struct i2o_controller *i2o_find_iop(int unit)
+{
+       struct i2o_controller *c;
+
+       list_for_each_entry(c, &i2o_controllers, list) {
+               if (c->unit == unit)
+                       return c;
+       }
+
+       return NULL;
+};
+
+/**
+ *     i2o_iop_find_device - Find a I2O device on an I2O controller
+ *     @c: I2O controller where the I2O device hangs on
+ *     @tid: TID of the I2O device to search for
+ *
+ *     Searches the devices of the I2O controller for a device with TID tid and
+ *     returns it.
+ *
+ *     Returns a pointer to the I2O device if found, otherwise NULL.
+ */
+struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid)
+{
+       struct i2o_device *dev;
+
+       list_for_each_entry(dev, &c->devices, list)
+           if (dev->lct_data.tid == tid)
+               return dev;
+
+       return NULL;
+};
+
+/**
+ *     i2o_quiesce_controller - quiesce controller
+ *     @c: controller
+ *
+ *     Quiesce an IOP. Causes IOP to make external operation quiescent
+ *     (i2o 'READY' state). Internal operation of the IOP continues normally.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+static int i2o_iop_quiesce(struct i2o_controller *c)
+{
+       struct i2o_message *msg;
+       u32 m;
+       i2o_status_block *sb = c->status_block.virt;
+       int rc;
+
+       i2o_status_get(c);
+
+       /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */
+       if ((sb->iop_state != ADAPTER_STATE_READY) &&
+           (sb->iop_state != ADAPTER_STATE_OPERATIONAL))
+               return 0;
+
+       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+       if (m == I2O_QUEUE_EMPTY)
+               return -ETIMEDOUT;
+
+       writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+       writel(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | ADAPTER_TID,
+              &msg->u.head[1]);
+
+       /* Long timeout needed for quiesce if lots of devices */
+       if ((rc = i2o_msg_post_wait(c, m, 240)))
+               printk(KERN_INFO "%s: Unable to quiesce (status=%#x).\n",
+                      c->name, -rc);
+       else
+               pr_debug("%s: Quiesced.\n", c->name);
+
+       i2o_status_get(c);      // Entered READY state
+
+       return rc;
+};
+
+/**
+ *     i2o_iop_enable - move controller from ready to OPERATIONAL
+ *     @c: I2O controller
+ *
+ *     Enable IOP. This allows the IOP to resume external operations and
+ *     reverses the effect of a quiesce. Returns zero or an error code if
+ *     an error occurs.
+ */
+static int i2o_iop_enable(struct i2o_controller *c)
+{
+       struct i2o_message *msg;
+       u32 m;
+       i2o_status_block *sb = c->status_block.virt;
+       int rc;
+
+       i2o_status_get(c);
+
+       /* Enable only allowed on READY state */
+       if (sb->iop_state != ADAPTER_STATE_READY)
+               return -EINVAL;
+
+       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+       if (m == I2O_QUEUE_EMPTY)
+               return -ETIMEDOUT;
+
+       writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+       writel(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | ADAPTER_TID,
+              &msg->u.head[1]);
+
+       /* How long of a timeout do we need? */
+       if ((rc = i2o_msg_post_wait(c, m, 240)))
+               printk(KERN_ERR "%s: Could not enable (status=%#x).\n",
+                      c->name, -rc);
+       else
+               pr_debug("%s: Enabled.\n", c->name);
+
+       i2o_status_get(c);      // entered OPERATIONAL state
+
+       return rc;
+};
+
+/**
+ *     i2o_iop_quiesce_all - Quiesce all I2O controllers on the system
+ *
+ *     Quiesce all I2O controllers which are connected to the system.
+ */
+static inline void i2o_iop_quiesce_all(void)
+{
+       struct i2o_controller *c, *tmp;
+
+       list_for_each_entry_safe(c, tmp, &i2o_controllers, list) {
+               if (!c->no_quiesce)
+                       i2o_iop_quiesce(c);
+       }
+};
+
+/**
+ *     i2o_iop_enable_all - Enables all controllers on the system
+ *
+ *     Enables all I2O controllers which are connected to the system.
+ */
+static inline void i2o_iop_enable_all(void)
+{
+       struct i2o_controller *c, *tmp;
+
+       list_for_each_entry_safe(c, tmp, &i2o_controllers, list)
+           i2o_iop_enable(c);
+};
+
+/**
+ *     i2o_clear_controller - Bring I2O controller into HOLD state
+ *     @c: controller
+ *
+ *     Clear an IOP to HOLD state, ie. terminate external operations, clear all
+ *     input queues and prepare for a system restart. IOP's internal operation
+ *     continues normally and the outbound queue is alive. The IOP is not
+ *     expected to rebuild its LCT.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+static int i2o_iop_clear(struct i2o_controller *c)
+{
+       struct i2o_message *msg;
+       u32 m;
+       int rc;
+
+       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+       if (m == I2O_QUEUE_EMPTY)
+               return -ETIMEDOUT;
+
+       /* Quiesce all IOPs first */
+       i2o_iop_quiesce_all();
+
+       writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+       writel(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | ADAPTER_TID,
+              &msg->u.head[1]);
+
+       if ((rc = i2o_msg_post_wait(c, m, 30)))
+               printk(KERN_INFO "%s: Unable to clear (status=%#x).\n",
+                      c->name, -rc);
+       else
+               pr_debug("%s: Cleared.\n", c->name);
+
+       /* Enable all IOPs */
+       i2o_iop_enable_all();
+
+       i2o_status_get(c);
+
+       return rc;
+}
+
+/**
+ *     i2o_iop_reset - reset an I2O controller
+ *     @c: controller to reset
+ *
+ *     Reset the IOP into INIT state and wait until IOP gets into RESET state.
+ *     Terminate all external operations, clear IOP's inbound and outbound
+ *     queues, terminate all DDMs, and reload the IOP's operating environment
+ *     and all local DDMs. The IOP rebuilds its LCT.
+ */
+static int i2o_iop_reset(struct i2o_controller *c)
+{
+       u8 *status = c->status.virt;
+       struct i2o_message *msg;
+       u32 m;
+       unsigned long timeout;
+       i2o_status_block *sb = c->status_block.virt;
+       int rc = 0;
+
+       pr_debug("Resetting controller\n");
+
+       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+       if (m == I2O_QUEUE_EMPTY)
+               return -ETIMEDOUT;
+
+       memset(status, 0, 4);
+
+       /* Quiesce all IOPs first */
+       i2o_iop_quiesce_all();
+
+       writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+       writel(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | ADAPTER_TID,
+              &msg->u.head[1]);
+       writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+       writel(0, &msg->u.s.tcntxt);    //FIXME: use reasonable transaction context
+       writel(0, &msg->body[0]);
+       writel(0, &msg->body[1]);
+       writel(i2o_ptr_low((void *)c->status.phys), &msg->body[2]);
+       writel(i2o_ptr_high((void *)c->status.phys), &msg->body[3]);
+
+       i2o_msg_post(c, m);
+
+       /* Wait for a reply */
+       timeout = jiffies + I2O_TIMEOUT_RESET * HZ;
+       while (!*status) {
+               if (time_after(jiffies, timeout)) {
+                       printk(KERN_ERR "IOP reset timeout.\n");
+                       rc = -ETIMEDOUT;
+                       goto exit;
+               }
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(1);
+
+               rmb();
+       }
+
+       if (*status == I2O_CMD_IN_PROGRESS) {
+               /*
+                * Once the reset is sent, the IOP goes into the INIT state
+                * which is indeterminate.  We need to wait until the IOP
+                * has rebooted before we can let the system talk to
+                * it. We read the inbound Free_List until a message is
+                * available. If we can't read one in the given ammount of
+                * time, we assume the IOP could not reboot properly.
+                */
+               pr_debug("%s: Reset in progress, waiting for reboot...\n",
+                        c->name);
+
+               m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
+               while (m == I2O_QUEUE_EMPTY) {
+                       if (time_after(jiffies, timeout)) {
+                               printk(KERN_ERR "IOP reset timeout.\n");
+                               rc = -ETIMEDOUT;
+                               goto exit;
+                       }
+                       set_current_state(TASK_UNINTERRUPTIBLE);
+                       schedule_timeout(1);
+
+                       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
+               }
+               i2o_msg_nop(c, m);
+       }
+
+       /* from here all quiesce commands are safe */
+       c->no_quiesce = 0;
+
+       /* If IopReset was rejected or didn't perform reset, try IopClear */
+       i2o_status_get(c);
+       if (*status == I2O_CMD_REJECTED || sb->iop_state != ADAPTER_STATE_RESET) {
+               printk(KERN_WARNING "%s: Reset rejected, trying to clear\n",
+                      c->name);
+               i2o_iop_clear(c);
+       } else
+               pr_debug("%s: Reset completed.\n", c->name);
+
+      exit:
+       /* Enable all IOPs */
+       i2o_iop_enable_all();
+
+       return rc;
+};
+
+/**
+ *     i2o_iop_init_outbound_queue - setup the outbound message queue
+ *     @c: I2O controller
+ *
+ *     Clear and (re)initialize IOP's outbound queue and post the message
+ *     frames to the IOP.
+ *
+ *     Returns 0 on success or a negative errno code on failure.
+ */
+int i2o_iop_init_outbound_queue(struct i2o_controller *c)
+{
+       u8 *status = c->status.virt;
+       u32 m;
+       struct i2o_message *msg;
+       ulong timeout;
+       int i;
+
+       pr_debug("%s: Initializing Outbound Queue...\n", c->name);
+
+       memset(status, 0, 4);
+
+       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+       if (m == I2O_QUEUE_EMPTY)
+               return -ETIMEDOUT;
+
+       writel(EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6, &msg->u.head[0]);
+       writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
+              &msg->u.head[1]);
+       writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+       writel(0x0106, &msg->u.s.tcntxt);       /* FIXME: why 0x0106, maybe in
+                                                  Spec? */
+       writel(PAGE_SIZE, &msg->body[0]);
+       writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]);     /* Outbound msg frame
+                                                                  size in words and Initcode */
+       writel(0xd0000004, &msg->body[2]);
+       writel(i2o_ptr_low((void *)c->status.phys), &msg->body[3]);
+       writel(i2o_ptr_high((void *)c->status.phys), &msg->body[4]);
+
+       i2o_msg_post(c, m);
+
+       timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
+       while (*status <= I2O_CMD_IN_PROGRESS) {
+               if (time_after(jiffies, timeout)) {
+                       printk(KERN_WARNING "%s: Timeout Initializing\n",
+                              c->name);
+                       return -ETIMEDOUT;
+               }
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(1);
+
+               rmb();
+       }
+
+       m = c->out_queue.phys;
+
+       /* Post frames */
+       for (i = 0; i < NMBR_MSG_FRAMES; i++) {
+               i2o_flush_reply(c, m);
+               m += MSG_FRAME_SIZE * 4;
+       }
+
+       return 0;
+}
+
+/**
+ *     i2o_iop_activate - Bring controller up to HOLD
+ *     @c: controller
+ *
+ *     This function brings an I2O controller into HOLD state. The adapter
+ *     is reset if necessary and then the queues and resource table are read.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+static int i2o_iop_activate(struct i2o_controller *c)
+{
+       i2o_status_block *sb = c->status_block.virt;
+       int rc;
+       /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */
+       /* In READY state, Get status */
+
+       rc = i2o_status_get(c);
+       if (rc) {
+               printk(KERN_INFO "Unable to obtain status of %s, "
+                      "attempting a reset.\n", c->name);
+               if (i2o_iop_reset(c))
+                       return rc;
+       }
+
+       if (sb->i2o_version > I2OVER15) {
+               printk(KERN_ERR "%s: Not running vrs. 1.5. of the I2O "
+                      "Specification.\n", c->name);
+               return -ENODEV;
+       }
+
+       switch (sb->iop_state) {
+       case ADAPTER_STATE_FAULTED:
+               printk(KERN_CRIT "%s: hardware fault\n", c->name);
+               return -ENODEV;
+
+       case ADAPTER_STATE_READY:
+       case ADAPTER_STATE_OPERATIONAL:
+       case ADAPTER_STATE_HOLD:
+       case ADAPTER_STATE_FAILED:
+               pr_debug("already running, trying to reset...\n");
+               if (i2o_iop_reset(c))
+                       return -ENODEV;
+       }
+
+       rc = i2o_iop_init_outbound_queue(c);
+       if (rc)
+               return rc;
+
+       /* In HOLD state */
+
+       rc = i2o_hrt_get(c);
+       if (rc)
+               return rc;
+
+       return 0;
+};
+
+/**
+ *     i2o_iop_systab_set - Set the I2O System Table of the specified IOP
+ *     @c: I2O controller to which the system table should be send
+ *
+ *     Before the systab could be set i2o_systab_build() must be called.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+static int i2o_iop_systab_set(struct i2o_controller *c)
+{
+       struct i2o_message *msg;
+       u32 m;
+       i2o_status_block *sb = c->status_block.virt;
+       struct device *dev = &c->pdev->dev;
+       struct resource *root;
+       int rc;
+
+       if (sb->current_mem_size < sb->desired_mem_size) {
+               struct resource *res = &c->mem_resource;
+               res->name = c->pdev->bus->name;
+               res->flags = IORESOURCE_MEM;
+               res->start = 0;
+               res->end = 0;
+               printk("%s: requires private memory resources.\n", c->name);
+               root = pci_find_parent_resource(c->pdev, res);
+               if (root == NULL)
+                       printk("Can't find parent resource!\n");
+               if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20,     /* Unspecified, so use 1Mb and play safe */
+                                             NULL, NULL) >= 0) {
+                       c->mem_alloc = 1;
+                       sb->current_mem_size = 1 + res->end - res->start;
+                       sb->current_mem_base = res->start;
+                       printk(KERN_INFO
+                              "%s: allocated %ld bytes of PCI memory at 0x%08lX.\n",
+                              c->name, 1 + res->end - res->start, res->start);
+               }
+       }
+
+       if (sb->current_io_size < sb->desired_io_size) {
+               struct resource *res = &c->io_resource;
+               res->name = c->pdev->bus->name;
+               res->flags = IORESOURCE_IO;
+               res->start = 0;
+               res->end = 0;
+               printk("%s: requires private memory resources.\n", c->name);
+               root = pci_find_parent_resource(c->pdev, res);
+               if (root == NULL)
+                       printk("Can't find parent resource!\n");
+               if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20,        /* Unspecified, so use 1Mb and play safe */
+                                             NULL, NULL) >= 0) {
+                       c->io_alloc = 1;
+                       sb->current_io_size = 1 + res->end - res->start;
+                       sb->current_mem_base = res->start;
+                       printk(KERN_INFO
+                              "%s: allocated %ld bytes of PCI I/O at 0x%08lX.\n",
+                              c->name, 1 + res->end - res->start, res->start);
+               }
+       }
+
+       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+       if (m == I2O_QUEUE_EMPTY)
+               return -ETIMEDOUT;
+
+       i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len,
+                                        PCI_DMA_TODEVICE);
+       if (!i2o_systab.phys) {
+               i2o_msg_nop(c, m);
+               return -ENOMEM;
+       }
+
+       writel(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6, &msg->u.head[0]);
+       writel(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | ADAPTER_TID,
+              &msg->u.head[1]);
+
+       /*
+        * Provide three SGL-elements:
+        * System table (SysTab), Private memory space declaration and
+        * Private i/o space declaration
+        *
+        * FIXME: is this still true?
+        * Nasty one here. We can't use dma_alloc_coherent to send the
+        * same table to everyone. We have to go remap it for them all
+        */
+
+       writel(c->unit + 2, &msg->body[0]);
+       writel(0, &msg->body[1]);
+       writel(0x54000000 | i2o_systab.phys, &msg->body[2]);
+       writel(i2o_systab.phys, &msg->body[3]);
+       writel(0x54000000 | sb->current_mem_size, &msg->body[4]);
+       writel(sb->current_mem_base, &msg->body[5]);
+       writel(0xd4000000 | sb->current_io_size, &msg->body[6]);
+       writel(sb->current_io_base, &msg->body[6]);
+
+       rc = i2o_msg_post_wait(c, m, 120);
+
+       dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len,
+                        PCI_DMA_TODEVICE);
+
+       if (rc < 0)
+               printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n",
+                      c->name, -rc);
+       else
+               pr_debug("%s: SysTab set.\n", c->name);
+
+       i2o_status_get(c);      // Entered READY state
+
+       return rc;
+}
+
+/**
+ *     i2o_iop_online - Bring a controller online into OPERATIONAL state.
+ *     @c: I2O controller
+ *
+ *     Send the system table and enable the I2O controller.
+ *
+ *     Returns 0 on success or negativer error code on failure.
+ */
+static int i2o_iop_online(struct i2o_controller *c)
+{
+       int rc;
+
+       rc = i2o_iop_systab_set(c);
+       if (rc)
+               return rc;
+
+       /* In READY state */
+       pr_debug("%s: Attempting to enable...\n", c->name);
+       rc = i2o_iop_enable(c);
+       if (rc)
+               return rc;
+
+       return 0;
+};
+
+/**
+ *     i2o_iop_remove - Remove the I2O controller from the I2O core
+ *     @c: I2O controller
+ *
+ *     Remove the I2O controller from the I2O core. If devices are attached to
+ *     the controller remove these also and finally reset the controller.
+ */
+void i2o_iop_remove(struct i2o_controller *c)
+{
+       struct i2o_device *dev, *tmp;
+
+       pr_debug("Deleting controller %s\n", c->name);
+
+       i2o_driver_notify_controller_remove_all(c);
+
+       list_del(&c->list);
+
+       list_for_each_entry_safe(dev, tmp, &c->devices, list)
+           i2o_device_remove(dev);
+
+       /* Ask the IOP to switch to RESET state */
+       i2o_iop_reset(c);
+}
+
+/**
+ *     i2o_systab_build - Build system table
+ *
+ *     The system table contains information about all the IOPs in the system
+ *     (duh) and is used by the Executives on the IOPs to establish peer2peer
+ *     connections. We're not supporting peer2peer at the moment, but this
+ *     will be needed down the road for things like lan2lan forwarding.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+static int i2o_systab_build(void)
+{
+       struct i2o_controller *c, *tmp;
+       int num_controllers = 0;
+       u32 change_ind = 0;
+       int count = 0;
+       struct i2o_sys_tbl *systab = i2o_systab.virt;
+
+       list_for_each_entry_safe(c, tmp, &i2o_controllers, list)
+           num_controllers++;
+
+       if (systab) {
+               change_ind = systab->change_ind;
+               kfree(i2o_systab.virt);
+       }
+
+       /* Header + IOPs */
+       i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers *
+           sizeof(struct i2o_sys_tbl_entry);
+
+       systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL);
+       if (!systab) {
+               printk(KERN_ERR "i2o: unable to allocate memory for System "
+                      "Table\n");
+               return -ENOMEM;
+       }
+       memset(systab, 0, i2o_systab.len);
+
+       systab->version = I2OVERSION;
+       systab->change_ind = change_ind + 1;
+
+       list_for_each_entry_safe(c, tmp, &i2o_controllers, list) {
+               i2o_status_block *sb;
+
+               if (count >= num_controllers) {
+                       printk(KERN_ERR "i2o: controller added while building "
+                              "system table\n");
+                       break;
+               }
+
+               sb = c->status_block.virt;
+
+               /*
+                * Get updated IOP state so we have the latest information
+                *
+                * We should delete the controller at this point if it
+                * doesn't respond since if it's not on the system table
+                * it is techninically not part of the I2O subsystem...
+                */
+               if (unlikely(i2o_status_get(c))) {
+                       printk(KERN_ERR "%s: Deleting b/c could not get status"
+                              " while attempting to build system table\n",
+                              c->name);
+                       i2o_iop_remove(c);
+                       continue;       // try the next one
+               }
+
+               systab->iops[count].org_id = sb->org_id;
+               systab->iops[count].iop_id = c->unit + 2;
+               systab->iops[count].seg_num = 0;
+               systab->iops[count].i2o_version = sb->i2o_version;
+               systab->iops[count].iop_state = sb->iop_state;
+               systab->iops[count].msg_type = sb->msg_type;
+               systab->iops[count].frame_size = sb->inbound_frame_size;
+               systab->iops[count].last_changed = change_ind;
+               systab->iops[count].iop_capabilities = sb->iop_capabilities;
+               systab->iops[count].inbound_low = i2o_ptr_low(c->post_port);
+               systab->iops[count].inbound_high = i2o_ptr_high(c->post_port);
+
+               count++;
+       }
+
+       systab->num_entries = count;
+
+       return 0;
+};
+
+/**
+ *     i2o_parse_hrt - Parse the hardware resource table.
+ *     @c: I2O controller
+ *
+ *     We don't do anything with it except dumping it (in debug mode).
+ *
+ *     Returns 0.
+ */
+static int i2o_parse_hrt(struct i2o_controller *c)
+{
+       i2o_dump_hrt(c);
+       return 0;
+};
+
+/**
+ *     i2o_status_get - Get the status block from the I2O controller
+ *     @c: I2O controller
+ *
+ *     Issue a status query on the controller. This updates the attached
+ *     status block. The status block could then be accessed through
+ *     c->status_block.
+ *
+ *     Returns 0 on sucess or negative error code on failure.
+ */
+int i2o_status_get(struct i2o_controller *c)
+{
+       struct i2o_message *msg;
+       u32 m;
+       u8 *status_block;
+       unsigned long timeout;
+
+       status_block = (u8 *) c->status_block.virt;
+       memset(status_block, 0, sizeof(i2o_status_block));
+
+       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+       if (m == I2O_QUEUE_EMPTY)
+               return -ETIMEDOUT;
+
+       writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+       writel(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | ADAPTER_TID,
+              &msg->u.head[1]);
+       writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+       writel(0, &msg->u.s.tcntxt);    // FIXME: use resonable transaction context
+       writel(0, &msg->body[0]);
+       writel(0, &msg->body[1]);
+       writel(i2o_ptr_low((void *)c->status_block.phys), &msg->body[2]);
+       writel(i2o_ptr_high((void *)c->status_block.phys), &msg->body[3]);
+       writel(sizeof(i2o_status_block), &msg->body[4]);        /* always 88 bytes */
+
+       i2o_msg_post(c, m);
+
+       /* Wait for a reply */
+       timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ;
+       while (status_block[87] != 0xFF) {
+               if (time_after(jiffies, timeout)) {
+                       printk(KERN_ERR "%s: Get status timeout.\n", c->name);
+                       return -ETIMEDOUT;
+               }
+
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(1);
+
+               rmb();
+       }
+
+#ifdef DEBUG
+       i2o_debug_state(c);
+#endif
+
+       return 0;
+}
+
+/*
+ *     i2o_hrt_get - Get the Hardware Resource Table from the I2O controller
+ *     @c: I2O controller from which the HRT should be fetched
+ *
+ *     The HRT contains information about possible hidden devices but is
+ *     mostly useless to us.
+ *
+ *     Returns 0 on success or negativer error code on failure.
+ */
+int i2o_hrt_get(struct i2o_controller *c)
+{
+       int rc;
+       int i;
+       i2o_hrt *hrt = c->hrt.virt;
+       u32 size = sizeof(i2o_hrt);
+       struct device *dev = &c->pdev->dev;
+
+       for (i = 0; i < I2O_HRT_GET_TRIES; i++) {
+               struct i2o_message *msg;
+               u32 m;
+
+               m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+               if (m == I2O_QUEUE_EMPTY)
+                       return -ETIMEDOUT;
+
+               writel(SIX_WORD_MSG_SIZE | SGL_OFFSET_4, &msg->u.head[0]);
+               writel(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | ADAPTER_TID,
+                      &msg->u.head[1]);
+               writel(0xd0000000 | c->hrt.len, &msg->body[0]);
+               writel(c->hrt.phys, &msg->body[1]);
+
+               rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt);
+
+               if (rc < 0) {
+                       printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n",
+                              c->name, -rc);
+                       return rc;
+               }
+
+               size = hrt->num_entries * hrt->entry_len << 2;
+               if (size > c->hrt.len) {
+                       if (i2o_dma_realloc(dev, &c->hrt, size, GFP_KERNEL))
+                               return -ENOMEM;
+                       else
+                               hrt = c->hrt.virt;
+               } else
+                       return i2o_parse_hrt(c);
+       }
+
+       printk(KERN_ERR "%s: Unable to get HRT after %d tries, giving up\n",
+              c->name, I2O_HRT_GET_TRIES);
+
+       return -EBUSY;
+}
+
+/**
+ *     i2o_iop_alloc - Allocate and initialize a i2o_controller struct
+ *
+ *     Allocate the necessary memory for a i2o_controller struct and
+ *     initialize the lists.
+ *
+ *     Returns a pointer to the I2O controller or a negative error code on
+ *     failure.
+ */
+struct i2o_controller *i2o_iop_alloc(void)
+{
+       static int unit = 0;    /* 0 and 1 are NULL IOP and Local Host */
+       struct i2o_controller *c;
+
+       c = kmalloc(sizeof(*c), GFP_KERNEL);
+       if (!c) {
+               printk(KERN_ERR "i2o: Insufficient memory to allocate the "
+                      "controller.\n");
+               return ERR_PTR(-ENOMEM);
+       }
+       memset(c, 0, sizeof(*c));
+
+       INIT_LIST_HEAD(&c->devices);
+       c->lock = SPIN_LOCK_UNLOCKED;
+       init_MUTEX(&c->lct_lock);
+       c->unit = unit++;
+       sprintf(c->name, "iop%d", c->unit);
+
+#if BITS_PER_LONG == 64
+       c->context_list_lock = SPIN_LOCK_UNLOCKED;
+       atomic_set(&c->context_list_counter, 0);
+       INIT_LIST_HEAD(&c->context_list);
+#endif
+
+       return c;
+};
+
+/**
+ *     i2o_iop_free - Free the i2o_controller struct
+ *     @c: I2O controller to free
+ */
+void i2o_iop_free(struct i2o_controller *c)
+{
+       kfree(c);
+};
+
+/**
+ *     i2o_iop_add - Initialize the I2O controller and add him to the I2O core
+ *     @c: controller
+ *
+ *     Initialize the I2O controller and if no error occurs add him to the I2O
+ *     core.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+int i2o_iop_add(struct i2o_controller *c)
+{
+       int rc;
+
+       printk(KERN_INFO "%s: Activating I2O controller...\n", c->name);
+       printk(KERN_INFO "%s: This may take a few minutes if there are many "
+              "devices\n", c->name);
+
+       if ((rc = i2o_iop_activate(c))) {
+               printk(KERN_ERR "%s: controller could not activated\n",
+                      c->name);
+               i2o_iop_reset(c);
+               return rc;
+       }
+
+       pr_debug("building sys table %s...\n", c->name);
+
+       if ((rc = i2o_systab_build())) {
+               i2o_iop_reset(c);
+               return rc;
+       }
+
+       pr_debug("online controller %s...\n", c->name);
+
+       if ((rc = i2o_iop_online(c))) {
+               i2o_iop_reset(c);
+               return rc;
+       }
+
+       pr_debug("getting LCT %s...\n", c->name);
+
+       if ((rc = i2o_exec_lct_get(c))) {
+               i2o_iop_reset(c);
+               return rc;
+       }
+
+       list_add(&c->list, &i2o_controllers);
+
+       i2o_driver_notify_controller_add_all(c);
+
+       printk(KERN_INFO "%s: Controller added\n", c->name);
+
+       return 0;
+};
+
+/**
+ *     i2o_event_register - Turn on/off event notification for a I2O device
+ *     @dev: I2O device which should receive the event registration request
+ *     @drv: driver which want to get notified
+ *     @tcntxt: transaction context to use with this notifier
+ *     @evt_mask: mask of events
+ *
+ *     Create and posts an event registration message to the task. No reply
+ *     is waited for, or expected. If you do not want further notifications,
+ *     call the i2o_event_register again with a evt_mask of 0.
+ *
+ *     Returns 0 on success or -ETIMEDOUT if no message could be fetched for
+ *     sending the request.
+ */
+int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv,
+                      int tcntxt, u32 evt_mask)
+{
+       struct i2o_controller *c = dev->iop;
+       struct i2o_message *msg;
+       u32 m;
+
+       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+       if (m == I2O_QUEUE_EMPTY)
+               return -ETIMEDOUT;
+
+       writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+       writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->lct_data.
+              tid, &msg->u.head[1]);
+       writel(drv->context, &msg->u.s.icntxt);
+       writel(tcntxt, &msg->u.s.tcntxt);
+       writel(evt_mask, &msg->body[0]);
+
+       i2o_msg_post(c, m);
+
+       return 0;
+};
+
+/**
+ *     i2o_iop_init - I2O main initialization function
+ *
+ *     Initialize the I2O drivers (OSM) functions, register the Executive OSM,
+ *     initialize the I2O PCI part and finally initialize I2O device stuff.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_iop_init(void)
+{
+       int rc = 0;
+
+       printk(KERN_INFO "I2O Core - (C) Copyright 1999 Red Hat Software\n");
+
+       rc = i2o_device_init();
+       if (rc)
+               goto exit;
+
+       rc = i2o_driver_init();
+       if (rc)
+               goto device_exit;
+
+       rc = i2o_exec_init();
+       if (rc)
+               goto driver_exit;
+
+       rc = i2o_pci_init();
+       if (rc < 0)
+               goto exec_exit;
+
+       return 0;
+
+      exec_exit:
+       i2o_exec_exit();
+
+      driver_exit:
+       i2o_driver_exit();
+
+      device_exit:
+       i2o_device_exit();
+
+      exit:
+       return rc;
+}
+
+/**
+ *     i2o_iop_exit - I2O main exit function
+ *
+ *     Removes I2O controllers from PCI subsystem and shut down OSMs.
+ */
+static void __exit i2o_iop_exit(void)
+{
+       i2o_pci_exit();
+       i2o_exec_exit();
+       i2o_driver_exit();
+       i2o_device_exit();
+};
+
+module_init(i2o_iop_init);
+module_exit(i2o_iop_exit);
+
+MODULE_AUTHOR("Red Hat Software");
+MODULE_DESCRIPTION("I2O Core");
+MODULE_LICENSE("GPL");
+
+#if BITS_PER_LONG == 64
+EXPORT_SYMBOL(i2o_cntxt_list_add);
+EXPORT_SYMBOL(i2o_cntxt_list_get);
+EXPORT_SYMBOL(i2o_cntxt_list_remove);
+EXPORT_SYMBOL(i2o_cntxt_list_get_ptr);
+#endif
+EXPORT_SYMBOL(i2o_msg_get_wait);
+EXPORT_SYMBOL(i2o_msg_nop);
+EXPORT_SYMBOL(i2o_find_iop);
+EXPORT_SYMBOL(i2o_iop_find_device);
+EXPORT_SYMBOL(i2o_event_register);
+EXPORT_SYMBOL(i2o_status_get);
+EXPORT_SYMBOL(i2o_hrt_get);
+EXPORT_SYMBOL(i2o_controllers);
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
new file mode 100644 (file)
index 0000000..9ee58b6
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ *     PCI handling of I2O controller
+ *
+ *     Copyright (C) 1999-2002 Red Hat Software
+ *
+ *     Written by Alan Cox, Building Number Three Ltd
+ *
+ *     This program is free software; you can redistribute 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.
+ *
+ *     A lot of the I2O message side code from this is taken from the Red
+ *     Creek RCPCI45 adapter driver by Red Creek Communications
+ *
+ *     Fixes/additions:
+ *             Philipp Rumpf
+ *             Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ *             Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
+ *             Deepak Saxena <deepak@plexity.net>
+ *             Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
+ *             Alan Cox <alan@redhat.com>:
+ *                     Ported to Linux 2.5.
+ *             Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *                     Minor fixes for 2.6.
+ *             Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *                     Support for sysfs included.
+ */
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/i2o.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif                         // CONFIG_MTRR
+
+/* Module internal functions from other sources */
+extern struct i2o_controller *i2o_iop_alloc(void);
+extern void i2o_iop_free(struct i2o_controller *);
+
+extern int i2o_iop_add(struct i2o_controller *);
+extern void i2o_iop_remove(struct i2o_controller *);
+
+extern int i2o_driver_dispatch(struct i2o_controller *, u32,
+                              struct i2o_message *);
+
+/* PCI device id table for all I2O controllers */
+static struct pci_device_id __devinitdata i2o_pci_ids[] = {
+       {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
+       {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)},
+       {0}
+};
+
+/**
+ *     i2o_dma_realloc - Realloc DMA memory
+ *     @dev: struct device pointer to the PCI device of the I2O controller
+ *     @addr: pointer to a i2o_dma struct DMA buffer
+ *     @len: new length of memory
+ *     @gfp_mask: GFP mask
+ *
+ *     If there was something allocated in the addr, free it first. If len > 0
+ *     than try to allocate it and write the addresses back to the addr
+ *     structure. If len == 0 set the virtual address to NULL.
+ *
+ *     Returns the 0 on success or negative error code on failure.
+ */
+int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len,
+                   unsigned int gfp_mask)
+{
+       i2o_dma_free(dev, addr);
+
+       if (len)
+               return i2o_dma_alloc(dev, addr, len, gfp_mask);
+
+       return 0;
+};
+
+/**
+ *     i2o_pci_free - Frees the DMA memory for the I2O controller
+ *     @c: I2O controller to free
+ *
+ *     Remove all allocated DMA memory and unmap memory IO regions. If MTRR
+ *     is enabled, also remove it again.
+ */
+static void __devexit i2o_pci_free(struct i2o_controller *c)
+{
+       struct device *dev;
+
+       dev = &c->pdev->dev;
+
+       i2o_dma_free(dev, &c->out_queue);
+       i2o_dma_free(dev, &c->status_block);
+       if (c->lct)
+               kfree(c->lct);
+       i2o_dma_free(dev, &c->dlct);
+       i2o_dma_free(dev, &c->hrt);
+       i2o_dma_free(dev, &c->status);
+
+#ifdef CONFIG_MTRR
+       if (c->mtrr_reg0 >= 0)
+               mtrr_del(c->mtrr_reg0, 0, 0);
+       if (c->mtrr_reg1 >= 0)
+               mtrr_del(c->mtrr_reg1, 0, 0);
+#endif
+
+       if (c->raptor && c->in_queue.virt)
+               iounmap(c->in_queue.virt);
+
+       if (c->base.virt)
+               iounmap(c->base.virt);
+}
+
+/**
+ *     i2o_pci_alloc - Allocate DMA memory, map IO memory for I2O controller
+ *     @c: I2O controller
+ *
+ *     Allocate DMA memory for a PCI (or in theory AGP) I2O controller. All
+ *     IO mappings are also done here. If MTRR is enabled, also do add memory
+ *     regions here.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+static int __devinit i2o_pci_alloc(struct i2o_controller *c)
+{
+       struct pci_dev *pdev = c->pdev;
+       struct device *dev = &pdev->dev;
+       int i;
+
+       for (i = 0; i < 6; i++) {
+               /* Skip I/O spaces */
+               if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
+                       if (!c->base.phys) {
+                               c->base.phys = pci_resource_start(pdev, i);
+                               c->base.len = pci_resource_len(pdev, i);
+
+                               /*
+                                * If we know what card it is, set the size
+                                * correctly. Code is taken from dpt_i2o.c
+                                */
+                               if(pdev->device == 0xa501) {
+                                       if(pdev->subsystem_device >= 0xc032 &&
+                                          pdev->subsystem_device <= 0xc03b) {
+                                               if(c->base.len > 0x400000)
+                                                       c->base.len = 0x400000;
+                                       } else {
+                                               if(c->base.len > 0x100000)
+                                                       c->base.len = 0x100000;
+                                       }
+                               }
+                               if (!c->raptor)
+                                       break;
+                       } else {
+                               c->in_queue.phys = pci_resource_start(pdev, i);
+                               c->in_queue.len = pci_resource_len(pdev, i);
+                               break;
+                       }
+               }
+       }
+
+       if (i == 6) {
+               printk(KERN_ERR "i2o: I2O controller has no memory regions"
+                      " defined.\n");
+               i2o_pci_free(c);
+               return -EINVAL;
+       }
+
+       /* Map the I2O controller */
+       if (c->raptor) {
+               printk(KERN_INFO "i2o: PCI I2O controller\n");
+               printk(KERN_INFO "     BAR0 at 0x%08lX size=%ld\n",
+                      (unsigned long)c->base.phys, (unsigned long)c->base.len);
+               printk(KERN_INFO "     BAR1 at 0x%08lX size=%ld\n",
+                      (unsigned long)c->in_queue.phys,
+                      (unsigned long)c->in_queue.len);
+       } else
+               printk(KERN_INFO "i2o: PCI I2O controller at %08lX size=%ld\n",
+                      (unsigned long)c->base.phys, (unsigned long)c->base.len);
+
+       c->base.virt = ioremap(c->base.phys, c->base.len);
+       if (!c->base.virt) {
+               printk(KERN_ERR "i2o: Unable to map controller.\n");
+               return -ENOMEM;
+       }
+
+       if (c->raptor) {
+               c->in_queue.virt = ioremap(c->in_queue.phys, c->in_queue.len);
+               if (!c->in_queue.virt) {
+                       printk(KERN_ERR "i2o: Unable to map controller.\n");
+                       i2o_pci_free(c);
+                       return -ENOMEM;
+               }
+       } else
+               c->in_queue = c->base;
+
+       c->irq_mask = c->base.virt + 0x34;
+       c->post_port = c->base.virt + 0x40;
+       c->reply_port = c->base.virt + 0x44;
+
+#ifdef CONFIG_MTRR
+       /* Enable Write Combining MTRR for IOP's memory region */
+       c->mtrr_reg0 = mtrr_add(c->in_queue.phys, c->in_queue.len,
+                               MTRR_TYPE_WRCOMB, 1);
+       c->mtrr_reg1 = -1;
+
+       if (c->mtrr_reg0 < 0)
+               printk(KERN_WARNING "i2o: could not enable write combining "
+                      "MTRR\n");
+       else
+               printk(KERN_INFO "i2o: using write combining MTRR\n");
+
+       /*
+        * If it is an INTEL i960 I/O processor then set the first 64K to
+        * Uncacheable since the region contains the messaging unit which
+        * shouldn't be cached.
+        */
+       if ((pdev->vendor == PCI_VENDOR_ID_INTEL ||
+            pdev->vendor == PCI_VENDOR_ID_DPT) && !c->raptor) {
+               printk(KERN_INFO "i2o: MTRR workaround for Intel i960 processor"
+                      "\n");
+               c->mtrr_reg1 = mtrr_add(c->base.phys, 0x10000,
+                                       MTRR_TYPE_UNCACHABLE, 1);
+
+               if (c->mtrr_reg1 < 0) {
+                       printk(KERN_WARNING "i2o_pci: Error in setting "
+                              "MTRR_TYPE_UNCACHABLE\n");
+                       mtrr_del(c->mtrr_reg0, c->in_queue.phys,
+                                c->in_queue.len);
+                       c->mtrr_reg0 = -1;
+               }
+       }
+#endif
+
+       if (i2o_dma_alloc(dev, &c->status, 4, GFP_KERNEL)) {
+               i2o_pci_free(c);
+               return -ENOMEM;
+       }
+
+       if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt), GFP_KERNEL)) {
+               i2o_pci_free(c);
+               return -ENOMEM;
+       }
+
+       if (i2o_dma_alloc(dev, &c->dlct, 8192, GFP_KERNEL)) {
+               i2o_pci_free(c);
+               return -ENOMEM;
+       }
+
+       if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block),
+                         GFP_KERNEL)) {
+               i2o_pci_free(c);
+               return -ENOMEM;
+       }
+
+       if (i2o_dma_alloc(dev, &c->out_queue, MSG_POOL_SIZE, GFP_KERNEL)) {
+               i2o_pci_free(c);
+               return -ENOMEM;
+       }
+
+       pci_set_drvdata(pdev, c);
+
+       return 0;
+}
+
+/**
+ *     i2o_pci_interrupt - Interrupt handler for I2O controller
+ *     @irq: interrupt line
+ *     @dev_id: pointer to the I2O controller
+ *     @r: pointer to registers
+ *
+ *     Handle an interrupt from a PCI based I2O controller. This turns out
+ *     to be rather simple. We keep the controller pointer in the cookie.
+ */
+static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
+{
+       struct i2o_controller *c = dev_id;
+       struct device *dev = &c->pdev->dev;
+       struct i2o_message *m;
+       u32 mv;
+       u32 *msg;
+
+       /*
+        * Old 960 steppings had a bug in the I2O unit that caused
+        * the queue to appear empty when it wasn't.
+        */
+       mv = I2O_REPLY_READ32(c);
+       if (mv == I2O_QUEUE_EMPTY) {
+               mv = I2O_REPLY_READ32(c);
+               if (unlikely(mv == I2O_QUEUE_EMPTY)) {
+                       return IRQ_NONE;
+               } else
+                       pr_debug("960 bug detected\n");
+       }
+
+       while (mv != I2O_QUEUE_EMPTY) {
+               /*
+                * Map the message from the page frame map to kernel virtual.
+                * Because bus_to_virt is deprecated, we have calculate the
+                * location by ourself!
+                */
+               m = (struct i2o_message *)(mv -
+                                          (unsigned long)c->out_queue.phys +
+                                          (unsigned long)c->out_queue.virt);
+
+               msg = (u32 *) m;
+
+               /*
+                *      Ensure this message is seen coherently but cachably by
+                *      the processor
+                */
+               dma_sync_single_for_cpu(dev, c->out_queue.phys, MSG_FRAME_SIZE,
+                                       PCI_DMA_FROMDEVICE);
+
+               /* dispatch it */
+               if (i2o_driver_dispatch(c, mv, m))
+                       /* flush it if result != 0 */
+                       i2o_flush_reply(c, mv);
+
+               /*
+                * That 960 bug again...
+                */
+               mv = I2O_REPLY_READ32(c);
+               if (mv == I2O_QUEUE_EMPTY)
+                       mv = I2O_REPLY_READ32(c);
+       }
+       return IRQ_HANDLED;
+}
+
+/**
+ *     i2o_pci_irq_enable - Allocate interrupt for I2O controller
+ *
+ *     Allocate an interrupt for the I2O controller, and activate interrupts
+ *     on the I2O controller.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+static int i2o_pci_irq_enable(struct i2o_controller *c)
+{
+       struct pci_dev *pdev = c->pdev;
+       int rc;
+
+       I2O_IRQ_WRITE32(c, 0xffffffff);
+
+       if (pdev->irq) {
+               rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ,
+                                c->name, c);
+               if (rc < 0) {
+                       printk(KERN_ERR "%s: unable to allocate interrupt %d."
+                              "\n", c->name, pdev->irq);
+                       return rc;
+               }
+       }
+
+       I2O_IRQ_WRITE32(c, 0x00000000);
+
+       printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq);
+
+       return 0;
+}
+
+/**
+ *     i2o_pci_irq_disable - Free interrupt for I2O controller
+ *     @c: I2O controller
+ *
+ *     Disable interrupts in I2O controller and then free interrupt.
+ */
+static void i2o_pci_irq_disable(struct i2o_controller *c)
+{
+       I2O_IRQ_WRITE32(c, 0xffffffff);
+
+       if (c->pdev->irq > 0)
+               free_irq(c->pdev->irq, c);
+}
+
+/**
+ *     i2o_pci_probe - Probe the PCI device for an I2O controller
+ *     @dev: PCI device to test
+ *     @id: id which matched with the PCI device id table
+ *
+ *     Probe the PCI device for any device which is a memory of the
+ *     Intelligent, I2O class or an Adaptec Zero Channel Controller. We
+ *     attempt to set up each such device and register it with the core.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+static int __devinit i2o_pci_probe(struct pci_dev *pdev,
+                                  const struct pci_device_id *id)
+{
+       struct i2o_controller *c;
+       int rc;
+
+       printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
+
+       if ((pdev->class & 0xff) > 1) {
+               printk(KERN_WARNING "i2o: I2O controller found but does not "
+                      "support I2O 1.5 (skipping).\n");
+               return -ENODEV;
+       }
+
+       if ((rc = pci_enable_device(pdev))) {
+               printk(KERN_WARNING "i2o: I2O controller found but could not be"
+                      " enabled.\n");
+               return rc;
+       }
+
+       printk(KERN_INFO "i2o: I2O controller found on bus %d at %d.\n",
+              pdev->bus->number, pdev->devfn);
+
+       if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+               printk(KERN_WARNING "i2o: I2O controller on bus %d at %d: No "
+                      "suitable DMA available!\n", pdev->bus->number,
+                      pdev->devfn);
+               rc = -ENODEV;
+               goto disable;
+       }
+
+       pci_set_master(pdev);
+
+       c = i2o_iop_alloc();
+       if (IS_ERR(c)) {
+               printk(KERN_ERR "i2o: memory for I2O controller could not be "
+                      "allocated\n");
+               rc = PTR_ERR(c);
+               goto disable;
+       }
+
+       c->pdev = pdev;
+       c->device = pdev->dev;
+
+       /* Cards that fall apart if you hit them with large I/O loads... */
+       if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) {
+               c->short_req = 1;
+               printk(KERN_INFO "i2o: Symbios FC920 workarounds activated.\n");
+       }
+
+       if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) {
+               c->promise = 1;
+               printk(KERN_INFO "i2o: Promise workarounds activated.\n");
+       }
+
+       /* Cards that go bananas if you quiesce them before you reset them. */
+       if (pdev->vendor == PCI_VENDOR_ID_DPT) {
+               c->no_quiesce = 1;
+               if (pdev->device == 0xa511)
+                       c->raptor = 1;
+       }
+
+       if ((rc = i2o_pci_alloc(c))) {
+               printk(KERN_ERR "i2o: DMA / IO allocation for I2O controller "
+                      " failed\n");
+               goto free_controller;
+       }
+
+       if (i2o_pci_irq_enable(c)) {
+               printk(KERN_ERR "i2o: unable to enable interrupts for I2O "
+                      "controller\n");
+               goto free_pci;
+       }
+
+       if ((rc = i2o_iop_add(c)))
+               goto uninstall;
+
+       return 0;
+
+      uninstall:
+       i2o_pci_irq_disable(c);
+
+      free_pci:
+       i2o_pci_free(c);
+
+      free_controller:
+       i2o_iop_free(c);
+
+      disable:
+       pci_disable_device(pdev);
+
+       return rc;
+}
+
+/**
+ *     i2o_pci_remove - Removes a I2O controller from the system
+ *     pdev: I2O controller which should be removed
+ *
+ *     Reset the I2O controller, disable interrupts and remove all allocated
+ *     resources.
+ */
+static void __devexit i2o_pci_remove(struct pci_dev *pdev)
+{
+       struct i2o_controller *c;
+       c = pci_get_drvdata(pdev);
+
+       i2o_iop_remove(c);
+       i2o_pci_irq_disable(c);
+       i2o_pci_free(c);
+
+       printk(KERN_INFO "%s: Controller removed.\n", c->name);
+
+       i2o_iop_free(c);
+       pci_disable_device(pdev);
+};
+
+/* PCI driver for I2O controller */
+static struct pci_driver i2o_pci_driver = {
+       .name = "I2O controller",
+       .id_table = i2o_pci_ids,
+       .probe = i2o_pci_probe,
+       .remove = __devexit_p(i2o_pci_remove),
+};
+
+/**
+ *     i2o_pci_init - registers I2O PCI driver in PCI subsystem
+ *
+ *     Returns > 0 on success or negative error code on failure.
+ */
+int __init i2o_pci_init(void)
+{
+       return pci_register_driver(&i2o_pci_driver);
+};
+
+/**
+ *     i2o_pci_exit - unregisters I2O PCI driver from PCI subsystem
+ */
+void __exit i2o_pci_exit(void)
+{
+       pci_unregister_driver(&i2o_pci_driver);
+};
+
+EXPORT_SYMBOL(i2o_dma_realloc);
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
new file mode 100644 (file)
index 0000000..6b1b517
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# MMC subsystem configuration
+#
+
+menu "MMC/SD Card support"
+
+config MMC
+       tristate "MMC support"
+       help
+         MMC is the "multi-media card" bus protocol.
+
+         If you want MMC support, you should say Y here and also
+         to the specific driver for your MMC interface.
+
+config MMC_DEBUG
+       bool "MMC debugging"
+       depends on MMC != n
+       help
+         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
+       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 PXA255 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.
+
+endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
new file mode 100644 (file)
index 0000000..def0111
--- /dev/null
@@ -0,0 +1,21 @@
+#
+# 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
+
+mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
new file mode 100644 (file)
index 0000000..5c3d848
--- /dev/null
@@ -0,0 +1,913 @@
+/*
+ *  linux/drivers/mmc/mmc.c
+ *
+ *  Copyright (C) 2003-2004 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/config.h>
+#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 <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+
+#include "mmc.h"
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(x...)      printk(KERN_DEBUG x)
+#else
+#define DBG(x...)      do { } while (0)
+#endif
+
+#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 command
+ *     @host: MMC host which completed command
+ *     @mrq: MMC request which completed
+ *
+ *     MMC drivers should call this function when they have completed
+ *     their processing of a command.  This should be called before the
+ *     data part of the command has completed.
+ */
+void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
+{
+       struct mmc_command *cmd = mrq->cmd;
+       int err = mrq->cmd->error;
+       DBG("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", cmd->opcode,
+           err, 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)
+{
+       DBG("MMC: starting cmd %02x arg %08x flags %08x\n",
+           mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags);
+
+       WARN_ON(host->card_busy == NULL);
+
+       mrq->cmd->error = 0;
+       mrq->cmd->mrq = mrq;
+       if (mrq->data) {
+               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(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->card_busy == NULL);
+
+       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_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->card_busy == NULL)
+                       break;
+               spin_unlock_irqrestore(&host->lock, flags);
+               schedule();
+               spin_lock_irqsave(&host->lock, flags);
+       }
+       set_current_state(TASK_RUNNING);
+       host->card_busy = card;
+       spin_unlock_irqrestore(&host->lock, flags);
+       remove_wait_queue(&host->wq, &wait);
+
+       if (card != (void *)-1 && host->card_selected != card) {
+               struct mmc_command cmd;
+
+               host->card_selected = card;
+
+               cmd.opcode = MMC_SELECT_CARD;
+               cmd.arg = card->rca << 16;
+               cmd.flags = MMC_RSP_R1;
+
+               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+       }
+
+       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->card_busy == NULL);
+
+       spin_lock_irqsave(&host->lock, flags);
+       host->card_busy = NULL;
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       wake_up(&host->wq);
+}
+
+EXPORT_SYMBOL(mmc_release_host);
+
+/*
+ * 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_wait_for_cmd(host, &cmd, 0);
+       }
+}
+
+
+static inline void mmc_delay(unsigned int ms)
+{
+       if (ms < HZ / 1000) {
+               yield();
+               mdelay(ms);
+       } else {
+               msleep_interruptible (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;
+               host->ops->set_ios(host, &host->ios);
+       } else {
+               ocr = 0;
+       }
+
+       return ocr;
+}
+
+#define UNSTUFF_BITS(resp,start,size)                                  \
+       ({                                                              \
+               const u32 __mask = (1 << (size)) - 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);        \
+               __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));
+
+       /*
+        * The selection of the format here is guesswork based upon
+        * information people have sent to date.
+        */
+       switch (card->csd.mmca_vsn) {
+       case 0: /* MMC v1.? */
+       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.x ? */
+       case 3: /* MMC v3.x ? */
+               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",
+                       card->host->host_name, 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;
+
+       /*
+        * We only understand CSD structure v1.1 and v2.
+        * v2 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",
+                       card->host->host_name, 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);
+}
+
+/*
+ * 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;
+
+       cmd.opcode = MMC_GO_IDLE_STATE;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_NONE;
+
+       mmc_wait_for_cmd(host, &cmd, 0);
+
+       mmc_delay(1);
+}
+
+/*
+ * Apply power to the MMC stack.
+ */
+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.power_mode = MMC_POWER_UP;
+       host->ops->set_ios(host, &host->ios);
+
+       mmc_delay(1);
+
+       host->ios.clock = host->f_min;
+       host->ios.power_mode = MMC_POWER_ON;
+       host->ops->set_ios(host, &host->ios);
+
+       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.power_mode = MMC_POWER_OFF;
+       host->ops->set_ios(host, &host->ios);
+}
+
+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;
+
+       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;
+}
+
+/*
+ * 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;
+
+               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",
+                               host->host_name, 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;
+
+               cmd.opcode = MMC_SET_RELATIVE_ADDR;
+               cmd.arg = card->rca << 16;
+               cmd.flags = MMC_RSP_R1;
+
+               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;
+
+               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 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) && max_dtr > card->csd.max_dtr)
+                       max_dtr = card->csd.max_dtr;
+
+       DBG("MMC: selected %d.%03dMHz transfer rate\n",
+           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;
+
+               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;
+
+               mmc_power_up(host);
+               mmc_idle_cards(host);
+
+               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;
+               host->ops->set_ios(host, &host->ios);
+
+               /*
+                * 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.)
+        */
+       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;
+       host->ops->set_ios(host, &host->ios);
+
+       mmc_read_csds(host);
+}
+
+
+/**
+ *     mmc_detect_change - process change of state on a MMC socket
+ *     @host: host which changed state.
+ *
+ *     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)
+{
+       schedule_work(&host->detect);
+}
+
+EXPORT_SYMBOL(mmc_detect_change);
+
+
+static void mmc_rescan(void *data)
+{
+       struct mmc_host *host = data;
+       struct list_head *l, *n;
+
+       mmc_claim_host(host);
+
+       if (host->ios.power_mode == MMC_POWER_ON)
+               mmc_check_cards(host);
+
+       mmc_setup(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);
+               host->ops->set_ios(host, &host->ios);
+       }
+
+       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 = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+       if (host) {
+               memset(host, 0, sizeof(struct mmc_host) + extra);
+
+               spin_lock_init(&host->lock);
+               init_waitqueue_head(&host->wq);
+               INIT_LIST_HEAD(&host->cards);
+               INIT_WORK(&host->detect, mmc_rescan, host);
+
+               host->dev = dev;
+
+               /*
+                * 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_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
+               host->max_seg_size = PAGE_CACHE_SIZE;
+       }
+
+       return host;
+}
+
+EXPORT_SYMBOL(mmc_alloc_host);
+
+/**
+ *     mmc_add_host - initialise host hardware
+ *     @host: mmc host
+ */
+int mmc_add_host(struct mmc_host *host)
+{
+       static unsigned int host_num;
+
+       snprintf(host->host_name, sizeof(host->host_name),
+                "mmc%d", host_num++);
+
+       mmc_power_off(host);
+       mmc_detect_change(host);
+
+       return 0;
+}
+
+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);
+}
+
+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)
+{
+       flush_scheduled_work();
+       kfree(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, u32 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_detect_change(host);
+
+       return 0;
+}
+
+EXPORT_SYMBOL(mmc_resume_host);
+
+#endif
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/mmc.h b/drivers/mmc/mmc.h
new file mode 100644 (file)
index 0000000..b498dff
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  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);
+#endif
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
new file mode 100644 (file)
index 0000000..f76673a
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ * 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/sched.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/devfs_fs_kernel.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/protocol.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;
+};
+
+static DECLARE_MUTEX(open_lock);
+
+static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
+{
+       struct mmc_blk_data *md;
+
+       down(&open_lock);
+       md = disk->private_data;
+       if (md && md->usage == 0)
+               md = NULL;
+       if (md)
+               md->usage++;
+       up(&open_lock);
+
+       return md;
+}
+
+static void mmc_blk_put(struct mmc_blk_data *md)
+{
+       down(&open_lock);
+       md->usage--;
+       if (md->usage == 0) {
+               put_disk(md->disk);
+               mmc_cleanup_queue(&md->queue);
+               kfree(md);
+       }
+       up(&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;
+       }
+
+       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_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       struct block_device *bdev = inode->i_bdev;
+
+       if (cmd == HDIO_GETGEO) {
+               struct hd_geometry geo;
+
+               memset(&geo, 0, sizeof(struct hd_geometry));
+
+               geo.cylinders   = get_capacity(bdev->bd_disk) / (4 * 16);
+               geo.heads       = 4;
+               geo.sectors     = 16;
+               geo.start       = get_start_sect(bdev);
+
+               return copy_to_user((void __user *)arg, &geo, sizeof(geo))
+                       ? -EFAULT : 0;
+       }
+
+       return -ENOTTY;
+}
+
+static struct block_device_operations mmc_bdops = {
+       .open                   = mmc_blk_open,
+       .release                = mmc_blk_release,
+       .ioctl                  = mmc_blk_ioctl,
+       .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 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;
+       int ret;
+
+       if (mmc_card_claim_host(card))
+               goto cmd_err;
+
+       do {
+               struct mmc_blk_request brq;
+               struct mmc_command cmd;
+
+               memset(&brq, 0, sizeof(struct mmc_blk_request));
+               brq.mrq.cmd = &brq.cmd;
+               brq.mrq.data = &brq.data;
+
+               brq.cmd.arg = req->sector << 9;
+               brq.cmd.flags = MMC_RSP_R1;
+               brq.data.req = req;
+               brq.data.timeout_ns = card->csd.tacc_ns * 10;
+               brq.data.timeout_clks = card->csd.tacc_clks * 10;
+               brq.data.blksz_bits = md->block_bits;
+               brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
+               brq.stop.opcode = MMC_STOP_TRANSMISSION;
+               brq.stop.arg = 0;
+               brq.stop.flags = MMC_RSP_R1B;
+
+               if (rq_data_dir(req) == READ) {
+                       brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
+                       brq.data.flags |= MMC_DATA_READ;
+               } else {
+                       brq.cmd.opcode = MMC_WRITE_BLOCK;
+                       brq.cmd.flags = MMC_RSP_R1B;
+                       brq.data.flags |= MMC_DATA_WRITE;
+                       brq.data.blocks = 1;
+               }
+               brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL;
+
+               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;
+               }
+
+               do {
+                       int err;
+
+                       cmd.opcode = MMC_SEND_STATUS;
+                       cmd.arg = card->rca << 16;
+                       cmd.flags = MMC_RSP_R1;
+                       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);
+               }
+               spin_unlock_irq(&md->lock);
+       } while (ret);
+
+       mmc_card_release_host(card);
+
+       return 1;
+
+ cmd_err:
+       mmc_card_release_host(card);
+
+       /*
+        * This is a little draconian, but until we get proper
+        * error handling sorted out here, its the best we can
+        * do - especially as some hosts have no idea how much
+        * data was transferred before the error occurred.
+        */
+       spin_lock_irq(&md->lock);
+       do {
+               ret = end_that_request_chunk(req, 0,
+                               req->current_nr_sectors << 9);
+       } while (ret);
+
+       add_disk_randomness(req->rq_disk);
+       blkdev_dequeue_request(req);
+       end_that_request_last(req);
+       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 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) {
+               memset(md, 0, sizeof(struct mmc_blk_data));
+
+               md->disk = alloc_disk(1 << MMC_SHIFT);
+               if (md->disk == NULL) {
+                       kfree(md);
+                       md = ERR_PTR(-ENOMEM);
+                       goto out;
+               }
+
+               spin_lock_init(&md->lock);
+               md->usage = 1;
+
+               ret = mmc_init_queue(&md->queue, card, &md->lock);
+               if (ret) {
+                       put_disk(md->disk);
+                       kfree(md);
+                       md = ERR_PTR(ret);
+                       goto out;
+               }
+               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;
+
+               sprintf(md->disk->disk_name, "mmcblk%d", devidx);
+               sprintf(md->disk->devfs_name, "mmc/blk%d", devidx);
+
+               md->block_bits = card->csd.read_blkbits;
+
+               blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
+               set_capacity(md->disk, card->csd.capacity);
+       }
+ out:
+       return md;
+}
+
+static int
+mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
+{
+       struct mmc_command cmd;
+       int err;
+
+       mmc_card_claim_host(card);
+       cmd.opcode = MMC_SET_BLOCKLEN;
+       cmd.arg = 1 << card->csd.read_blkbits;
+       cmd.flags = MMC_RSP_R1;
+       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;
+
+       if (card->csd.cmdclass & ~0x1ff)
+               return -ENODEV;
+
+       if (card->csd.read_blkbits < 9) {
+               printk(KERN_WARNING "%s: read blocksize too small (%u)\n",
+                       mmc_card_id(card), 1 << card->csd.read_blkbits);
+               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 %dKiB\n",
+               md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
+               (card->csd.capacity << card->csd.read_blkbits) / 1024);
+
+       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;
+
+               del_gendisk(md->disk);
+
+               /*
+                * I think this is needed.
+                */
+               md->disk->queue = NULL;
+
+               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, u32 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;
+
+       devfs_mk_dir("mmc");
+       return mmc_register_driver(&mmc_driver);
+
+ out:
+       return res;
+}
+
+static void __exit mmc_blk_exit(void)
+{
+       mmc_unregister_driver(&mmc_driver);
+       devfs_remove("mmc");
+       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
new file mode 100644 (file)
index 0000000..e818b92
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ *  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/mmc/card.h>
+#include <linux/mmc/host.h>
+#include "mmc_queue.h"
+
+#define MMC_QUEUE_EXIT         (1 << 0)
+#define MMC_QUEUE_SUSPENDED    (1 << 1)
+
+/*
+ * 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 (req->flags & REQ_SPECIAL) {
+               /*
+                * Special commands already have the command
+                * blocks already setup in req->special.
+                */
+               BUG_ON(!req->special);
+
+               ret = BLKPREP_OK;
+       } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
+               /*
+                * 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->flags |= REQ_DONTPREP;
+
+       return ret;
+}
+
+static int mmc_queue_thread(void *d)
+{
+       struct mmc_queue *mq = d;
+       struct request_queue *q = mq->queue;
+       DECLARE_WAITQUEUE(wait, current);
+
+       /*
+        * 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;
+
+       daemonize("mmcqd");
+
+       complete(&mq->thread_complete);
+
+       down(&mq->thread_sem);
+       add_wait_queue(&mq->thread_wq, &wait);
+       do {
+               struct request *req = NULL;
+
+               spin_lock_irq(q->queue_lock);
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (!blk_queue_plugged(q))
+                       mq->req = req = elv_next_request(q);
+               spin_unlock(q->queue_lock);
+
+               if (!req) {
+                       if (mq->flags & MMC_QUEUE_EXIT)
+                               break;
+                       up(&mq->thread_sem);
+                       schedule();
+                       down(&mq->thread_sem);
+                       continue;
+               }
+               set_current_state(TASK_RUNNING);
+
+               mq->issue_fn(mq, req);
+       } while (1);
+       remove_wait_queue(&mq->thread_wq, &wait);
+       up(&mq->thread_sem);
+
+       complete_and_exit(&mq->thread_complete, 0);
+       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;
+
+       if (!mq->req)
+               wake_up(&mq->thread_wq);
+}
+
+/**
+ * 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 (host->dev->dma_mask && *host->dev->dma_mask)
+               limit = *host->dev->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_sectors);
+       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;
+
+       init_completion(&mq->thread_complete);
+       init_waitqueue_head(&mq->thread_wq);
+       init_MUTEX(&mq->thread_sem);
+
+       ret = kernel_thread(mmc_queue_thread, mq, CLONE_KERNEL);
+       if (ret < 0) {
+               blk_cleanup_queue(mq->queue);
+       } else {
+               wait_for_completion(&mq->thread_complete);
+               init_completion(&mq->thread_complete);
+               ret = 0;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(mmc_init_queue);
+
+void mmc_cleanup_queue(struct mmc_queue *mq)
+{
+       mq->flags |= MMC_QUEUE_EXIT;
+       wake_up(&mq->thread_wq);
+       wait_for_completion(&mq->thread_complete);
+       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
new file mode 100644 (file)
index 0000000..6bef900
--- /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 completion       thread_complete;
+       wait_queue_head_t       thread_wq;
+       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 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
new file mode 100644 (file)
index 0000000..2b7ebda
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ *  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/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)
+
+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_hotplug(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 i = 0;
+
+#define add_env(fmt,val)                                               \
+       ({                                                              \
+               int len, ret = -ENOMEM;                                 \
+               if (i < num_envp) {                                     \
+                       envp[i++] = buf;                                \
+                       len = snprintf(buf, buf_size, fmt, val) + 1;    \
+                       buf_size -= len;                                \
+                       buf += len;                                     \
+                       if (buf_size >= 0)                              \
+                               ret = 0;                                \
+               }                                                       \
+               ret;                                                    \
+       })
+
+       for (i = 0; i < 12; i++)
+               ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
+       ccc[12] = '\0';
+
+       i = 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);
+
+       return 0;
+}
+
+static int mmc_bus_suspend(struct device *dev, u32 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 struct bus_type mmc_bus_type = {
+       .name           = "mmc",
+       .match          = mmc_bus_match,
+       .hotplug        = mmc_bus_hotplug,
+       .suspend        = mmc_bus_suspend,
+       .resume         = mmc_bus_resume,
+};
+
+
+static int mmc_drv_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_drv_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;
+}
+
+
+/**
+ *     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;
+       drv->drv.probe = mmc_drv_probe;
+       drv->drv.remove = mmc_drv_remove;
+       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);
+
+
+#define MMC_ATTR(name, fmt, args...)                                   \
+static ssize_t mmc_dev_show_##name (struct device *dev, char *buf)     \
+{                                                                      \
+       struct mmc_card *card = dev_to_mmc_card(dev);                   \
+       return sprintf(buf, fmt, args);                                 \
+}                                                                      \
+static DEVICE_ATTR(name, S_IRUGO, mmc_dev_show_##name, NULL)
+
+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(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);
+
+static struct device_attribute *mmc_dev_attributes[] = {
+       &dev_attr_cid,
+       &dev_attr_csd,
+       &dev_attr_date,
+       &dev_attr_fwrev,
+       &dev_attr_hwrev,
+       &dev_attr_manfid,
+       &dev_attr_name,
+       &dev_attr_oemid,
+       &dev_attr_serial,
+};
+
+/*
+ * 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 = card->host->dev;
+       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, i;
+
+       snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+                "%s:%04x", card->host->host_name, card->rca);
+
+       ret = device_add(&card->dev);
+       if (ret == 0)
+               for (i = 0; i < ARRAY_SIZE(mmc_dev_attributes); i++)
+                       device_create_file(&card->dev, mmc_dev_attributes[i]);
+
+       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))
+               device_del(&card->dev);
+
+       put_device(&card->dev);
+}
+
+
+static int __init mmc_init(void)
+{
+       return bus_register(&mmc_bus_type);
+}
+
+static void __exit mmc_exit(void)
+{
+       bus_unregister(&mmc_bus_type);
+}
+
+module_init(mmc_init);
+module_exit(mmc_exit);
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
new file mode 100644 (file)
index 0000000..47e1636
--- /dev/null
@@ -0,0 +1,679 @@
+/*
+ *  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/config.h>
+#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/blkdev.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware/amba.h>
+#include <asm/hardware/clock.h>
+#include <asm/mach/mmc.h>
+
+#include "mmci.h"
+
+#define DRIVER_NAME "mmci-pl18x"
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(host,fmt,args...)  \
+       pr_debug("%s: %s: " fmt, host->mmc->host_name, __func__ , args)
+#else
+#define DBG(host,fmt,args...)  do { } while (0)
+#endif
+
+static unsigned int fmax = 515633;
+
+static void
+mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
+{
+       writel(0, host->base + MMCICOMMAND);
+
+       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;
+       void *base;
+
+       DBG(host, "blksz %04x blks %04x flags %08x\n",
+           1 << data->blksz_bits, data->blocks, data->flags);
+
+       host->data = data;
+       host->size = data->blocks << data->blksz_bits;
+       host->data_xfered = 0;
+
+       mmci_init_sg(host, data);
+
+       timeout = data->timeout_clks +
+                 ((unsigned long long)data->timeout_ns * host->cclk) /
+                  1000000000ULL;
+
+       base = host->base;
+       writel(timeout, base + MMCIDATATIMER);
+       writel(host->size, base + MMCIDATALENGTH);
+
+       datactrl = MCI_DPSM_ENABLE | data->blksz_bits << 4;
+       if (data->flags & MMC_DATA_READ) {
+               datactrl |= MCI_DPSM_DIRECTION;
+               irqmask = MCI_RXFIFOHALFFULLMASK;
+       } 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 *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;
+       switch (cmd->flags & MMC_RSP_MASK) {
+       case MMC_RSP_NONE:
+       default:
+               break;
+       case MMC_RSP_LONG:
+               c |= MCI_CPSM_LONGRSP;
+       case MMC_RSP_SHORT:
+               c |= MCI_CPSM_RESPONSE;
+               break;
+       }
+       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 += 1 << data->blksz_bits;
+       }
+       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;
+       }
+       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 *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) {
+               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 *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 *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 pt_regs *regs)
+{
+       struct mmci_host *host = dev_id;
+       void *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, &flags);
+
+               host->sg_off += len;
+               host->size -= len;
+               remain -= len;
+
+               if (remain)
+                       break;
+
+               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 pt_regs *regs)
+{
+       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;
+
+       DBG(host, "clock %uHz busmode %u powermode %u Vdd %u\n",
+           ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
+
+       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 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);
+
+       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_use(host->clk);
+       if (ret)
+               goto clk_free;
+
+       ret = clk_enable(host->clk);
+       if (ret)
+               goto clk_unuse;
+
+       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;
+
+       /*
+        * We can do SGIO
+        */
+       mmc->max_hw_segs = 16;
+       mmc->max_phys_segs = 16;
+
+       /*
+        * 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.
+        * Choose 64 (512-byte) sectors as the limit.
+        */
+       mmc->max_sectors = 64;
+
+       /*
+        * 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_sectors << 9;
+
+       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, SA_SHIRQ, DRIVER_NAME " (cmd)", host);
+       if (ret)
+               goto unmap;
+
+       ret = request_irq(dev->irq[1], mmci_pio_irq, SA_SHIRQ, 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%08lx irq %d,%d\n",
+               mmc->host_name, amba_rev(dev), amba_config(dev),
+               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_unuse:
+       clk_unuse(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_unuse(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, u32 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
new file mode 100644 (file)
index 0000000..ce3a026
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ *  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                    *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;
+
+       struct scatterlist      sg[NR_SG];
+       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)
+{
+       struct scatterlist *sg = host->sg;
+       struct request *req = data->req;
+
+       /*
+        * Ideally, we want the higher levels to pass us a scatter list.
+        */
+       host->sg_len = blk_rq_map_sg(req->q, req, sg);
+       host->sg_ptr = 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, unsigned long *flags)
+{
+       kunmap_atomic(host->sg_ptr->page, KM_BIO_SRC_IRQ);
+       local_irq_restore(*flags);
+}
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
new file mode 100644 (file)
index 0000000..23a5091
--- /dev/null
@@ -0,0 +1,604 @@
+/*
+ *  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/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.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/irq.h>
+#include <asm/sizes.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/mmc.h>
+
+#include "pxamci.h"
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(x...)      printk(KERN_DEBUG x)
+#else
+#define DBG(x...)      do { } while (0)
+#endif
+
+struct pxamci_host {
+       struct mmc_host         *mmc;
+       spinlock_t              lock;
+       struct resource         *res;
+       void                    *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;
+
+       dma_addr_t              dma_buf;
+       unsigned int            dma_size;
+       unsigned int            dma_dir;
+};
+
+/*
+ * The base MMC clock rate
+ */
+#define CLOCKRATE      20000000
+
+static inline unsigned int ns_to_clocks(unsigned int ns)
+{
+       return (ns * (CLOCKRATE / 1000000) + 999) / 1000;
+}
+
+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 int timeout, size;
+       dma_addr_t dma;
+       u32 dcmd;
+       int i;
+
+       host->data = data;
+
+       if (data->flags & MMC_DATA_STREAM)
+               nob = 0xffff;
+
+       writel(nob, host->base + MMC_NOB);
+       writel(1 << data->blksz_bits, host->base + MMC_BLKLEN);
+
+       timeout = ns_to_clocks(data->timeout_ns) + data->timeout_clks;
+       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_size = data->blocks << data->blksz_bits;
+       host->dma_buf = dma_map_single(mmc_dev(host->mmc), data->req->buffer,
+                                      host->dma_size, host->dma_dir);
+
+       for (i = 0, size = host->dma_size, dma = host->dma_buf; size; i++) {
+               u32 len = size;
+
+               if (len > DCMD_LENGTH)
+                       len = 0x1000;
+
+               if (data->flags & MMC_DATA_READ) {
+                       host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO;
+                       host->sg_cpu[i].dtadr = dma;
+               } else {
+                       host->sg_cpu[i].dsadr = dma;
+                       host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO;
+               }
+               host->sg_cpu[i].dcmd = dcmd | len;
+
+               dma += len;
+               size -= len;
+
+               if (size) {
+                       host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) *
+                                                sizeof(struct pxa_dma_desc);
+               } else {
+                       host->sg_cpu[i].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;
+
+       switch (cmd->flags & (MMC_RSP_MASK | MMC_RSP_CRC)) {
+       case MMC_RSP_SHORT | MMC_RSP_CRC:
+               cmdat |= CMDAT_RESP_SHORT;
+               break;
+       case MMC_RSP_SHORT:
+               cmdat |= CMDAT_RESP_R3;
+               break;
+       case MMC_RSP_LONG | MMC_RSP_CRC:
+               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)
+{
+       DBG("PXAMCI: request done\n");
+       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) {
+               cmd->error = MMC_ERR_BADCRC;
+       }
+
+       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_single(mmc_dev(host->mmc), host->dma_buf, host->dma_size,
+                        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_bits;
+       else
+               data->bytes_xfered = 0;
+
+       pxamci_disable_irq(host, DATA_TRAN_DONE);
+
+       host->data = NULL;
+       if (host->mrq->stop && data->error == MMC_ERR_NONE) {
+               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 pt_regs *regs)
+{
+       struct pxamci_host *host = devid;
+       unsigned int ireg;
+       int handled = 0;
+
+       ireg = readl(host->base + MMC_I_REG);
+
+       DBG("PXAMCI: irq %08x\n", ireg);
+
+       if (ireg) {
+               unsigned stat = readl(host->base + MMC_STAT);
+
+               DBG("PXAMCI: stat %08x\n", 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 void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct pxamci_host *host = mmc_priv(mmc);
+
+       DBG("pxamci_set_ios: clock %u power %u vdd %u.%02u\n",
+           ios->clock, ios->power_mode, ios->vdd / 100,
+           ios->vdd % 100);
+
+       if (ios->clock) {
+               unsigned int clk = CLOCKRATE / ios->clock;
+               if (CLOCKRATE / clk > ios->clock)
+                       clk <<= 1;
+               host->clkrt = fls(clk) - 1;
+
+               /*
+                * we write clkrt on the next command
+                */
+       } else if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
+               /*
+                * Ensure that the clock is off.
+                */
+               writel(STOP_CLOCK, host->base + MMC_STRPCL);
+       }
+
+       if (host->power_mode != ios->power_mode) {
+               host->power_mode = ios->power_mode;
+
+               if (host->pdata && host->pdata->setpower)
+                       host->pdata->setpower(mmc->dev, ios->vdd);
+
+               if (ios->power_mode == MMC_POWER_ON)
+                       host->cmdat |= CMDAT_INIT;
+       }
+
+       DBG("pxamci_set_ios: clkrt = %x cmdat = %x\n",
+           host->clkrt, host->cmdat);
+}
+
+static struct mmc_host_ops pxamci_ops = {
+       .request        = pxamci_request,
+       .set_ios        = pxamci_set_ios,
+};
+
+static void pxamci_dma_irq(int dma, void *devid, struct pt_regs *regs)
+{
+       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 pt_regs *regs)
+{
+       mmc_detect_change(devid);
+       return IRQ_HANDLED;
+}
+
+static int pxamci_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       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 == NO_IRQ)
+               return -ENXIO;
+
+       r = request_mem_region(r->start, SZ_4K, "PXAMCI");
+       if (!r)
+               return -EBUSY;
+
+       mmc = mmc_alloc_host(sizeof(struct pxamci_host), dev);
+       if (!mmc) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       mmc->ops = &pxamci_ops;
+       mmc->f_min = 312500;
+       mmc->f_max = 20000000;
+
+       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(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 = TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD|
+                     END_CMD_RES|PRG_DONE|DATA_TRAN_DONE;
+
+       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);
+
+       pxa_gpio_mode(GPIO6_MMCCLK_MD);
+       pxa_gpio_mode(GPIO8_MMCCS0_MD);
+       pxa_set_cken(CKEN12_MMC, 1);
+
+       host->dma = pxa_request_dma("PXAMCI", DMA_PRIO_LOW, pxamci_dma_irq, host);
+       if (host->dma < 0) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       ret = request_irq(host->irq, pxamci_irq, 0, "PXAMCI", host);
+       if (ret)
+               goto out;
+
+       dev_set_drvdata(dev, mmc);
+
+       if (host->pdata && host->pdata->init)
+               host->pdata->init(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(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 device *dev)
+{
+       struct mmc_host *mmc = dev_get_drvdata(dev);
+
+       dev_set_drvdata(dev, NULL);
+
+       if (mmc) {
+               struct pxamci_host *host = mmc_priv(mmc);
+
+               if (host->pdata && host->pdata->exit)
+                       host->pdata->exit(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);
+
+               pxa_set_cken(CKEN12_MMC, 0);
+
+               free_irq(host->irq, host);
+               pxa_free_dma(host->dma);
+               iounmap(host->base);
+               dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+
+               pxa_set_cken(CKEN12_MMC, 0);
+
+               release_resource(host->res);
+
+               mmc_free_host(mmc);
+       }
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int pxamci_suspend(struct device *dev, u32 state, u32 level)
+{
+       struct mmc_host *mmc = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (mmc && level == SUSPEND_DISABLE)
+               ret = mmc_suspend_host(mmc, state);
+
+       return ret;
+}
+
+static int pxamci_resume(struct device *dev, u32 level)
+{
+       struct mmc_host *mmc = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (mmc && level == RESUME_ENABLE)
+               ret = mmc_resume_host(mmc);
+
+       return ret;
+}
+#else
+#define pxamci_suspend NULL
+#define pxamci_resume  NULL
+#endif
+
+static struct device_driver pxamci_driver = {
+       .name           = "pxa2xx-mci",
+       .bus            = &platform_bus_type,
+       .probe          = pxamci_probe,
+       .remove         = pxamci_remove,
+       .suspend        = pxamci_suspend,
+       .resume         = pxamci_resume,
+};
+
+static int __init pxamci_init(void)
+{
+       return driver_register(&pxamci_driver);
+}
+
+static void __exit pxamci_exit(void)
+{
+       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
new file mode 100644 (file)
index 0000000..a80b24d
--- /dev/null
@@ -0,0 +1,94 @@
+#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
+#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)
+
+#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 */
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
new file mode 100644 (file)
index 0000000..104488c
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * $Id: ixp2000.c,v 1.1 2004/09/02 00:13:41 dsaxena Exp $
+ *
+ * drivers/mtd/maps/ixp2000.c
+ *
+ * Mapping for the Intel XScale IXP2000 based systems
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.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/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/flash.h>
+
+#include <linux/reboot.h>
+
+struct ixp2000_flash_info {
+       struct          mtd_info *mtd;
+       struct          map_info map;
+       struct          mtd_partition *partitions;
+       struct          resource *res;
+       int             nr_banks;
+};
+
+static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs)
+{
+       unsigned long (*set_bank)(unsigned long) =
+               (unsigned long(*)(unsigned long))map->map_priv_2;
+
+       return (set_bank ? set_bank(ofs) : ofs);
+}
+
+#ifdef __ARMEB__
+/*
+ * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which
+ * causes the lower address bits to be XORed with 0x11 on 8 bit accesses
+ * and XORed with 0x10 on 16 bit accesses. See the spec update, erratta 44.
+ */
+static int errata44_workaround = 0;
+
+static inline unsigned long address_fix8_write(unsigned long addr)
+{
+       if (errata44_workaround) {
+               return (addr ^ 3);
+       }
+       return addr;
+}
+#else
+
+#define address_fix8_write(x)  (x)
+#endif
+
+static map_word ixp2000_flash_read8(struct map_info *map, unsigned long ofs)
+{
+       map_word val;
+
+       val.x[0] =  *((u8 *)(map->map_priv_1 + flash_bank_setup(map, ofs)));
+       return val;
+}
+
+/*
+ * We can't use the standard memcpy due to the broken SlowPort
+ * address translation on rev A0 and A1 silicon and the fact that
+ * we have banked flash.
+ */
+static void ixp2000_flash_copy_from(struct map_info *map, void *to,
+                             unsigned long from, ssize_t len)
+{
+       from = flash_bank_setup(map, from);
+       while(len--)
+               *(__u8 *) to++ = *(__u8 *)(map->map_priv_1 + from++);
+}
+
+static void ixp2000_flash_write8(struct map_info *map, map_word d, unsigned long ofs)
+{
+       *(__u8 *) (address_fix8_write(map->map_priv_1 +
+                                     flash_bank_setup(map, ofs))) = d.x[0];
+}
+
+static void ixp2000_flash_copy_to(struct map_info *map, unsigned long to,
+                           const void *from, ssize_t len)
+{
+       to = flash_bank_setup(map, to);
+       while(len--) {
+               unsigned long tmp = address_fix8_write(map->map_priv_1 + to++);
+               *(__u8 *)(tmp) = *(__u8 *)(from++);
+       }
+}
+
+
+static int ixp2000_flash_remove(struct device *_dev)
+{
+       struct platform_device *dev = to_platform_device(_dev);
+       struct flash_platform_data *plat = dev->dev.platform_data;
+       struct ixp2000_flash_info *info = dev_get_drvdata(&dev->dev);
+
+       dev_set_drvdata(&dev->dev, NULL);
+
+       if(!info)
+               return 0;
+
+       if (info->mtd) {
+               del_mtd_partitions(info->mtd);
+               map_destroy(info->mtd);
+       }
+       if (info->map.map_priv_1)
+               iounmap((void *) info->map.map_priv_1);
+
+       if (info->partitions)
+               kfree(info->partitions);
+
+       if (info->res) {
+               release_resource(info->res);
+               kfree(info->res);
+       }
+
+       if (plat->exit)
+               plat->exit();
+
+       return 0;
+}
+
+
+static int ixp2000_flash_probe(struct device *_dev)
+{
+       static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
+       struct platform_device *dev = to_platform_device(_dev);
+       struct ixp2000_flash_data *ixp_data = dev->dev.platform_data;
+       struct flash_platform_data *plat;
+       struct ixp2000_flash_info *info;
+       unsigned long window_size;
+       int err = -1;
+
+       if (!ixp_data)
+               return -ENODEV;
+
+       plat = ixp_data->platform_data;
+       if (!plat)
+               return -ENODEV;
+
+       window_size = dev->resource->end - dev->resource->start + 1;
+       dev_info(_dev, "Probe of IXP2000 flash(%d banks x %dM)\n",
+                       ixp_data->nr_banks, ((u32)window_size >> 20));
+
+       if (plat->width != 1) {
+               dev_err(_dev, "IXP2000 MTD map only supports 8-bit mode, asking for %d\n",
+                               plat->width * 8);
+               return -EIO;
+       }
+
+       info = kmalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL);
+       if(!info) {
+               err = -ENOMEM;
+               goto Error;
+       }
+       memzero(info, sizeof(struct ixp2000_flash_info));
+
+       dev_set_drvdata(&dev->dev, info);
+
+       /*
+        * Tell the MTD layer we're not 1:1 mapped so that it does
+        * not attempt to do a direct access on us.
+        */
+       info->map.phys = NO_XIP;
+
+       info->nr_banks = ixp_data->nr_banks;
+       info->map.size = ixp_data->nr_banks * window_size;
+       info->map.bankwidth = 1;
+
+       /*
+        * map_priv_2 is used to store a ptr to to the bank_setup routine
+        */
+       info->map.map_priv_2 = (u32) ixp_data->bank_setup;
+
+       info->map.name = dev->dev.bus_id;
+       info->map.read = ixp2000_flash_read8;
+       info->map.write = ixp2000_flash_write8;
+       info->map.copy_from = ixp2000_flash_copy_from;
+       info->map.copy_to = ixp2000_flash_copy_to;
+
+       info->res = request_mem_region(dev->resource->start,
+                       dev->resource->end - dev->resource->start + 1,
+                       dev->dev.bus_id);
+       if (!info->res) {
+               dev_err(_dev, "Could not reserve memory region\n");
+               err = -ENOMEM;
+               goto Error;
+       }
+
+       info->map.map_priv_1 =
+           (unsigned long) ioremap(dev->resource->start,
+                                   dev->resource->end - dev->resource->start + 1);
+       if (!info->map.map_priv_1) {
+               dev_err(_dev, "Failed to ioremap flash region\n");
+               err = -EIO;
+               goto Error;
+       }
+
+       /*
+        * Setup read mode for FLASH
+        */
+       *IXP2000_SLOWPORT_FRM = 1;
+
+#if defined(__ARMEB__)
+       /*
+        * Enable errata 44 workaround for NPUs with broken slowport
+        */
+
+       errata44_workaround = ixp2000_has_broken_slowport();
+       dev_info(_dev, "Errata 44 workaround %s\n",
+              errata44_workaround ? "enabled" : "disabled");
+#endif
+
+       info->mtd = do_map_probe(plat->map_name, &info->map);
+       if (!info->mtd) {
+               dev_err(_dev, "map_probe failed\n");
+               err = -ENXIO;
+               goto Error;
+       }
+       info->mtd->owner = THIS_MODULE;
+
+       err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
+       if (err > 0) {
+               err = add_mtd_partitions(info->mtd, info->partitions, err);
+               if(err)
+                       dev_err(_dev, "Could not parse partitions\n");
+       }
+
+       if (err)
+               goto Error;
+
+       return 0;
+
+Error:
+       ixp2000_flash_remove(_dev);
+       return err;
+}
+
+static struct device_driver ixp2000_flash_driver = {
+       .name           = "IXP2000-Flash",
+       .bus            = &platform_bus_type,
+       .probe          = &ixp2000_flash_probe,
+       .remove         = &ixp2000_flash_remove
+};
+
+static int __init ixp2000_flash_init(void)
+{
+       return driver_register(&ixp2000_flash_driver);
+}
+
+static void __exit ixp2000_flash_exit(void)
+{
+       driver_unregister(&ixp2000_flash_driver);
+}
+
+module_init(ixp2000_flash_init);
+module_exit(ixp2000_flash_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
+
index 7ebc8cc..1770b1a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ixp4xx.c,v 1.3 2004/07/12 22:38:29 dwmw2 Exp $
+ * $Id: ixp4xx.c,v 1.6 2004/09/17 00:25:06 gleixner Exp $
  *
  * drivers/mtd/maps/ixp4xx.c
  *
@@ -69,9 +69,22 @@ static void ixp4xx_copy_from(struct map_info *map, void *to,
                dest[len - 1] = BYTE0(src[i]);
 }
 
+/*
+ * Unaligned writes are ignored, causing the 8-bit
+ * probe to fail and proceed to the 16-bit probe (which succeeds).
+ */
+static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
+{
+       if (!(adr & 1))
+              *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
+}
+
+/*
+ * Fast write16 function without the probing check above
+ */
 static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
 {
-       *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
+       *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
 }
 
 struct ixp4xx_flash_info {
@@ -88,6 +101,7 @@ static int ixp4xx_flash_remove(struct device *_dev)
        struct platform_device *dev = to_platform_device(_dev);
        struct flash_platform_data *plat = dev->dev.platform_data;
        struct ixp4xx_flash_info *info = dev_get_drvdata(&dev->dev);
+       map_word d;
 
        dev_set_drvdata(&dev->dev, NULL);
 
@@ -97,7 +111,8 @@ static int ixp4xx_flash_remove(struct device *_dev)
        /*
         * This is required for a soft reboot to work.
         */
-       ixp4xx_write16(&info->map, 0xff, 0x55 * 0x2);
+       d.x[0] = 0xff;
+       ixp4xx_write16(&info->map, d, 0x55 * 0x2);
 
        if (info->mtd) {
                del_mtd_partitions(info->mtd);
@@ -169,7 +184,7 @@ static int ixp4xx_flash_probe(struct device *_dev)
        info->map.bankwidth = 2;
        info->map.name = dev->dev.bus_id;
        info->map.read = ixp4xx_read16,
-       info->map.write = ixp4xx_write16,
+       info->map.write = ixp4xx_probe_write16,
        info->map.copy_from = ixp4xx_copy_from,
 
        info->res = request_mem_region(dev->resource->start, 
@@ -182,7 +197,7 @@ static int ixp4xx_flash_probe(struct device *_dev)
        }
 
        info->map.map_priv_1 =
-           (unsigned long) ioremap(dev->resource->start, 
+           (void __iomem *) ioremap(dev->resource->start,
                                    dev->resource->end - dev->resource->start + 1);
        if (!info->map.map_priv_1) {
                printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n");
@@ -198,6 +213,9 @@ static int ixp4xx_flash_probe(struct device *_dev)
        }
        info->mtd->owner = THIS_MODULE;
 
+       /* Use the fast version */
+       info->map.write = ixp4xx_write16,
+
        err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
        if (err > 0) {
                err = add_mtd_partitions(info->mtd, info->partitions, err);
index 62dd139..1b18b3a 100644 (file)
@@ -1698,7 +1698,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        /* Configure DMA attributes. */
-       if ((sizeof(dma_addr_t) > 32) &&
+       if ((sizeof(dma_addr_t) > 4) &&
            !pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL) &&
            !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
                pci_using_dac = 1;
index 22e7dfb..04dcacd 100644 (file)
@@ -41,6 +41,8 @@
                          module by all drivers that require it.
   Alan Cox             : Spinlocking work, added 'BUG_83C690'
   Paul Gortmaker       : Separate out Tx timeout code from Tx path.
+  Paul Gortmaker       : Remove old unused single Tx buffer code.
+  Hayato Fujiwara      : Add m32r support.
 
   Sources:
   The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
@@ -218,6 +220,15 @@ void ei_tx_timeout(struct net_device *dev)
        int txsr, isr, tickssofar = jiffies - dev->trans_start;
        unsigned long flags;
 
+#if defined(CONFIG_M32R) && defined(CONFIG_SMP)
+       unsigned long icucr;
+
+       local_irq_save(flags);
+       icucr = inl(ICUCR1);
+       icucr |= M32R_ICUCR_ISMOD11;
+       outl(icucr, ICUCR1);
+       local_irq_restore(flags);
+#endif
        ei_local->stat.tx_errors++;
 
        spin_lock_irqsave(&ei_local->page_lock, flags);
@@ -289,8 +300,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
     
-#ifdef EI_PINGPONG
-
        /*
         * We have two Tx slots available for use. Find the first free
         * slot, and then perform some sanity checks. With two Tx bufs,
@@ -309,7 +318,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
        else if (ei_local->tx2 == 0) 
        {
-               output_page = ei_local->tx_start_page + TX_1X_PAGES;
+               output_page = ei_local->tx_start_page + TX_PAGES/2;
                ei_local->tx2 = send_length;
                if (ei_debug  &&  ei_local->tx1 > 0)
                        printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
@@ -366,28 +375,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
        else
                netif_start_queue(dev);
 
-#else  /* EI_PINGPONG */
-
-       /*
-        * Only one Tx buffer in use. You need two Tx bufs to come close to
-        * back-to-back transmits. Expect a 20 -> 25% performance hit on
-        * reasonable hardware if you only use one Tx buffer.
-        */
-
-       if (length == send_length)
-               ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
-       else {
-               memset(scratch, 0, ETH_ZLEN);
-               memcpy(scratch, skb->data, skb->len);
-               ei_block_output(dev, ETH_ZLEN, scratch, ei_local->tx_start_page);
-       }
-       ei_local->txing = 1;
-       NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
-       dev->trans_start = jiffies;
-       netif_stop_queue(dev);
-
-#endif /* EI_PINGPONG */
-
        /* Turn 8390 interrupts back on. */
        ei_local->irqlock = 0;
        outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -590,8 +577,6 @@ static void ei_tx_intr(struct net_device *dev)
     
        outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
 
-#ifdef EI_PINGPONG
-
        /*
         * There are two Tx buffers, see which one finished, and trigger
         * the send of another one if it exists.
@@ -634,13 +619,6 @@ static void ei_tx_intr(struct net_device *dev)
 //     else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
 //                     dev->name, ei_local->lasttx);
 
-#else  /* EI_PINGPONG */
-       /*
-        *  Single Tx buffer: mark it free so another packet can be loaded.
-        */
-       ei_local->txing = 0;
-#endif
-
        /* Minimize Tx latency: update the statistics after we restart TXing. */
        if (status & ENTSR_COL)
                ei_local->stat.collisions++;
index ca57a7a..91fa987 100755 (executable)
@@ -719,7 +719,7 @@ static int amd8111e_tx(struct net_device *dev)
        return 0;
 }
 
-#if CONFIG_AMD8111E_NAPI 
+#ifdef CONFIG_AMD8111E_NAPI
 /* This function handles the driver receive operation in polling mode */
 static int amd8111e_rx_poll(struct net_device *dev, int * budget)
 {
index 77ff7df..edcc387 100644 (file)
@@ -231,7 +231,7 @@ err_free_irq:
 static int arcrimi_reset(struct net_device *dev, int really_reset)
 {
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-       void *ioaddr = lp->mem_start + 0x800;
+       void __iomem *ioaddr = lp->mem_start + 0x800;
 
        BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
 
@@ -252,7 +252,7 @@ static int arcrimi_reset(struct net_device *dev, int really_reset)
 static void arcrimi_setmask(struct net_device *dev, int mask)
 {
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-       void *ioaddr = lp->mem_start + 0x800;
+       void __iomem *ioaddr = lp->mem_start + 0x800;
 
        AINTMASK(mask);
 }
@@ -260,7 +260,7 @@ static void arcrimi_setmask(struct net_device *dev, int mask)
 static int arcrimi_status(struct net_device *dev)
 {
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-       void *ioaddr = lp->mem_start + 0x800;
+       void __iomem *ioaddr = lp->mem_start + 0x800;
 
        return ASTATUS();
 }
@@ -268,7 +268,7 @@ static int arcrimi_status(struct net_device *dev)
 static void arcrimi_command(struct net_device *dev, int cmd)
 {
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-       void *ioaddr = lp->mem_start + 0x800;
+       void __iomem *ioaddr = lp->mem_start + 0x800;
 
        ACOMMAND(cmd);
 }
@@ -277,7 +277,7 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
                                 void *buf, int count)
 {
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-       void *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
+       void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
        TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
 }
 
@@ -286,7 +286,7 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse
                                   void *buf, int count)
 {
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-       void *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
+       void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
        TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
 }
 
index 49f5cee..a76519a 100644 (file)
@@ -1285,7 +1285,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
        int res = 1;
 
        skb->mac.raw = (unsigned char *)skb->data;
-       eth_data = (struct ethhdr *)skb->data;
+       eth_data = eth_hdr(skb);
 
        /* make sure that the curr_active_slave and the slaves list do
         * not change during tx
index f1507b5..b0ef7ad 100644 (file)
 
 #include <linux/config.h>
 
+#ifdef CONFIG_ARCH_IXDP2X01
+/* IXDP2401/IXDP2801 uses dword-aligned register addressing */
+#define CS89x0_PORT(reg) ((reg) * 2)
+#else
+#define CS89x0_PORT(reg) (reg)
+#endif
+
 #define PP_ChipID 0x0000       /* offset   0h -> Corp -ID              */
                                /* offset   2h -> Model/Product Number  */
                                /* offset   3h -> Chip Revision Number  */
 #define RAM_SIZE       0x1000       /*  The card has 4k bytes or RAM */
 #define PKT_START PP_TxFrame  /*  Start of packet RAM */
 
-#define RX_FRAME_PORT  0x0000
+#define RX_FRAME_PORT  CS89x0_PORT(0x0000)
 #define TX_FRAME_PORT RX_FRAME_PORT
-#define TX_CMD_PORT    0x0004
+#define TX_CMD_PORT    CS89x0_PORT(0x0004)
 #define TX_NOW         0x0000       /*  Tx packet after   5 bytes copied */
 #define TX_AFTER_381   0x0040       /*  Tx packet after 381 bytes copied */
 #define TX_AFTER_ALL   0x00c0       /*  Tx packet after all bytes copied */
-#define TX_LEN_PORT    0x0006
-#define ISQ_PORT       0x0008
-#define ADD_PORT       0x000A
-#define DATA_PORT      0x000C
+#define TX_LEN_PORT    CS89x0_PORT(0x0006)
+#define ISQ_PORT       CS89x0_PORT(0x0008)
+#define ADD_PORT       CS89x0_PORT(0x000A)
+#define DATA_PORT      CS89x0_PORT(0x000C)
 
 #define EEPROM_WRITE_EN                0x00F0
 #define EEPROM_WRITE_DIS       0x0000
index 86302fa..d463673 100644 (file)
@@ -92,7 +92,7 @@ enum dl2x_offsets {
        EepromCtrl = 0x4a,
        ExpromAddr = 0x4c,
        Exprodata = 0x50,
-       WakeEvent0x51,
+       WakeEvent = 0x51,
        CountDown = 0x54,
        IntStatusAck = 0x5a,
        IntEnable = 0x5c,
diff --git a/drivers/net/gt64240eth.h b/drivers/net/gt64240eth.h
new file mode 100644 (file)
index 0000000..7e7af0d
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 Patton Electronics Company
+ * Copyright (C) 2002 Momentum Computer
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             stevel@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms 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.
+ *
+ * Ethernet driver definitions for the MIPS GT96100 Advanced
+ * Communication Controller.
+ * 
+ * Modified for the Marvellous GT64240 Retarded Communication Controller.
+ */
+#ifndef _GT64240ETH_H
+#define _GT64240ETH_H
+
+#include <asm/gt64240.h>
+
+#define ETHERNET_PORTS_DIFFERENCE_OFFSETS      0x400
+
+/* Translate those weanie names from Galileo/VxWorks header files: */
+
+#define GT64240_MRR                    MAIN_ROUTING_REGISTER
+#define GT64240_CIU_ARBITER_CONFIG     COMM_UNIT_ARBITER_CONFIGURATION_REGISTER
+#define GT64240_CIU_ARBITER_CONTROL    COMM_UNIT_ARBITER_CONTROL
+#define GT64240_MAIN_LOW_CAUSE         LOW_INTERRUPT_CAUSE_REGISTER
+#define GT64240_MAIN_HIGH_CAUSE        HIGH_INTERRUPT_CAUSE_REGISTER
+#define GT64240_CPU_LOW_MASK           CPU_INTERRUPT_MASK_REGISTER_LOW
+#define GT64240_CPU_HIGH_MASK          CPU_INTERRUPT_MASK_REGISTER_HIGH
+#define GT64240_CPU_SELECT_CAUSE       CPU_SELECT_CAUSE_REGISTER
+
+#define GT64240_ETH_PHY_ADDR_REG       ETHERNET_PHY_ADDRESS_REGISTER
+#define GT64240_ETH_PORT_CONFIG        ETHERNET0_PORT_CONFIGURATION_REGISTER
+#define GT64240_ETH_PORT_CONFIG_EXT    ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER
+#define GT64240_ETH_PORT_COMMAND       ETHERNET0_PORT_COMMAND_REGISTER
+#define GT64240_ETH_PORT_STATUS        ETHERNET0_PORT_STATUS_REGISTER
+#define GT64240_ETH_IO_SIZE            ETHERNET_PORTS_DIFFERENCE_OFFSETS
+#define GT64240_ETH_SMI_REG            ETHERNET_SMI_REGISTER
+#define GT64240_ETH_MIB_COUNT_BASE     ETHERNET0_MIB_COUNTER_BASE
+#define GT64240_ETH_SDMA_CONFIG        ETHERNET0_SDMA_CONFIGURATION_REGISTER
+#define GT64240_ETH_SDMA_COMM          ETHERNET0_SDMA_COMMAND_REGISTER
+#define GT64240_ETH_INT_MASK           ETHERNET0_INTERRUPT_MASK_REGISTER
+#define GT64240_ETH_INT_CAUSE          ETHERNET0_INTERRUPT_CAUSE_REGISTER
+#define GT64240_ETH_CURR_TX_DESC_PTR0  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0
+#define GT64240_ETH_CURR_TX_DESC_PTR1  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER1
+#define GT64240_ETH_1ST_RX_DESC_PTR0   ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0
+#define GT64240_ETH_CURR_RX_DESC_PTR0  ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0
+#define GT64240_ETH_HASH_TBL_PTR       ETHERNET0_HASH_TABLE_POINTER_REGISTER
+
+/* Turn on NAPI by default */
+
+#define        GT64240_NAPI                    1
+
+/* Some 64240 settings that SHOULD eventually be setup in PROM monitor: */
+/* (Board-specific to the DSL3224 Rev A board ONLY!)                    */
+#define D3224_MPP_CTRL0_SETTING                0x66669900
+#define D3224_MPP_CTRL1_SETTING                0x00000000
+#define D3224_MPP_CTRL2_SETTING                0x00887700
+#define D3224_MPP_CTRL3_SETTING                0x00000044
+#define D3224_GPP_IO_CTRL_SETTING      0x0000e800
+#define D3224_GPP_LEVEL_CTRL_SETTING   0xf001f703
+#define D3224_GPP_VALUE_SETTING                0x00000000
+
+/* Keep the ring sizes a power of two for efficiency. */
+//-#define TX_RING_SIZE 16
+#define TX_RING_SIZE   64      /* TESTING !!! */
+#define RX_RING_SIZE   32
+#define PKT_BUF_SZ     1536    /* Size of each temporary Rx buffer. */
+
+#define RX_HASH_TABLE_SIZE 16384
+#define HASH_HOP_NUMBER 12
+
+#define NUM_INTERFACES 3
+
+#define GT64240ETH_TX_TIMEOUT HZ/4
+
+#define MIPS_GT64240_BASE 0xf4000000
+#define GT64240_ETH0_BASE (MIPS_GT64240_BASE + GT64240_ETH_PORT_CONFIG)
+#define GT64240_ETH1_BASE (GT64240_ETH0_BASE + GT64240_ETH_IO_SIZE)
+#define GT64240_ETH2_BASE (GT64240_ETH1_BASE + GT64240_ETH_IO_SIZE)
+
+#if defined(CONFIG_MIPS_DSL3224)
+#define GT64240_ETHER0_IRQ 4
+#define GT64240_ETHER1_IRQ 4
+#else
+#define GT64240_ETHER0_IRQ -1
+#define GT64240_ETHER1_IRQ -1
+#endif
+
+#define REV_GT64240  0x1
+#define REV_GT64240A 0x10
+
+#define GT64240ETH_READ(gp, offset)                                    \
+       GT_READ((gp)->port_offset + (offset))
+
+#define GT64240ETH_WRITE(gp, offset, data)                             \
+       GT_WRITE((gp)->port_offset + (offset), (data))
+
+#define GT64240ETH_SETBIT(gp, offset, bits)                            \
+       GT64240ETH_WRITE((gp), (offset),                                \
+                        GT64240ETH_READ((gp), (offset)) | (bits))
+
+#define GT64240ETH_CLRBIT(gp, offset, bits)                            \
+       GT64240ETH_WRITE((gp), (offset),                                \
+                        GT64240ETH_READ((gp), (offset)) & ~(bits))
+
+#define GT64240_READ(ofs)              GT_READ(ofs)
+#define GT64240_WRITE(ofs, data)       GT_WRITE((ofs), (data))
+
+/* Bit definitions of the SMI Reg */
+enum {
+       smirDataMask = 0xffff,
+       smirPhyAdMask = 0x1f << 16,
+       smirPhyAdBit = 16,
+       smirRegAdMask = 0x1f << 21,
+       smirRegAdBit = 21,
+       smirOpCode = 1 << 26,
+       smirReadValid = 1 << 27,
+       smirBusy = 1 << 28
+};
+
+/* Bit definitions of the Port Config Reg */
+enum pcr_bits {
+       pcrPM = 1 << 0,
+       pcrRBM = 1 << 1,
+       pcrPBF = 1 << 2,
+       pcrEN = 1 << 7,
+       pcrLPBKMask = 0x3 << 8,
+       pcrLPBKBit = 1 << 8,
+       pcrFC = 1 << 10,
+       pcrHS = 1 << 12,
+       pcrHM = 1 << 13,
+       pcrHDM = 1 << 14,
+       pcrHD = 1 << 15,
+       pcrISLMask = 0x7 << 28,
+       pcrISLBit = 28,
+       pcrACCS = 1 << 31
+};
+
+/* Bit definitions of the Port Config Extend Reg */
+enum pcxr_bits {
+       pcxrIGMP = 1,
+       pcxrSPAN = 2,
+       pcxrPAR = 4,
+       pcxrPRIOtxMask = 0x7 << 3,
+       pcxrPRIOtxBit = 3,
+       pcxrPRIOrxMask = 0x3 << 6,
+       pcxrPRIOrxBit = 6,
+       pcxrPRIOrxOverride = 1 << 8,
+       pcxrDPLXen = 1 << 9,
+       pcxrFCTLen = 1 << 10,
+       pcxrFLP = 1 << 11,
+       pcxrFCTL = 1 << 12,
+       pcxrMFLMask = 0x3 << 14,
+       pcxrMFLBit = 14,
+       pcxrMIBclrMode = 1 << 16,
+       pcxrSpeed = 1 << 18,
+       pcxrSpeeden = 1 << 19,
+       pcxrRMIIen = 1 << 20,
+       pcxrDSCPen = 1 << 21
+};
+
+/* Bit definitions of the Port Command Reg */
+enum pcmr_bits {
+       pcmrFJ = 1 << 15
+};
+
+
+/* Bit definitions of the Port Status Reg */
+enum psr_bits {
+       psrSpeed = 1,
+       psrDuplex = 2,
+       psrFctl = 4,
+       psrLink = 8,
+       psrPause = 1 << 4,
+       psrTxLow = 1 << 5,
+       psrTxHigh = 1 << 6,
+       psrTxInProg = 1 << 7
+};
+
+/* Bit definitions of the SDMA Config Reg */
+enum sdcr_bits {
+       sdcrRCMask = 0xf << 2,
+       sdcrRCBit = 2,
+       sdcrBLMR = 1 << 6,
+       sdcrBLMT = 1 << 7,
+       sdcrPOVR = 1 << 8,
+       sdcrRIFB = 1 << 9,
+       sdcrBSZMask = 0x3 << 12,
+       sdcrBSZBit = 12
+};
+
+/* Bit definitions of the SDMA Command Reg */
+enum sdcmr_bits {
+       sdcmrERD = 1 << 7,
+       sdcmrAR = 1 << 15,
+       sdcmrSTDH = 1 << 16,
+       sdcmrSTDL = 1 << 17,
+       sdcmrTXDH = 1 << 23,
+       sdcmrTXDL = 1 << 24,
+       sdcmrAT = 1 << 31
+};
+
+/* Bit definitions of the Interrupt Cause Reg */
+enum icr_bits {
+       icrRxBuffer = 1,
+       icrTxBufferHigh = 1 << 2,
+       icrTxBufferLow = 1 << 3,
+       icrTxEndHigh = 1 << 6,
+       icrTxEndLow = 1 << 7,
+       icrRxError = 1 << 8,
+       icrTxErrorHigh = 1 << 10,
+       icrTxErrorLow = 1 << 11,
+       icrRxOVR = 1 << 12,
+       icrTxUdr = 1 << 13,
+       icrRxBufferQ0 = 1 << 16,
+       icrRxBufferQ1 = 1 << 17,
+       icrRxBufferQ2 = 1 << 18,
+       icrRxBufferQ3 = 1 << 19,
+       icrRxErrorQ0 = 1 << 20,
+       icrRxErrorQ1 = 1 << 21,
+       icrRxErrorQ2 = 1 << 22,
+       icrRxErrorQ3 = 1 << 23,
+       icrMIIPhySTC = 1 << 28,
+       icrSMIdone = 1 << 29,
+       icrEtherIntSum = 1 << 31
+};
+
+
+/* The Rx and Tx descriptor lists. */
+#ifdef __LITTLE_ENDIAN
+typedef struct {
+       u32 cmdstat;
+       u16 reserved;           //-prk21aug01    u32 reserved:16;
+       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
+       u32 buff_ptr;
+       u32 next;
+} gt64240_td_t;
+
+typedef struct {
+       u32 cmdstat;
+       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
+       u16 buff_sz;            //-prk21aug01    u32 buff_sz:16;
+       u32 buff_ptr;
+       u32 next;
+} gt64240_rd_t;
+#elif defined(__BIG_ENDIAN)
+typedef struct {
+       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
+       u16 reserved;           //-prk21aug01    u32 reserved:16;
+       u32 cmdstat;
+       u32 next;
+       u32 buff_ptr;
+} gt64240_td_t;
+
+typedef struct {
+       u16 buff_sz;            //-prk21aug01    u32 buff_sz:16;
+       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
+       u32 cmdstat;
+       u32 next;
+       u32 buff_ptr;
+} gt64240_rd_t;
+#else
+#error Either __BIG_ENDIAN or __LITTLE_ENDIAN must be defined!
+#endif
+
+
+/* Values for the Tx command-status descriptor entry. */
+enum td_cmdstat {
+       txOwn = 1 << 31,
+       txAutoMode = 1 << 30,
+       txEI = 1 << 23,
+       txGenCRC = 1 << 22,
+       txPad = 1 << 18,
+       txFirst = 1 << 17,
+       txLast = 1 << 16,
+       txErrorSummary = 1 << 15,
+       txReTxCntMask = 0x0f << 10,
+       txReTxCntBit = 10,
+       txCollision = 1 << 9,
+       txReTxLimit = 1 << 8,
+       txUnderrun = 1 << 6,
+       txLateCollision = 1 << 5
+};
+
+
+/* Values for the Rx command-status descriptor entry. */
+enum rd_cmdstat {
+       rxOwn = 1 << 31,
+       rxAutoMode = 1 << 30,
+       rxEI = 1 << 23,
+       rxFirst = 1 << 17,
+       rxLast = 1 << 16,
+       rxErrorSummary = 1 << 15,
+       rxIGMP = 1 << 14,
+       rxHashExpired = 1 << 13,
+       rxMissedFrame = 1 << 12,
+       rxFrameType = 1 << 11,
+       rxShortFrame = 1 << 8,
+       rxMaxFrameLen = 1 << 7,
+       rxOverrun = 1 << 6,
+       rxCollision = 1 << 4,
+       rxCRCError = 1
+};
+
+/* Bit fields of a Hash Table Entry */
+enum hash_table_entry {
+       hteValid = 1,
+       hteSkip = 2,
+       hteRD = 4
+};
+
+// The MIB counters
+typedef struct {
+       u32 byteReceived;
+       u32 byteSent;
+       u32 framesReceived;
+       u32 framesSent;
+       u32 totalByteReceived;
+       u32 totalFramesReceived;
+       u32 broadcastFramesReceived;
+       u32 multicastFramesReceived;
+       u32 cRCError;
+       u32 oversizeFrames;
+       u32 fragments;
+       u32 jabber;
+       u32 collision;
+       u32 lateCollision;
+       u32 frames64;
+       u32 frames65_127;
+       u32 frames128_255;
+       u32 frames256_511;
+       u32 frames512_1023;
+       u32 frames1024_MaxSize;
+       u32 macRxError;
+       u32 droppedFrames;
+       u32 outMulticastFrames;
+       u32 outBroadcastFrames;
+       u32 undersizeFrames;
+} mib_counters_t;
+
+
+struct gt64240_private {
+       gt64240_rd_t *rx_ring;
+       gt64240_td_t *tx_ring;
+       // The Rx and Tx rings must be 16-byte aligned
+       dma_addr_t rx_ring_dma;
+       dma_addr_t tx_ring_dma;
+       char *hash_table;
+       // The Hash Table must be 8-byte aligned
+       dma_addr_t hash_table_dma;
+       int hash_mode;
+
+       // The Rx buffers must be 8-byte aligned
+       char *rx_buff;
+       dma_addr_t rx_buff_dma;
+       // Tx buffers (tx_skbuff[i]->data) with less than 8 bytes
+       // of payload must be 8-byte aligned
+       struct sk_buff *tx_skbuff[TX_RING_SIZE];
+       int rx_next_out;        /* The next free ring entry to receive */
+       int tx_next_in;         /* The next free ring entry to send */
+       int tx_next_out;        /* The last ring entry the ISR processed */
+       int tx_count;           /* current # of pkts waiting to be sent in Tx ring */
+       int intr_work_done;     /* number of Rx and Tx pkts processed in the isr */
+       int tx_full;            /* Tx ring is full */
+
+       mib_counters_t mib;
+       struct net_device_stats stats;
+
+       int io_size;
+       int port_num;           // 0 or 1
+       u32 port_offset;
+
+       int phy_addr;           // PHY address
+       u32 last_psr;           // last value of the port status register
+
+       int options;            /* User-settable misc. driver options. */
+       int drv_flags;
+       spinlock_t lock;        /* Serialise access to device */
+       struct mii_if_info mii_if;
+
+       u32 msg_enable;
+};
+
+#endif /* _GT64240ETH_H */
index 6b85ab3..803d5a1 100644 (file)
@@ -193,7 +193,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
 
        bpq = (struct bpqdev *)dev->priv;
 
-       eth = (struct ethhdr *)skb->mac.raw;
+       eth = eth_hdr(skb);
 
        if (!(bpq->acpt_addr[0] & 0x01) &&
            memcmp(eth->h_source, bpq->acpt_addr, ETH_ALEN))
index c7076aa..e2a28b5 100644 (file)
@@ -602,8 +602,6 @@ static int ax25_open(struct tty_struct *tty)
 
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
 
        /* Restore default settings */
        ax->dev->type = ARPHRD_AX25;
index 5310033..7436af6 100644 (file)
@@ -228,6 +228,21 @@ typedef struct emac_regs {
         (desc & EMAC_BAD_RX_PACKET)
 #endif
 
+/* SoC implementation specific EMAC register defaults */
+#if defined(CONFIG_440GP)
+#define EMAC_RWMR_DEFAULT              0x80009000
+#define EMAC_TMR0_DEFAULT              0x00000000
+#define EMAC_TMR1_DEFAULT              0xf8640000
+#elif defined(CONFIG_440GX)
+#define EMAC_RWMR_DEFAULT              0x1000a200
+#define EMAC_TMR0_DEFAULT              EMAC_TMR0_TFAE_2_32
+#define EMAC_TMR1_DEFAULT              0xa00f0000
+#else
+#define EMAC_RWMR_DEFAULT              0x0f002000
+#define EMAC_TMR0_DEFAULT              0x00000000
+#define EMAC_TMR1_DEFAULT              0x380f0000
+#endif                         /* CONFIG_440GP */
+
 /* Revision specific EMAC register defaults */
 #ifdef CONFIG_IBM_EMAC4
 #define EMAC_M1_DEFAULT                        (EMAC_M1_BASE | \
@@ -236,7 +251,7 @@ typedef struct emac_regs {
 #define EMAC_RMR_DEFAULT               (EMAC_RMR_BASE | \
                                        EMAC_RMR_RFAF_128_2048)
 #define EMAC_TMR0_XMIT                 (EMAC_TMR0_GNP0 | \
-                                       EMAC_TMR0_TFAE_128_2048)
+                                       EMAC_TMR0_DEFAULT)
 #define EMAC_TRTR_DEFAULT              EMAC_TRTR_1024
 #else                          /* !CONFIG_IBM_EMAC4 */
 #define EMAC_M1_DEFAULT                        EMAC_M1_BASE
@@ -245,19 +260,4 @@ typedef struct emac_regs {
 #define EMAC_TRTR_DEFAULT              EMAC_TRTR_1600
 #endif                         /* CONFIG_IBM_EMAC4 */
 
-/* SoC implementation specific EMAC register defaults */
-#if defined(CONFIG_440GP)
-#define EMAC_RWMR_DEFAULT              0x80009000
-#define EMAC_TMR0_DEFAULT              0x00000000
-#define EMAC_TMR1_DEFAULT              0xf8640000
-#elif defined(CONFIG_440GX)
-#define EMAC_RWMR_DEFAULT              0x1000a200
-#define EMAC_TMR0_DEFAULT              EMAC_TMR0_TFAE_128_2048
-#define EMAC_TMR1_DEFAULT              0x88810000
-#else
-#define EMAC_RWMR_DEFAULT              0x0f002000
-#define EMAC_TMR0_DEFAULT              0x00000000
-#define EMAC_TMR1_DEFAULT              0x380f0000
-#endif                         /* CONFIG_440GP */
-
 #endif
index 2ca3de0..6b0328f 100644 (file)
@@ -90,23 +90,24 @@ MODULE_PARM_DESC(skb_res, "Amount of data to reserve on skb buffs\n"
 
 #define RGMII_PRIV(ocpdev) ((struct ibm_ocp_rgmii*)ocp_get_drvdata(ocpdev))
 
-static unsigned int rgmii_enable[] =
-    { RGMII_RTBI, RGMII_RGMII, RGMII_TBI, RGMII_GMII };
+static unsigned int rgmii_enable[] = {
+       RGMII_RTBI,
+       RGMII_RGMII,
+       RGMII_TBI,
+       RGMII_GMII
+};
 
-static unsigned int rgmii_speed_mask[] = { 0,
-       0,
+static unsigned int rgmii_speed_mask[] = {
        RGMII_MII2_SPDMASK,
        RGMII_MII3_SPDMASK
 };
 
-static unsigned int rgmii_speed100[] = { 0,
-       0,
+static unsigned int rgmii_speed100[] = {
        RGMII_MII2_100MB,
        RGMII_MII3_100MB
 };
 
-static unsigned int rgmii_speed1000[] = { 0,
-       0,
+static unsigned int rgmii_speed1000[] = {
        RGMII_MII2_1000MB,
        RGMII_MII3_1000MB
 };
@@ -122,11 +123,21 @@ static unsigned int zmii_enable[][4] = {
         ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI3)},
        {ZMII_SMII3, ZMII_RMII3, ZMII_MII3, ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI2)}
 };
-static unsigned int mdi_enable[] =
-    { ZMII_MDI0, ZMII_MDI1, ZMII_MDI2, ZMII_MDI3 };
+
+static unsigned int mdi_enable[] = {
+       ZMII_MDI0,
+       ZMII_MDI1,
+       ZMII_MDI2,
+       ZMII_MDI3
+};
 
 static unsigned int zmii_speed = 0x0;
-static unsigned int zmii_speed100[] = { ZMII_MII0_100MB, ZMII_MII1_100MB };
+static unsigned int zmii_speed100[] = {
+       ZMII_MII0_100MB,
+       ZMII_MII1_100MB,
+       ZMII_MII2_100MB,
+       ZMII_MII3_100MB
+};
 
 /* Since multiple EMACs share MDIO lines in various ways, we need
  * to avoid re-using the same PHY ID in cases where the arch didn't
@@ -367,6 +378,7 @@ static void emac_close_zmii(struct ocp_device *ocpdev)
 
 int emac_phy_read(struct net_device *dev, int mii_id, int reg)
 {
+       int count;
        uint32_t stacr;
        struct ocp_enet_private *fep = dev->priv;
        emac_t *emacp = fep->emacp;
@@ -385,9 +397,13 @@ int emac_phy_read(struct net_device *dev, int mii_id, int reg)
                emacp = fep->emacp;
        }
 
-       udelay(MDIO_DELAY);
+       count = 0;
+       while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+                                       && (count++ < MDIO_DELAY))
+               udelay(1);
+       MDIO_DEBUG((" (count was %d)\n", count));
 
-       if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) {
+       if ((stacr & EMAC_STACR_OC) == 0) {
                printk(KERN_WARNING "%s: PHY read timeout #1!\n", dev->name);
                return -1;
        }
@@ -398,8 +414,11 @@ int emac_phy_read(struct net_device *dev, int mii_id, int reg)
 
        out_be32(&emacp->em0stacr, stacr);
 
-       udelay(MDIO_DELAY);
-       stacr = in_be32(&emacp->em0stacr);
+       count = 0;
+       while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+                                       && (count++ < MDIO_DELAY))
+               udelay(1);
+       MDIO_DEBUG((" (count was %d)\n", count));
 
        if ((stacr & EMAC_STACR_OC) == 0) {
                printk(KERN_WARNING "%s: PHY read timeout #2!\n", dev->name);
@@ -419,6 +438,7 @@ int emac_phy_read(struct net_device *dev, int mii_id, int reg)
 
 void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data)
 {
+       int count;
        uint32_t stacr;
        struct ocp_enet_private *fep = dev->priv;
        emac_t *emacp = fep->emacp;
@@ -437,9 +457,13 @@ void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data)
                emacp = fep->emacp;
        }
 
-       udelay(MDIO_DELAY);
+       count = 0;
+       while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+                                       && (count++ < MDIO_DELAY))
+               udelay(1);
+       MDIO_DEBUG((" (count was %d)\n", count));
 
-       if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) {
+       if ((stacr & EMAC_STACR_OC) == 0) {
                printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
                return;
        }
@@ -451,9 +475,12 @@ void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data)
 
        out_be32(&emacp->em0stacr, stacr);
 
-       udelay(MDIO_DELAY);
+       while (((stacr = in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0)
+                                       && (count++ < 5000))
+               udelay(1);
+       MDIO_DEBUG((" (count was %d)\n", count));
 
-       if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0)
+       if ((stacr & EMAC_STACR_OC) == 0)
                printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
 
        /* Check for a write error */
@@ -1940,8 +1967,6 @@ static struct ocp_driver emac_driver = {
 
 static int __init emac_init(void)
 {
-       int rc;
-
        printk(KERN_INFO DRV_NAME ": " DRV_DESC ", version " DRV_VERSION "\n");
        printk(KERN_INFO "Maintained by " DRV_AUTHOR "\n");
 
@@ -1950,13 +1975,8 @@ static int __init emac_init(void)
                       skb_res);
                skb_res = 2;
        }
-       rc = ocp_register_driver(&emac_driver);
-       if (rc < 0) {
-               ocp_unregister_driver(&emac_driver);
-               return -ENODEV;
-       }
 
-       return 0;
+       return ocp_register_driver(&emac_driver);
 }
 
 static void __exit emac_exit(void)
index 691ce4e..97e6e1e 100644 (file)
@@ -67,7 +67,7 @@
 #define TX_TIMEOUT             (2*HZ)
 
 /* MDIO latency delay */
-#define MDIO_DELAY             50
+#define MDIO_DELAY             250
 
 /* Power managment shift registers */
 #define IBM_CPM_EMMII  0       /* Shift value for MII */
index 02d847c..6597791 100644 (file)
@@ -55,8 +55,6 @@ int mal_register_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac)
 
        write_unlock_irqrestore(&mal_list_lock, flags);
 
-       MOD_INC_USE_COUNT;
-
        return 0;
 }
 
@@ -73,8 +71,6 @@ int mal_unregister_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac)
 
        write_unlock_irqrestore(&mal_list_lock, flags);
 
-       MOD_DEC_USE_COUNT;
-
        return 0;
 }
 
index 599d15b..51a470d 100644 (file)
@@ -77,6 +77,8 @@
 #define IbmVethPool1DftCnt  256
 #define IbmVethPool2DftCnt  256
 
+#define IBM_VETH_INVALID_MAP ((u16)0xffff)
+
 struct ibmveth_buff_pool {
     u32 size;
     u32 index;
index a93cda6..e16f8b2 100644 (file)
@@ -506,7 +506,7 @@ static struct net_device_stats *ioc3_get_stats(struct net_device *dev)
 
 static void ioc3_tcpudp_checksum(struct sk_buff *skb, uint32_t hwsum, int len)
 {
-       struct ethhdr *eh = skb->mac.ethernet;
+       struct ethhdr *eh = eth_hdr(skb);
        uint32_t csum, ehsum;
        unsigned int proto;
        struct iphdr *ih;
@@ -1333,7 +1333,7 @@ static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                uint32_t csum, ehsum;
                uint16_t *eh;
 
-               /* The MAC header.  skb->mac.ethernet seem the logic approach
+               /* The MAC header.  skb->mac seem the logic approach
                   to find the MAC header - except it's a NULL pointer ...  */
                eh = (uint16_t *) skb->data;
 
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
new file mode 100644 (file)
index 0000000..41d38b3
--- /dev/null
@@ -0,0 +1,2646 @@
+/*
+ * drivers/net/mv64340_eth.c - Driver for MV64340X ethernet ports
+ * Copyright (C) 2002 Matthew Dharm <mdharm@momenco.com>
+ *
+ * Based on the 64360 driver from:
+ * Copyright (C) 2002 rabeeh@galileo.co.il
+ *
+ * Copyright (C) 2003 PMC-Sierra, Inc.,
+ *     written by Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * Copyright (C) 2003 Ralf Baechle <ralf@linux-mips.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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/fcntl.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ip.h>
+#include <linux/init.h>
+#include <linux/in.h>
+#include <linux/pci.h>
+#include <linux/workqueue.h>
+#include <asm/smp.h>
+#include <linux/skbuff.h>
+#include <linux/tcp.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <net/ip.h>
+
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/types.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include "mv643xx_eth.h"
+
+/*
+ * The first part is the high level driver of the gigE ethernet ports. 
+ */
+
+/* Definition for configuring driver */
+#undef MV64340_RX_QUEUE_FILL_ON_TASK
+
+/* Constants */
+#define EXTRA_BYTES 32
+#define WRAP       ETH_HLEN + 2 + 4 + 16
+#define BUFFER_MTU dev->mtu + WRAP
+#define INT_CAUSE_UNMASK_ALL           0x0007ffff
+#define INT_CAUSE_UNMASK_ALL_EXT       0x0011ffff
+#ifdef MV64340_RX_FILL_ON_TASK
+#define INT_CAUSE_MASK_ALL             0x00000000
+#define INT_CAUSE_CHECK_BITS           INT_CAUSE_UNMASK_ALL
+#define INT_CAUSE_CHECK_BITS_EXT       INT_CAUSE_UNMASK_ALL_EXT
+#endif
+
+/* Static function declarations */
+static int mv64340_eth_real_open(struct net_device *);
+static int mv64340_eth_real_stop(struct net_device *);
+static int mv64340_eth_change_mtu(struct net_device *, int);
+static struct net_device_stats *mv64340_eth_get_stats(struct net_device *);
+static void eth_port_init_mac_tables(unsigned int eth_port_num);
+#ifdef MV64340_NAPI
+static int mv64340_poll(struct net_device *dev, int *budget);
+#endif
+
+unsigned char prom_mac_addr_base[6];
+unsigned long mv64340_sram_base;
+
+/*
+ * Changes MTU (maximum transfer unit) of the gigabit ethenret port
+ *
+ * Input : pointer to ethernet interface network device structure
+ *         new mtu size 
+ * Output : 0 upon success, -EINVAL upon failure
+ */
+static int mv64340_eth_change_mtu(struct net_device *dev, int new_mtu)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&mp->lock, flags);
+
+       if ((new_mtu > 9500) || (new_mtu < 64)) {
+               spin_unlock_irqrestore(&mp->lock, flags);
+               return -EINVAL;
+       }
+
+       dev->mtu = new_mtu;
+       /* 
+        * Stop then re-open the interface. This will allocate RX skb's with
+        * the new MTU.
+        * There is a possible danger that the open will not successed, due
+        * to memory is full, which might fail the open function.
+        */
+       if (netif_running(dev)) {
+               if (mv64340_eth_real_stop(dev))
+                       printk(KERN_ERR
+                              "%s: Fatal error on stopping device\n",
+                              dev->name);
+               if (mv64340_eth_real_open(dev))
+                       printk(KERN_ERR
+                              "%s: Fatal error on opening device\n",
+                              dev->name);
+       }
+
+       spin_unlock_irqrestore(&mp->lock, flags);
+       return 0;
+}
+
+/*
+ * mv64340_eth_rx_task
+ *                                                                    
+ * Fills / refills RX queue on a certain gigabit ethernet port
+ *
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
+ */
+static void mv64340_eth_rx_task(void *data)
+{
+       struct net_device *dev = (struct net_device *) data;
+       struct mv64340_private *mp = netdev_priv(dev);
+       struct pkt_info pkt_info;
+       struct sk_buff *skb;
+
+       if (test_and_set_bit(0, &mp->rx_task_busy))
+               panic("%s: Error in test_set_bit / clear_bit", dev->name);
+
+       while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) {
+               /* The +8 for buffer allignment and another 32 byte extra */
+
+               skb = dev_alloc_skb(BUFFER_MTU + 8 + EXTRA_BYTES);
+               if (!skb)
+                       /* Better luck next time */
+                       break;
+               mp->rx_ring_skbs++;
+               pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT;
+               pkt_info.byte_cnt = dev->mtu + ETH_HLEN + 4 + 2 + EXTRA_BYTES;
+               /* Allign buffer to 8 bytes */
+               if (pkt_info.byte_cnt & ~0x7) {
+                       pkt_info.byte_cnt &= ~0x7;
+                       pkt_info.byte_cnt += 8;
+               }
+               pkt_info.buf_ptr =
+                   pci_map_single(0, skb->data,
+                                  dev->mtu + ETH_HLEN + 4 + 2 + EXTRA_BYTES,
+                                  PCI_DMA_FROMDEVICE);
+               pkt_info.return_info = skb;
+               if (eth_rx_return_buff(mp, &pkt_info) != ETH_OK) {
+                       printk(KERN_ERR
+                              "%s: Error allocating RX Ring\n", dev->name);
+                       break;
+               }
+               skb_reserve(skb, 2);
+       }
+       clear_bit(0, &mp->rx_task_busy);
+       /*
+        * If RX ring is empty of SKB, set a timer to try allocating
+        * again in a later time .
+        */
+       if ((mp->rx_ring_skbs == 0) && (mp->rx_timer_flag == 0)) {
+               printk(KERN_INFO "%s: Rx ring is empty\n", dev->name);
+               /* After 100mSec */
+               mp->timeout.expires = jiffies + (HZ / 10);
+               add_timer(&mp->timeout);
+               mp->rx_timer_flag = 1;
+       }
+#if MV64340_RX_QUEUE_FILL_ON_TASK
+       else {
+               /* Return interrupts */
+               MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(mp->port_num),
+                        INT_CAUSE_UNMASK_ALL);
+       }
+#endif
+}
+
+/*
+ * mv64340_eth_rx_task_timer_wrapper
+ *                                                                    
+ * Timer routine to wake up RX queue filling task. This function is
+ * used only in case the RX queue is empty, and all alloc_skb has
+ * failed (due to out of memory event).
+ *
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
+ */
+static void mv64340_eth_rx_task_timer_wrapper(unsigned long data)
+{
+       struct net_device *dev = (struct net_device *) data;
+       struct mv64340_private *mp = netdev_priv(dev);
+
+       mp->rx_timer_flag = 0;
+       mv64340_eth_rx_task((void *) data);
+}
+
+
+/*
+ * mv64340_eth_update_mac_address
+ *                                                                    
+ * Update the MAC address of the port in the address table
+ *
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
+ */
+static void mv64340_eth_update_mac_address(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+       unsigned int port_num = mp->port_num;
+
+       eth_port_init_mac_tables(port_num);
+       memcpy(mp->port_mac_addr, dev->dev_addr, 6);
+       eth_port_uc_addr_set(port_num, mp->port_mac_addr);
+}
+
+/*
+ * mv64340_eth_set_rx_mode
+ *                                                                    
+ * Change from promiscuos to regular rx mode
+ *
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
+ */
+static void mv64340_eth_set_rx_mode(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+
+       if (dev->flags & IFF_PROMISC) {
+               ethernet_set_config_reg
+                   (mp->port_num,
+                    ethernet_get_config_reg(mp->port_num) |
+                    ETH_UNICAST_PROMISCUOUS_MODE);
+       } else {
+               ethernet_set_config_reg
+                   (mp->port_num,
+                    ethernet_get_config_reg(mp->port_num) &
+                    ~(unsigned int) ETH_UNICAST_PROMISCUOUS_MODE);
+       }
+}
+
+
+/*
+ * mv64340_eth_set_mac_address
+ *                                                                    
+ * Change the interface's mac address.
+ * No special hardware thing should be done because interface is always
+ * put in promiscuous mode.
+ *
+ * Input : pointer to ethernet interface network device structure and
+ *         a pointer to the designated entry to be added to the cache.
+ * Output : zero upon success, negative upon failure
+ */
+static int mv64340_eth_set_mac_address(struct net_device *dev, void *addr)
+{
+       int i;
+
+       for (i = 0; i < 6; i++)
+               /* +2 is for the offset of the HW addr type */
+               dev->dev_addr[i] = ((unsigned char *) addr)[i + 2];
+       mv64340_eth_update_mac_address(dev);
+       return 0;
+}
+
+/*
+ * mv64340_eth_tx_timeout
+ *                                                                    
+ * Called upon a timeout on transmitting a packet
+ *
+ * Input : pointer to ethernet interface network device structure.
+ * Output : N/A
+ */
+static void mv64340_eth_tx_timeout(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+
+       printk(KERN_INFO "%s: TX timeout  ", dev->name);
+
+       /* Do the reset outside of interrupt context */
+       schedule_work(&mp->tx_timeout_task);
+}
+
+/*
+ * mv64340_eth_tx_timeout_task
+ *
+ * Actual routine to reset the adapter when a timeout on Tx has occurred
+ */
+static void mv64340_eth_tx_timeout_task(struct net_device *dev)
+{
+        struct mv64340_private *mp = netdev_priv(dev);
+
+        netif_device_detach(dev);
+        eth_port_reset(mp->port_num);
+        eth_port_start(mp);
+        netif_device_attach(dev);
+}
+
+/*
+ * mv64340_eth_free_tx_queue
+ *
+ * Input : dev - a pointer to the required interface
+ *
+ * Output : 0 if was able to release skb , nonzero otherwise
+ */
+static int mv64340_eth_free_tx_queue(struct net_device *dev,
+                             unsigned int eth_int_cause_ext)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+       struct net_device_stats *stats = &mp->stats;
+       struct pkt_info pkt_info;
+       int released = 1;
+
+       if (!(eth_int_cause_ext & (BIT0 | BIT8)))
+               return released;
+
+       spin_lock(&mp->lock);
+
+       /* Check only queue 0 */
+       while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
+               if (pkt_info.cmd_sts & BIT0) {
+                       printk("%s: Error in TX\n", dev->name);
+                       stats->tx_errors++;
+               }
+
+               /* 
+                * If return_info is different than 0, release the skb.
+                * The case where return_info is not 0 is only in case
+                * when transmitted a scatter/gather packet, where only
+                * last skb releases the whole chain.
+                */
+               if (pkt_info.return_info) {
+                       dev_kfree_skb_irq((struct sk_buff *)
+                                         pkt_info.return_info);
+                       released = 0;
+                       if (skb_shinfo(pkt_info.return_info)->nr_frags)
+                               pci_unmap_page(NULL, pkt_info.buf_ptr,
+                                       pkt_info.byte_cnt, PCI_DMA_TODEVICE);
+
+                       if (mp->tx_ring_skbs != 1)
+                               mp->tx_ring_skbs--;
+               } else 
+                       pci_unmap_page(NULL, pkt_info.buf_ptr,
+                                       pkt_info.byte_cnt, PCI_DMA_TODEVICE);
+
+               /* 
+                * Decrement the number of outstanding skbs counter on
+                * the TX queue.
+                */
+               if (mp->tx_ring_skbs == 0)
+                       panic("ERROR - TX outstanding SKBs counter is corrupted");
+
+       }
+
+       spin_unlock(&mp->lock);
+
+       return released;
+}
+
+/*
+ * mv64340_eth_receive
+ *
+ * This function is forward packets that are received from the port's
+ * queues toward kernel core or FastRoute them to another interface.
+ *
+ * Input : dev - a pointer to the required interface
+ *         max - maximum number to receive (0 means unlimted)
+ *
+ * Output : number of served packets
+ */
+#ifdef MV64340_NAPI
+static int mv64340_eth_receive_queue(struct net_device *dev, unsigned int max,
+                                                               int budget)
+#else
+static int mv64340_eth_receive_queue(struct net_device *dev, unsigned int max)
+#endif
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+       struct net_device_stats *stats = &mp->stats;
+       unsigned int received_packets = 0;
+       struct sk_buff *skb;
+       struct pkt_info pkt_info;
+
+#ifdef MV64340_NAPI
+       while (eth_port_receive(mp, &pkt_info) == ETH_OK && budget > 0) {
+#else
+       while ((--max) && eth_port_receive(mp, &pkt_info) == ETH_OK) {
+#endif
+               mp->rx_ring_skbs--;
+               received_packets++;
+#ifdef MV64340_NAPI
+               budget--;
+#endif
+               /* Update statistics. Note byte count includes 4 byte CRC count */
+               stats->rx_packets++;
+               stats->rx_bytes += pkt_info.byte_cnt;
+               skb = (struct sk_buff *) pkt_info.return_info;
+               /*
+                * In case received a packet without first / last bits on OR
+                * the error summary bit is on, the packets needs to be dropeed.
+                */
+               if (((pkt_info.cmd_sts
+                     & (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) !=
+                    (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC))
+                   || (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) {
+                       stats->rx_dropped++;
+                       if ((pkt_info.cmd_sts & (ETH_RX_FIRST_DESC |
+                                                ETH_RX_LAST_DESC)) !=
+                           (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) {
+                               if (net_ratelimit())
+                                       printk(KERN_ERR
+                                              "%s: Received packet spread on multiple"
+                                              " descriptors\n",
+                                              dev->name);
+                       }
+                       if (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)
+                               stats->rx_errors++;
+
+                       dev_kfree_skb_irq(skb);
+               } else {
+                       /*
+                        * The -4 is for the CRC in the trailer of the
+                        * received packet
+                        */
+                       skb_put(skb, pkt_info.byte_cnt - 4);
+                       skb->dev = dev;
+
+                       if (pkt_info.cmd_sts & ETH_LAYER_4_CHECKSUM_OK) {
+                               skb->ip_summed = CHECKSUM_UNNECESSARY;
+                               skb->csum = htons((pkt_info.cmd_sts
+                                                       & 0x0007fff8) >> 3);
+                       }
+                       skb->protocol = eth_type_trans(skb, dev);
+#ifdef MV64340_NAPI
+                       netif_receive_skb(skb);
+#else
+                       netif_rx(skb);
+#endif
+               }
+       }
+
+       return received_packets;
+}
+
+/*
+ * mv64340_eth_int_handler
+ *
+ * Main interrupt handler for the gigbit ethernet ports
+ *
+ * Input : irq - irq number (not used)
+ *         dev_id - a pointer to the required interface's data structure
+ *         regs   - not used
+ * Output : N/A
+ */
+
+static irqreturn_t mv64340_eth_int_handler(int irq, void *dev_id,
+       struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) dev_id;
+       struct mv64340_private *mp = netdev_priv(dev);
+       u32 eth_int_cause, eth_int_cause_ext = 0;
+       unsigned int port_num = mp->port_num;
+
+       /* Read interrupt cause registers */
+       eth_int_cause = MV_READ(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num)) &
+                       INT_CAUSE_UNMASK_ALL;
+
+       if (eth_int_cause & BIT1)
+               eth_int_cause_ext =
+               MV_READ(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
+               INT_CAUSE_UNMASK_ALL_EXT;
+
+#ifdef MV64340_NAPI
+       if (!(eth_int_cause & 0x0007fffd)) {
+       /* Dont ack the Rx interrupt */
+#endif
+               /*
+                * Clear specific ethernet port intrerrupt registers by
+                * acknowleding relevant bits.
+                */
+               MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num),
+                        ~eth_int_cause);
+               if (eth_int_cause_ext != 0x0)
+                       MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),
+                                ~eth_int_cause_ext);
+
+               /* UDP change : We may need this */
+               if ((eth_int_cause_ext & 0x0000ffff) &&
+                   (mv64340_eth_free_tx_queue(dev, eth_int_cause_ext) == 0) &&
+                   (MV64340_TX_QUEUE_SIZE > mp->tx_ring_skbs + 1))
+                                         netif_wake_queue(dev);
+#ifdef MV64340_NAPI
+       } else {
+               if (netif_rx_schedule_prep(dev)) {
+                       /* Mask all the interrupts */
+                       MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),0);
+                       MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
+                       __netif_rx_schedule(dev);
+               }
+#else
+               {
+               if (eth_int_cause & (BIT2 | BIT11))
+                       mv64340_eth_receive_queue(dev, 0);
+
+               /*
+                * After forwarded received packets to upper layer,  add a task
+                * in an interrupts enabled context that refills the RX ring
+                * with skb's.
+                */
+#if MV64340_RX_QUEUE_FILL_ON_TASK
+               /* Unmask all interrupts on ethernet port */
+               MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),
+                        INT_CAUSE_MASK_ALL);
+               queue_task(&mp->rx_task, &tq_immediate);
+               mark_bh(IMMEDIATE_BH);
+#else
+               mp->rx_task.func(dev);
+#endif
+#endif
+       }
+       /* PHY status changed */
+       if (eth_int_cause_ext & (BIT16 | BIT20)) {
+               unsigned int phy_reg_data;
+
+               /* Check Link status on ethernet port */
+               eth_port_read_smi_reg(port_num, 1, &phy_reg_data);
+               if (!(phy_reg_data & 0x20)) {
+                       netif_stop_queue(dev);
+               } else {
+                       netif_wake_queue(dev);
+
+                       /*
+                        * Start all TX queues on ethernet port. This is good in
+                        * case of previous packets where not transmitted, due
+                        * to link down and this command re-enables all TX
+                        * queues.
+                        * Note that it is possible to get a TX resource error
+                        * interrupt after issuing this, since not all TX queues
+                        * are enabled, or has anything to send.
+                        */
+                       MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 1);
+               }
+       }
+
+       /*
+        * If no real interrupt occured, exit.
+        * This can happen when using gigE interrupt coalescing mechanism.
+        */
+       if ((eth_int_cause == 0x0) && (eth_int_cause_ext == 0x0))
+               return IRQ_NONE;
+
+       return IRQ_HANDLED;
+}
+
+#ifdef MV64340_COAL
+
+/*
+ * eth_port_set_rx_coal - Sets coalescing interrupt mechanism on RX path
+ *
+ * DESCRIPTION:
+ *     This routine sets the RX coalescing interrupt mechanism parameter.
+ *     This parameter is a timeout counter, that counts in 64 t_clk
+ *     chunks ; that when timeout event occurs a maskable interrupt
+ *     occurs.
+ *     The parameter is calculated using the tClk of the MV-643xx chip
+ *     , and the required delay of the interrupt in usec.
+ *
+ * INPUT:
+ *     unsigned int eth_port_num      Ethernet port number
+ *     unsigned int t_clk        t_clk of the MV-643xx chip in HZ units
+ *     unsigned int delay       Delay in usec
+ *
+ * OUTPUT:
+ *     Interrupt coalescing mechanism value is set in MV-643xx chip.
+ *
+ * RETURN:
+ *     The interrupt coalescing value set in the gigE port.
+ *
+ */
+static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
+       unsigned int t_clk, unsigned int delay)
+{
+       unsigned int coal = ((t_clk / 1000000) * delay) / 64;
+
+       /* Set RX Coalescing mechanism */
+       MV_WRITE(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num),
+                ((coal & 0x3fff) << 8) |
+                (MV_READ(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num))
+                 & 0xffc000ff));
+
+       return coal;
+}
+#endif
+
+/*
+ * eth_port_set_tx_coal - Sets coalescing interrupt mechanism on TX path
+ *
+ * DESCRIPTION:
+ *     This routine sets the TX coalescing interrupt mechanism parameter.
+ *     This parameter is a timeout counter, that counts in 64 t_clk
+ *     chunks ; that when timeout event occurs a maskable interrupt
+ *     occurs.
+ *     The parameter is calculated using the t_cLK frequency of the 
+ *     MV-643xx chip and the required delay in the interrupt in uSec
+ *
+ * INPUT:
+ *     unsigned int eth_port_num      Ethernet port number
+ *     unsigned int t_clk        t_clk of the MV-643xx chip in HZ units
+ *     unsigned int delay       Delay in uSeconds
+ *
+ * OUTPUT:
+ *     Interrupt coalescing mechanism value is set in MV-643xx chip.
+ *
+ * RETURN:
+ *     The interrupt coalescing value set in the gigE port.
+ *
+ */
+static unsigned int eth_port_set_tx_coal(unsigned int eth_port_num,
+       unsigned int t_clk, unsigned int delay)
+{
+       unsigned int coal;
+       coal = ((t_clk / 1000000) * delay) / 64;
+       /* Set TX Coalescing mechanism */
+       MV_WRITE(MV64340_ETH_TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num),
+                coal << 4);
+       return coal;
+}
+
+/*
+ * mv64340_eth_open
+ *
+ * This function is called when openning the network device. The function
+ * should initialize all the hardware, initialize cyclic Rx/Tx
+ * descriptors chain and buffers and allocate an IRQ to the network
+ * device.
+ *
+ * Input : a pointer to the network device structure
+ *
+ * Output : zero of success , nonzero if fails.
+ */
+
+static int mv64340_eth_open(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+       unsigned int port_num = mp->port_num;
+       int err = err;
+
+       spin_lock_irq(&mp->lock);
+
+       err = request_irq(dev->irq, mv64340_eth_int_handler,
+                         SA_INTERRUPT | SA_SAMPLE_RANDOM, dev->name, dev);
+
+       if (err) {
+               printk(KERN_ERR "Can not assign IRQ number to MV64340_eth%d\n",
+                      port_num);
+               err = -EAGAIN;
+               goto out;
+       }
+
+       if (mv64340_eth_real_open(dev)) {
+               printk("%s: Error opening interface\n", dev->name);
+               err = -EBUSY;
+               goto out_free;
+       }
+
+       spin_unlock_irq(&mp->lock);
+
+       return 0;
+
+out_free:
+       free_irq(dev->irq, dev);
+
+out:
+       spin_unlock_irq(&mp->lock);
+
+       return err;
+}
+
+/*
+ * ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
+ *
+ * DESCRIPTION:
+ *       This function prepares a Rx chained list of descriptors and packet 
+ *       buffers in a form of a ring. The routine must be called after port 
+ *       initialization routine and before port start routine. 
+ *       The Ethernet SDMA engine uses CPU bus addresses to access the various 
+ *       devices in the system (i.e. DRAM). This function uses the ethernet 
+ *       struct 'virtual to physical' routine (set by the user) to set the ring 
+ *       with physical addresses.
+ *
+ * INPUT:
+ *     struct mv64340_private   *mp   Ethernet Port Control srtuct. 
+ *      int                    rx_desc_num       Number of Rx descriptors
+ *      int                    rx_buff_size      Size of Rx buffer
+ *      unsigned int    rx_desc_base_addr  Rx descriptors memory area base addr.
+ *      unsigned int    rx_buff_base_addr  Rx buffer memory area base addr.
+ *
+ * OUTPUT:
+ *      The routine updates the Ethernet port control struct with information 
+ *      regarding the Rx descriptors and buffers.
+ *
+ * RETURN:
+ *      false if the given descriptors memory area is not aligned according to
+ *      Ethernet SDMA specifications.
+ *      true otherwise.
+ */
+static int ether_init_rx_desc_ring(struct mv64340_private * mp,
+       unsigned long rx_buff_base_addr)
+{
+       unsigned long buffer_addr = rx_buff_base_addr;
+       volatile struct eth_rx_desc *p_rx_desc;
+       int rx_desc_num = mp->rx_ring_size;
+       unsigned long rx_desc_base_addr = (unsigned long) mp->p_rx_desc_area;
+       int rx_buff_size = 1536;        /* Dummy, will be replaced later */
+       int i;
+
+       p_rx_desc = (struct eth_rx_desc *) rx_desc_base_addr;
+
+       /* Rx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */
+       if (rx_buff_base_addr & 0xf)
+               return 0;
+
+       /* Rx buffers are limited to 64K bytes and Minimum size is 8 bytes  */
+       if ((rx_buff_size < 8) || (rx_buff_size > RX_BUFFER_MAX_SIZE))
+               return 0;
+
+       /* Rx buffers must be 64-bit aligned.       */
+       if ((rx_buff_base_addr + rx_buff_size) & 0x7)
+               return 0;
+
+       /* initialize the Rx descriptors ring */
+       for (i = 0; i < rx_desc_num; i++) {
+               p_rx_desc[i].buf_size = rx_buff_size;
+               p_rx_desc[i].byte_cnt = 0x0000;
+               p_rx_desc[i].cmd_sts =
+                       ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
+               p_rx_desc[i].next_desc_ptr = mp->rx_desc_dma +
+                       ((i + 1) % rx_desc_num) * sizeof(struct eth_rx_desc);
+               p_rx_desc[i].buf_ptr = buffer_addr;
+
+               mp->rx_skb[i] = NULL;
+               buffer_addr += rx_buff_size;
+       }
+
+       /* Save Rx desc pointer to driver struct. */
+       mp->rx_curr_desc_q = 0;
+       mp->rx_used_desc_q = 0;
+
+       mp->rx_desc_area_size = rx_desc_num * sizeof(struct eth_rx_desc);
+
+       mp->port_rx_queue_command |= 1;
+
+       return 1;
+}
+
+/*
+ * ether_init_tx_desc_ring - Curve a Tx chain desc list and buffer in memory.
+ *
+ * DESCRIPTION:
+ *       This function prepares a Tx chained list of descriptors and packet 
+ *       buffers in a form of a ring. The routine must be called after port 
+ *       initialization routine and before port start routine. 
+ *       The Ethernet SDMA engine uses CPU bus addresses to access the various 
+ *       devices in the system (i.e. DRAM). This function uses the ethernet 
+ *       struct 'virtual to physical' routine (set by the user) to set the ring 
+ *       with physical addresses.
+ *
+ * INPUT:
+ *     struct mv64340_private   *mp   Ethernet Port Control srtuct. 
+ *      int            tx_desc_num        Number of Tx descriptors
+ *      int            tx_buff_size       Size of Tx buffer
+ *      unsigned int    tx_desc_base_addr  Tx descriptors memory area base addr.
+ *
+ * OUTPUT:
+ *      The routine updates the Ethernet port control struct with information 
+ *      regarding the Tx descriptors and buffers.
+ *
+ * RETURN:
+ *      false if the given descriptors memory area is not aligned according to
+ *      Ethernet SDMA specifications.
+ *      true otherwise.
+ */
+static int ether_init_tx_desc_ring(struct mv64340_private *mp)
+{
+       unsigned long tx_desc_base_addr = (unsigned long) mp->p_tx_desc_area;
+       int tx_desc_num = mp->tx_ring_size;
+       struct eth_tx_desc *p_tx_desc;
+       int i;
+
+       /* Tx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */
+       if (tx_desc_base_addr & 0xf)
+               return 0;
+
+       /* save the first desc pointer to link with the last descriptor */
+       p_tx_desc = (struct eth_tx_desc *) tx_desc_base_addr;
+
+       /* Initialize the Tx descriptors ring */
+       for (i = 0; i < tx_desc_num; i++) {
+               p_tx_desc[i].byte_cnt   = 0x0000;
+               p_tx_desc[i].l4i_chk    = 0x0000;
+               p_tx_desc[i].cmd_sts    = 0x00000000;
+               p_tx_desc[i].next_desc_ptr = mp->tx_desc_dma +
+                       ((i + 1) % tx_desc_num) * sizeof(struct eth_tx_desc);
+               p_tx_desc[i].buf_ptr    = 0x00000000;
+               mp->tx_skb[i]           = NULL;
+       }
+
+       /* Set Tx desc pointer in driver struct. */
+       mp->tx_curr_desc_q = 0;
+       mp->tx_used_desc_q = 0;
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+        mp->tx_first_desc_q = 0;
+#endif
+       /* Init Tx ring base and size parameters */
+       mp->tx_desc_area_size   = tx_desc_num * sizeof(struct eth_tx_desc);
+
+       /* Add the queue to the list of Tx queues of this port */
+       mp->port_tx_queue_command |= 1;
+
+       return 1;
+}
+
+/* Helper function for mv64340_eth_open */
+static int mv64340_eth_real_open(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+       unsigned int port_num = mp->port_num;
+       u32 phy_reg_data;
+       unsigned int size;
+
+       /* Stop RX Queues */
+       MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
+                0x0000ff00);
+
+       /* Clear the ethernet port interrupts */
+       MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+       MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+
+       /* Unmask RX buffer and TX end interrupt */
+       MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),
+                INT_CAUSE_UNMASK_ALL);
+
+       /* Unmask phy and link status changes interrupts */
+       MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+                INT_CAUSE_UNMASK_ALL_EXT);
+
+       /* Set the MAC Address */
+       memcpy(mp->port_mac_addr, dev->dev_addr, 6);
+
+       eth_port_init(mp);
+
+       INIT_WORK(&mp->rx_task, (void (*)(void *)) mv64340_eth_rx_task, dev);
+
+       memset(&mp->timeout, 0, sizeof(struct timer_list));
+       mp->timeout.function = mv64340_eth_rx_task_timer_wrapper;
+       mp->timeout.data = (unsigned long) dev;
+
+       mp->rx_task_busy = 0;
+       mp->rx_timer_flag = 0;
+
+       /* Allocate TX ring */
+       mp->tx_ring_skbs = 0;
+       mp->tx_ring_size = MV64340_TX_QUEUE_SIZE;
+       size = mp->tx_ring_size * sizeof(struct eth_tx_desc);
+       mp->tx_desc_area_size = size;
+
+       /* Assumes allocated ring is 16 bytes alligned */
+       mp->p_tx_desc_area = pci_alloc_consistent(NULL, size, &mp->tx_desc_dma);
+       if (!mp->p_tx_desc_area) {
+               printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
+                      dev->name, size);
+               return -ENOMEM;
+       }
+       memset((void *) mp->p_tx_desc_area, 0, mp->tx_desc_area_size);
+
+       /* Dummy will be replaced upon real tx */
+       ether_init_tx_desc_ring(mp);
+
+       /* Allocate RX ring */
+       /* Meantime RX Ring are fixed - but must be configurable by user */
+       mp->rx_ring_size = MV64340_RX_QUEUE_SIZE;
+       mp->rx_ring_skbs = 0;
+       size = mp->rx_ring_size * sizeof(struct eth_rx_desc);
+       mp->rx_desc_area_size = size;
+
+       /* Assumes allocated ring is 16 bytes aligned */
+
+       mp->p_rx_desc_area = pci_alloc_consistent(NULL, size, &mp->rx_desc_dma);
+
+       if (!mp->p_rx_desc_area) {
+               printk(KERN_ERR "%s: Cannot allocate Rx ring (size %d bytes)\n",
+                      dev->name, size);
+               printk(KERN_ERR "%s: Freeing previously allocated TX queues...",
+                      dev->name);
+               pci_free_consistent(0, mp->tx_desc_area_size,
+                                   (void *) mp->p_tx_desc_area,
+                                   mp->tx_desc_dma);
+               return -ENOMEM;
+       }
+       memset(mp->p_rx_desc_area, 0, size);
+
+       if (!(ether_init_rx_desc_ring(mp, 0)))
+               panic("%s: Error initializing RX Ring", dev->name);
+
+       mv64340_eth_rx_task(dev);       /* Fill RX ring with skb's */
+
+       eth_port_start(mp);
+
+       /* Interrupt Coalescing */
+
+#ifdef MV64340_COAL
+       mp->rx_int_coal =
+               eth_port_set_rx_coal(port_num, 133000000, MV64340_RX_COAL);
+#endif
+
+       mp->tx_int_coal =
+               eth_port_set_tx_coal (port_num, 133000000, MV64340_TX_COAL);  
+
+       /* Increase the Rx side buffer size */
+
+       MV_WRITE (MV64340_ETH_PORT_SERIAL_CONTROL_REG(port_num), (0x5 << 17) |
+                       (MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(port_num))
+                                       & 0xfff1ffff));
+
+       /* Check Link status on phy */
+       eth_port_read_smi_reg(port_num, 1, &phy_reg_data);
+       if (!(phy_reg_data & 0x20))
+               netif_stop_queue(dev);
+       else
+               netif_start_queue(dev);
+
+       return 0;
+}
+
+static void mv64340_eth_free_tx_rings(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+       unsigned int port_num = mp->port_num;
+       unsigned int curr;
+
+       /* Stop Tx Queues */
+       MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num),
+                0x0000ff00);
+
+       /* Free TX rings */
+       /* Free outstanding skb's on TX rings */
+       for (curr = 0;
+            (mp->tx_ring_skbs) && (curr < MV64340_TX_QUEUE_SIZE);
+            curr++) {
+               if (mp->tx_skb[curr]) {
+                       dev_kfree_skb(mp->tx_skb[curr]);
+                       mp->tx_ring_skbs--;
+               }
+       }
+       if (mp->tx_ring_skbs != 0)
+               printk("%s: Error on Tx descriptor free - could not free %d"
+                    " descriptors\n", dev->name,
+                    mp->tx_ring_skbs);
+       pci_free_consistent(0, mp->tx_desc_area_size,
+                           (void *) mp->p_tx_desc_area, mp->tx_desc_dma);
+}
+
+static void mv64340_eth_free_rx_rings(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+       unsigned int port_num = mp->port_num;
+       int curr;
+
+       /* Stop RX Queues */
+       MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
+                0x0000ff00);
+
+       /* Free RX rings */
+       /* Free preallocated skb's on RX rings */
+       for (curr = 0;
+               mp->rx_ring_skbs && (curr < MV64340_RX_QUEUE_SIZE);
+               curr++) {
+               if (mp->rx_skb[curr]) {
+                       dev_kfree_skb(mp->rx_skb[curr]);
+                       mp->rx_ring_skbs--;
+               }
+       }
+
+       if (mp->rx_ring_skbs != 0)
+               printk(KERN_ERR
+                      "%s: Error in freeing Rx Ring. %d skb's still"
+                      " stuck in RX Ring - ignoring them\n", dev->name,
+                      mp->rx_ring_skbs);
+       pci_free_consistent(0, mp->rx_desc_area_size,
+                           (void *) mp->p_rx_desc_area,
+                           mp->rx_desc_dma);
+}
+
+/*
+ * mv64340_eth_stop
+ *
+ * This function is used when closing the network device. 
+ * It updates the hardware, 
+ * release all memory that holds buffers and descriptors and release the IRQ.
+ * Input : a pointer to the device structure
+ * Output : zero if success , nonzero if fails
+ */
+
+/* Helper function for mv64340_eth_stop */
+
+static int mv64340_eth_real_stop(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+       unsigned int port_num = mp->port_num;
+
+       netif_stop_queue(dev);
+
+       mv64340_eth_free_tx_rings(dev);
+       mv64340_eth_free_rx_rings(dev);
+
+       eth_port_reset(mp->port_num);
+
+       /* Disable ethernet port interrupts */
+       MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+       MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+
+       /* Mask RX buffer and TX end interrupt */
+       MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num), 0);
+
+       /* Mask phy and link status changes interrupts */
+       MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
+
+       return 0;
+}
+
+static int mv64340_eth_stop(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+
+       spin_lock_irq(&mp->lock);
+
+       mv64340_eth_real_stop(dev);
+
+       free_irq(dev->irq, dev);
+       spin_unlock_irq(&mp->lock);
+
+       return 0;
+}
+
+#ifdef MV64340_NAPI
+static void mv64340_tx(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+        struct pkt_info pkt_info;
+
+       while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
+               if (pkt_info.return_info) {
+                       dev_kfree_skb_irq((struct sk_buff *)
+                                                  pkt_info.return_info);
+                       if (skb_shinfo(pkt_info.return_info)->nr_frags) 
+                                 pci_unmap_page(NULL, pkt_info.buf_ptr,
+                                             pkt_info.byte_cnt,
+                                             PCI_DMA_TODEVICE);
+
+                         if (mp->tx_ring_skbs != 1)
+                                  mp->tx_ring_skbs--;
+                } else 
+                       pci_unmap_page(NULL, pkt_info.buf_ptr, pkt_info.byte_cnt,
+                                      PCI_DMA_TODEVICE);
+       }
+
+       if (netif_queue_stopped(dev) &&
+            MV64340_TX_QUEUE_SIZE > mp->tx_ring_skbs + 1)
+                       netif_wake_queue(dev);
+}
+
+/*
+ * mv64340_poll
+ *
+ * This function is used in case of NAPI
+ */
+static int mv64340_poll(struct net_device *dev, int *budget)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+       int     done = 1, orig_budget, work_done;
+       unsigned int port_num = mp->port_num;
+       unsigned long flags;
+
+#ifdef MV64340_TX_FAST_REFILL
+       if (++mp->tx_clean_threshold > 5) {
+               spin_lock_irqsave(&mp->lock, flags);
+               mv64340_tx(dev);
+               mp->tx_clean_threshold = 0;
+               spin_unlock_irqrestore(&mp->lock, flags);
+       }
+#endif
+
+       if ((u32)(MV_READ(MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))                                      != (u32)mp->rx_used_desc_q) {
+               orig_budget = *budget;
+               if (orig_budget > dev->quota)
+                       orig_budget = dev->quota;
+               work_done = mv64340_eth_receive_queue(dev, 0, orig_budget);
+               mp->rx_task.func(dev);
+               *budget -= work_done;
+               dev->quota -= work_done;
+               if (work_done >= orig_budget)
+                       done = 0;
+       }
+
+       if (done) {
+               spin_lock_irqsave(&mp->lock, flags);
+               __netif_rx_complete(dev);
+               MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num),0);
+                MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),0);
+               MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num), 
+                                               INT_CAUSE_UNMASK_ALL);
+               MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+                                                INT_CAUSE_UNMASK_ALL_EXT);
+               spin_unlock_irqrestore(&mp->lock, flags);
+       }
+
+       return done ? 0 : 1;
+}
+#endif
+
+/*
+ * mv64340_eth_start_xmit
+ *
+ * This function is queues a packet in the Tx descriptor for 
+ * required port.
+ *
+ * Input : skb - a pointer to socket buffer
+ *         dev - a pointer to the required port
+ *
+ * Output : zero upon success
+ */
+static int mv64340_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+       struct net_device_stats *stats = &mp->stats;
+       ETH_FUNC_RET_STATUS status;
+       unsigned long flags;
+       struct pkt_info pkt_info;
+
+       if (netif_queue_stopped(dev)) {
+               printk(KERN_ERR
+                      "%s: Tried sending packet when interface is stopped\n",
+                      dev->name);
+               return 1;
+       }
+
+       /* This is a hard error, log it. */
+       if ((MV64340_TX_QUEUE_SIZE - mp->tx_ring_skbs) <=
+           (skb_shinfo(skb)->nr_frags + 1)) {
+               netif_stop_queue(dev);
+               printk(KERN_ERR
+                      "%s: Bug in mv64340_eth - Trying to transmit when"
+                      " queue full !\n", dev->name);
+               return 1;
+       }
+
+       /* Paranoid check - this shouldn't happen */
+       if (skb == NULL) {
+               stats->tx_dropped++;
+               return 1;
+       }
+
+       spin_lock_irqsave(&mp->lock, flags);
+
+       /* Update packet info data structure -- DMA owned, first last */
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+       if (!skb_shinfo(skb)->nr_frags || (skb_shinfo(skb)->nr_frags > 3)) {
+#endif
+               pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
+                                  ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
+
+               pkt_info.byte_cnt = skb->len;
+               pkt_info.buf_ptr = pci_map_single(0, skb->data, skb->len,
+                                                 PCI_DMA_TODEVICE);
+
+
+               pkt_info.return_info = skb;
+               status = eth_port_send(mp, &pkt_info);
+               if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
+                       printk(KERN_ERR "%s: Error on transmitting packet\n",
+                                      dev->name);
+               mp->tx_ring_skbs++;
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+       } else {
+               unsigned int    frag;
+               u32             ipheader;
+
+                /* first frag which is skb header */
+                pkt_info.byte_cnt = skb_headlen(skb);
+                pkt_info.buf_ptr = pci_map_single(0, skb->data,
+                                        skb_headlen(skb), PCI_DMA_TODEVICE);
+                pkt_info.return_info = 0;
+                ipheader = skb->nh.iph->ihl << 11;
+                pkt_info.cmd_sts = ETH_TX_FIRST_DESC | 
+                                       ETH_GEN_TCP_UDP_CHECKSUM |
+                                       ETH_GEN_IP_V_4_CHECKSUM |
+                                        ipheader;
+               /* CPU already calculated pseudo header checksum. So, use it */
+                pkt_info.l4i_chk = skb->h.th->check;
+                status = eth_port_send(mp, &pkt_info);
+               if (status != ETH_OK) {
+                       if ((status == ETH_ERROR))
+                               printk(KERN_ERR "%s: Error on transmitting packet\n", dev->name);
+                       if (status == ETH_QUEUE_FULL)
+                               printk("Error on Queue Full \n");
+                       if (status == ETH_QUEUE_LAST_RESOURCE)
+                               printk("Tx resource error \n");
+               }
+
+                /* Check for the remaining frags */
+                for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
+                        skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
+                        pkt_info.l4i_chk = 0x0000;
+                        pkt_info.cmd_sts = 0x00000000;
+
+                        /* Last Frag enables interrupt and frees the skb */
+                        if (frag == (skb_shinfo(skb)->nr_frags - 1)) {
+                                pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
+                                                        ETH_TX_LAST_DESC;
+                                pkt_info.return_info = skb;
+                                mp->tx_ring_skbs++;
+                        }
+                        else {
+                                pkt_info.return_info = 0;
+                        }
+                        pkt_info.byte_cnt = this_frag->size;
+                        if (this_frag->size < 8)
+                                printk("%d : \n", skb_shinfo(skb)->nr_frags);
+
+                        pkt_info.buf_ptr = pci_map_page(NULL, this_frag->page,
+                                        this_frag->page_offset,
+                                        this_frag->size, PCI_DMA_TODEVICE);
+
+                        status = eth_port_send(mp, &pkt_info);
+
+                       if (status != ETH_OK) {
+                               if ((status == ETH_ERROR))
+                                       printk(KERN_ERR "%s: Error on transmitting packet\n", dev->name);
+
+                                        if (status == ETH_QUEUE_LAST_RESOURCE)
+                                       printk("Tx resource error \n");
+
+                               if (status == ETH_QUEUE_FULL)
+                                       printk("Queue is full \n");
+                       }
+                }
+        }
+#endif
+
+       /* Check if TX queue can handle another skb. If not, then
+        * signal higher layers to stop requesting TX
+        */
+       if (MV64340_TX_QUEUE_SIZE <= (mp->tx_ring_skbs + 1))
+               /* 
+                * Stop getting skb's from upper layers.
+                * Getting skb's from upper layers will be enabled again after
+                * packets are released.
+                */
+               netif_stop_queue(dev);
+
+       /* Update statistics and start of transmittion time */
+       stats->tx_bytes += skb->len;
+       stats->tx_packets++;
+       dev->trans_start = jiffies;
+
+       spin_unlock_irqrestore(&mp->lock, flags);
+
+       return 0;               /* success */
+}
+
+/*
+ * mv64340_eth_get_stats
+ *
+ * Returns a pointer to the interface statistics.
+ *
+ * Input : dev - a pointer to the required interface
+ *
+ * Output : a pointer to the interface's statistics
+ */
+
+static struct net_device_stats *mv64340_eth_get_stats(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+
+       return &mp->stats;
+}
+
+/*/
+ * mv64340_eth_init
+ *                                                                    
+ * First function called after registering the network device. 
+ * It's purpose is to initialize the device as an ethernet device, 
+ * fill the structure that was given in registration with pointers
+ * to functions, and setting the MAC address of the interface
+ *
+ * Input : number of port to initialize
+ * Output : -ENONMEM if failed , 0 if success
+ */
+static struct net_device *mv64340_eth_init(int port_num)
+{
+       struct mv64340_private *mp;
+       struct net_device *dev;
+       int err;
+
+       dev = alloc_etherdev(sizeof(struct mv64340_private));
+       if (!dev)
+               return NULL;
+
+       mp = netdev_priv(dev);
+
+       dev->irq = ETH_PORT0_IRQ_NUM + port_num;
+
+       dev->open = mv64340_eth_open;
+       dev->stop = mv64340_eth_stop;
+       dev->hard_start_xmit = mv64340_eth_start_xmit;
+       dev->get_stats = mv64340_eth_get_stats;
+       dev->set_mac_address = mv64340_eth_set_mac_address;
+       dev->set_multicast_list = mv64340_eth_set_rx_mode;
+
+       /* No need to Tx Timeout */
+       dev->tx_timeout = mv64340_eth_tx_timeout;
+#ifdef MV64340_NAPI
+        dev->poll = mv64340_poll;
+        dev->weight = 64;
+#endif
+
+       dev->watchdog_timeo = 2 * HZ;
+       dev->tx_queue_len = MV64340_TX_QUEUE_SIZE;
+       dev->base_addr = 0;
+       dev->change_mtu = mv64340_eth_change_mtu;
+
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+#ifdef MAX_SKB_FRAGS
+#ifndef CONFIG_JAGUAR_DMALOW
+        /*
+         * Zero copy can only work if we use Discovery II memory. Else, we will
+         * have to map the buffers to ISA memory which is only 16 MB
+         */
+        dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_CSUM;
+#endif
+#endif
+#endif
+
+       mp->port_num = port_num;
+
+       /* Configure the timeout task */
+        INIT_WORK(&mp->tx_timeout_task,
+                  (void (*)(void *))mv64340_eth_tx_timeout_task, dev);
+
+       spin_lock_init(&mp->lock);
+
+       /* set MAC addresses */
+       memcpy(dev->dev_addr, prom_mac_addr_base, 6);
+       dev->dev_addr[5] += port_num;
+
+       err = register_netdev(dev);
+       if (err)
+               goto out_free_dev;
+
+       printk(KERN_NOTICE "%s: port %d with MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
+               dev->name, port_num,
+               dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+               dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+
+       if (dev->features & NETIF_F_SG)
+               printk("Scatter Gather Enabled  ");
+
+       if (dev->features & NETIF_F_IP_CSUM)
+               printk("TX TCP/IP Checksumming Supported  \n");
+
+       printk("RX TCP/UDP Checksum Offload ON, \n");
+       printk("TX and RX Interrupt Coalescing ON \n");
+
+#ifdef MV64340_NAPI
+       printk("RX NAPI Enabled \n");
+#endif
+
+       return dev;
+
+out_free_dev:
+       free_netdev(dev);
+
+       return NULL;
+}
+
+static void mv64340_eth_remove(struct net_device *dev)
+{
+       struct mv64340_private *mp = netdev_priv(dev);
+
+       unregister_netdev(dev);
+       flush_scheduled_work();
+       free_netdev(dev);
+}
+
+static struct net_device *mv64340_dev0;
+static struct net_device *mv64340_dev1;
+static struct net_device *mv64340_dev2;
+
+/*
+ * mv64340_init_module
+ *
+ * Registers the network drivers into the Linux kernel
+ *
+ * Input : N/A
+ *
+ * Output : N/A
+ */
+static int __init mv64340_init_module(void)
+{
+       printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
+
+#ifdef CONFIG_MV643XX_ETH_0
+       mv64340_dev0 = mv64340_eth_init(0);
+       if (!mv64340_dev0) {
+               printk(KERN_ERR
+                      "Error registering MV-64360 ethernet port 0\n");
+       }
+#endif
+#ifdef CONFIG_MV643XX_ETH_1
+       mv64340_dev1 = mv64340_eth_init(1);
+       if (!mv64340_dev1) {
+               printk(KERN_ERR
+                      "Error registering MV-64360 ethernet port 1\n");
+       }
+#endif
+#ifdef CONFIG_MV643XX_ETH_2
+       mv64340_dev2 = mv64340_eth_init(2);
+       if (!mv64340_dev2) {
+               printk(KERN_ERR
+                      "Error registering MV-64360 ethernet port 2\n");
+       }
+#endif
+       return 0;
+}
+
+/*
+ * mv64340_cleanup_module
+ *
+ * Registers the network drivers into the Linux kernel
+ *
+ * Input : N/A
+ *
+ * Output : N/A
+ */
+static void __exit mv64340_cleanup_module(void)
+{
+       if (mv64340_dev2)
+               mv64340_eth_remove(mv64340_dev2);
+       if (mv64340_dev1)
+               mv64340_eth_remove(mv64340_dev1);
+       if (mv64340_dev0)
+               mv64340_eth_remove(mv64340_dev0);
+}
+
+module_init(mv64340_init_module);
+module_exit(mv64340_cleanup_module);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Rabeeh Khoury, Assaf Hoffman, Matthew Dharm and Manish Lachwani");
+MODULE_DESCRIPTION("Ethernet driver for Marvell MV64340");
+
+/*
+ *  The second part is the low level driver of the gigE ethernet ports.
+ */
+
+/*
+ * Marvell's Gigabit Ethernet controller low level driver
+ *
+ * DESCRIPTION:
+ *       This file introduce low level API to Marvell's Gigabit Ethernet
+ *             controller. This Gigabit Ethernet Controller driver API controls
+ *             1) Operations (i.e. port init, start, reset etc').
+ *             2) Data flow (i.e. port send, receive etc').
+ *             Each Gigabit Ethernet port is controlled via
+ *              struct mv64340_private.
+ *             This struct includes user configuration information as well as
+ *             driver internal data needed for its operations.
+ *
+ *             Supported Features:  
+ *             - This low level driver is OS independent. Allocating memory for
+ *               the descriptor rings and buffers are not within the scope of
+ *               this driver.
+ *             - The user is free from Rx/Tx queue managing.
+ *             - This low level driver introduce functionality API that enable
+ *               the to operate Marvell's Gigabit Ethernet Controller in a
+ *               convenient way.
+ *             - Simple Gigabit Ethernet port operation API.
+ *             - Simple Gigabit Ethernet port data flow API.
+ *             - Data flow and operation API support per queue functionality.
+ *             - Support cached descriptors for better performance.
+ *             - Enable access to all four DRAM banks and internal SRAM memory
+ *               spaces.
+ *             - PHY access and control API.
+ *             - Port control register configuration API.
+ *             - Full control over Unicast and Multicast MAC configurations.
+ *                                                                
+ *             Operation flow:
+ *
+ *             Initialization phase
+ *             This phase complete the initialization of the the mv64340_private
+ *             struct. 
+ *             User information regarding port configuration has to be set
+ *             prior to calling the port initialization routine.
+ *
+ *             In this phase any port Tx/Rx activity is halted, MIB counters
+ *             are cleared, PHY address is set according to user parameter and
+ *             access to DRAM and internal SRAM memory spaces.
+ *
+ *             Driver ring initialization
+ *             Allocating memory for the descriptor rings and buffers is not 
+ *             within the scope of this driver. Thus, the user is required to
+ *             allocate memory for the descriptors ring and buffers. Those
+ *             memory parameters are used by the Rx and Tx ring initialization
+ *             routines in order to curve the descriptor linked list in a form
+ *             of a ring.
+ *             Note: Pay special attention to alignment issues when using
+ *             cached descriptors/buffers. In this phase the driver store
+ *             information in the mv64340_private struct regarding each queue
+ *             ring.
+ *
+ *             Driver start 
+ *             This phase prepares the Ethernet port for Rx and Tx activity.
+ *             It uses the information stored in the mv64340_private struct to 
+ *             initialize the various port registers.
+ *
+ *             Data flow:
+ *             All packet references to/from the driver are done using
+ *              struct pkt_info.
+ *             This struct is a unified struct used with Rx and Tx operations. 
+ *             This way the user is not required to be familiar with neither
+ *             Tx nor Rx descriptors structures.
+ *             The driver's descriptors rings are management by indexes.
+ *             Those indexes controls the ring resources and used to indicate
+ *             a SW resource error:
+ *             'current' 
+ *             This index points to the current available resource for use. For 
+ *             example in Rx process this index will point to the descriptor  
+ *             that will be passed to the user upon calling the receive routine.
+ *             In Tx process, this index will point to the descriptor
+ *             that will be assigned with the user packet info and transmitted.
+ *             'used'    
+ *             This index points to the descriptor that need to restore its 
+ *             resources. For example in Rx process, using the Rx buffer return
+ *             API will attach the buffer returned in packet info to the
+ *             descriptor pointed by 'used'. In Tx process, using the Tx
+ *             descriptor return will merely return the user packet info with
+ *             the command status of  the transmitted buffer pointed by the
+ *             'used' index. Nevertheless, it is essential to use this routine
+ *             to update the 'used' index.
+ *             'first'
+ *             This index supports Tx Scatter-Gather. It points to the first 
+ *             descriptor of a packet assembled of multiple buffers. For example
+ *             when in middle of Such packet we have a Tx resource error the 
+ *             'curr' index get the value of 'first' to indicate that the ring 
+ *             returned to its state before trying to transmit this packet.
+ *
+ *             Receive operation:
+ *             The eth_port_receive API set the packet information struct,
+ *             passed by the caller, with received information from the 
+ *             'current' SDMA descriptor. 
+ *             It is the user responsibility to return this resource back
+ *             to the Rx descriptor ring to enable the reuse of this source.
+ *             Return Rx resource is done using the eth_rx_return_buff API.
+ *
+ *             Transmit operation:
+ *             The eth_port_send API supports Scatter-Gather which enables to
+ *             send a packet spanned over multiple buffers. This means that
+ *             for each packet info structure given by the user and put into
+ *             the Tx descriptors ring, will be transmitted only if the 'LAST'
+ *             bit will be set in the packet info command status field. This
+ *             API also consider restriction regarding buffer alignments and
+ *             sizes.
+ *             The user must return a Tx resource after ensuring the buffer
+ *             has been transmitted to enable the Tx ring indexes to update.
+ *
+ *             BOARD LAYOUT
+ *             This device is on-board.  No jumper diagram is necessary.
+ *
+ *             EXTERNAL INTERFACE
+ *
+ *       Prior to calling the initialization routine eth_port_init() the user
+ *      must set the following fields under mv64340_private struct:
+ *       port_num             User Ethernet port number.
+ *       port_mac_addr[6]          User defined port MAC address.
+ *       port_config          User port configuration value.
+ *       port_config_extend    User port config extend value.
+ *       port_sdma_config      User port SDMA config value.
+ *       port_serial_control   User port serial control value.
+ *
+ *       This driver introduce a set of default values:
+ *       PORT_CONFIG_VALUE           Default port configuration value
+ *       PORT_CONFIG_EXTEND_VALUE    Default port extend configuration value
+ *       PORT_SDMA_CONFIG_VALUE      Default sdma control value
+ *       PORT_SERIAL_CONTROL_VALUE   Default port serial control value
+ *
+ *             This driver data flow is done using the struct pkt_info which
+ *              is a unified struct for Rx and Tx operations:
+ *
+ *             byte_cnt        Tx/Rx descriptor buffer byte count.
+ *             l4i_chk         CPU provided TCP Checksum. For Tx operation
+ *                              only.
+ *             cmd_sts         Tx/Rx descriptor command status.
+ *             buf_ptr         Tx/Rx descriptor buffer pointer.
+ *             return_info     Tx/Rx user resource return information.
+ */
+
+/* defines */
+/* SDMA command macros */
+#define ETH_ENABLE_TX_QUEUE(eth_port) \
+       MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), 1)
+
+#define ETH_DISABLE_TX_QUEUE(eth_port) \
+       MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port),      \
+                (1 << 8))
+
+#define ETH_ENABLE_RX_QUEUE(rx_queue, eth_port) \
+       MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port),       \
+                (1 << rx_queue))
+
+#define ETH_DISABLE_RX_QUEUE(rx_queue, eth_port) \
+       MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port),       \
+                (1 << (8 + rx_queue)))
+
+#define LINK_UP_TIMEOUT                100000
+#define PHY_BUSY_TIMEOUT       10000000
+
+/* locals */
+
+/* PHY routines */
+static int ethernet_phy_get(unsigned int eth_port_num);
+
+/* Ethernet Port routines */
+static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
+       int option);
+
+/*
+ * eth_port_init - Initialize the Ethernet port driver
+ *
+ * DESCRIPTION:
+ *       This function prepares the ethernet port to start its activity:
+ *       1) Completes the ethernet port driver struct initialization toward port
+ *           start routine.
+ *       2) Resets the device to a quiescent state in case of warm reboot.
+ *       3) Enable SDMA access to all four DRAM banks as well as internal SRAM.
+ *       4) Clean MAC tables. The reset status of those tables is unknown.
+ *       5) Set PHY address. 
+ *       Note: Call this routine prior to eth_port_start routine and after
+ *       setting user values in the user fields of Ethernet port control
+ *       struct.
+ *
+ * INPUT:
+ *       struct mv64340_private *mp   Ethernet port control struct
+ *
+ * OUTPUT:
+ *       See description.
+ *
+ * RETURN:
+ *       None.
+ */
+static void eth_port_init(struct mv64340_private * mp)
+{
+       mp->port_config = PORT_CONFIG_VALUE;
+       mp->port_config_extend = PORT_CONFIG_EXTEND_VALUE;
+#if defined(__BIG_ENDIAN)
+       mp->port_sdma_config = PORT_SDMA_CONFIG_VALUE;
+#elif defined(__LITTLE_ENDIAN)
+       mp->port_sdma_config = PORT_SDMA_CONFIG_VALUE |
+               ETH_BLM_RX_NO_SWAP | ETH_BLM_TX_NO_SWAP;
+#else
+#error One of __LITTLE_ENDIAN or __BIG_ENDIAN must be defined!
+#endif
+       mp->port_serial_control = PORT_SERIAL_CONTROL_VALUE;
+
+       mp->port_rx_queue_command = 0;
+       mp->port_tx_queue_command = 0;
+
+       mp->rx_resource_err = 0;
+       mp->tx_resource_err = 0;
+
+       eth_port_reset(mp->port_num);
+
+       eth_port_init_mac_tables(mp->port_num);
+
+       ethernet_phy_reset(mp->port_num);
+}
+
+/*
+ * eth_port_start - Start the Ethernet port activity.
+ *
+ * DESCRIPTION:
+ *       This routine prepares the Ethernet port for Rx and Tx activity:
+ *       1. Initialize Tx and Rx Current Descriptor Pointer for each queue that
+ *          has been initialized a descriptor's ring (using
+ *          ether_init_tx_desc_ring for Tx and ether_init_rx_desc_ring for Rx)
+ *       2. Initialize and enable the Ethernet configuration port by writing to
+ *          the port's configuration and command registers.
+ *       3. Initialize and enable the SDMA by writing to the SDMA's 
+ *          configuration and command registers.  After completing these steps,
+ *          the ethernet port SDMA can starts to perform Rx and Tx activities.
+ *
+ *       Note: Each Rx and Tx queue descriptor's list must be initialized prior
+ *       to calling this function (use ether_init_tx_desc_ring for Tx queues
+ *       and ether_init_rx_desc_ring for Rx queues).
+ *
+ * INPUT:
+ *       struct mv64340_private        *mp   Ethernet port control struct
+ *
+ * OUTPUT:
+ *       Ethernet port is ready to receive and transmit.
+ *
+ * RETURN:
+ *       false if the port PHY is not up.
+ *       true otherwise.
+ */
+static int eth_port_start(struct mv64340_private *mp)
+{
+       unsigned int eth_port_num = mp->port_num;
+       int tx_curr_desc, rx_curr_desc;
+       unsigned int phy_reg_data;
+
+       /* Assignment of Tx CTRP of given queue */
+       tx_curr_desc = mp->tx_curr_desc_q;
+       MV_WRITE(MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num),
+                (struct eth_tx_desc *) mp->tx_desc_dma + tx_curr_desc);
+
+       /* Assignment of Rx CRDP of given queue */
+       rx_curr_desc = mp->rx_curr_desc_q;
+       MV_WRITE(MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num),
+                (struct eth_rx_desc *) mp->rx_desc_dma + rx_curr_desc);
+
+       /* Add the assigned Ethernet address to the port's address table */
+       eth_port_uc_addr_set(mp->port_num, mp->port_mac_addr);
+
+       /* Assign port configuration and command. */
+       MV_WRITE(MV64340_ETH_PORT_CONFIG_REG(eth_port_num),
+                mp->port_config);
+
+       MV_WRITE(MV64340_ETH_PORT_CONFIG_EXTEND_REG(eth_port_num),
+                mp->port_config_extend);
+
+       MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num),
+                mp->port_serial_control);
+
+       MV_SET_REG_BITS(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num),
+                       ETH_SERIAL_PORT_ENABLE);
+
+       /* Assign port SDMA configuration */
+       MV_WRITE(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num),
+                mp->port_sdma_config);
+
+       /* Enable port Rx. */
+       MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port_num),
+                mp->port_rx_queue_command);
+
+       /* Check if link is up */
+       eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data);
+
+       if (!(phy_reg_data & 0x20))
+               return 0;
+
+       return 1;
+}
+
+/*
+ * eth_port_uc_addr_set - This function Set the port Unicast address.
+ *
+ * DESCRIPTION:
+ *             This function Set the port Ethernet MAC address.
+ *
+ * INPUT:
+ *     unsigned int eth_port_num     Port number.
+ *     char *        p_addr            Address to be set 
+ *
+ * OUTPUT:
+ *     Set MAC address low and high registers. also calls eth_port_uc_addr() 
+ *       To set the unicast table with the proper information.
+ *
+ * RETURN:
+ *     N/A.
+ *
+ */
+static void eth_port_uc_addr_set(unsigned int eth_port_num,
+                                unsigned char *p_addr)
+{
+       unsigned int mac_h;
+       unsigned int mac_l;
+
+       mac_l = (p_addr[4] << 8) | (p_addr[5]);
+       mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) |
+           (p_addr[2] << 8) | (p_addr[3] << 0);
+
+       MV_WRITE(MV64340_ETH_MAC_ADDR_LOW(eth_port_num), mac_l);
+       MV_WRITE(MV64340_ETH_MAC_ADDR_HIGH(eth_port_num), mac_h);
+
+       /* Accept frames of this address */
+       eth_port_uc_addr(eth_port_num, p_addr[5], ACCEPT_MAC_ADDR);
+
+       return;
+}
+
+/*
+ * eth_port_uc_addr - This function Set the port unicast address table
+ *
+ * DESCRIPTION:
+ *     This function locates the proper entry in the Unicast table for the 
+ *     specified MAC nibble and sets its properties according to function 
+ *     parameters.
+ *
+ * INPUT:
+ *     unsigned int    eth_port_num      Port number.
+ *     unsigned char uc_nibble         Unicast MAC Address last nibble. 
+ *     int                     option      0 = Add, 1 = remove address.
+ *
+ * OUTPUT:
+ *     This function add/removes MAC addresses from the port unicast address
+ *     table. 
+ *
+ * RETURN:
+ *     true is output succeeded.
+ *     false if option parameter is invalid.
+ *
+ */
+static int eth_port_uc_addr(unsigned int eth_port_num,
+       unsigned char uc_nibble, int option)
+{
+       unsigned int unicast_reg;
+       unsigned int tbl_offset;
+       unsigned int reg_offset;
+
+       /* Locate the Unicast table entry */
+       uc_nibble = (0xf & uc_nibble);
+       tbl_offset = (uc_nibble / 4) * 4;       /* Register offset from unicast table base */
+       reg_offset = uc_nibble % 4;     /* Entry offset within the above register */
+
+       switch (option) {
+       case REJECT_MAC_ADDR:
+               /* Clear accepts frame bit at specified unicast DA table entry */
+               unicast_reg = MV_READ((MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
+                                 (eth_port_num) + tbl_offset));
+
+               unicast_reg &= (0x0E << (8 * reg_offset));
+
+               MV_WRITE(
+                        (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
+                         (eth_port_num) + tbl_offset), unicast_reg);
+               break;
+
+       case ACCEPT_MAC_ADDR:
+               /* Set accepts frame bit at unicast DA filter table entry */
+               unicast_reg =
+                   MV_READ(
+                                (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
+                                 (eth_port_num) + tbl_offset));
+
+               unicast_reg |= (0x01 << (8 * reg_offset));
+
+               MV_WRITE(
+                        (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
+                         (eth_port_num) + tbl_offset), unicast_reg);
+
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+/*
+ * eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
+ *
+ * DESCRIPTION:
+ *       Go through all the DA filter tables (Unicast, Special Multicast &
+ *       Other Multicast) and set each entry to 0.
+ *
+ * INPUT:
+ *     unsigned int    eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       Multicast and Unicast packets are rejected.
+ *
+ * RETURN:
+ *       None.
+ */
+static void eth_port_init_mac_tables(unsigned int eth_port_num)
+{
+       int table_index;
+
+       /* Clear DA filter unicast table (Ex_dFUT) */
+       for (table_index = 0; table_index <= 0xC; table_index += 4)
+               MV_WRITE(
+                        (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
+                         (eth_port_num) + table_index), 0);
+
+       for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+               /* Clear DA filter special multicast table (Ex_dFSMT) */
+               MV_WRITE(
+                        (MV64340_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+                         (eth_port_num) + table_index), 0);
+               /* Clear DA filter other multicast table (Ex_dFOMT) */
+               MV_WRITE((MV64340_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+                         (eth_port_num) + table_index), 0);
+       }
+}
+
+/*
+ * eth_clear_mib_counters - Clear all MIB counters
+ *
+ * DESCRIPTION:
+ *       This function clears all MIB counters of a specific ethernet port.
+ *       A read from the MIB counter will reset the counter.
+ *
+ * INPUT:
+ *     unsigned int    eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       After reading all MIB counters, the counters resets.
+ *
+ * RETURN:
+ *       MIB counter value.
+ *
+ */
+static void eth_clear_mib_counters(unsigned int eth_port_num)
+{
+       int i;
+
+       /* Perform dummy reads from MIB counters */
+       for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION; i += 4)
+               MV_READ(MV64340_ETH_MIB_COUNTERS_BASE(eth_port_num) + i);
+}
+
+
+/*
+ * ethernet_phy_get - Get the ethernet port PHY address.
+ *
+ * DESCRIPTION:
+ *       This routine returns the given ethernet port PHY address.
+ *
+ * INPUT:
+ *             unsigned int   eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       PHY address.
+ *
+ */
+static int ethernet_phy_get(unsigned int eth_port_num)
+{
+       unsigned int reg_data;
+
+       reg_data = MV_READ(MV64340_ETH_PHY_ADDR_REG);
+
+       return ((reg_data >> (5 * eth_port_num)) & 0x1f);
+}
+
+/*
+ * ethernet_phy_reset - Reset Ethernet port PHY.
+ *
+ * DESCRIPTION:
+ *       This routine utilize the SMI interface to reset the ethernet port PHY.
+ *       The routine waits until the link is up again or link up is timeout.
+ *
+ * INPUT:
+ *     unsigned int   eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       The ethernet port PHY renew its link.
+ *
+ * RETURN:
+ *       None.
+ *
+ */
+static int ethernet_phy_reset(unsigned int eth_port_num)
+{
+       unsigned int time_out = 50;
+       unsigned int phy_reg_data;
+
+       /* Reset the PHY */
+       eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
+       phy_reg_data |= 0x8000; /* Set bit 15 to reset the PHY */
+       eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data);
+
+       /* Poll on the PHY LINK */
+       do {
+               eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data);
+
+               if (time_out-- == 0)
+                       return 0;
+       } while (!(phy_reg_data & 0x20));
+
+       return 1;
+}
+
+/*
+ * eth_port_reset - Reset Ethernet port
+ *
+ * DESCRIPTION:
+ *     This routine resets the chip by aborting any SDMA engine activity and
+ *      clearing the MIB counters. The Receiver and the Transmit unit are in 
+ *      idle state after this command is performed and the port is disabled.
+ *
+ * INPUT:
+ *     unsigned int   eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       Channel activity is halted.
+ *
+ * RETURN:
+ *       None.
+ *
+ */
+static void eth_port_reset(unsigned int eth_port_num)
+{
+       unsigned int reg_data;
+
+       /* Stop Tx port activity. Check port Tx activity. */
+       reg_data =
+           MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port_num));
+
+       if (reg_data & 0xFF) {
+               /* Issue stop command for active channels only */
+               MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG
+                        (eth_port_num), (reg_data << 8));
+
+               /* Wait for all Tx activity to terminate. */
+               do {
+                       /* Check port cause register that all Tx queues are stopped */
+                       reg_data =
+                           MV_READ
+                           (MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG
+                            (eth_port_num));
+               }
+               while (reg_data & 0xFF);
+       }
+
+       /* Stop Rx port activity. Check port Rx activity. */
+       reg_data =
+           MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
+                        (eth_port_num));
+
+       if (reg_data & 0xFF) {
+               /* Issue stop command for active channels only */
+               MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
+                        (eth_port_num), (reg_data << 8));
+
+               /* Wait for all Rx activity to terminate. */
+               do {
+                       /* Check port cause register that all Rx queues are stopped */
+                       reg_data =
+                           MV_READ
+                           (MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
+                            (eth_port_num));
+               }
+               while (reg_data & 0xFF);
+       }
+
+
+       /* Clear all MIB counters */
+       eth_clear_mib_counters(eth_port_num);
+
+       /* Reset the Enable bit in the Configuration Register */
+       reg_data =
+           MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num));
+       reg_data &= ~ETH_SERIAL_PORT_ENABLE;
+       MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num), reg_data);
+
+       return;
+}
+
+/*
+ * ethernet_set_config_reg - Set specified bits in configuration register.
+ *
+ * DESCRIPTION:
+ *       This function sets specified bits in the given ethernet 
+ *       configuration register. 
+ *
+ * INPUT:
+ *     unsigned int   eth_port_num   Ethernet Port number.
+ *      unsigned int    value   32 bit value.
+ *
+ * OUTPUT:
+ *      The set bits in the value parameter are set in the configuration 
+ *      register.
+ *
+ * RETURN:
+ *      None.
+ *
+ */
+static void ethernet_set_config_reg(unsigned int eth_port_num,
+                                   unsigned int value)
+{
+       unsigned int eth_config_reg;
+
+       eth_config_reg =
+           MV_READ(MV64340_ETH_PORT_CONFIG_REG(eth_port_num));
+       eth_config_reg |= value;
+       MV_WRITE(MV64340_ETH_PORT_CONFIG_REG(eth_port_num),
+                eth_config_reg);
+}
+
+/*
+ * ethernet_get_config_reg - Get the port configuration register
+ *
+ * DESCRIPTION:
+ *       This function returns the configuration register value of the given 
+ *       ethernet port.
+ *
+ * INPUT:
+ *     unsigned int   eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       Port configuration register value.
+ */
+static unsigned int ethernet_get_config_reg(unsigned int eth_port_num)
+{
+       unsigned int eth_config_reg;
+
+       eth_config_reg = MV_READ(MV64340_ETH_PORT_CONFIG_EXTEND_REG
+                                     (eth_port_num));
+       return eth_config_reg;
+}
+
+
+/*
+ * eth_port_read_smi_reg - Read PHY registers
+ *
+ * DESCRIPTION:
+ *       This routine utilize the SMI interface to interact with the PHY in 
+ *       order to perform PHY register read.
+ *
+ * INPUT:
+ *     unsigned int   eth_port_num   Ethernet Port number.
+ *       unsigned int   phy_reg   PHY register address offset.
+ *       unsigned int   *value   Register value buffer.
+ *
+ * OUTPUT:
+ *       Write the value of a specified PHY register into given buffer.
+ *
+ * RETURN:
+ *       false if the PHY is busy or read data is not in valid state.
+ *       true otherwise.
+ *
+ */
+static int eth_port_read_smi_reg(unsigned int eth_port_num,
+       unsigned int phy_reg, unsigned int *value)
+{
+       int phy_addr = ethernet_phy_get(eth_port_num);
+       unsigned int time_out = PHY_BUSY_TIMEOUT;
+       unsigned int reg_value;
+
+       /* first check that it is not busy */
+       do {
+               reg_value = MV_READ(MV64340_ETH_SMI_REG);
+               if (time_out-- == 0)
+                       return 0;
+       } while (reg_value & ETH_SMI_BUSY);
+
+       /* not busy */
+
+       MV_WRITE(MV64340_ETH_SMI_REG,
+                (phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
+
+       time_out = PHY_BUSY_TIMEOUT;    /* initialize the time out var again */
+
+       do {
+               reg_value = MV_READ(MV64340_ETH_SMI_REG);
+               if (time_out-- == 0)
+                       return 0;
+       } while (reg_value & ETH_SMI_READ_VALID);
+
+       /* Wait for the data to update in the SMI register */
+       for (time_out = 0; time_out < PHY_BUSY_TIMEOUT; time_out++);
+
+       reg_value = MV_READ(MV64340_ETH_SMI_REG);
+
+       *value = reg_value & 0xffff;
+
+       return 1;
+}
+
+/*
+ * eth_port_write_smi_reg - Write to PHY registers
+ *
+ * DESCRIPTION:
+ *       This routine utilize the SMI interface to interact with the PHY in 
+ *       order to perform writes to PHY registers.
+ *
+ * INPUT:
+ *     unsigned int   eth_port_num   Ethernet Port number.
+ *      unsigned int   phy_reg   PHY register address offset.
+ *      unsigned int    value   Register value.
+ *
+ * OUTPUT:
+ *      Write the given value to the specified PHY register.
+ *
+ * RETURN:
+ *      false if the PHY is busy.
+ *      true otherwise.
+ *
+ */
+static int eth_port_write_smi_reg(unsigned int eth_port_num,
+       unsigned int phy_reg, unsigned int value)
+{
+       unsigned int time_out = PHY_BUSY_TIMEOUT;
+       unsigned int reg_value;
+       int phy_addr;
+
+       phy_addr = ethernet_phy_get(eth_port_num);
+
+       /* first check that it is not busy */
+       do {
+               reg_value = MV_READ(MV64340_ETH_SMI_REG);
+               if (time_out-- == 0)
+                       return 0;
+       } while (reg_value & ETH_SMI_BUSY);
+
+       /* not busy */
+       MV_WRITE(MV64340_ETH_SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
+                ETH_SMI_OPCODE_WRITE | (value & 0xffff));
+
+       return 1;
+}
+
+/*
+ * eth_port_send - Send an Ethernet packet
+ *
+ * DESCRIPTION:
+ *     This routine send a given packet described by p_pktinfo parameter. It 
+ *      supports transmitting of a packet spaned over multiple buffers. The 
+ *      routine updates 'curr' and 'first' indexes according to the packet 
+ *      segment passed to the routine. In case the packet segment is first, 
+ *      the 'first' index is update. In any case, the 'curr' index is updated. 
+ *      If the routine get into Tx resource error it assigns 'curr' index as 
+ *      'first'. This way the function can abort Tx process of multiple 
+ *      descriptors per packet.
+ *
+ * INPUT:
+ *     struct mv64340_private   *mp   Ethernet Port Control srtuct. 
+ *     struct pkt_info        *p_pkt_info       User packet buffer.
+ *
+ * OUTPUT:
+ *     Tx ring 'curr' and 'first' indexes are updated. 
+ *
+ * RETURN:
+ *      ETH_QUEUE_FULL in case of Tx resource error.
+ *     ETH_ERROR in case the routine can not access Tx desc ring.
+ *     ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource.
+ *      ETH_OK otherwise.
+ *
+ */
+#ifdef  MV64340_CHECKSUM_OFFLOAD_TX
+/*
+ * Modified to include the first descriptor pointer in case of SG
+ */
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * mp,
+                                         struct pkt_info * p_pkt_info)
+{
+       int tx_desc_curr, tx_desc_used, tx_first_desc, tx_next_desc;
+       volatile struct eth_tx_desc *current_descriptor;
+       volatile struct eth_tx_desc *first_descriptor;
+       u32 command_status, first_chip_ptr;
+
+       /* Do not process Tx ring in case of Tx ring resource error */
+       if (mp->tx_resource_err)
+               return ETH_QUEUE_FULL;
+
+       /* Get the Tx Desc ring indexes */
+       tx_desc_curr = mp->tx_curr_desc_q;
+       tx_desc_used = mp->tx_used_desc_q;
+
+       current_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
+       if (current_descriptor == NULL)
+               return ETH_ERROR;
+
+       tx_next_desc = (tx_desc_curr + 1) % MV64340_TX_QUEUE_SIZE;
+       command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC;
+
+       if (command_status & ETH_TX_FIRST_DESC) {
+               tx_first_desc = tx_desc_curr;
+               mp->tx_first_desc_q = tx_first_desc;
+
+                /* fill first descriptor */
+                first_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
+                first_descriptor->l4i_chk = p_pkt_info->l4i_chk;
+                first_descriptor->cmd_sts = command_status;
+                first_descriptor->byte_cnt = p_pkt_info->byte_cnt;
+                first_descriptor->buf_ptr = p_pkt_info->buf_ptr;
+                first_descriptor->next_desc_ptr = mp->tx_desc_dma +
+                       tx_next_desc * sizeof(struct eth_tx_desc);
+               wmb();
+        } else {
+                tx_first_desc = mp->tx_first_desc_q;
+                first_descriptor = &mp->p_tx_desc_area[tx_first_desc];
+                if (first_descriptor == NULL) {
+                        printk("First desc is NULL !!\n");
+                        return ETH_ERROR;
+                }
+                if (command_status & ETH_TX_LAST_DESC)
+                        current_descriptor->next_desc_ptr = 0x00000000;
+                else {
+                        command_status |= ETH_BUFFER_OWNED_BY_DMA;
+                        current_descriptor->next_desc_ptr = mp->tx_desc_dma +
+                               tx_next_desc * sizeof(struct eth_tx_desc);
+                }
+        }
+
+        if (p_pkt_info->byte_cnt < 8) {
+                printk(" < 8 problem \n");
+                return ETH_ERROR;
+        }
+
+        current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
+        current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
+        current_descriptor->l4i_chk = p_pkt_info->l4i_chk;
+        current_descriptor->cmd_sts = command_status;
+
+        mp->tx_skb[tx_desc_curr] = (struct sk_buff*) p_pkt_info->return_info;
+
+        wmb();
+
+        /* Set last desc with DMA ownership and interrupt enable. */
+        if (command_status & ETH_TX_LAST_DESC) {
+                current_descriptor->cmd_sts = command_status |
+                                        ETH_TX_ENABLE_INTERRUPT |
+                                        ETH_BUFFER_OWNED_BY_DMA;
+
+               if (!(command_status & ETH_TX_FIRST_DESC))
+                       first_descriptor->cmd_sts |= ETH_BUFFER_OWNED_BY_DMA;
+               wmb();
+
+               first_chip_ptr = MV_READ(MV64340_ETH_CURRENT_SERVED_TX_DESC_PTR(mp->port_num));
+
+               /* Apply send command */
+               if (first_chip_ptr == 0x00000000)
+                       MV_WRITE(MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(mp->port_num), (struct eth_tx_desc *) mp->tx_desc_dma + tx_first_desc);
+
+                ETH_ENABLE_TX_QUEUE(mp->port_num);
+
+               /*
+                * Finish Tx packet. Update first desc in case of Tx resource
+                * error */
+                tx_first_desc = tx_next_desc;
+                mp->tx_first_desc_q = tx_first_desc;
+       } else {
+               if (! (command_status & ETH_TX_FIRST_DESC) ) {
+                       current_descriptor->cmd_sts = command_status;
+                       wmb();
+               }
+       }
+
+        /* Check for ring index overlap in the Tx desc ring */
+        if (tx_next_desc == tx_desc_used) {
+                mp->tx_resource_err = 1;
+                mp->tx_curr_desc_q = tx_first_desc;
+
+                return ETH_QUEUE_LAST_RESOURCE;
+       }
+
+        mp->tx_curr_desc_q = tx_next_desc;
+        wmb();
+
+        return ETH_OK;
+}
+#else
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * mp,
+                                        struct pkt_info * p_pkt_info)
+{
+       int tx_desc_curr;
+       int tx_desc_used;
+       volatile struct eth_tx_desc* current_descriptor;
+       unsigned int command_status;
+
+       /* Do not process Tx ring in case of Tx ring resource error */
+       if (mp->tx_resource_err)
+               return ETH_QUEUE_FULL;
+
+       /* Get the Tx Desc ring indexes */
+       tx_desc_curr = mp->tx_curr_desc_q;
+       tx_desc_used = mp->tx_used_desc_q;
+       current_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
+
+       if (current_descriptor == NULL)
+               return ETH_ERROR;
+
+       command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC;
+
+/* XXX Is this for real ?!?!? */
+       /* Buffers with a payload smaller than 8 bytes must be aligned to a
+        * 64-bit boundary. We use the memory allocated for Tx descriptor.
+        * This memory is located in TX_BUF_OFFSET_IN_DESC offset within the
+        * Tx descriptor. */
+       if (p_pkt_info->byte_cnt <= 8) {
+               printk(KERN_ERR
+                      "You have failed in the < 8 bytes errata - fixme\n");
+               return ETH_ERROR;
+       }
+       current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
+       current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
+       mp->tx_skb[tx_desc_curr] = (struct sk_buff *) p_pkt_info->return_info;
+
+       mb();
+
+       /* Set last desc with DMA ownership and interrupt enable. */
+       current_descriptor->cmd_sts = command_status |
+                       ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT;
+
+       /* Apply send command */
+       ETH_ENABLE_TX_QUEUE(mp->port_num);
+
+       /* Finish Tx packet. Update first desc in case of Tx resource error */
+       tx_desc_curr = (tx_desc_curr + 1) % MV64340_TX_QUEUE_SIZE;
+
+       /* Update the current descriptor */
+       mp->tx_curr_desc_q = tx_desc_curr;
+
+       /* Check for ring index overlap in the Tx desc ring */
+       if (tx_desc_curr == tx_desc_used) {
+               mp->tx_resource_err = 1;
+               return ETH_QUEUE_LAST_RESOURCE;
+       }
+
+       return ETH_OK;
+}
+#endif
+
+/*
+ * eth_tx_return_desc - Free all used Tx descriptors
+ *
+ * DESCRIPTION:
+ *     This routine returns the transmitted packet information to the caller.
+ *      It uses the 'first' index to support Tx desc return in case a transmit 
+ *      of a packet spanned over multiple buffer still in process.
+ *      In case the Tx queue was in "resource error" condition, where there are 
+ *      no available Tx resources, the function resets the resource error flag.
+ *
+ * INPUT:
+ *     struct mv64340_private   *mp   Ethernet Port Control srtuct. 
+ *     struct pkt_info        *p_pkt_info       User packet buffer.
+ *
+ * OUTPUT:
+ *     Tx ring 'first' and 'used' indexes are updated. 
+ *
+ * RETURN:
+ *     ETH_ERROR in case the routine can not access Tx desc ring.
+ *      ETH_RETRY in case there is transmission in process.
+ *     ETH_END_OF_JOB if the routine has nothing to release.
+ *      ETH_OK otherwise.
+ *
+ */
+static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv64340_private * mp,
+                                             struct pkt_info * p_pkt_info)
+{
+       int tx_desc_used, tx_desc_curr;
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+        int tx_first_desc;
+#endif
+       volatile struct eth_tx_desc *p_tx_desc_used;
+       unsigned int command_status;
+
+       /* Get the Tx Desc ring indexes */
+       tx_desc_curr = mp->tx_curr_desc_q;
+       tx_desc_used = mp->tx_used_desc_q;
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+        tx_first_desc = mp->tx_first_desc_q;
+#endif
+       p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used];
+
+       /* XXX Sanity check */
+       if (p_tx_desc_used == NULL)
+               return ETH_ERROR;
+
+       command_status = p_tx_desc_used->cmd_sts;
+
+       /* Still transmitting... */
+#ifndef MV64340_CHECKSUM_OFFLOAD_TX
+       if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
+               return ETH_RETRY;
+#endif
+       /* Stop release. About to overlap the current available Tx descriptor */
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+       if (tx_desc_used == tx_first_desc && !mp->tx_resource_err)
+               return ETH_END_OF_JOB;
+#else
+       if (tx_desc_used == tx_desc_curr && !mp->tx_resource_err)
+               return ETH_END_OF_JOB;
+#endif
+
+       /* Pass the packet information to the caller */
+       p_pkt_info->cmd_sts = command_status;
+       p_pkt_info->return_info = mp->tx_skb[tx_desc_used];
+       mp->tx_skb[tx_desc_used] = NULL;
+
+       /* Update the next descriptor to release. */
+       mp->tx_used_desc_q = (tx_desc_used + 1) % MV64340_TX_QUEUE_SIZE;
+
+       /* Any Tx return cancels the Tx resource error status */
+       mp->tx_resource_err = 0;
+
+       return ETH_OK;
+}
+
+/*
+ * eth_port_receive - Get received information from Rx ring.
+ *
+ * DESCRIPTION:
+ *     This routine returns the received data to the caller. There is no 
+ *     data copying during routine operation. All information is returned 
+ *     using pointer to packet information struct passed from the caller. 
+ *      If the routine exhausts        Rx ring resources then the resource error flag 
+ *      is set.  
+ *
+ * INPUT:
+ *     struct mv64340_private   *mp   Ethernet Port Control srtuct. 
+ *     struct pkt_info        *p_pkt_info       User packet buffer.
+ *
+ * OUTPUT:
+ *     Rx ring current and used indexes are updated. 
+ *
+ * RETURN:
+ *     ETH_ERROR in case the routine can not access Rx desc ring.
+ *     ETH_QUEUE_FULL if Rx ring resources are exhausted.
+ *     ETH_END_OF_JOB if there is no received data.
+ *      ETH_OK otherwise.
+ */
+static ETH_FUNC_RET_STATUS eth_port_receive(struct mv64340_private * mp,
+                                           struct pkt_info * p_pkt_info)
+{
+       int rx_next_curr_desc, rx_curr_desc, rx_used_desc;
+       volatile struct eth_rx_desc * p_rx_desc;
+       unsigned int command_status;
+
+       /* Do not process Rx ring in case of Rx ring resource error */
+       if (mp->rx_resource_err)
+               return ETH_QUEUE_FULL;
+
+       /* Get the Rx Desc ring 'curr and 'used' indexes */
+       rx_curr_desc = mp->rx_curr_desc_q;
+       rx_used_desc = mp->rx_used_desc_q;
+
+       p_rx_desc = &mp->p_rx_desc_area[rx_curr_desc];
+
+       /* The following parameters are used to save readings from memory */
+       command_status = p_rx_desc->cmd_sts;
+
+       /* Nothing to receive... */
+       if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
+               return ETH_END_OF_JOB;
+
+       p_pkt_info->byte_cnt = (p_rx_desc->byte_cnt) - RX_BUF_OFFSET;
+       p_pkt_info->cmd_sts = command_status;
+       p_pkt_info->buf_ptr = (p_rx_desc->buf_ptr) + RX_BUF_OFFSET;
+       p_pkt_info->return_info = mp->rx_skb[rx_curr_desc];
+       p_pkt_info->l4i_chk = p_rx_desc->buf_size;
+
+       /* Clean the return info field to indicate that the packet has been */
+       /* moved to the upper layers                                        */
+       mp->rx_skb[rx_curr_desc] = NULL;
+
+       /* Update current index in data structure */
+       rx_next_curr_desc = (rx_curr_desc + 1) % MV64340_RX_QUEUE_SIZE;
+       mp->rx_curr_desc_q = rx_next_curr_desc;
+
+       /* Rx descriptors exhausted. Set the Rx ring resource error flag */
+       if (rx_next_curr_desc == rx_used_desc)
+               mp->rx_resource_err = 1;
+
+       mb();
+       return ETH_OK;
+}
+
+/*
+ * eth_rx_return_buff - Returns a Rx buffer back to the Rx ring.
+ *
+ * DESCRIPTION:
+ *     This routine returns a Rx buffer back to the Rx ring. It retrieves the 
+ *      next 'used' descriptor and attached the returned buffer to it.
+ *      In case the Rx ring was in "resource error" condition, where there are 
+ *      no available Rx resources, the function resets the resource error flag.
+ *
+ * INPUT:
+ *     struct mv64340_private *mp   Ethernet Port Control srtuct. 
+ *      struct pkt_info        *p_pkt_info   Information on the returned buffer.
+ *
+ * OUTPUT:
+ *     New available Rx resource in Rx descriptor ring.
+ *
+ * RETURN:
+ *     ETH_ERROR in case the routine can not access Rx desc ring.
+ *      ETH_OK otherwise.
+ */
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv64340_private * mp,
+       struct pkt_info * p_pkt_info)
+{
+       int used_rx_desc;       /* Where to return Rx resource */
+       volatile struct eth_rx_desc* p_used_rx_desc;
+
+       /* Get 'used' Rx descriptor */
+       used_rx_desc = mp->rx_used_desc_q;
+       p_used_rx_desc = &mp->p_rx_desc_area[used_rx_desc];
+
+       p_used_rx_desc->buf_ptr = p_pkt_info->buf_ptr;
+       p_used_rx_desc->buf_size = p_pkt_info->byte_cnt;
+       mp->rx_skb[used_rx_desc] = p_pkt_info->return_info;
+
+       /* Flush the write pipe */
+       mb();
+
+       /* Return the descriptor to DMA ownership */
+       p_used_rx_desc->cmd_sts =
+               ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
+
+       /* Flush descriptor and CPU pipe */
+       mb();
+
+       /* Move the used descriptor pointer to the next descriptor */
+       mp->rx_used_desc_q = (used_rx_desc + 1) % MV64340_RX_QUEUE_SIZE;
+
+       /* Any Rx return cancels the Rx resource error status */
+       mp->rx_resource_err = 0;
+
+       return ETH_OK;
+}
diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h
new file mode 100644 (file)
index 0000000..46a057d
--- /dev/null
@@ -0,0 +1,601 @@
+#ifndef __MV64340_ETH_H__
+#define __MV64340_ETH_H__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+#include <linux/mv643xx.h>
+
+#define        BIT0    0x00000001
+#define        BIT1    0x00000002
+#define        BIT2    0x00000004
+#define        BIT3    0x00000008
+#define        BIT4    0x00000010
+#define        BIT5    0x00000020
+#define        BIT6    0x00000040
+#define        BIT7    0x00000080
+#define        BIT8    0x00000100
+#define        BIT9    0x00000200
+#define        BIT10   0x00000400
+#define        BIT11   0x00000800
+#define        BIT12   0x00001000
+#define        BIT13   0x00002000
+#define        BIT14   0x00004000
+#define        BIT15   0x00008000
+#define        BIT16   0x00010000
+#define        BIT17   0x00020000
+#define        BIT18   0x00040000
+#define        BIT19   0x00080000
+#define        BIT20   0x00100000
+#define        BIT21   0x00200000
+#define        BIT22   0x00400000
+#define        BIT23   0x00800000
+#define        BIT24   0x01000000
+#define        BIT25   0x02000000
+#define        BIT26   0x04000000
+#define        BIT27   0x08000000
+#define        BIT28   0x10000000
+#define        BIT29   0x20000000
+#define        BIT30   0x40000000
+#define        BIT31   0x80000000
+
+/*
+ *  The first part is the high level driver of the gigE ethernet ports.
+ */
+
+#define ETH_PORT0_IRQ_NUM 48                   /* main high register, bit0 */
+#define ETH_PORT1_IRQ_NUM ETH_PORT0_IRQ_NUM+1  /* main high register, bit1 */
+#define ETH_PORT2_IRQ_NUM ETH_PORT0_IRQ_NUM+2  /* main high register, bit1 */
+
+/* Checksum offload for Tx works */
+#define  MV64340_CHECKSUM_OFFLOAD_TX
+#define         MV64340_NAPI
+#define         MV64340_TX_FAST_REFILL
+#undef  MV64340_COAL
+
+/* 
+ * Number of RX / TX descriptors on RX / TX rings.
+ * Note that allocating RX descriptors is done by allocating the RX
+ * ring AND a preallocated RX buffers (skb's) for each descriptor.
+ * The TX descriptors only allocates the TX descriptors ring,
+ * with no pre allocated TX buffers (skb's are allocated by higher layers.
+ */
+
+/* Default TX ring size is 1000 descriptors */
+#define MV64340_TX_QUEUE_SIZE 1000
+
+/* Default RX ring size is 400 descriptors */
+#define MV64340_RX_QUEUE_SIZE 400
+
+#define MV64340_TX_COAL 100
+#ifdef MV64340_COAL
+#define MV64340_RX_COAL 100
+#endif
+
+
+/*
+ * The second part is the low level driver of the gigE ethernet ports.   *
+ */
+
+
+/*
+ * Header File for : MV-643xx network interface header 
+ *
+ * DESCRIPTION:
+ *       This header file contains macros typedefs and function declaration for
+ *       the Marvell Gig Bit Ethernet Controller. 
+ *
+ * DEPENDENCIES:
+ *       None.
+ *
+ */
+
+/* Default port configuration value */
+#define PORT_CONFIG_VALUE                       \
+             ETH_UNICAST_NORMAL_MODE           |   \
+             ETH_DEFAULT_RX_QUEUE_0            |   \
+             ETH_DEFAULT_RX_ARP_QUEUE_0                |   \
+             ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP   |   \
+             ETH_RECEIVE_BC_IF_IP              |   \
+             ETH_RECEIVE_BC_IF_ARP             |   \
+             ETH_CAPTURE_TCP_FRAMES_DIS                |   \
+             ETH_CAPTURE_UDP_FRAMES_DIS                |   \
+             ETH_DEFAULT_RX_TCP_QUEUE_0                |   \
+             ETH_DEFAULT_RX_UDP_QUEUE_0                |   \
+             ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+/* Default port extend configuration value */
+#define PORT_CONFIG_EXTEND_VALUE               \
+             ETH_SPAN_BPDU_PACKETS_AS_NORMAL   |   \
+             ETH_PARTITION_DISABLE
+
+
+/* Default sdma control value */
+#define PORT_SDMA_CONFIG_VALUE                 \
+                        ETH_RX_BURST_SIZE_16_64BIT     |       \
+                        GT_ETH_IPG_INT_RX(0)           |       \
+                        ETH_TX_BURST_SIZE_16_64BIT;
+
+#define GT_ETH_IPG_INT_RX(value)                \
+            ((value & 0x3fff) << 8)
+
+/* Default port serial control value */
+#define PORT_SERIAL_CONTROL_VALUE              \
+                       ETH_FORCE_LINK_PASS                     |       \
+                       ETH_ENABLE_AUTO_NEG_FOR_DUPLX           |       \
+                       ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL      |       \
+                       ETH_ADV_SYMMETRIC_FLOW_CTRL             |       \
+                       ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX       |       \
+                       ETH_FORCE_BP_MODE_NO_JAM                |       \
+                       BIT9                                    |       \
+                       ETH_DO_NOT_FORCE_LINK_FAIL              |       \
+                       ETH_RETRANSMIT_16_ATTEMPTS              |       \
+                       ETH_ENABLE_AUTO_NEG_SPEED_GMII          |       \
+                       ETH_DTE_ADV_0                           |       \
+                       ETH_DISABLE_AUTO_NEG_BYPASS             |       \
+                       ETH_AUTO_NEG_NO_CHANGE                  |       \
+                       ETH_MAX_RX_PACKET_9700BYTE              |       \
+                       ETH_CLR_EXT_LOOPBACK                    |       \
+                       ETH_SET_FULL_DUPLEX_MODE                |       \
+                       ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+#define RX_BUFFER_MAX_SIZE  0x4000000
+#define TX_BUFFER_MAX_SIZE  0x4000000
+
+/* MAC accepet/reject macros */
+#define ACCEPT_MAC_ADDR            0
+#define REJECT_MAC_ADDR            1
+
+/* Buffer offset from buffer pointer */
+#define RX_BUF_OFFSET                          0x2
+
+/* Gigabit Ethernet Unit Global Registers */
+
+/* MIB Counters register definitions */
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW   0x0
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH  0x4
+#define ETH_MIB_BAD_OCTETS_RECEIVED        0x8
+#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR  0xc
+#define ETH_MIB_GOOD_FRAMES_RECEIVED       0x10
+#define ETH_MIB_BAD_FRAMES_RECEIVED        0x14
+#define ETH_MIB_BROADCAST_FRAMES_RECEIVED  0x18
+#define ETH_MIB_MULTICAST_FRAMES_RECEIVED  0x1c
+#define ETH_MIB_FRAMES_64_OCTETS           0x20
+#define ETH_MIB_FRAMES_65_TO_127_OCTETS    0x24
+#define ETH_MIB_FRAMES_128_TO_255_OCTETS   0x28
+#define ETH_MIB_FRAMES_256_TO_511_OCTETS   0x2c
+#define ETH_MIB_FRAMES_512_TO_1023_OCTETS  0x30
+#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS  0x34
+#define ETH_MIB_GOOD_OCTETS_SENT_LOW       0x38
+#define ETH_MIB_GOOD_OCTETS_SENT_HIGH      0x3c
+#define ETH_MIB_GOOD_FRAMES_SENT           0x40
+#define ETH_MIB_EXCESSIVE_COLLISION        0x44
+#define ETH_MIB_MULTICAST_FRAMES_SENT      0x48
+#define ETH_MIB_BROADCAST_FRAMES_SENT      0x4c
+#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50
+#define ETH_MIB_FC_SENT                    0x54
+#define ETH_MIB_GOOD_FC_RECEIVED           0x58
+#define ETH_MIB_BAD_FC_RECEIVED            0x5c
+#define ETH_MIB_UNDERSIZE_RECEIVED         0x60
+#define ETH_MIB_FRAGMENTS_RECEIVED         0x64
+#define ETH_MIB_OVERSIZE_RECEIVED          0x68
+#define ETH_MIB_JABBER_RECEIVED            0x6c
+#define ETH_MIB_MAC_RECEIVE_ERROR          0x70
+#define ETH_MIB_BAD_CRC_EVENT              0x74
+#define ETH_MIB_COLLISION                  0x78
+#define ETH_MIB_LATE_COLLISION             0x7c
+
+/* Port serial status reg (PSR) */
+#define ETH_INTERFACE_GMII_MII                          0
+#define ETH_INTERFACE_PCM                               BIT0
+#define ETH_LINK_IS_DOWN                                0
+#define ETH_LINK_IS_UP                                  BIT1
+#define ETH_PORT_AT_HALF_DUPLEX                         0
+#define ETH_PORT_AT_FULL_DUPLEX                         BIT2
+#define ETH_RX_FLOW_CTRL_DISABLED                       0
+#define ETH_RX_FLOW_CTRL_ENBALED                        BIT3
+#define ETH_GMII_SPEED_100_10                           0
+#define ETH_GMII_SPEED_1000                             BIT4
+#define ETH_MII_SPEED_10                                0
+#define ETH_MII_SPEED_100                               BIT5
+#define ETH_NO_TX                                       0
+#define ETH_TX_IN_PROGRESS                              BIT7
+#define ETH_BYPASS_NO_ACTIVE                            0
+#define ETH_BYPASS_ACTIVE                               BIT8
+#define ETH_PORT_NOT_AT_PARTITION_STATE                 0
+#define ETH_PORT_AT_PARTITION_STATE                     BIT9
+#define ETH_PORT_TX_FIFO_NOT_EMPTY                      0
+#define ETH_PORT_TX_FIFO_EMPTY                          BIT10
+
+
+/* These macros describes the Port configuration reg (Px_cR) bits */
+#define ETH_UNICAST_NORMAL_MODE                         0
+#define ETH_UNICAST_PROMISCUOUS_MODE                    BIT0
+#define ETH_DEFAULT_RX_QUEUE_0                          0
+#define ETH_DEFAULT_RX_QUEUE_1                          BIT1
+#define ETH_DEFAULT_RX_QUEUE_2                          BIT2
+#define ETH_DEFAULT_RX_QUEUE_3                          (BIT2 | BIT1)
+#define ETH_DEFAULT_RX_QUEUE_4                          BIT3
+#define ETH_DEFAULT_RX_QUEUE_5                          (BIT3 | BIT1)
+#define ETH_DEFAULT_RX_QUEUE_6                          (BIT3 | BIT2)
+#define ETH_DEFAULT_RX_QUEUE_7                          (BIT3 | BIT2 | BIT1)
+#define ETH_DEFAULT_RX_ARP_QUEUE_0                      0
+#define ETH_DEFAULT_RX_ARP_QUEUE_1                      BIT4
+#define ETH_DEFAULT_RX_ARP_QUEUE_2                      BIT5
+#define ETH_DEFAULT_RX_ARP_QUEUE_3                      (BIT5 | BIT4)
+#define ETH_DEFAULT_RX_ARP_QUEUE_4                      BIT6
+#define ETH_DEFAULT_RX_ARP_QUEUE_5                      (BIT6 | BIT4)
+#define ETH_DEFAULT_RX_ARP_QUEUE_6                      (BIT6 | BIT5)
+#define ETH_DEFAULT_RX_ARP_QUEUE_7                      (BIT6 | BIT5 | BIT4)
+#define ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP                 0
+#define ETH_REJECT_BC_IF_NOT_IP_OR_ARP                  BIT7
+#define ETH_RECEIVE_BC_IF_IP                            0
+#define ETH_REJECT_BC_IF_IP                             BIT8
+#define ETH_RECEIVE_BC_IF_ARP                           0
+#define ETH_REJECT_BC_IF_ARP                            BIT9
+#define ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY               BIT12
+#define ETH_CAPTURE_TCP_FRAMES_DIS                      0
+#define ETH_CAPTURE_TCP_FRAMES_EN                       BIT14
+#define ETH_CAPTURE_UDP_FRAMES_DIS                      0
+#define ETH_CAPTURE_UDP_FRAMES_EN                       BIT15
+#define ETH_DEFAULT_RX_TCP_QUEUE_0                      0
+#define ETH_DEFAULT_RX_TCP_QUEUE_1                      BIT16
+#define ETH_DEFAULT_RX_TCP_QUEUE_2                      BIT17
+#define ETH_DEFAULT_RX_TCP_QUEUE_3                      (BIT17 | BIT16)
+#define ETH_DEFAULT_RX_TCP_QUEUE_4                      BIT18
+#define ETH_DEFAULT_RX_TCP_QUEUE_5                      (BIT18 | BIT16)
+#define ETH_DEFAULT_RX_TCP_QUEUE_6                      (BIT18 | BIT17)
+#define ETH_DEFAULT_RX_TCP_QUEUE_7                      (BIT18 | BIT17 | BIT16)
+#define ETH_DEFAULT_RX_UDP_QUEUE_0                      0
+#define ETH_DEFAULT_RX_UDP_QUEUE_1                      BIT19
+#define ETH_DEFAULT_RX_UDP_QUEUE_2                      BIT20
+#define ETH_DEFAULT_RX_UDP_QUEUE_3                      (BIT20 | BIT19)
+#define ETH_DEFAULT_RX_UDP_QUEUE_4                      (BIT21
+#define ETH_DEFAULT_RX_UDP_QUEUE_5                      (BIT21 | BIT19)
+#define ETH_DEFAULT_RX_UDP_QUEUE_6                      (BIT21 | BIT20)
+#define ETH_DEFAULT_RX_UDP_QUEUE_7                      (BIT21 | BIT20 | BIT19)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_0                      0
+#define ETH_DEFAULT_RX_BPDU_QUEUE_1                     BIT22
+#define ETH_DEFAULT_RX_BPDU_QUEUE_2                     BIT23
+#define ETH_DEFAULT_RX_BPDU_QUEUE_3                     (BIT23 | BIT22)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_4                     BIT24
+#define ETH_DEFAULT_RX_BPDU_QUEUE_5                     (BIT24 | BIT22)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_6                     (BIT24 | BIT23)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_7                     (BIT24 | BIT23 | BIT22)
+
+
+/* These macros describes the Port configuration extend reg (Px_cXR) bits*/
+#define ETH_CLASSIFY_EN                                 BIT0
+#define ETH_SPAN_BPDU_PACKETS_AS_NORMAL                 0
+#define ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7             BIT1
+#define ETH_PARTITION_DISABLE                           0
+#define ETH_PARTITION_ENABLE                            BIT2
+
+
+/* Tx/Rx queue command reg (RQCR/TQCR)*/
+#define ETH_QUEUE_0_ENABLE                              BIT0
+#define ETH_QUEUE_1_ENABLE                              BIT1
+#define ETH_QUEUE_2_ENABLE                              BIT2
+#define ETH_QUEUE_3_ENABLE                              BIT3
+#define ETH_QUEUE_4_ENABLE                              BIT4
+#define ETH_QUEUE_5_ENABLE                              BIT5
+#define ETH_QUEUE_6_ENABLE                              BIT6
+#define ETH_QUEUE_7_ENABLE                              BIT7
+#define ETH_QUEUE_0_DISABLE                             BIT8
+#define ETH_QUEUE_1_DISABLE                             BIT9
+#define ETH_QUEUE_2_DISABLE                             BIT10
+#define ETH_QUEUE_3_DISABLE                             BIT11
+#define ETH_QUEUE_4_DISABLE                             BIT12
+#define ETH_QUEUE_5_DISABLE                             BIT13
+#define ETH_QUEUE_6_DISABLE                             BIT14
+#define ETH_QUEUE_7_DISABLE                             BIT15
+
+
+/* These macros describes the Port Sdma configuration reg (SDCR) bits */
+#define ETH_RIFB                                        BIT0
+#define ETH_RX_BURST_SIZE_1_64BIT                       0
+#define ETH_RX_BURST_SIZE_2_64BIT                       BIT1
+#define ETH_RX_BURST_SIZE_4_64BIT                       BIT2
+#define ETH_RX_BURST_SIZE_8_64BIT                       (BIT2 | BIT1)
+#define ETH_RX_BURST_SIZE_16_64BIT                      BIT3
+#define ETH_BLM_RX_NO_SWAP                              BIT4
+#define ETH_BLM_RX_BYTE_SWAP                            0
+#define ETH_BLM_TX_NO_SWAP                              BIT5
+#define ETH_BLM_TX_BYTE_SWAP                            0
+#define ETH_DESCRIPTORS_BYTE_SWAP                       BIT6
+#define ETH_DESCRIPTORS_NO_SWAP                         0
+#define ETH_TX_BURST_SIZE_1_64BIT                       0
+#define ETH_TX_BURST_SIZE_2_64BIT                       BIT22
+#define ETH_TX_BURST_SIZE_4_64BIT                       BIT23
+#define ETH_TX_BURST_SIZE_8_64BIT                       (BIT23 | BIT22)
+#define ETH_TX_BURST_SIZE_16_64BIT                      BIT24
+
+
+
+/* These macros describes the Port serial control reg (PSCR) bits */
+#define ETH_SERIAL_PORT_DISABLE                         0
+#define ETH_SERIAL_PORT_ENABLE                          BIT0
+#define ETH_FORCE_LINK_PASS                             BIT1
+#define ETH_DO_NOT_FORCE_LINK_PASS                      0
+#define ETH_ENABLE_AUTO_NEG_FOR_DUPLX                   0
+#define ETH_DISABLE_AUTO_NEG_FOR_DUPLX                  BIT2
+#define ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL               0
+#define ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL              BIT3
+#define ETH_ADV_NO_FLOW_CTRL                            0
+#define ETH_ADV_SYMMETRIC_FLOW_CTRL                     BIT4
+#define ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX               0
+#define ETH_FORCE_FC_MODE_TX_PAUSE_DIS                  BIT5
+#define ETH_FORCE_BP_MODE_NO_JAM                        0
+#define ETH_FORCE_BP_MODE_JAM_TX                        BIT7
+#define ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR              BIT8
+#define ETH_FORCE_LINK_FAIL                             0
+#define ETH_DO_NOT_FORCE_LINK_FAIL                      BIT10
+#define ETH_RETRANSMIT_16_ATTEMPTS                      0
+#define ETH_RETRANSMIT_FOREVER                          BIT11
+#define ETH_DISABLE_AUTO_NEG_SPEED_GMII                 BIT13
+#define ETH_ENABLE_AUTO_NEG_SPEED_GMII                  0
+#define ETH_DTE_ADV_0                                   0
+#define ETH_DTE_ADV_1                                   BIT14
+#define ETH_DISABLE_AUTO_NEG_BYPASS                     0
+#define ETH_ENABLE_AUTO_NEG_BYPASS                      BIT15
+#define ETH_AUTO_NEG_NO_CHANGE                          0
+#define ETH_RESTART_AUTO_NEG                            BIT16
+#define ETH_MAX_RX_PACKET_1518BYTE                      0
+#define ETH_MAX_RX_PACKET_1522BYTE                      BIT17
+#define ETH_MAX_RX_PACKET_1552BYTE                      BIT18
+#define ETH_MAX_RX_PACKET_9022BYTE                      (BIT18 | BIT17)
+#define ETH_MAX_RX_PACKET_9192BYTE                      BIT19
+#define ETH_MAX_RX_PACKET_9700BYTE                      (BIT19 | BIT17)
+#define ETH_SET_EXT_LOOPBACK                            BIT20
+#define ETH_CLR_EXT_LOOPBACK                            0
+#define ETH_SET_FULL_DUPLEX_MODE                        BIT21
+#define ETH_SET_HALF_DUPLEX_MODE                        0
+#define ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX       BIT22
+#define ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX      0
+#define ETH_SET_GMII_SPEED_TO_10_100                    0
+#define ETH_SET_GMII_SPEED_TO_1000                      BIT23
+#define ETH_SET_MII_SPEED_TO_10                         0
+#define ETH_SET_MII_SPEED_TO_100                        BIT24
+
+
+/* SMI reg */
+#define ETH_SMI_BUSY           BIT28   /* 0 - Write, 1 - Read          */
+#define ETH_SMI_READ_VALID     BIT27   /* 0 - Write, 1 - Read          */
+#define ETH_SMI_OPCODE_WRITE   0       /* Completion of Read operation */
+#define ETH_SMI_OPCODE_READ    BIT26   /* Operation is in progress             */
+
+/* SDMA command status fields macros */
+
+/* Tx & Rx descriptors status */
+#define ETH_ERROR_SUMMARY                   (BIT0)
+
+/* Tx & Rx descriptors command */
+#define ETH_BUFFER_OWNED_BY_DMA             (BIT31)
+
+/* Tx descriptors status */
+#define ETH_LC_ERROR                        (0   )
+#define ETH_UR_ERROR                        (BIT1 )
+#define ETH_RL_ERROR                        (BIT2 )
+#define ETH_LLC_SNAP_FORMAT                 (BIT9 )
+
+/* Rx descriptors status */
+#define ETH_CRC_ERROR                       (0   )
+#define ETH_OVERRUN_ERROR                   (BIT1 )
+#define ETH_MAX_FRAME_LENGTH_ERROR          (BIT2 )
+#define ETH_RESOURCE_ERROR                  ((BIT2 | BIT1))
+#define ETH_VLAN_TAGGED                     (BIT19)
+#define ETH_BPDU_FRAME                      (BIT20)
+#define ETH_TCP_FRAME_OVER_IP_V_4           (0    )
+#define ETH_UDP_FRAME_OVER_IP_V_4           (BIT21)
+#define ETH_OTHER_FRAME_TYPE                (BIT22)
+#define ETH_LAYER_2_IS_ETH_V_2              (BIT23)
+#define ETH_FRAME_TYPE_IP_V_4               (BIT24)
+#define ETH_FRAME_HEADER_OK                 (BIT25)
+#define ETH_RX_LAST_DESC                    (BIT26)
+#define ETH_RX_FIRST_DESC                   (BIT27)
+#define ETH_UNKNOWN_DESTINATION_ADDR        (BIT28)
+#define ETH_RX_ENABLE_INTERRUPT             (BIT29)
+#define ETH_LAYER_4_CHECKSUM_OK             (BIT30)
+
+/* Rx descriptors byte count */
+#define ETH_FRAME_FRAGMENTED                (BIT2)
+
+/* Tx descriptors command */
+#define ETH_LAYER_4_CHECKSUM_FIRST_DESC                (BIT10)
+#define ETH_FRAME_SET_TO_VLAN               (BIT15)
+#define ETH_TCP_FRAME                       (0   )
+#define ETH_UDP_FRAME                       (BIT16)
+#define ETH_GEN_TCP_UDP_CHECKSUM            (BIT17)
+#define ETH_GEN_IP_V_4_CHECKSUM             (BIT18)
+#define ETH_ZERO_PADDING                    (BIT19)
+#define ETH_TX_LAST_DESC                    (BIT20)
+#define ETH_TX_FIRST_DESC                   (BIT21)
+#define ETH_GEN_CRC                         (BIT22)
+#define ETH_TX_ENABLE_INTERRUPT             (BIT23)
+#define ETH_AUTO_MODE                       (BIT30)
+
+/* typedefs */
+
+typedef enum _eth_func_ret_status {
+       ETH_OK,                 /* Returned as expected.                    */
+       ETH_ERROR,              /* Fundamental error.                       */
+       ETH_RETRY,              /* Could not process request. Try later.    */
+       ETH_END_OF_JOB,         /* Ring has nothing to process.             */
+       ETH_QUEUE_FULL,         /* Ring resource error.                     */
+       ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust.         */
+} ETH_FUNC_RET_STATUS;
+
+typedef enum _eth_target {
+       ETH_TARGET_DRAM,
+       ETH_TARGET_DEVICE,
+       ETH_TARGET_CBS,
+       ETH_TARGET_PCI0,
+       ETH_TARGET_PCI1
+} ETH_TARGET;
+
+/* These are for big-endian machines.  Little endian needs different
+ * definitions.
+ */
+#if defined(__BIG_ENDIAN)
+struct eth_rx_desc {
+       u16     byte_cnt;       /* Descriptor buffer byte count     */
+       u16     buf_size;       /* Buffer size                      */
+       u32     cmd_sts;        /* Descriptor command status        */
+       u32     next_desc_ptr;  /* Next descriptor pointer          */
+       u32     buf_ptr;        /* Descriptor buffer pointer        */
+};
+
+struct eth_tx_desc {
+       u16     byte_cnt;       /* buffer byte count */
+       u16     l4i_chk;        /* CPU provided TCP checksum */
+       u32     cmd_sts;        /* Command/status field */
+       u32     next_desc_ptr;  /* Pointer to next descriptor */
+       u32     buf_ptr;        /* pointer to buffer for this descriptor */
+};
+
+#elif defined(__LITTLE_ENDIAN)
+struct eth_rx_desc {
+       u32     cmd_sts;        /* Descriptor command status        */
+       u16     buf_size;       /* Buffer size                      */
+       u16     byte_cnt;       /* Descriptor buffer byte count     */
+       u32     buf_ptr;        /* Descriptor buffer pointer        */
+       u32     next_desc_ptr;  /* Next descriptor pointer          */
+};
+
+struct eth_tx_desc {
+       u32     cmd_sts;        /* Command/status field */
+       u16     l4i_chk;        /* CPU provided TCP checksum */
+       u16     byte_cnt;       /* buffer byte count */
+       u32     buf_ptr;        /* pointer to buffer for this descriptor */
+       u32     next_desc_ptr;  /* Pointer to next descriptor */
+};
+#else
+#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
+#endif
+
+/* Unified struct for Rx and Tx operations. The user is not required to */
+/* be familier with neither Tx nor Rx descriptors.                       */
+struct pkt_info {
+       unsigned short  byte_cnt;       /* Descriptor buffer byte count     */
+       unsigned short  l4i_chk;        /* Tx CPU provided TCP Checksum     */
+       unsigned int    cmd_sts;        /* Descriptor command status        */
+       dma_addr_t      buf_ptr;        /* Descriptor buffer pointer        */
+       struct sk_buff  * return_info;  /* User resource return information */
+};
+
+
+/* Ethernet port specific infomation */
+
+struct mv64340_private {
+       int     port_num;               /* User Ethernet port number */
+       u8      port_mac_addr[6];       /* User defined port MAC address. */
+       u32     port_config;            /* User port configuration value */
+       u32     port_config_extend;     /* User port config extend value */
+       u32     port_sdma_config;       /* User port SDMA config value */
+       u32     port_serial_control;    /* User port serial control value */
+       u32     port_tx_queue_command;  /* Port active Tx queues summary */
+       u32     port_rx_queue_command;  /* Port active Rx queues summary */
+
+       int     rx_resource_err;        /* Rx ring resource error flag */
+       int     tx_resource_err;        /* Tx ring resource error flag */
+
+       /* Tx/Rx rings managment indexes fields. For driver use */
+
+       /* Next available and first returning Rx resource */
+       int rx_curr_desc_q, rx_used_desc_q;
+
+       /* Next available and first returning Tx resource */
+       int tx_curr_desc_q, tx_used_desc_q;
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+        int tx_first_desc_q;
+#endif
+
+#ifdef MV64340_TX_FAST_REFILL
+       u32     tx_clean_threshold;
+#endif
+
+       volatile struct eth_rx_desc     * p_rx_desc_area;
+       dma_addr_t                      rx_desc_dma;
+       unsigned int                    rx_desc_area_size;
+       struct sk_buff                  * rx_skb[MV64340_RX_QUEUE_SIZE];
+
+       volatile struct eth_tx_desc     * p_tx_desc_area;
+       dma_addr_t                      tx_desc_dma;
+       unsigned int                    tx_desc_area_size;
+       struct sk_buff                  * tx_skb[MV64340_TX_QUEUE_SIZE];
+
+       struct work_struct              tx_timeout_task;
+
+       /*
+        * Former struct mv64340_eth_priv members start here
+        */
+       struct net_device_stats stats;
+       spinlock_t lock;
+       /* Size of Tx Ring per queue */
+       unsigned int tx_ring_size;
+       /* Ammont of SKBs outstanding on Tx queue */
+       unsigned int tx_ring_skbs;
+       /* Size of Rx Ring per queue */
+       unsigned int rx_ring_size;
+       /* Ammount of SKBs allocated to Rx Ring per queue */
+       unsigned int rx_ring_skbs;
+
+       /*
+        * rx_task used to fill RX ring out of bottom half context 
+        */
+       struct work_struct rx_task;
+
+       /* 
+        * Used in case RX Ring is empty, which can be caused when 
+        * system does not have resources (skb's) 
+        */
+       struct timer_list timeout;
+       long rx_task_busy __attribute__ ((aligned(SMP_CACHE_BYTES)));
+       unsigned rx_timer_flag;
+
+       u32 rx_int_coal;
+       u32 tx_int_coal;
+};
+
+/* ethernet.h API list */
+
+/* Port operation control routines */
+static void eth_port_init(struct mv64340_private *mp);
+static void eth_port_reset(unsigned int eth_port_num);
+static int eth_port_start(struct mv64340_private *mp);
+
+static void ethernet_set_config_reg(unsigned int eth_port_num,
+                                   unsigned int value);
+static unsigned int ethernet_get_config_reg(unsigned int eth_port_num);
+
+/* Port MAC address routines */
+static void eth_port_uc_addr_set(unsigned int eth_port_num,
+                                unsigned char *p_addr);
+
+/* PHY and MIB routines */
+static int ethernet_phy_reset(unsigned int eth_port_num);
+
+static int eth_port_write_smi_reg(unsigned int eth_port_num,
+                                  unsigned int phy_reg,
+                                  unsigned int value);
+
+static int eth_port_read_smi_reg(unsigned int eth_port_num,
+                                 unsigned int phy_reg,
+                                 unsigned int *value);
+
+static void eth_clear_mib_counters(unsigned int eth_port_num);
+
+/* Port data flow control routines */
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private *mp,
+                                        struct pkt_info * p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv64340_private *mp,
+                                             struct pkt_info * p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_port_receive(struct mv64340_private *mp,
+                                           struct pkt_info * p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv64340_private *mp,
+                                             struct pkt_info * p_pkt_info);
+
+#endif  /* __MV64340_ETH_H__ */
index c4c9cb2..c5f9595 100644 (file)
@@ -85,7 +85,7 @@ static char version[] =
 static struct myri_eth *root_myri_dev;
 #endif
 
-static void myri_reset_off(unsigned long lp, unsigned long cregs)
+static void myri_reset_off(void __iomem *lp, void __iomem *cregs)
 {
        /* Clear IRQ mask. */
        sbus_writel(0, lp + LANAI_EIMASK);
@@ -94,7 +94,7 @@ static void myri_reset_off(unsigned long lp, unsigned long cregs)
        sbus_writel(CONTROL_ROFF, cregs + MYRICTRL_CTRL);
 }
 
-static void myri_reset_on(unsigned long cregs)
+static void myri_reset_on(void __iomem *cregs)
 {
        /* Enable RESET function. */
        sbus_writel(CONTROL_RON, cregs + MYRICTRL_CTRL);
@@ -103,14 +103,14 @@ static void myri_reset_on(unsigned long cregs)
        sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
 }
 
-static void myri_disable_irq(unsigned long lp, unsigned long cregs)
+static void myri_disable_irq(void __iomem *lp, void __iomem *cregs)
 {
        sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
        sbus_writel(0, lp + LANAI_EIMASK);
        sbus_writel(ISTAT_HOST, lp + LANAI_ISTAT);
 }
 
-static void myri_enable_irq(unsigned long lp, unsigned long cregs)
+static void myri_enable_irq(void __iomem *lp, void __iomem *cregs)
 {
        sbus_writel(CONTROL_EIRQ, cregs + MYRICTRL_CTRL);
        sbus_writel(ISTAT_HOST, lp + LANAI_EIMASK);
@@ -119,7 +119,7 @@ static void myri_enable_irq(unsigned long lp, unsigned long cregs)
 static inline void bang_the_chip(struct myri_eth *mp)
 {
        struct myri_shmem *shmem        = mp->shmem;
-       unsigned long cregs             = mp->cregs;
+       void __iomem *cregs             = mp->cregs;
 
        sbus_writel(1, &shmem->send);
        sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
@@ -128,7 +128,7 @@ static inline void bang_the_chip(struct myri_eth *mp)
 static int myri_do_handshake(struct myri_eth *mp)
 {
        struct myri_shmem *shmem        = mp->shmem;
-       unsigned long cregs = mp->cregs;
+       void __iomem *cregs = mp->cregs;
        struct myri_channel *chan       = &shmem->channel;
        int tick                        = 0;
 
@@ -176,27 +176,27 @@ static int myri_do_handshake(struct myri_eth *mp)
 static int myri_load_lanai(struct myri_eth *mp)
 {
        struct net_device       *dev = mp->dev;
-       struct myri_shmem       *shmem = mp->shmem;
-       unsigned char           *rptr;
+       struct myri_shmem __iomem *shmem = mp->shmem;
+       void __iomem            *rptr;
        int                     i;
 
        myri_disable_irq(mp->lregs, mp->cregs);
        myri_reset_on(mp->cregs);
 
-       rptr = (unsigned char *) mp->lanai;
+       rptr = mp->lanai;
        for (i = 0; i < mp->eeprom.ramsz; i++)
-               sbus_writeb(0, &rptr[i]);
+               sbus_writeb(0, rptr + i);
 
        if (mp->eeprom.cpuvers >= CPUVERS_3_0)
                sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL);
 
        /* Load executable code. */
        for (i = 0; i < sizeof(lanai4_code); i++)
-               sbus_writeb(lanai4_code[i], &rptr[(lanai4_code_off * 2) + i]);
+               sbus_writeb(lanai4_code[i], rptr + (lanai4_code_off * 2) + i);
 
        /* Load data segment. */
        for (i = 0; i < sizeof(lanai4_data); i++)
-               sbus_writeb(lanai4_data[i], &rptr[(lanai4_data_off * 2) + i]);
+               sbus_writeb(lanai4_data[i], rptr + (lanai4_data_off * 2) + i);
 
        /* Set device address. */
        sbus_writeb(0, &shmem->addr[0]);
@@ -237,15 +237,15 @@ static int myri_load_lanai(struct myri_eth *mp)
 
 static void myri_clean_rings(struct myri_eth *mp)
 {
-       struct sendq *sq = mp->sq;
-       struct recvq *rq = mp->rq;
+       struct sendq __iomem *sq = mp->sq;
+       struct recvq __iomem *rq = mp->rq;
        int i;
 
        sbus_writel(0, &rq->tail);
        sbus_writel(0, &rq->head);
        for (i = 0; i < (RX_RING_SIZE+1); i++) {
                if (mp->rx_skbs[i] != NULL) {
-                       struct myri_rxd *rxd = &rq->myri_rxd[i];
+                       struct myri_rxd __iomem *rxd = &rq->myri_rxd[i];
                        u32 dma_addr;
 
                        dma_addr = sbus_readl(&rxd->myri_scatters[0].addr);
@@ -261,7 +261,7 @@ static void myri_clean_rings(struct myri_eth *mp)
        for (i = 0; i < TX_RING_SIZE; i++) {
                if (mp->tx_skbs[i] != NULL) {
                        struct sk_buff *skb = mp->tx_skbs[i];
-                       struct myri_txd *txd = &sq->myri_txd[i];
+                       struct myri_txd __iomem *txd = &sq->myri_txd[i];
                        u32 dma_addr;
 
                        dma_addr = sbus_readl(&txd->myri_gathers[0].addr);
@@ -274,8 +274,8 @@ static void myri_clean_rings(struct myri_eth *mp)
 
 static void myri_init_rings(struct myri_eth *mp, int from_irq)
 {
-       struct recvq *rq = mp->rq;
-       struct myri_rxd *rxd = &rq->myri_rxd[0];
+       struct recvq __iomem *rq = mp->rq;
+       struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
        struct net_device *dev = mp->dev;
        int gfp_flags = GFP_KERNEL;
        int i;
@@ -343,7 +343,7 @@ static void dump_ehdr_and_myripad(unsigned char *stuff)
 
 static void myri_tx(struct myri_eth *mp, struct net_device *dev)
 {
-       struct sendq *sq        = mp->sq;
+       struct sendq __iomem *sq= mp->sq;
        int entry               = mp->tx_old;
        int limit               = sbus_readl(&sq->head);
 
@@ -376,7 +376,7 @@ static unsigned short myri_type_trans(struct sk_buff *skb, struct net_device *de
        
        skb->mac.raw = (((unsigned char *)skb->data) + MYRI_PAD_LEN);
        skb_pull(skb, dev->hard_header_len);
-       eth = skb->mac.ethernet;
+       eth = eth_hdr(skb);
        
 #ifdef DEBUG_HEADER
        DHDR(("myri_type_trans: "));
@@ -411,8 +411,8 @@ static unsigned short myri_type_trans(struct sk_buff *skb, struct net_device *de
 
 static void myri_rx(struct myri_eth *mp, struct net_device *dev)
 {
-       struct recvq *rq        = mp->rq;
-       struct recvq *rqa       = mp->rqack;
+       struct recvq __iomem *rq = mp->rq;
+       struct recvq __iomem *rqa = mp->rqack;
        int entry               = sbus_readl(&rqa->head);
        int limit               = sbus_readl(&rqa->tail);
        int drops;
@@ -423,11 +423,11 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev)
        drops = 0;
        DRX(("\n"));
        while (entry != limit) {
-               struct myri_rxd *rxdack = &rqa->myri_rxd[entry];
+               struct myri_rxd __iomem *rxdack = &rqa->myri_rxd[entry];
                u32 csum                = sbus_readl(&rxdack->csum);
                int len                 = sbus_readl(&rxdack->myri_scatters[0].len);
                int index               = sbus_readl(&rxdack->ctx);
-               struct myri_rxd *rxd    = &rq->myri_rxd[rq->tail];
+               struct myri_rxd __iomem *rxd    = &rq->myri_rxd[rq->tail];
                struct sk_buff *skb     = mp->rx_skbs[index];
 
                /* Ack it. */
@@ -545,7 +545,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct net_device *dev          = (struct net_device *) dev_id;
        struct myri_eth *mp             = (struct myri_eth *) dev->priv;
-       unsigned long lregs             = mp->lregs;
+       void __iomem *lregs             = mp->lregs;
        struct myri_channel *chan       = &mp->shmem->channel;
        unsigned long flags;
        u32 status;
@@ -610,8 +610,8 @@ static void myri_tx_timeout(struct net_device *dev)
 static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct myri_eth *mp = (struct myri_eth *) dev->priv;
-       struct sendq *sq = mp->sq;
-       struct myri_txd *txd;
+       struct sendq __iomem *sq = mp->sq;
+       struct myri_txd __iomem *txd;
        unsigned long flags;
        unsigned int head, tail;
        int len, entry;
@@ -998,22 +998,20 @@ static int __init myri_ether_init(struct sbus_dev *sdev, int num)
                        printk("MyriCOM: Cannot map MyriCOM registers.\n");
                        goto err;
                }
-               mp->lanai = (unsigned short *) (mp->regs + (256 * 1024));
-               mp->lanai3 = (unsigned int *) mp->lanai;
-               mp->lregs = (unsigned long) &mp->lanai[0x10000];
+               mp->lanai = mp->regs + (256 * 1024);
+               mp->lregs = mp->lanai + (0x10000 * 2);
        } else {
                DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));
                mp->cregs = sbus_ioremap(&sdev->resource[0], 0,
                                         PAGE_SIZE, "MyriCOM Control Regs");
                mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024),
                                         PAGE_SIZE, "MyriCOM LANAI Regs");
-               mp->lanai = (unsigned short *)
+               mp->lanai =
                        sbus_ioremap(&sdev->resource[0], (512 * 1024),
                                     mp->eeprom.ramsz, "MyriCOM SRAM");
-               mp->lanai3 = (unsigned int *) mp->lanai;
        }
-       DET(("Registers mapped: cregs[%lx] lregs[%lx] lanai[%p] lanai3[%p]\n",
-            mp->cregs, mp->lregs, mp->lanai, mp->lanai3));
+       DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n",
+            mp->cregs, mp->lregs, mp->lanai));
 
        if (mp->eeprom.cpuvers >= CPUVERS_4_0)
                mp->shmem_base = 0xf000;
@@ -1022,7 +1020,8 @@ static int __init myri_ether_init(struct sbus_dev *sdev, int num)
 
        DET(("Shared memory base is %04x, ", mp->shmem_base));
 
-       mp->shmem = (struct myri_shmem *) &mp->lanai[mp->shmem_base];
+       mp->shmem = (struct myri_shmem __iomem *)
+               (mp->lanai + (mp->shmem_base * 2));
        DET(("shmem mapped at %p\n", mp->shmem));
 
        mp->rqack       = &mp->shmem->channel.recvqa;
index 944ddfa..9391e55 100644 (file)
@@ -270,22 +270,21 @@ struct myri_eth {
         * to obtain good cache hit rates.
         */
        spinlock_t                      irq_lock;
-       struct myri_shmem               *shmem;         /* Shared data structures.    */
-       unsigned long                   cregs;          /* Control register space.    */
-       struct recvq                    *rqack;         /* Where we ack rx's.         */
-       struct recvq                    *rq;            /* Where we put buffers.      */
-       struct sendq                    *sq;            /* Where we stuff tx's.       */
+       struct myri_shmem __iomem       *shmem;         /* Shared data structures.    */
+       void __iomem                    *cregs;         /* Control register space.    */
+       struct recvq __iomem            *rqack;         /* Where we ack rx's.         */
+       struct recvq __iomem            *rq;            /* Where we put buffers.      */
+       struct sendq __iomem            *sq;            /* Where we stuff tx's.       */
        struct net_device               *dev;           /* Linux/NET dev struct.      */
        int                             tx_old;         /* To speed up tx cleaning.   */
-       unsigned long                   lregs;          /* Quick ptr to LANAI regs.   */
+       void __iomem                    *lregs;         /* Quick ptr to LANAI regs.   */
        struct sk_buff         *rx_skbs[RX_RING_SIZE+1];/* RX skb's                   */
        struct sk_buff         *tx_skbs[TX_RING_SIZE];  /* TX skb's                   */
        struct net_device_stats         enet_stats;     /* Interface stats.           */
 
        /* These are less frequently accessed. */
-       unsigned long                   regs;          /* MyriCOM register space.    */
-       unsigned short                  *lanai;         /* View 2 of register space.  */
-       unsigned int                    *lanai3;        /* View 3 of register space.  */
+       void __iomem                    *regs;          /* MyriCOM register space.    */
+       void __iomem                    *lanai;         /* View 2 of register space.  */
        unsigned int                    myri_bursts;    /* SBUS bursts.               */
        struct myri_eeprom              eeprom;         /* Local copy of EEPROM.      */
        unsigned int                    reg_size;       /* Size of register space.    */
index 5a7ce8e..abf8576 100644 (file)
@@ -892,7 +892,7 @@ SK_AC       *pAC,           /* adapter context */
 SK_IOC IoC,            /* I/O context */
 SK_U32 PortNumber)     /* Port Number */
 {
-       int ReturnCode;
+       int ReturnCode = 0;
 #if (!defined(SK_SLIM) || defined(DEBUG))
        if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
                return (SK_ADDR_ILLEGAL_PORT);
@@ -1424,7 +1424,7 @@ SK_IOC    IoC,                    /* I/O context */
 SK_U32 PortNumber,             /* port whose promiscuous mode changes */
 int            NewPromMode)    /* new promiscuous mode */
 {
-       int ReturnCode;
+       int ReturnCode = 0;
 #if (!defined(SK_SLIM) || defined(DEBUG))
        if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
                return (SK_ADDR_ILLEGAL_PORT);
index 6209a35..0c1995b 100644 (file)
@@ -672,7 +672,9 @@ static int slip_receive_room(struct tty_struct *tty)
  * Handle the 'receiver data ready' interrupt.
  * This function is called by the 'tty_io' module in the kernel when
  * a block of SLIP data has been received, which can now be decapsulated
- * and sent on to some IP layer for further processing.
+ * and sent on to some IP layer for further processing. This will not
+ * be re-entered while running but other ldisc functions may be called
+ * in parallel
  */
  
 static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
@@ -841,9 +843,11 @@ sl_alloc(dev_t line)
  * SLIP line discipline is called for.  Because we are
  * sure the tty line exists, we only have to link it to
  * a free SLIP channel...
+ *
+ * Called in process context serialized from other ldisc calls.
  */
-static int
-slip_open(struct tty_struct *tty)
+
+static int slip_open(struct tty_struct *tty)
 {
        struct slip *sl;
        int err;
@@ -876,11 +880,11 @@ slip_open(struct tty_struct *tty)
        tty->disc_data = sl;
        sl->line = tty_devnum(tty);
        sl->pid = current->pid;
+       
+       /* FIXME: already done before we were called - seems this can go */
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
-
+               
        if (!test_bit(SLF_INUSE, &sl->flags)) {
                /* Perform the low-level SLIP initialization. */
                if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0)
@@ -923,6 +927,9 @@ err_exit:
 }
 
 /*
+
+  FIXME: 1,2 are fixed 3 was never true anyway.
+  
    Let me to blame a bit.
    1. TTY module calls this funstion on soft interrupt.
    2. TTY module calls this function WITH MASKED INTERRUPTS!
@@ -941,9 +948,8 @@ err_exit:
 
 /*
  * Close down a SLIP channel.
- * This means flushing out any pending queues, and then restoring the
- * TTY line discipline to what it was before it got hooked to SLIP
- * (which usually is TTY again).
+ * This means flushing out any pending queues, and then returning. This
+ * call is serialized against other ldisc functions.
  */
 static void
 slip_close(struct tty_struct *tty)
index 85fae09..5d224b6 100644 (file)
@@ -55,6 +55,9 @@
  *                                  smc_phy_configure
  *                                - clean up (and fix stack overrun) in PHY
  *                                  MII read/write functions
+ *   09/15/04  Hayato Fujiwara    - Add m32r support.
+ *                                - Modify for SMP kernel; Change spin-locked
+ *                                  regions.
  */
 static const char version[] =
        "smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre <nico@cam.org>\n";
@@ -256,24 +259,18 @@ static void PRINT_PKT(u_char *buf, int length)
 
 /* this enables an interrupt in the interrupt mask register */
 #define SMC_ENABLE_INT(x) do {                                         \
-       unsigned long flags;                                            \
        unsigned char mask;                                             \
-       spin_lock_irqsave(&lp->lock, flags);                            \
        mask = SMC_GET_INT_MASK();                                      \
        mask |= (x);                                                    \
        SMC_SET_INT_MASK(mask);                                         \
-       spin_unlock_irqrestore(&lp->lock, flags);                       \
 } while (0)
 
 /* this disables an interrupt from the interrupt mask register */
 #define SMC_DISABLE_INT(x) do {                                                \
-       unsigned long flags;                                            \
        unsigned char mask;                                             \
-       spin_lock_irqsave(&lp->lock, flags);                            \
        mask = SMC_GET_INT_MASK();                                      \
        mask &= ~(x);                                                   \
        SMC_SET_INT_MASK(mask);                                         \
-       spin_unlock_irqrestore(&lp->lock, flags);                       \
 } while (0)
 
 /*
@@ -580,9 +577,12 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct smc_local *lp = netdev_priv(dev);
        unsigned long ioaddr = dev->base_addr;
        unsigned int numPages, poll_count, status, saved_bank;
+       unsigned long flags;
 
        DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
 
+       spin_lock_irqsave(&lp->lock, flags);
+
        BUG_ON(lp->saved_skb != NULL);
        lp->saved_skb = skb;
 
@@ -604,6 +604,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
                lp->stats.tx_errors++;
                lp->stats.tx_dropped++;
                dev_kfree_skb(skb);
+               spin_unlock_irqrestore(&lp->lock, flags);
                return 0;
        }
 
@@ -652,6 +653,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        SMC_SELECT_BANK(saved_bank);
+       spin_unlock_irqrestore(&lp->lock, flags);
        return 0;
 }
 
@@ -1166,6 +1168,8 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
 
+       spin_lock(&lp->lock);
+
        saved_bank = SMC_CURRENT_BANK();
        SMC_SELECT_BANK(2);
        saved_pointer = SMC_GET_PTR();
@@ -1189,8 +1193,6 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                if (!status)
                        break;
 
-               spin_lock(&lp->lock);
-
                if (status & IM_RCV_INT) {
                        DBG(3, "%s: RX irq\n", dev->name);
                        smc_rcv(dev);
@@ -1239,7 +1241,6 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name);
                }
 
-               spin_unlock(&lp->lock);
        } while (--timeout);
 
        /* restore register states */
@@ -1249,6 +1250,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout);
 
+       spin_unlock(&lp->lock);
        /*
         * We return IRQ_HANDLED unconditionally here even if there was
         * nothing to do.  There is a possibility that a packet might
@@ -1264,7 +1266,9 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static void smc_timeout(struct net_device *dev)
 {
        struct smc_local *lp = netdev_priv(dev);
+       unsigned long flags;
 
+       spin_lock_irqsave(&lp->lock, flags);
        DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
 
        smc_reset(dev);
@@ -1298,6 +1302,9 @@ static void smc_timeout(struct net_device *dev)
        }
        /* We can accept TX packets again */
        dev->trans_start = jiffies;
+
+       spin_unlock_irqrestore(&lp->lock, flags);
+
        netif_wake_queue(dev);
 }
 
@@ -1438,7 +1445,7 @@ smc_open(struct net_device *dev)
         * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
         */
        if (!is_valid_ether_addr(dev->dev_addr)) {
-               DBG(2, (KERN_DEBUG "smc_open: no valid ethernet hw addr\n"));
+               DBG(2, "smc_open: no valid ethernet hw addr\n");
                return -EINVAL;
        }
 
@@ -1878,7 +1885,9 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
        if (retval)
                goto err_out;
 
+#if !defined(__m32r__)
        set_irq_type(dev->irq, IRQT_RISING);
+#endif
 #ifdef SMC_USE_PXA_DMA
        {
                int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
@@ -2154,10 +2163,12 @@ static struct device_driver smc_driver = {
 static int __init smc_init(void)
 {
 #ifdef MODULE
+#ifdef CONFIG_ISA
        if (io == -1)
                printk(KERN_WARNING 
                        "%s: You shouldn't use auto-probing with insmod!\n",
                        CARDNAME);
+#endif
 #endif
 
        return driver_register(&smc_driver);
index 7679022..cf74b74 100644 (file)
@@ -160,6 +160,19 @@ SMC_outw(u16 val, unsigned long ioaddr, int reg)
 #define SMC_insw(a, r, p, l)   insw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)  outsw((a) + (r), p, l)
 
+#elif   defined(CONFIG_M32R)
+
+#define SMC_CAN_USE_8BIT       0
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      0
+
+#define SMC_inb(a, r)          inb((a) + (r) - 0xa0000000)
+#define SMC_inw(a, r)          inw((a) + (r) - 0xa0000000)
+#define SMC_outb(v, a, r)      outb(v, (a) + (r) - 0xa0000000)
+#define SMC_outw(v, a, r)      outw(v, (a) + (r) - 0xa0000000)
+#define SMC_insw(a, r, p, l)   insw((a) + (r) - 0xa0000000, p, l)
+#define SMC_outsw(a, r, p, l)  outsw((a) + (r) - 0xa0000000, p, l)
+
 #else
 
 #define SMC_CAN_USE_8BIT       1
@@ -809,9 +822,10 @@ static const char * chip_ids[ 16 ] =  {
        do {                                                            \
                char *__ptr = (p);                                      \
                int __len = (l);                                        \
-               if (__len >= 2 && (long)__ptr & 2) {                    \
+               if (__len >= 2 && (unsigned long)__ptr & 2) {           \
                        __len -= 2;                                     \
-                       SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\
+                       SMC_outw( *(u16 *)__ptr, ioaddr, DATA_REG );    \
+                       __ptr += 2;                                     \
                }                                                       \
                SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2);        \
                if (__len & 2) {                                        \
@@ -823,7 +837,7 @@ static const char * chip_ids[ 16 ] =  {
        do {                                                            \
                char *__ptr = (p);                                      \
                int __len = (l);                                        \
-               if ((long)__ptr & 2) {                                  \
+               if ((unsigned long)__ptr & 2) {                         \
                        /*                                              \
                         * We want 32bit alignment here.                \
                         * Since some buses perform a full 32bit        \
@@ -831,7 +845,7 @@ static const char * chip_ids[ 16 ] =  {
                         * SMC_inw() here.  Back both source (on chip   \
                         * and destination) pointers of 2 bytes.        \
                         */                                             \
-                       (long)__ptr &= ~2;                              \
+                       __ptr -= 2;                                     \
                        __len += 2;                                     \
                        SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC );  \
                }                                                       \
index ec05d1b..25d3502 100644 (file)
@@ -68,7 +68,7 @@ static struct bigmac *root_bigmac_dev;
 
 #define QEC_RESET_TRIES 200
 
-static int qec_global_reset(unsigned long gregs)
+static int qec_global_reset(void __iomem *gregs)
 {
        int tries = QEC_RESET_TRIES;
 
@@ -88,7 +88,7 @@ static int qec_global_reset(unsigned long gregs)
 
 static void qec_init(struct bigmac *bp)
 {
-       unsigned long gregs = bp->gregs;
+       void __iomem *gregs = bp->gregs;
        struct sbus_dev *qec_sdev = bp->qec_sdev;
        u8 bsizes = bp->bigmac_bursts;
        u32 regval;
@@ -117,7 +117,7 @@ static void qec_init(struct bigmac *bp)
 #define TX_RESET_TRIES     32
 #define RX_RESET_TRIES     32
 
-static void bigmac_tx_reset(unsigned long bregs)
+static void bigmac_tx_reset(void __iomem *bregs)
 {
        int tries = TX_RESET_TRIES;
 
@@ -137,7 +137,7 @@ static void bigmac_tx_reset(unsigned long bregs)
        }
 }
 
-static void bigmac_rx_reset(unsigned long bregs)
+static void bigmac_rx_reset(void __iomem *bregs)
 {
        int tries = RX_RESET_TRIES;
 
@@ -159,7 +159,7 @@ static void bigmac_stop(struct bigmac *bp)
        bigmac_rx_reset(bp->bregs);
 }
 
-static void bigmac_get_counters(struct bigmac *bp, unsigned long bregs)
+static void bigmac_get_counters(struct bigmac *bp, void __iomem *bregs)
 {
        struct net_device_stats *stats = &bp->enet_stats;
 
@@ -244,7 +244,7 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq)
 #define MGMT_CLKON  (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB|MGMT_PAL_DCLOCK)
 #define MGMT_CLKOFF (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB)
 
-static void idle_transceiver(unsigned long tregs)
+static void idle_transceiver(void __iomem *tregs)
 {
        int i = 20;
 
@@ -256,7 +256,7 @@ static void idle_transceiver(unsigned long tregs)
        }
 }
 
-static void write_tcvr_bit(struct bigmac *bp, unsigned long tregs, int bit)
+static void write_tcvr_bit(struct bigmac *bp, void __iomem *tregs, int bit)
 {
        if (bp->tcvr_type == internal) {
                bit = (bit & 1) << 3;
@@ -279,7 +279,7 @@ static void write_tcvr_bit(struct bigmac *bp, unsigned long tregs, int bit)
        }
 }
 
-static int read_tcvr_bit(struct bigmac *bp, unsigned long tregs)
+static int read_tcvr_bit(struct bigmac *bp, void __iomem *tregs)
 {
        int retval = 0;
 
@@ -302,7 +302,7 @@ static int read_tcvr_bit(struct bigmac *bp, unsigned long tregs)
        return retval;
 }
 
-static int read_tcvr_bit2(struct bigmac *bp, unsigned long tregs)
+static int read_tcvr_bit2(struct bigmac *bp, void __iomem *tregs)
 {
        int retval = 0;
 
@@ -325,7 +325,7 @@ static int read_tcvr_bit2(struct bigmac *bp, unsigned long tregs)
 }
 
 static void put_tcvr_byte(struct bigmac *bp,
-                         unsigned long tregs,
+                         void __iomem *tregs,
                          unsigned int byte)
 {
        int shift = 4;
@@ -336,7 +336,7 @@ static void put_tcvr_byte(struct bigmac *bp,
        } while (shift >= 0);
 }
 
-static void bigmac_tcvr_write(struct bigmac *bp, unsigned long tregs,
+static void bigmac_tcvr_write(struct bigmac *bp, void __iomem *tregs,
                              int reg, unsigned short val)
 {
        int shift;
@@ -376,7 +376,7 @@ static void bigmac_tcvr_write(struct bigmac *bp, unsigned long tregs,
 }
 
 static unsigned short bigmac_tcvr_read(struct bigmac *bp,
-                                      unsigned long tregs,
+                                      void __iomem *tregs,
                                       int reg)
 {
        unsigned short retval = 0;
@@ -444,7 +444,7 @@ static unsigned short bigmac_tcvr_read(struct bigmac *bp,
 
 static void bigmac_tcvr_init(struct bigmac *bp)
 {
-       unsigned long tregs = bp->tregs;
+       void __iomem *tregs = bp->tregs;
        u32 mpal;
 
        idle_transceiver(tregs);
@@ -482,7 +482,7 @@ static void bigmac_tcvr_init(struct bigmac *bp)
 
 static int bigmac_init(struct bigmac *, int);
 
-static int try_next_permutation(struct bigmac *bp, unsigned long tregs)
+static int try_next_permutation(struct bigmac *bp, void __iomem *tregs)
 {
        if (bp->sw_bmcr & BMCR_SPEED100) {
                int timeout;
@@ -518,7 +518,7 @@ static int try_next_permutation(struct bigmac *bp, unsigned long tregs)
 static void bigmac_timer(unsigned long data)
 {
        struct bigmac *bp = (struct bigmac *) data;
-       unsigned long tregs = bp->tregs;
+       void __iomem *tregs = bp->tregs;
        int restart_timer = 0;
 
        bp->timer_ticks++;
@@ -573,7 +573,7 @@ static void bigmac_timer(unsigned long data)
  */
 static void bigmac_begin_auto_negotiation(struct bigmac *bp)
 {
-       unsigned long tregs = bp->tregs;
+       void __iomem *tregs = bp->tregs;
        int timeout;
 
        /* Grab new software copies of PHY registers. */
@@ -612,9 +612,9 @@ static void bigmac_begin_auto_negotiation(struct bigmac *bp)
 
 static int bigmac_init(struct bigmac *bp, int from_irq)
 {
-       unsigned long gregs        = bp->gregs;
-       unsigned long cregs        = bp->creg;
-       unsigned long bregs        = bp->bregs;
+       void __iomem *gregs        = bp->gregs;
+       void __iomem *cregs        = bp->creg;
+       void __iomem *bregs        = bp->bregs;
        unsigned char *e = &bp->dev->dev_addr[0];
 
        /* Latch current counters into statistics. */
@@ -987,7 +987,7 @@ static struct net_device_stats *bigmac_get_stats(struct net_device *dev)
 static void bigmac_set_multicast(struct net_device *dev)
 {
        struct bigmac *bp = (struct bigmac *) dev->priv;
-       unsigned long bregs = bp->bregs;
+       void __iomem *bregs = bp->bregs;
        struct dev_mc_list *dmi = dev->mc_list;
        char *addrs;
        int i;
index b4c5309..5674003 100644 (file)
@@ -303,10 +303,10 @@ enum bigmac_timer_state {
 };
 
 struct bigmac {
-       unsigned long   gregs;  /* QEC Global Registers               */
-       unsigned long   creg;   /* QEC BigMAC Channel Registers       */
-       unsigned long   bregs;  /* BigMAC Registers                   */
-       unsigned long   tregs;  /* BigMAC Transceiver                 */
+       void __iomem    *gregs; /* QEC Global Registers               */
+       void __iomem    *creg;  /* QEC BigMAC Channel Registers       */
+       void __iomem    *bregs; /* BigMAC Registers                   */
+       void __iomem    *tregs; /* BigMAC Transceiver                 */
        struct bmac_init_block  *bmac_block;    /* RX and TX descriptors */
        __u32                    bblock_dvma;   /* RX and TX descriptors */
 
index f2784d2..34e9f95 100644 (file)
@@ -397,7 +397,7 @@ struct quattro;
 
 /* Happy happy, joy joy! */
 struct happy_meal {
-       unsigned long   gregs;                  /* Happy meal global registers       */
+       void __iomem    *gregs;                 /* Happy meal global registers       */
        struct hmeal_init_block  *happy_block;  /* RX and TX descriptors (CPU addr)  */
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
@@ -423,14 +423,14 @@ struct happy_meal {
        struct net_device_stats   net_stats;      /* Statistical counters              */
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
-       u32 (*read32)(unsigned long);
-       void (*write32)(unsigned long, u32);
+       u32 (*read32)(void __iomem *);
+       void (*write32)(void __iomem *, u32);
 #endif
 
-       unsigned long   etxregs;        /* External transmitter regs         */
-       unsigned long   erxregs;        /* External receiver regs            */
-       unsigned long   bigmacregs;     /* BIGMAC core regs                  */
-       unsigned long   tcvregs;        /* MIF transceiver regs              */
+       void __iomem    *etxregs;        /* External transmitter regs        */
+       void __iomem    *erxregs;        /* External receiver regs           */
+       void __iomem    *bigmacregs;     /* BIGMAC core regs                 */
+       void __iomem    *tcvregs;        /* MIF transceiver regs             */
 
        dma_addr_t                hblock_dvma;    /* DVMA visible address happy block  */
        unsigned int              happy_flags;    /* Driver state flags                */
index e803115..6e4bb57 100644 (file)
@@ -230,9 +230,9 @@ struct lance_init_block {
 ((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem][0])))))
 
 struct lance_private {
-       unsigned long   lregs;          /* Lance RAP/RDP regs.          */
-       unsigned long   dregs;          /* DMA controller regs.         */
-       volatile struct lance_init_block *init_block;
+       void __iomem    *lregs;         /* Lance RAP/RDP regs.          */
+       void __iomem    *dregs;         /* DMA controller regs.         */
+       struct lance_init_block *init_block;
     
        spinlock_t      lock;
 
@@ -270,7 +270,7 @@ struct lance_private {
 #define LANCE_REG_SIZE 0x04UL
 
 #define STOP_LANCE(__lp) \
-do {   unsigned long __base = (__lp)->lregs; \
+do {   void __iomem *__base = (__lp)->lregs; \
        sbus_writew(LE_CSR0,    __base + RAP); \
        sbus_writew(LE_C0_STOP, __base + RDP); \
 } while (0)
@@ -314,7 +314,7 @@ static void load_csrs(struct lance_private *lp)
 static void lance_init_ring_dvma(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib = lp->init_block;
+       struct lance_init_block *ib = lp->init_block;
        dma_addr_t aib = lp->init_block_dvma;
        __u32 leptr;
        int i;
@@ -371,7 +371,7 @@ static void lance_init_ring_dvma(struct net_device *dev)
 static void lance_init_ring_pio(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib = lp->init_block;
+       struct lance_init_block *ib = lp->init_block;
        u32 leptr;
        int i;
     
@@ -501,8 +501,8 @@ static int init_restart_lance(struct lance_private *lp)
 static void lance_rx_dvma(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib = lp->init_block;
-       volatile struct lance_rx_desc *rd;
+       struct lance_init_block *ib = lp->init_block;
+       struct lance_rx_desc *rd;
        u8 bits;
        int len, entry = lp->rx_new;
        struct sk_buff *skb;
@@ -564,14 +564,14 @@ static void lance_rx_dvma(struct net_device *dev)
 static void lance_tx_dvma(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib = lp->init_block;
+       struct lance_init_block *ib = lp->init_block;
        int i, j;
 
        spin_lock(&lp->lock);
 
        j = lp->tx_old;
        for (i = j; i != lp->tx_new; i = j) {
-               volatile struct lance_tx_desc *td = &ib->btx_ring [i];
+               struct lance_tx_desc *td = &ib->btx_ring [i];
                u8 bits = td->tmd1_bits;
 
                /* If we hit a packet not owned by us, stop */
@@ -641,12 +641,12 @@ out:
        spin_unlock(&lp->lock);
 }
 
-static void lance_piocopy_to_skb(struct sk_buff *skb, volatile void *piobuf, int len)
+static void lance_piocopy_to_skb(struct sk_buff *skb, void __iomem *piobuf, int len)
 {
        u16 *p16 = (u16 *) skb->data;
        u32 *p32;
        u8 *p8;
-       unsigned long pbuf = (unsigned long) piobuf;
+       void __iomem *pbuf = piobuf;
 
        /* We know here that both src and dest are on a 16bit boundary. */
        *p16++ = sbus_readw(pbuf);
@@ -674,8 +674,8 @@ static void lance_piocopy_to_skb(struct sk_buff *skb, volatile void *piobuf, int
 static void lance_rx_pio(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib = lp->init_block;
-       volatile struct lance_rx_desc *rd;
+       struct lance_init_block *ib = lp->init_block;
+       struct lance_rx_desc *rd;
        unsigned char bits;
        int len, entry;
        struct sk_buff *skb;
@@ -736,14 +736,14 @@ static void lance_rx_pio(struct net_device *dev)
 static void lance_tx_pio(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib = lp->init_block;
+       struct lance_init_block *ib = lp->init_block;
        int i, j;
 
        spin_lock(&lp->lock);
 
        j = lp->tx_old;
        for (i = j; i != lp->tx_new; i = j) {
-               volatile struct lance_tx_desc *td = &ib->btx_ring [i];
+               struct lance_tx_desc *td = &ib->btx_ring [i];
                u8 bits = sbus_readb(&td->tmd1_bits);
 
                /* If we hit a packet not owned by us, stop */
@@ -880,7 +880,7 @@ static irqreturn_t lance_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static void build_fake_packet(struct lance_private *lp)
 {
        struct net_device *dev = lp->dev;
-       volatile struct lance_init_block *ib = lp->init_block;
+       struct lance_init_block *ib = lp->init_block;
        u16 *packet;
        struct ethhdr *eth;
        int i, entry;
@@ -916,7 +916,7 @@ struct net_device *last_dev;
 static int lance_open(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib = lp->init_block;
+       struct lance_init_block *ib = lp->init_block;
        int status = 0;
 
        last_dev = dev;
@@ -1006,9 +1006,9 @@ static int lance_reset(struct net_device *dev)
        return status;
 }
 
-static void lance_piocopy_from_skb(volatile void *dest, unsigned char *src, int len)
+static void lance_piocopy_from_skb(void __iomem *dest, unsigned char *src, int len)
 {
-       unsigned long piobuf = (unsigned long) dest;
+       void __iomem *piobuf = dest;
        u32 *p32;
        u16 *p16;
        u8 *p8;
@@ -1064,11 +1064,11 @@ static void lance_piocopy_from_skb(volatile void *dest, unsigned char *src, int
                sbus_writeb(src[0], piobuf);
 }
 
-static void lance_piozero(volatile void *dest, int len)
+static void lance_piozero(void __iomem *dest, int len)
 {
-       unsigned long piobuf = (unsigned long) dest;
+       void __iomem *piobuf = dest;
 
-       if (piobuf & 1) {
+       if ((unsigned long)piobuf & 1) {
                sbus_writeb(0, piobuf);
                piobuf += 1;
                len -= 1;
@@ -1079,7 +1079,7 @@ static void lance_piozero(volatile void *dest, int len)
                sbus_writeb(0, piobuf);
                return;
        }
-       if (piobuf & 2) {
+       if ((unsigned long)piobuf & 2) {
                sbus_writew(0, piobuf);
                piobuf += 2;
                len -= 2;
@@ -1113,7 +1113,7 @@ static void lance_tx_timeout(struct net_device *dev)
 static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib = lp->init_block;
+       struct lance_init_block *ib = lp->init_block;
        int entry, skblen, len;
 
        skblen = skb->len;
@@ -1174,8 +1174,8 @@ static struct net_device_stats *lance_get_stats(struct net_device *dev)
 static void lance_load_multicast(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib = lp->init_block;
-       volatile u16 *mcast_table = (u16 *) &ib->filter;
+       struct lance_init_block *ib = lp->init_block;
+       u16 *mcast_table = (u16 *) &ib->filter;
        struct dev_mc_list *dmi = dev->mc_list;
        char *addrs;
        int i;
@@ -1224,7 +1224,7 @@ static void lance_load_multicast(struct net_device *dev)
 static void lance_set_multicast(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib = lp->init_block;
+       struct lance_init_block *ib = lp->init_block;
        u16 mode;
 
        if (!netif_running(dev))
@@ -1277,12 +1277,12 @@ static void lance_free_hwresources(struct lance_private *lp)
                sbus_iounmap(lp->lregs, LANCE_REG_SIZE);
        if (lp->init_block != NULL) {
                if (lp->pio_buffer) {
-                       sbus_iounmap((unsigned long)lp->init_block,
+                       sbus_iounmap(lp->init_block,
                                     sizeof(struct lance_init_block));
                } else {
                        sbus_free_consistent(lp->sdev,
                                             sizeof(struct lance_init_block),
-                                            (void *)lp->init_block,
+                                            lp->init_block,
                                             lp->init_block_dvma);
                }
        }
@@ -1349,7 +1349,7 @@ static int __init sparc_lance_init(struct sbus_dev *sdev,
 
        lp->sdev = sdev;
        if (lebuffer) {
-               lp->init_block = (volatile struct lance_init_block *)
+               lp->init_block =
                        sbus_ioremap(&lebuffer->resource[0], 0,
                                     sizeof(struct lance_init_block), "lebuffer");
                if (lp->init_block == NULL) {
@@ -1362,7 +1362,7 @@ static int __init sparc_lance_init(struct sbus_dev *sdev,
                lp->rx = lance_rx_pio;
                lp->tx = lance_tx_pio;
        } else {
-               lp->init_block = (volatile struct lance_init_block *)
+               lp->init_block =
                        sbus_alloc_consistent(sdev, sizeof(struct lance_init_block),
                                              &lp->init_block_dvma);
                if (lp->init_block == NULL ||
index 39a4b40..1ed3ff5 100644 (file)
@@ -49,7 +49,7 @@ static void qe_set_multicast(struct net_device *dev);
 
 #define QEC_RESET_TRIES 200
 
-static inline int qec_global_reset(unsigned long gregs)
+static inline int qec_global_reset(void __iomem *gregs)
 {
        int tries = QEC_RESET_TRIES;
 
@@ -73,8 +73,8 @@ static inline int qec_global_reset(unsigned long gregs)
 
 static inline int qe_stop(struct sunqe *qep)
 {
-       unsigned long cregs = qep->qcregs;
-       unsigned long mregs = qep->mregs;
+       void __iomem *cregs = qep->qcregs;
+       void __iomem *mregs = qep->mregs;
        int tries;
 
        /* Reset the MACE, then the QEC channel. */
@@ -130,9 +130,9 @@ static void qe_init_rings(struct sunqe *qep)
 static int qe_init(struct sunqe *qep, int from_irq)
 {
        struct sunqec *qecp = qep->parent;
-       unsigned long cregs = qep->qcregs;
-       unsigned long mregs = qep->mregs;
-       unsigned long gregs = qecp->gregs;
+       void __iomem *cregs = qep->qcregs;
+       void __iomem *mregs = qep->mregs;
+       void __iomem *gregs = qecp->gregs;
        unsigned char *e = &qep->dev->dev_addr[0];
        u32 tmp;
        int i;
@@ -699,7 +699,7 @@ static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 static u32 qe_get_link(struct net_device *dev)
 {
        struct sunqe *qep = dev->priv;
-       unsigned long mregs = qep->mregs;
+       void __iomem *mregs = qep->mregs;
        u8 phyconfig;
 
        spin_lock_irq(&qep->lock);
index b90ed5d..af34f36 100644 (file)
@@ -311,7 +311,7 @@ struct qe_init_block {
 struct sunqe;
 
 struct sunqec {
-       unsigned long           gregs;          /* QEC Global Registers         */
+       void __iomem            *gregs;         /* QEC Global Registers         */
        struct sunqe            *qes[4];        /* Each child MACE              */
        unsigned int            qec_bursts;     /* Support burst sizes          */
        struct sbus_dev         *qec_sdev;      /* QEC's SBUS device            */
@@ -331,8 +331,8 @@ struct sunqe_buffers {
 ((__u32)((unsigned long)(&(((struct sunqe_buffers *)0)->mem[elem][0]))))
 
 struct sunqe {
-       unsigned long                   qcregs;         /* QEC per-channel Registers   */
-       unsigned long                   mregs;          /* Per-channel MACE Registers  */
+       void __iomem                    *qcregs;                /* QEC per-channel Registers   */
+       void __iomem                    *mregs;         /* Per-channel MACE Registers  */
        struct qe_init_block            *qe_block;      /* RX and TX descriptors       */
        __u32                           qblock_dvma;    /* RX and TX descriptors       */
        spinlock_t                      lock;           /* Protects txfull state       */
index e209b79..2fc59c9 100644 (file)
@@ -251,8 +251,8 @@ struct olympic_private {
        u16 arb;      /* be16 */
        u16 asb;      /* be16 */
 
-       u8 *olympic_mmio;
-       u8 *olympic_lap;
+       u8 __iomem *olympic_mmio;
+       u8 __iomem *olympic_lap;
        struct pci_dev *pdev ; 
        char *olympic_card_name ; 
 
index f053d2a..57a6d29 100644 (file)
@@ -78,6 +78,8 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
+#include <linux/crc-ccitt.h>
+#include <linux/crc32.h>
 
 #include "via-velocity.h"
 
@@ -226,7 +228,10 @@ VELOCITY_PARAM(wol_opts, "Wake On Lan options");
 
 VELOCITY_PARAM(int_works, "Number of packets per interrupt services");
 
-static int velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int rx_copybreak = 200;
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
+
 static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info);
 static int velocity_get_pci_info(struct velocity_info *, struct pci_dev *pdev);
 static void velocity_print_info(struct velocity_info *vptr);
@@ -238,10 +243,8 @@ static void velocity_set_multi(struct net_device *dev);
 static struct net_device_stats *velocity_get_stats(struct net_device *dev);
 static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int velocity_close(struct net_device *dev);
-static int velocity_rx_srv(struct velocity_info *vptr, int status);
 static int velocity_receive_frame(struct velocity_info *, int idx);
 static int velocity_alloc_rx_buf(struct velocity_info *, int idx);
-static void velocity_init_registers(struct velocity_info *vptr, enum velocity_init_type type);
 static void velocity_free_rd_ring(struct velocity_info *vptr);
 static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *);
 static int velocity_soft_reset(struct velocity_info *vptr);
@@ -254,25 +257,40 @@ static void enable_flow_control_ability(struct velocity_info *vptr);
 static void enable_mii_autopoll(struct mac_regs * regs);
 static int velocity_mii_read(struct mac_regs *, u8 byIdx, u16 * pdata);
 static int velocity_mii_write(struct mac_regs *, u8 byMiiAddr, u16 data);
-static int velocity_set_wol(struct velocity_info *vptr);
-static void velocity_save_context(struct velocity_info *vptr, struct velocity_context *context);
-static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context);
 static u32 mii_check_media_mode(struct mac_regs * regs);
 static u32 check_connection_type(struct mac_regs * regs);
-static void velocity_init_cam_filter(struct velocity_info *vptr);
 static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status);
 
 #ifdef CONFIG_PM
+
 static int velocity_suspend(struct pci_dev *pdev, u32 state);
 static int velocity_resume(struct pci_dev *pdev);
 
 static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr);
 
 static struct notifier_block velocity_inetaddr_notifier = {
-      notifier_call:velocity_netdev_event,
+      .notifier_call   = velocity_netdev_event,
 };
 
-#endif                         /* CONFIG_PM */
+static spinlock_t velocity_dev_list_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(velocity_dev_list);
+
+static void velocity_register_notifier(void)
+{
+       register_inetaddr_notifier(&velocity_inetaddr_notifier);
+}
+
+static void velocity_unregister_notifier(void)
+{
+       unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
+}
+
+#else                          /* CONFIG_PM */
+
+#define velocity_register_notifier()   do {} while (0)
+#define velocity_unregister_notifier() do {} while (0)
+
+#endif                         /* !CONFIG_PM */
 
 /*
  *     Internal board variants. At the moment we have only one
@@ -289,8 +307,9 @@ static struct velocity_info_tbl chip_info_table[] = {
  */
 
 static struct pci_device_id velocity_id_table[] __devinitdata = {
-       {0x1106, 0x3119, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &chip_info_table[0]},
-       {0,}
+       {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) chip_info_table},
+       {0, }
 };
 
 MODULE_DEVICE_TABLE(pci, velocity_id_table);
@@ -326,12 +345,22 @@ static void __devexit velocity_remove1(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct velocity_info *vptr = dev->priv;
 
+#ifdef CONFIG_PM
+       unsigned long flags;
+
+       spin_lock_irqsave(&velocity_dev_list_lock, flags);
+       if (!list_empty(&velocity_dev_list))
+               list_del(&vptr->list);
+       spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
+#endif
        unregister_netdev(dev);
        iounmap(vptr->mac_regs);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
        free_netdev(dev);
+
+       velocity_nics--;
 }
 
 /**
@@ -435,7 +464,7 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
 {
        struct mac_regs * regs = vptr->mac_regs;
 
-       /* T urn on MCFG_PQEN, turn off MCFG_RTGOPT */
+       /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
        WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
        WORD_REG_BITS_ON(MCFG_VIDFR, &regs->MCFG);
 
@@ -477,13 +506,13 @@ static void velocity_rx_reset(struct velocity_info *vptr)
        struct mac_regs * regs = vptr->mac_regs;
        int i;
 
-       vptr->rd_used = vptr->rd_curr = 0;
+       vptr->rd_dirty = vptr->rd_filled = vptr->rd_curr = 0;
 
        /*
         *      Init state, all RD entries belong to the NIC
         */
        for (i = 0; i < vptr->options.numrx; ++i)
-               vptr->rd_ring[i].rdesc0.owner = cpu_to_le32(OWNED_BY_NIC);
+               vptr->rd_ring[i].rdesc0.owner = OWNED_BY_NIC;
 
        writew(vptr->options.numrx, &regs->RBRDU);
        writel(vptr->rd_pool_dma, &regs->RDBaseLo);
@@ -558,10 +587,15 @@ static void velocity_init_registers(struct velocity_info *vptr,
 
                writeb(WOLCFG_SAM | WOLCFG_SAB, &regs->WOLCFGSet);
                /*
-                *      Bback off algorithm use original IEEE standard
+                *      Back off algorithm use original IEEE standard
                 */
                BYTE_REG_BITS_SET(CFGB_OFSET, (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | CFGB_BAKOPT), &regs->CFGB);
 
+               /*
+                *      Init CAM filter
+                */
+               velocity_init_cam_filter(vptr);
+
                /*
                 *      Set packet filter: Receive directed and broadcast address
                 */
@@ -586,8 +620,6 @@ static void velocity_init_registers(struct velocity_info *vptr,
                        mac_tx_queue_run(regs, i);
                }
 
-               velocity_init_cam_filter(vptr);
-
                init_flow_control_register(vptr);
 
                writel(CR0_STOP, &regs->CR0Clr);
@@ -595,7 +627,6 @@ static void velocity_init_registers(struct velocity_info *vptr,
 
                mii_status = velocity_get_opt_media_mode(vptr);
                netif_stop_queue(vptr->dev);
-               mac_clear_isr(regs);
 
                mii_init(vptr, mii_status);
 
@@ -662,7 +693,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
        struct mac_regs * regs;
        int ret = -ENOMEM;
 
-       if (velocity_nics++ >= MAX_UNITS) {
+       if (velocity_nics >= MAX_UNITS) {
                printk(KERN_NOTICE VELOCITY_NAME ": already found %d NICs.\n", 
                                velocity_nics);
                return -ENODEV;
@@ -694,7 +725,6 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
 
        vptr->dev = dev;
 
-       dev->priv = vptr;
        dev->irq = pdev->irq;
 
        ret = pci_enable_device(pdev);
@@ -729,7 +759,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
                dev->dev_addr[i] = readb(&regs->PAR[i]);
 
 
-       velocity_get_options(&vptr->options, velocity_nics - 1, dev->name);
+       velocity_get_options(&vptr->options, velocity_nics, dev->name);
 
        /* 
         *      Mask out the options cannot be set to the chip
@@ -775,6 +805,16 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
        /* and leave the chip powered down */
        
        pci_set_power_state(pdev, 3);
+#ifdef CONFIG_PM
+       {
+               unsigned long flags;
+
+               spin_lock_irqsave(&velocity_dev_list_lock, flags);
+               list_add(&vptr->list, &velocity_dev_list);
+               spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
+       }
+#endif
+       velocity_nics++;
 out:
        return ret;
 
@@ -827,9 +867,8 @@ static void __devinit velocity_init_info(struct pci_dev *pdev, struct velocity_i
        vptr->io_size = info->io_size;
        vptr->num_txq = info->txqueue;
        vptr->multicast_limit = MCAM_SIZE;
-
        spin_lock_init(&vptr->lock);
-       spin_lock_init(&vptr->xmit_lock);
+       INIT_LIST_HEAD(&vptr->list);
 }
 
 /**
@@ -966,6 +1005,60 @@ static void velocity_free_rings(struct velocity_info *vptr)
        pci_free_consistent(vptr->pdev, size, vptr->tx_bufs, vptr->tx_bufs_dma);
 }
 
+static inline void velocity_give_many_rx_descs(struct velocity_info *vptr)
+{
+       struct mac_regs *regs = vptr->mac_regs;
+       int avail, dirty, unusable;
+
+       /*
+        * RD number must be equal to 4X per hardware spec
+        * (programming guide rev 1.20, p.13)
+        */
+       if (vptr->rd_filled < 4)
+               return;
+
+       wmb();
+
+       unusable = vptr->rd_filled & 0x0003;
+       dirty = vptr->rd_dirty - unusable;
+       for (avail = vptr->rd_filled & 0xfffc; avail; avail--) {
+               dirty = (dirty > 0) ? dirty - 1 : vptr->options.numrx - 1;
+               vptr->rd_ring[dirty].rdesc0.owner = OWNED_BY_NIC;
+       }
+
+       writew(vptr->rd_filled & 0xfffc, &regs->RBRDU);
+       vptr->rd_filled = unusable;
+}
+
+static int velocity_rx_refill(struct velocity_info *vptr)
+{
+       int dirty = vptr->rd_dirty, done = 0, ret = 0;
+
+       do {
+               struct rx_desc *rd = vptr->rd_ring + dirty;
+
+               /* Fine for an all zero Rx desc at init time as well */
+               if (rd->rdesc0.owner == OWNED_BY_NIC)
+                       break;
+
+               if (!vptr->rd_info[dirty].skb) {
+                       ret = velocity_alloc_rx_buf(vptr, dirty);
+                       if (ret < 0)
+                               break;
+               }
+               done++;
+               dirty = (dirty < vptr->options.numrx - 1) ? dirty + 1 : 0;      
+       } while (dirty != vptr->rd_curr);
+
+       if (done) {
+               vptr->rd_dirty = dirty;
+               vptr->rd_filled += done;
+               velocity_give_many_rx_descs(vptr);
+       }
+
+       return ret;
+}
+
 /**
  *     velocity_init_rd_ring   -       set up receive ring
  *     @vptr: velocity to configure
@@ -976,9 +1069,7 @@ static void velocity_free_rings(struct velocity_info *vptr)
 
 static int velocity_init_rd_ring(struct velocity_info *vptr)
 {
-       int i, ret = -ENOMEM;
-       struct rx_desc *rd;
-       struct velocity_rd_info *rd_info;
+       int ret = -ENOMEM;
        unsigned int rsize = sizeof(struct velocity_rd_info) * 
                                        vptr->options.numrx;
 
@@ -987,28 +1078,20 @@ static int velocity_init_rd_ring(struct velocity_info *vptr)
                goto out;
        memset(vptr->rd_info, 0, rsize);
 
-       /* Init the RD ring entries */
-       for (i = 0; i < vptr->options.numrx; i++) {
-               rd = &(vptr->rd_ring[i]);
-               rd_info = &(vptr->rd_info[i]);
+       vptr->rd_filled = vptr->rd_dirty = vptr->rd_curr = 0;
 
-               ret = velocity_alloc_rx_buf(vptr, i);
-               if (ret < 0) {
-                       VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
-                               "%s: failed to allocate RX buffer.\n", 
-                               vptr->dev->name);
-                       velocity_free_rd_ring(vptr);
-                       goto out;
-               }
-               rd->rdesc0.owner = OWNED_BY_NIC;
+       ret = velocity_rx_refill(vptr);
+       if (ret < 0) {
+               VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
+                       "%s: failed to allocate RX buffer.\n", vptr->dev->name);
+               velocity_free_rd_ring(vptr);
        }
-       vptr->rd_used = vptr->rd_curr = 0;
 out:
        return ret;
 }
 
 /**
- *     velocity_free_rd_ring   -       set up receive ring
+ *     velocity_free_rd_ring   -       free receive ring
  *     @vptr: velocity to clean up
  *
  *     Free the receive buffers for each ring slot and any
@@ -1025,7 +1108,7 @@ static void velocity_free_rd_ring(struct velocity_info *vptr)
        for (i = 0; i < vptr->options.numrx; i++) {
                struct velocity_rd_info *rd_info = &(vptr->rd_info[i]);
 
-               if (!rd_info->skb_dma)
+               if (!rd_info->skb)
                        continue;
                pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz,
                                 PCI_DMA_FROMDEVICE);
@@ -1073,8 +1156,10 @@ static int velocity_init_td_ring(struct velocity_info *vptr)
                for (i = 0; i < vptr->options.numtx; i++, curr += sizeof(struct tx_desc)) {
                        td = &(vptr->td_rings[j][i]);
                        td_info = &(vptr->td_infos[j][i]);
-                       td_info->buf = vptr->tx_bufs + (i + j) * PKT_BUF_SZ;
-                       td_info->buf_dma = vptr->tx_bufs_dma + (i + j) * PKT_BUF_SZ;
+                       td_info->buf = vptr->tx_bufs +
+                               (j * vptr->options.numtx + i) * PKT_BUF_SZ;
+                       td_info->buf_dma = vptr->tx_bufs_dma +
+                               (j * vptr->options.numtx + i) * PKT_BUF_SZ;
                }
                vptr->td_tail[j] = vptr->td_curr[j] = vptr->td_used[j] = 0;
        }
@@ -1146,40 +1231,27 @@ static void velocity_free_td_ring(struct velocity_info *vptr)
  
 static int velocity_rx_srv(struct velocity_info *vptr, int status)
 {
-       struct rx_desc *rd;
        struct net_device_stats *stats = &vptr->stats;
-       struct mac_regs * regs = vptr->mac_regs;
        int rd_curr = vptr->rd_curr;
        int works = 0;
 
-       while (1) {
-
-               rd = &(vptr->rd_ring[rd_curr]);
+       do {
+               struct rx_desc *rd = vptr->rd_ring + rd_curr;
 
-               if ((vptr->rd_info[rd_curr]).skb == NULL) {
-                       if (velocity_alloc_rx_buf(vptr, rd_curr) < 0)
-                               break;
-               }
-
-               if (works++ > 15)
+               if (!vptr->rd_info[rd_curr].skb)
                        break;
 
                if (rd->rdesc0.owner == OWNED_BY_NIC)
                        break;
 
+               rmb();
+
                /*
                 *      Don't drop CE or RL error frame although RXOK is off
-                *      FIXME: need to handle copybreak
                 */
                if ((rd->rdesc0.RSR & RSR_RXOK) || (!(rd->rdesc0.RSR & RSR_RXOK) && (rd->rdesc0.RSR & (RSR_CE | RSR_RL)))) {
-                       if (velocity_receive_frame(vptr, rd_curr) == 0) {
-                               if (velocity_alloc_rx_buf(vptr, rd_curr) < 0) {
-                                       VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not allocate rx buf\n", vptr->dev->name);
-                                       break;
-                               }
-                       } else {
+                       if (velocity_receive_frame(vptr, rd_curr) < 0)
                                stats->rx_dropped++;
-                       }
                } else {
                        if (rd->rdesc0.RSR & RSR_CRC)
                                stats->rx_crc_errors++;
@@ -1191,26 +1263,20 @@ static int velocity_rx_srv(struct velocity_info *vptr, int status)
 
                rd->inten = 1;
 
-               if (++vptr->rd_used >= 4) {
-                       int i, rd_prev = rd_curr;
-                       for (i = 0; i < 4; i++) {
-                               if (--rd_prev < 0)
-                                       rd_prev = vptr->options.numrx - 1;
-
-                               rd = &(vptr->rd_ring[rd_prev]);
-                               rd->rdesc0.owner = OWNED_BY_NIC;
-                       }
-                       writew(4, &(regs->RBRDU));
-                       vptr->rd_used -= 4;
-               }
-
                vptr->dev->last_rx = jiffies;
 
                rd_curr++;
                if (rd_curr >= vptr->options.numrx)
                        rd_curr = 0;
-       }
+       } while (++works <= 15);
+
        vptr->rd_curr = rd_curr;
+
+       if (works > 0 && velocity_rx_refill(vptr) < 0) {
+               VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
+                       "%s: rx buf allocation failure\n", vptr->dev->name);
+       }
+
        VAR_USED(stats);
        return works;
 }
@@ -1241,6 +1307,65 @@ static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb)
        }
 }
 
+/**
+ *     velocity_rx_copy        -       in place Rx copy for small packets
+ *     @rx_skb: network layer packet buffer candidate
+ *     @pkt_size: received data size
+ *     @rd: receive packet descriptor
+ *     @dev: network device
+ *
+ *     Replace the current skb that is scheduled for Rx processing by a
+ *     shorter, immediatly allocated skb, if the received packet is small
+ *     enough. This function returns a negative value if the received
+ *     packet is too big or if memory is exhausted.
+ */
+static inline int velocity_rx_copy(struct sk_buff **rx_skb, int pkt_size,
+                                  struct velocity_info *vptr)
+{
+       int ret = -1;
+
+       if (pkt_size < rx_copybreak) {
+               struct sk_buff *new_skb;
+
+               new_skb = dev_alloc_skb(pkt_size + 2);
+               if (new_skb) {
+                       new_skb->dev = vptr->dev;
+                       new_skb->ip_summed = rx_skb[0]->ip_summed;
+
+                       if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN)
+                               skb_reserve(new_skb, 2);
+
+                       memcpy(new_skb->data, rx_skb[0]->tail, pkt_size);
+                       *rx_skb = new_skb;
+                       ret = 0;
+               }
+               
+       }
+       return ret;
+}
+
+/**
+ *     velocity_iph_realign    -       IP header alignment
+ *     @vptr: velocity we are handling
+ *     @skb: network layer packet buffer
+ *     @pkt_size: received data size
+ *
+ *     Align IP header on a 2 bytes boundary. This behavior can be
+ *     configured by the user.
+ */
+static inline void velocity_iph_realign(struct velocity_info *vptr,
+                                       struct sk_buff *skb, int pkt_size)
+{
+       /* FIXME - memmove ? */
+       if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) {
+               int i;
+
+               for (i = pkt_size; i >= 0; i--)
+                       *(skb->data + i + 2) = *(skb->data + i);
+               skb_reserve(skb, 2);
+       }
+}
+
 /**
  *     velocity_receive_frame  -       received packet processor
  *     @vptr: velocity we are handling
@@ -1252,9 +1377,11 @@ static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb)
  
 static int velocity_receive_frame(struct velocity_info *vptr, int idx)
 {
+       void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int);
        struct net_device_stats *stats = &vptr->stats;
        struct velocity_rd_info *rd_info = &(vptr->rd_info[idx]);
        struct rx_desc *rd = &(vptr->rd_ring[idx]);
+       int pkt_len = rd->rdesc0.len;
        struct sk_buff *skb;
 
        if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) {
@@ -1269,22 +1396,8 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
        skb = rd_info->skb;
        skb->dev = vptr->dev;
 
-       pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz, 
-                                                       PCI_DMA_FROMDEVICE);
-       rd_info->skb_dma = (dma_addr_t) NULL;
-       rd_info->skb = NULL;
-
-       /* FIXME - memmove ? */
-       if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) {
-               int i;
-               for (i = rd->rdesc0.len + 4; i >= 0; i--)
-                       *(skb->data + i + 2) = *(skb->data + i);
-               skb->data += 2;
-               skb->tail += 2;
-       }
-
-       skb_put(skb, (rd->rdesc0.len - 4));
-       skb->protocol = eth_type_trans(skb, skb->dev);
+       pci_dma_sync_single_for_cpu(vptr->pdev, rd_info->skb_dma,
+                                   vptr->rx_buf_sz, PCI_DMA_FROMDEVICE);
 
        /*
         *      Drop frame not meeting IEEE 802.3
@@ -1297,13 +1410,23 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
                }
        }
 
+       pci_action = pci_dma_sync_single_for_device;
+
        velocity_rx_csum(rd, skb);
-       
-       /*
-        *      FIXME: need rx_copybreak handling
-        */
 
-       stats->rx_bytes += skb->len;
+       if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) {
+               velocity_iph_realign(vptr, skb, pkt_len);
+               pci_action = pci_unmap_single;
+               rd_info->skb = NULL;
+       }
+
+       pci_action(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz,
+                  PCI_DMA_FROMDEVICE);
+
+       skb_put(skb, pkt_len - 4);
+       skb->protocol = eth_type_trans(skb, skb->dev);  
+
+       stats->rx_bytes += pkt_len;
        netif_rx(skb);
 
        return 0;
@@ -1962,32 +2085,6 @@ static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs)
 }
 
 
-/**
- *     ether_crc       -       ethernet CRC function
- *
- *     Compute an ethernet CRC hash of the data block provided. This
- *     is not performance optimised but is not needed in performance
- *     critical code paths.
- *
- *     FIXME: could we use shared code here ?
- */
-static inline u32 ether_crc(int length, unsigned char *data)
-{
-       static unsigned const ethernet_polynomial = 0x04c11db7U;
-       
-       int crc = -1;
-
-       while (--length >= 0) {
-               unsigned char current_octet = *data++;
-               int bit;
-               for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
-                       crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
-               }
-       }
-       return crc;
-}
-
 /**
  *     velocity_set_multi      -       filter list change callback
  *     @dev: network device
@@ -2123,13 +2220,13 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  */
  
 static struct pci_driver velocity_driver = {
-      name:VELOCITY_NAME,
-      id_table:velocity_id_table,
-      probe:velocity_found1,
-      remove:velocity_remove1,
+      .name    = VELOCITY_NAME,
+      .id_table        = velocity_id_table,
+      .probe   = velocity_found1,
+      .remove  = __devexit_p(velocity_remove1),
 #ifdef CONFIG_PM
-      suspend:velocity_suspend,
-      resume:velocity_resume,
+      .suspend = velocity_suspend,
+      .resume  = velocity_resume,
 #endif
 };
 
@@ -2145,11 +2242,11 @@ static struct pci_driver velocity_driver = {
 static int __init velocity_init_module(void)
 {
        int ret;
-       ret = pci_module_init(&velocity_driver);
 
-#ifdef CONFIG_PM
-       register_inetaddr_notifier(&velocity_inetaddr_notifier);
-#endif
+       velocity_register_notifier();
+       ret = pci_module_init(&velocity_driver);
+       if (ret < 0)
+               velocity_unregister_notifier();
        return ret;
 }
 
@@ -2164,9 +2261,7 @@ static int __init velocity_init_module(void)
  
 static void __exit velocity_cleanup_module(void)
 {
-#ifdef CONFIG_PM
-       unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
-#endif
+       velocity_unregister_notifier();
        pci_unregister_driver(&velocity_driver);
 }
 
@@ -2992,172 +3087,6 @@ static void velocity_restore_context(struct velocity_info *vptr, struct velocity
 
 }
 
-static int velocity_suspend(struct pci_dev *pdev, u32 state)
-{
-       struct velocity_info *vptr = pci_get_drvdata(pdev);
-       unsigned long flags;
-       
-       if(!netif_running(vptr->dev))
-               return 0;
-               
-       netif_device_detach(vptr->dev);
-       
-       spin_lock_irqsave(&vptr->lock, flags);
-       pci_save_state(pdev, vptr->pci_state);
-#ifdef ETHTOOL_GWOL
-       if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
-               velocity_get_ip(vptr);
-               velocity_save_context(vptr, &vptr->context);
-               velocity_shutdown(vptr);
-               velocity_set_wol(vptr);
-               pci_enable_wake(pdev, 3, 1);
-               pci_set_power_state(pdev, 3);
-       } else {
-               velocity_save_context(vptr, &vptr->context);
-               velocity_shutdown(vptr);
-               pci_disable_device(pdev);
-               pci_set_power_state(pdev, state);
-       }
-#else
-       pci_set_power_state(pdev, state);
-#endif
-       spin_unlock_irqrestore(&vptr->lock, flags);
-       return 0;
-}
-
-static int velocity_resume(struct pci_dev *pdev)
-{
-       struct velocity_info *vptr = pci_get_drvdata(pdev);
-       unsigned long flags;
-       int i;
-       
-       if(!netif_running(vptr->dev))
-               return 0;
-               
-       pci_set_power_state(pdev, 0);
-       pci_enable_wake(pdev, 0, 0);
-       pci_restore_state(pdev, vptr->pci_state);
-
-       mac_wol_reset(vptr->mac_regs);
-
-       spin_lock_irqsave(&vptr->lock, flags);
-       velocity_restore_context(vptr, &vptr->context);
-       velocity_init_registers(vptr, VELOCITY_INIT_WOL);
-       mac_disable_int(vptr->mac_regs);
-
-       velocity_tx_srv(vptr, 0);
-
-       for (i = 0; i < vptr->num_txq; i++) {
-               if (vptr->td_used[i]) {
-                       mac_tx_queue_wake(vptr->mac_regs, i);
-               }
-       }
-
-       mac_enable_int(vptr->mac_regs);
-       spin_unlock_irqrestore(&vptr->lock, flags);
-       netif_device_attach(vptr->dev);
-
-       return 0;
-}
-
-static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
-{
-       struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
-       struct net_device *dev;
-       struct velocity_info *vptr;
-
-       if (ifa) {
-               dev = ifa->ifa_dev->dev;
-               vptr = dev->priv;
-               velocity_get_ip(vptr);
-       }
-       return NOTIFY_DONE;
-}
-#endif
-
-/*
- * Purpose: Functions to set WOL.
- */
-
-const static unsigned short crc16_tab[256] = {
-       0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
-       0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
-       0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
-       0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
-       0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
-       0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
-       0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
-       0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
-       0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
-       0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
-       0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
-       0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
-       0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
-       0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
-       0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
-       0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
-       0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
-       0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
-       0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
-       0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
-       0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
-       0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
-       0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
-       0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
-       0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
-       0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
-       0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
-       0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
-       0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
-       0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
-       0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
-       0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-};
-
-
-static u32 mask_pattern[2][4] = {
-       {0x00203000, 0x000003C0, 0x00000000, 0x0000000},        /* ARP          */
-       {0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff}         /* Magic Packet */ 
-};
-
-/**
- *     ether_crc16     -       compute ethernet CRC
- *     @len: buffer length
- *     @cp: buffer
- *     @crc16: initial CRC
- *
- *     Compute a CRC value for a block of data. 
- *     FIXME: can we use generic functions ?
- */
-static u16 ether_crc16(int len, u8 * cp, u16 crc16)
-{
-       while (len--)
-               crc16 = (crc16 >> 8) ^ crc16_tab[(crc16 ^ *cp++) & 0xff];
-       return (crc16);
-}
-
-/**
- *     bit_reverse             -       16bit reverse
- *     @data: 16bit data t reverse
- *
- *     Reverse the order of a 16bit value and return the reversed bits
- */
-static u16 bit_reverse(u16 data)
-{
-       u32 new = 0x00000000;
-       int ii;
-
-
-       for (ii = 0; ii < 16; ii++) {
-               new |= ((u32) (data & 1) << (31 - ii));
-               data >>= 1;
-       }
-
-       return (u16) (new >> 16);
-}
-
 /**
  *     wol_calc_crc            -       WOL CRC
  *     @pattern: data pattern
@@ -3166,7 +3095,7 @@ static u16 bit_reverse(u16 data)
  *     Compute the wake on lan crc hashes for the packet header
  *     we are interested in.
  */
+
 u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
 {
        u16 crc = 0xFFFF;
@@ -3186,12 +3115,12 @@ u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
                                continue;
                        }
                        mask >>= 1;
-                       crc = ether_crc16(1, &(pattern[i * 8 + j]), crc);
+                       crc = crc_ccitt(crc, &(pattern[i * 8 + j]), 1);
                }
        }
        /*      Finally, invert the result once to get the correct data */
        crc = ~crc;
-       return bit_reverse(crc);
+       return bitreverse(crc) >> 16;
 }
 
 /**
@@ -3203,13 +3132,18 @@ u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
  *
  *     FIXME: check static buffer is safe here
  */
+
 static int velocity_set_wol(struct velocity_info *vptr)
 {
        struct mac_regs * regs = vptr->mac_regs;
        static u8 buf[256];
        int i;
 
+       static u32 mask_pattern[2][4] = {
+               {0x00203000, 0x000003C0, 0x00000000, 0x0000000}, /* ARP */
+               {0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff}  /* Magic Packet */
+       };
+
        writew(0xFFFF, &regs->WOLCRClr);
        writeb(WOLCFG_SAB | WOLCFG_SAM, &regs->WOLCFGSet);
        writew(WOLCR_MAGIC_EN, &regs->WOLCRSet);
@@ -3236,7 +3170,8 @@ static int velocity_set_wol(struct velocity_info *vptr)
 
                memcpy(arp->ar_tip, vptr->ip_addr, 4);
 
-               crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf, (u8 *) & mask_pattern[0][0]);
+               crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf,
+                               (u8 *) & mask_pattern[0][0]);
 
                writew(crc, &regs->PatternCRC[0]);
                writew(WOLCR_ARP_EN, &regs->WOLCRSet);
@@ -3275,3 +3210,92 @@ static int velocity_set_wol(struct velocity_info *vptr)
        return 0;
 }
 
+static int velocity_suspend(struct pci_dev *pdev, u32 state)
+{
+       struct velocity_info *vptr = pci_get_drvdata(pdev);
+       unsigned long flags;
+
+       if(!netif_running(vptr->dev))
+               return 0;
+
+       netif_device_detach(vptr->dev);
+
+       spin_lock_irqsave(&vptr->lock, flags);
+       pci_save_state(pdev, vptr->pci_state);
+#ifdef ETHTOOL_GWOL
+       if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
+               velocity_get_ip(vptr);
+               velocity_save_context(vptr, &vptr->context);
+               velocity_shutdown(vptr);
+               velocity_set_wol(vptr);
+               pci_enable_wake(pdev, 3, 1);
+               pci_set_power_state(pdev, 3);
+       } else {
+               velocity_save_context(vptr, &vptr->context);
+               velocity_shutdown(vptr);
+               pci_disable_device(pdev);
+               pci_set_power_state(pdev, state);
+       }
+#else
+       pci_set_power_state(pdev, state);
+#endif
+       spin_unlock_irqrestore(&vptr->lock, flags);
+       return 0;
+}
+
+static int velocity_resume(struct pci_dev *pdev)
+{
+       struct velocity_info *vptr = pci_get_drvdata(pdev);
+       unsigned long flags;
+       int i;
+
+       if(!netif_running(vptr->dev))
+               return 0;
+
+       pci_set_power_state(pdev, 0);
+       pci_enable_wake(pdev, 0, 0);
+       pci_restore_state(pdev, vptr->pci_state);
+
+       mac_wol_reset(vptr->mac_regs);
+
+       spin_lock_irqsave(&vptr->lock, flags);
+       velocity_restore_context(vptr, &vptr->context);
+       velocity_init_registers(vptr, VELOCITY_INIT_WOL);
+       mac_disable_int(vptr->mac_regs);
+
+       velocity_tx_srv(vptr, 0);
+
+       for (i = 0; i < vptr->num_txq; i++) {
+               if (vptr->td_used[i]) {
+                       mac_tx_queue_wake(vptr->mac_regs, i);
+               }
+       }
+
+       mac_enable_int(vptr->mac_regs);
+       spin_unlock_irqrestore(&vptr->lock, flags);
+       netif_device_attach(vptr->dev);
+
+       return 0;
+}
+
+static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
+{
+       struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
+
+       if (ifa) {
+               struct net_device *dev = ifa->ifa_dev->dev;
+               struct velocity_info *vptr;
+               unsigned long flags;
+
+               spin_lock_irqsave(&velocity_dev_list_lock, flags);
+               list_for_each_entry(vptr, &velocity_dev_list, list) {
+                       if (vptr->dev == dev) {
+                               velocity_get_ip(vptr);
+                               break;
+                       }
+               }
+               spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
+       }
+       return NOTIFY_DONE;
+}
+#endif
index 2175b86..9a187de 100644 (file)
@@ -37,7 +37,6 @@
 #define OPTION_DEFAULT      { [0 ... MAX_UNITS-1] = -1}
 
 #define REV_ID_VT6110       (0)
-#define DEVICE_ID           (0x3119)
 
 #define BYTE_REG_BITS_ON(x,p)       do { writeb(readb((p))|(x),(p));} while (0)
 #define WORD_REG_BITS_ON(x,p)       do { writew(readw((p))|(x),(p));} while (0)
@@ -1320,7 +1319,7 @@ static inline void mac_set_cam_mask(struct mac_regs * regs, u8 * mask, enum velo
        /* disable CAMEN */
        writeb(0, &regs->CAMADDR);
 
-       /* Select CAM mask */
+       /* Select mar */
        BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
 }
 
@@ -1361,7 +1360,7 @@ static inline void mac_set_cam(struct mac_regs * regs, int idx, u8 *addr, enum v
 
        writeb(0, &regs->CAMADDR);
 
-       /* Select CAM mask */
+       /* Select mar */
        BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
 }
 
@@ -1402,7 +1401,7 @@ static inline void mac_get_cam(struct mac_regs * regs, int idx, u8 *addr, enum v
 
        writeb(0, &regs->CAMADDR);
 
-       /* Select CAM mask */
+       /* Select mar */
        BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
 }
 
@@ -1734,14 +1733,13 @@ struct velocity_opt {
 };
 
 struct velocity_info {
-       struct velocity_info *next;
-       struct velocity_info *prev;
+       struct list_head list;
 
        struct pci_dev *pdev;
        struct net_device *dev;
        struct net_device_stats stats;
 
-#if CONFIG_PM
+#ifdef CONFIG_PM
        u32 pci_state[16];
 #endif
 
@@ -1772,7 +1770,8 @@ struct velocity_info {
        struct velocity_td_info *td_infos[TX_QUEUE_NO];
 
        int rd_curr;
-       int rd_used;
+       int rd_dirty;
+       u32 rd_filled;
        struct rx_desc *rd_ring;
        struct velocity_rd_info *rd_info;       /* It's an array */
 
@@ -1793,7 +1792,6 @@ struct velocity_info {
        u8 mCAMmask[(MCAM_SIZE / 8)];
 
        spinlock_t lock;
-       spinlock_t xmit_lock;
 
        int wol_opts;
        u8 wol_passwd[6];
index cd1cd85..07bfe10 100644 (file)
@@ -186,7 +186,7 @@ static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble),
            reset_timer(struct net_device *dev);
 
 static u8 bps_to_speed_code(u32 bps);
-static u8 log2(u32 n);
+static u8 cycx_log2(u32 n);
 
 static unsigned dec_to_uint(u8 *str, int len);
 
@@ -263,7 +263,7 @@ int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf)
        else
                card->wandev.mtu = 64;
 
-       cfg.pktlen = log2(card->wandev.mtu);
+       cfg.pktlen = cycx_log2(card->wandev.mtu);
 
        if (conf->station == WANOPT_DTE) {
                cfg.locaddr = 3; /* DTE */
@@ -1513,7 +1513,7 @@ static u8 bps_to_speed_code(u32 bps)
 }
 
 /* log base 2 */
-static u8 log2(u32 n)
+static u8 cycx_log2(u32 n)
 {
        u8 log = 0;
 
index 058ff80..9dccd95 100644 (file)
@@ -64,7 +64,7 @@ void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3)
 #endif
 }
 
-inline void lmc_trace(struct net_device *dev, char *msg){
+void lmc_trace(struct net_device *dev, char *msg){
 #ifdef LMC_TRACE
     unsigned long j = jiffies + 3; /* Wait for 50 ms */
 
index e6af492..a4bfff8 100644 (file)
@@ -164,9 +164,9 @@ typedef     unsigned char   ucchar;         /* 8 bits, unsigned */
  * (required to support Alpha systems) *
  ***************************************/
 #ifdef __KERNEL__
-#define cpc_writeb(port,val)   {writeb((ucchar)(val),(ulong)(port)); mb();}
-#define cpc_writew(port,val)   {writew((ushort)(val),(ulong)(port)); mb();}
-#define cpc_writel(port,val)   {writel((uclong)(val),(ulong)(port)); mb();}
+#define cpc_writeb(port,val)   {writeb((ucchar)(val),(port)); mb();}
+#define cpc_writew(port,val)   {writew((ushort)(val),(port)); mb();}
+#define cpc_writel(port,val)   {writel((uclong)(val),(port)); mb();}
 
 #define cpc_readb(port)                readb(port)
 #define cpc_readw(port)                readw(port)
@@ -358,17 +358,17 @@ typedef struct pc300hw {
        uclong iophys;          /* PLX registers I/O base */
        uclong iosize;          /* PLX registers I/O size */
        uclong plxphys;         /* PLX registers MMIO base (physical) */
-       uclong plxbase;         /* PLX registers MMIO base (virtual) */
+       void __iomem * plxbase; /* PLX registers MMIO base (virtual) */
        uclong plxsize;         /* PLX registers MMIO size */
        uclong scaphys;         /* SCA registers MMIO base (physical) */
-       uclong scabase;         /* SCA registers MMIO base (virtual) */
+       void __iomem * scabase; /* SCA registers MMIO base (virtual) */
        uclong scasize;         /* SCA registers MMIO size */
        uclong ramphys;         /* On-board RAM MMIO base (physical) */
-       uclong rambase;         /* On-board RAM MMIO base (virtual) */
+       void __iomem * rambase; /* On-board RAM MMIO base (virtual) */
        uclong alloc_ramsize;   /* RAM MMIO size allocated by the PCI bridge */
        uclong ramsize;         /* On-board RAM MMIO size */
        uclong falcphys;        /* FALC registers MMIO base (physical) */
-       uclong falcbase;        /* FALC registers MMIO base (virtual) */
+       void __iomem * falcbase;/* FALC registers MMIO base (virtual) */
        uclong falcsize;        /* FALC registers MMIO size */
 } pc300hw_t;
 
index 29b8268..7a972ca 100644 (file)
@@ -307,7 +307,7 @@ static void tx_dma_buf_pt_init(pc300_t * card, int ch)
 {
        int i;
        int ch_factor = ch * N_DMA_TX_BUF;
-       volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
                                       + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
        for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) {
@@ -322,7 +322,7 @@ static void tx_dma_buf_init(pc300_t * card, int ch)
 {
        int i;
        int ch_factor = ch * N_DMA_TX_BUF;
-       volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
                               + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
        for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) {
@@ -337,7 +337,7 @@ static void rx_dma_buf_pt_init(pc300_t * card, int ch)
 {
        int i;
        int ch_factor = ch * N_DMA_RX_BUF;
-       volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
                                       + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
        for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) {
@@ -352,7 +352,7 @@ static void rx_dma_buf_init(pc300_t * card, int ch)
 {
        int i;
        int ch_factor = ch * N_DMA_RX_BUF;
-       volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
                                       + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
        for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) {
@@ -365,7 +365,7 @@ static void rx_dma_buf_init(pc300_t * card, int ch)
 
 static void tx_dma_buf_check(pc300_t * card, int ch)
 {
-       volatile pcsca_bd_t *ptdescr;
+       volatile pcsca_bd_t __iomem *ptdescr;
        int i;
        ucshort first_bd = card->chan[ch].tx_first_bd;
        ucshort next_bd = card->chan[ch].tx_next_bd;
@@ -374,10 +374,10 @@ static void tx_dma_buf_check(pc300_t * card, int ch)
               first_bd, TX_BD_ADDR(ch, first_bd),
               next_bd, TX_BD_ADDR(ch, next_bd));
        for (i = first_bd,
-            ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, first_bd));
+            ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, first_bd));
             i != ((next_bd + 1) & (N_DMA_TX_BUF - 1));
             i = (i + 1) & (N_DMA_TX_BUF - 1), 
-                ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, i))) {
+                ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i))) {
                printk("\n CH%d TX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d",
                       ch, i, (uclong) cpc_readl(&ptdescr->next),
                       (uclong) cpc_readl(&ptdescr->ptbuf),
@@ -390,7 +390,7 @@ static void tx_dma_buf_check(pc300_t * card, int ch)
 /* Show all TX buffer descriptors */
 static void tx1_dma_buf_check(pc300_t * card, int ch)
 {
-       volatile pcsca_bd_t *ptdescr;
+       volatile pcsca_bd_t __iomem *ptdescr;
        int i;
        ucshort first_bd = card->chan[ch].tx_first_bd;
        ucshort next_bd = card->chan[ch].tx_next_bd;
@@ -404,7 +404,7 @@ static void tx1_dma_buf_check(pc300_t * card, int ch)
               (uclong) cpc_readl(scabase + DTX_REG(CDAL, ch)),
               (uclong) cpc_readl(scabase + DTX_REG(EDAL, ch)));
        for (i = 0; i < N_DMA_TX_BUF; i++) {
-               ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, i));
+               ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i));
                printk("\n CH%d TX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d",
                       ch, i, (uclong) cpc_readl(&ptdescr->next),
                       (uclong) cpc_readl(&ptdescr->ptbuf),
@@ -416,7 +416,7 @@ static void tx1_dma_buf_check(pc300_t * card, int ch)
                         
 static void rx_dma_buf_check(pc300_t * card, int ch)
 {
-       volatile pcsca_bd_t *ptdescr;
+       volatile pcsca_bd_t __iomem *ptdescr;
        int i;
        ucshort first_bd = card->chan[ch].rx_first_bd;
        ucshort last_bd = card->chan[ch].rx_last_bd;
@@ -424,7 +424,7 @@ static void rx_dma_buf_check(pc300_t * card, int ch)
 
        ch_factor = ch * N_DMA_RX_BUF;
        printk("#CH%d: f_bd = %d, l_bd = %d\n", ch, first_bd, last_bd);
-       for (i = 0, ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+       for (i = 0, ptdescr = (card->hw.rambase +
                                              DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
             i < N_DMA_RX_BUF; i++, ptdescr++) {
                if (cpc_readb(&ptdescr->status) & DST_OSB)
@@ -439,12 +439,12 @@ static void rx_dma_buf_check(pc300_t * card, int ch)
 
 int dma_get_rx_frame_size(pc300_t * card, int ch)
 {
-       volatile pcsca_bd_t *ptdescr;
+       volatile pcsca_bd_t __iomem *ptdescr;
        ucshort first_bd = card->chan[ch].rx_first_bd;
        int rcvd = 0;
        volatile ucchar status;
 
-       ptdescr = (pcsca_bd_t *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd));
+       ptdescr = (card->hw.rambase + RX_BD_ADDR(ch, first_bd));
        while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
                rcvd += cpc_readw(&ptdescr->len);
                first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1);
@@ -453,7 +453,7 @@ int dma_get_rx_frame_size(pc300_t * card, int ch)
                        * (dma_buf_read will clean the buffer descriptors in this case). */
                        return (rcvd);
                }
-               ptdescr = (pcsca_bd_t *)(card->hw.rambase + cpc_readl(&ptdescr->next));
+               ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
        }
        return (-1);
 }
@@ -465,7 +465,7 @@ int dma_get_rx_frame_size(pc300_t * card, int ch)
 int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
 {
        int i, nchar;
-       volatile pcsca_bd_t *ptdescr;
+       volatile pcsca_bd_t __iomem *ptdescr;
        int tosend = len;
        ucchar nbuf = ((len - 1) / BD_DEF_LEN) + 1;
 
@@ -474,11 +474,11 @@ int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
        }
 
        for (i = 0; i < nbuf; i++) {
-               ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+               ptdescr = (card->hw.rambase +
                                          TX_BD_ADDR(ch, card->chan[ch].tx_next_bd));
                nchar = cpc_min(BD_DEF_LEN, tosend);
                if (cpc_readb(&ptdescr->status) & DST_OSB) {
-                       memcpy_toio((void *)(card->hw.rambase + cpc_readl(&ptdescr->ptbuf)),
+                       memcpy_toio((card->hw.rambase + cpc_readl(&ptdescr->ptbuf)),
                                    &ptdata[len - tosend], nchar);
                        cpc_writew(&ptdescr->len, nchar);
                        card->chan[ch].nfree_tx_bd--;
@@ -507,11 +507,11 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
 {
        int nchar;
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       volatile pcsca_bd_t *ptdescr;
+       volatile pcsca_bd_t __iomem *ptdescr;
        int rcvd = 0;
        volatile ucchar status;
 
-       ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+       ptdescr = (card->hw.rambase +
                                  RX_BD_ADDR(ch, chan->rx_first_bd));
        while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
                nchar = cpc_readw(&ptdescr->len);
@@ -527,7 +527,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
                                chan->rx_first_bd = (chan->rx_first_bd+1) & (N_DMA_RX_BUF-1);
                                if (status & DST_EOM)
                                        break;
-                               ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+                               ptdescr = (card->hw.rambase +
                                                          cpc_readl(&ptdescr->next));
                                status = cpc_readb(&ptdescr->status);
                        }
@@ -536,7 +536,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
                if (nchar != 0) {
                        if (skb) {
                                memcpy_fromio(skb_put(skb, nchar),
-                                (void *)(card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar);
+                                (card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar);
                        }
                        rcvd += nchar;
                }
@@ -547,7 +547,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
                if (status & DST_EOM)
                        break;
 
-               ptdescr = (pcsca_bd_t *) (card->hw.rambase + cpc_readl(&ptdescr->next));
+               ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
        }
 
        if (rcvd != 0) {
@@ -562,7 +562,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
 
 void tx_dma_stop(pc300_t * card, int ch)
 {
-       uclong scabase = card->hw.scabase;
+       void __iomem *scabase = card->hw.scabase;
        ucchar drr_ena_bit = 1 << (5 + 2 * ch);
        ucchar drr_rst_bit = 1 << (1 + 2 * ch);
 
@@ -573,7 +573,7 @@ void tx_dma_stop(pc300_t * card, int ch)
 
 void rx_dma_stop(pc300_t * card, int ch)
 {
-       uclong scabase = card->hw.scabase;
+       void __iomem *scabase = card->hw.scabase;
        ucchar drr_ena_bit = 1 << (4 + 2 * ch);
        ucchar drr_rst_bit = 1 << (2 * ch);
 
@@ -584,7 +584,7 @@ void rx_dma_stop(pc300_t * card, int ch)
 
 void rx_dma_start(pc300_t * card, int ch)
 {
-       uclong scabase = card->hw.scabase;
+       void __iomem *scabase = card->hw.scabase;
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        
        /* Start DMA */
@@ -609,7 +609,7 @@ void rx_dma_start(pc300_t * card, int ch)
 /*************************/
 void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
 {
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
        unsigned long i = 0;
 
        while (cpc_readb(falcbase + F_REG(SIS, ch)) & SIS_CEC) {
@@ -627,7 +627,7 @@ void falc_intr_enable(pc300_t * card, int ch)
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        /* Interrupt pins are open-drain */
        cpc_writeb(falcbase + F_REG(IPC, ch),
@@ -674,7 +674,7 @@ void falc_intr_enable(pc300_t * card, int ch)
 
 void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
 {
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
        ucchar tshf = card->chan[ch].falc.offset;
 
        cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch),
@@ -690,7 +690,7 @@ void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
 
 void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
 {
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
        ucchar tshf = card->chan[ch].falc.offset;
 
        cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch),
@@ -708,7 +708,7 @@ void falc_close_all_timeslots(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        cpc_writeb(falcbase + F_REG(ICB1, ch), 0xff);
        cpc_writeb(falcbase + F_REG(TTR1, ch), 0);
@@ -730,7 +730,7 @@ void falc_open_all_timeslots(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        cpc_writeb(falcbase + F_REG(ICB1, ch), 0);
        if (conf->fr_mode == PC300_FR_UNFRAMED) {
@@ -811,7 +811,7 @@ void falc_init_t1(pc300_t * card, int ch)
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
        ucchar dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0);
 
        /* Switch to T1 mode (PCM 24) */
@@ -980,7 +980,7 @@ void falc_init_e1(pc300_t * card, int ch)
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
        ucchar dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0);
 
        /* Switch to E1 mode (PCM 30) */
@@ -1157,7 +1157,7 @@ void falc_init_e1(pc300_t * card, int ch)
 
 void falc_init_hdlc(pc300_t * card, int ch)
 {
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 
@@ -1186,7 +1186,7 @@ void te_config(pc300_t * card, int ch)
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
        ucchar dummy;
        unsigned long flags;
 
@@ -1246,7 +1246,7 @@ void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        /* Verify LOS */
        if (frs0 & FRS0_LOS) {
@@ -1402,7 +1402,7 @@ void falc_update_stats(pc300_t * card, int ch)
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
        ucshort counter;
 
        counter = cpc_readb(falcbase + F_REG(FECL, ch));
@@ -1455,7 +1455,7 @@ void falc_remote_loop(pc300_t * card, int ch, int loop_on)
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        if (loop_on) {
                // EVENT_FALC_ABNORMAL
@@ -1499,7 +1499,7 @@ void falc_local_loop(pc300_t * card, int ch, int loop_on)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        if (loop_on) {
                cpc_writeb(falcbase + F_REG(LIM0, ch),
@@ -1527,7 +1527,7 @@ void falc_payload_loop(pc300_t * card, int ch, int loop_on)
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        if (loop_on) {
                // EVENT_FALC_ABNORMAL
@@ -1580,7 +1580,7 @@ void turn_off_xlu(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        if (conf->media == IF_IFACE_T1) {
                cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1601,7 +1601,7 @@ void turn_off_xld(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        if (conf->media == IF_IFACE_T1) {
                cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1624,7 +1624,7 @@ void falc_generate_loop_up_code(pc300_t * card, int ch)
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        if (conf->media == IF_IFACE_T1) {
                cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1657,7 +1657,7 @@ void falc_generate_loop_down_code(pc300_t * card, int ch)
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        if (conf->media == IF_IFACE_T1) {
                cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1687,7 +1687,7 @@ void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        if (activate) {
                pfalc->prbs = 1;
@@ -1973,11 +1973,11 @@ static void sca_tx_intr(pc300dev_t *dev)
        pc300ch_t *chan = (pc300ch_t *)dev->chan; 
        pc300_t *card = (pc300_t *)chan->card; 
        int ch = chan->channel; 
-       volatile pcsca_bd_t * ptdescr; 
+       volatile pcsca_bd_t __iomem * ptdescr; 
        struct net_device_stats *stats = hdlc_stats(dev->dev);
 
     /* Clean up descriptors from previous transmission */
-       ptdescr = (pcsca_bd_t *)(card->hw.rambase +
+       ptdescr = (card->hw.rambase +
                                                TX_BD_ADDR(ch,chan->tx_first_bd));
        while ((cpc_readl(card->hw.scabase + DTX_REG(CDAL,ch)) != 
                                                        TX_BD_ADDR(ch,chan->tx_first_bd)) && 
@@ -1988,8 +1988,7 @@ static void sca_tx_intr(pc300dev_t *dev)
                cpc_writew(&ptdescr->len, 0);
                chan->nfree_tx_bd++;
                chan->tx_first_bd = (chan->tx_first_bd + 1) & (N_DMA_TX_BUF - 1);
-               ptdescr = (pcsca_bd_t *)(card->hw.rambase +
-                                               TX_BD_ADDR(ch,chan->tx_first_bd));
+               ptdescr = (card->hw.rambase + TX_BD_ADDR(ch,chan->tx_first_bd));
     }
 
 #ifdef CONFIG_PC300_MLPPP
@@ -2006,7 +2005,7 @@ static void sca_tx_intr(pc300dev_t *dev)
 
 static void sca_intr(pc300_t * card)
 {
-       uclong scabase = card->hw.scabase;
+       void __iomem *scabase = card->hw.scabase;
        volatile uclong status;
        int ch;
        int intr_count = 0;
@@ -2187,7 +2186,7 @@ static void falc_t1_loop_detection(pc300_t * card, int ch, ucchar frs1)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&
            !pfalc->loop_gen) {
@@ -2212,7 +2211,7 @@ static void falc_e1_loop_detection(pc300_t * card, int ch, ucchar rsp)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
 
        if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&
            !pfalc->loop_gen) {
@@ -2237,7 +2236,7 @@ static void falc_t1_intr(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
        ucchar isr0, isr3, gis;
        ucchar dummy;
 
@@ -2284,7 +2283,7 @@ static void falc_e1_intr(pc300_t * card, int ch)
 {
        pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
        falc_t *pfalc = (falc_t *) & chan->falc;
-       uclong falcbase = card->hw.falcbase;
+       void __iomem *falcbase = card->hw.falcbase;
        ucchar isr1, isr2, isr3, gis, rsp;
        ucchar dummy;
 
@@ -2408,7 +2407,7 @@ static irqreturn_t cpc_intr(int irq, void *dev_id, struct pt_regs *regs)
 void cpc_sca_status(pc300_t * card, int ch)
 {
        ucchar ilar;
-       uclong scabase = card->hw.scabase;
+       void __iomem *scabase = card->hw.scabase;
        uclong flags;
 
        tx_dma_buf_check(card, ch);
@@ -2544,7 +2543,7 @@ int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        int ch = chan->channel;
        void __user *arg = ifr->ifr_data;
        struct if_settings *settings = &ifr->ifr_settings;
-       uclong scabase = card->hw.scabase;
+       void __iomem *scabase = card->hw.scabase;
 
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
@@ -2863,8 +2862,8 @@ int ch_config(pc300dev_t * d)
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
        pc300_t *card = (pc300_t *) chan->card;
-       uclong scabase = card->hw.scabase;
-       uclong plxbase = card->hw.plxbase;
+       void __iomem *scabase = card->hw.scabase;
+       void __iomem *plxbase = card->hw.plxbase;
        int ch = chan->channel;
        uclong clkrate = chan->conf.phys_settings.clock_rate;
        uclong clktype = chan->conf.phys_settings.clock_type;
@@ -3010,7 +3009,7 @@ int rx_config(pc300dev_t * d)
 {
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300_t *card = (pc300_t *) chan->card;
-       uclong scabase = card->hw.scabase;
+       void __iomem *scabase = card->hw.scabase;
        int ch = chan->channel;
 
        cpc_writeb(scabase + DSR_RX(ch), 0);
@@ -3041,7 +3040,7 @@ int tx_config(pc300dev_t * d)
 {
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300_t *card = (pc300_t *) chan->card;
-       uclong scabase = card->hw.scabase;
+       void __iomem *scabase = card->hw.scabase;
        int ch = chan->channel;
 
        cpc_writeb(scabase + DSR_TX(ch), 0);
@@ -3105,7 +3104,7 @@ void cpc_opench(pc300dev_t * d)
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300_t *card = (pc300_t *) chan->card;
        int ch = chan->channel;
-       uclong scabase = card->hw.scabase;
+       void __iomem *scabase = card->hw.scabase;
 
        ch_config(d);
 
@@ -3211,7 +3210,7 @@ static uclong detect_ram(pc300_t * card)
 {
        uclong i;
        ucchar data;
-       uclong rambase = card->hw.rambase;
+       void __iomem *rambase = card->hw.rambase;
 
        card->hw.ramsize = PC300_RAMSIZE;
        /* Let's find out how much RAM is present on this board */
@@ -3227,7 +3226,7 @@ static uclong detect_ram(pc300_t * card)
 
 static void plx_init(pc300_t * card)
 {
-       struct RUNTIME_9050 *plx_ctl = (struct RUNTIME_9050 *) card->hw.plxbase;
+       struct RUNTIME_9050 __iomem *plx_ctl = card->hw.plxbase;
 
        /* Reset PLX */
        cpc_writel(&plx_ctl->init_ctrl,
@@ -3532,10 +3531,9 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if ((err = pci_enable_device(pdev)) != 0)
                goto err_release_sca;
 
-       card->hw.plxbase = (uclong) ioremap(card->hw.plxphys, card->hw.plxsize);
-       card->hw.rambase = (uclong) ioremap(card->hw.ramphys,
-                                           card->hw.alloc_ramsize);
-       card->hw.scabase = (uclong) ioremap(card->hw.scaphys, card->hw.scasize);
+       card->hw.plxbase = ioremap(card->hw.plxphys, card->hw.plxsize);
+       card->hw.rambase = ioremap(card->hw.ramphys, card->hw.alloc_ramsize);
+       card->hw.scabase = ioremap(card->hw.scaphys, card->hw.scasize);
        switch (device_id) {
                case PCI_DEVICE_ID_PC300_TE_1:
                case PCI_DEVICE_ID_PC300_TE_2:
@@ -3543,14 +3541,13 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                case PCI_DEVICE_ID_PC300_TE_M_2:
                        request_mem_region(card->hw.falcphys, card->hw.falcsize,
                                           "FALC Registers");
-                       card->hw.falcbase = (uclong) ioremap(card->hw.falcphys,
-                                                            card->hw.falcsize);
+                       card->hw.falcbase = ioremap(card->hw.falcphys, card->hw.falcsize);
                        break;
 
                case PCI_DEVICE_ID_PC300_RX_1:
                case PCI_DEVICE_ID_PC300_RX_2:
                default:
-                       card->hw.falcbase = 0;
+                       card->hw.falcbase = NULL;
                        break;
        }
 
@@ -3616,11 +3613,11 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        return 0;
 
 err_io_unmap:
-       iounmap((void *) card->hw.plxbase);
-       iounmap((void *) card->hw.scabase);
-       iounmap((void *) card->hw.rambase);
+       iounmap(card->hw.plxbase);
+       iounmap(card->hw.scabase);
+       iounmap(card->hw.rambase);
        if (card->hw.type == PC300_TE) {
-               iounmap((void *) card->hw.falcbase);
+               iounmap(card->hw.falcbase);
                release_mem_region(card->hw.falcphys, card->hw.falcsize);
        }
 err_release_sca:
@@ -3649,15 +3646,15 @@ static void __devexit cpc_remove_one(struct pci_dev *pdev)
                for (i = 0; i < card->hw.nchan; i++) {
                        unregister_hdlc_device(card->chan[i].d.dev);
                }
-               iounmap((void *) card->hw.plxbase);
-               iounmap((void *) card->hw.scabase);
-               iounmap((void *) card->hw.rambase);
+               iounmap(card->hw.plxbase);
+               iounmap(card->hw.scabase);
+               iounmap(card->hw.rambase);
                release_mem_region(card->hw.plxphys, card->hw.plxsize);
                release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize);
                release_mem_region(card->hw.scaphys, card->hw.scasize);
                release_region(card->hw.iophys, card->hw.iosize);
                if (card->hw.type == PC300_TE) {
-                       iounmap((void *) card->hw.falcbase);
+                       iounmap(card->hw.falcbase);
                        release_mem_region(card->hw.falcphys, card->hw.falcsize);
                }
                for (i = 0; i < card->hw.nchan; i++)
index b00fb78..e66c250 100644 (file)
@@ -3628,11 +3628,7 @@ static void tty_poll_work (void* data)
        if ((tty=card->tty)==NULL)
                return;
        
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup){
-               (tty->ldisc.write_wakeup)(tty);
-       }
-       wake_up_interruptible(&tty->write_wait);
+       tty_wakeup(tty);
 #if defined(SERIAL_HAVE_POLL_WAIT)
        wake_up_interruptible(&tty->poll_wait);
 #endif 
@@ -3857,6 +3853,7 @@ static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len)
        char fp=0;
        struct tty_struct *tty;
        int i;
+       struct tty_ldisc *ld;
        
        if (!card->tty_open){
                dbg_printk(KERN_INFO "%s: TTY not open during receive\n",
@@ -3944,8 +3941,11 @@ static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len)
                        len -= offset;
                }
                sdla_peek(&card->hw, addr, card->tty_rx+offset, len);
-               if (tty->ldisc.receive_buf){
-                       tty->ldisc.receive_buf(tty,card->tty_rx,&fp,olen);
+               ld = tty_ldisc_ref(tty);
+               if (ld) {
+                       if (ld->receive_buf)
+                               ld->receive_buf(tty,card->tty_rx,&fp,olen);
+                       tty_ldisc_deref(ld);
                }else{
                        if (net_ratelimit()){
                                printk(KERN_INFO 
@@ -4252,14 +4252,10 @@ static void wanpipe_tty_flush_buffer(struct tty_struct *tty)
        if (!tty)
                return;
        
-       wake_up_interruptible(&tty->write_wait);
 #if defined(SERIAL_HAVE_POLL_WAIT)
        wake_up_interruptible(&tty->poll_wait);
 #endif
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
-
+       tty_wakeup(tty);
        return;
 }
 
index 52f4088..2efccb0 100644 (file)
@@ -3678,7 +3678,7 @@ static int process_udp_mgmt_pkt(sdla_t* card)
                                 break;
                         }
 
-                       (void *)ptr_trc_el = card->u.f.curr_trc_el;
+                       ptr_trc_el = (void *)card->u.f.curr_trc_el;
 
                         buffer_length = 0;
                        fr_udp_pkt->data[0x00] = 0x00;
@@ -3729,7 +3729,7 @@ static int process_udp_mgmt_pkt(sdla_t* card)
                                
                                ptr_trc_el ++;
                                if((void *)ptr_trc_el > card->u.f.trc_el_last)
-                                       (void*)ptr_trc_el = card->u.f.trc_el_base;
+                                       ptr_trc_el = (void*)card->u.f.trc_el_base;
 
                                buffer_length += sizeof(fpipemon_trc_hdr_t);
                                        if(fpipemon_trc->fpipemon_trc_hdr.data_passed) {
index 501e9a7..c8bc6da 100644 (file)
@@ -937,7 +937,7 @@ int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
                         peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
                                curlen);
                         addr       += curlen;
-                        (char*)buf += curlen;
+                        buf         = (char*)buf + curlen;
                         len        -= curlen;
                 }
 
@@ -1019,7 +1019,7 @@ int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
                         poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
                                curlen);
                        addr       += curlen;
-                        (char*)buf += curlen;
+                        buf         = (char*)buf + curlen;
                         len        -= curlen;
                 }
 
@@ -2001,7 +2001,7 @@ static int detect_s514 (sdlahw_t* hw)
        (void *)hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr,
                (unsigned long)MAX_SIZEOF_S514_MEMORY);
        /* map the physical control register memory to virtual memory */
-       (void *)hw->vector = ioremap(
+       hw->vector = (unsigned long)ioremap(
                (unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE),
                (unsigned long)16);
      
index be10f8c..74e151a 100644 (file)
@@ -976,7 +976,7 @@ static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump)
 
                         dump.length     -= len;
                         dump.offset     += len;
-                        (char*)dump.ptr += len;
+                        dump.ptr         = (char*)dump.ptr + len;
                 }
                
                 sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */
index 20bd0df..51c5413 100644 (file)
@@ -1,4 +1,4 @@
-/* airport.c 0.13e
+/* airport.c
  *
  * A driver for "Hermes" chipset based Apple Airport wireless
  * card.
@@ -11,6 +11,9 @@
  *  0.06 : fix possible hang on powerup, add sleep support
  */
 
+#define DRIVER_NAME "airport"
+#define PFX DRIVER_NAME ": "
+
 #include <linux/config.h>
 
 #include <linux/module.h>
@@ -25,6 +28,7 @@
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -50,7 +54,7 @@ static int
 airport_suspend(struct macio_dev *mdev, u32 state)
 {
        struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
-       struct orinoco_private *priv = dev->priv;
+       struct orinoco_private *priv = netdev_priv(dev);
        unsigned long flags;
        int err;
 
@@ -84,15 +88,14 @@ static int
 airport_resume(struct macio_dev *mdev)
 {
        struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
-       struct orinoco_private *priv = dev->priv;
+       struct orinoco_private *priv = netdev_priv(dev);
        unsigned long flags;
        int err;
 
        printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
 
        pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(HZ/5);
+       msleep(200);
 
        enable_irq(dev->irq);
 
@@ -126,7 +129,7 @@ static int
 airport_detach(struct macio_dev *mdev)
 {
        struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
-       struct orinoco_private *priv = dev->priv;
+       struct orinoco_private *priv = netdev_priv(dev);
        struct airport *card = priv->card;
 
        if (card->ndev_registered)
@@ -144,8 +147,7 @@ airport_detach(struct macio_dev *mdev)
        macio_release_resource(mdev, 0);
 
        pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(HZ);
+       ssleep(1);
 
        macio_set_drvdata(mdev, NULL);
        free_netdev(dev);
@@ -171,14 +173,12 @@ static int airport_hard_reset(struct orinoco_private *priv)
        disable_irq(dev->irq);
 
        pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 0);
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(HZ);
+       ssleep(1);
        pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 1);
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(HZ);
+       ssleep(1);
 
        enable_irq(dev->irq);
-       schedule_timeout(HZ);
+       ssleep(1);
 #endif
 
        return 0;
@@ -194,24 +194,24 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
        hermes_t *hw;
 
        if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
-               printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n");
+               printk(KERN_ERR PFX "wrong interrupt/addresses in OF tree\n");
                return -ENODEV;
        }
 
        /* Allocate space for private device-specific data */
        dev = alloc_orinocodev(sizeof(*card), airport_hard_reset);
        if (! dev) {
-               printk(KERN_ERR "airport: can't allocate device datas\n");
+               printk(KERN_ERR PFX "can't allocate device datas\n");
                return -ENODEV;
        }
-       priv = dev->priv;
+       priv = netdev_priv(dev);
        card = priv->card;
 
        hw = &priv->hw;
        card->mdev = mdev;
 
        if (macio_request_resource(mdev, 0, "airport")) {
-               printk(KERN_ERR "airport: can't request IO resource !\n");
+               printk(KERN_ERR PFX "can't request IO resource !\n");
                free_netdev(dev);
                return -EBUSY;
        }
@@ -224,11 +224,11 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
        /* Setup interrupts & base address */
        dev->irq = macio_irq(mdev, 0);
        phys_addr = macio_resource_start(mdev, 0);  /* Physical address */
-       printk(KERN_DEBUG "Airport at physical address %lx\n", phys_addr);
+       printk(KERN_DEBUG PFX "Airport at physical address %lx\n", phys_addr);
        dev->base_addr = phys_addr;
        card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
        if (!card->vaddr) {
-               printk("airport: ioremap() failed\n");
+               printk(PFX "ioremap() failed\n");
                goto failed;
        }
 
@@ -237,24 +237,23 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
                
        /* Power up card */
        pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(HZ);
+       ssleep(1);
 
        /* Reset it before we get the interrupt */
        hermes_init(hw);
 
        if (request_irq(dev->irq, orinoco_interrupt, 0, "Airport", dev)) {
-               printk(KERN_ERR "airport: Couldn't get IRQ %d\n", dev->irq);
+               printk(KERN_ERR PFX "Couldn't get IRQ %d\n", dev->irq);
                goto failed;
        }
        card->irq_requested = 1;
 
        /* Tell the stack we exist */
        if (register_netdev(dev) != 0) {
-               printk(KERN_ERR "airport: register_netdev() failed\n");
+               printk(KERN_ERR PFX "register_netdev() failed\n");
                goto failed;
        }
-       printk(KERN_DEBUG "airport: card registered for interface %s\n", dev->name);
+       printk(KERN_DEBUG PFX "card registered for interface %s\n", dev->name);
        card->ndev_registered = 1;
        return 0;
  failed:
@@ -263,7 +262,8 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
 }                              /* airport_attach */
 
 
-static char version[] __initdata = "airport.c 0.13e (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+       " (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
 MODULE_LICENSE("Dual MPL/GPL");
@@ -280,7 +280,7 @@ static struct of_match airport_match[] =
 
 static struct macio_driver airport_driver = 
 {
-       .name           = "airport",
+       .name           = DRIVER_NAME,
        .match_table    = airport_match,
        .probe          = airport_attach,
        .remove         = airport_detach,
index d5ec3de..7300901 100644 (file)
@@ -13,8 +13,8 @@
  * (wvlan_hcf.c) library, and the NetBSD wireless driver (in no
  * particular order).
  *
- * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
- * Copyright (C) 2001, David Gibson, IBM <hermes@gibson.dropbear.id.au>
+ * Copyright (C) 2000, David Gibson, Linuxcare Australia.
+ * (C) Copyright David Gibson, IBM Corp. 2001-2003.
  * 
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
 #include "hermes.h"
 
 MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller");
-MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
-#ifdef MODULE_LICENSE
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>"
+       " & David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 /* These are maximum timeouts. Most often, card wil react much faster */
 #define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
@@ -226,7 +225,7 @@ int hermes_init(hermes_t *hw)
  *
  * Callable from any context, but locking is your problem. */
 int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
-                     hermes_response_t *resp)
+                     struct hermes_response *resp)
 {
        int err;
        int k;
@@ -392,7 +391,6 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
                return -EIO;
        }
 
-
        return 0;
 }
 
index 761c542..4f46b48 100644 (file)
@@ -4,21 +4,21 @@
 /*
  * Configuration RIDs
  */
-#define HERMES_RID_CNFPORTTYPE                 0xFC00  /* used */
-#define HERMES_RID_CNFOWNMACADDR               0xFC01  /* used */
-#define HERMES_RID_CNFDESIREDSSID              0xFC02  /* used */
-#define HERMES_RID_CNFOWNCHANNEL               0xFC03  /* used */
-#define HERMES_RID_CNFOWNSSID                  0xFC04  /* used */
+#define HERMES_RID_CNFPORTTYPE                 0xFC00
+#define HERMES_RID_CNFOWNMACADDR               0xFC01
+#define HERMES_RID_CNFDESIREDSSID              0xFC02
+#define HERMES_RID_CNFOWNCHANNEL               0xFC03
+#define HERMES_RID_CNFOWNSSID                  0xFC04
 #define HERMES_RID_CNFOWNATIMWINDOW            0xFC05
-#define HERMES_RID_CNFSYSTEMSCALE              0xFC06  /* used */
+#define HERMES_RID_CNFSYSTEMSCALE              0xFC06
 #define HERMES_RID_CNFMAXDATALEN               0xFC07
 #define HERMES_RID_CNFWDSADDRESS               0xFC08
-#define HERMES_RID_CNFPMENABLED                        0xFC09  /* used */
+#define HERMES_RID_CNFPMENABLED                        0xFC09
 #define HERMES_RID_CNFPMEPS                    0xFC0A
-#define HERMES_RID_CNFMULTICASTRECEIVE         0xFC0B  /* used */
-#define HERMES_RID_CNFMAXSLEEPDURATION         0xFC0C  /* used */
-#define HERMES_RID_CNFPMHOLDOVERDURATION       0xFC0D  /* used */
-#define HERMES_RID_CNFOWNNAME                  0xFC0E  /* used */
+#define HERMES_RID_CNFMULTICASTRECEIVE         0xFC0B
+#define HERMES_RID_CNFMAXSLEEPDURATION         0xFC0C
+#define HERMES_RID_CNFPMHOLDOVERDURATION       0xFC0D
+#define HERMES_RID_CNFOWNNAME                  0xFC0E
 #define HERMES_RID_CNFOWNDTIMPERIOD            0xFC10
 #define HERMES_RID_CNFWDSADDRESS1              0xFC11
 #define HERMES_RID_CNFWDSADDRESS2              0xFC12
 #define HERMES_RID_CNFWDSADDRESS5              0xFC15
 #define HERMES_RID_CNFWDSADDRESS6              0xFC16
 #define HERMES_RID_CNFMULTICASTPMBUFFERING     0xFC17
-#define HERMES_RID_CNFWEPENABLED_AGERE         0xFC20  /* used */
+#define HERMES_RID_CNFWEPENABLED_AGERE         0xFC20
+#define HERMES_RID_CNFAUTHENTICATION_AGERE     0xFC21
 #define HERMES_RID_CNFMANDATORYBSSID_SYMBOL    0xFC21
-#define HERMES_RID_CNFWEPDEFAULTKEYID          0xFC23  /* used */
-#define HERMES_RID_CNFDEFAULTKEY0              0xFC24  /* used */
-#define HERMES_RID_CNFDEFAULTKEY1              0xFC25  /* used */
-#define HERMES_RID_CNFMWOROBUST_AGERE          0xFC25  /* used */
-#define HERMES_RID_CNFDEFAULTKEY2              0xFC26  /* used */
-#define HERMES_RID_CNFDEFAULTKEY3              0xFC27  /* used */
-#define HERMES_RID_CNFWEPFLAGS_INTERSIL                0xFC28  /* used */
+#define HERMES_RID_CNFWEPDEFAULTKEYID          0xFC23
+#define HERMES_RID_CNFDEFAULTKEY0              0xFC24
+#define HERMES_RID_CNFDEFAULTKEY1              0xFC25
+#define HERMES_RID_CNFMWOROBUST_AGERE          0xFC25
+#define HERMES_RID_CNFDEFAULTKEY2              0xFC26
+#define HERMES_RID_CNFDEFAULTKEY3              0xFC27
+#define HERMES_RID_CNFWEPFLAGS_INTERSIL                0xFC28
 #define HERMES_RID_CNFWEPKEYMAPPINGTABLE       0xFC29
-#define HERMES_RID_CNFAUTHENTICATION           0xFC2A  /* used */
+#define HERMES_RID_CNFAUTHENTICATION           0xFC2A
 #define HERMES_RID_CNFMAXASSOCSTA              0xFC2B
 #define        HERMES_RID_CNFKEYLENGTH_SYMBOL          0xFC2B
 #define HERMES_RID_CNFTXCONTROL                        0xFC2C
 #define HERMES_RID_CNFTIMCTRL                  0xFC40
 #define HERMES_RID_CNFTHIRTY2TALLY             0xFC42
 #define HERMES_RID_CNFENHSECURITY              0xFC43
-#define HERMES_RID_CNFGROUPADDRESSES           0xFC80  /* used */
-#define HERMES_RID_CNFCREATEIBSS               0xFC81  /* used */
-#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD   0xFC82  /* used */
-#define HERMES_RID_CNFRTSTHRESHOLD             0xFC83  /* used */
-#define HERMES_RID_CNFTXRATECONTROL            0xFC84  /* used */
-#define HERMES_RID_CNFPROMISCUOUSMODE          0xFC85  /* used */
+#define HERMES_RID_CNFGROUPADDRESSES           0xFC80
+#define HERMES_RID_CNFCREATEIBSS               0xFC81
+#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD   0xFC82
+#define HERMES_RID_CNFRTSTHRESHOLD             0xFC83
+#define HERMES_RID_CNFTXRATECONTROL            0xFC84
+#define HERMES_RID_CNFPROMISCUOUSMODE          0xFC85
 #define HERMES_RID_CNFBASICRATES_SYMBOL                0xFC8A
-#define HERMES_RID_CNFPREAMBLE_SYMBOL          0xFC8C  /* used */
+#define HERMES_RID_CNFPREAMBLE_SYMBOL          0xFC8C
 #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD0  0xFC90
 #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD1  0xFC91
 #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD2  0xFC92
 #define HERMES_RID_CNFRTSTHRESHOLD4            0xFC9B
 #define HERMES_RID_CNFRTSTHRESHOLD5            0xFC9C
 #define HERMES_RID_CNFRTSTHRESHOLD6            0xFC9D
+#define HERMES_RID_CNFHOSTSCAN_SYMBOL          0xFCAB
 #define HERMES_RID_CNFSHORTPREAMBLE            0xFCB0
-#define HERMES_RID_CNFWEPKEYS_AGERE            0xFCB0  /* used */
+#define HERMES_RID_CNFWEPKEYS_AGERE            0xFCB0
 #define HERMES_RID_CNFEXCLUDELONGPREAMBLE      0xFCB1
-#define HERMES_RID_CNFTXKEY_AGERE              0xFCB1  /* used */
+#define HERMES_RID_CNFTXKEY_AGERE              0xFCB1
 #define HERMES_RID_CNFAUTHENTICATIONRSPTO      0xFCB2
+#define HERMES_RID_CNFSCANSSID_AGERE           0xFCB2
 #define HERMES_RID_CNFBASICRATES               0xFCB3
 #define HERMES_RID_CNFSUPPORTEDRATES           0xFCB4
-#define HERMES_RID_CNFTICKTIME                 0xFCE0  /* used */
+#define HERMES_RID_CNFTICKTIME                 0xFCE0
 #define HERMES_RID_CNFSCANREQUEST              0xFCE1
 #define HERMES_RID_CNFJOINREQUEST              0xFCE2
 #define HERMES_RID_CNFAUTHENTICATESTATION      0xFCE3
 #define HERMES_RID_CNFCHANNELINFOREQUEST       0xFCE4
+#define HERMES_RID_CNFHOSTSCAN                 0xFCE5
 
 /*
  * Information RIDs
 #define HERMES_RID_NICID                       0xFD0B
 #define HERMES_RID_MFISUPRANGE                 0xFD0C
 #define HERMES_RID_CFISUPRANGE                 0xFD0D
-#define HERMES_RID_CHANNELLIST                 0xFD10  /* used */
+#define HERMES_RID_CHANNELLIST                 0xFD10
 #define HERMES_RID_REGULATORYDOMAINS           0xFD11
 #define HERMES_RID_TEMPTYPE                    0xFD12
 #define HERMES_RID_CIS                         0xFD13
-#define HERMES_RID_STAID                       0xFD20  /* used */
+#define HERMES_RID_STAID                       0xFD20
 #define HERMES_RID_STASUPRANGE                 0xFD21
 #define HERMES_RID_MFIACTRANGES                        0xFD22
 #define HERMES_RID_CFIACTRANGES2               0xFD23
-#define HERMES_RID_SECONDARYVERSION_SYMBOL     0xFD24  /* used */
+#define HERMES_RID_SECONDARYVERSION_SYMBOL     0xFD24
 #define HERMES_RID_PORTSTATUS                  0xFD40
-#define HERMES_RID_CURRENTSSID                 0xFD41  /* used */
-#define HERMES_RID_CURRENTBSSID                        0xFD42  /* used */
-#define HERMES_RID_COMMSQUALITY                        0xFD43  /* used */
-#define HERMES_RID_CURRENTTXRATE               0xFD44  /* used */
+#define HERMES_RID_CURRENTSSID                 0xFD41
+#define HERMES_RID_CURRENTBSSID                        0xFD42
+#define HERMES_RID_COMMSQUALITY                        0xFD43
+#define HERMES_RID_CURRENTTXRATE               0xFD44
 #define HERMES_RID_CURRENTBEACONINTERVAL       0xFD45
 #define HERMES_RID_CURRENTSCALETHRESHOLDS      0xFD46
 #define HERMES_RID_PROTOCOLRSPTIME             0xFD47
-#define HERMES_RID_SHORTRETRYLIMIT             0xFD48  /* used */
-#define HERMES_RID_LONGRETRYLIMIT              0xFD49  /* used */
-#define HERMES_RID_MAXTRANSMITLIFETIME         0xFD4A  /* used */
+#define HERMES_RID_SHORTRETRYLIMIT             0xFD48
+#define HERMES_RID_LONGRETRYLIMIT              0xFD49
+#define HERMES_RID_MAXTRANSMITLIFETIME         0xFD4A
 #define HERMES_RID_MAXRECEIVELIFETIME          0xFD4B
 #define HERMES_RID_CFPOLLABLE                  0xFD4C
 #define HERMES_RID_AUTHENTICATIONALGORITHMS    0xFD4D
 #define HERMES_RID_PRIVACYOPTIONIMPLEMENTED    0xFD4F
+#define HERMES_RID_DBMCOMMSQUALITY_INTERSIL    0xFD51
 #define HERMES_RID_CURRENTTXRATE1              0xFD80
 #define HERMES_RID_CURRENTTXRATE2              0xFD81
 #define HERMES_RID_CURRENTTXRATE3              0xFD82
 #define HERMES_RID_OWNMACADDR                  0xFD86
 #define HERMES_RID_SCANRESULTSTABLE            0xFD88
 #define HERMES_RID_PHYTYPE                     0xFDC0
-#define HERMES_RID_CURRENTCHANNEL              0xFDC1  /* used */
+#define HERMES_RID_CURRENTCHANNEL              0xFDC1
 #define HERMES_RID_CURRENTPOWERSTATE           0xFDC2
 #define HERMES_RID_CCAMODE                     0xFDC3
-#define HERMES_RID_SUPPORTEDDATARATES          0xFDC6  /* used */
+#define HERMES_RID_SUPPORTEDDATARATES          0xFDC6
 #define HERMES_RID_BUILDSEQ                    0xFFFE
 #define HERMES_RID_FWID                                0xFFFF
 
-/* "ID" structure - used for ESSID and station nickname */
-struct hermes_idstring {
-       u16 len;
-       u16 val[16];
-} __attribute__ ((packed));
-
-typedef struct hermes_multicast {
-       u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN];
-} __attribute__ ((packed)) hermes_multicast_t;
-
 #endif
index 07d626e..53dd524 100644 (file)
@@ -76,4 +76,3 @@ struct ieee802_11_hdr {
 #define IEEE802_11_SCTL_SEQ            0xFFF0
 
 #endif /* _IEEE802_11_H */
-
index 972a851..c2f5f78 100644 (file)
@@ -7,39 +7,19 @@
 #ifndef _ORINOCO_H
 #define _ORINOCO_H
 
+#define DRIVER_VERSION "0.13e"
+
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
 #include <linux/version.h>
-#include "hermes.h"
-
-/* Workqueue / task queue backwards compatibility stuff */
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
-#include <linux/workqueue.h>
-#else
-#include <linux/tqueue.h>
-#define work_struct tq_struct
-#define INIT_WORK INIT_TQUEUE
-#define schedule_work schedule_task
-#endif
-
-/* Interrupt handler backwards compatibility stuff */
-#ifndef IRQ_NONE
-
-#define IRQ_NONE
-#define IRQ_HANDLED
-typedef void irqreturn_t;
 
-#endif
+#include "hermes.h"
 
 /* To enable debug messages */
 //#define ORINOCO_DEBUG                3
 
-#if (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10)
-#error "orinoco driver requires Wireless extensions v10 or later."
-#endif /* (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10) */
 #define WIRELESS_SPY           // enable iwspy support
 
 #define ORINOCO_MAX_KEY_SIZE   14
@@ -50,11 +30,6 @@ struct orinoco_key {
        char data[ORINOCO_MAX_KEY_SIZE];
 } __attribute__ ((packed));
 
-#define ORINOCO_INTEN          ( HERMES_EV_RX | HERMES_EV_ALLOC | HERMES_EV_TX | \
-                               HERMES_EV_TXEXC | HERMES_EV_WTERR | HERMES_EV_INFO | \
-                               HERMES_EV_INFDROP )
-
-
 struct orinoco_private {
        void *card;     /* Pointer to card dependent structure */
        int (*hard_reset)(struct orinoco_private *);
@@ -78,7 +53,6 @@ struct orinoco_private {
        hermes_t hw;
        u16 txfid;
 
-
        /* Capabilities of the hardware/firmware */
        int firmware_type;
 #define FIRMWARE_TYPE_AGERE 1
@@ -128,6 +102,10 @@ extern int orinoco_debug;
 #define TRACE_ENTER(devname) DEBUG(2, "%s: -> %s()\n", devname, __FUNCTION__);
 #define TRACE_EXIT(devname)  DEBUG(2, "%s: <- %s()\n", devname, __FUNCTION__);
 
+/********************************************************************/
+/* Exported prototypes                                              */
+/********************************************************************/
+
 extern struct net_device *alloc_orinocodev(int sizeof_card,
                                           int (*hard_reset)(struct orinoco_private *));
 extern int __orinoco_up(struct net_device *dev);
index 292eeff..4eb92ac 100644 (file)
@@ -1,4 +1,4 @@
-/* orinoco_cs.c 0.13e  - (formerly known as dldwd_cs.c)
+/* orinoco_cs.c (formerly known as dldwd_cs.c)
  *
  * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
  * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
@@ -10,6 +10,9 @@
  * Copyright notice & release notes in file orinoco.c
  */
 
+#define DRIVER_NAME "orinoco_cs"
+#define PFX DRIVER_NAME ": "
+
 #include <linux/config.h>
 #ifdef  __IN_PCMCIA_PACKAGE__
 #include <pcmcia/k_compat.h>
@@ -47,9 +50,7 @@
 
 MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 /* Module parameters */
 
@@ -76,7 +77,7 @@ MODULE_PARM(ignore_cis_vcc, "i");
  * device driver with appropriate cards, through the card
  * configuration database.
  */
-static dev_info_t dev_info = "orinoco_cs";
+static dev_info_t dev_info = DRIVER_NAME;
 
 /********************************************************************/
 /* Data structures                                                 */
@@ -144,15 +145,6 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
 /* PCMCIA stuff                                                    */
 /********************************************************************/
 
-/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which
- * does this, but it's not in 2.4 so we do our own for now. */
-static void
-orinoco_cs_error(client_handle_t handle, int func, int ret)
-{
-       error_info_t err = { func, ret };
-       pcmcia_report_error(handle, &err);
-}
-
 /*
  * This creates an "instance" of the driver, allocating local data
  * structures for one device.  The device is registered with Card
@@ -174,7 +166,7 @@ orinoco_cs_attach(void)
        dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
        if (! dev)
                return NULL;
-       priv = dev->priv;
+       priv = netdev_priv(dev);
        card = priv->card;
 
        /* Link both structures together */
@@ -216,7 +208,7 @@ orinoco_cs_attach(void)
 
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
-               orinoco_cs_error(link->handle, RegisterClient, ret);
+               cs_error(link->handle, RegisterClient, ret);
                orinoco_cs_detach(link);
                return NULL;
        }
@@ -230,8 +222,7 @@ orinoco_cs_attach(void)
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void
-orinoco_cs_detach(dev_link_t * link)
+static void orinoco_cs_detach(dev_link_t *link)
 {
        dev_link_t **linkp;
        struct net_device *dev = link->priv;
@@ -240,10 +231,8 @@ orinoco_cs_detach(dev_link_t * link)
        for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
                if (*linkp == link)
                        break;
-       if (*linkp == NULL) {
-               BUG();
-               return;
-       }
+
+       BUG_ON(*linkp == NULL);
 
        if (link->state & DEV_CONFIG)
                orinoco_cs_release(link);
@@ -254,9 +243,9 @@ orinoco_cs_detach(dev_link_t * link)
 
        /* Unlink device structure, and free it */
        *linkp = link->next;
-       DEBUG(0, "orinoco_cs: detach: link=%p link->dev=%p\n", link, link->dev);
+       DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
        if (link->dev) {
-               DEBUG(0, "orinoco_cs: About to unregister net device %p\n",
+               DEBUG(0, PFX "About to unregister net device %p\n",
                      dev);
                unregister_netdev(dev);
        }
@@ -269,15 +258,16 @@ orinoco_cs_detach(dev_link_t * link)
  * device available to the system.
  */
 
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+#define CS_CHECK(fn, ret) do { \
+               last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
+       } while (0)
 
 static void
 orinoco_cs_config(dev_link_t *link)
 {
        struct net_device *dev = link->priv;
        client_handle_t handle = link->handle;
-       struct orinoco_private *priv = dev->priv;
+       struct orinoco_private *priv = netdev_priv(dev);
        struct orinoco_pccard *card = priv->card;
        hermes_t *hw = &priv->hw;
        int last_fn, last_ret;
@@ -308,7 +298,8 @@ orinoco_cs_config(dev_link_t *link)
        link->state |= DEV_CONFIG;
 
        /* Look up the current Vcc */
-       CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
+       CS_CHECK(GetConfigurationInfo,
+                pcmcia_get_configuration_info(handle, &conf));
        link->conf.Vcc = conf.Vcc;
 
        /*
@@ -412,8 +403,9 @@ orinoco_cs_config(dev_link_t *link)
                        pcmcia_release_io(link->handle, &link->io);
                last_ret = pcmcia_get_next_tuple(handle, &tuple);
                if (last_ret  == CS_NO_MORE_ITEMS) {
-                       printk(KERN_ERR "GetNextTuple().  No matching CIS configuration, "
-                              "maybe you need the ignore_cis_vcc=1 parameter.\n");
+                       printk(KERN_ERR PFX "GetNextTuple(): No matching "
+                              "CIS configuration, maybe you need the "
+                              "ignore_cis_vcc=1 parameter.\n");
                        goto cs_failed;
                }
        }
@@ -451,7 +443,8 @@ orinoco_cs_config(dev_link_t *link)
         * the I/O windows and the interrupt mapping, and putting the
         * card and host interface into "Memory and IO" mode.
         */
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+       CS_CHECK(RequestConfiguration,
+                pcmcia_request_configuration(link->handle, &link->conf));
 
        /* Ok, we have the configuration, prepare to register the netdev */
        dev->base_addr = link->io.BasePort1;
@@ -463,7 +456,7 @@ orinoco_cs_config(dev_link_t *link)
        dev->name[0] = '\0';
        /* Tell the stack we exist */
        if (register_netdev(dev) != 0) {
-               printk(KERN_ERR "orinoco_cs: register_netdev() failed\n");
+               printk(KERN_ERR PFX "register_netdev() failed\n");
                goto failed;
        }
 
@@ -495,7 +488,7 @@ orinoco_cs_config(dev_link_t *link)
        return;
 
  cs_failed:
-       orinoco_cs_error(link->handle, last_fn, last_ret);
+       cs_error(link->handle, last_fn, last_ret);
 
  failed:
        orinoco_cs_release(link);
@@ -510,7 +503,7 @@ static void
 orinoco_cs_release(dev_link_t *link)
 {
        struct net_device *dev = link->priv;
-       struct orinoco_private *priv = dev->priv;
+       struct orinoco_private *priv = netdev_priv(dev);
        unsigned long flags;
 
        /* We're committed to taking the device away now, so mark the
@@ -538,7 +531,7 @@ orinoco_cs_event(event_t event, int priority,
 {
        dev_link_t *link = args->client_data;
        struct net_device *dev = link->priv;
-       struct orinoco_private *priv = dev->priv;
+       struct orinoco_private *priv = netdev_priv(dev);
        struct orinoco_pccard *card = priv->card;
        int err = 0;
        unsigned long flags;
@@ -635,12 +628,14 @@ orinoco_cs_event(event_t event, int priority,
 
 /* Can't be declared "const" or the whole __initdata section will
  * become const */
-static char version[] __initdata = "orinoco_cs.c 0.13e (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+       " (David Gibson <hermes@gibson.dropbear.id.au>, "
+       "Pavel Roskin <proski@gnu.org>, et al)";
 
 static struct pcmcia_driver orinoco_driver = {
        .owner          = THIS_MODULE,
        .drv            = {
-               .name   = "orinoco_cs",
+               .name   = DRIVER_NAME,
        },
        .attach         = orinoco_cs_attach,
        .detach         = orinoco_cs_detach,
@@ -660,7 +655,7 @@ exit_orinoco_cs(void)
        pcmcia_unregister_driver(&orinoco_driver);
 
        if (dev_list)
-               DEBUG(0, "orinoco_cs: Removing leftover devices.\n");
+               DEBUG(0, PFX "Removing leftover devices.\n");
        while (dev_list != NULL) {
                if (dev_list->state & DEV_CONFIG)
                        orinoco_cs_release(dev_list);
@@ -670,4 +665,3 @@ exit_orinoco_cs(void)
 
 module_init(init_orinoco_cs);
 module_exit(exit_orinoco_cs);
-
index 6d49850..c77afa1 100644 (file)
@@ -28,9 +28,9 @@ typedef struct ray_dev_t {
     dev_node_t  node;
     window_handle_t amem_handle;   /* handle to window for attribute memory  */
     window_handle_t rmem_handle;   /* handle to window for rx buffer on card */
-    UCHAR *sram;                   /* pointer to beginning of shared RAM     */
-    UCHAR *amem;                   /* pointer to attribute mem window        */
-    UCHAR *rmem;                   /* pointer to receive buffer window       */
+    void __iomem *sram;            /* pointer to beginning of shared RAM     */
+    void __iomem *amem;            /* pointer to attribute mem window        */
+    void __iomem *rmem;            /* pointer to receive buffer window       */
     dev_link_t *finder;            /* pointer back to dev_link_t for card    */
     struct timer_list timer;
     long tx_ccs_lock;
index 1cbd34b..3047d8c 100644 (file)
@@ -3822,17 +3822,18 @@ static irqreturn_t wavelan_interrupt(int irq, void *dev_id, struct pt_regs *regs
        if ((hasr & HASR_MMC_INTR) && (lp->hacr & HACR_MMC_INT_ENABLE)) {
                u8 dce_status;
 
-#ifdef DEBUG_INTERRUPT_ERROR
-               printk(KERN_INFO
-                      "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n",
-                      dev->name, dce_status);
-#endif
                /*
                 * Interrupt from the modem management controller.
                 * This will clear it -- ignored for now.
                 */
                mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status,
                         sizeof(dce_status));
+
+#ifdef DEBUG_INTERRUPT_ERROR
+               printk(KERN_INFO
+                      "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n",
+                      dev->name, dce_status);
+#endif
        }
 
        /* Check if not controller interrupt */
index a8def27..08866f6 100644 (file)
@@ -16,4 +16,7 @@ int sync_start(void);
 /* remove the hooks */
 void sync_stop(void);
  
+/* sync the given CPU's buffer */
+void sync_buffer(int cpu);
+
 #endif /* OPROFILE_BUFFER_SYNC_H */
index 66eafcd..23be201 100644 (file)
 
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <linux/workqueue.h>
 #include <linux/cache.h>
  
 struct task_struct;
  
-/* allocate a sample buffer for each CPU */
 int alloc_cpu_buffers(void);
-
 void free_cpu_buffers(void);
 
+void start_cpu_work(void);
+void end_cpu_work(void);
+
 /* CPU buffer is composed of such entries (which are
  * also used for context switch notes)
  */
@@ -38,11 +40,12 @@ struct oprofile_cpu_buffer {
        struct op_sample * buffer;
        unsigned long sample_received;
        unsigned long sample_lost_overflow;
-       unsigned long sample_lost_task_exit;
+       int cpu;
+       struct work_struct work;
 } ____cacheline_aligned;
 
 extern struct oprofile_cpu_buffer cpu_buffer[];
 
-void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf);
+void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
 
 #endif /* OPROFILE_CPU_BUFFER_H */
index 8e92b03..3ec23d8 100644 (file)
@@ -22,14 +22,10 @@ void oprofile_reset_stats(void)
        struct oprofile_cpu_buffer * cpu_buf; 
        int i;
  
-       for (i = 0; i < NR_CPUS; ++i) {
-               if (!cpu_possible(i))
-                       continue;
-
+       for_each_cpu(i) {
                cpu_buf = &cpu_buffer[i]; 
                cpu_buf->sample_received = 0;
                cpu_buf->sample_lost_overflow = 0;
-               cpu_buf->sample_lost_task_exit = 0;
        }
  
        atomic_set(&oprofile_stats.sample_lost_no_mm, 0);
@@ -50,10 +46,7 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
        if (!dir)
                return;
 
-       for (i = 0; i < NR_CPUS; ++i) {
-               if (!cpu_possible(i))
-                       continue;
-
+       for_each_cpu(i) {
                cpu_buf = &cpu_buffer[i]; 
                snprintf(buf, 10, "cpu%d", i);
                cpudir = oprofilefs_mkdir(sb, dir, buf);
@@ -66,8 +59,6 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
                        &cpu_buf->sample_received);
                oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_overflow",
                        &cpu_buf->sample_lost_overflow);
-               oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_task_exit",
-                       &cpu_buf->sample_lost_task_exit);
        }
  
        oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mm",
index 3fae2c7..5f03189 100644 (file)
@@ -19,7 +19,7 @@ static int timer_notify(struct notifier_block * self, unsigned long val, void *
 {
        struct pt_regs * regs = (struct pt_regs *)data;
        int cpu = smp_processor_id();
-       unsigned long eip = instruction_pointer(regs);
+       unsigned long eip = profile_pc(regs);
  
        oprofile_add_sample(eip, !user_mode(regs), 0, cpu);
        return 0;
index 6e67ea0..45f2be4 100644 (file)
@@ -11,7 +11,7 @@
  *      (at your option) any later version.
  *
  *     by Alan Cox <alan@redhat.com> and 
- *        Alex deVries <adevries@thepuffingroup.com> 
+ *        Alex deVries <alex@onefishtwo.ca>
  */
 
 #include <linux/errno.h>
index 377c723..474eacd 100644 (file)
@@ -35,7 +35,7 @@ ifndef CONFIG_X86
 obj-y += syscall.o
 endif
 
-host-progs := gen-devlist
+hostprogs-y := gen-devlist
 
 # Dependencies on generated files need to be listed explicitly
 $(obj)/names.o: $(obj)/devlist.h $(obj)/classlist.h
index 3dc99c1..9117a95 100644 (file)
@@ -88,6 +88,18 @@ config HOTPLUG_PCI_ACPI
 
          When in doubt, say N.
 
+config HOTPLUG_PCI_ACPI_IBM
+       tristate "ACPI PCI Hotplug driver IBM extensions"
+       depends on HOTPLUG_PCI_ACPI
+       help
+         Say Y here if you have an IBM system that supports PCI Hotplug using
+         ACPI.
+
+         To compile this driver as a module, choose M here: the
+         module will be called acpiphp_ibm.
+
+         When in doubt, say N.
+
 config HOTPLUG_PCI_CPCI
        bool "CompactPCI Hotplug driver"
        depends on HOTPLUG_PCI
index a972757..4fc3ed9 100644 (file)
@@ -7,6 +7,7 @@ obj-$(CONFIG_HOTPLUG_PCI_FAKE)          += fakephp.o
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)       += cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)          += ibmphp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)         += acpiphp.o
+obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM)     += acpiphp_ibm.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550)  += cpcihp_zt5550.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o
 obj-$(CONFIG_HOTPLUG_PCI_PCIE)         += pciehp.o
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
new file mode 100644 (file)
index 0000000..fe7866c
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ * ACPI PCI Hot Plug IBM Extension
+ *
+ * Copyright (C) 2004 Vernon Mauery <vernux@us.ibm.com>
+ * Copyright (C) 2004 IBM Corp.
+ *
+ * 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.
+ *
+ * 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 <vernux@us.ibm.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <acpi/acpi_bus.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <asm/uaccess.h>
+#include <linux/moduleparam.h>
+
+#include "acpiphp.h"
+#include "pci_hotplug.h"
+
+#define DRIVER_VERSION "1.0.1"
+#define DRIVER_AUTHOR  "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
+#define DRIVER_DESC    "ACPI Hot Plug PCI Controller Driver IBM extension"
+
+static int debug;
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
+module_param(debug, bool, 644);
+MODULE_PARM_DESC(debug, " Debugging mode enabled or not");
+#define MY_NAME "acpiphp_ibm"
+
+#undef dbg
+#define dbg(format, arg...)                            \
+do {                                                   \
+       if (debug)                                      \
+               printk(KERN_DEBUG "%s: " format,        \
+                               MY_NAME , ## arg);      \
+} while (0)
+
+#define FOUND_APCI 0x61504349
+/* these are the names for the IBM ACPI pseudo-device */
+#define IBM_HARDWARE_ID1 "IBM37D0"
+#define IBM_HARDWARE_ID2 "IBM37D4"
+
+/* union apci_descriptor - allows access to the
+ * various device descriptors that are embedded in the
+ * aPCI table
+ */
+union apci_descriptor {
+       struct {
+               char sig[4];
+               u8   len;
+       } header;
+       struct {
+               u8  type;
+               u8  len;
+               u16 slot_id;
+               u8  bus_id;
+               u8  dev_num;
+               u8  slot_num;
+               u8  slot_attr[2];
+               u8  attn;
+               u8  status[2];
+               u8  sun;
+       } slot;
+       struct {
+               u8 type;
+               u8 len;
+       } generic;
+};
+
+/* struct notification - keeps info about the device
+ * that cause the ACPI notification event
+ */
+struct notification {
+       struct acpi_device *device;
+       u8                  event;
+};
+
+static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status);
+static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status);
+static void ibm_handle_events(acpi_handle handle, u32 event, void *context);
+static int ibm_get_table_from_acpi(char **bufp);
+static ssize_t ibm_read_apci_table(struct kobject *kobj,
+               char *buffer, loff_t pos, size_t size);
+static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
+               u32 lvl, void *context, void **rv);
+static int __init ibm_acpiphp_init(void);
+static void __exit ibm_acpiphp_exit(void);
+
+static acpi_handle ibm_acpi_handle;
+static struct notification ibm_note;
+static struct bin_attribute ibm_apci_table_attr = {
+           .attr = {
+                   .name = "apci_table",
+                   .owner = THIS_MODULE,
+                   .mode = S_IRUGO,
+           },
+           .read = ibm_read_apci_table,
+           .write = NULL,
+};
+static struct acpiphp_attention_info ibm_attention_info = 
+{
+       .set_attn = ibm_set_attention_status,
+       .get_attn = ibm_get_attention_status,
+       .owner = THIS_MODULE,
+};
+
+
+/**
+ * ibm_set_attention_status - callback method to set the attention LED
+ * @slot: the hotplug_slot to work with
+ * @status: what to set the LED to (0 or 1)
+ *
+ * Description: this method is registered with the acpiphp module as a
+ * callback to do the device specific task of setting the LED status
+ **/
+static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
+{
+       int retval = 0;
+       union acpi_object args[2]; 
+       struct acpi_object_list params = { .pointer = args, .count = 2 };
+       acpi_status stat; 
+       unsigned long rc = 0;
+       struct acpiphp_slot *acpi_slot;
+
+       acpi_slot = ((struct slot *)(slot->private))->acpi_slot;
+
+       dbg("%s: set slot %d attention status to %d\n", __FUNCTION__,
+                       acpi_slot->sun, (status ? 1 : 0));
+
+       args[0].type = ACPI_TYPE_INTEGER;
+       args[0].integer.value = acpi_slot->sun;
+       args[1].type = ACPI_TYPE_INTEGER;
+       args[1].integer.value = (status) ? 1 : 0;
+
+       stat = acpi_evaluate_integer(ibm_acpi_handle, "APLS", &params, &rc);
+       if (ACPI_FAILURE(stat)) {
+               retval = -ENODEV;
+               err("APLS evaluation failed:  0x%08x\n", stat);
+       } else if (!rc) {
+               retval = -ERANGE;
+               err("APLS method failed:  0x%08lx\n", rc);
+       }
+       return retval;
+}
+
+/**
+ * ibm_get_attention_status - callback method to get attention LED status
+ * @slot: the hotplug_slot to work with
+ * @status: returns what the LED is set to (0 or 1)
+ *
+ * Description: this method is registered with the acpiphp module as a
+ * callback to do the device specific task of getting the LED status
+ * 
+ * Because there is no direct method of getting the LED status directly
+ * from an ACPI call, we read the aPCI table and parse out our
+ * slot descriptor to read the status from that.
+ **/
+static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
+{
+       int retval = -EINVAL, ind = 0, size;
+       char *table = NULL;
+       struct acpiphp_slot *acpi_slot;
+       union apci_descriptor *des;
+
+       acpi_slot = ((struct slot *)(slot->private))->acpi_slot;
+
+       size = ibm_get_table_from_acpi(&table);
+       if (size <= 0 || !table)
+               goto get_attn_done;
+       // read the header
+       des = (union apci_descriptor *)&table[ind];
+       if (memcmp(des->header.sig, "aPCI", 4) != 0)
+               goto get_attn_done;
+       des = (union apci_descriptor *)&table[ind += des->header.len];
+       while (ind < size && (des->generic.type != 0x82 ||
+                       des->slot.slot_id != acpi_slot->sun))
+               des = (union apci_descriptor *)&table[ind += des->generic.len];
+       if (ind < size && des->slot.slot_id == acpi_slot->sun) {
+               retval = 0;
+               if (des->slot.attn & 0xa0 || des->slot.status[1] & 0x08)
+                       *status = 1;
+               else
+                       *status = 0;
+       }
+
+       dbg("%s: get slot %d attention status is %d retval=%x\n",
+                       __FUNCTION__, acpi_slot->sun, *status, retval);
+
+get_attn_done:
+       kfree(table);
+       return retval;
+}
+
+/**
+ * ibm_handle_events - listens for ACPI events for the IBM37D0 device
+ * @handle: an ACPI handle to the device that caused the event
+ * @event: the event info (device specific)
+ * @context: passed context (our notification struct)
+ *
+ * Description: this method is registered as a callback with the ACPI
+ * subsystem it is called when this device has an event to notify the OS of
+ *
+ * The events actually come from the device as two events that get
+ * synthesized into one event with data by this function.  The event
+ * ID comes first and then the slot number that caused it.  We report
+ * this as one event to the OS.
+ *
+ * From section 5.6.2.2 of the ACPI 2.0 spec, I understand that the OSPM will
+ * only re-enable the interrupt that causes this event AFTER this method
+ * has returned, thereby enforcing serial access for the notification struct.
+ **/
+static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
+{
+       u8 detail = event & 0x0f;
+       u8 subevent = event & 0xf0;
+       struct notification *note = context;
+
+       dbg("%s: Received notification %02x\n", __FUNCTION__, event);
+
+       if (subevent == 0x80) {
+               dbg("%s: generationg bus event\n", __FUNCTION__);
+               acpi_bus_generate_event(note->device, note->event, detail);
+       } else
+               note->event = event;
+}
+
+/**
+ * ibm_get_table_from_acpi - reads the APLS buffer from ACPI
+ * @bufp: address to pointer to allocate for the table
+ *
+ * Description: this method reads the APLS buffer in from ACPI and
+ * stores the "stripped" table into a single buffer
+ * it allocates and passes the address back in bufp
+ *
+ * If NULL is passed in as buffer, this method only calculates
+ * the size of the table and returns that without filling
+ * in the buffer
+ *
+ * returns < 0 on error or the size of the table on success
+ **/
+static int ibm_get_table_from_acpi(char **bufp)
+{
+       union acpi_object *package;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       acpi_status status;
+       char *lbuf = NULL;
+       int i, size = -EIO;
+
+       status = acpi_evaluate_object(ibm_acpi_handle, "APCI", NULL, &buffer);
+       if (ACPI_FAILURE(status)) {
+               err("%s:  APCI evaluation failed\n", __FUNCTION__);
+               return -ENODEV;
+       }
+
+       package = (union acpi_object *) buffer.pointer;
+       if(!(package) ||
+                       (package->type != ACPI_TYPE_PACKAGE) ||
+                       !(package->package.elements)) {
+               err("%s:  Invalid APCI object\n", __FUNCTION__);
+               goto read_table_done;
+       }
+
+       for(size = 0, i = 0; i < package->package.count; i++) {
+               if (package->package.elements[i].type != ACPI_TYPE_BUFFER) {
+                       err("%s:  Invalid APCI element %d\n", __FUNCTION__, i);
+                       goto read_table_done;
+               }
+               size += package->package.elements[i].buffer.length;
+       }
+
+       if (bufp == NULL)
+               goto read_table_done;
+
+       lbuf = kmalloc(size, GFP_KERNEL);
+       dbg("%s: element count: %i, ASL table size: %i, &table = 0x%p\n",
+                       __FUNCTION__, package->package.count, size, lbuf);
+
+       if (lbuf) {
+               *bufp = lbuf;
+               memset(lbuf, 0, size);
+       } else {
+               size = -ENOMEM;
+               goto read_table_done;
+       }
+
+       size = 0;
+       for (i=0; i<package->package.count; i++) {
+               memcpy(&lbuf[size],
+                               package->package.elements[i].buffer.pointer,
+                               package->package.elements[i].buffer.length);
+               size += package->package.elements[i].buffer.length;
+       }
+
+read_table_done:
+       kfree(buffer.pointer);
+       return size;
+}
+
+/**
+ * ibm_read_apci_table - callback for the sysfs apci_table file
+ * @kobj: the kobject this binary attribute is a part of
+ * @buffer: the kernel space buffer to fill
+ * @pos: the offset into the file
+ * @size: the number of bytes requested
+ *
+ * Description: gets registered with sysfs as the reader callback
+ * to be executed when /sys/bus/pci/slots/apci_table gets read
+ *
+ * Since we don't get notified on open and close for this file,
+ * things get really tricky here...
+ * our solution is to only allow reading the table in all at once
+ **/
+static ssize_t ibm_read_apci_table(struct kobject *kobj,
+               char *buffer, loff_t pos, size_t size)
+{
+       int bytes_read = -EINVAL;
+       char *table = NULL;
+       
+       dbg("%s: pos = %d, size = %zd\n", __FUNCTION__, (int)pos, size);
+
+       if (pos == 0) {
+               bytes_read = ibm_get_table_from_acpi(&table);
+               if (bytes_read > 0 && bytes_read <= size)
+                       memcpy(buffer, table, bytes_read);
+               kfree(table);
+       }
+       return bytes_read;
+}
+
+/**
+ * ibm_find_acpi_device - callback to find our ACPI device
+ * @handle: the ACPI handle of the device we are inspecting
+ * @lvl: depth into the namespace tree
+ * @context: a pointer to our handle to fill when we find the device
+ * @rv: a return value to fill if desired
+ *
+ * Description: used as a callback when calling acpi_walk_namespace
+ * to find our device.  When this method returns non-zero
+ * acpi_walk_namespace quits its search and returns our value
+ **/
+static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
+               u32 lvl, void *context, void **rv)
+{
+       acpi_handle *phandle = (acpi_handle *)context;
+       acpi_status status; 
+       struct acpi_device_info info; 
+       struct acpi_buffer info_buffer = {
+               .length = sizeof(struct acpi_device_info),
+               .pointer = &info,
+       };
+
+       status = acpi_get_object_info(handle, &info_buffer);
+       if (ACPI_FAILURE(status)) {
+               err("%s:  Failed to get device information", __FUNCTION__);
+               return 0;
+       }
+       info.hardware_id.value[sizeof(info.hardware_id.value) - 1] = '\0';
+
+       if(info.current_status && (info.valid & ACPI_VALID_HID) &&
+                       (!strcmp(info.hardware_id.value, IBM_HARDWARE_ID1) ||
+                       !strcmp(info.hardware_id.value, IBM_HARDWARE_ID2))) {
+               dbg("found hardware: %s, handle: %p\n", info.hardware_id.value,
+                               handle);
+               *phandle = handle;
+               /* returning non-zero causes the search to stop
+                * and returns this value to the caller of 
+                * acpi_walk_namespace, but it also causes some warnings
+                * in the acpi debug code to print...
+                */
+               return FOUND_APCI;
+       }
+       return 0;
+}
+
+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;
+
+       dbg("%s\n", __FUNCTION__);
+
+       if (acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                       ACPI_UINT32_MAX, ibm_find_acpi_device,
+                       &ibm_acpi_handle, NULL) != FOUND_APCI) {
+               err("%s: acpi_walk_namespace failed\n", __FUNCTION__);
+               retval = -ENODEV;
+               goto init_return;
+       }
+       dbg("%s: found IBM aPCI device\n", __FUNCTION__);
+       if (acpi_bus_get_device(ibm_acpi_handle, &device)) {
+               err("%s: acpi_bus_get_device failed\n", __FUNCTION__);
+               retval = -ENODEV;
+               goto init_return;
+       }
+       if (acpiphp_register_attention(&ibm_attention_info)) {
+               retval = -ENODEV;
+               goto init_return;
+       }
+
+       ibm_note.device = device;
+       status = acpi_install_notify_handler(
+                       ibm_acpi_handle,
+                       ACPI_DEVICE_NOTIFY,
+                       ibm_handle_events,
+                       &ibm_note);
+       if (ACPI_FAILURE(status)) {
+               err("%s:  Failed to register notification handler\n",
+                               __FUNCTION__);
+               retval = -EBUSY;
+               goto init_cleanup;
+       }
+
+       ibm_apci_table_attr.size = ibm_get_table_from_acpi(NULL);
+       retval = sysfs_create_bin_file(sysdir, &ibm_apci_table_attr);
+
+       return retval;
+
+init_cleanup:
+       acpiphp_unregister_attention(&ibm_attention_info);
+init_return:
+       return retval;
+}
+
+static void __exit ibm_acpiphp_exit(void)
+{
+       acpi_status status;
+       struct kobject *sysdir = &pci_hotplug_slots_subsys.kset.kobj;
+
+       dbg("%s\n", __FUNCTION__);
+
+       if (acpiphp_unregister_attention(&ibm_attention_info))
+               err("%s: attention info deregistration failed", __FUNCTION__);
+
+          status = acpi_remove_notify_handler(
+                          ibm_acpi_handle,
+                          ACPI_DEVICE_NOTIFY,
+                          ibm_handle_events);
+          if (ACPI_FAILURE(status))
+                  err("%s:  Notification handler removal failed\n",
+                                  __FUNCTION__);
+       // remove the /sys entries
+       if (sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr))
+               err("%s: removal of sysfs file apci_table failed\n",
+                               __FUNCTION__);
+}
+
+module_init(ibm_acpiphp_init);
+module_exit(ibm_acpiphp_exit);
index 5ef19b1..889b2e3 100644 (file)
@@ -59,6 +59,18 @@ int pci_remove_device_safe(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_remove_device_safe);
 
+void pci_remove_bus(struct pci_bus *b)
+{
+       pci_proc_detach_bus(b);
+
+       spin_lock(&pci_bus_lock);
+       list_del(&b->node);
+       spin_unlock(&pci_bus_lock);
+
+       class_device_unregister(&b->class_dev);
+}
+EXPORT_SYMBOL(pci_remove_bus);
+
 /**
  * pci_remove_bus_device - remove a PCI device and any children
  * @dev: the device to remove
@@ -77,13 +89,7 @@ void pci_remove_bus_device(struct pci_dev *dev)
                struct pci_bus *b = dev->subordinate;
 
                pci_remove_behind_bridge(dev);
-               pci_proc_detach_bus(b);
-
-               spin_lock(&pci_bus_lock);
-               list_del(&b->node);
-               spin_unlock(&pci_bus_lock);
-
-               class_device_unregister(&b->class_dev);
+               pci_remove_bus(b);
                dev->subordinate = NULL;
        }
 
index 7f0f6c2..e21250c 100644 (file)
@@ -537,10 +537,11 @@ pci_assign_unassigned_resources(void)
 
        /* Depth first, calculate sizes and alignments of all
           subordinate buses. */
-       for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next)
+       list_for_each(ln, &pci_root_buses) {
                pci_bus_size_bridges(pci_bus_b(ln));
+       }
        /* Depth last, allocate resources and update the hardware. */
-       for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) {
+       list_for_each(ln, &pci_root_buses) {
                pci_bus_assign_resources(pci_bus_b(ln));
                pci_enable_bridges(pci_bus_b(ln));
        }
index bd79f3b..124225e 100644 (file)
@@ -566,7 +566,6 @@ static int
 au1000_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
 {
        unsigned int speed;
-       unsigned long start;
        u_long flags;
 
        if(map->map>=MAX_WIN){
@@ -588,25 +587,19 @@ au1000_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
        }
 
        spin_lock_irqsave(&pcmcia_lock, flags);
-       start=map->sys_start;
-
-       if(map->sys_stop==0)
-               map->sys_stop=MAP_SIZE-1;
-
        if (map->flags & MAP_ATTRIB) {
-               map->sys_start = pcmcia_socket[sock].phys_attr + 
+               map->static_start = pcmcia_socket[sock].phys_attr + 
                        map->card_start;
        }
        else {
-               map->sys_start = pcmcia_socket[sock].phys_mem + 
+               map->static_start = pcmcia_socket[sock].phys_mem + 
                        map->card_start;
        }
 
-       map->sys_stop=map->sys_start+(map->sys_stop-start);
        pcmcia_socket[sock].mem_map[map->map]=*map;
        spin_unlock_irqrestore(&pcmcia_lock, flags);
-       debug(3, "set_mem_map %d start %x stop %x card_start %x\n", 
-                       map->map, map->sys_start, map->sys_stop, 
+       debug(3, "set_mem_map %d start %x card_start %x\n", 
+                       map->map, map->static_start,
                        map->card_start);
        return 0;
 
index fd08c3a..875c9cf 100644 (file)
@@ -636,19 +636,17 @@ static int hs_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
        hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
        struct pccard_mem_map *smem;
        int map = mem->map;
-       unsigned long paddr, size;
+       unsigned long paddr;
 
 #if 0
-       DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, sys_start=0x%08lx, sys_end=0x%08lx, card_start=0x%08x)\n",
-           sock, map, mem->flags, mem->sys_start, mem->sys_stop, mem->card_start);
+       DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, card_start=0x%08x)\n",
+           sock, map, mem->flags, mem->card_start);
 #endif
 
        if (map >= MAX_WIN)
            return -EINVAL;
        smem = &sp->mem_maps[map];
        
-       size = mem->sys_stop - mem->sys_start + 1;
-       
        paddr = sp->mem_base;               /* base of Attribute mapping */
        if (!(mem->flags & MAP_ATTRIB))
            paddr += HD64465_PCC_WINDOW;    /* base of Common mapping */
@@ -660,8 +658,7 @@ static int hs_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
         * queries our fixed mapping.  I wish this fact had been
         * documented - Greg Banks.
         */
-       mem->sys_start = paddr;
-       mem->sys_stop = paddr + size - 1;
+       mem->static_start = paddr;
        
        *smem = *mem;
        
index 57b1bca..4f00c9d 100644 (file)
@@ -502,10 +502,10 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
                return -EINVAL;
        }
 
-       if ((mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) {
+       if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) {
                printk("pd6729_set_mem_map: invalid address / speed");
                /* printk("invalid mem map for socket %i : %lx to %lx with a start of %x\n",
-                        sock, mem->sys_start, mem->sys_stop, mem->card_start); */
+                        sock, mem->res->start, mem->res->end, mem->card_start); */
                return -EINVAL;
        }
 
@@ -515,7 +515,7 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
 
        /* write the start address */
        base = I365_MEM(map);
-       i = (mem->sys_start >> 12) & 0x0fff;
+       i = (mem->res->start >> 12) & 0x0fff;
        if (mem->flags & MAP_16BIT)
                i |= I365_MEM_16BIT;
        if (mem->flags & MAP_0WS)
@@ -524,7 +524,7 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
 
        /* write the stop address */
 
-       i= (mem->sys_stop >> 12) & 0x0fff;
+       i= (mem->res->end >> 12) & 0x0fff;
        switch (to_cycles(mem->speed)) {
        case 0:
                break;
@@ -543,11 +543,11 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
 
        /* Take care of high byte */
        indirect_write(socket, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
-       indirect_write(socket, PD67_EXT_DATA, mem->sys_start >> 24);
+       indirect_write(socket, PD67_EXT_DATA, mem->res->start >> 24);
 
        /* card start */
 
-       i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+       i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff;
        if (mem->flags & MAP_WRPROT)
                i |= I365_MEM_WRPROT;
        if (mem->flags & MAP_ATTRIB) {
@@ -577,7 +577,7 @@ static int pd6729_init(struct pcmcia_socket *sock)
        int i;
        struct resource res = { .end = 0x0fff };
        pccard_io_map io = { 0, 0, 0, 0, 1 };
-       pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff };
+       pccard_mem_map mem = { .res = &res, };
 
        pd6729_set_socket(sock, &dead_socket);
        for (i = 0; i < 2; i++) {
index 491d11b..2bdf9a0 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/arch/pxa-regs.h>
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
@@ -178,39 +179,6 @@ int pxa2xx_drv_pcmcia_probe(struct device *dev)
        first = ops->first;
        nr = ops->nr;
 
-       /* Setup GPIOs for PCMCIA/CF alternate function mode.
-        *
-        * It would be nice if set_GPIO_mode included support
-        * for driving GPIO outputs to default high/low state
-        * before programming GPIOs as outputs. Setting GPIO
-        * outputs to default high/low state via GPSR/GPCR
-        * before defining them as outputs should reduce
-        * the possibility of glitching outputs during GPIO
-        * setup. This of course assumes external terminators
-        * are present to hold GPIOs in a defined state.
-        *
-        * In the meantime, setup default state of GPIO
-        * outputs before we enable them as outputs.
-        */
-
-       GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
-               GPIO_bit(GPIO49_nPWE) |
-               GPIO_bit(GPIO50_nPIOR) |
-               GPIO_bit(GPIO51_nPIOW) |
-               GPIO_bit(GPIO52_nPCE_1) |
-               GPIO_bit(GPIO53_nPCE_2);
-
-       pxa_gpio_mode(GPIO48_nPOE_MD);
-       pxa_gpio_mode(GPIO49_nPWE_MD);
-       pxa_gpio_mode(GPIO50_nPIOR_MD);
-       pxa_gpio_mode(GPIO51_nPIOW_MD);
-       pxa_gpio_mode(GPIO52_nPCE_1_MD);
-       pxa_gpio_mode(GPIO53_nPCE_2_MD);
-       pxa_gpio_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */
-       pxa_gpio_mode(GPIO55_nPREG_MD);
-       pxa_gpio_mode(GPIO56_nPWAIT_MD);
-       pxa_gpio_mode(GPIO57_nIOIS16_MD);
-
        /* Provide our PXA2xx specific timing routines. */
        ops->set_timing  = pxa2xx_pcmcia_set_timing;
 #ifdef CONFIG_CPU_FREQ
index e22a57a..48726e7 100644 (file)
 #include <asm/hardware.h>
 #include <asm/hardware/sa1111.h>
 #include <asm/mach-types.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 
 #include "sa1111_generic.h"
 
+static int
+lubbock_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+       /*
+        * Setup default state of GPIO outputs
+        * before we enable them as outputs.
+        */
+       GPSR(GPIO48_nPOE) =
+               GPIO_bit(GPIO48_nPOE) |
+               GPIO_bit(GPIO49_nPWE) |
+               GPIO_bit(GPIO50_nPIOR) |
+               GPIO_bit(GPIO51_nPIOW) |
+               GPIO_bit(GPIO52_nPCE_1) |
+               GPIO_bit(GPIO53_nPCE_2);
+
+       pxa_gpio_mode(GPIO48_nPOE_MD);
+       pxa_gpio_mode(GPIO49_nPWE_MD);
+       pxa_gpio_mode(GPIO50_nPIOR_MD);
+       pxa_gpio_mode(GPIO51_nPIOW_MD);
+       pxa_gpio_mode(GPIO52_nPCE_1_MD);
+       pxa_gpio_mode(GPIO53_nPCE_2_MD);
+       pxa_gpio_mode(GPIO54_pSKTSEL_MD);
+       pxa_gpio_mode(GPIO55_nPREG_MD);
+       pxa_gpio_mode(GPIO56_nPWAIT_MD);
+       pxa_gpio_mode(GPIO57_nIOIS16_MD);
+
+       return sa1111_pcmcia_hw_init(skt);
+}
+
 static int
 lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
                                const socket_state_t *state)
@@ -201,7 +231,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 
 static struct pcmcia_low_level lubbock_pcmcia_ops = {
        .owner                  = THIS_MODULE,
-       .hw_init                = sa1111_pcmcia_hw_init,
+       .hw_init                = lubbock_pcmcia_hw_init,
        .hw_shutdown            = sa1111_pcmcia_hw_shutdown,
        .socket_state           = sa1111_pcmcia_socket_state,
        .configure_socket       = lubbock_pcmcia_configure_socket,
index 6d393e7..a45fee3 100644 (file)
 
 #include "soc_common.h"
 
+/* FIXME: platform dependent resource declaration has to move out of this file */
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
 #ifdef DEBUG
 
 static int pc_debug;
@@ -448,9 +453,7 @@ soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
 
        skt->ops->set_timing(skt);
 
-       map->sys_stop -= map->sys_start;
-       map->sys_stop += res->start + map->card_start;
-       map->sys_start = res->start + map->card_start;
+       map->static_start = res->start + map->card_start;
 
        return 0;
 }
@@ -662,6 +665,7 @@ static void soc_pcmcia_cpufreq_unregister(void)
 int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
 {
        struct skt_dev_info *sinfo;
+       struct soc_pcmcia_socket *skt;
        int ret, i;
 
        down(&soc_pcmcia_sockets_lock);
@@ -679,7 +683,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
         * Initialise the per-socket structure.
         */
        for (i = 0; i < nr; i++) {
-               struct soc_pcmcia_socket *skt = &sinfo->skt[i];
+               skt = &sinfo->skt[i];
 
                skt->socket.ops = &soc_common_pcmcia_operations;
                skt->socket.owner = ops->owner;
@@ -777,7 +781,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
        goto out;
 
        do {
-               struct soc_pcmcia_socket *skt = &sinfo->skt[i];
+               skt = &sinfo->skt[i];
 
                del_timer_sync(&skt->poll_timer);
                pcmcia_unregister_socket(&skt->socket);
index 7c3bfbf..7f04a6b 100644 (file)
@@ -107,7 +107,7 @@ struct cardbus_type {
 struct yenta_socket {
        struct pci_dev *dev;
        int cb_irq, io_irq;
-       void *base;
+       void __iomem *base;
        struct timer_list poll_timer;
 
        struct pcmcia_socket socket;
index 781a4c0..f7548c4 100644 (file)
@@ -240,12 +240,14 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
 {
        struct pnp_dev *dev = to_pnp_dev(dmdev);
        int i, ret;
-       pnp_info_buffer_t *buffer = (pnp_info_buffer_t *)
-                               pnp_alloc(sizeof(pnp_info_buffer_t));
-       if (!buffer)
-               return -ENOMEM;
+       pnp_info_buffer_t *buffer;
+
        if (!dev)
                return -EINVAL;
+
+       buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t));
+       if (!buffer)
+               return -ENOMEM;
        buffer->len = PAGE_SIZE;
        buffer->buffer = buf;
        buffer->curr = buffer->buffer;
index 88fcd16..2fa4d21 100644 (file)
@@ -90,8 +90,10 @@ static int proc_read_escd(char *buf, char **start, off_t pos,
        tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL);
        if (!tmpbuf) return -ENOMEM;
 
-       if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base))
+       if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) {
+               kfree(tmpbuf);
                return -EIO;
+       }
 
        escd_size = (unsigned char)(tmpbuf[0]) + (unsigned char)(tmpbuf[1])*256;
 
@@ -168,8 +170,10 @@ static int proc_read_node(char *buf, char **start, off_t pos,
 
        node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
        if (!node) return -ENOMEM;
-       if (pnp_bios_get_dev_node(&nodenum, boot, node))
+       if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
+               kfree(node);
                return -EIO;
+       }
        len = node->size - sizeof(struct pnp_bios_node);
        memcpy(buf, node->data, len);
        kfree(node);
index f990065..7aafbf8 100644 (file)
@@ -346,12 +346,12 @@ pnpbios_parse_resource_option_data(unsigned char * p, unsigned char * end, struc
 {
        unsigned int len, tag;
        int priority = 0;
-       struct pnp_option *option;
+       struct pnp_option *option, *option_independent;
 
        if (!p)
                return NULL;
 
-       option = pnp_register_independent_option(dev);
+       option_independent = option = pnp_register_independent_option(dev);
        if (!option)
                return NULL;
 
@@ -428,9 +428,14 @@ pnpbios_parse_resource_option_data(unsigned char * p, unsigned char * end, struc
                case SMALL_TAG_ENDDEP:
                        if (len != 0)
                                goto len_err;
+                       if (option_independent == option)
+                               printk(KERN_WARNING "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n");
+                       option = option_independent;
                        break;
 
                case SMALL_TAG_END:
+                       if (option_independent != option)
+                               printk(KERN_WARNING "PnPBIOS: Missing SMALL_TAG_ENDDEP tag\n");
                        p = p + 2;
                        return (unsigned char *)p;
                        break;
index da52c86..d42015c 100644 (file)
@@ -104,4 +104,8 @@ static int __init pnp_system_init(void)
        return pnp_register_driver(&system_pnp_driver);
 }
 
-subsys_initcall(pnp_system_init);
+/**
+ * Reserve motherboard resources after PCI claim BARs,
+ * but before PCI assign resources for uninitialized PCI devices
+ */
+fs_initcall(pnp_system_init);
index ca83f9b..b7a764c 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/ctype.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -19,6 +20,7 @@
 //#define DCSSBLK_DEBUG                /* Debug messages on/off */
 #define DCSSBLK_NAME "dcssblk"
 #define DCSSBLK_MINORS_PER_DISK 1
+#define DCSSBLK_PARM_LEN 400
 
 #ifdef DCSSBLK_DEBUG
 #define PRINT_DEBUG(x...) printk(KERN_DEBUG DCSSBLK_NAME " debug: " x)
@@ -34,6 +36,8 @@ static int dcssblk_open(struct inode *inode, struct file *filp);
 static int dcssblk_release(struct inode *inode, struct file *filp);
 static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
 
+static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
+
 static int dcssblk_major;
 static struct block_device_operations dcssblk_devops = {
        .owner   = THIS_MODULE,
@@ -641,6 +645,47 @@ fail:
        return 0;
 }
 
+static void
+dcssblk_check_params(void)
+{
+       int rc, i, j, k;
+       char buf[9];
+       struct dcssblk_dev_info *dev_info;
+
+       for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0');
+            i++) {
+               for (j = i; (dcssblk_segments[j] != ',')  &&
+                           (dcssblk_segments[j] != '\0') &&
+                           (dcssblk_segments[j] != '(')  &&
+                           (j - i) < 8; j++)
+               {
+                       buf[j-i] = dcssblk_segments[j];
+               }
+               buf[j-i] = '\0';
+               rc = dcssblk_add_store(dcssblk_root_dev, buf, j-i);
+               if ((rc >= 0) && (dcssblk_segments[j] == '(')) {
+                       for (k = 0; buf[k] != '\0'; k++)
+                               buf[k] = toupper(buf[k]);
+                       if (!strncmp(&dcssblk_segments[j], "(local)", 7)) {
+                               down_read(&dcssblk_devices_sem);
+                               dev_info = dcssblk_get_device_by_name(buf);
+                               up_read(&dcssblk_devices_sem);
+                               if (dev_info)
+                                       dcssblk_shared_store(&dev_info->dev,
+                                                            "0\n", 2);
+                       }
+               }
+               while ((dcssblk_segments[j] != ',') &&
+                      (dcssblk_segments[j] != '\0'))
+               {
+                       j++;
+               }
+               if (dcssblk_segments[j] == '\0')
+                       break;
+               i = j;
+       }
+}
+
 /*
  * The init/exit functions.
  */
@@ -689,6 +734,9 @@ dcssblk_init(void)
        }
        dcssblk_major = rc;
        init_rwsem(&dcssblk_devices_sem);
+
+       dcssblk_check_params();
+
        PRINT_DEBUG("...finished!\n");
        return 0;
 }
@@ -696,4 +744,12 @@ dcssblk_init(void)
 module_init(dcssblk_init);
 module_exit(dcssblk_exit);
 
+module_param_string(segments, dcssblk_segments, DCSSBLK_PARM_LEN, 0444);
+MODULE_PARM_DESC(segments, "Name of DCSS segment(s) to be loaded, "
+                "comma-separated list, each name max. 8 chars.\n"
+                "Adding \"(local)\" to segment name equals echoing 0 to "
+                "/sys/devices/dcssblk/<segment name>/shared after loading "
+                "the segment - \n"
+                "e.g. segments=\"mydcss1,mydcss2,mydcss3(local)\"");
+
 MODULE_LICENSE("GPL");
index e92bb94..9c72ffb 100644 (file)
@@ -366,10 +366,7 @@ raw3215_tasklet(void *data)
        tty = raw->tty;
        if (tty != NULL &&
            RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
-               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   tty->ldisc.write_wakeup)
-                       (tty->ldisc.write_wakeup)(tty);
-               wake_up_interruptible(&tty->write_wait);
+               tty_wakeup(tty);
        }
 }
 
@@ -1055,10 +1052,7 @@ tty3215_flush_buffer(struct tty_struct *tty)
 
        raw = (struct raw3215_info *) tty->driver_data;
        raw3215_flush_buffer(raw);
-       wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
 }
 
 /*
index a1ad375..cd11cb1 100644 (file)
@@ -277,10 +277,7 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
        wake_up(&sclp_tty_waitq);
        /* check if the tty needs a wake up call */
        if (sclp_tty != NULL) {
-               if ((sclp_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   sclp_tty->ldisc.write_wakeup)
-                       (sclp_tty->ldisc.write_wakeup)(sclp_tty);
-               wake_up_interruptible(&sclp_tty->write_wait);
+               tty_wakeup(sclp_tty);
        }
 }
 
index 22760a1..cc143fa 100644 (file)
@@ -139,10 +139,7 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request)
        wake_up(&sclp_vt220_waitq);
        /* Check if the tty needs a wake up call */
        if (sclp_vt220_tty != NULL) {
-               if ((sclp_vt220_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   (sclp_vt220_tty->ldisc.write_wakeup != NULL))
-                       (sclp_vt220_tty->ldisc.write_wakeup)(sclp_vt220_tty);
-               wake_up_interruptible(&sclp_vt220_tty->write_wait);
+               tty_wakeup(sclp_vt220_tty);
        }
 }
 
index 29000d5..4a06c7d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
- *   $Revision: 1.31 $
+ *   $Revision: 1.33 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *                           IBM Corporation
@@ -229,7 +229,7 @@ s390_redo_validation (void)
        unsigned int irq;
 
        CIO_TRACE_EVENT (0, "redoval");
-       for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
+       for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
                int ret;
                struct subchannel *sch;
 
index 9b86522..21a75ee 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/ccwgroup.c
  *  bus driver for ccwgroup
- *   $Revision: 1.28 $
+ *   $Revision: 1.29 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                       IBM Corporation
@@ -191,14 +191,12 @@ ccwgroup_create(struct device *root,
                gdev->cdev[i]->dev.driver_data = gdev;
        del_drvdata = 1;
 
-       *gdev = (struct ccwgroup_device) {
-               .creator_id = creator_id,
-               .count = argc,
-               .dev = {
-                       .bus = &ccwgroup_bus_type,
-                       .parent = root,
-                       .release = ccwgroup_release,
-               },
+       gdev->creator_id = creator_id;
+       gdev->count = argc;
+       gdev->dev = (struct device ) {
+               .bus = &ccwgroup_bus_type,
+               .parent = root,
+               .release = ccwgroup_release,
        };
 
        snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s",
index 1670434..7e26f0f 100644 (file)
@@ -63,10 +63,6 @@ struct crw {
 #define CRW_ERC_PERRI    0x07 /* perm. error, facility init */
 #define CRW_ERC_PMOD     0x08 /* installed parameters modified */
 
-#define MCHCHK_STATUS_TO_PROCESS    0x00000001
-#define MCHCHK_STATUS_IN_PROGRESS   0x00000002
-#define MCHCHK_STATUS_WAITING       0x00000004
-
 extern __inline__ int stcrw(struct crw *pcrw )
 {
         int ccode;
index 8793138..3ad0ace 100644 (file)
 #define FSF_SERVICE_CLASS_NOT_SUPPORTED                0x00000006
 #define FSF_FCPLUN_NOT_VALID                   0x00000009
 #define FSF_ACCESS_DENIED                      0x00000010
-#define FSF_ACCESS_TYPE_NOT_VALID              0x00000011
 #define FSF_LUN_SHARING_VIOLATION               0x00000012
-#define FSF_COMMAND_ABORTED_ULP                        0x00000020
-#define FSF_COMMAND_ABORTED_ADAPTER            0x00000021
 #define FSF_FCP_COMMAND_DOES_NOT_EXIST         0x00000022
 #define FSF_DIRECTION_INDICATOR_NOT_VALID      0x00000030
-#define FSF_INBOUND_DATA_LENGTH_NOT_VALID      0x00000031 /* FIX: obsolete? */
-#define FSF_OUTBOUND_DATA_LENGTH_NOT_VALID     0x00000032 /* FIX: obsolete? */
 #define FSF_CMND_LENGTH_NOT_VALID              0x00000033
 #define FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED   0x00000040
 #define FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED    0x00000041
-#define FSF_REQUEST_BUF_NOT_VALID              0x00000042
-#define FSF_RESPONSE_BUF_NOT_VALID             0x00000043
 #define FSF_ELS_COMMAND_REJECTED               0x00000050
 #define FSF_GENERIC_COMMAND_REJECTED           0x00000051
 #define FSF_OPERATION_PARTIALLY_SUCCESSFUL     0x00000052
 #define FSF_HBA_PORTSTATE_LINKDOWN             0x00000006
 #define FSF_HBA_PORTSTATE_ERROR                        0x00000007
 
+/* IO states of adapter */
+#define FSF_IOSTAT_NPORT_RJT                   0x00000004
+#define FSF_IOSTAT_FABRIC_RJT                  0x00000005
+#define FSF_IOSTAT_LS_RJT                      0x00000009
 
 struct fsf_queue_designator;
 struct fsf_status_read_buffer;
index d45619f..1ff81be 100644 (file)
@@ -1531,8 +1531,7 @@ static void aurora_close(struct tty_struct * tty, struct file * filp)
        aurora_shutdown_port(bp, port);
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+       tty_ldisc_flush(tty);
        tty->closing = 0;
        port->event = 0;
        port->tty = 0;
@@ -1743,10 +1742,7 @@ static void aurora_flush_buffer(struct tty_struct *tty)
        port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
        restore_flags(flags);
        
-       wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
 #ifdef AURORA_DEBUG
        printk("aurora_flush_buffer: end\n");
 #endif
@@ -2223,10 +2219,7 @@ static void do_softint(void *private_)
                return;
 
        if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   tty->ldisc.write_wakeup)
-                       (tty->ldisc.write_wakeup)(tty);
-               wake_up_interruptible(&tty->write_wait);
+               tty_wakeup(tty);
        }
 #ifdef AURORA_DEBUG
        printk("do_softint: end\n");
index 37189ef..d5259f7 100644 (file)
@@ -452,7 +452,7 @@ static void fans_full_blast(void)
        }
 }
 
-#define POLL_INTERVAL  (5 * HZ)
+#define POLL_INTERVAL  (5 * 1000)
 static unsigned long last_warning_jiffies;
 static struct task_struct *kenvctrld_task;
 
@@ -468,8 +468,7 @@ static int kenvctrld(void *__unused)
                struct bbc_cpu_temperature *tp;
                struct bbc_fan_control *fp;
 
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(POLL_INTERVAL);
+               msleep_interruptible(POLL_INTERVAL);
                if (signal_pending(current))
                        break;
 
index a489c54..2dcd3cd 100644 (file)
@@ -189,13 +189,13 @@ static int wait_for_pin(struct bbc_i2c_bus *bp, u8 *status)
        while (limit-- > 0) {
                u8 val;
 
-               current->state = TASK_INTERRUPTIBLE;
+               set_current_state(TASK_INTERRUPTIBLE);
                *status = val = readb(bp->i2c_control_regs + 0);
                if ((val & I2C_PCF_PIN) == 0) {
                        ret = 0;
                        break;
                }
-               schedule_timeout(HZ/4);
+               msleep_interruptible(250);
        }
        remove_wait_queue(&bp->wq, &wait);
        bp->waiting = 0;
index 2dd778f..facbce6 100644 (file)
   Define the Driver Message Levels.
 */
 
-enum BusLogic_MessageLevel
-{
-  BusLogic_AnnounceLevel =                     0,
-  BusLogic_InfoLevel =                         1,
-  BusLogic_NoticeLevel =                       2,
-  BusLogic_WarningLevel =                      3,
-  BusLogic_ErrorLevel =                                4
+enum BusLogic_MessageLevel {
+       BusLogic_AnnounceLevel = 0,
+       BusLogic_InfoLevel = 1,
+       BusLogic_NoticeLevel = 2,
+       BusLogic_WarningLevel = 3,
+       BusLogic_ErrorLevel = 4
 };
 
-static char *BusLogic_MessageLevelMap[] =
-    { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, KERN_ERR };
+static char *BusLogic_MessageLevelMap[] = { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, KERN_ERR };
 
 
 /*
@@ -166,17 +164,15 @@ static char *BusLogic_MessageLevelMap[] =
   of I/O Addresses required by each type.
 */
 
-enum BusLogic_HostAdapterType
-{
-  BusLogic_MultiMaster =                       1,
-  BusLogic_FlashPoint =                                2
+enum BusLogic_HostAdapterType {
+       BusLogic_MultiMaster = 1,
+       BusLogic_FlashPoint = 2
 } PACKED;
 
 #define BusLogic_MultiMasterAddressCount       4
 #define BusLogic_FlashPointAddressCount                256
 
-static int BusLogic_HostAdapterAddressCount[3] =
-    { 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount };
+static int BusLogic_HostAdapterAddressCount[3] = { 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount };
 
 
 /*
@@ -206,39 +202,35 @@ static int BusLogic_HostAdapterAddressCount[3] =
   Define the possible Host Adapter Bus Types.
 */
 
-enum BusLogic_HostAdapterBusType
-{
-  BusLogic_Unknown_Bus =                       0,
-  BusLogic_ISA_Bus =                           1,
-  BusLogic_EISA_Bus =                          2,
-  BusLogic_PCI_Bus =                           3,
-  BusLogic_VESA_Bus =                          4,
-  BusLogic_MCA_Bus =                           5
+enum BusLogic_HostAdapterBusType {
+       BusLogic_Unknown_Bus = 0,
+       BusLogic_ISA_Bus = 1,
+       BusLogic_EISA_Bus = 2,
+       BusLogic_PCI_Bus = 3,
+       BusLogic_VESA_Bus = 4,
+       BusLogic_MCA_Bus = 5
 } PACKED;
 
-static char *BusLogic_HostAdapterBusNames[] =
-    { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" };
+static char *BusLogic_HostAdapterBusNames[] = { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" };
 
-static enum BusLogic_HostAdapterBusType BusLogic_HostAdapterBusTypes[] =
-{
-  BusLogic_VESA_Bus,                           /* BT-4xx */
-  BusLogic_ISA_Bus,                            /* BT-5xx */
-  BusLogic_MCA_Bus,                            /* BT-6xx */
-  BusLogic_EISA_Bus,                           /* BT-7xx */
-  BusLogic_Unknown_Bus,                                /* BT-8xx */
-  BusLogic_PCI_Bus                             /* BT-9xx */
+static enum BusLogic_HostAdapterBusType BusLogic_HostAdapterBusTypes[] = {
+       BusLogic_VESA_Bus,      /* BT-4xx */
+       BusLogic_ISA_Bus,       /* BT-5xx */
+       BusLogic_MCA_Bus,       /* BT-6xx */
+       BusLogic_EISA_Bus,      /* BT-7xx */
+       BusLogic_Unknown_Bus,   /* BT-8xx */
+       BusLogic_PCI_Bus        /* BT-9xx */
 };
 
 /*
   Define the possible Host Adapter BIOS Disk Geometry Translations.
 */
 
-enum BusLogic_BIOS_DiskGeometryTranslation
-{
-  BusLogic_BIOS_Disk_Not_Installed =           0,
-  BusLogic_BIOS_Disk_Installed_64x32 =         1,
-  BusLogic_BIOS_Disk_Installed_128x32 =                2,
-  BusLogic_BIOS_Disk_Installed_255x63 =                3
+enum BusLogic_BIOS_DiskGeometryTranslation {
+       BusLogic_BIOS_Disk_Not_Installed = 0,
+       BusLogic_BIOS_Disk_Installed_64x32 = 1,
+       BusLogic_BIOS_Disk_Installed_128x32 = 2,
+       BusLogic_BIOS_Disk_Installed_255x63 = 3
 } PACKED;
 
 
@@ -247,18 +239,17 @@ enum BusLogic_BIOS_DiskGeometryTranslation
 */
 
 typedef enum {
-  false,
-  true
+       false,
+       true
 } PACKED boolean;
 
 /*
   Define a 10^18 Statistics Byte Counter data type.
 */
 
-struct BusLogic_ByteCounter
-{
-  unsigned int Units;
-  unsigned int Billions;
+struct BusLogic_ByteCounter {
+       unsigned int Units;
+       unsigned int Billions;
 };
 
 
@@ -266,58 +257,54 @@ struct BusLogic_ByteCounter
   Define the structure for I/O Address and Bus Probing Information.
 */
 
-struct BusLogic_ProbeInfo
-{
-  enum BusLogic_HostAdapterType HostAdapterType;
-  enum BusLogic_HostAdapterBusType HostAdapterBusType;
-  unsigned long IO_Address;
-  unsigned long PCI_Address;
-  struct pci_dev *PCI_Device;
-  unsigned char Bus;
-  unsigned char Device;
-  unsigned char IRQ_Channel;
+struct BusLogic_ProbeInfo {
+       enum BusLogic_HostAdapterType HostAdapterType;
+       enum BusLogic_HostAdapterBusType HostAdapterBusType;
+       unsigned long IO_Address;
+       unsigned long PCI_Address;
+       struct pci_dev *PCI_Device;
+       unsigned char Bus;
+       unsigned char Device;
+       unsigned char IRQ_Channel;
 };
 
 /*
   Define the Probe Options.
 */
 
-struct BusLogic_ProbeOptions
-{
-  boolean NoProbe:1;                                   /* Bit 0 */
-  boolean NoProbeISA:1;                                        /* Bit 1 */
-  boolean NoProbePCI:1;                                        /* Bit 2 */
-  boolean NoSortPCI:1;                                 /* Bit 3 */
-  boolean MultiMasterFirst:1;                          /* Bit 4 */
-  boolean FlashPointFirst:1;                           /* Bit 5 */
-  boolean LimitedProbeISA:1;                           /* Bit 6 */
-  boolean Probe330:1;                                  /* Bit 7 */
-  boolean Probe334:1;                                  /* Bit 8 */
-  boolean Probe230:1;                                  /* Bit 9 */
-  boolean Probe234:1;                                  /* Bit 10 */
-  boolean Probe130:1;                                  /* Bit 11 */
-  boolean Probe134:1;                                  /* Bit 12 */
+struct BusLogic_ProbeOptions {
+       boolean NoProbe:1;      /* Bit 0 */
+       boolean NoProbeISA:1;   /* Bit 1 */
+       boolean NoProbePCI:1;   /* Bit 2 */
+       boolean NoSortPCI:1;    /* Bit 3 */
+       boolean MultiMasterFirst:1;     /* Bit 4 */
+       boolean FlashPointFirst:1;      /* Bit 5 */
+       boolean LimitedProbeISA:1;      /* Bit 6 */
+       boolean Probe330:1;     /* Bit 7 */
+       boolean Probe334:1;     /* Bit 8 */
+       boolean Probe230:1;     /* Bit 9 */
+       boolean Probe234:1;     /* Bit 10 */
+       boolean Probe130:1;     /* Bit 11 */
+       boolean Probe134:1;     /* Bit 12 */
 };
 
 /*
   Define the Global Options.
 */
 
-struct BusLogic_GlobalOptions
-{
-  boolean TraceProbe:1;                                        /* Bit 0 */
-  boolean TraceHardwareReset:1;                                /* Bit 1 */
-  boolean TraceConfiguration:1;                                /* Bit 2 */
-  boolean TraceErrors:1;                               /* Bit 3 */
+struct BusLogic_GlobalOptions {
+       boolean TraceProbe:1;   /* Bit 0 */
+       boolean TraceHardwareReset:1;   /* Bit 1 */
+       boolean TraceConfiguration:1;   /* Bit 2 */
+       boolean TraceErrors:1;  /* Bit 3 */
 };
 
 /*
   Define the Local Options.
 */
 
-struct BusLogic_LocalOptions
-{
-  boolean InhibitTargetInquiry:1;                      /* Bit 0 */
+struct BusLogic_LocalOptions {
+       boolean InhibitTargetInquiry:1; /* Bit 0 */
 };
 
 /*
@@ -335,198 +322,188 @@ struct BusLogic_LocalOptions
   Define the structure of the write-only Control Register.
 */
 
-union BusLogic_ControlRegister
-{
-  unsigned char All;
-  struct {
-    unsigned char :4;                                  /* Bits 0-3 */
-    boolean SCSIBusReset:1;                            /* Bit 4 */
-    boolean InterruptReset:1;                          /* Bit 5 */
-    boolean SoftReset:1;                               /* Bit 6 */
-    boolean HardReset:1;                               /* Bit 7 */
-  } cr;
+union BusLogic_ControlRegister {
+       unsigned char All;
+       struct {
+               unsigned char:4;        /* Bits 0-3 */
+               boolean SCSIBusReset:1; /* Bit 4 */
+               boolean InterruptReset:1;       /* Bit 5 */
+               boolean SoftReset:1;    /* Bit 6 */
+               boolean HardReset:1;    /* Bit 7 */
+       } cr;
 };
 
 /*
   Define the structure of the read-only Status Register.
 */
 
-union BusLogic_StatusRegister
-{
-  unsigned char All;
-  struct {
-    boolean CommandInvalid:1;                          /* Bit 0 */
-    boolean Reserved:1;                                        /* Bit 1 */
-    boolean DataInRegisterReady:1;                     /* Bit 2 */
-    boolean CommandParameterRegisterBusy:1;            /* Bit 3 */
-    boolean HostAdapterReady:1;                                /* Bit 4 */
-    boolean InitializationRequired:1;                  /* Bit 5 */
-    boolean DiagnosticFailure:1;                       /* Bit 6 */
-    boolean DiagnosticActive:1;                                /* Bit 7 */
-  } sr;
+union BusLogic_StatusRegister {
+       unsigned char All;
+       struct {
+               boolean CommandInvalid:1;       /* Bit 0 */
+               boolean Reserved:1;     /* Bit 1 */
+               boolean DataInRegisterReady:1;  /* Bit 2 */
+               boolean CommandParameterRegisterBusy:1; /* Bit 3 */
+               boolean HostAdapterReady:1;     /* Bit 4 */
+               boolean InitializationRequired:1;       /* Bit 5 */
+               boolean DiagnosticFailure:1;    /* Bit 6 */
+               boolean DiagnosticActive:1;     /* Bit 7 */
+       } sr;
 };
 
 /*
   Define the structure of the read-only Interrupt Register.
 */
 
-union BusLogic_InterruptRegister
-{
-  unsigned char All;
-  struct {
-    boolean IncomingMailboxLoaded:1;                   /* Bit 0 */
-    boolean OutgoingMailboxAvailable:1;                        /* Bit 1 */
-    boolean CommandComplete:1;                         /* Bit 2 */
-    boolean ExternalBusReset:1;                                /* Bit 3 */
-    unsigned char Reserved:3;                          /* Bits 4-6 */
-    boolean InterruptValid:1;                          /* Bit 7 */
-  } ir;
+union BusLogic_InterruptRegister {
+       unsigned char All;
+       struct {
+               boolean IncomingMailboxLoaded:1;        /* Bit 0 */
+               boolean OutgoingMailboxAvailable:1;     /* Bit 1 */
+               boolean CommandComplete:1;      /* Bit 2 */
+               boolean ExternalBusReset:1;     /* Bit 3 */
+               unsigned char Reserved:3;       /* Bits 4-6 */
+               boolean InterruptValid:1;       /* Bit 7 */
+       } ir;
 };
 
 /*
   Define the structure of the read-only Geometry Register.
 */
 
-union BusLogic_GeometryRegister
-{
-  unsigned char All;
-  struct {
-    enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2;/* Bits 0-1 */
-    enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2;/* Bits 2-3 */
-    unsigned char :3;                                          /* Bits 4-6 */
-    boolean ExtendedTranslationEnabled:1;                      /* Bit 7 */
-  } gr;
+union BusLogic_GeometryRegister {
+       unsigned char All;
+       struct {
+               enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2;    /* Bits 0-1 */
+               enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2;    /* Bits 2-3 */
+               unsigned char:3;        /* Bits 4-6 */
+               boolean ExtendedTranslationEnabled:1;   /* Bit 7 */
+       } gr;
 };
 
 /*
   Define the BusLogic SCSI Host Adapter Command Register Operation Codes.
 */
 
-enum BusLogic_OperationCode
-{
-  BusLogic_TestCommandCompleteInterrupt =              0x00,
-  BusLogic_InitializeMailbox =                         0x01,
-  BusLogic_ExecuteMailboxCommand =                     0x02,
-  BusLogic_ExecuteBIOSCommand =                                0x03,
-  BusLogic_InquireBoardID =                            0x04,
-  BusLogic_EnableOutgoingMailboxAvailableInt =         0x05,
-  BusLogic_SetSCSISelectionTimeout =                   0x06,
-  BusLogic_SetPreemptTimeOnBus =                       0x07,
-  BusLogic_SetTimeOffBus =                             0x08,
-  BusLogic_SetBusTransferRate =                                0x09,
-  BusLogic_InquireInstalledDevicesID0to7 =             0x0A,
-  BusLogic_InquireConfiguration =                      0x0B,
-  BusLogic_EnableTargetMode =                          0x0C,
-  BusLogic_InquireSetupInformation =                   0x0D,
-  BusLogic_WriteAdapterLocalRAM =                      0x1A,
-  BusLogic_ReadAdapterLocalRAM =                       0x1B,
-  BusLogic_WriteBusMasterChipFIFO =                    0x1C,
-  BusLogic_ReadBusMasterChipFIFO =                     0x1D,
-  BusLogic_EchoCommandData =                           0x1F,
-  BusLogic_HostAdapterDiagnostic =                     0x20,
-  BusLogic_SetAdapterOptions =                         0x21,
-  BusLogic_InquireInstalledDevicesID8to15 =            0x23,
-  BusLogic_InquireTargetDevices =                      0x24,
-  BusLogic_DisableHostAdapterInterrupt =               0x25,
-  BusLogic_InitializeExtendedMailbox =                 0x81,
-  BusLogic_ExecuteSCSICommand =                                0x83,
-  BusLogic_InquireFirmwareVersion3rdDigit =            0x84,
-  BusLogic_InquireFirmwareVersionLetter =              0x85,
-  BusLogic_InquirePCIHostAdapterInformation =          0x86,
-  BusLogic_InquireHostAdapterModelNumber =             0x8B,
-  BusLogic_InquireSynchronousPeriod =                  0x8C,
-  BusLogic_InquireExtendedSetupInformation =           0x8D,
-  BusLogic_EnableStrictRoundRobinMode =                        0x8F,
-  BusLogic_StoreHostAdapterLocalRAM =                  0x90,
-  BusLogic_FetchHostAdapterLocalRAM =                  0x91,
-  BusLogic_StoreLocalDataInEEPROM =                    0x92,
-  BusLogic_UploadAutoSCSICode =                                0x94,
-  BusLogic_ModifyIOAddress =                           0x95,
-  BusLogic_SetCCBFormat =                              0x96,
-  BusLogic_WriteInquiryBuffer =                                0x9A,
-  BusLogic_ReadInquiryBuffer =                         0x9B,
-  BusLogic_FlashROMUploadDownload =                    0xA7,
-  BusLogic_ReadSCAMData =                              0xA8,
-  BusLogic_WriteSCAMData =                             0xA9
+enum BusLogic_OperationCode {
+       BusLogic_TestCommandCompleteInterrupt = 0x00,
+       BusLogic_InitializeMailbox = 0x01,
+       BusLogic_ExecuteMailboxCommand = 0x02,
+       BusLogic_ExecuteBIOSCommand = 0x03,
+       BusLogic_InquireBoardID = 0x04,
+       BusLogic_EnableOutgoingMailboxAvailableInt = 0x05,
+       BusLogic_SetSCSISelectionTimeout = 0x06,
+       BusLogic_SetPreemptTimeOnBus = 0x07,
+       BusLogic_SetTimeOffBus = 0x08,
+       BusLogic_SetBusTransferRate = 0x09,
+       BusLogic_InquireInstalledDevicesID0to7 = 0x0A,
+       BusLogic_InquireConfiguration = 0x0B,
+       BusLogic_EnableTargetMode = 0x0C,
+       BusLogic_InquireSetupInformation = 0x0D,
+       BusLogic_WriteAdapterLocalRAM = 0x1A,
+       BusLogic_ReadAdapterLocalRAM = 0x1B,
+       BusLogic_WriteBusMasterChipFIFO = 0x1C,
+       BusLogic_ReadBusMasterChipFIFO = 0x1D,
+       BusLogic_EchoCommandData = 0x1F,
+       BusLogic_HostAdapterDiagnostic = 0x20,
+       BusLogic_SetAdapterOptions = 0x21,
+       BusLogic_InquireInstalledDevicesID8to15 = 0x23,
+       BusLogic_InquireTargetDevices = 0x24,
+       BusLogic_DisableHostAdapterInterrupt = 0x25,
+       BusLogic_InitializeExtendedMailbox = 0x81,
+       BusLogic_ExecuteSCSICommand = 0x83,
+       BusLogic_InquireFirmwareVersion3rdDigit = 0x84,
+       BusLogic_InquireFirmwareVersionLetter = 0x85,
+       BusLogic_InquirePCIHostAdapterInformation = 0x86,
+       BusLogic_InquireHostAdapterModelNumber = 0x8B,
+       BusLogic_InquireSynchronousPeriod = 0x8C,
+       BusLogic_InquireExtendedSetupInformation = 0x8D,
+       BusLogic_EnableStrictRoundRobinMode = 0x8F,
+       BusLogic_StoreHostAdapterLocalRAM = 0x90,
+       BusLogic_FetchHostAdapterLocalRAM = 0x91,
+       BusLogic_StoreLocalDataInEEPROM = 0x92,
+       BusLogic_UploadAutoSCSICode = 0x94,
+       BusLogic_ModifyIOAddress = 0x95,
+       BusLogic_SetCCBFormat = 0x96,
+       BusLogic_WriteInquiryBuffer = 0x9A,
+       BusLogic_ReadInquiryBuffer = 0x9B,
+       BusLogic_FlashROMUploadDownload = 0xA7,
+       BusLogic_ReadSCAMData = 0xA8,
+       BusLogic_WriteSCAMData = 0xA9
 };
 
 /*
   Define the Inquire Board ID reply structure.
 */
 
-struct BusLogic_BoardID
-{
-  unsigned char BoardType;                             /* Byte 0 */
-  unsigned char CustomFeatures;                                /* Byte 1 */
-  unsigned char FirmwareVersion1stDigit;               /* Byte 2 */
-  unsigned char FirmwareVersion2ndDigit;               /* Byte 3 */
+struct BusLogic_BoardID {
+       unsigned char BoardType;        /* Byte 0 */
+       unsigned char CustomFeatures;   /* Byte 1 */
+       unsigned char FirmwareVersion1stDigit;  /* Byte 2 */
+       unsigned char FirmwareVersion2ndDigit;  /* Byte 3 */
 };
 
 /*
   Define the Inquire Configuration reply structure.
 */
 
-struct BusLogic_Configuration
-{
-  unsigned char :5;                                    /* Byte 0 Bits 0-4 */
-  boolean DMA_Channel5:1;                              /* Byte 0 Bit 5 */
-  boolean DMA_Channel6:1;                              /* Byte 0 Bit 6 */
-  boolean DMA_Channel7:1;                              /* Byte 0 Bit 7 */
-  boolean IRQ_Channel9:1;                              /* Byte 1 Bit 0 */
-  boolean IRQ_Channel10:1;                             /* Byte 1 Bit 1 */
-  boolean IRQ_Channel11:1;                             /* Byte 1 Bit 2 */
-  boolean IRQ_Channel12:1;                             /* Byte 1 Bit 3 */
-  unsigned char :1;                                    /* Byte 1 Bit 4 */
-  boolean IRQ_Channel14:1;                             /* Byte 1 Bit 5 */
-  boolean IRQ_Channel15:1;                             /* Byte 1 Bit 6 */
-  unsigned char :1;                                    /* Byte 1 Bit 7 */
-  unsigned char HostAdapterID:4;                       /* Byte 2 Bits 0-3 */
-  unsigned char :4;                                    /* Byte 2 Bits 4-7 */
+struct BusLogic_Configuration {
+       unsigned char:5;        /* Byte 0 Bits 0-4 */
+       boolean DMA_Channel5:1; /* Byte 0 Bit 5 */
+       boolean DMA_Channel6:1; /* Byte 0 Bit 6 */
+       boolean DMA_Channel7:1; /* Byte 0 Bit 7 */
+       boolean IRQ_Channel9:1; /* Byte 1 Bit 0 */
+       boolean IRQ_Channel10:1;        /* Byte 1 Bit 1 */
+       boolean IRQ_Channel11:1;        /* Byte 1 Bit 2 */
+       boolean IRQ_Channel12:1;        /* Byte 1 Bit 3 */
+       unsigned char:1;        /* Byte 1 Bit 4 */
+       boolean IRQ_Channel14:1;        /* Byte 1 Bit 5 */
+       boolean IRQ_Channel15:1;        /* Byte 1 Bit 6 */
+       unsigned char:1;        /* Byte 1 Bit 7 */
+       unsigned char HostAdapterID:4;  /* Byte 2 Bits 0-3 */
+       unsigned char:4;        /* Byte 2 Bits 4-7 */
 };
 
 /*
   Define the Inquire Setup Information reply structure.
 */
 
-struct BusLogic_SynchronousValue
-{
-  unsigned char Offset:4;                              /* Bits 0-3 */
-  unsigned char TransferPeriod:3;                      /* Bits 4-6 */
-  boolean Synchronous:1;                               /* Bit 7 */
+struct BusLogic_SynchronousValue {
+       unsigned char Offset:4; /* Bits 0-3 */
+       unsigned char TransferPeriod:3; /* Bits 4-6 */
+       boolean Synchronous:1;  /* Bit 7 */
 };
 
-struct BusLogic_SetupInformation
-{
-  boolean SynchronousInitiationEnabled:1;              /* Byte 0 Bit 0 */
-  boolean ParityCheckingEnabled:1;                     /* Byte 0 Bit 1 */
-  unsigned char :6;                                    /* Byte 0 Bits 2-7 */
-  unsigned char BusTransferRate;                       /* Byte 1 */
-  unsigned char PreemptTimeOnBus;                      /* Byte 2 */
-  unsigned char TimeOffBus;                            /* Byte 3 */
-  unsigned char MailboxCount;                          /* Byte 4 */
-  unsigned char MailboxAddress[3];                     /* Bytes 5-7 */
-  struct BusLogic_SynchronousValue SynchronousValuesID0to7[8];/* Bytes 8-15 */
-  unsigned char DisconnectPermittedID0to7;             /* Byte 16 */
-  unsigned char Signature;                             /* Byte 17 */
-  unsigned char CharacterD;                            /* Byte 18 */
-  unsigned char HostBusType;                           /* Byte 19 */
-  unsigned char WideTransfersPermittedID0to7;          /* Byte 20 */
-  unsigned char WideTransfersActiveID0to7;             /* Byte 21 */
-  struct BusLogic_SynchronousValue SynchronousValuesID8to15[8]; /* Bytes 22-29 */
-  unsigned char DisconnectPermittedID8to15;            /* Byte 30 */
-  unsigned char :8;                                    /* Byte 31 */
-  unsigned char WideTransfersPermittedID8to15;         /* Byte 32 */
-  unsigned char WideTransfersActiveID8to15;            /* Byte 33 */
+struct BusLogic_SetupInformation {
+       boolean SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */
+       boolean ParityCheckingEnabled:1;        /* Byte 0 Bit 1 */
+       unsigned char:6;        /* Byte 0 Bits 2-7 */
+       unsigned char BusTransferRate;  /* Byte 1 */
+       unsigned char PreemptTimeOnBus; /* Byte 2 */
+       unsigned char TimeOffBus;       /* Byte 3 */
+       unsigned char MailboxCount;     /* Byte 4 */
+       unsigned char MailboxAddress[3];        /* Bytes 5-7 */
+       struct BusLogic_SynchronousValue SynchronousValuesID0to7[8];    /* Bytes 8-15 */
+       unsigned char DisconnectPermittedID0to7;        /* Byte 16 */
+       unsigned char Signature;        /* Byte 17 */
+       unsigned char CharacterD;       /* Byte 18 */
+       unsigned char HostBusType;      /* Byte 19 */
+       unsigned char WideTransfersPermittedID0to7;     /* Byte 20 */
+       unsigned char WideTransfersActiveID0to7;        /* Byte 21 */
+       struct BusLogic_SynchronousValue SynchronousValuesID8to15[8];   /* Bytes 22-29 */
+       unsigned char DisconnectPermittedID8to15;       /* Byte 30 */
+       unsigned char:8;        /* Byte 31 */
+       unsigned char WideTransfersPermittedID8to15;    /* Byte 32 */
+       unsigned char WideTransfersActiveID8to15;       /* Byte 33 */
 };
 
 /*
   Define the Initialize Extended Mailbox request structure.
 */
 
-struct BusLogic_ExtendedMailboxRequest
-{
-  unsigned char MailboxCount;                          /* Byte 0 */
-  u32 BaseMailboxAddress;                              /* Bytes 1-4 */
+struct BusLogic_ExtendedMailboxRequest {
+       unsigned char MailboxCount;     /* Byte 0 */
+       u32 BaseMailboxAddress; /* Bytes 1-4 */
 } PACKED;
 
 
@@ -536,67 +513,63 @@ struct BusLogic_ExtendedMailboxRequest
   the Modify I/O Address command.
 */
 
-enum BusLogic_ISACompatibleIOPort
-{
-  BusLogic_IO_330 =                            0,
-  BusLogic_IO_334 =                            1,
-  BusLogic_IO_230 =                            2,
-  BusLogic_IO_234 =                            3,
-  BusLogic_IO_130 =                            4,
-  BusLogic_IO_134 =                            5,
-  BusLogic_IO_Disable =                                6,
-  BusLogic_IO_Disable2 =                       7
+enum BusLogic_ISACompatibleIOPort {
+       BusLogic_IO_330 = 0,
+       BusLogic_IO_334 = 1,
+       BusLogic_IO_230 = 2,
+       BusLogic_IO_234 = 3,
+       BusLogic_IO_130 = 4,
+       BusLogic_IO_134 = 5,
+       BusLogic_IO_Disable = 6,
+       BusLogic_IO_Disable2 = 7
 } PACKED;
 
-struct BusLogic_PCIHostAdapterInformation
-{
-  enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort;/* Byte 0 */
-  unsigned char PCIAssignedIRQChannel;                 /* Byte 1 */
-  boolean LowByteTerminated:1;                         /* Byte 2 Bit 0 */
-  boolean HighByteTerminated:1;                                /* Byte 2 Bit 1 */
-  unsigned char :2;                                    /* Byte 2 Bits 2-3 */
-  boolean JP1:1;                                       /* Byte 2 Bit 4 */
-  boolean JP2:1;                                       /* Byte 2 Bit 5 */
-  boolean JP3:1;                                       /* Byte 2 Bit 6 */
-  boolean GenericInfoValid:1;                          /* Byte 2 Bit 7 */
-  unsigned char :8;                                    /* Byte 3 */
+struct BusLogic_PCIHostAdapterInformation {
+       enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort;  /* Byte 0 */
+       unsigned char PCIAssignedIRQChannel;    /* Byte 1 */
+       boolean LowByteTerminated:1;    /* Byte 2 Bit 0 */
+       boolean HighByteTerminated:1;   /* Byte 2 Bit 1 */
+       unsigned char:2;        /* Byte 2 Bits 2-3 */
+       boolean JP1:1;          /* Byte 2 Bit 4 */
+       boolean JP2:1;          /* Byte 2 Bit 5 */
+       boolean JP3:1;          /* Byte 2 Bit 6 */
+       boolean GenericInfoValid:1;     /* Byte 2 Bit 7 */
+       unsigned char:8;        /* Byte 3 */
 };
 
 /*
   Define the Inquire Extended Setup Information reply structure.
 */
 
-struct BusLogic_ExtendedSetupInformation
-{
-  unsigned char BusType;                               /* Byte 0 */
-  unsigned char BIOS_Address;                          /* Byte 1 */
-  unsigned short ScatterGatherLimit;                   /* Bytes 2-3 */
-  unsigned char MailboxCount;                          /* Byte 4 */
-  u32 BaseMailboxAddress;                              /* Bytes 5-8 */
-  struct {
-           unsigned char :2;                           /* Byte 9 Bits 0-1 */
-          boolean FastOnEISA:1;                        /* Byte 9 Bit 2 */
-          unsigned char :3;                            /* Byte 9 Bits 3-5 */
-          boolean LevelSensitiveInterrupt:1;           /* Byte 9 Bit 6 */
-          unsigned char :1;                            /* Byte 9 Bit 7 */
-  } Misc;
-  unsigned char FirmwareRevision[3];                   /* Bytes 10-12 */
-  boolean HostWideSCSI:1;                              /* Byte 13 Bit 0 */
-  boolean HostDifferentialSCSI:1;                      /* Byte 13 Bit 1 */
-  boolean HostSupportsSCAM:1;                          /* Byte 13 Bit 2 */
-  boolean HostUltraSCSI:1;                             /* Byte 13 Bit 3 */
-  boolean HostSmartTermination:1;                      /* Byte 13 Bit 4 */
-  unsigned char :3;                                    /* Byte 13 Bits 5-7 */
+struct BusLogic_ExtendedSetupInformation {
+       unsigned char BusType;  /* Byte 0 */
+       unsigned char BIOS_Address;     /* Byte 1 */
+       unsigned short ScatterGatherLimit;      /* Bytes 2-3 */
+       unsigned char MailboxCount;     /* Byte 4 */
+       u32 BaseMailboxAddress; /* Bytes 5-8 */
+       struct {
+               unsigned char:2;        /* Byte 9 Bits 0-1 */
+               boolean FastOnEISA:1;   /* Byte 9 Bit 2 */
+               unsigned char:3;        /* Byte 9 Bits 3-5 */
+               boolean LevelSensitiveInterrupt:1;      /* Byte 9 Bit 6 */
+               unsigned char:1;        /* Byte 9 Bit 7 */
+       } Misc;
+       unsigned char FirmwareRevision[3];      /* Bytes 10-12 */
+       boolean HostWideSCSI:1; /* Byte 13 Bit 0 */
+       boolean HostDifferentialSCSI:1; /* Byte 13 Bit 1 */
+       boolean HostSupportsSCAM:1;     /* Byte 13 Bit 2 */
+       boolean HostUltraSCSI:1;        /* Byte 13 Bit 3 */
+       boolean HostSmartTermination:1; /* Byte 13 Bit 4 */
+       unsigned char:3;        /* Byte 13 Bits 5-7 */
 } PACKED;
 
 /*
   Define the Enable Strict Round Robin Mode request type.
 */
 
-enum BusLogic_RoundRobinModeRequest
-{
-  BusLogic_AggressiveRoundRobinMode =          0,
-  BusLogic_StrictRoundRobinMode =              1
+enum BusLogic_RoundRobinModeRequest {
+       BusLogic_AggressiveRoundRobinMode = 0,
+       BusLogic_StrictRoundRobinMode = 1
 } PACKED;
 
 
@@ -607,96 +580,93 @@ enum BusLogic_RoundRobinModeRequest
 #define BusLogic_BIOS_BaseOffset               0
 #define BusLogic_AutoSCSI_BaseOffset           64
 
-struct BusLogic_FetchHostAdapterLocalRAMRequest
-{
-  unsigned char ByteOffset;                            /* Byte 0 */
-  unsigned char ByteCount;                             /* Byte 1 */
+struct BusLogic_FetchHostAdapterLocalRAMRequest {
+       unsigned char ByteOffset;       /* Byte 0 */
+       unsigned char ByteCount;        /* Byte 1 */
 };
 
 /*
   Define the Host Adapter Local RAM AutoSCSI structure.
 */
 
-struct BusLogic_AutoSCSIData
-{
-  unsigned char InternalFactorySignature[2];           /* Bytes 0-1 */
-  unsigned char InformationByteCount;                  /* Byte 2 */
-  unsigned char HostAdapterType[6];                    /* Bytes 3-8 */
-  unsigned char :8;                                    /* Byte 9 */
-  boolean FloppyEnabled:1;                             /* Byte 10 Bit 0 */
-  boolean FloppySecondary:1;                           /* Byte 10 Bit 1 */
-  boolean LevelSensitiveInterrupt:1;                   /* Byte 10 Bit 2 */
-  unsigned char :2;                                    /* Byte 10 Bits 3-4 */
-  unsigned char SystemRAMAreaForBIOS:3;                        /* Byte 10 Bits 5-7 */
-  unsigned char DMA_Channel:7;                         /* Byte 11 Bits 0-6 */
-  boolean DMA_AutoConfiguration:1;                     /* Byte 11 Bit 7 */
-  unsigned char IRQ_Channel:7;                         /* Byte 12 Bits 0-6 */
-  boolean IRQ_AutoConfiguration:1;                     /* Byte 12 Bit 7 */
-  unsigned char DMA_TransferRate;                      /* Byte 13 */
-  unsigned char SCSI_ID;                               /* Byte 14 */
-  boolean LowByteTerminated:1;                         /* Byte 15 Bit 0 */
-  boolean ParityCheckingEnabled:1;                     /* Byte 15 Bit 1 */
-  boolean HighByteTerminated:1;                                /* Byte 15 Bit 2 */
-  boolean NoisyCablingEnvironment:1;                   /* Byte 15 Bit 3 */
-  boolean FastSynchronousNegotiation:1;                        /* Byte 15 Bit 4 */
-  boolean BusResetEnabled:1;                           /* Byte 15 Bit 5 */
-  boolean :1;                                          /* Byte 15 Bit 6 */
-  boolean ActiveNegationEnabled:1;                     /* Byte 15 Bit 7 */
-  unsigned char BusOnDelay;                            /* Byte 16 */
-  unsigned char BusOffDelay;                           /* Byte 17 */
-  boolean HostAdapterBIOSEnabled:1;                    /* Byte 18 Bit 0 */
-  boolean BIOSRedirectionOfINT19Enabled:1;             /* Byte 18 Bit 1 */
-  boolean ExtendedTranslationEnabled:1;                        /* Byte 18 Bit 2 */
-  boolean MapRemovableAsFixedEnabled:1;                        /* Byte 18 Bit 3 */
-  boolean :1;                                          /* Byte 18 Bit 4 */
-  boolean BIOSSupportsMoreThan2DrivesEnabled:1;                /* Byte 18 Bit 5 */
-  boolean BIOSInterruptModeEnabled:1;                  /* Byte 18 Bit 6 */
-  boolean FlopticalSupportEnabled:1;                   /* Byte 19 Bit 7 */
-  unsigned short DeviceEnabled;                                /* Bytes 19-20 */
-  unsigned short WidePermitted;                                /* Bytes 21-22 */
-  unsigned short FastPermitted;                                /* Bytes 23-24 */
-  unsigned short SynchronousPermitted;                 /* Bytes 25-26 */
-  unsigned short DisconnectPermitted;                  /* Bytes 27-28 */
-  unsigned short SendStartUnitCommand;                 /* Bytes 29-30 */
-  unsigned short IgnoreInBIOSScan;                     /* Bytes 31-32 */
-  unsigned char PCIInterruptPin:2;                     /* Byte 33 Bits 0-1 */
-  unsigned char HostAdapterIOPortAddress:2;            /* Byte 33 Bits 2-3 */
-  boolean StrictRoundRobinModeEnabled:1;               /* Byte 33 Bit 4 */
-  boolean VESABusSpeedGreaterThan33MHz:1;              /* Byte 33 Bit 5 */
-  boolean VESABurstWriteEnabled:1;                     /* Byte 33 Bit 6 */
-  boolean VESABurstReadEnabled:1;                      /* Byte 33 Bit 7 */
-  unsigned short UltraPermitted;                       /* Bytes 34-35 */
-  unsigned int :32;                                    /* Bytes 36-39 */
-  unsigned char :8;                                    /* Byte 40 */
-  unsigned char AutoSCSIMaximumLUN;                    /* Byte 41 */
-  boolean :1;                                          /* Byte 42 Bit 0 */
-  boolean SCAM_Dominant:1;                             /* Byte 42 Bit 1 */
-  boolean SCAM_Enabled:1;                              /* Byte 42 Bit 2 */
-  boolean SCAM_Level2:1;                               /* Byte 42 Bit 3 */
-  unsigned char :4;                                    /* Byte 42 Bits 4-7 */
-  boolean INT13ExtensionEnabled:1;                     /* Byte 43 Bit 0 */
-  boolean :1;                                          /* Byte 43 Bit 1 */
-  boolean CDROMBootEnabled:1;                          /* Byte 43 Bit 2 */
-  unsigned char :5;                                    /* Byte 43 Bits 3-7 */
-  unsigned char BootTargetID:4;                                /* Byte 44 Bits 0-3 */
-  unsigned char BootChannel:4;                         /* Byte 44 Bits 4-7 */
-  unsigned char ForceBusDeviceScanningOrder:1;         /* Byte 45 Bit 0 */
-  unsigned char :7;                                    /* Byte 45 Bits 1-7 */
-  unsigned short NonTaggedToAlternateLUNPermitted;     /* Bytes 46-47 */
-  unsigned short RenegotiateSyncAfterCheckCondition;   /* Bytes 48-49 */
-  unsigned char Reserved[10];                          /* Bytes 50-59 */
-  unsigned char ManufacturingDiagnostic[2];            /* Bytes 60-61 */
-  unsigned short Checksum;                             /* Bytes 62-63 */
+struct BusLogic_AutoSCSIData {
+       unsigned char InternalFactorySignature[2];      /* Bytes 0-1 */
+       unsigned char InformationByteCount;     /* Byte 2 */
+       unsigned char HostAdapterType[6];       /* Bytes 3-8 */
+       unsigned char:8;        /* Byte 9 */
+       boolean FloppyEnabled:1;        /* Byte 10 Bit 0 */
+       boolean FloppySecondary:1;      /* Byte 10 Bit 1 */
+       boolean LevelSensitiveInterrupt:1;      /* Byte 10 Bit 2 */
+       unsigned char:2;        /* Byte 10 Bits 3-4 */
+       unsigned char SystemRAMAreaForBIOS:3;   /* Byte 10 Bits 5-7 */
+       unsigned char DMA_Channel:7;    /* Byte 11 Bits 0-6 */
+       boolean DMA_AutoConfiguration:1;        /* Byte 11 Bit 7 */
+       unsigned char IRQ_Channel:7;    /* Byte 12 Bits 0-6 */
+       boolean IRQ_AutoConfiguration:1;        /* Byte 12 Bit 7 */
+       unsigned char DMA_TransferRate; /* Byte 13 */
+       unsigned char SCSI_ID;  /* Byte 14 */
+       boolean LowByteTerminated:1;    /* Byte 15 Bit 0 */
+       boolean ParityCheckingEnabled:1;        /* Byte 15 Bit 1 */
+       boolean HighByteTerminated:1;   /* Byte 15 Bit 2 */
+       boolean NoisyCablingEnvironment:1;      /* Byte 15 Bit 3 */
+       boolean FastSynchronousNegotiation:1;   /* Byte 15 Bit 4 */
+       boolean BusResetEnabled:1;      /* Byte 15 Bit 5 */
+        boolean:1;             /* Byte 15 Bit 6 */
+       boolean ActiveNegationEnabled:1;        /* Byte 15 Bit 7 */
+       unsigned char BusOnDelay;       /* Byte 16 */
+       unsigned char BusOffDelay;      /* Byte 17 */
+       boolean HostAdapterBIOSEnabled:1;       /* Byte 18 Bit 0 */
+       boolean BIOSRedirectionOfINT19Enabled:1;        /* Byte 18 Bit 1 */
+       boolean ExtendedTranslationEnabled:1;   /* Byte 18 Bit 2 */
+       boolean MapRemovableAsFixedEnabled:1;   /* Byte 18 Bit 3 */
+        boolean:1;             /* Byte 18 Bit 4 */
+       boolean BIOSSupportsMoreThan2DrivesEnabled:1;   /* Byte 18 Bit 5 */
+       boolean BIOSInterruptModeEnabled:1;     /* Byte 18 Bit 6 */
+       boolean FlopticalSupportEnabled:1;      /* Byte 19 Bit 7 */
+       unsigned short DeviceEnabled;   /* Bytes 19-20 */
+       unsigned short WidePermitted;   /* Bytes 21-22 */
+       unsigned short FastPermitted;   /* Bytes 23-24 */
+       unsigned short SynchronousPermitted;    /* Bytes 25-26 */
+       unsigned short DisconnectPermitted;     /* Bytes 27-28 */
+       unsigned short SendStartUnitCommand;    /* Bytes 29-30 */
+       unsigned short IgnoreInBIOSScan;        /* Bytes 31-32 */
+       unsigned char PCIInterruptPin:2;        /* Byte 33 Bits 0-1 */
+       unsigned char HostAdapterIOPortAddress:2;       /* Byte 33 Bits 2-3 */
+       boolean StrictRoundRobinModeEnabled:1;  /* Byte 33 Bit 4 */
+       boolean VESABusSpeedGreaterThan33MHz:1; /* Byte 33 Bit 5 */
+       boolean VESABurstWriteEnabled:1;        /* Byte 33 Bit 6 */
+       boolean VESABurstReadEnabled:1; /* Byte 33 Bit 7 */
+       unsigned short UltraPermitted;  /* Bytes 34-35 */
+       unsigned int:32;        /* Bytes 36-39 */
+       unsigned char:8;        /* Byte 40 */
+       unsigned char AutoSCSIMaximumLUN;       /* Byte 41 */
+        boolean:1;             /* Byte 42 Bit 0 */
+       boolean SCAM_Dominant:1;        /* Byte 42 Bit 1 */
+       boolean SCAM_Enabled:1; /* Byte 42 Bit 2 */
+       boolean SCAM_Level2:1;  /* Byte 42 Bit 3 */
+       unsigned char:4;        /* Byte 42 Bits 4-7 */
+       boolean INT13ExtensionEnabled:1;        /* Byte 43 Bit 0 */
+        boolean:1;             /* Byte 43 Bit 1 */
+       boolean CDROMBootEnabled:1;     /* Byte 43 Bit 2 */
+       unsigned char:5;        /* Byte 43 Bits 3-7 */
+       unsigned char BootTargetID:4;   /* Byte 44 Bits 0-3 */
+       unsigned char BootChannel:4;    /* Byte 44 Bits 4-7 */
+       unsigned char ForceBusDeviceScanningOrder:1;    /* Byte 45 Bit 0 */
+       unsigned char:7;        /* Byte 45 Bits 1-7 */
+       unsigned short NonTaggedToAlternateLUNPermitted;        /* Bytes 46-47 */
+       unsigned short RenegotiateSyncAfterCheckCondition;      /* Bytes 48-49 */
+       unsigned char Reserved[10];     /* Bytes 50-59 */
+       unsigned char ManufacturingDiagnostic[2];       /* Bytes 60-61 */
+       unsigned short Checksum;        /* Bytes 62-63 */
 } PACKED;
 
 /*
   Define the Host Adapter Local RAM Auto SCSI Byte 45 structure.
 */
 
-struct BusLogic_AutoSCSIByte45
-{
-  unsigned char ForceBusDeviceScanningOrder:1;         /* Bit 0 */
-  unsigned char :7;                                    /* Bits 1-7 */
+struct BusLogic_AutoSCSIByte45 {
+       unsigned char ForceBusDeviceScanningOrder:1;    /* Bit 0 */
+       unsigned char:7;        /* Bits 1-7 */
 };
 
 /*
@@ -705,12 +675,11 @@ struct BusLogic_AutoSCSIByte45
 
 #define BusLogic_BIOS_DriveMapOffset           17
 
-struct BusLogic_BIOSDriveMapByte
-{
-  unsigned char TargetIDBit3:1;                                /* Bit 0 */
-  unsigned char :2;                                    /* Bits 1-2 */
-  enum BusLogic_BIOS_DiskGeometryTranslation DiskGeometry:2; /* Bits 3-4 */
-  unsigned char TargetID:3;                            /* Bits 5-7 */
+struct BusLogic_BIOSDriveMapByte {
+       unsigned char TargetIDBit3:1;   /* Bit 0 */
+       unsigned char:2;        /* Bits 1-2 */
+       enum BusLogic_BIOS_DiskGeometryTranslation DiskGeometry:2;      /* Bits 3-4 */
+       unsigned char TargetID:3;       /* Bits 5-7 */
 };
 
 /*
@@ -718,21 +687,19 @@ struct BusLogic_BIOSDriveMapByte
   necessary to support more than 8 Logical Units per Target Device.
 */
 
-enum BusLogic_SetCCBFormatRequest
-{
-  BusLogic_LegacyLUNFormatCCB =                        0,
-  BusLogic_ExtendedLUNFormatCCB =              1
+enum BusLogic_SetCCBFormatRequest {
+       BusLogic_LegacyLUNFormatCCB = 0,
+       BusLogic_ExtendedLUNFormatCCB = 1
 } PACKED;
 
 /*
   Define the Outgoing Mailbox Action Codes.
 */
 
-enum BusLogic_ActionCode
-{
-  BusLogic_OutgoingMailboxFree =               0x00,
-  BusLogic_MailboxStartCommand =               0x01,
-  BusLogic_MailboxAbortCommand =               0x02
+enum BusLogic_ActionCode {
+       BusLogic_OutgoingMailboxFree = 0x00,
+       BusLogic_MailboxStartCommand = 0x01,
+       BusLogic_MailboxAbortCommand = 0x02
 } PACKED;
 
 
@@ -742,28 +709,26 @@ enum BusLogic_ActionCode
   completion codes are stored in the CCB; it only uses codes 1, 2, 4, and 5.
 */
 
-enum BusLogic_CompletionCode
-{
-  BusLogic_IncomingMailboxFree =               0x00,
-  BusLogic_CommandCompletedWithoutError =      0x01,
-  BusLogic_CommandAbortedAtHostRequest =       0x02,
-  BusLogic_AbortedCommandNotFound =            0x03,
-  BusLogic_CommandCompletedWithError =         0x04,
-  BusLogic_InvalidCCB =                                0x05
+enum BusLogic_CompletionCode {
+       BusLogic_IncomingMailboxFree = 0x00,
+       BusLogic_CommandCompletedWithoutError = 0x01,
+       BusLogic_CommandAbortedAtHostRequest = 0x02,
+       BusLogic_AbortedCommandNotFound = 0x03,
+       BusLogic_CommandCompletedWithError = 0x04,
+       BusLogic_InvalidCCB = 0x05
 } PACKED;
 
 /*
   Define the Command Control Block (CCB) Opcodes.
 */
 
-enum BusLogic_CCB_Opcode
-{
-  BusLogic_InitiatorCCB =                      0x00,
-  BusLogic_TargetCCB =                         0x01,
-  BusLogic_InitiatorCCB_ScatterGather =                0x02,
-  BusLogic_InitiatorCCB_ResidualDataLength =   0x03,
-  BusLogic_InitiatorCCB_ScatterGatherResidual =        0x04,
-  BusLogic_BusDeviceReset =                    0x81
+enum BusLogic_CCB_Opcode {
+       BusLogic_InitiatorCCB = 0x00,
+       BusLogic_TargetCCB = 0x01,
+       BusLogic_InitiatorCCB_ScatterGather = 0x02,
+       BusLogic_InitiatorCCB_ResidualDataLength = 0x03,
+       BusLogic_InitiatorCCB_ScatterGatherResidual = 0x04,
+       BusLogic_BusDeviceReset = 0x81
 } PACKED;
 
 
@@ -771,12 +736,11 @@ enum BusLogic_CCB_Opcode
   Define the CCB Data Direction Codes.
 */
 
-enum BusLogic_DataDirection
-{
-  BusLogic_UncheckedDataTransfer =             0,
-  BusLogic_DataInLengthChecked =               1,
-  BusLogic_DataOutLengthChecked =              2,
-  BusLogic_NoDataTransfer =                    3
+enum BusLogic_DataDirection {
+       BusLogic_UncheckedDataTransfer = 0,
+       BusLogic_DataInLengthChecked = 1,
+       BusLogic_DataOutLengthChecked = 2,
+       BusLogic_NoDataTransfer = 3
 };
 
 
@@ -785,33 +749,32 @@ enum BusLogic_DataDirection
   return status code 0x0C; it uses 0x12 for both overruns and underruns.
 */
 
-enum BusLogic_HostAdapterStatus
-{
-  BusLogic_CommandCompletedNormally =          0x00,
-  BusLogic_LinkedCommandCompleted =            0x0A,
-  BusLogic_LinkedCommandCompletedWithFlag =    0x0B,
-  BusLogic_DataUnderRun =                      0x0C,
-  BusLogic_SCSISelectionTimeout =              0x11,
-  BusLogic_DataOverRun =                       0x12,
-  BusLogic_UnexpectedBusFree =                 0x13,
-  BusLogic_InvalidBusPhaseRequested =          0x14,
-  BusLogic_InvalidOutgoingMailboxActionCode =  0x15,
-  BusLogic_InvalidCommandOperationCode =       0x16,
-  BusLogic_LinkedCCBhasInvalidLUN =            0x17,
-  BusLogic_InvalidCommandParameter =           0x1A,
-  BusLogic_AutoRequestSenseFailed =            0x1B,
-  BusLogic_TaggedQueuingMessageRejected =      0x1C,
-  BusLogic_UnsupportedMessageReceived =                0x1D,
-  BusLogic_HostAdapterHardwareFailed =         0x20,
-  BusLogic_TargetFailedResponseToATN =         0x21,
-  BusLogic_HostAdapterAssertedRST =            0x22,
-  BusLogic_OtherDeviceAssertedRST =            0x23,
-  BusLogic_TargetDeviceReconnectedImproperly = 0x24,
-  BusLogic_HostAdapterAssertedBusDeviceReset = 0x25,
-  BusLogic_AbortQueueGenerated =               0x26,
-  BusLogic_HostAdapterSoftwareError =          0x27,
-  BusLogic_HostAdapterHardwareTimeoutError =   0x30,
-  BusLogic_SCSIParityErrorDetected =           0x34
+enum BusLogic_HostAdapterStatus {
+       BusLogic_CommandCompletedNormally = 0x00,
+       BusLogic_LinkedCommandCompleted = 0x0A,
+       BusLogic_LinkedCommandCompletedWithFlag = 0x0B,
+       BusLogic_DataUnderRun = 0x0C,
+       BusLogic_SCSISelectionTimeout = 0x11,
+       BusLogic_DataOverRun = 0x12,
+       BusLogic_UnexpectedBusFree = 0x13,
+       BusLogic_InvalidBusPhaseRequested = 0x14,
+       BusLogic_InvalidOutgoingMailboxActionCode = 0x15,
+       BusLogic_InvalidCommandOperationCode = 0x16,
+       BusLogic_LinkedCCBhasInvalidLUN = 0x17,
+       BusLogic_InvalidCommandParameter = 0x1A,
+       BusLogic_AutoRequestSenseFailed = 0x1B,
+       BusLogic_TaggedQueuingMessageRejected = 0x1C,
+       BusLogic_UnsupportedMessageReceived = 0x1D,
+       BusLogic_HostAdapterHardwareFailed = 0x20,
+       BusLogic_TargetFailedResponseToATN = 0x21,
+       BusLogic_HostAdapterAssertedRST = 0x22,
+       BusLogic_OtherDeviceAssertedRST = 0x23,
+       BusLogic_TargetDeviceReconnectedImproperly = 0x24,
+       BusLogic_HostAdapterAssertedBusDeviceReset = 0x25,
+       BusLogic_AbortQueueGenerated = 0x26,
+       BusLogic_HostAdapterSoftwareError = 0x27,
+       BusLogic_HostAdapterHardwareTimeoutError = 0x30,
+       BusLogic_SCSIParityErrorDetected = 0x34
 } PACKED;
 
 
@@ -819,23 +782,21 @@ enum BusLogic_HostAdapterStatus
   Define the SCSI Target Device Status Codes.
 */
 
-enum BusLogic_TargetDeviceStatus
-{
-  BusLogic_OperationGood =                     0x00,
-  BusLogic_CheckCondition =                    0x02,
-  BusLogic_DeviceBusy =                                0x08
+enum BusLogic_TargetDeviceStatus {
+       BusLogic_OperationGood = 0x00,
+       BusLogic_CheckCondition = 0x02,
+       BusLogic_DeviceBusy = 0x08
 } PACKED;
 
 /*
   Define the Queue Tag Codes.
 */
 
-enum BusLogic_QueueTag
-{
-  BusLogic_SimpleQueueTag =                    0,
-  BusLogic_HeadOfQueueTag =                    1,
-  BusLogic_OrderedQueueTag =                   2,
-  BusLogic_ReservedQT =                                3
+enum BusLogic_QueueTag {
+       BusLogic_SimpleQueueTag = 0,
+       BusLogic_HeadOfQueueTag = 1,
+       BusLogic_OrderedQueueTag = 2,
+       BusLogic_ReservedQT = 3
 };
 
 /*
@@ -852,22 +813,20 @@ typedef unsigned char SCSI_CDB_T[BusLogic_CDB_MaxLength];
   Firmware Interface and the FlashPoint SCCB Manager.
 */
 
-struct BusLogic_ScatterGatherSegment
-{
-  u32 SegmentByteCount;                                        /* Bytes 0-3 */
-  u32 SegmentDataPointer;                              /* Bytes 4-7 */
+struct BusLogic_ScatterGatherSegment {
+       u32 SegmentByteCount;   /* Bytes 0-3 */
+       u32 SegmentDataPointer; /* Bytes 4-7 */
 };
 
 /*
   Define the Driver CCB Status Codes.
 */
 
-enum BusLogic_CCB_Status
-{
-  BusLogic_CCB_Free =                          0,
-  BusLogic_CCB_Active =                                1,
-  BusLogic_CCB_Completed =                     2,
-  BusLogic_CCB_Reset =                         3
+enum BusLogic_CCB_Status {
+       BusLogic_CCB_Free = 0,
+       BusLogic_CCB_Active = 1,
+       BusLogic_CCB_Completed = 2,
+       BusLogic_CCB_Reset = 3
 } PACKED;
 
 
@@ -890,82 +849,79 @@ enum BusLogic_CCB_Status
   32 Logical Units per Target Device.
 */
 
-struct BusLogic_CCB
-{
-  /*
-    MultiMaster Firmware and FlashPoint SCCB Manager Common Portion.
-  */
-  enum BusLogic_CCB_Opcode Opcode;                     /* Byte 0 */
-  unsigned char :3;                                    /* Byte 1 Bits 0-2 */
-  enum BusLogic_DataDirection DataDirection:2;         /* Byte 1 Bits 3-4 */
-  boolean TagEnable:1;                                 /* Byte 1 Bit 5 */
-  enum BusLogic_QueueTag QueueTag:2;                   /* Byte 1 Bits 6-7 */
-  unsigned char CDB_Length;                            /* Byte 2 */
-  unsigned char SenseDataLength;                       /* Byte 3 */
-  u32 DataLength;                                      /* Bytes 4-7 */
-  u32 DataPointer;                                     /* Bytes 8-11 */
-  unsigned char :8;                                    /* Byte 12 */
-  unsigned char :8;                                    /* Byte 13 */
-  enum BusLogic_HostAdapterStatus HostAdapterStatus;   /* Byte 14 */
-  enum BusLogic_TargetDeviceStatus TargetDeviceStatus; /* Byte 15 */
-  unsigned char TargetID;                              /* Byte 16 */
-  unsigned char LogicalUnit:5;                         /* Byte 17 Bits 0-4 */
-  boolean LegacyTagEnable:1;                           /* Byte 17 Bit 5 */
-  enum BusLogic_QueueTag LegacyQueueTag:2;             /* Byte 17 Bits 6-7 */
-  SCSI_CDB_T CDB;                                      /* Bytes 18-29 */
-  unsigned char :8;                                    /* Byte 30 */
-  unsigned char :8;                                    /* Byte 31 */
-  unsigned int :32;                                    /* Bytes 32-35 */
-  u32 SenseDataPointer;                                        /* Bytes 36-39 */
-  /*
-    FlashPoint SCCB Manager Defined Portion.
-  */
-  void (*CallbackFunction)(struct BusLogic_CCB *);     /* Bytes 40-43 */
-  u32 BaseAddress;                                     /* Bytes 44-47 */
-  enum BusLogic_CompletionCode CompletionCode;         /* Byte 48 */
+struct BusLogic_CCB {
+       /*
+          MultiMaster Firmware and FlashPoint SCCB Manager Common Portion.
+        */
+       enum BusLogic_CCB_Opcode Opcode;        /* Byte 0 */
+       unsigned char:3;        /* Byte 1 Bits 0-2 */
+       enum BusLogic_DataDirection DataDirection:2;    /* Byte 1 Bits 3-4 */
+       boolean TagEnable:1;    /* Byte 1 Bit 5 */
+       enum BusLogic_QueueTag QueueTag:2;      /* Byte 1 Bits 6-7 */
+       unsigned char CDB_Length;       /* Byte 2 */
+       unsigned char SenseDataLength;  /* Byte 3 */
+       u32 DataLength;         /* Bytes 4-7 */
+       u32 DataPointer;        /* Bytes 8-11 */
+       unsigned char:8;        /* Byte 12 */
+       unsigned char:8;        /* Byte 13 */
+       enum BusLogic_HostAdapterStatus HostAdapterStatus;      /* Byte 14 */
+       enum BusLogic_TargetDeviceStatus TargetDeviceStatus;    /* Byte 15 */
+       unsigned char TargetID; /* Byte 16 */
+       unsigned char LogicalUnit:5;    /* Byte 17 Bits 0-4 */
+       boolean LegacyTagEnable:1;      /* Byte 17 Bit 5 */
+       enum BusLogic_QueueTag LegacyQueueTag:2;        /* Byte 17 Bits 6-7 */
+       SCSI_CDB_T CDB;         /* Bytes 18-29 */
+       unsigned char:8;        /* Byte 30 */
+       unsigned char:8;        /* Byte 31 */
+       unsigned int:32;        /* Bytes 32-35 */
+       u32 SenseDataPointer;   /* Bytes 36-39 */
+       /*
+          FlashPoint SCCB Manager Defined Portion.
+        */
+       void (*CallbackFunction) (struct BusLogic_CCB *);       /* Bytes 40-43 */
+       u32 BaseAddress;        /* Bytes 44-47 */
+       enum BusLogic_CompletionCode CompletionCode;    /* Byte 48 */
 #ifndef CONFIG_SCSI_OMIT_FLASHPOINT
-  unsigned char :8;                                    /* Byte 49 */
-  unsigned short OS_Flags;                             /* Bytes 50-51 */
-  unsigned char Private[48];                           /* Bytes 52-99 */
+       unsigned char:8;        /* Byte 49 */
+       unsigned short OS_Flags;        /* Bytes 50-51 */
+       unsigned char Private[48];      /* Bytes 52-99 */
 #endif
-  /*
-    BusLogic Linux Driver Defined Portion.
-  */
-  dma_addr_t AllocationGroupHead;
-  unsigned int AllocationGroupSize;
-  u32 DMA_Handle;
-  enum BusLogic_CCB_Status Status;
-  unsigned long SerialNumber;
-  struct scsi_cmnd *Command;
-  struct BusLogic_HostAdapter *HostAdapter;
-  struct BusLogic_CCB *Next;
-  struct BusLogic_CCB *NextAll;
-  struct BusLogic_ScatterGatherSegment
-    ScatterGatherList[BusLogic_ScatterGatherLimit];
+       /*
+          BusLogic Linux Driver Defined Portion.
+        */
+       dma_addr_t AllocationGroupHead;
+       unsigned int AllocationGroupSize;
+       u32 DMA_Handle;
+       enum BusLogic_CCB_Status Status;
+       unsigned long SerialNumber;
+       struct scsi_cmnd *Command;
+       struct BusLogic_HostAdapter *HostAdapter;
+       struct BusLogic_CCB *Next;
+       struct BusLogic_CCB *NextAll;
+       struct BusLogic_ScatterGatherSegment
+        ScatterGatherList[BusLogic_ScatterGatherLimit];
 };
 
 /*
   Define the 32 Bit Mode Outgoing Mailbox structure.
 */
 
-struct BusLogic_OutgoingMailbox
-{
-  u32 CCB;                                             /* Bytes 0-3 */
-  unsigned int :24;                                    /* Bytes 4-6 */
-  enum BusLogic_ActionCode ActionCode;                 /* Byte 7 */
+struct BusLogic_OutgoingMailbox {
+       u32 CCB;                /* Bytes 0-3 */
+       unsigned int:24;        /* Bytes 4-6 */
+       enum BusLogic_ActionCode ActionCode;    /* Byte 7 */
 };
 
 /*
   Define the 32 Bit Mode Incoming Mailbox structure.
 */
 
-struct BusLogic_IncomingMailbox
-{
-  u32 CCB;                                             /* Bytes 0-3 */
-  enum BusLogic_HostAdapterStatus HostAdapterStatus;   /* Byte 4 */
-  enum BusLogic_TargetDeviceStatus TargetDeviceStatus; /* Byte 5 */
-  unsigned char :8;                                    /* Byte 6 */
-  enum BusLogic_CompletionCode CompletionCode;         /* Byte 7 */
+struct BusLogic_IncomingMailbox {
+       u32 CCB;                /* Bytes 0-3 */
+       enum BusLogic_HostAdapterStatus HostAdapterStatus;      /* Byte 4 */
+       enum BusLogic_TargetDeviceStatus TargetDeviceStatus;    /* Byte 5 */
+       unsigned char:8;        /* Byte 6 */
+       enum BusLogic_CompletionCode CompletionCode;    /* Byte 7 */
 };
 
 
@@ -973,29 +929,27 @@ struct BusLogic_IncomingMailbox
   Define the BusLogic Driver Options structure.
 */
 
-struct BusLogic_DriverOptions
-{
-  unsigned short TaggedQueuingPermitted;
-  unsigned short TaggedQueuingPermittedMask;
-  unsigned short BusSettleTime;
-  struct BusLogic_LocalOptions LocalOptions;
-  unsigned char CommonQueueDepth;
-  unsigned char QueueDepth[BusLogic_MaxTargetDevices];
+struct BusLogic_DriverOptions {
+       unsigned short TaggedQueuingPermitted;
+       unsigned short TaggedQueuingPermittedMask;
+       unsigned short BusSettleTime;
+       struct BusLogic_LocalOptions LocalOptions;
+       unsigned char CommonQueueDepth;
+       unsigned char QueueDepth[BusLogic_MaxTargetDevices];
 };
 
 /*
   Define the Host Adapter Target Flags structure.
 */
 
-struct BusLogic_TargetFlags
-{
-  boolean TargetExists:1;
-  boolean TaggedQueuingSupported:1;
-  boolean WideTransfersSupported:1;
-  boolean TaggedQueuingActive:1;
-  boolean WideTransfersActive:1;
-  boolean CommandSuccessfulFlag:1;
-  boolean TargetInfoReported:1;
+struct BusLogic_TargetFlags {
+       boolean TargetExists:1;
+       boolean TaggedQueuingSupported:1;
+       boolean WideTransfersSupported:1;
+       boolean TaggedQueuingActive:1;
+       boolean WideTransfersActive:1;
+       boolean CommandSuccessfulFlag:1;
+       boolean TargetInfoReported:1;
 };
 
 /*
@@ -1006,25 +960,24 @@ struct BusLogic_TargetFlags
 
 typedef unsigned int BusLogic_CommandSizeBuckets_T[BusLogic_SizeBuckets];
 
-struct BusLogic_TargetStatistics
-{
-  unsigned int CommandsAttempted;
-  unsigned int CommandsCompleted;
-  unsigned int ReadCommands;
-  unsigned int WriteCommands;
-  struct BusLogic_ByteCounter TotalBytesRead;
-  struct BusLogic_ByteCounter TotalBytesWritten;
-  BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets;
-  BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets;
-  unsigned short CommandAbortsRequested;
-  unsigned short CommandAbortsAttempted;
-  unsigned short CommandAbortsCompleted;
-  unsigned short BusDeviceResetsRequested;
-  unsigned short BusDeviceResetsAttempted;
-  unsigned short BusDeviceResetsCompleted;
-  unsigned short HostAdapterResetsRequested;
-  unsigned short HostAdapterResetsAttempted;
-  unsigned short HostAdapterResetsCompleted;
+struct BusLogic_TargetStatistics {
+       unsigned int CommandsAttempted;
+       unsigned int CommandsCompleted;
+       unsigned int ReadCommands;
+       unsigned int WriteCommands;
+       struct BusLogic_ByteCounter TotalBytesRead;
+       struct BusLogic_ByteCounter TotalBytesWritten;
+       BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets;
+       BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets;
+       unsigned short CommandAbortsRequested;
+       unsigned short CommandAbortsAttempted;
+       unsigned short CommandAbortsCompleted;
+       unsigned short BusDeviceResetsRequested;
+       unsigned short BusDeviceResetsAttempted;
+       unsigned short BusDeviceResetsCompleted;
+       unsigned short HostAdapterResetsRequested;
+       unsigned short HostAdapterResetsAttempted;
+       unsigned short HostAdapterResetsCompleted;
 };
 
 /*
@@ -1041,183 +994,179 @@ typedef unsigned int FlashPoint_CardHandle_T;
   by the FlashPoint SCCB Manager.
 */
 
-struct FlashPoint_Info
-{
-  u32 BaseAddress;                                     /* Bytes 0-3 */
-  boolean Present;                                     /* Byte 4 */
-  unsigned char IRQ_Channel;                           /* Byte 5 */
-  unsigned char SCSI_ID;                               /* Byte 6 */
-  unsigned char SCSI_LUN;                              /* Byte 7 */
-  unsigned short FirmwareRevision;                     /* Bytes 8-9 */
-  unsigned short SynchronousPermitted;                 /* Bytes 10-11 */
-  unsigned short FastPermitted;                                /* Bytes 12-13 */
-  unsigned short UltraPermitted;                       /* Bytes 14-15 */
-  unsigned short DisconnectPermitted;                  /* Bytes 16-17 */
-  unsigned short WidePermitted;                                /* Bytes 18-19 */
-  boolean ParityCheckingEnabled:1;                     /* Byte 20 Bit 0 */
-  boolean HostWideSCSI:1;                              /* Byte 20 Bit 1 */
-  boolean HostSoftReset:1;                             /* Byte 20 Bit 2 */
-  boolean ExtendedTranslationEnabled:1;                        /* Byte 20 Bit 3 */
-  boolean LowByteTerminated:1;                         /* Byte 20 Bit 4 */
-  boolean HighByteTerminated:1;                                /* Byte 20 Bit 5 */
-  boolean ReportDataUnderrun:1;                                /* Byte 20 Bit 6 */
-  boolean SCAM_Enabled:1;                              /* Byte 20 Bit 7 */
-  boolean SCAM_Level2:1;                               /* Byte 21 Bit 0 */
-  unsigned char :7;                                    /* Byte 21 Bits 1-7 */
-  unsigned char Family;                                        /* Byte 22 */
-  unsigned char BusType;                               /* Byte 23 */
-  unsigned char ModelNumber[3];                                /* Bytes 24-26 */
-  unsigned char RelativeCardNumber;                    /* Byte 27 */
-  unsigned char Reserved[4];                           /* Bytes 28-31 */
-  unsigned int OS_Reserved;                            /* Bytes 32-35 */
-  unsigned char TranslationInfo[4];                    /* Bytes 36-39 */
-  unsigned int Reserved2[5];                           /* Bytes 40-59 */
-  unsigned int SecondaryRange;                         /* Bytes 60-63 */
+struct FlashPoint_Info {
+       u32 BaseAddress;        /* Bytes 0-3 */
+       boolean Present;        /* Byte 4 */
+       unsigned char IRQ_Channel;      /* Byte 5 */
+       unsigned char SCSI_ID;  /* Byte 6 */
+       unsigned char SCSI_LUN; /* Byte 7 */
+       unsigned short FirmwareRevision;        /* Bytes 8-9 */
+       unsigned short SynchronousPermitted;    /* Bytes 10-11 */
+       unsigned short FastPermitted;   /* Bytes 12-13 */
+       unsigned short UltraPermitted;  /* Bytes 14-15 */
+       unsigned short DisconnectPermitted;     /* Bytes 16-17 */
+       unsigned short WidePermitted;   /* Bytes 18-19 */
+       boolean ParityCheckingEnabled:1;        /* Byte 20 Bit 0 */
+       boolean HostWideSCSI:1; /* Byte 20 Bit 1 */
+       boolean HostSoftReset:1;        /* Byte 20 Bit 2 */
+       boolean ExtendedTranslationEnabled:1;   /* Byte 20 Bit 3 */
+       boolean LowByteTerminated:1;    /* Byte 20 Bit 4 */
+       boolean HighByteTerminated:1;   /* Byte 20 Bit 5 */
+       boolean ReportDataUnderrun:1;   /* Byte 20 Bit 6 */
+       boolean SCAM_Enabled:1; /* Byte 20 Bit 7 */
+       boolean SCAM_Level2:1;  /* Byte 21 Bit 0 */
+       unsigned char:7;        /* Byte 21 Bits 1-7 */
+       unsigned char Family;   /* Byte 22 */
+       unsigned char BusType;  /* Byte 23 */
+       unsigned char ModelNumber[3];   /* Bytes 24-26 */
+       unsigned char RelativeCardNumber;       /* Byte 27 */
+       unsigned char Reserved[4];      /* Bytes 28-31 */
+       unsigned int OS_Reserved;       /* Bytes 32-35 */
+       unsigned char TranslationInfo[4];       /* Bytes 36-39 */
+       unsigned int Reserved2[5];      /* Bytes 40-59 */
+       unsigned int SecondaryRange;    /* Bytes 60-63 */
 };
 
 /*
   Define the BusLogic Driver Host Adapter structure.
 */
 
-struct BusLogic_HostAdapter
-{
-  struct Scsi_Host *SCSI_Host;
-  struct pci_dev *PCI_Device;
-  enum BusLogic_HostAdapterType HostAdapterType;
-  enum BusLogic_HostAdapterBusType HostAdapterBusType;
-  unsigned long IO_Address;
-  unsigned long PCI_Address;
-  unsigned short AddressCount;
-  unsigned char HostNumber;
-  unsigned char ModelName[9];
-  unsigned char FirmwareVersion[6];
-  unsigned char FullModelName[18];
-  unsigned char Bus;
-  unsigned char Device;
-  unsigned char IRQ_Channel;
-  unsigned char DMA_Channel;
-  unsigned char SCSI_ID;
-  boolean IRQ_ChannelAcquired:1;
-  boolean DMA_ChannelAcquired:1;
-  boolean ExtendedTranslationEnabled:1;
-  boolean ParityCheckingEnabled:1;
-  boolean BusResetEnabled:1;
-  boolean LevelSensitiveInterrupt:1;
-  boolean HostWideSCSI:1;
-  boolean HostDifferentialSCSI:1;
-  boolean HostSupportsSCAM:1;
-  boolean HostUltraSCSI:1;
-  boolean ExtendedLUNSupport:1;
-  boolean TerminationInfoValid:1;
-  boolean LowByteTerminated:1;
-  boolean HighByteTerminated:1;
-  boolean BounceBuffersRequired:1;
-  boolean StrictRoundRobinModeSupport:1;
-  boolean SCAM_Enabled:1;
-  boolean SCAM_Level2:1;
-  boolean HostAdapterInitialized:1;
-  boolean HostAdapterExternalReset:1;
-  boolean HostAdapterInternalError:1;
-  boolean ProcessCompletedCCBsActive;
-  volatile boolean HostAdapterCommandCompleted;
-  unsigned short HostAdapterScatterGatherLimit;
-  unsigned short DriverScatterGatherLimit;
-  unsigned short MaxTargetDevices;
-  unsigned short MaxLogicalUnits;
-  unsigned short MailboxCount;
-  unsigned short InitialCCBs;
-  unsigned short IncrementalCCBs;
-  unsigned short AllocatedCCBs;
-  unsigned short DriverQueueDepth;
-  unsigned short HostAdapterQueueDepth;
-  unsigned short UntaggedQueueDepth;
-  unsigned short CommonQueueDepth;
-  unsigned short BusSettleTime;
-  unsigned short SynchronousPermitted;
-  unsigned short FastPermitted;
-  unsigned short UltraPermitted;
-  unsigned short WidePermitted;
-  unsigned short DisconnectPermitted;
-  unsigned short TaggedQueuingPermitted;
-  unsigned short ExternalHostAdapterResets;
-  unsigned short HostAdapterInternalErrors;
-  unsigned short TargetDeviceCount;
-  unsigned short MessageBufferLength;
-  u32 BIOS_Address;
-  struct BusLogic_DriverOptions *DriverOptions;
-  struct FlashPoint_Info FlashPointInfo;
-  FlashPoint_CardHandle_T CardHandle;
-  struct BusLogic_HostAdapter *Next;
-  struct BusLogic_CCB *All_CCBs;
-  struct BusLogic_CCB *Free_CCBs;
-  struct BusLogic_CCB *FirstCompletedCCB;
-  struct BusLogic_CCB *LastCompletedCCB;
-  struct BusLogic_CCB *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices];
-  struct BusLogic_TargetFlags TargetFlags[BusLogic_MaxTargetDevices];
-  unsigned char QueueDepth[BusLogic_MaxTargetDevices];
-  unsigned char SynchronousPeriod[BusLogic_MaxTargetDevices];
-  unsigned char SynchronousOffset[BusLogic_MaxTargetDevices];
-  unsigned char ActiveCommands[BusLogic_MaxTargetDevices];
-  unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices];
-  unsigned long LastSequencePoint[BusLogic_MaxTargetDevices];
-  unsigned long LastResetAttempted[BusLogic_MaxTargetDevices];
-  unsigned long LastResetCompleted[BusLogic_MaxTargetDevices];
-  struct BusLogic_OutgoingMailbox *FirstOutgoingMailbox;
-  struct BusLogic_OutgoingMailbox *LastOutgoingMailbox;
-  struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
-  struct BusLogic_IncomingMailbox *FirstIncomingMailbox;
-  struct BusLogic_IncomingMailbox *LastIncomingMailbox;
-  struct BusLogic_IncomingMailbox *NextIncomingMailbox;
-  struct BusLogic_TargetStatistics TargetStatistics[BusLogic_MaxTargetDevices];
-  unsigned char *MailboxSpace;
-  dma_addr_t MailboxSpaceHandle;
-  unsigned int MailboxSize;
-  unsigned long CCB_Offset;
-  char MessageBuffer[BusLogic_MessageBufferSize];
+struct BusLogic_HostAdapter {
+       struct Scsi_Host *SCSI_Host;
+       struct pci_dev *PCI_Device;
+       enum BusLogic_HostAdapterType HostAdapterType;
+       enum BusLogic_HostAdapterBusType HostAdapterBusType;
+       unsigned long IO_Address;
+       unsigned long PCI_Address;
+       unsigned short AddressCount;
+       unsigned char HostNumber;
+       unsigned char ModelName[9];
+       unsigned char FirmwareVersion[6];
+       unsigned char FullModelName[18];
+       unsigned char Bus;
+       unsigned char Device;
+       unsigned char IRQ_Channel;
+       unsigned char DMA_Channel;
+       unsigned char SCSI_ID;
+       boolean IRQ_ChannelAcquired:1;
+       boolean DMA_ChannelAcquired:1;
+       boolean ExtendedTranslationEnabled:1;
+       boolean ParityCheckingEnabled:1;
+       boolean BusResetEnabled:1;
+       boolean LevelSensitiveInterrupt:1;
+       boolean HostWideSCSI:1;
+       boolean HostDifferentialSCSI:1;
+       boolean HostSupportsSCAM:1;
+       boolean HostUltraSCSI:1;
+       boolean ExtendedLUNSupport:1;
+       boolean TerminationInfoValid:1;
+       boolean LowByteTerminated:1;
+       boolean HighByteTerminated:1;
+       boolean BounceBuffersRequired:1;
+       boolean StrictRoundRobinModeSupport:1;
+       boolean SCAM_Enabled:1;
+       boolean SCAM_Level2:1;
+       boolean HostAdapterInitialized:1;
+       boolean HostAdapterExternalReset:1;
+       boolean HostAdapterInternalError:1;
+       boolean ProcessCompletedCCBsActive;
+       volatile boolean HostAdapterCommandCompleted;
+       unsigned short HostAdapterScatterGatherLimit;
+       unsigned short DriverScatterGatherLimit;
+       unsigned short MaxTargetDevices;
+       unsigned short MaxLogicalUnits;
+       unsigned short MailboxCount;
+       unsigned short InitialCCBs;
+       unsigned short IncrementalCCBs;
+       unsigned short AllocatedCCBs;
+       unsigned short DriverQueueDepth;
+       unsigned short HostAdapterQueueDepth;
+       unsigned short UntaggedQueueDepth;
+       unsigned short CommonQueueDepth;
+       unsigned short BusSettleTime;
+       unsigned short SynchronousPermitted;
+       unsigned short FastPermitted;
+       unsigned short UltraPermitted;
+       unsigned short WidePermitted;
+       unsigned short DisconnectPermitted;
+       unsigned short TaggedQueuingPermitted;
+       unsigned short ExternalHostAdapterResets;
+       unsigned short HostAdapterInternalErrors;
+       unsigned short TargetDeviceCount;
+       unsigned short MessageBufferLength;
+       u32 BIOS_Address;
+       struct BusLogic_DriverOptions *DriverOptions;
+       struct FlashPoint_Info FlashPointInfo;
+       FlashPoint_CardHandle_T CardHandle;
+       struct BusLogic_HostAdapter *Next;
+       struct BusLogic_CCB *All_CCBs;
+       struct BusLogic_CCB *Free_CCBs;
+       struct BusLogic_CCB *FirstCompletedCCB;
+       struct BusLogic_CCB *LastCompletedCCB;
+       struct BusLogic_CCB *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices];
+       struct BusLogic_TargetFlags TargetFlags[BusLogic_MaxTargetDevices];
+       unsigned char QueueDepth[BusLogic_MaxTargetDevices];
+       unsigned char SynchronousPeriod[BusLogic_MaxTargetDevices];
+       unsigned char SynchronousOffset[BusLogic_MaxTargetDevices];
+       unsigned char ActiveCommands[BusLogic_MaxTargetDevices];
+       unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices];
+       unsigned long LastSequencePoint[BusLogic_MaxTargetDevices];
+       unsigned long LastResetAttempted[BusLogic_MaxTargetDevices];
+       unsigned long LastResetCompleted[BusLogic_MaxTargetDevices];
+       struct BusLogic_OutgoingMailbox *FirstOutgoingMailbox;
+       struct BusLogic_OutgoingMailbox *LastOutgoingMailbox;
+       struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
+       struct BusLogic_IncomingMailbox *FirstIncomingMailbox;
+       struct BusLogic_IncomingMailbox *LastIncomingMailbox;
+       struct BusLogic_IncomingMailbox *NextIncomingMailbox;
+       struct BusLogic_TargetStatistics TargetStatistics[BusLogic_MaxTargetDevices];
+       unsigned char *MailboxSpace;
+       dma_addr_t MailboxSpaceHandle;
+       unsigned int MailboxSize;
+       unsigned long CCB_Offset;
+       char MessageBuffer[BusLogic_MessageBufferSize];
 };
 
 /*
   Define a structure for the BIOS Disk Parameters.
 */
 
-struct BIOS_DiskParameters
-{
-  int Heads;
-  int Sectors;
-  int Cylinders;
+struct BIOS_DiskParameters {
+       int Heads;
+       int Sectors;
+       int Cylinders;
 };
 
 /*
   Define a structure for the SCSI Inquiry command results.
 */
 
-struct SCSI_Inquiry
-{
-  unsigned char PeripheralDeviceType:5;                        /* Byte 0 Bits 0-4 */
-  unsigned char PeripheralQualifier:3;                 /* Byte 0 Bits 5-7 */
-  unsigned char DeviceTypeModifier:7;                  /* Byte 1 Bits 0-6 */
-  boolean RMB:1;                                       /* Byte 1 Bit 7 */
-  unsigned char ANSI_ApprovedVersion:3;                        /* Byte 2 Bits 0-2 */
-  unsigned char ECMA_Version:3;                                /* Byte 2 Bits 3-5 */
-  unsigned char ISO_Version:2;                         /* Byte 2 Bits 6-7 */
-  unsigned char ResponseDataFormat:4;                  /* Byte 3 Bits 0-3 */
-  unsigned char :2;                                    /* Byte 3 Bits 4-5 */
-  boolean TrmIOP:1;                                    /* Byte 3 Bit 6 */
-  boolean AENC:1;                                      /* Byte 3 Bit 7 */
-  unsigned char AdditionalLength;                      /* Byte 4 */
-  unsigned char :8;                                    /* Byte 5 */
-  unsigned char :8;                                    /* Byte 6 */
-  boolean SftRe:1;                                     /* Byte 7 Bit 0 */
-  boolean CmdQue:1;                                    /* Byte 7 Bit 1 */
-  boolean :1;                                          /* Byte 7 Bit 2 */
-  boolean Linked:1;                                    /* Byte 7 Bit 3 */
-  boolean Sync:1;                                      /* Byte 7 Bit 4 */
-  boolean WBus16:1;                                    /* Byte 7 Bit 5 */
-  boolean WBus32:1;                                    /* Byte 7 Bit 6 */
-  boolean RelAdr:1;                                    /* Byte 7 Bit 7 */
-  unsigned char VendorIdentification[8];               /* Bytes 8-15 */
-  unsigned char ProductIdentification[16];             /* Bytes 16-31 */
-  unsigned char ProductRevisionLevel[4];               /* Bytes 32-35 */
+struct SCSI_Inquiry {
+       unsigned char PeripheralDeviceType:5;   /* Byte 0 Bits 0-4 */
+       unsigned char PeripheralQualifier:3;    /* Byte 0 Bits 5-7 */
+       unsigned char DeviceTypeModifier:7;     /* Byte 1 Bits 0-6 */
+       boolean RMB:1;          /* Byte 1 Bit 7 */
+       unsigned char ANSI_ApprovedVersion:3;   /* Byte 2 Bits 0-2 */
+       unsigned char ECMA_Version:3;   /* Byte 2 Bits 3-5 */
+       unsigned char ISO_Version:2;    /* Byte 2 Bits 6-7 */
+       unsigned char ResponseDataFormat:4;     /* Byte 3 Bits 0-3 */
+       unsigned char:2;        /* Byte 3 Bits 4-5 */
+       boolean TrmIOP:1;       /* Byte 3 Bit 6 */
+       boolean AENC:1;         /* Byte 3 Bit 7 */
+       unsigned char AdditionalLength; /* Byte 4 */
+       unsigned char:8;        /* Byte 5 */
+       unsigned char:8;        /* Byte 6 */
+       boolean SftRe:1;        /* Byte 7 Bit 0 */
+       boolean CmdQue:1;       /* Byte 7 Bit 1 */
+        boolean:1;             /* Byte 7 Bit 2 */
+       boolean Linked:1;       /* Byte 7 Bit 3 */
+       boolean Sync:1;         /* Byte 7 Bit 4 */
+       boolean WBus16:1;       /* Byte 7 Bit 5 */
+       boolean WBus32:1;       /* Byte 7 Bit 6 */
+       boolean RelAdr:1;       /* Byte 7 Bit 7 */
+       unsigned char VendorIdentification[8];  /* Bytes 8-15 */
+       unsigned char ProductIdentification[16];        /* Bytes 16-31 */
+       unsigned char ProductRevisionLevel[4];  /* Bytes 32-35 */
 };
 
 /*
@@ -1226,7 +1175,7 @@ struct SCSI_Inquiry
 
 static inline void BusLogic_AcquireHostAdapterLock(struct BusLogic_HostAdapter *HostAdapter)
 {
-  spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
+       spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
 }
 
 /*
@@ -1235,7 +1184,7 @@ static inline void BusLogic_AcquireHostAdapterLock(struct BusLogic_HostAdapter *
 
 static inline void BusLogic_ReleaseHostAdapterLock(struct BusLogic_HostAdapter *HostAdapter)
 {
-  spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
+       spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
 }
 
 
@@ -1244,10 +1193,9 @@ static inline void BusLogic_ReleaseHostAdapterLock(struct BusLogic_HostAdapter *
   but is only called from the interrupt handler.
 */
 
-static inline void BusLogic_AcquireHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter,
-                                                    unsigned long *ProcessorFlags)
+static inline void BusLogic_AcquireHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter, unsigned long *ProcessorFlags)
 {
-  spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
+       spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
 }
 
 
@@ -1256,10 +1204,9 @@ static inline void BusLogic_AcquireHostAdapterLockIH(struct BusLogic_HostAdapter
   but is only called from the interrupt handler.
 */
 
-static inline void BusLogic_ReleaseHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter,
-                                                    unsigned long *ProcessorFlags)
+static inline void BusLogic_ReleaseHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter, unsigned long *ProcessorFlags)
 {
-  spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
+       spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
 }
 
 
@@ -1270,65 +1217,60 @@ static inline void BusLogic_ReleaseHostAdapterLockIH(struct BusLogic_HostAdapter
 
 static inline void BusLogic_SCSIBusReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.SCSIBusReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+       union BusLogic_ControlRegister ControlRegister;
+       ControlRegister.All = 0;
+       ControlRegister.cr.SCSIBusReset = true;
+       outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline void BusLogic_InterruptReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.InterruptReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+       union BusLogic_ControlRegister ControlRegister;
+       ControlRegister.All = 0;
+       ControlRegister.cr.InterruptReset = true;
+       outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline void BusLogic_SoftReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.SoftReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+       union BusLogic_ControlRegister ControlRegister;
+       ControlRegister.All = 0;
+       ControlRegister.cr.SoftReset = true;
+       outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline void BusLogic_HardReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.HardReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+       union BusLogic_ControlRegister ControlRegister;
+       ControlRegister.All = 0;
+       ControlRegister.cr.HardReset = true;
+       outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadStatusRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset);
+       return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset);
 }
 
 static inline void BusLogic_WriteCommandParameterRegister(struct BusLogic_HostAdapter
-                                                         *HostAdapter,
-                                                         unsigned char Value)
+                                                         *HostAdapter, unsigned char Value)
 {
-  outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset);
+       outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadDataInRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset);
+       return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadInterruptRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset);
+       return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadGeometryRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset);
+       return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset);
 }
 
 /*
@@ -1339,7 +1281,7 @@ static inline unsigned char BusLogic_ReadGeometryRegister(struct BusLogic_HostAd
 
 static inline void BusLogic_StartMailboxCommand(struct BusLogic_HostAdapter *HostAdapter)
 {
-  BusLogic_WriteCommandParameterRegister(HostAdapter, BusLogic_ExecuteMailboxCommand);
+       BusLogic_WriteCommandParameterRegister(HostAdapter, BusLogic_ExecuteMailboxCommand);
 }
 
 /*
@@ -1348,7 +1290,7 @@ static inline void BusLogic_StartMailboxCommand(struct BusLogic_HostAdapter *Hos
 
 static inline void BusLogic_Delay(int Seconds)
 {
-  mdelay(1000 * Seconds);
+       mdelay(1000 * Seconds);
 }
 
 /*
@@ -1358,12 +1300,12 @@ static inline void BusLogic_Delay(int Seconds)
 
 static inline u32 Virtual_to_Bus(void *VirtualAddress)
 {
-  return (u32) virt_to_bus(VirtualAddress);
+       return (u32) virt_to_bus(VirtualAddress);
 }
 
 static inline void *Bus_to_Virtual(u32 BusAddress)
 {
-  return (void *) bus_to_virt(BusAddress);
+       return (void *) bus_to_virt(BusAddress);
 }
 
 /*
@@ -1374,7 +1316,7 @@ static inline void *Bus_to_Virtual(u32 BusAddress)
 
 static inline u32 Virtual_to_32Bit_Virtual(void *VirtualAddress)
 {
-  return (u32) (unsigned long) VirtualAddress;
+       return (u32) (unsigned long) VirtualAddress;
 }
 
 /*
@@ -1384,7 +1326,8 @@ static inline u32 Virtual_to_32Bit_Virtual(void *VirtualAddress)
 
 static inline void BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter)
 {
-  if (*ErrorCounter < 65535) (*ErrorCounter)++;
+       if (*ErrorCounter < 65535)
+               (*ErrorCounter)++;
 }
 
 /*
@@ -1392,40 +1335,35 @@ static inline void BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter)
 */
 
 static inline void BusLogic_IncrementByteCounter(struct BusLogic_ByteCounter
-                                                *ByteCounter,
-                                                unsigned int Amount)
+                                                *ByteCounter, unsigned int Amount)
 {
-  ByteCounter->Units += Amount;
-  if (ByteCounter->Units > 999999999)
-    {
-      ByteCounter->Units -= 1000000000;
-      ByteCounter->Billions++;
-    }
+       ByteCounter->Units += Amount;
+       if (ByteCounter->Units > 999999999) {
+               ByteCounter->Units -= 1000000000;
+               ByteCounter->Billions++;
+       }
 }
 
 /*
   BusLogic_IncrementSizeBucket increments the Bucket for Amount.
 */
 
-static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T
-                                               CommandSizeBuckets,
-                                               unsigned int Amount)
-{
-  int Index = 0;
-  if (Amount < 8*1024)
-    {
-      if (Amount < 2*1024)
-       Index = (Amount < 1*1024 ? 0 : 1);
-      else Index = (Amount < 4*1024 ? 2 : 3);
-    }
-  else if (Amount < 128*1024)
-    {
-      if (Amount < 32*1024)
-       Index = (Amount < 16*1024 ? 4 : 5);
-      else Index = (Amount < 64*1024 ? 6 : 7);
-    }
-  else Index = (Amount < 256*1024 ? 8 : 9);
-  CommandSizeBuckets[Index]++;
+static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T CommandSizeBuckets, unsigned int Amount)
+{
+       int Index = 0;
+       if (Amount < 8 * 1024) {
+               if (Amount < 2 * 1024)
+                       Index = (Amount < 1 * 1024 ? 0 : 1);
+               else
+                       Index = (Amount < 4 * 1024 ? 2 : 3);
+       } else if (Amount < 128 * 1024) {
+               if (Amount < 32 * 1024)
+                       Index = (Amount < 16 * 1024 ? 4 : 5);
+               else
+                       Index = (Amount < 64 * 1024 ? 6 : 7);
+       } else
+               Index = (Amount < 256 * 1024 ? 8 : 9);
+       CommandSizeBuckets[Index]++;
 }
 
 /*
@@ -1450,20 +1388,14 @@ static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T
 static const char *BusLogic_DriverInfo(struct Scsi_Host *);
 static int BusLogic_DetectHostAdapter(struct scsi_host_template *);
 static int BusLogic_ReleaseHostAdapter(struct Scsi_Host *);
-static int BusLogic_QueueCommand(struct scsi_cmnd *,
-                                void (*CompletionRoutine)(struct scsi_cmnd *));
-static int BusLogic_BIOSDiskParameters(struct scsi_device *,
-                                      struct block_device *,
-                                      sector_t, int *);
-static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *,
-                                     char **, off_t, int, int);
+static int BusLogic_QueueCommand(struct scsi_cmnd *, void (*CompletionRoutine) (struct scsi_cmnd *));
+static int BusLogic_BIOSDiskParameters(struct scsi_device *, struct block_device *, sector_t, int *);
+static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t, int, int);
 static int BusLogic_SlaveConfigure(struct scsi_device *);
 static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *);
 static irqreturn_t BusLogic_InterruptHandler(int, void *, struct pt_regs *);
-static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *,
-                                    boolean HardReset);
-static void BusLogic_Message(enum BusLogic_MessageLevel, char *,
-                            struct BusLogic_HostAdapter *, ...);
+static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, boolean HardReset);
+static void BusLogic_Message(enum BusLogic_MessageLevel, char *, struct BusLogic_HostAdapter *, ...);
 static int __init BusLogic_Setup(char *);
 
-#endif /* _BUSLOGIC_H */
+#endif                         /* _BUSLOGIC_H */
index e3bb9dd..2032b62 100644 (file)
  * possible) function may be used.  Before the specific driver initialization
  * code finishes, NCR5380_print_options should be called.
  */
-
 static int do_abort(struct Scsi_Host *host);
 static void do_reset(struct Scsi_Host *host);
-static struct NCR5380_hostdata *first_host = NULL;
-static struct NCR5380_hostdata *last_host = NULL;
-static struct timer_list usleep_timer;
 
 /*
  *     initialize_SCp          -       init the scsi pointer field
@@ -533,9 +529,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
 #define USLEEP_WAITLONG USLEEP_SLEEP
 #endif
 
-static struct Scsi_Host *expires_first = NULL;
-static spinlock_t timer_lock;  /* Guards expires list */
-
 /* 
  * Function : int should_disconnect (unsigned char cmd)
  *
@@ -578,90 +571,10 @@ static int should_disconnect(unsigned char cmd)
        }
 }
 
-/*
- * Assumes instance->time_expires has been set in higher level code.
- * We should move to a timer per host
- *
- * Locks: Takes the timer queue lock
- */
-
-static int NCR5380_set_timer(struct Scsi_Host *instance)
-{
-       struct Scsi_Host *tmp, **prev;
-       unsigned long flags;
-
-       if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) {
-               return -1;
-       }
-       
-       spin_lock_irqsave(&timer_lock, flags);
-       for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
-               if (((struct NCR5380_hostdata *) instance->hostdata)->time_expires < ((struct NCR5380_hostdata *) tmp->hostdata)->time_expires)
-                       break;
-
-       ((struct NCR5380_hostdata *) instance->hostdata)->next_timer = tmp;
-       *prev = instance;
-
-       mod_timer(&usleep_timer, ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires);
-       
-       spin_unlock_irqrestore(&timer_lock, flags);
-       return 0;
-}
-
-/**
- *     NCR5380_timer_fn        -       handle polled timeouts
- *     @unused: unused
- *
- *     Walk the list of controllers, find which controllers have exceeded
- *     their expiry timeout and then schedule the processing co-routine to
- *     do the real work.
- *
- *     Doing something about unwanted reentrancy here might be useful 
- *
- *     Locks: disables irqs, takes and frees the timer lock
- */
-static void NCR5380_timer_fn(unsigned long unused)
-{
-       struct Scsi_Host *instance;
-       struct NCR5380_hostdata *hostdata;
-       unsigned long flags;
-
-       spin_lock_irqsave(&timer_lock, flags);
-       for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);) 
-       {
-               hostdata = (struct NCR5380_hostdata *) expires_first->hostdata;
-               schedule_work(&hostdata->coroutine);
-               instance = hostdata->next_timer;
-               hostdata->next_timer = NULL;
-               hostdata->time_expires = 0;
-               expires_first = instance;
-       }
-
-       del_timer(&usleep_timer);
-       if (expires_first) {
-               usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires;
-               add_timer(&usleep_timer);
-       }
-       spin_unlock_irqrestore(&timer_lock, flags);
-}
-
-/**
- *     NCR5380_all_init        -       global setup
- *
- *     Set up the global values and timers needed by the NCR5380 driver
- */
-static inline void NCR5380_all_init(void)
+static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long timeout)
 {
-       static int done = 0;
-       if (!done) {
-               dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n"));
-               done = 1;
-               init_timer(&usleep_timer);
-               spin_lock_init(&timer_lock);
-               usleep_timer.function = NCR5380_timer_fn;
-       }
+       hostdata->time_expires = jiffies + timeout;
+       schedule_delayed_work(&hostdata->coroutine, hostdata->time_expires);
 }
 
 
@@ -787,22 +700,6 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance)
        }
 }
 
-/**
- *     NCR5380_coroutine_running       -       coroutine status
- *     @instance: controller to check
- *
- *     Return true if the co-routine for this controller is running
- *     or scheduled to run
- *
- *     FIXME: this test function belongs in the workqueue code!
- */
-static int NCR5380_coroutine_running(struct Scsi_Host *instance)
-{
-       struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata;
-       return test_bit(0, &hostdata->coroutine.pending);
-}
-
 /**
  *     NCR5380_print_status    -       dump controller info
  *     @instance: controller to dump
@@ -819,8 +716,6 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
        char *start;
        int len;
 
-       printk("NCR5380 : coroutine is%s running.\n",  NCR5380_coroutine_running(instance)? "" : "n't");
-
        NCR5380_dprint(NDEBUG_ANY, instance);
        NCR5380_dprint_phase(NDEBUG_ANY, instance);
 
@@ -900,7 +795,6 @@ int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, of
        SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n", pas_wmaxi, pas_maxi);
 #endif
        spin_lock_irq(instance->host_lock);
-       SPRINTF("NCR5380 : coroutine is%s running.\n", NCR5380_coroutine_running(instance) ? "" : "n't");
        if (!hostdata->connected)
                SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
        else
@@ -912,7 +806,6 @@ int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, of
        SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
        for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
                pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
-
        spin_unlock_irq(instance->host_lock);
        
        *start = buffer;
@@ -964,7 +857,7 @@ static char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
  *     Locks: interrupts must be enabled when we are called 
  */
 
-static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
+static int __devinit NCR5380_init(struct Scsi_Host *instance, int flags)
 {
        NCR5380_local_declare();
        int i, pass;
@@ -984,7 +877,6 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
 #endif
 
        NCR5380_setup(instance);
-       NCR5380_all_init();
 
        hostdata->aborted = 0;
        hostdata->id_mask = 1 << instance->this_id;
@@ -1021,18 +913,8 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
        else
                hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags;
 
-       hostdata->next = NULL;
-       
-       if (!first_host)
-               first_host = hostdata;
-       else
-               last_host->next = hostdata;
-
-       last_host = hostdata;
-       
        hostdata->host = instance;
        hostdata->time_expires = 0;
-       hostdata->next_timer = NULL;
 
 #ifndef AUTOSENSE
        if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)
@@ -1088,6 +970,19 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
        return 0;
 }
 
+/**
+ *     NCR5380_exit    -       remove an NCR5380
+ *     @instance: adapter to remove
+ */
+
+static void __devexit NCR5380_exit(struct Scsi_Host *instance)
+{
+       struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
+
+       cancel_delayed_work(&hostdata->coroutine);
+       flush_scheduled_work();
+}
+
 /**
  *     NCR5380_queue_command           -       queue a command
  *     @cmd: SCSI command
@@ -1169,6 +1064,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
        return 0;
 }
 
+
 /**
  *     NCR5380_main    -       NCR state machines
  *
@@ -1184,28 +1080,11 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 static void NCR5380_main(void *p)
 {
        struct NCR5380_hostdata *hostdata = p;
+       struct Scsi_Host *instance = hostdata->host;
        Scsi_Cmnd *tmp, *prev;
-       struct Scsi_Host *instance;
        int done;
-       unsigned long flags = 0;
        
-       /*
-        * 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 can 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.
-        */
-
-       instance = hostdata->host;
-
-       if(instance->irq != SCSI_IRQ_NONE)
-               spin_lock_irqsave(instance->host_lock, flags);
-
+       spin_lock_irq(instance->host_lock);
        do {
                /* Lock held here */
                done = 1;
@@ -1286,8 +1165,7 @@ static void NCR5380_main(void *p)
                                LIST(tmp, hostdata->issue_queue);
                                tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
                                hostdata->issue_queue = tmp;
-                               hostdata->time_expires = jiffies + USLEEP_WAITLONG;
-                               NCR5380_set_timer(instance);
+                               NCR5380_set_timer(hostdata, USLEEP_WAITLONG);
                        }
                }       /* if hostdata->selecting */
                if (hostdata->connected
@@ -1304,8 +1182,7 @@ static void NCR5380_main(void *p)
                        break;
        } while (!done);
        
-       if(instance->irq != SCSI_IRQ_NONE)
-               spin_unlock_irqrestore(instance->host_lock, flags);
+       spin_unlock_irq(instance->host_lock);
 }
 
 #ifndef DONT_USE_INTR
@@ -1330,12 +1207,13 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
        struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
        int done;
        unsigned char basr;
+       unsigned long flags;
 
        dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq));
 
        do {
                done = 1;
-               spin_lock_irq(instance->host_lock);
+               spin_lock_irqsave(instance->host_lock, flags);
                /* Look for pending interrupts */
                NCR5380_setup(instance);
                basr = NCR5380_read(BUS_AND_STATUS_REG);
@@ -1386,7 +1264,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
 #endif
                        }
                }       /* if BASR_IRQ */
-               spin_unlock_irq(instance->host_lock);
+               spin_unlock_irqrestore(instance->host_lock, flags);
                if(!done)
                        schedule_work(&hostdata->coroutine);
        } while (!done);
@@ -1469,12 +1347,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
        int err;
        NCR5380_setup(instance);
 
-       if (hostdata->selecting) {
-               if(instance->irq != SCSI_IRQ_NONE)
-                       spin_unlock_irq(instance->host_lock);
-               goto part2;     /* RvC: sorry prof. Dijkstra, but it keeps the
-                                  rest of the code nearly the same */
-       }
+       if (hostdata->selecting)
+               goto part2;
 
        hostdata->restart_select = 0;
 
@@ -1495,16 +1369,12 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
        NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
        NCR5380_write(MODE_REG, MR_ARBITRATE);
 
-       if(instance->irq != SCSI_IRQ_NONE)
-               spin_unlock_irq(instance->host_lock);
 
        /* We can be relaxed here, interrupts are on, we are
           in workqueue context, the birds are singing in the trees */
-
+       spin_unlock_irq(instance->host_lock);
        err = NCR5380_poll_politely(instance, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, 5*HZ);
-       if(instance->irq != SCSI_IRQ_NONE)
-               spin_lock_irq(instance->host_lock);
-
+       spin_lock_irq(instance->host_lock);
        if (err < 0) {
                printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__);
                NCR5380_write(MODE_REG, MR_BASE);
@@ -1628,8 +1498,7 @@ part2:
        if (!value && (hostdata->select_time < HZ/4)) {
                /* RvC: we still must wait for a device response */
                hostdata->select_time++;        /* after 25 ticks the device has failed */
-               hostdata->time_expires = jiffies + 1;
-               NCR5380_set_timer(instance);
+               NCR5380_set_timer(hostdata, 1);
                return 0;       /* RvC: we return here with hostdata->selecting set,
                                   to go to sleep */
        }
@@ -1638,8 +1507,6 @@ part2:
                                           waiting period */
        if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
                NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-               if(instance->irq != SCSI_IRQ_NONE)
-                       spin_lock_irq(instance->host_lock);
                NCR5380_reselect(instance);
                printk("scsi%d : reselection after won arbitration?\n", instance->host_no);
                NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
@@ -1665,8 +1532,6 @@ part2:
                        NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
                        return -1;
                }
-               if(instance->irq != SCSI_IRQ_NONE)
-                       spin_lock_irq(instance->host_lock);
                cmd->result = DID_BAD_TARGET << 16;
                collect_stats(hostdata, cmd);
                cmd->scsi_done(cmd);
@@ -1693,11 +1558,13 @@ part2:
         */
 
        /* Wait for start of REQ/ACK handshake */
-       
+
+       spin_unlock_irq(instance->host_lock);
        err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
+       spin_lock_irq(instance->host_lock);
        
-       if(err)
-       {       printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
+       if(err) {
+               printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
                NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
                goto failed;
        }
@@ -1705,9 +1572,6 @@ part2:
        dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id));
        tmp[0] = IDENTIFY(((instance->irq == SCSI_IRQ_NONE) ? 0 : 1), cmd->device->lun);
 
-       if(instance->irq != SCSI_IRQ_NONE)
-               spin_lock_irq(instance->host_lock);
-               
        len = 1;
        cmd->tag = 0;
 
@@ -1720,15 +1584,14 @@ part2:
        hostdata->connected = cmd;
        hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
 
-       initialize_SCp(cmd);
-
+       if (cmd->SCp.ptr != (char *)cmd->sense_buffer) {
+               initialize_SCp(cmd);
+       }
 
        return 0;
 
        /* Selection failed */
 failed:
-       if(instance->irq != SCSI_IRQ_NONE)
-               spin_lock_irq(instance->host_lock);
        return -1;
 
 }
@@ -1804,8 +1667,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
                while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed);
                if (!(tmp & SR_REQ)) {
                        /* timeout condition */
-                       hostdata->time_expires = jiffies + USLEEP_SLEEP;
-                       NCR5380_set_timer(instance);
+                       NCR5380_set_timer(hostdata, USLEEP_SLEEP);
                        break;
                }
 
@@ -2643,9 +2505,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
                                 */
                                NCR5380_transfer_pio(instance, &phase, &len, &data);
                                if (!cmd->device->disconnect && should_disconnect(cmd->cmnd[0])) {
-                                       hostdata->time_expires = jiffies + USLEEP_SLEEP;
+                                       NCR5380_set_timer(hostdata, USLEEP_SLEEP);
                                        dprintk(NDEBUG_USLEEP, ("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
-                                       NCR5380_set_timer(instance);
                                        return;
                                }
                                break;
@@ -2664,9 +2525,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
                        /* RvC: go to sleep if polling time expired
                         */
                        if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) {
-                               hostdata->time_expires = jiffies + USLEEP_SLEEP;
+                               NCR5380_set_timer(hostdata, USLEEP_SLEEP);
                                dprintk(NDEBUG_USLEEP, ("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
-                               NCR5380_set_timer(instance);
                                return;
                        }
                }
index 321540c..b5103f9 100644 (file)
 struct NCR5380_hostdata {
        NCR5380_implementation_fields;          /* implementation specific */
        struct Scsi_Host *host;                 /* Host backpointer */
-       struct NCR5380_hostdata *next;          /* Next in our hot chain */
        unsigned char id_mask, id_higher_mask;  /* 1 << id, all bits greater */
        unsigned char targets_present;          /* targets we have connected
                                                   to, so we can call a select
@@ -270,7 +269,6 @@ struct NCR5380_hostdata {
        volatile unsigned aborted:1;            /* flag, says aborted */
        int flags;
        unsigned long time_expires;             /* in jiffies, set prior to sleeping */
-       struct Scsi_Host *next_timer;
        int select_time;                        /* timer in select for target response */
        volatile Scsi_Cmnd *selecting;
        struct work_struct coroutine;           /* our co-routine */
@@ -295,6 +293,7 @@ struct NCR5380_hostdata {
 static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible);
 #endif
 static int NCR5380_init(struct Scsi_Host *instance, int flags);
+static void NCR5380_exit(struct Scsi_Host *instance);
 static void NCR5380_information_transfer(struct Scsi_Host *instance);
 #ifndef DONT_USE_INTR
 static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs);
index cba290c..c402351 100644 (file)
@@ -91,10 +91,12 @@ struct chain {
 };
 
 /* These belong in scsi.h also */
-#define any2scsi(up, p)                                \
-(up)[0] = (((unsigned long)(p)) >> 16)  ;      \
-(up)[1] = (((unsigned long)(p)) >> 8);         \
-(up)[2] = ((unsigned long)(p));
+static inline void any2scsi(u8 *p, u32 v)
+{
+       p[0] = v >> 16;
+       p[1] = v >> 8;
+       p[2] = v;
+}
 
 #define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) )
 
index b299815..c2523a3 100644 (file)
@@ -46,7 +46,7 @@ config AIC79XX_RESET_DELAY_MS
 
 config AIC79XX_BUILD_FIRMWARE
        bool "Build Adapter Firmware with Kernel Build"
-       depends on SCSI_AIC79XX
+       depends on SCSI_AIC79XX && !PREVENT_FIRMWARE_BUILD
        help
        This option should only be enabled if you are modifying the firmware
        source to the aic79xx driver and wish to have the generated firmware
index 473a658..8398e0d 100644 (file)
@@ -61,7 +61,7 @@ config AIC7XXX_PROBE_EISA_VL
 
 config AIC7XXX_BUILD_FIRMWARE
        bool "Build Adapter Firmware with Kernel Build"
-       depends on SCSI_AIC7XXX
+       depends on SCSI_AIC7XXX && !PREVENT_FIRMWARE_BUILD
        help
        This option should only be enabled if you are modifying the firmware
        source to the aic7xxx driver and wish to have the generated firmware
index 9139845..7cc83da 100644 (file)
@@ -452,8 +452,10 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
         * or read prefetching could be initiated by the
         * CPU or host bridge.  Our device does not support
         * either, so look for data corruption and/or flaged
-        * PCI errors.
+        * PCI errors.  First pause without causing another
+        * chip reset.
         */
+       hcntrl &= ~CHIPRST;
        ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
        while (ahd_is_paused(ahd) == 0)
                ;
index 01cfab0..476780b 100644 (file)
@@ -1284,8 +1284,10 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
         * or read prefetching could be initiated by the
         * CPU or host bridge.  Our device does not support
         * either, so look for data corruption and/or flagged
-        * PCI errors.
+        * PCI errors.  First pause without causing another
+        * chip reset.
         */
+       hcntrl &= ~CHIPRST;
        ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
        while (ahc_is_paused(ahc) == 0)
                ;
index e8c345b..8c91fda 100644 (file)
@@ -34,10 +34,14 @@ $(PROG):  ${GENHDRS} $(SRCS)
        $(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS)
 
 aicdb.h:
-       @if [ -e "/usr/include/db3/db_185.h" ]; then            \
+       @if [ -e "/usr/include/db4/db_185.h" ]; then            \
+               echo "#include <db4/db_185.h>" > aicdb.h;       \
+        elif [ -e "/usr/include/db3/db_185.h" ]; then          \
                echo "#include <db3/db_185.h>" > aicdb.h;       \
         elif [ -e "/usr/include/db2/db_185.h" ]; then          \
                echo "#include <db2/db_185.h>" > aicdb.h;       \
+        elif [ -e "/usr/include/db1/db_185.h" ]; then          \
+               echo "#include <db1/db_185.h>" > aicdb.h;       \
         elif [ -e "/usr/include/db/db_185.h" ]; then           \
                echo "#include <db/db_185.h>" > aicdb.h;        \
         elif [ -e "/usr/include/db_185.h" ]; then              \
diff --git a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile
new file mode 100644 (file)
index 0000000..4e247b6
--- /dev/null
@@ -0,0 +1,5 @@
+obj-$(CONFIG_SCSI_IBMVSCSI)    += ibmvscsic.o
+
+ibmvscsic-y                    += ibmvscsi.o
+ibmvscsic-$(CONFIG_PPC_ISERIES)        += iseries_vscsi.o 
+ibmvscsic-$(CONFIG_PPC_PSERIES)        += rpa_vscsi.o 
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
new file mode 100644 (file)
index 0000000..210ee7d
--- /dev/null
@@ -0,0 +1,1393 @@
+/* ------------------------------------------------------------
+ * ibmvscsi.c
+ * (C) Copyright IBM Corporation 1994, 2004
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.com)
+ *          Dave Boutcher (sleddog@us.ibm.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
+ *
+ * ------------------------------------------------------------
+ * Emulation of a SCSI host adapter for Virtual I/O devices
+ *
+ * This driver supports the SCSI adapter implemented by the IBM
+ * Power5 firmware.  That SCSI adapter is not a physical adapter,
+ * but allows Linux SCSI peripheral drivers to directly
+ * access devices in another logical partition on the physical system.
+ *
+ * The virtual adapter(s) are present in the open firmware device
+ * tree just like real adapters.
+ *
+ * One of the capabilities provided on these systems is the ability
+ * to DMA between partitions.  The architecture states that for VSCSI,
+ * the server side is allowed to DMA to and from the client.  The client
+ * is never trusted to DMA to or from the server directly.
+ *
+ * Messages are sent between partitions on a "Command/Response Queue" 
+ * (CRQ), which is just a buffer of 16 byte entries in the receiver's 
+ * Senders cannot access the buffer directly, but send messages by
+ * making a hypervisor call and passing in the 16 bytes.  The hypervisor
+ * puts the message in the next 16 byte space in round-robbin fashion,
+ * turns on the high order bit of the message (the valid bit), and 
+ * generates an interrupt to the receiver (if interrupts are turned on.) 
+ * The receiver just turns off the valid bit when they have copied out
+ * the message.
+ *
+ * The VSCSI client builds a SCSI Remote Protocol (SRP) Information Unit
+ * (IU) (as defined in the T10 standard available at www.t10.org), gets 
+ * a DMA address for the message, and sends it to the server as the
+ * payload of a CRQ message.  The server DMAs the SRP IU and processes it,
+ * including doing any additional data transfers.  When it is done, it
+ * DMAs the SRP response back to the same address as the request came from,
+ * and sends a CRQ message back to inform the client that the request has
+ * completed.
+ *
+ * Note that some of the underlying infrastructure is different between
+ * machines conforming to the "RS/6000 Platform Architecture" (RPA) and
+ * the older iSeries hypervisor models.  To support both, some low level
+ * routines have been broken out into rpa_vscsi.c and iseries_vscsi.c.
+ * The Makefile should pick one, not two, not zero, of these.
+ *
+ * TODO: This is currently pretty tied to the IBM i/pSeries hypervisor
+ * interfaces.  It would be really nice to abstract this above an RDMA
+ * layer.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
+#include <asm/vio.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include "ibmvscsi.h"
+
+/* The values below are somewhat arbitrary default values, but 
+ * OS/400 will use 3 busses (disks, CDs, tapes, I think.)
+ * Note that there are 3 bits of channel value, 6 bits of id, and
+ * 5 bits of LUN.
+ */
+static int max_id = 64;
+static int max_channel = 3;
+static int init_timeout = 5;
+static int max_requests = 50;
+
+#define IBMVSCSI_VERSION "1.5.1"
+
+MODULE_DESCRIPTION("IBM Virtual SCSI");
+MODULE_AUTHOR("Dave Boutcher");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(IBMVSCSI_VERSION);
+
+module_param_named(max_id, max_id, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_id, "Largest ID value for each channel");
+module_param_named(max_channel, max_channel, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_channel, "Largest channel value");
+module_param_named(init_timeout, init_timeout, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds");
+module_param_named(max_requests, max_requests, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_requests, "Maximum requests for this adapter");
+
+/* ------------------------------------------------------------
+ * Routines for the event pool and event structs
+ */
+/**
+ * initialize_event_pool: - Allocates and initializes the event pool for a host
+ * @pool:      event_pool to be initialized
+ * @size:      Number of events in pool
+ * @hostdata:  ibmvscsi_host_data who owns the event pool
+ *
+ * Returns zero on success.
+*/
+static int initialize_event_pool(struct event_pool *pool,
+                                int size, struct ibmvscsi_host_data *hostdata)
+{
+       int i;
+
+       pool->size = size;
+       pool->next = 0;
+       pool->events = kmalloc(pool->size * sizeof(*pool->events), GFP_KERNEL);
+       if (!pool->events)
+               return -ENOMEM;
+       memset(pool->events, 0x00, pool->size * sizeof(*pool->events));
+
+       pool->iu_storage =
+           dma_alloc_coherent(hostdata->dev,
+                              pool->size * sizeof(*pool->iu_storage),
+                              &pool->iu_token, 0);
+       if (!pool->iu_storage) {
+               kfree(pool->events);
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < pool->size; ++i) {
+               struct srp_event_struct *evt = &pool->events[i];
+               memset(&evt->crq, 0x00, sizeof(evt->crq));
+               atomic_set(&evt->free, 1);
+               evt->crq.valid = 0x80;
+               evt->crq.IU_length = sizeof(*evt->xfer_iu);
+               evt->crq.IU_data_ptr = pool->iu_token + 
+                       sizeof(*evt->xfer_iu) * i;
+               evt->xfer_iu = pool->iu_storage + i;
+               evt->hostdata = hostdata;
+       }
+
+       return 0;
+}
+
+/**
+ * release_event_pool: - Frees memory of an event pool of a host
+ * @pool:      event_pool to be released
+ * @hostdata:  ibmvscsi_host_data who owns the even pool
+ *
+ * Returns zero on success.
+*/
+static void release_event_pool(struct event_pool *pool,
+                              struct ibmvscsi_host_data *hostdata)
+{
+       int i, in_use = 0;
+       for (i = 0; i < pool->size; ++i)
+               if (atomic_read(&pool->events[i].free) != 1)
+                       ++in_use;
+       if (in_use)
+               printk(KERN_WARNING
+                      "ibmvscsi: releasing event pool with %d "
+                      "events still in use?\n", in_use);
+       kfree(pool->events);
+       dma_free_coherent(hostdata->dev,
+                         pool->size * sizeof(*pool->iu_storage),
+                         pool->iu_storage, pool->iu_token);
+}
+
+/**
+ * valid_event_struct: - Determines if event is valid.
+ * @pool:      event_pool that contains the event
+ * @evt:       srp_event_struct to be checked for validity
+ *
+ * Returns zero if event is invalid, one otherwise.
+*/
+static int valid_event_struct(struct event_pool *pool,
+                               struct srp_event_struct *evt)
+{
+       int index = evt - pool->events;
+       if (index < 0 || index >= pool->size)   /* outside of bounds */
+               return 0;
+       if (evt != pool->events + index)        /* unaligned */
+               return 0;
+       return 1;
+}
+
+/**
+ * ibmvscsi_free-event_struct: - Changes status of event to "free"
+ * @pool:      event_pool that contains the event
+ * @evt:       srp_event_struct to be modified
+ *
+*/
+static void free_event_struct(struct event_pool *pool,
+                                      struct srp_event_struct *evt)
+{
+       if (!valid_event_struct(pool, evt)) {
+               printk(KERN_ERR
+                      "ibmvscsi: Freeing invalid event_struct %p "
+                      "(not in pool %p)\n", evt, pool->events);
+               return;
+       }
+       if (atomic_inc_return(&evt->free) != 1) {
+               printk(KERN_ERR
+                      "ibmvscsi: Freeing event_struct %p "
+                      "which is not in use!\n", evt);
+               return;
+       }
+}
+
+/**
+ * get_evt_struct: - Gets the next free event in pool
+ * @pool:      event_pool that contains the events to be searched
+ *
+ * Returns the next event in "free" state, and NULL if none are free.
+ * Note that no synchronization is done here, we assume the host_lock
+ * will syncrhonze things.
+*/
+static struct srp_event_struct *get_event_struct(struct event_pool *pool)
+{
+       int i;
+       int poolsize = pool->size;
+       int offset = pool->next;
+
+       for (i = 0; i < poolsize; i++) {
+               offset = (offset + 1) % poolsize;
+               if (!atomic_dec_if_positive(&pool->events[offset].free)) {
+                       pool->next = offset;
+                       return &pool->events[offset];
+               }
+       }
+
+       printk(KERN_ERR "ibmvscsi: found no event struct in pool!\n");
+       return NULL;
+}
+
+/**
+ * init_event_struct: Initialize fields in an event struct that are always 
+ *                    required.
+ * @evt:        The event
+ * @done:       Routine to call when the event is responded to
+ * @format:     SRP or MAD format
+ * @timeout:    timeout value set in the CRQ
+ */
+static void init_event_struct(struct srp_event_struct *evt_struct,
+                             void (*done) (struct srp_event_struct *),
+                             u8 format,
+                             int timeout)
+{
+       evt_struct->cmnd = NULL;
+       evt_struct->cmnd_done = NULL;
+       evt_struct->crq.format = format;
+       evt_struct->crq.timeout = timeout;
+       evt_struct->done = done;
+}
+
+/* ------------------------------------------------------------
+ * Routines for receiving SCSI responses from the hosting partition
+ */
+
+/**
+ * set_srp_direction: Set the fields in the srp related to data
+ *     direction and number of buffers based on the direction in
+ *     the scsi_cmnd and the number of buffers
+ */
+static void set_srp_direction(struct scsi_cmnd *cmd,
+                             struct srp_cmd *srp_cmd, 
+                             int numbuf)
+{
+       if (numbuf == 0)
+               return;
+       
+       if (numbuf == 1) {
+               if (cmd->sc_data_direction == DMA_TO_DEVICE)
+                       srp_cmd->data_out_format = SRP_DIRECT_BUFFER;
+               else 
+                       srp_cmd->data_in_format = SRP_DIRECT_BUFFER;
+       } else {
+               if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+                       srp_cmd->data_out_format = SRP_INDIRECT_BUFFER;
+                       srp_cmd->data_out_count = numbuf;
+               } else {
+                       srp_cmd->data_in_format = SRP_INDIRECT_BUFFER;
+                       srp_cmd->data_in_count = numbuf;
+               }
+       }
+}
+
+/**
+ * unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format
+ * @cmd:       srp_cmd whose additional_data member will be unmapped
+ * @dev:       device for which the memory is mapped
+ *
+*/
+static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev)
+{
+       int i;
+
+       if ((cmd->data_out_format == SRP_NO_BUFFER) &&
+           (cmd->data_in_format == SRP_NO_BUFFER))
+               return;
+       else if ((cmd->data_out_format == SRP_DIRECT_BUFFER) ||
+                (cmd->data_in_format == SRP_DIRECT_BUFFER)) {
+               struct memory_descriptor *data =
+                       (struct memory_descriptor *)cmd->additional_data;
+               dma_unmap_single(dev, data->virtual_address, data->length,
+                                DMA_BIDIRECTIONAL);
+       } else {
+               struct indirect_descriptor *indirect =
+                       (struct indirect_descriptor *)cmd->additional_data;
+               int num_mapped = indirect->head.length / 
+                       sizeof(indirect->list[0]);
+               for (i = 0; i < num_mapped; ++i) {
+                       struct memory_descriptor *data = &indirect->list[i];
+                       dma_unmap_single(dev,
+                                        data->virtual_address,
+                                        data->length, DMA_BIDIRECTIONAL);
+               }
+       }
+}
+
+/**
+ * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields
+ * @cmd:       Scsi_Cmnd with the scatterlist
+ * @srp_cmd:   srp_cmd that contains the memory descriptor
+ * @dev:       device for which to map dma memory
+ *
+ * Called by map_data_for_srp_cmd() when building srp cmd from scsi cmd.
+ * Returns 1 on success.
+*/
+static int map_sg_data(struct scsi_cmnd *cmd,
+                      struct srp_cmd *srp_cmd, struct device *dev)
+{
+
+       int i, sg_mapped;
+       u64 total_length = 0;
+       struct scatterlist *sg = cmd->request_buffer;
+       struct memory_descriptor *data =
+           (struct memory_descriptor *)srp_cmd->additional_data;
+       struct indirect_descriptor *indirect =
+           (struct indirect_descriptor *)data;
+
+       sg_mapped = dma_map_sg(dev, sg, cmd->use_sg, DMA_BIDIRECTIONAL);
+
+       if (sg_mapped == 0)
+               return 0;
+
+       set_srp_direction(cmd, srp_cmd, sg_mapped);
+
+       /* special case; we can use a single direct descriptor */
+       if (sg_mapped == 1) {
+               data->virtual_address = sg_dma_address(&sg[0]);
+               data->length = sg_dma_len(&sg[0]);
+               data->memory_handle = 0;
+               return 1;
+       }
+
+       if (sg_mapped > MAX_INDIRECT_BUFS) {
+               printk(KERN_ERR
+                      "ibmvscsi: More than %d mapped sg entries, got %d\n",
+                      MAX_INDIRECT_BUFS, sg_mapped);
+               return 0;
+       }
+
+       indirect->head.virtual_address = 0;
+       indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
+       indirect->head.memory_handle = 0;
+       for (i = 0; i < sg_mapped; ++i) {
+               struct memory_descriptor *descr = &indirect->list[i];
+               struct scatterlist *sg_entry = &sg[i];
+               descr->virtual_address = sg_dma_address(sg_entry);
+               descr->length = sg_dma_len(sg_entry);
+               descr->memory_handle = 0;
+               total_length += sg_dma_len(sg_entry);
+       }
+       indirect->total_length = total_length;
+
+       return 1;
+}
+
+/**
+ * map_single_data: - Maps memory and initializes memory decriptor fields
+ * @cmd:       struct scsi_cmnd with the memory to be mapped
+ * @srp_cmd:   srp_cmd that contains the memory descriptor
+ * @dev:       device for which to map dma memory
+ *
+ * Called by map_data_for_srp_cmd() when building srp cmd from scsi cmd.
+ * Returns 1 on success.
+*/
+static int map_single_data(struct scsi_cmnd *cmd,
+                          struct srp_cmd *srp_cmd, struct device *dev)
+{
+       struct memory_descriptor *data =
+           (struct memory_descriptor *)srp_cmd->additional_data;
+
+       data->virtual_address =
+               dma_map_single(dev, cmd->request_buffer,
+                              cmd->request_bufflen,
+                              DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(data->virtual_address)) {
+               printk(KERN_ERR
+                      "ibmvscsi: Unable to map request_buffer for command!\n");
+               return 0;
+       }
+       data->length = cmd->request_bufflen;
+       data->memory_handle = 0;
+
+       set_srp_direction(cmd, srp_cmd, 1);
+
+       return 1;
+}
+
+/**
+ * map_data_for_srp_cmd: - Calls functions to map data for srp cmds
+ * @cmd:       struct scsi_cmnd with the memory to be mapped
+ * @srp_cmd:   srp_cmd that contains the memory descriptor
+ * @dev:       dma device for which to map dma memory
+ *
+ * Called by scsi_cmd_to_srp_cmd() when converting scsi cmds to srp cmds 
+ * Returns 1 on success.
+*/
+static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
+                               struct srp_cmd *srp_cmd, struct device *dev)
+{
+       switch (cmd->sc_data_direction) {
+       case DMA_FROM_DEVICE:
+       case DMA_TO_DEVICE:
+               break;
+       case DMA_NONE:
+               return 1;
+       case DMA_BIDIRECTIONAL:
+               printk(KERN_ERR
+                      "ibmvscsi: Can't map DMA_BIDIRECTIONAL to read/write\n");
+               return 0;
+       default:
+               printk(KERN_ERR
+                      "ibmvscsi: Unknown data direction 0x%02x; can't map!\n",
+                      cmd->sc_data_direction);
+               return 0;
+       }
+
+       if (!cmd->request_buffer)
+               return 1;
+       if (cmd->use_sg)
+               return map_sg_data(cmd, srp_cmd, dev);
+       return map_single_data(cmd, srp_cmd, dev);
+}
+
+/* ------------------------------------------------------------
+ * Routines for sending and receiving SRPs
+ */
+/**
+ * ibmvscsi_send_srp_event: - Transforms event to u64 array and calls send_crq()
+ * @evt_struct:        evt_struct to be sent
+ * @hostdata:  ibmvscsi_host_data of host
+ *
+ * Returns the value returned from ibmvscsi_send_crq(). (Zero for success)
+ * Note that this routine assumes that host_lock is held for synchronization
+*/
+static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
+                                  struct ibmvscsi_host_data *hostdata)
+{
+       struct scsi_cmnd *cmnd = evt_struct->cmnd;
+       u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
+       int rc;
+
+       /* If we have exhausted our request limit, just fail this request.
+        * 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
+        */
+       if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
+           (atomic_dec_if_positive(&hostdata->request_limit) < 0)) {
+               /* See if the adapter is disabled */
+               if (atomic_read(&hostdata->request_limit) < 0) {
+                       if (cmnd)
+                               cmnd->result = DID_ERROR << 16;
+                       if (evt_struct->cmnd_done)
+                               evt_struct->cmnd_done(cmnd);
+                       unmap_cmd_data(&evt_struct->iu.srp.cmd,
+                                      hostdata->dev);
+                       free_event_struct(&hostdata->pool, evt_struct);
+                       return 0;
+               } else {
+                       printk("ibmvscsi: Warning, request_limit exceeded\n");
+                       unmap_cmd_data(&evt_struct->iu.srp.cmd,
+                                      hostdata->dev);
+                       free_event_struct(&hostdata->pool, evt_struct);
+                       return SCSI_MLQUEUE_HOST_BUSY;
+               }
+       }
+
+       /* Copy the IU into the transfer area */
+       *evt_struct->xfer_iu = evt_struct->iu;
+       evt_struct->xfer_iu->srp.generic.tag = (u64)evt_struct;
+
+       /* Add this to the sent list.  We need to do this 
+        * before we actually send 
+        * in case it comes back REALLY fast
+        */
+       list_add_tail(&evt_struct->list, &hostdata->sent);
+
+       if ((rc =
+            ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
+               list_del(&evt_struct->list);
+
+               cmnd = evt_struct->cmnd;
+               printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n",
+                      rc);
+               unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
+               free_event_struct(&hostdata->pool, evt_struct);
+               if (cmnd)
+                       cmnd->result = DID_ERROR << 16;
+               if (evt_struct->cmnd_done)
+                       evt_struct->cmnd_done(cmnd);
+       }
+
+       return 0;
+}
+
+/**
+ * handle_cmd_rsp: -  Handle responses from commands
+ * @evt_struct:        srp_event_struct to be handled
+ *
+ * Used as a callback by when sending scsi cmds.
+ * Gets called by ibmvscsi_handle_crq()
+*/
+static void handle_cmd_rsp(struct srp_event_struct *evt_struct)
+{
+       struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp;
+       struct scsi_cmnd *cmnd = evt_struct->cmnd;
+
+       if (cmnd) {
+               cmnd->result = rsp->status;
+               if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)
+                       memcpy(cmnd->sense_buffer,
+                              rsp->sense_and_response_data,
+                              rsp->sense_data_list_length);
+               unmap_cmd_data(&evt_struct->iu.srp.cmd, 
+                              evt_struct->hostdata->dev);
+
+               if (rsp->doover)
+                       cmnd->resid = rsp->data_out_residual_count;
+               else if (rsp->diover)
+                       cmnd->resid = rsp->data_in_residual_count;
+       }
+
+       if (evt_struct->cmnd_done)
+               evt_struct->cmnd_done(cmnd);
+}
+
+/**
+ * lun_from_dev: - Returns the lun of the scsi device
+ * @dev:       struct scsi_device
+ *
+*/
+static inline u16 lun_from_dev(struct scsi_device *dev)
+{
+       return (0x2 << 14) | (dev->id << 8) | (dev->channel << 5) | dev->lun;
+}
+
+/**
+ * ibmvscsi_queue: - The queuecommand function of the scsi template 
+ * @cmd:       struct scsi_cmnd to be executed
+ * @done:      Callback function to be called when cmd is completed
+*/
+static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
+                                void (*done) (struct scsi_cmnd *))
+{
+       struct srp_cmd *srp_cmd;
+       struct srp_event_struct *evt_struct;
+       struct ibmvscsi_host_data *hostdata =
+               (struct ibmvscsi_host_data *)&cmnd->device->host->hostdata;
+       u16 lun = lun_from_dev(cmnd->device);
+
+       evt_struct = get_event_struct(&hostdata->pool);
+       if (!evt_struct)
+               return SCSI_MLQUEUE_HOST_BUSY;
+
+       init_event_struct(evt_struct,
+                         handle_cmd_rsp,
+                         VIOSRP_SRP_FORMAT,
+                         cmnd->timeout);
+
+       evt_struct->cmnd = cmnd;
+       evt_struct->cmnd_done = done;
+
+       /* Set up the actual SRP IU */
+       srp_cmd = &evt_struct->iu.srp.cmd;
+       memset(srp_cmd, 0x00, sizeof(*srp_cmd));
+       srp_cmd->type = SRP_CMD_TYPE;
+       memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
+       srp_cmd->lun = ((u64) lun) << 48;
+
+       if (!map_data_for_srp_cmd(cmnd, srp_cmd, hostdata->dev)) {
+               printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n");
+               free_event_struct(&hostdata->pool, evt_struct);
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+
+       /* Fix up dma address of the buffer itself */
+       if ((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||
+           (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) {
+               struct indirect_descriptor *indirect =
+                   (struct indirect_descriptor *)srp_cmd->additional_data;
+               indirect->head.virtual_address = evt_struct->crq.IU_data_ptr +
+                   offsetof(struct srp_cmd, additional_data) +
+                   offsetof(struct indirect_descriptor, list);
+       }
+
+       return ibmvscsi_send_srp_event(evt_struct, hostdata);
+}
+
+/* ------------------------------------------------------------
+ * Routines for driver initialization
+ */
+/**
+ * adapter_info_rsp: - Handle response to MAD adapter info request
+ * @evt_struct:        srp_event_struct with the response
+ *
+ * Used as a "done" callback by when sending adapter_info. Gets called
+ * by ibmvscsi_handle_crq()
+*/
+static void adapter_info_rsp(struct srp_event_struct *evt_struct)
+{
+       struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
+       dma_unmap_single(hostdata->dev,
+                        evt_struct->iu.mad.adapter_info.buffer,
+                        evt_struct->iu.mad.adapter_info.common.length,
+                        DMA_BIDIRECTIONAL);
+
+       if (evt_struct->xfer_iu->mad.adapter_info.common.status) {
+               printk("ibmvscsi: error %d getting adapter info\n",
+                      evt_struct->xfer_iu->mad.adapter_info.common.status);
+       } else {
+               printk("ibmvscsi: host srp version: %s, "
+                      "host partition %s (%d), OS %d\n",
+                      hostdata->madapter_info.srp_version,
+                      hostdata->madapter_info.partition_name,
+                      hostdata->madapter_info.partition_number,
+                      hostdata->madapter_info.os_type);
+       }
+}
+
+/**
+ * send_mad_adapter_info: - Sends the mad adapter info request
+ *      and stores the result so it can be retrieved with
+ *      sysfs.  We COULD consider causing a failure if the
+ *      returned SRP version doesn't match ours.
+ * @hostdata:  ibmvscsi_host_data of host
+ * 
+ * Returns zero if successful.
+*/
+static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
+{
+       struct viosrp_adapter_info *req;
+       struct srp_event_struct *evt_struct;
+       
+       memset(&hostdata->madapter_info, 0x00, sizeof(hostdata->madapter_info));
+       
+       evt_struct = get_event_struct(&hostdata->pool);
+       if (!evt_struct) {
+               printk(KERN_ERR "ibmvscsi: couldn't allocate an event "
+                      "for ADAPTER_INFO_REQ!\n");
+               return;
+       }
+
+       init_event_struct(evt_struct,
+                         adapter_info_rsp,
+                         VIOSRP_MAD_FORMAT,
+                         init_timeout * HZ);
+       
+       req = &evt_struct->iu.mad.adapter_info;
+       memset(req, 0x00, sizeof(*req));
+       
+       req->common.type = VIOSRP_ADAPTER_INFO_TYPE;
+       req->common.length = sizeof(hostdata->madapter_info);
+       req->buffer = dma_map_single(hostdata->dev,
+                                    &hostdata->madapter_info,
+                                    sizeof(hostdata->madapter_info),
+                                    DMA_BIDIRECTIONAL);
+
+       if (dma_mapping_error(req->buffer)) {
+               printk(KERN_ERR
+                      "ibmvscsi: Unable to map request_buffer "
+                      "for adapter_info!\n");
+               free_event_struct(&hostdata->pool, evt_struct);
+               return;
+       }
+       
+       if (ibmvscsi_send_srp_event(evt_struct, hostdata))
+               printk(KERN_ERR "ibmvscsi: couldn't send ADAPTER_INFO_REQ!\n");
+};
+
+/**
+ * login_rsp: - Handle response to SRP login request
+ * @evt_struct:        srp_event_struct with the response
+ *
+ * Used as a "done" callback by when sending srp_login. Gets called
+ * by ibmvscsi_handle_crq()
+*/
+static void login_rsp(struct srp_event_struct *evt_struct)
+{
+       struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
+       switch (evt_struct->xfer_iu->srp.generic.type) {
+       case SRP_LOGIN_RSP_TYPE:        /* it worked! */
+               break;
+       case SRP_LOGIN_REJ_TYPE:        /* refused! */
+               printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REQ rejected\n");
+               /* Login failed.  */
+               atomic_set(&hostdata->request_limit, -1);
+               return;
+       default:
+               printk(KERN_ERR
+                      "ibmvscsi: Invalid login response typecode 0x%02x!\n",
+                      evt_struct->xfer_iu->srp.generic.type);
+               /* Login failed.  */
+               atomic_set(&hostdata->request_limit, -1);
+               return;
+       }
+
+       printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
+
+       if (evt_struct->xfer_iu->srp.login_rsp.request_limit_delta >
+           (max_requests - 2))
+               evt_struct->xfer_iu->srp.login_rsp.request_limit_delta =
+                   max_requests - 2;
+
+       /* Now we know what the real request-limit is */
+       atomic_set(&hostdata->request_limit,
+                  evt_struct->xfer_iu->srp.login_rsp.request_limit_delta);
+
+       hostdata->host->can_queue =
+           evt_struct->xfer_iu->srp.login_rsp.request_limit_delta - 2;
+
+       if (hostdata->host->can_queue < 1) {
+               printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n");
+               return;
+       }
+
+       send_mad_adapter_info(hostdata);
+       return;
+}
+
+/**
+ * send_srp_login: - Sends the srp login
+ * @hostdata:  ibmvscsi_host_data of host
+ * 
+ * Returns zero if successful.
+*/
+static int send_srp_login(struct ibmvscsi_host_data *hostdata)
+{
+       int rc;
+       unsigned long flags;
+       struct srp_login_req *login;
+       struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool);
+       if (!evt_struct) {
+               printk(KERN_ERR
+                      "ibmvscsi: couldn't allocate an event for login req!\n");
+               return FAILED;
+       }
+
+       init_event_struct(evt_struct,
+                         login_rsp,
+                         VIOSRP_SRP_FORMAT,
+                         init_timeout * HZ);
+
+       login = &evt_struct->iu.srp.login_req;
+       login->type = SRP_LOGIN_REQ_TYPE;
+       login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu);
+       login->required_buffer_formats = 0x0006;
+       
+       /* Start out with a request limit of 1, since this is negotiated in
+        * the login request we are just sending
+        */
+       atomic_set(&hostdata->request_limit, 1);
+
+       spin_lock_irqsave(hostdata->host->host_lock, flags);
+       rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
+       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+       return rc;
+};
+
+/**
+ * sync_completion: Signal that a synchronous command has completed
+ * Note that after returning from this call, the evt_struct is freed.
+ * the caller waiting on this completion shouldn't touch the evt_struct
+ * again.
+ */
+static void sync_completion(struct srp_event_struct *evt_struct)
+{
+       complete(&evt_struct->comp);
+}
+
+/**
+ * ibmvscsi_abort: Abort a command...from scsi host template
+ * send this over to the server and wait synchronously for the response
+ */
+static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
+{
+       struct ibmvscsi_host_data *hostdata =
+           (struct ibmvscsi_host_data *)cmd->device->host->hostdata;
+       struct srp_tsk_mgmt *tsk_mgmt;
+       struct srp_event_struct *evt;
+       struct srp_event_struct *tmp_evt, *found_evt;
+       u16 lun = lun_from_dev(cmd->device);
+
+       /* First, find this command in our sent list so we can figure
+        * out the correct tag
+        */
+       found_evt = NULL;
+       list_for_each_entry(tmp_evt, &hostdata->sent, list) {
+               if (tmp_evt->cmnd == cmd) {
+                       found_evt = tmp_evt;
+                       break;
+               }
+       }
+
+       if (!found_evt) 
+               return FAILED;
+
+       evt = get_event_struct(&hostdata->pool);
+       if (evt == NULL) {
+               printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");
+               return FAILED;
+       }
+       
+       init_event_struct(evt,
+                         sync_completion,
+                         VIOSRP_SRP_FORMAT,
+                         init_timeout * HZ);
+
+       tsk_mgmt = &evt->iu.srp.tsk_mgmt;
+       
+       /* Set up an abort SRP command */
+       memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
+       tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+       tsk_mgmt->lun = ((u64) lun) << 48;
+       tsk_mgmt->task_mgmt_flags = 0x01;       /* ABORT TASK */
+       tsk_mgmt->managed_task_tag = (u64) found_evt;
+
+       printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
+              tsk_mgmt->lun, tsk_mgmt->managed_task_tag);
+
+       init_completion(&evt->comp);
+       if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+               printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
+               return FAILED;
+       }
+
+       spin_unlock_irq(hostdata->host->host_lock);
+       wait_for_completion(&evt->comp);
+       spin_lock_irq(hostdata->host->host_lock);
+
+       /* Because we dropped the spinlock above, it's possible
+        * The event is no longer in our list.  Make sure it didn't
+        * complete while we were aborting
+        */
+       found_evt = NULL;
+       list_for_each_entry(tmp_evt, &hostdata->sent, list) {
+               if (tmp_evt->cmnd == cmd) {
+                       found_evt = tmp_evt;
+                       break;
+               }
+       }
+
+       printk(KERN_INFO
+              "ibmvscsi: successfully aborted task tag 0x%lx\n",
+              tsk_mgmt->managed_task_tag);
+
+       if (found_evt == NULL)
+               return SUCCESS;
+
+       cmd->result = (DID_ABORT << 16);
+       list_del(&found_evt->list);
+       unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
+       free_event_struct(&found_evt->hostdata->pool, found_evt);
+       atomic_inc(&hostdata->request_limit);
+       return SUCCESS;
+}
+
+/**
+ * ibmvscsi_eh_device_reset_handler: Reset a single LUN...from scsi host 
+ * template send this over to the server and wait synchronously for the 
+ * response
+ */
+static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
+{
+       struct ibmvscsi_host_data *hostdata =
+           (struct ibmvscsi_host_data *)cmd->device->host->hostdata;
+
+       struct srp_tsk_mgmt *tsk_mgmt;
+       struct srp_event_struct *evt;
+       struct srp_event_struct *tmp_evt, *pos;
+       u16 lun = lun_from_dev(cmd->device);
+
+       evt = get_event_struct(&hostdata->pool);
+       if (evt == NULL) {
+               printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");
+               return FAILED;
+       }
+       
+       init_event_struct(evt,
+                         sync_completion,
+                         VIOSRP_SRP_FORMAT,
+                         init_timeout * HZ);
+
+       tsk_mgmt = &evt->iu.srp.tsk_mgmt;
+
+       /* Set up a lun reset SRP command */
+       memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
+       tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+       tsk_mgmt->lun = ((u64) lun) << 48;
+       tsk_mgmt->task_mgmt_flags = 0x08;       /* LUN RESET */
+
+       printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
+              tsk_mgmt->lun);
+
+       init_completion(&evt->comp);
+       if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+               printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
+               return FAILED;
+       }
+
+       spin_unlock_irq(hostdata->host->host_lock);
+       wait_for_completion(&evt->comp);
+       spin_lock_irq(hostdata->host->host_lock);
+
+       /* We need to find all commands for this LUN that have not yet been
+        * responded to, and fail them with DID_RESET
+        */
+       list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
+               if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) {
+                       if (tmp_evt->cmnd)
+                               tmp_evt->cmnd->result = (DID_RESET << 16);
+                       list_del(&tmp_evt->list);
+                       unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt->hostdata->dev);
+                       free_event_struct(&tmp_evt->hostdata->pool,
+                                                  tmp_evt);
+                       atomic_inc(&hostdata->request_limit);
+                       if (tmp_evt->cmnd_done)
+                               tmp_evt->cmnd_done(tmp_evt->cmnd);
+                       else if (tmp_evt->done)
+                               tmp_evt->done(tmp_evt);
+               }
+       }
+       return SUCCESS;
+}
+
+/**
+ * purge_requests: Our virtual adapter just shut down.  purge any sent requests
+ * @hostdata:    the adapter
+ */
+static void purge_requests(struct ibmvscsi_host_data *hostdata)
+{
+       struct srp_event_struct *tmp_evt, *pos;
+       unsigned long flags;
+
+       spin_lock_irqsave(hostdata->host->host_lock, flags);
+       list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
+               list_del(&tmp_evt->list);
+               if (tmp_evt->cmnd) {
+                       tmp_evt->cmnd->result = (DID_ERROR << 16);
+                       unmap_cmd_data(&tmp_evt->iu.srp.cmd, 
+                                      tmp_evt->hostdata->dev);
+                       if (tmp_evt->cmnd_done)
+                               tmp_evt->cmnd_done(tmp_evt->cmnd);
+               } else {
+                       if (tmp_evt->done) {
+                               tmp_evt->done(tmp_evt);
+                       }
+               }
+               free_event_struct(&tmp_evt->hostdata->pool, tmp_evt);
+       }
+       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+}
+
+/**
+ * ibmvscsi_handle_crq: - Handles and frees received events in the CRQ
+ * @crq:       Command/Response queue
+ * @hostdata:  ibmvscsi_host_data of host
+ *
+*/
+void ibmvscsi_handle_crq(struct viosrp_crq *crq,
+                        struct ibmvscsi_host_data *hostdata)
+{
+       unsigned long flags;
+       struct srp_event_struct *evt_struct =
+           (struct srp_event_struct *)crq->IU_data_ptr;
+       switch (crq->valid) {
+       case 0xC0:              /* initialization */
+               switch (crq->format) {
+               case 0x01:      /* Initialization message */
+                       printk(KERN_INFO "ibmvscsi: partner initialized\n");
+                       /* Send back a response */
+                       if (ibmvscsi_send_crq(hostdata,
+                                             0xC002000000000000LL, 0) == 0) {
+                               /* Now login */
+                               send_srp_login(hostdata);
+                       } else {
+                               printk(KERN_ERR
+                                      "ibmvscsi: Unable to send init rsp\n");
+                       }
+
+                       break;
+               case 0x02:      /* Initialization response */
+                       printk(KERN_INFO
+                              "ibmvscsi: partner initialization complete\n");
+
+                       /* Now login */
+                       send_srp_login(hostdata);
+                       break;
+               default:
+                       printk(KERN_ERR "ibmvscsi: unknown crq message type\n");
+               }
+               return;
+       case 0xFF:              /* Hypervisor telling us the connection is closed */
+               printk(KERN_INFO "ibmvscsi: Virtual adapter failed!\n");
+
+               atomic_set(&hostdata->request_limit, -1);
+               purge_requests(hostdata);
+               ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
+               return;
+       case 0x80:              /* real payload */
+               break;
+       default:
+               printk(KERN_ERR
+                      "ibmvscsi: got an invalid message type 0x%02x\n",
+                      crq->valid);
+               return;
+       }
+
+       /* The only kind of payload CRQs we should get are responses to
+        * things we send. Make sure this response is to something we
+        * actually sent
+        */
+       if (!valid_event_struct(&hostdata->pool, evt_struct)) {
+               printk(KERN_ERR
+                      "ibmvscsi: returned correlation_token 0x%p is invalid!\n",
+                      (void *)crq->IU_data_ptr);
+               return;
+       }
+
+       if (crq->format == VIOSRP_SRP_FORMAT)
+               atomic_add(evt_struct->xfer_iu->srp.rsp.request_limit_delta,
+                          &hostdata->request_limit);
+
+       if (evt_struct->done)
+               evt_struct->done(evt_struct);
+       else
+               printk(KERN_ERR
+                      "ibmvscsi: returned done() is NULL; not running it!\n");
+
+       /*
+        * Lock the host_lock before messing with these structures, since we
+        * are running in a task context
+        */
+       spin_lock_irqsave(evt_struct->hostdata->host->host_lock, flags);
+       list_del(&evt_struct->list);
+       free_event_struct(&evt_struct->hostdata->pool, evt_struct);
+       spin_unlock_irqrestore(evt_struct->hostdata->host->host_lock, flags);
+}
+
+/**
+ * ibmvscsi_get_host_config: Send the command to the server to get host
+ * configuration data.  The data is opaque to us.
+ */
+static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
+                                  unsigned char *buffer, int length)
+{
+       struct viosrp_host_config *host_config;
+       struct srp_event_struct *evt_struct;
+       int rc;
+
+       evt_struct = get_event_struct(&hostdata->pool);
+       if (!evt_struct) {
+               printk(KERN_ERR
+                      "ibmvscsi: could't allocate event for HOST_CONFIG!\n");
+               return -1;
+       }
+
+       init_event_struct(evt_struct,
+                         sync_completion,
+                         VIOSRP_MAD_FORMAT,
+                         init_timeout * HZ);
+
+       host_config = &evt_struct->iu.mad.host_config;
+
+       /* Set up a lun reset SRP command */
+       memset(host_config, 0x00, sizeof(*host_config));
+       host_config->common.type = VIOSRP_HOST_CONFIG_TYPE;
+       host_config->common.length = length;
+       host_config->buffer = dma_map_single(hostdata->dev, buffer, length,
+                                           DMA_BIDIRECTIONAL);
+
+       if (dma_mapping_error(host_config->buffer)) {
+               printk(KERN_ERR
+                      "ibmvscsi: dma_mapping error " "getting host config\n");
+               free_event_struct(&hostdata->pool, evt_struct);
+               return -1;
+       }
+
+       init_completion(&evt_struct->comp);
+       rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
+       if (rc == 0) {
+               wait_for_completion(&evt_struct->comp);
+               dma_unmap_single(hostdata->dev, host_config->buffer,
+                                length, DMA_BIDIRECTIONAL);
+       }
+
+       return rc;
+}
+
+/* ------------------------------------------------------------
+ * sysfs attributes
+ */
+static ssize_t show_host_srp_version(struct class_device *class_dev, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(class_dev);
+       struct ibmvscsi_host_data *hostdata =
+           (struct ibmvscsi_host_data *)shost->hostdata;
+       int len;
+
+       len = snprintf(buf, PAGE_SIZE, "%s\n",
+                      hostdata->madapter_info.srp_version);
+       return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_srp_version = {
+       .attr = {
+                .name = "srp_version",
+                .mode = S_IRUGO,
+                },
+       .show = show_host_srp_version,
+};
+
+static ssize_t show_host_partition_name(struct class_device *class_dev,
+                                       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(class_dev);
+       struct ibmvscsi_host_data *hostdata =
+           (struct ibmvscsi_host_data *)shost->hostdata;
+       int len;
+
+       len = snprintf(buf, PAGE_SIZE, "%s\n",
+                      hostdata->madapter_info.partition_name);
+       return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_partition_name = {
+       .attr = {
+                .name = "partition_name",
+                .mode = S_IRUGO,
+                },
+       .show = show_host_partition_name,
+};
+
+static ssize_t show_host_partition_number(struct class_device *class_dev,
+                                         char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(class_dev);
+       struct ibmvscsi_host_data *hostdata =
+           (struct ibmvscsi_host_data *)shost->hostdata;
+       int len;
+
+       len = snprintf(buf, PAGE_SIZE, "%d\n",
+                      hostdata->madapter_info.partition_number);
+       return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_partition_number = {
+       .attr = {
+                .name = "partition_number",
+                .mode = S_IRUGO,
+                },
+       .show = show_host_partition_number,
+};
+
+static ssize_t show_host_mad_version(struct class_device *class_dev, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(class_dev);
+       struct ibmvscsi_host_data *hostdata =
+           (struct ibmvscsi_host_data *)shost->hostdata;
+       int len;
+
+       len = snprintf(buf, PAGE_SIZE, "%d\n",
+                      hostdata->madapter_info.mad_version);
+       return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_mad_version = {
+       .attr = {
+                .name = "mad_version",
+                .mode = S_IRUGO,
+                },
+       .show = show_host_mad_version,
+};
+
+static ssize_t show_host_os_type(struct class_device *class_dev, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(class_dev);
+       struct ibmvscsi_host_data *hostdata =
+           (struct ibmvscsi_host_data *)shost->hostdata;
+       int len;
+
+       len = snprintf(buf, PAGE_SIZE, "%d\n", hostdata->madapter_info.os_type);
+       return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_os_type = {
+       .attr = {
+                .name = "os_type",
+                .mode = S_IRUGO,
+                },
+       .show = show_host_os_type,
+};
+
+static ssize_t show_host_config(struct class_device *class_dev, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(class_dev);
+       struct ibmvscsi_host_data *hostdata =
+           (struct ibmvscsi_host_data *)shost->hostdata;
+
+       /* returns null-terminated host config data */
+       if (ibmvscsi_do_host_config(hostdata, buf, PAGE_SIZE) == 0)
+               return strlen(buf);
+       else
+               return 0;
+}
+
+static struct class_device_attribute ibmvscsi_host_config = {
+       .attr = {
+                .name = "config",
+                .mode = S_IRUGO,
+                },
+       .show = show_host_config,
+};
+
+static struct class_device_attribute *ibmvscsi_attrs[] = {
+       &ibmvscsi_host_srp_version,
+       &ibmvscsi_host_partition_name,
+       &ibmvscsi_host_partition_number,
+       &ibmvscsi_host_mad_version,
+       &ibmvscsi_host_os_type,
+       &ibmvscsi_host_config,
+       NULL
+};
+
+/* ------------------------------------------------------------
+ * SCSI driver registration
+ */
+static struct scsi_host_template driver_template = {
+       .module = THIS_MODULE,
+       .name = "IBM POWER Virtual SCSI Adapter " IBMVSCSI_VERSION,
+       .proc_name = "ibmvscsi",
+       .queuecommand = ibmvscsi_queuecommand,
+       .eh_abort_handler = ibmvscsi_eh_abort_handler,
+       .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
+       .cmd_per_lun = 16,
+       .can_queue = 1,         /* Updated after SRP_LOGIN */
+       .this_id = -1,
+       .sg_tablesize = MAX_INDIRECT_BUFS,
+       .use_clustering = ENABLE_CLUSTERING,
+       .shost_attrs = ibmvscsi_attrs,
+};
+
+/**
+ * Called by bus code for each adapter
+ */
+static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
+{
+       struct ibmvscsi_host_data *hostdata;
+       struct Scsi_Host *host;
+       struct device *dev = &vdev->dev;
+       unsigned long wait_switch = 0;
+
+       vdev->dev.driver_data = NULL;
+
+       host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
+       if (!host) {
+               printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
+               goto scsi_host_alloc_failed;
+       }
+
+       hostdata = (struct ibmvscsi_host_data *)host->hostdata;
+       memset(hostdata, 0x00, sizeof(*hostdata));
+       INIT_LIST_HEAD(&hostdata->sent);
+       hostdata->host = host;
+       hostdata->dev = dev;
+       atomic_set(&hostdata->request_limit, -1);
+
+       if (ibmvscsi_init_crq_queue(&hostdata->queue, hostdata,
+                                   max_requests) != 0) {
+               printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
+               goto init_crq_failed;
+       }
+       if (initialize_event_pool(&hostdata->pool, max_requests, hostdata) != 0) {
+               printk(KERN_ERR "ibmvscsi: couldn't initialize event pool\n");
+               goto init_pool_failed;
+       }
+
+       host->max_lun = 8;
+       host->max_id = max_id;
+       host->max_channel = max_channel;
+
+       if (scsi_add_host(hostdata->host, hostdata->dev))
+               goto add_host_failed;
+
+       /* Try to send an initialization message.  Note that this is allowed
+        * to fail if the other end is not acive.  In that case we don't
+        * want to scan
+        */
+       if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0) {
+               /*
+                * Wait around max init_timeout secs for the adapter to finish
+                * initializing. When we are done initializing, we will have a
+                * valid request_limit.  We don't want Linux scanning before
+                * we are ready.
+                */
+               for (wait_switch = jiffies + (init_timeout * HZ);
+                    time_before(jiffies, wait_switch) &&
+                    atomic_read(&hostdata->request_limit) < 0;) {
+
+                       set_current_state(TASK_UNINTERRUPTIBLE);
+                       schedule_timeout(HZ / 100);
+               }
+
+               /* if we now have a valid request_limit, initiate a scan */
+               if (atomic_read(&hostdata->request_limit) > 0)
+                       scsi_scan_host(host);
+       }
+
+       vdev->dev.driver_data = hostdata;
+       return 0;
+
+      add_host_failed:
+       release_event_pool(&hostdata->pool, hostdata);
+      init_pool_failed:
+       ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests);
+      init_crq_failed:
+       scsi_host_put(host);
+      scsi_host_alloc_failed:
+       return -1;
+}
+
+static int ibmvscsi_remove(struct vio_dev *vdev)
+{
+       struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
+       release_event_pool(&hostdata->pool, hostdata);
+       ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
+                                  max_requests);
+       
+       scsi_remove_host(hostdata->host);
+       scsi_host_put(hostdata->host);
+
+       return 0;
+}
+
+/**
+ * ibmvscsi_device_table: Used by vio.c to match devices in the device tree we 
+ * support.
+ */
+static struct vio_device_id ibmvscsi_device_table[] __devinitdata = {
+       {"vscsi", "IBM,v-scsi"},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(vio, ibmvscsi_device_table);
+static struct vio_driver ibmvscsi_driver = {
+       .name = "ibmvscsi",
+       .id_table = ibmvscsi_device_table,
+       .probe = ibmvscsi_probe,
+       .remove = ibmvscsi_remove
+};
+
+int __init ibmvscsi_module_init(void)
+{
+       return vio_register_driver(&ibmvscsi_driver);
+}
+
+void __exit ibmvscsi_module_exit(void)
+{
+       vio_unregister_driver(&ibmvscsi_driver);
+}
+
+module_init(ibmvscsi_module_init);
+module_exit(ibmvscsi_module_exit);
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
new file mode 100644 (file)
index 0000000..dbe1735
--- /dev/null
@@ -0,0 +1,108 @@
+/* ------------------------------------------------------------
+ * ibmvscsi.h
+ * (C) Copyright IBM Corporation 1994, 2003
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.com)
+ *          Dave Boutcher (sleddog@us.ibm.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
+ *
+ * ------------------------------------------------------------
+ * Emulation of a SCSI host adapter for Virtual I/O devices
+ *
+ * This driver allows the Linux SCSI peripheral drivers to directly
+ * access devices in the hosting partition, either on an iSeries
+ * hypervisor system or a converged hypervisor system.
+ */
+#ifndef IBMVSCSI_H
+#define IBMVSCSI_H
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include "viosrp.h"
+
+struct scsi_cmnd;
+struct Scsi_Host;
+
+/* Number of indirect bufs...the list of these has to fit in the
+ * additional data of the srp_cmd struct along with the indirect
+ * descriptor
+ */
+#define MAX_INDIRECT_BUFS 10
+
+/* ------------------------------------------------------------
+ * Data Structures
+ */
+/* an RPA command/response transport queue */
+struct crq_queue {
+       struct viosrp_crq *msgs;
+       int size, cur;
+       dma_addr_t msg_token;
+       spinlock_t lock;
+};
+
+/* a unit of work for the hosting partition */
+struct srp_event_struct {
+       union viosrp_iu *xfer_iu;
+       struct scsi_cmnd *cmnd;
+       struct list_head list;
+       void (*done) (struct srp_event_struct *);
+       struct viosrp_crq crq;
+       struct ibmvscsi_host_data *hostdata;
+       atomic_t free;
+       union viosrp_iu iu;
+       void (*cmnd_done) (struct scsi_cmnd *);
+       struct completion comp;
+};
+
+/* a pool of event structs for use */
+struct event_pool {
+       struct srp_event_struct *events;
+       u32 size;
+       int next;
+       union viosrp_iu *iu_storage;
+       dma_addr_t iu_token;
+};
+
+/* all driver data associated with a host adapter */
+struct ibmvscsi_host_data {
+       atomic_t request_limit;
+       struct device *dev;
+       struct event_pool pool;
+       struct crq_queue queue;
+       struct tasklet_struct srp_task;
+       struct list_head sent;
+       struct Scsi_Host *host;
+       struct mad_adapter_info_data madapter_info;
+};
+
+/* routines for managing a command/response queue */
+int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+                           struct ibmvscsi_host_data *hostdata,
+                           int max_requests);
+void ibmvscsi_release_crq_queue(struct crq_queue *queue,
+                               struct ibmvscsi_host_data *hostdata,
+                               int max_requests);
+void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+                             struct ibmvscsi_host_data *hostdata);
+
+void ibmvscsi_handle_crq(struct viosrp_crq *crq,
+                        struct ibmvscsi_host_data *hostdata);
+int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
+                     u64 word1, u64 word2);
+
+#endif                         /* IBMVSCSI_H */
diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
new file mode 100644 (file)
index 0000000..e9202f2
--- /dev/null
@@ -0,0 +1,144 @@
+/* ------------------------------------------------------------
+ * iSeries_vscsi.c
+ * (C) Copyright IBM Corporation 1994, 2003
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.com)
+ *          Dave Boutcher (sleddog@us.ibm.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
+ *
+ * ------------------------------------------------------------
+ * iSeries-specific functions of the SCSI host adapter for Virtual I/O devices
+ *
+ * This driver allows the Linux SCSI peripheral drivers to directly
+ * access devices in the hosting partition, either on an iSeries
+ * hypervisor system or a converged hypervisor system.
+ */
+
+#include <asm/iSeries/vio.h>
+#include <asm/iSeries/HvLpEvent.h>
+#include <asm/iSeries/HvTypes.h>
+#include <asm/iSeries/HvLpConfig.h>
+#include <asm/vio.h>
+#include <linux/device.h>
+#include "ibmvscsi.h"
+
+/* global variables */
+static struct ibmvscsi_host_data *single_host_data;
+
+/* ------------------------------------------------------------
+ * Routines for direct interpartition interaction
+ */
+struct srp_lp_event {
+       struct HvLpEvent lpevt; /* 0x00-0x17          */
+       u32 reserved1;          /* 0x18-0x1B; unused  */
+       u16 version;            /* 0x1C-0x1D; unused  */
+       u16 subtype_rc;         /* 0x1E-0x1F; unused  */
+       struct viosrp_crq crq;  /* 0x20-0x3F          */
+};
+
+/** 
+ * standard interface for handling logical partition events.
+ */
+static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
+{
+       struct srp_lp_event *evt = (struct srp_lp_event *)lpevt;
+
+       if (!evt) {
+               printk(KERN_ERR "ibmvscsi: received null event\n");
+               return;
+       }
+
+       if (single_host_data == NULL) {
+               printk(KERN_ERR
+                      "ibmvscsi: received event, no adapter present\n");
+               return;
+       }
+
+       ibmvscsi_handle_crq(&evt->crq, single_host_data);
+}
+
+/* ------------------------------------------------------------
+ * Routines for driver initialization
+ */
+int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+                           struct ibmvscsi_host_data *hostdata,
+                           int max_requests)
+{
+       int rc;
+
+       single_host_data = hostdata;
+       rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, 0);
+       if (rc < 0) {
+               printk("viopath_open failed with rc %d in open_event_path\n",
+                      rc);
+               goto viopath_open_failed;
+       }
+
+       rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event);
+       if (rc < 0) {
+               printk("vio_setHandler failed with rc %d in open_event_path\n",
+                      rc);
+               goto vio_setHandler_failed;
+       }
+       return 0;
+
+      vio_setHandler_failed:
+       viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
+      viopath_open_failed:
+       return -1;
+}
+
+void ibmvscsi_release_crq_queue(struct crq_queue *queue,
+                               struct ibmvscsi_host_data *hostdata,
+                               int max_requests)
+{
+       vio_clearHandler(viomajorsubtype_scsi);
+       viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
+}
+
+/**
+ * reset_crq_queue: - resets a crq after a failure
+ * @queue:     crq_queue to initialize and register
+ * @hostdata:  ibmvscsi_host_data of host
+ *
+ * no-op for iSeries
+ */
+void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+                             struct ibmvscsi_host_data *hostdata)
+{
+}
+
+/**
+ * ibmvscsi_send_crq: - Send a CRQ
+ * @hostdata:  the adapter
+ * @word1:     the first 64 bits of the data
+ * @word2:     the second 64 bits of the data
+ */
+int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+{
+       single_host_data = hostdata;
+       return HvCallEvent_signalLpEventFast(viopath_hostLp,
+                                            HvLpEvent_Type_VirtualIo,
+                                            viomajorsubtype_scsi,
+                                            HvLpEvent_AckInd_NoAck,
+                                            HvLpEvent_AckType_ImmediateAck,
+                                            viopath_sourceinst(viopath_hostLp),
+                                            viopath_targetinst(viopath_hostLp),
+                                            0,
+                                            VIOVERSION << 16, word1, word2, 0,
+                                            0);
+}
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
new file mode 100644 (file)
index 0000000..b4e8265
--- /dev/null
@@ -0,0 +1,260 @@
+/* ------------------------------------------------------------
+ * rpa_vscsi.c
+ * (C) Copyright IBM Corporation 1994, 2003
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.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
+ *
+ * ------------------------------------------------------------
+ * RPA-specific functions of the SCSI host adapter for Virtual I/O devices
+ *
+ * This driver allows the Linux SCSI peripheral drivers to directly
+ * access devices in the hosting partition, either on an iSeries
+ * hypervisor system or a converged hypervisor system.
+ */
+
+#include <asm/vio.h>
+#include <asm/iommu.h>
+#include <asm/hvcall.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include "ibmvscsi.h"
+
+/* ------------------------------------------------------------
+ * Routines for managing the command/response queue
+ */
+/**
+ * ibmvscsi_handle_event: - Interrupt handler for crq events
+ * @irq:       number of irq to handle, not used
+ * @dev_instance: ibmvscsi_host_data of host that received interrupt
+ * @regs:      pt_regs with registers
+ *
+ * Disables interrupts and schedules srp_task
+ * Always returns IRQ_HANDLED
+ */
+static irqreturn_t ibmvscsi_handle_event(int irq,
+                                        void *dev_instance,
+                                        struct pt_regs *regs)
+{
+       struct ibmvscsi_host_data *hostdata =
+           (struct ibmvscsi_host_data *)dev_instance;
+       vio_disable_interrupts(to_vio_dev(hostdata->dev));
+       tasklet_schedule(&hostdata->srp_task);
+       return IRQ_HANDLED;
+}
+
+/**
+ * release_crq_queue: - Deallocates data and unregisters CRQ
+ * @queue:     crq_queue to initialize and register
+ * @host_data: ibmvscsi_host_data of host
+ *
+ * Frees irq, deallocates a page for messages, unmaps dma, and unregisters
+ * the crq with the hypervisor.
+ */
+void ibmvscsi_release_crq_queue(struct crq_queue *queue,
+                               struct ibmvscsi_host_data *hostdata,
+                               int max_requests)
+{
+       long rc;
+       struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+       free_irq(vdev->irq, (void *)hostdata);
+       tasklet_kill(&hostdata->srp_task);
+       do {
+               rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+       } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+       dma_unmap_single(hostdata->dev,
+                        queue->msg_token,
+                        queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
+       free_page((unsigned long)queue->msgs);
+}
+
+/**
+ * crq_queue_next_crq: - Returns the next entry in message queue
+ * @queue:     crq_queue to use
+ *
+ * Returns pointer to next entry in queue, or NULL if there are no new 
+ * entried in the CRQ.
+ */
+static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue)
+{
+       struct viosrp_crq *crq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&queue->lock, flags);
+       crq = &queue->msgs[queue->cur];
+       if (crq->valid & 0x80) {
+               if (++queue->cur == queue->size)
+                       queue->cur = 0;
+       } else
+               crq = NULL;
+       spin_unlock_irqrestore(&queue->lock, flags);
+
+       return crq;
+}
+
+/**
+ * ibmvscsi_send_crq: - Send a CRQ
+ * @hostdata:  the adapter
+ * @word1:     the first 64 bits of the data
+ * @word2:     the second 64 bits of the data
+ */
+int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+{
+       struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+       return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2);
+}
+
+/**
+ * ibmvscsi_task: - Process srps asynchronously
+ * @data:      ibmvscsi_host_data of host
+ */
+static void ibmvscsi_task(void *data)
+{
+       struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
+       struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+       struct viosrp_crq *crq;
+       int done = 0;
+
+       while (!done) {
+               /* Pull all the valid messages off the CRQ */
+               while ((crq = crq_queue_next_crq(&hostdata->queue)) != NULL) {
+                       ibmvscsi_handle_crq(crq, hostdata);
+                       crq->valid = 0x00;
+               }
+
+               vio_enable_interrupts(vdev);
+               if ((crq = crq_queue_next_crq(&hostdata->queue)) != NULL) {
+                       vio_disable_interrupts(vdev);
+                       ibmvscsi_handle_crq(crq, hostdata);
+                       crq->valid = 0x00;
+               } else {
+                       done = 1;
+               }
+       }
+}
+
+/**
+ * initialize_crq_queue: - Initializes and registers CRQ with hypervisor
+ * @queue:     crq_queue to initialize and register
+ * @hostdata:  ibmvscsi_host_data of host
+ *
+ * Allocates a page for messages, maps it for dma, and registers
+ * the crq with the hypervisor.
+ * Returns zero on success.
+ */
+int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+                           struct ibmvscsi_host_data *hostdata,
+                           int max_requests)
+{
+       int rc;
+       struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+       queue->msgs = (struct viosrp_crq *)get_zeroed_page(GFP_KERNEL);
+
+       if (!queue->msgs)
+               goto malloc_failed;
+       queue->size = PAGE_SIZE / sizeof(*queue->msgs);
+
+       queue->msg_token = dma_map_single(hostdata->dev, queue->msgs,
+                                         queue->size * sizeof(*queue->msgs),
+                                         DMA_BIDIRECTIONAL);
+
+       if (dma_mapping_error(queue->msg_token))
+               goto map_failed;
+
+       rc = plpar_hcall_norets(H_REG_CRQ,
+                               vdev->unit_address,
+                               queue->msg_token, PAGE_SIZE);
+       if (rc == 2) {
+               /* Adapter is good, but other end is not ready */
+               printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+       } else if (rc != 0) {
+               printk(KERN_WARNING "ibmvscsi: Error %d opening adapter\n", rc);
+               goto reg_crq_failed;
+       }
+
+       if (request_irq(vdev->irq,
+                       ibmvscsi_handle_event,
+                       0, "ibmvscsi", (void *)hostdata) != 0) {
+               printk(KERN_ERR "ibmvscsi: couldn't register irq 0x%x\n",
+                      vdev->irq);
+               goto req_irq_failed;
+       }
+
+       rc = vio_enable_interrupts(vdev);
+       if (rc != 0) {
+               printk(KERN_ERR "ibmvscsi:  Error %d enabling interrupts!!!\n",
+                      rc);
+               goto req_irq_failed;
+       }
+
+       queue->cur = 0;
+       queue->lock = SPIN_LOCK_UNLOCKED;
+
+       tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
+                    (unsigned long)hostdata);
+
+       return 0;
+
+      req_irq_failed:
+       do {
+               rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+       } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+      reg_crq_failed:
+       dma_unmap_single(hostdata->dev,
+                        queue->msg_token,
+                        queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
+      map_failed:
+       free_page((unsigned long)queue->msgs);
+      malloc_failed:
+       return -1;
+}
+
+/**
+ * reset_crq_queue: - resets a crq after a failure
+ * @queue:     crq_queue to initialize and register
+ * @hostdata:  ibmvscsi_host_data of host
+ *
+ */
+void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+                             struct ibmvscsi_host_data *hostdata)
+{
+       int rc;
+       struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+       /* Close the CRQ */
+       do {
+               rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+       } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+
+       /* Clean out the queue */
+       memset(queue->msgs, 0x00, PAGE_SIZE);
+       queue->cur = 0;
+
+       /* And re-open it again */
+       rc = plpar_hcall_norets(H_REG_CRQ,
+                               vdev->unit_address,
+                               queue->msg_token, PAGE_SIZE);
+       if (rc == 2) {
+               /* Adapter is good, but other end is not ready */
+               printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+       } else if (rc != 0) {
+               printk(KERN_WARNING
+                      "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
+       }
+}
diff --git a/drivers/scsi/ibmvscsi/srp.h b/drivers/scsi/ibmvscsi/srp.h
new file mode 100644 (file)
index 0000000..e952c1c
--- /dev/null
@@ -0,0 +1,225 @@
+/*****************************************************************************/
+/* srp.h -- SCSI RDMA Protocol definitions                                   */
+/*                                                                           */
+/* Written By: Colin Devilbis, IBM Corporation                               */
+/*                                                                           */
+/* Copyright (C) 2003 IBM Corporation                                        */
+/*                                                                           */
+/* This program is free software; you can redistribute it and/or modify      */
+/* it under the terms of the GNU General Public License as published by      */
+/* the Free Software Foundation; either version 2 of the License, or         */
+/* (at your option) any later version.                                       */
+/*                                                                           */
+/* This program is distributed in the hope that it will be useful,           */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
+/* GNU General Public License for more details.                              */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License         */
+/* along with this program; if not, write to the Free Software               */
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+/*                                                                           */
+/*                                                                           */
+/* This file contains structures and definitions for the SCSI RDMA Protocol  */
+/* (SRP) as defined in the T10 standard available at www.t10.org.  This      */
+/* file was based on the 16a version of the standard                         */
+/*                                                                           */
+/*****************************************************************************/
+#ifndef SRP_H
+#define SRP_H
+
+#define PACKED __attribute__((packed))
+
+enum srp_types {
+       SRP_LOGIN_REQ_TYPE = 0x00,
+       SRP_LOGIN_RSP_TYPE = 0xC0,
+       SRP_LOGIN_REJ_TYPE = 0x80,
+       SRP_I_LOGOUT_TYPE = 0x03,
+       SRP_T_LOGOUT_TYPE = 0x80,
+       SRP_TSK_MGMT_TYPE = 0x01,
+       SRP_CMD_TYPE = 0x02,
+       SRP_RSP_TYPE = 0xC1,
+       SRP_CRED_REQ_TYPE = 0x81,
+       SRP_CRED_RSP_TYPE = 0x41,
+       SRP_AER_REQ_TYPE = 0x82,
+       SRP_AER_RSP_TYPE = 0x42
+};
+
+enum srp_descriptor_formats {
+       SRP_NO_BUFFER = 0x00,
+       SRP_DIRECT_BUFFER = 0x01,
+       SRP_INDIRECT_BUFFER = 0x02
+};
+
+struct memory_descriptor {
+       u64 virtual_address;
+       u32 memory_handle;
+       u32 length;
+};
+
+struct indirect_descriptor {
+       struct memory_descriptor head;
+       u32 total_length;
+       struct memory_descriptor list[1] PACKED;
+};
+
+struct srp_generic {
+       u8 type;
+       u8 reserved1[7];
+       u64 tag;
+};
+
+struct srp_login_req {
+       u8 type;
+       u8 reserved1[7];
+       u64 tag;
+       u32 max_requested_initiator_to_target_iulen;
+       u32 reserved2;
+       u16 required_buffer_formats;
+       u8 reserved3:6;
+       u8 multi_channel_action:2;
+       u8 reserved4;
+       u32 reserved5;
+       u8 initiator_port_identifier[16];
+       u8 target_port_identifier[16];
+};
+
+struct srp_login_rsp {
+       u8 type;
+       u8 reserved1[3];
+       u32 request_limit_delta;
+       u64 tag;
+       u32 max_initiator_to_target_iulen;
+       u32 max_target_to_initiator_iulen;
+       u16 supported_buffer_formats;
+       u8 reserved2:6;
+       u8 multi_channel_result:2;
+       u8 reserved3;
+       u8 reserved4[24];
+};
+
+struct srp_login_rej {
+       u8 type;
+       u8 reserved1[3];
+       u32 reason;
+       u64 tag;
+       u64 reserved2;
+       u16 supported_buffer_formats;
+       u8 reserved3[6];
+};
+
+struct srp_i_logout {
+       u8 type;
+       u8 reserved1[7];
+       u64 tag;
+};
+
+struct srp_t_logout {
+       u8 type;
+       u8 reserved1[3];
+       u32 reason;
+       u64 tag;
+};
+
+struct srp_tsk_mgmt {
+       u8 type;
+       u8 reserved1[7];
+       u64 tag;
+       u32 reserved2;
+       u64 lun PACKED;
+       u8 reserved3;
+       u8 reserved4;
+       u8 task_mgmt_flags;
+       u8 reserved5;
+       u64 managed_task_tag;
+       u64 reserved6;
+};
+
+struct srp_cmd {
+       u8 type;
+       u32 reserved1 PACKED;
+       u8 data_out_format:4;
+       u8 data_in_format:4;
+       u8 data_out_count;
+       u8 data_in_count;
+       u64 tag;
+       u32 reserved2;
+       u64 lun PACKED;
+       u8 reserved3;
+       u8 reserved4:5;
+       u8 task_attribute:3;
+       u8 reserved5;
+       u8 additional_cdb_len;
+       u8 cdb[16];
+       u8 additional_data[0x100 - 0x30];
+};
+
+struct srp_rsp {
+       u8 type;
+       u8 reserved1[3];
+       u32 request_limit_delta;
+       u64 tag;
+       u16 reserved2;
+       u8 reserved3:2;
+       u8 diunder:1;
+       u8 diover:1;
+       u8 dounder:1;
+       u8 doover:1;
+       u8 snsvalid:1;
+       u8 rspvalid:1;
+       u8 status;
+       u32 data_in_residual_count;
+       u32 data_out_residual_count;
+       u32 sense_data_list_length;
+       u32 response_data_list_length;
+       u8 sense_and_response_data[18];
+};
+
+struct srp_cred_req {
+       u8 type;
+       u8 reserved1[3];
+       u32 request_limit_delta;
+       u64 tag;
+};
+
+struct srp_cred_rsp {
+       u8 type;
+       u8 reserved1[7];
+       u64 tag;
+};
+
+struct srp_aer_req {
+       u8 type;
+       u8 reserved1[3];
+       u32 request_limit_delta;
+       u64 tag;
+       u32 reserved2;
+       u64 lun;
+       u32 sense_data_list_length;
+       u32 reserved3;
+       u8 sense_data[20];
+};
+
+struct srp_aer_rsp {
+       u8 type;
+       u8 reserved1[7];
+       u64 tag;
+};
+
+union srp_iu {
+       struct srp_generic generic;
+       struct srp_login_req login_req;
+       struct srp_login_rsp login_rsp;
+       struct srp_login_rej login_rej;
+       struct srp_i_logout i_logout;
+       struct srp_t_logout t_logout;
+       struct srp_tsk_mgmt tsk_mgmt;
+       struct srp_cmd cmd;
+       struct srp_rsp rsp;
+       struct srp_cred_req cred_req;
+       struct srp_cred_rsp cred_rsp;
+       struct srp_aer_req aer_req;
+       struct srp_aer_rsp aer_rsp;
+};
+
+#endif
diff --git a/drivers/scsi/ibmvscsi/viosrp.h b/drivers/scsi/ibmvscsi/viosrp.h
new file mode 100644 (file)
index 0000000..6a6bba8
--- /dev/null
@@ -0,0 +1,126 @@
+/*****************************************************************************/
+/* srp.h -- SCSI RDMA Protocol definitions                                   */
+/*                                                                           */
+/* Written By: Colin Devilbis, IBM Corporation                               */
+/*                                                                           */
+/* Copyright (C) 2003 IBM Corporation                                        */
+/*                                                                           */
+/* This program is free software; you can redistribute it and/or modify      */
+/* it under the terms of the GNU General Public License as published by      */
+/* the Free Software Foundation; either version 2 of the License, or         */
+/* (at your option) any later version.                                       */
+/*                                                                           */
+/* This program is distributed in the hope that it will be useful,           */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
+/* GNU General Public License for more details.                              */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License         */
+/* along with this program; if not, write to the Free Software               */
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+/*                                                                           */
+/*                                                                           */
+/* This file contains structures and definitions for IBM RPA (RS/6000        */
+/* platform architecture) implementation of the SRP (SCSI RDMA Protocol)     */
+/* standard.  SRP is used on IBM iSeries and pSeries platforms to send SCSI  */
+/* commands between logical partitions.                                      */
+/*                                                                           */
+/* SRP Information Units (IUs) are sent on a "Command/Response Queue" (CRQ)  */
+/* between partitions.  The definitions in this file are architected,        */
+/* and cannot be changed without breaking compatibility with other versions  */
+/* of Linux and other operating systems (AIX, OS/400) that talk this protocol*/
+/* between logical partitions                                                */
+/*****************************************************************************/
+#ifndef VIOSRP_H
+#define VIOSRP_H
+#include "srp.h"
+
+enum viosrp_crq_formats {
+       VIOSRP_SRP_FORMAT = 0x01,
+       VIOSRP_MAD_FORMAT = 0x02,
+       VIOSRP_OS400_FORMAT = 0x03,
+       VIOSRP_AIX_FORMAT = 0x04,
+       VIOSRP_LINUX_FORMAT = 0x06,
+       VIOSRP_INLINE_FORMAT = 0x07
+};
+
+struct viosrp_crq {
+       u8 valid;               /* used by RPA */
+       u8 format;              /* SCSI vs out-of-band */
+       u8 reserved;
+       u8 status;              /* non-scsi failure? (e.g. DMA failure) */
+       u16 timeout;            /* in seconds */
+       u16 IU_length;          /* in bytes */
+       u64 IU_data_ptr;        /* the TCE for transferring data */
+};
+
+/* MADs are Management requests above and beyond the IUs defined in the SRP
+ * standard.  
+ */
+enum viosrp_mad_types {
+       VIOSRP_EMPTY_IU_TYPE = 0x01,
+       VIOSRP_ERROR_LOG_TYPE = 0x02,
+       VIOSRP_ADAPTER_INFO_TYPE = 0x03,
+       VIOSRP_HOST_CONFIG_TYPE = 0x04
+};
+
+/* 
+ * Common MAD header
+ */
+struct mad_common {
+       u32 type;
+       u16 status;
+       u16 length;
+       u64 tag;
+};
+
+/*
+ * All SRP (and MAD) requests normally flow from the
+ * client to the server.  There is no way for the server to send
+ * an asynchronous message back to the client.  The Empty IU is used
+ * to hang out a meaningless request to the server so that it can respond
+ * asynchrouously with something like a SCSI AER 
+ */
+struct viosrp_empty_iu {
+       struct mad_common common;
+       u64 buffer;
+       u32 port;
+};
+
+struct viosrp_error_log {
+       struct mad_common common;
+       u64 buffer;
+};
+
+struct viosrp_adapter_info {
+       struct mad_common common;
+       u64 buffer;
+};
+
+struct viosrp_host_config {
+       struct mad_common common;
+       u64 buffer;
+};
+
+union mad_iu {
+       struct viosrp_empty_iu empty_iu;
+       struct viosrp_error_log error_log;
+       struct viosrp_adapter_info adapter_info;
+       struct viosrp_host_config host_config;
+};
+
+union viosrp_iu {
+       union srp_iu srp;
+       union mad_iu mad;
+};
+
+struct mad_adapter_info_data {
+       char srp_version[8];
+       char partition_name[96];
+       u32 partition_number;
+       u32 mad_version;
+       u32 os_type;
+       u32 port_max_txu[8];    /* per-port maximum transfer */
+};
+
+#endif
index bf39427..40bfff7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ipr.c -- driver for IBM Power Linux RAID adapters
  *
- * Written By: Brian King, IBM Corporation
+ * Written By: Brian King <brking@us.ibm.com>, IBM Corporation
  *
  * Copyright (C) 2003, 2004 IBM Corporation
  *
@@ -93,7 +93,7 @@ static spinlock_t ipr_driver_lock = SPIN_LOCK_UNLOCKED;
 
 /* This table describes the differences between DMA controller chips */
 static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
-       { /* Gemstone */
+       { /* Gemstone and Citrine */
                .mailbox = 0x0042C,
                .cache_line_size = 0x20,
                {
@@ -208,6 +208,8 @@ struct ipr_error_table_t ipr_error_table[] = {
        "Synchronization required"},
        {0x024E0000, 0, 0,
        "No ready, IOA shutdown"},
+       {0x025A0000, 0, 0,
+       "Not ready, IOA has been shutdown"},
        {0x02670100, 0, 1,
        "3020: Storage subsystem configuration error"},
        {0x03110B00, 0, 0,
@@ -880,11 +882,13 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd)
  **/
 static void ipr_log_vpd(struct ipr_std_inq_vpids *vpids, u8 *serial_num)
 {
-       char buffer[max_t(int, sizeof(struct ipr_std_inq_vpids),
-                         IPR_SERIAL_NUM_LEN) + 1];
+       char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN
+                   + IPR_SERIAL_NUM_LEN];
 
-       memcpy(buffer, vpids, sizeof(struct ipr_std_inq_vpids));
-       buffer[sizeof(struct ipr_std_inq_vpids)] = '\0';
+       memcpy(buffer, vpids->vendor_id, IPR_VENDOR_ID_LEN);
+       memcpy(buffer + IPR_VENDOR_ID_LEN, vpids->product_id,
+              IPR_PROD_ID_LEN);
+       buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN] = '\0';
        ipr_err("Vendor/Product ID: %s\n", buffer);
 
        memcpy(buffer, serial_num, IPR_SERIAL_NUM_LEN);
@@ -1765,6 +1769,33 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
 #define ipr_get_ioa_dump(ioa_cfg, dump) do { } while(0)
 #endif
 
+/**
+ * ipr_release_dump - Free adapter dump memory
+ * @kref:      kref struct
+ *
+ * Return value:
+ *     nothing
+ **/
+static void ipr_release_dump(struct kref *kref)
+{
+       struct ipr_dump *dump = container_of(kref,struct ipr_dump,kref);
+       struct ipr_ioa_cfg *ioa_cfg = dump->ioa_cfg;
+       unsigned long lock_flags = 0;
+       int i;
+
+       ENTER;
+       spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+       ioa_cfg->dump = NULL;
+       ioa_cfg->sdt_state = INACTIVE;
+       spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+
+       for (i = 0; i < dump->ioa_dump.next_page_index; i++)
+               free_page((unsigned long) dump->ioa_dump.ioa_data[i]);
+
+       kfree(dump);
+       LEAVE;
+}
+
 /**
  * ipr_worker_thread - Worker thread
  * @data:              ioa config struct
@@ -1791,13 +1822,14 @@ static void ipr_worker_thread(void *data)
 
        if (ioa_cfg->sdt_state == GET_DUMP) {
                dump = ioa_cfg->dump;
-               if (!dump || !kobject_get(&dump->kobj)) {
+               if (!dump) {
                        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
                        return;
                }
+               kref_get(&dump->kref);
                spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
                ipr_get_ioa_dump(ioa_cfg, dump);
-               kobject_put(&dump->kobj);
+               kref_put(&dump->kref, ipr_release_dump);
 
                spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
                if (ioa_cfg->sdt_state == DUMP_OBTAINED)
@@ -2008,7 +2040,7 @@ static ssize_t ipr_store_diagnostics(struct class_device *class_dev,
                wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
 
                /* Wait for a second for any errors to be logged */
-               schedule_timeout(HZ);
+               msleep(1000);
        } else {
                spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
                return -EIO;
@@ -2392,15 +2424,15 @@ static ssize_t ipr_read_dump(struct kobject *kobj, char *buf,
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
        dump = ioa_cfg->dump;
 
-       if (ioa_cfg->sdt_state != DUMP_OBTAINED || !dump || !kobject_get(&dump->kobj)) {
+       if (ioa_cfg->sdt_state != DUMP_OBTAINED || !dump) {
                spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
                return 0;
        }
-
+       kref_get(&dump->kref);
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 
        if (off > dump->driver_dump.hdr.len) {
-               kobject_put(&dump->kobj);
+               kref_put(&dump->kref, ipr_release_dump);
                return 0;
        }
 
@@ -2450,41 +2482,10 @@ static ssize_t ipr_read_dump(struct kobject *kobj, char *buf,
                count -= len;
        }
 
-       kobject_put(&dump->kobj);
+       kref_put(&dump->kref, ipr_release_dump);
        return rc;
 }
 
-/**
- * ipr_release_dump - Free adapter dump memory
- * @kobj:      kobject struct
- *
- * Return value:
- *     nothing
- **/
-static void ipr_release_dump(struct kobject *kobj)
-{
-       struct ipr_dump *dump = container_of(kobj,struct ipr_dump,kobj);
-       struct ipr_ioa_cfg *ioa_cfg = dump->ioa_cfg;
-       unsigned long lock_flags = 0;
-       int i;
-
-       ENTER;
-       spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
-       ioa_cfg->dump = NULL;
-       ioa_cfg->sdt_state = INACTIVE;
-       spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-
-       for (i = 0; i < dump->ioa_dump.next_page_index; i++)
-               free_page((unsigned long) dump->ioa_dump.ioa_data[i]);
-
-       kfree(dump);
-       LEAVE;
-}
-
-static struct kobj_type ipr_dump_kobj_type = {
-       .release = ipr_release_dump,
-};
-
 /**
  * ipr_alloc_dump - Prepare for adapter dump
  * @ioa_cfg:   ioa config struct
@@ -2506,8 +2507,7 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
        }
 
        memset(dump, 0, sizeof(struct ipr_dump));
-       kobject_init(&dump->kobj);
-       dump->kobj.ktype = &ipr_dump_kobj_type;
+       kref_init(&dump->kref);
        dump->ioa_cfg = ioa_cfg;
 
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -2554,7 +2554,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg)
        ioa_cfg->dump = NULL;
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 
-       kobject_put(&dump->kobj);
+       kref_put(&dump->kref, ipr_release_dump);
 
        LEAVE;
        return 0;
@@ -2690,8 +2690,6 @@ static ssize_t ipr_store_tcq_enable(struct device *dev,
        struct ipr_resource_entry *res;
        unsigned long lock_flags = 0;
        int tcq_active = simple_strtoul(buf, NULL, 10);
-       int qdepth = IPR_MAX_CMD_PER_LUN;
-       int tagged = 0;
        ssize_t len = -ENXIO;
 
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -2699,13 +2697,13 @@ static ssize_t ipr_store_tcq_enable(struct device *dev,
        res = (struct ipr_resource_entry *)sdev->hostdata;
 
        if (res) {
-               res->tcq_active = 0;
-               qdepth = res->qdepth;
-
                if (ipr_is_gscsi(res) && sdev->tagged_supported) {
                        if (tcq_active) {
-                               tagged = MSG_ORDERED_TAG;
                                res->tcq_active = 1;
+                               scsi_activate_tcq(sdev, res->qdepth);
+                       } else {
+                               res->tcq_active = 0;
+                               scsi_deactivate_tcq(sdev, res->qdepth);
                        }
 
                        len = strlen(buf);
@@ -2715,7 +2713,6 @@ static ssize_t ipr_store_tcq_enable(struct device *dev,
        }
 
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-       scsi_adjust_queue_depth(sdev, tagged, qdepth);
        return len;
 }
 
@@ -2785,7 +2782,8 @@ static int ipr_biosparam(struct scsi_device *sdev,
                         struct block_device *block_device,
                         sector_t capacity, int *parm)
 {
-       int heads, sectors, cylinders;
+       int heads, sectors;
+       sector_t cylinders;
 
        heads = 128;
        sectors = 32;
@@ -2849,8 +2847,8 @@ static int ipr_slave_configure(struct scsi_device *sdev)
                        sdev->scsi_level = 4;
                if (ipr_is_vset_device(res))
                        sdev->timeout = IPR_VSET_RW_TIMEOUT;
-
-               sdev->allow_restart = 1;
+               if (IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data))
+                       sdev->allow_restart = 1;
                scsi_adjust_queue_depth(sdev, 0, res->qdepth);
        }
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -3080,7 +3078,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
        struct ipr_ioa_cfg *ioa_cfg;
        struct ipr_resource_entry *res;
        struct ipr_cmd_pkt *cmd_pkt;
-       u32 ioasc, ioarcb_addr;
+       u32 ioasc;
        int op_found = 0;
 
        ENTER;
@@ -3101,21 +3099,15 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
        if (!op_found)
                return SUCCESS;
 
-       ioarcb_addr = be32_to_cpu(ipr_cmd->ioarcb.ioarcb_host_pci_addr);
-
        ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
        ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle;
        cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt;
        cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
-       cmd_pkt->cdb[0] = IPR_ABORT_TASK;
-       cmd_pkt->cdb[2] = (ioarcb_addr >> 24) & 0xff;
-       cmd_pkt->cdb[3] = (ioarcb_addr >> 16) & 0xff;
-       cmd_pkt->cdb[4] = (ioarcb_addr >> 8) & 0xff;
-       cmd_pkt->cdb[5] = ioarcb_addr & 0xff;
+       cmd_pkt->cdb[0] = IPR_CANCEL_ALL_REQUESTS;
        ipr_cmd->u.sdev = scsi_cmd->device;
 
        ipr_sdev_err(scsi_cmd->device, "Aborting command: %02X\n", scsi_cmd->cmnd[0]);
-       ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_ABORT_TASK_TIMEOUT);
+       ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT);
        ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
 
        /*
@@ -3737,7 +3729,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
 
        switch (ioasc & IPR_IOASC_IOASC_MASK) {
        case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST:
-               scsi_cmd->result |= (DID_ERROR << 16);
+               scsi_cmd->result |= (DID_IMM_RETRY << 16);
                break;
        case IPR_IOASC_IR_RESOURCE_HANDLE:
                scsi_cmd->result |= (DID_NO_CONNECT << 16);
@@ -3873,7 +3865,7 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
         * We have told the host to stop giving us new requests, but
         * ERP ops don't count. FIXME
         */
-       if (unlikely(!ioa_cfg->allow_cmds))
+       if (unlikely(!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead))
                return SCSI_MLQUEUE_HOST_BUSY;
 
        /*
@@ -5437,13 +5429,15 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
  **/
 static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg)
 {
+       struct pci_dev *pdev = ioa_cfg->pdev;
+
        ENTER;
-       free_irq(ioa_cfg->pdev->irq, ioa_cfg);
+       free_irq(pdev->irq, ioa_cfg);
        iounmap((void *) ioa_cfg->hdw_dma_regs);
-       release_mem_region(ioa_cfg->hdw_dma_regs_pci,
-                          pci_resource_len(ioa_cfg->pdev, 0));
+       pci_release_regions(pdev);
        ipr_free_mem(ioa_cfg);
        scsi_host_put(ioa_cfg->host);
+       pci_disable_device(pdev);
        LEAVE;
 }
 
@@ -5458,7 +5452,7 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
 {
        struct ipr_cmnd *ipr_cmd;
        struct ipr_ioarcb *ioarcb;
-       u32 dma_addr;
+       dma_addr_t dma_addr;
        int i;
 
        ioa_cfg->ipr_cmd_pool = pci_pool_create (IPR_NAME, ioa_cfg->pdev,
@@ -5508,14 +5502,15 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
  **/
 static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
 {
-       int i;
+       struct pci_dev *pdev = ioa_cfg->pdev;
+       int i, rc = -ENOMEM;
 
        ENTER;
        ioa_cfg->res_entries = kmalloc(sizeof(struct ipr_resource_entry) *
                                       IPR_MAX_PHYSICAL_DEVS, GFP_KERNEL);
 
        if (!ioa_cfg->res_entries)
-               goto cleanup;
+               goto out;
 
        memset(ioa_cfg->res_entries, 0,
               sizeof(struct ipr_resource_entry) * IPR_MAX_PHYSICAL_DEVS);
@@ -5528,24 +5523,24 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
                                                &ioa_cfg->vpd_cbs_dma);
 
        if (!ioa_cfg->vpd_cbs)
-               goto cleanup;
+               goto out_free_res_entries;
 
        if (ipr_alloc_cmd_blks(ioa_cfg))
-               goto cleanup;
+               goto out_free_vpd_cbs;
 
        ioa_cfg->host_rrq = pci_alloc_consistent(ioa_cfg->pdev,
                                                 sizeof(u32) * IPR_NUM_CMD_BLKS,
                                                 &ioa_cfg->host_rrq_dma);
 
        if (!ioa_cfg->host_rrq)
-               goto cleanup;
+               goto out_ipr_free_cmd_blocks;
 
        ioa_cfg->cfg_table = pci_alloc_consistent(ioa_cfg->pdev,
                                                  sizeof(struct ipr_config_table),
                                                  &ioa_cfg->cfg_table_dma);
 
        if (!ioa_cfg->cfg_table)
-               goto cleanup;
+               goto out_free_host_rrq;
 
        for (i = 0; i < IPR_NUM_HCAMS; i++) {
                ioa_cfg->hostrcb[i] = pci_alloc_consistent(ioa_cfg->pdev,
@@ -5553,9 +5548,8 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
                                                           &ioa_cfg->hostrcb_dma[i]);
 
                if (!ioa_cfg->hostrcb[i])
-                       goto cleanup;
+                       goto out_free_hostrcb_dma;
 
-               memset(ioa_cfg->hostrcb[i], 0, sizeof(struct ipr_hostrcb));
                ioa_cfg->hostrcb[i]->hostrcb_dma =
                        ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam);
                list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q);
@@ -5565,19 +5559,35 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
                                 IPR_NUM_TRACE_ENTRIES, GFP_KERNEL);
 
        if (!ioa_cfg->trace)
-               goto cleanup;
+               goto out_free_hostrcb_dma;
 
        memset(ioa_cfg->trace, 0,
               sizeof(struct ipr_trace_entry) * IPR_NUM_TRACE_ENTRIES);
 
+       rc = 0;
+out:
        LEAVE;
-       return 0;
-
-cleanup:
-       ipr_free_mem(ioa_cfg);
+       return rc;
 
-       LEAVE;
-       return -ENOMEM;
+out_free_hostrcb_dma:
+       while (i-- > 0) {
+               pci_free_consistent(pdev, sizeof(struct ipr_hostrcb),
+                                   ioa_cfg->hostrcb[i],
+                                   ioa_cfg->hostrcb_dma[i]);
+       }
+       pci_free_consistent(pdev, sizeof(struct ipr_config_table),
+                           ioa_cfg->cfg_table, ioa_cfg->cfg_table_dma);
+out_free_host_rrq:
+       pci_free_consistent(pdev, sizeof(u32) * IPR_NUM_CMD_BLKS,
+                           ioa_cfg->host_rrq, ioa_cfg->host_rrq_dma);
+out_ipr_free_cmd_blocks:
+       ipr_free_cmd_blks(ioa_cfg);
+out_free_vpd_cbs:
+       pci_free_consistent(pdev, sizeof(struct ipr_misc_cbs),
+                           ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
+out_free_res_entries:
+       kfree(ioa_cfg->res_entries);
+       goto out;
 }
 
 /**
@@ -5678,7 +5688,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 
        if ((rc = pci_enable_device(pdev))) {
                dev_err(&pdev->dev, "Cannot enable adapter\n");
-               return rc;
+               goto out;
        }
 
        dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq);
@@ -5687,7 +5697,8 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 
        if (!host) {
                dev_err(&pdev->dev, "call to scsi_host_alloc failed!\n");
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto out_disable;
        }
 
        ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata;
@@ -5697,12 +5708,11 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 
        ipr_regs_pci = pci_resource_start(pdev, 0);
 
-       if (!request_mem_region(ipr_regs_pci,
-                               pci_resource_len(pdev, 0), IPR_NAME)) {
+       rc = pci_request_regions(pdev, IPR_NAME);
+       if (rc < 0) {
                dev_err(&pdev->dev,
                        "Couldn't register memory range of registers\n");
-               scsi_host_put(host);
-               return -ENOMEM;
+               goto out_scsi_host_put;
        }
 
        ipr_regs = (unsigned long)ioremap(ipr_regs_pci,
@@ -5711,9 +5721,8 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        if (!ipr_regs) {
                dev_err(&pdev->dev,
                        "Couldn't map memory range of registers\n");
-               release_mem_region(ipr_regs_pci, pci_resource_len(pdev, 0));
-               scsi_host_put(host);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto out_release_regions;
        }
 
        ioa_cfg->hdw_dma_regs = ipr_regs;
@@ -5723,11 +5732,10 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        ipr_init_ioa_cfg(ioa_cfg, host, pdev);
 
        pci_set_master(pdev);
-       rc = pci_set_dma_mask(pdev, 0xffffffff);
 
-       if (rc != PCIBIOS_SUCCESSFUL) {
+       rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       if (rc < 0) {
                dev_err(&pdev->dev, "Failed to set PCI DMA mask\n");
-               rc = -EIO;
                goto cleanup_nomem;
        }
 
@@ -5755,8 +5763,12 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        if ((rc = ipr_set_pcix_cmd_reg(ioa_cfg)))
                goto cleanup_nomem;
 
-       if ((rc = ipr_alloc_mem(ioa_cfg)))
-               goto cleanup;
+       rc = ipr_alloc_mem(ioa_cfg);
+       if (rc < 0) {
+               dev_err(&pdev->dev,
+                       "Couldn't allocate enough memory for device driver!\n");
+               goto cleanup_nomem;
+       }
 
        ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
        rc = request_irq(pdev->irq, ipr_isr, SA_SHIRQ, IPR_NAME, ioa_cfg);
@@ -5772,18 +5784,20 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        spin_unlock(&ipr_driver_lock);
 
        LEAVE;
-       return 0;
+out:
+       return rc;
 
-cleanup:
-       dev_err(&pdev->dev, "Couldn't allocate enough memory for device driver!\n");
 cleanup_nolog:
        ipr_free_mem(ioa_cfg);
 cleanup_nomem:
        iounmap((void *) ipr_regs);
-       release_mem_region(ipr_regs_pci, pci_resource_len(pdev, 0));
+out_release_regions:
+       pci_release_regions(pdev);
+out_scsi_host_put:
        scsi_host_put(host);
-
-       return rc;
+out_disable:
+       pci_disable_device(pdev);
+       goto out;
 }
 
 /**
@@ -5988,9 +6002,15 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
        { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D,
              0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B,
+             0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780,
                0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_570F,
+               0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
        { }
 };
 MODULE_DEVICE_TABLE(pci, ipr_pci_table);
@@ -6009,16 +6029,14 @@ static struct pci_driver ipr_driver = {
  * ipr_init - Module entry point
  *
  * Return value:
- *     0 on success / non-zero on failure
+ *     0 on success / negative value on failure
  **/
 static int __init ipr_init(void)
 {
        ipr_info("IBM Power RAID SCSI Device Driver version: %s %s\n",
                 IPR_DRIVER_VERSION, IPR_DRIVER_DATE);
 
-       pci_register_driver(&ipr_driver);
-
-       return 0;
+       return pci_module_init(&ipr_driver);
 }
 
 /**
index 6d616ac..e91afc4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ipr.h -- driver for IBM Power Linux RAID adapters
  *
- * Written By: Brian King, IBM Corporation
+ * Written By: Brian King <brking@us.ibm.com>, IBM Corporation
  *
  * Copyright (C) 2003, 2004 IBM Corporation
  *
@@ -19,6 +19,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
+ * Alan Cox <alan@redhat.com> - Removed several careless u32/dma_addr_t errors
+ *                             that broke 64bit platforms.
  */
 
 #ifndef _IPR_H
@@ -27,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/completion.h>
 #include <linux/list.h>
+#include <linux/kref.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #ifdef CONFIG_KDB
@@ -36,8 +39,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.0.10"
-#define IPR_DRIVER_DATE "(June 7, 2004)"
+#define IPR_DRIVER_VERSION "2.0.11"
+#define IPR_DRIVER_DATE "(August 3, 2004)"
 
 /*
  * IPR_DBG_TRACE: Setting this to 1 will turn on some general function tracing
@@ -72,6 +75,8 @@
 #define IPR_SUBS_DEV_ID_5703   0x0278
 #define IPR_SUBS_DEV_ID_572E  0x02D3
 #define IPR_SUBS_DEV_ID_573D  0x02D4
+#define IPR_SUBS_DEV_ID_570F   0x02BD
+#define IPR_SUBS_DEV_ID_571B   0x02BE
 
 #define IPR_NAME                               "ipr"
 
 #define        IPR_BUS_RESET                                   0x10
 #define IPR_ID_HOST_RR_Q                               0xC4
 #define IPR_QUERY_IOA_CONFIG                           0xC5
-#define IPR_ABORT_TASK                                 0xC7
 #define IPR_CANCEL_ALL_REQUESTS                        0xCE
 #define IPR_HOST_CONTROLLED_ASYNC                      0xCF
 #define        IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE      0x01
@@ -667,7 +671,7 @@ struct ipr_hcam {
 
 struct ipr_hostrcb {
        struct ipr_hcam hcam;
-       u32 hostrcb_dma;
+       dma_addr_t hostrcb_dma;
        struct list_head queue;
 };
 
@@ -850,7 +854,7 @@ struct ipr_ioa_cfg {
        char cfg_table_start[8];
 #define IPR_CFG_TBL_START              "cfg"
        struct ipr_config_table *cfg_table;
-       u32 cfg_table_dma;
+       dma_addr_t cfg_table_dma;
 
        char resource_table_label[8];
 #define IPR_RES_TABLE_LABEL            "res_tbl"
@@ -861,12 +865,12 @@ struct ipr_ioa_cfg {
        char ipr_hcam_label[8];
 #define IPR_HCAM_LABEL                 "hcams"
        struct ipr_hostrcb *hostrcb[IPR_NUM_HCAMS];
-       u32 hostrcb_dma[IPR_NUM_HCAMS];
+       dma_addr_t hostrcb_dma[IPR_NUM_HCAMS];
        struct list_head hostrcb_free_q;
        struct list_head hostrcb_pending_q;
 
        u32 *host_rrq;
-       u32 host_rrq_dma;
+       dma_addr_t host_rrq_dma;
 #define IPR_HRRQ_REQ_RESP_HANDLE_MASK  0xfffffffc
 #define IPR_HRRQ_RESP_BIT_SET                  0x00000002
 #define IPR_HRRQ_TOGGLE_BIT                            0x00000001
@@ -905,7 +909,7 @@ struct ipr_ioa_cfg {
        enum ipr_sdt_state sdt_state;
 
        struct ipr_misc_cbs *vpd_cbs;
-       u32 vpd_cbs_dma;
+       dma_addr_t vpd_cbs_dma;
 
        struct pci_pool *ipr_cmd_pool;
 
@@ -1029,7 +1033,7 @@ struct ipr_ioa_dump {
 }__attribute__((packed, aligned (4)));
 
 struct ipr_dump {
-       struct kobject kobj;
+       struct kref kref;
        struct ipr_ioa_cfg *ioa_cfg;
        struct ipr_driver_dump driver_dump;
        struct ipr_ioa_dump ioa_dump;
diff --git a/drivers/scsi/megaraid/Kconfig.megaraid b/drivers/scsi/megaraid/Kconfig.megaraid
new file mode 100644 (file)
index 0000000..97c7a76
--- /dev/null
@@ -0,0 +1,77 @@
+config MEGARAID_NEWGEN
+       bool "LSI Logic New Generation RAID Device Drivers"
+       depends on PCI && SCSI
+       help
+       LSI Logic RAID Device Drivers
+
+config MEGARAID_MM
+       tristate "LSI Logic Management Module (New Driver)"
+       depends on PCI && SCSI && MEGARAID_NEWGEN
+       help
+       Management Module provides ioctl, sysfs support for LSI Logic
+       RAID controllers.
+       To compile this driver as a module, choose M here: the
+       module will be called megaraid_mm
+
+
+config MEGARAID_MAILBOX
+       tristate "LSI Logic MegaRAID Driver (New Driver)"
+       depends on PCI && SCSI && MEGARAID_MM
+       help
+       List of supported controllers
+
+       OEM     Product Name            VID :DID :SVID:SSID
+       ---     ------------            ---- ---- ---- ----
+       Dell PERC3/QC                   101E:1960:1028:0471
+       Dell PERC3/DC                   101E:1960:1028:0493
+       Dell PERC3/SC                   101E:1960:1028:0475
+       Dell PERC3/Di                   1028:000E:1028:0123
+       Dell PERC4/SC                   1000:1960:1028:0520
+       Dell PERC4/DC                   1000:1960:1028:0518
+       Dell PERC4/QC                   1000:0407:1028:0531
+       Dell PERC4/Di                   1028:000F:1028:014A
+       Dell PERC 4e/Si                 1028:0013:1028:016c
+       Dell PERC 4e/Di                 1028:0013:1028:016d
+       Dell PERC 4e/Di                 1028:0013:1028:016e
+       Dell PERC 4e/Di                 1028:0013:1028:016f
+       Dell PERC 4e/Di                 1028:0013:1028:0170
+       Dell PERC 4e/DC                 1000:0408:1028:0002
+       Dell PERC 4e/SC                 1000:0408:1028:0001
+       LSI MegaRAID SCSI 320-0         1000:1960:1000:A520
+       LSI MegaRAID SCSI 320-1         1000:1960:1000:0520
+       LSI MegaRAID SCSI 320-2         1000:1960:1000:0518
+       LSI MegaRAID SCSI 320-0X        1000:0407:1000:0530
+       LSI MegaRAID SCSI 320-2X        1000:0407:1000:0532
+       LSI MegaRAID SCSI 320-4X        1000:0407:1000:0531
+       LSI MegaRAID SCSI 320-1E        1000:0408:1000:0001
+       LSI MegaRAID SCSI 320-2E        1000:0408:1000:0002
+       LSI MegaRAID SATA 150-4         1000:1960:1000:4523
+       LSI MegaRAID SATA 150-6         1000:1960:1000:0523
+       LSI MegaRAID SATA 300-4X        1000:0409:1000:3004
+       LSI MegaRAID SATA 300-8X        1000:0409:1000:3008
+       INTEL RAID Controller SRCU42X   1000:0407:8086:0532
+       INTEL RAID Controller SRCS16    1000:1960:8086:0523
+       INTEL RAID Controller SRCU42E   1000:0408:8086:0002
+       INTEL RAID Controller SRCZCRX   1000:0407:8086:0530
+       INTEL RAID Controller SRCS28X   1000:0409:8086:3008
+       INTEL RAID Controller SROMBU42E 1000:0408:8086:3431
+       INTEL RAID Controller SROMBU42E 1000:0408:8086:3499
+       INTEL RAID Controller SRCU51L   1000:1960:8086:0520
+       FSC MegaRAID PCI Express ROMB   1000:0408:1734:1065
+       ACER MegaRAID ROMB-2E           1000:0408:1025:004D
+
+       To compile this driver as a module, choose M here: the
+       module will be called megaraid_mbox
+
+if MEGARAID_NEWGEN=n
+config MEGARAID_LEGACY
+       tristate "LSI Logic Legacy MegaRAID Driver"
+       depends on PCI && SCSI
+       help
+       This driver supports the LSI MegaRAID 418, 428, 438, 466, 762, 490
+       and 467 SCSI host adapters. This driver also support the all U320
+       RAID controllers
+
+       To compile this driver as a module, choose M here: the
+       module will be called megaraid
+endif
diff --git a/drivers/scsi/megaraid/Makefile b/drivers/scsi/megaraid/Makefile
new file mode 100644 (file)
index 0000000..6dd99f2
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_MEGARAID_MM)      += megaraid_mm.o
+obj-$(CONFIG_MEGARAID_MAILBOX) += megaraid_mbox.o
diff --git a/drivers/scsi/megaraid/mbox_defs.h b/drivers/scsi/megaraid/mbox_defs.h
new file mode 100644 (file)
index 0000000..3052869
--- /dev/null
@@ -0,0 +1,790 @@
+/*
+ *
+ *                     Linux MegaRAID Unified device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic Corporation.
+ *
+ *        This program is free software; you can redistribute it and/or
+ *        modify it under the terms of the GNU General Public License
+ *        as published by the Free Software Foundation; either version
+ *        2 of the License, or (at your option) any later version.
+ *
+ * FILE                : mbox_defs.h
+ *
+ */
+#ifndef _MRAID_MBOX_DEFS_H_
+#define _MRAID_MBOX_DEFS_H_
+
+#include <linux/types.h>
+
+/*
+ * Commands and states for mailbox based controllers
+ */
+
+#define MBOXCMD_LREAD          0x01
+#define MBOXCMD_LWRITE         0x02
+#define MBOXCMD_PASSTHRU       0x03
+#define MBOXCMD_ADPEXTINQ      0x04
+#define MBOXCMD_ADAPTERINQ     0x05
+#define MBOXCMD_LREAD64                0xA7
+#define MBOXCMD_LWRITE64       0xA8
+#define MBOXCMD_PASSTHRU64     0xC3
+#define MBOXCMD_EXTPTHRU       0xE3
+
+#define MAIN_MISC_OPCODE       0xA4
+#define GET_MAX_SG_SUPPORT     0x01
+#define SUPPORT_EXT_CDB                0x16
+
+#define FC_NEW_CONFIG          0xA1
+#define NC_SUBOP_PRODUCT_INFO  0x0E
+#define NC_SUBOP_ENQUIRY3      0x0F
+#define ENQ3_GET_SOLICITED_FULL        0x02
+#define OP_DCMD_READ_CONFIG    0x04
+#define NEW_READ_CONFIG_8LD    0x67
+#define READ_CONFIG_8LD                0x07
+#define FLUSH_ADAPTER          0x0A
+#define FLUSH_SYSTEM           0xFE
+
+/*
+ * Command for random deletion of logical drives
+ */
+#define        FC_DEL_LOGDRV           0xA4
+#define        OP_SUP_DEL_LOGDRV       0x2A
+#define OP_GET_LDID_MAP                0x18
+#define OP_DEL_LOGDRV          0x1C
+
+/*
+ * BIOS commands
+ */
+#define IS_BIOS_ENABLED                0x62
+#define GET_BIOS               0x01
+#define CHNL_CLASS             0xA9
+#define GET_CHNL_CLASS         0x00
+#define SET_CHNL_CLASS         0x01
+#define CH_RAID                        0x01
+#define CH_SCSI                        0x00
+#define BIOS_PVT_DATA          0x40
+#define GET_BIOS_PVT_DATA      0x00
+
+
+/*
+ * Commands to support clustering
+ */
+#define GET_TARGET_ID          0x7D
+#define CLUSTER_OP             0x70
+#define GET_CLUSTER_MODE       0x02
+#define CLUSTER_CMD            0x6E
+#define RESERVE_LD             0x01
+#define RELEASE_LD             0x02
+#define RESET_RESERVATIONS     0x03
+#define RESERVATION_STATUS     0x04
+#define RESERVE_PD             0x05
+#define RELEASE_PD             0x06
+
+
+/*
+ * Module battery status
+ */
+#define BATTERY_MODULE_MISSING         0x01
+#define BATTERY_LOW_VOLTAGE            0x02
+#define BATTERY_TEMP_HIGH              0x04
+#define BATTERY_PACK_MISSING           0x08
+#define BATTERY_CHARGE_MASK            0x30
+#define BATTERY_CHARGE_DONE            0x00
+#define BATTERY_CHARGE_INPROG          0x10
+#define BATTERY_CHARGE_FAIL            0x20
+#define BATTERY_CYCLES_EXCEEDED                0x40
+
+/*
+ * Physical drive states.
+ */
+#define PDRV_UNCNF     0
+#define PDRV_ONLINE    3
+#define PDRV_FAILED    4
+#define PDRV_RBLD      5
+#define PDRV_HOTSPARE  6
+
+
+/*
+ * Raid logical drive states.
+ */
+#define RDRV_OFFLINE   0
+#define RDRV_DEGRADED  1
+#define RDRV_OPTIMAL   2
+#define RDRV_DELETED   3
+
+/*
+ * Read, write and cache policies
+ */
+#define NO_READ_AHEAD          0
+#define READ_AHEAD             1
+#define ADAP_READ_AHEAD                2
+#define WRMODE_WRITE_THRU      0
+#define WRMODE_WRITE_BACK      1
+#define CACHED_IO              0
+#define DIRECT_IO              1
+
+#define MAX_LOGICAL_DRIVES_8LD         8
+#define MAX_LOGICAL_DRIVES_40LD                40
+#define FC_MAX_PHYSICAL_DEVICES                256
+#define MAX_MBOX_CHANNELS              5
+#define MAX_MBOX_TARGET                        15
+#define MBOX_MAX_PHYSICAL_DRIVES       MAX_MBOX_CHANNELS*MAX_MBOX_TARGET
+#define MAX_ROW_SIZE_40LD              32
+#define MAX_ROW_SIZE_8LD               8
+#define SPAN_DEPTH_8_SPANS             8
+#define SPAN_DEPTH_4_SPANS             4
+#define MAX_REQ_SENSE_LEN              0x20
+
+
+
+/**
+ * struct mbox_t - Driver and f/w handshake structure.
+ * @cmd                : firmware command
+ * @cmdid      : command id
+ * @numsectors : number of sectors to be transferred
+ * @lba                : Logical Block Address on LD
+ * @xferaddr   : DMA address for data transfer
+ * @logdrv     : logical drive number
+ * @numsge     : number of scatter gather elements in sg list
+ * @resvd      : reserved
+ * @busy       : f/w busy, must wait to issue more commands.
+ * @numstatus  : number of commands completed.
+ * @status     : status of the commands completed
+ * @completed  : array of completed command ids.
+ * @poll       : poll and ack sequence
+ * @ack                : poll and ack sequence
+ *
+ * The central handshake structure between the driver and the firmware. This
+ * structure must be allocated by the driver and aligned at 8-byte boundary.
+ */
+#define MBOX_MAX_FIRMWARE_STATUS       46
+typedef struct {
+       uint8_t         cmd;
+       uint8_t         cmdid;
+       uint16_t        numsectors;
+       uint32_t        lba;
+       uint32_t        xferaddr;
+       uint8_t         logdrv;
+       uint8_t         numsge;
+       uint8_t         resvd;
+       uint8_t         busy;
+       uint8_t         numstatus;
+       uint8_t         status;
+       uint8_t         completed[MBOX_MAX_FIRMWARE_STATUS];
+       uint8_t         poll;
+       uint8_t         ack;
+} __attribute__ ((packed)) mbox_t;
+
+
+/**
+ * mbox64_t - 64-bit extension for the mailbox
+ * @segment_lo : the low 32-bits of the address of the scatter-gather list
+ * @segment_hi : the upper 32-bits of the address of the scatter-gather list
+ * @mbox       : 32-bit mailbox, whose xferadder field must be set to
+ *             0xFFFFFFFF
+ *
+ * This is the extension of the 32-bit mailbox to be able to perform DMA
+ * beyond 4GB address range.
+ */
+typedef struct {
+       uint32_t        xferaddr_lo;
+       uint32_t        xferaddr_hi;
+       mbox_t          mbox32;
+} __attribute__ ((packed)) mbox64_t;
+
+/*
+ * mailbox structure used for internal commands
+ */
+typedef struct {
+       u8      cmd;
+       u8      cmdid;
+       u8      opcode;
+       u8      subopcode;
+       u32     lba;
+       u32     xferaddr;
+       u8      logdrv;
+       u8      rsvd[3];
+       u8      numstatus;
+       u8      status;
+} __attribute__ ((packed)) int_mbox_t;
+
+/**
+ * mraid_passthru_t - passthru structure to issue commands to physical devices
+ * @timeout            : command timeout, 0=6sec, 1=60sec, 2=10min, 3=3hr
+ * @ars                        : set if ARS required after check condition
+ * @islogical          : set if command meant for logical devices
+ * @logdrv             : logical drive number if command for LD
+ * @channel            : Channel on which physical device is located
+ * @target             : SCSI target of the device
+ * @queuetag           : unused
+ * @queueaction                : unused
+ * @cdb                        : SCSI CDB
+ * @cdblen             : length of the CDB
+ * @reqsenselen                : amount of request sense data to be returned
+ * @reqsensearea       : Sense information buffer
+ * @numsge             : number of scatter-gather elements in the sg list
+ * @scsistatus         : SCSI status of the command completed.
+ * @dataxferaddr       : DMA data transfer address
+ * @dataxferlen                : amount of the data to be transferred.
+ */
+typedef struct {
+       uint8_t         timeout         :3;
+       uint8_t         ars             :1;
+       uint8_t         reserved        :3;
+       uint8_t         islogical       :1;
+       uint8_t         logdrv;
+       uint8_t         channel;
+       uint8_t         target;
+       uint8_t         queuetag;
+       uint8_t         queueaction;
+       uint8_t         cdb[10];
+       uint8_t         cdblen;
+       uint8_t         reqsenselen;
+       uint8_t         reqsensearea[MAX_REQ_SENSE_LEN];
+       uint8_t         numsge;
+       uint8_t         scsistatus;
+       uint32_t        dataxferaddr;
+       uint32_t        dataxferlen;
+} __attribute__ ((packed)) mraid_passthru_t;
+
+typedef struct {
+
+       uint32_t                dataxferaddr_lo;
+       uint32_t                dataxferaddr_hi;
+       mraid_passthru_t        pthru32;
+
+} __attribute__ ((packed)) mega_passthru64_t;
+
+/**
+ * mraid_epassthru_t - passthru structure to issue commands to physical devices
+ * @timeout            : command timeout, 0=6sec, 1=60sec, 2=10min, 3=3hr
+ * @ars                        : set if ARS required after check condition
+ * @rsvd1              : reserved field
+ * @cd_rom             : (?)
+ * @rsvd2              : reserved field
+ * @islogical          : set if command meant for logical devices
+ * @logdrv             : logical drive number if command for LD
+ * @channel            : Channel on which physical device is located
+ * @target             : SCSI target of the device
+ * @queuetag           : unused
+ * @queueaction                : unused
+ * @cdblen             : length of the CDB
+ * @rsvd3              : reserved field
+ * @cdb                        : SCSI CDB
+ * @numsge             : number of scatter-gather elements in the sg list
+ * @status             : SCSI status of the command completed.
+ * @reqsenselen                : amount of request sense data to be returned
+ * @reqsensearea       : Sense information buffer
+ * @rsvd4              : reserved field
+ * @dataxferaddr       : DMA data transfer address
+ * @dataxferlen                : amount of the data to be transferred.
+ */
+typedef struct {
+       uint8_t         timeout         :3;
+       uint8_t         ars             :1;
+       uint8_t         rsvd1           :1;
+       uint8_t         cd_rom          :1;
+       uint8_t         rsvd2           :1;
+       uint8_t         islogical       :1;
+       uint8_t         logdrv;
+       uint8_t         channel;
+       uint8_t         target;
+       uint8_t         queuetag;
+       uint8_t         queueaction;
+       uint8_t         cdblen;
+       uint8_t         rsvd3;
+       uint8_t         cdb[16];
+       uint8_t         numsge;
+       uint8_t         status;
+       uint8_t         reqsenselen;
+       uint8_t         reqsensearea[MAX_REQ_SENSE_LEN];
+       uint8_t         rsvd4;
+       uint32_t        dataxferaddr;
+       uint32_t        dataxferlen;
+} __attribute__ ((packed)) mraid_epassthru_t;
+
+
+/**
+ * mraid_pinfo_t - product info, static information about the controller
+ * @data_size          : current size in bytes (not including resvd)
+ * @config_signature   : Current value is 0x00282008
+ * @fw_version         : Firmware version
+ * @bios_version       : version of the BIOS
+ * @product_name       : Name given to the controller
+ * @max_commands       : Maximum concurrent commands supported
+ * @nchannels          : Number of SCSI Channels detected
+ * @fc_loop_present    : Number of Fibre Loops detected
+ * @mem_type           : EDO, FPM, SDRAM etc
+ * @signature          :
+ * @dram_size          : In terms of MB
+ * @subsysid           : device PCI subsystem ID
+ * @subsysvid          : device PCI subsystem vendor ID
+ * @notify_counters    :
+ * @pad1k              : 135 + 889 resvd = 1024 total size
+ *
+ * This structures holds the information about the controller which is not
+ * expected to change dynamically.
+ *
+ * The current value of config signature is 0x00282008:
+ * 0x28 = MAX_LOGICAL_DRIVES,
+ * 0x20 = Number of stripes and
+ * 0x08 = Number of spans
+ */
+typedef struct {
+       uint32_t        data_size;
+       uint32_t        config_signature;
+       uint8_t         fw_version[16];
+       uint8_t         bios_version[16];
+       uint8_t         product_name[80];
+       uint8_t         max_commands;
+       uint8_t         nchannels;
+       uint8_t         fc_loop_present;
+       uint8_t         mem_type;
+       uint32_t        signature;
+       uint16_t        dram_size;
+       uint16_t        subsysid;
+       uint16_t        subsysvid;
+       uint8_t         notify_counters;
+       uint8_t         pad1k[889];
+} __attribute__ ((packed)) mraid_pinfo_t;
+
+
+/**
+ * mraid_notify_t - the notification structure
+ * @global_counter             : Any change increments this counter
+ * @param_counter              : Indicates any params changed
+ * @param_id                   : Param modified - defined below
+ * @param_val                  : New val of last param modified
+ * @write_config_counter       : write config occurred
+ * @write_config_rsvd          :
+ * @ldrv_op_counter            : Indicates ldrv op started/completed
+ * @ldrv_opid                  : ldrv num
+ * @ldrv_opcmd                 : ldrv operation - defined below
+ * @ldrv_opstatus              : status of the operation
+ * @ldrv_state_counter         : Indicates change of ldrv state
+ * @ldrv_state_id              : ldrv num
+ * @ldrv_state_new             : New state
+ * @ldrv_state_old             : old state
+ * @pdrv_state_counter         : Indicates change of ldrv state
+ * @pdrv_state_id              : pdrv id
+ * @pdrv_state_new             : New state
+ * @pdrv_state_old             : old state
+ * @pdrv_fmt_counter           : Indicates pdrv format started/over
+ * @pdrv_fmt_id                        : pdrv id
+ * @pdrv_fmt_val               : format started/over
+ * @pdrv_fmt_rsvd              :
+ * @targ_xfer_counter          : Indicates SCSI-2 Xfer rate change
+ * @targ_xfer_id               : pdrv Id
+ * @targ_xfer_val              : new Xfer params of last pdrv
+ * @targ_xfer_rsvd             :
+ * @fcloop_id_chg_counter      : Indicates loopid changed
+ * @fcloopid_pdrvid            : pdrv id
+ * @fcloop_id0                 : loopid on fc loop 0
+ * @fcloop_id1                 : loopid on fc loop 1
+ * @fcloop_state_counter       : Indicates loop state changed
+ * @fcloop_state0              : state of fc loop 0
+ * @fcloop_state1              : state of fc loop 1
+ * @fcloop_state_rsvd          :
+ */
+typedef struct {
+       uint32_t        global_counter;
+       uint8_t         param_counter;
+       uint8_t         param_id;
+       uint16_t        param_val;
+       uint8_t         write_config_counter;
+       uint8_t         write_config_rsvd[3];
+       uint8_t         ldrv_op_counter;
+       uint8_t         ldrv_opid;
+       uint8_t         ldrv_opcmd;
+       uint8_t         ldrv_opstatus;
+       uint8_t         ldrv_state_counter;
+       uint8_t         ldrv_state_id;
+       uint8_t         ldrv_state_new;
+       uint8_t         ldrv_state_old;
+       uint8_t         pdrv_state_counter;
+       uint8_t         pdrv_state_id;
+       uint8_t         pdrv_state_new;
+       uint8_t         pdrv_state_old;
+       uint8_t         pdrv_fmt_counter;
+       uint8_t         pdrv_fmt_id;
+       uint8_t         pdrv_fmt_val;
+       uint8_t         pdrv_fmt_rsvd;
+       uint8_t         targ_xfer_counter;
+       uint8_t         targ_xfer_id;
+       uint8_t         targ_xfer_val;
+       uint8_t         targ_xfer_rsvd;
+       uint8_t         fcloop_id_chg_counter;
+       uint8_t         fcloopid_pdrvid;
+       uint8_t         fcloop_id0;
+       uint8_t         fcloop_id1;
+       uint8_t         fcloop_state_counter;
+       uint8_t         fcloop_state0;
+       uint8_t         fcloop_state1;
+       uint8_t         fcloop_state_rsvd;
+} __attribute__ ((packed)) mraid_notify_t;
+
+
+/**
+ * mraid_inquiry3_t - enquiry for device information
+ *
+ * @data_size          : current size in bytes (not including resvd)
+ * @notify             :
+ * @notify_rsvd                :
+ * @rebuild_rate       : rebuild rate (0% - 100%)
+ * @cache_flush_int    : cache flush interval in seconds
+ * @sense_alert                :
+ * @drive_insert_count : drive insertion count
+ * @battery_status     :
+ * @num_ldrv           : no. of Log Drives configured
+ * @recon_state                : state of reconstruct
+ * @ldrv_op_status     : logdrv Status
+ * @ldrv_size          : size of each log drv
+ * @ldrv_prop          :
+ * @ldrv_state         : state of log drives
+ * @pdrv_state         : state of phys drvs.
+ * @pdrv_format                :
+ * @targ_xfer          : phys device transfer rate
+ * @pad1k              : 761 + 263reserved = 1024 bytes total size
+ */
+#define MAX_NOTIFY_SIZE                0x80
+#define CUR_NOTIFY_SIZE                sizeof(mraid_notify_t)
+
+typedef struct {
+       uint32_t        data_size;
+
+       mraid_notify_t  notify;
+
+       uint8_t         notify_rsvd[MAX_NOTIFY_SIZE - CUR_NOTIFY_SIZE];
+
+       uint8_t         rebuild_rate;
+       uint8_t         cache_flush_int;
+       uint8_t         sense_alert;
+       uint8_t         drive_insert_count;
+
+       uint8_t         battery_status;
+       uint8_t         num_ldrv;
+       uint8_t         recon_state[MAX_LOGICAL_DRIVES_40LD / 8];
+       uint16_t        ldrv_op_status[MAX_LOGICAL_DRIVES_40LD / 8];
+
+       uint32_t        ldrv_size[MAX_LOGICAL_DRIVES_40LD];
+       uint8_t         ldrv_prop[MAX_LOGICAL_DRIVES_40LD];
+       uint8_t         ldrv_state[MAX_LOGICAL_DRIVES_40LD];
+       uint8_t         pdrv_state[FC_MAX_PHYSICAL_DEVICES];
+       uint16_t        pdrv_format[FC_MAX_PHYSICAL_DEVICES / 16];
+
+       uint8_t         targ_xfer[80];
+       uint8_t         pad1k[263];
+} __attribute__ ((packed)) mraid_inquiry3_t;
+
+
+/**
+ * mraid_adapinfo_t - information about the adapter
+ * @max_commands               : max concurrent commands supported
+ * @rebuild_rate               : rebuild rate - 0% thru 100%
+ * @max_targ_per_chan          : max targ per channel
+ * @nchannels                  : number of channels on HBA
+ * @fw_version                 : firmware version
+ * @age_of_flash               : number of times FW has been flashed
+ * @chip_set_value             : contents of 0xC0000832
+ * @dram_size                  : in MB
+ * @cache_flush_interval       : in seconds
+ * @bios_version               :
+ * @board_type                 :
+ * @sense_alert                        :
+ * @write_config_count         : increase with every configuration change
+ * @drive_inserted_count       : increase with every drive inserted
+ * @inserted_drive             : channel:Id of inserted drive
+ * @battery_status             : bit 0: battery module missing
+ *                             bit 1: VBAD
+ *                             bit 2: temprature high
+ *                             bit 3: battery pack missing
+ *                             bit 4,5:
+ *                                     00 - charge complete
+ *                                     01 - fast charge in progress
+ *                                     10 - fast charge fail
+ *                                     11 - undefined
+ *                             bit 6: counter > 1000
+ *                             bit 7: Undefined
+ * @dec_fault_bus_info         :
+ */
+typedef struct {
+       uint8_t         max_commands;
+       uint8_t         rebuild_rate;
+       uint8_t         max_targ_per_chan;
+       uint8_t         nchannels;
+       uint8_t         fw_version[4];
+       uint16_t        age_of_flash;
+       uint8_t         chip_set_value;
+       uint8_t         dram_size;
+       uint8_t         cache_flush_interval;
+       uint8_t         bios_version[4];
+       uint8_t         board_type;
+       uint8_t         sense_alert;
+       uint8_t         write_config_count;
+       uint8_t         battery_status;
+       uint8_t         dec_fault_bus_info;
+} __attribute__ ((packed)) mraid_adapinfo_t;
+
+
+/**
+ * mraid_ldrv_info_t - information about the logical drives
+ * @nldrv      : Number of logical drives configured
+ * @rsvd       :
+ * @size       : size of each logical drive
+ * @prop       :
+ * @state      : state of each logical drive
+ */
+typedef struct {
+       uint8_t         nldrv;
+       uint8_t         rsvd[3];
+       uint32_t        size[MAX_LOGICAL_DRIVES_8LD];
+       uint8_t         prop[MAX_LOGICAL_DRIVES_8LD];
+       uint8_t         state[MAX_LOGICAL_DRIVES_8LD];
+} __attribute__ ((packed)) mraid_ldrv_info_t;
+
+
+/**
+ * mraid_pdrv_info_t - information about the physical drives
+ * @pdrv_state : state of each physical drive
+ */
+typedef struct {
+       uint8_t         pdrv_state[MBOX_MAX_PHYSICAL_DRIVES];
+       uint8_t         rsvd;
+} __attribute__ ((packed)) mraid_pdrv_info_t;
+
+
+/**
+ * mraid_inquiry_t - RAID inquiry, mailbox command 0x05
+ * @mraid_adapinfo_t   : adapter information
+ * @mraid_ldrv_info_t  : logical drives information
+ * @mraid_pdrv_info_t  : physical drives information
+ */
+typedef struct {
+       mraid_adapinfo_t        adapter_info;
+       mraid_ldrv_info_t       logdrv_info;
+       mraid_pdrv_info_t       pdrv_info;
+} __attribute__ ((packed)) mraid_inquiry_t;
+
+
+/**
+ * mraid_extinq_t - RAID extended inquiry, mailbox command 0x04
+ *
+ * @raid_inq           : raid inquiry
+ * @phys_drv_format    :
+ * @stack_attn         :
+ * @modem_status       :
+ * @rsvd               :
+ */
+typedef struct {
+       mraid_inquiry_t raid_inq;
+       uint16_t        phys_drv_format[MAX_MBOX_CHANNELS];
+       uint8_t         stack_attn;
+       uint8_t         modem_status;
+       uint8_t         rsvd[2];
+} __attribute__ ((packed)) mraid_extinq_t;
+
+
+/**
+ * adap_device_t - device information
+ * @channel    : channel fpor the device
+ * @target     : target ID of the device
+ */
+typedef struct {
+       uint8_t         channel;
+       uint8_t         target;
+}__attribute__ ((packed)) adap_device_t;
+
+
+/**
+ * adap_span_40ld_t - 40LD span
+ * @start_blk  : starting block
+ * @num_blks   : number of blocks
+ */
+typedef struct {
+       uint32_t        start_blk;
+       uint32_t        num_blks;
+       adap_device_t   device[MAX_ROW_SIZE_40LD];
+}__attribute__ ((packed)) adap_span_40ld_t;
+
+
+/**
+ * adap_span_8ld_t - 8LD span
+ * @start_blk  : starting block
+ * @num_blks   : number of blocks
+ */
+typedef struct {
+       uint32_t        start_blk;
+       uint32_t        num_blks;
+       adap_device_t   device[MAX_ROW_SIZE_8LD];
+}__attribute__ ((packed)) adap_span_8ld_t;
+
+
+/**
+ * logdrv_param_t - logical drives parameters
+ *
+ * @span_depth : total number of spans
+ * @level      : RAID level
+ * @read_ahead : read ahead, no read ahead, adaptive read ahead
+ * @stripe_sz  : encoded stripe size
+ * @status     : status of the logical drive
+ * @write_mode : write mode, write_through/write_back
+ * @direct_io  : direct io or through cache
+ * @row_size   : number of stripes in a row
+ */
+typedef struct {
+       uint8_t         span_depth;
+       uint8_t         level;
+       uint8_t         read_ahead;
+       uint8_t         stripe_sz;
+       uint8_t         status;
+       uint8_t         write_mode;
+       uint8_t         direct_io;
+       uint8_t         row_size;
+} __attribute__ ((packed)) logdrv_param_t;
+
+
+/**
+ * logdrv_40ld_t - logical drive definition for 40LD controllers
+ * @lparam     : logical drives parameters
+ * @span       : span
+ */
+typedef struct {
+       logdrv_param_t          lparam;
+       adap_span_40ld_t        span[SPAN_DEPTH_8_SPANS];
+}__attribute__ ((packed)) logdrv_40ld_t;
+
+
+/**
+ * logdrv_8ld_span8_t - logical drive definition for 8LD controllers
+ * @lparam     : logical drives parameters
+ * @span       : span
+ *
+ * 8-LD logical drive with upto 8 spans
+ */
+typedef struct {
+       logdrv_param_t  lparam;
+       adap_span_8ld_t span[SPAN_DEPTH_8_SPANS];
+}__attribute__ ((packed)) logdrv_8ld_span8_t;
+
+
+/**
+ * logdrv_8ld_span4_t - logical drive definition for 8LD controllers
+ * @lparam     : logical drives parameters
+ * @span       : span
+ *
+ * 8-LD logical drive with upto 4 spans
+ */
+typedef struct {
+       logdrv_param_t  lparam;
+       adap_span_8ld_t span[SPAN_DEPTH_4_SPANS];
+}__attribute__ ((packed)) logdrv_8ld_span4_t;
+
+
+/**
+ * phys_drive_t - physical device information
+ * @type       : Type of the device
+ * @cur_status : current status of the device
+ * @tag_depth  : Level of tagging
+ * @sync_neg   : sync negotiation - ENABLE or DISBALE
+ * @size       : configurable size in terms of 512 byte
+ */
+typedef struct {
+       uint8_t         type;
+       uint8_t         cur_status;
+       uint8_t         tag_depth;
+       uint8_t         sync_neg;
+       uint32_t        size;
+}__attribute__ ((packed)) phys_drive_t;
+
+
+/**
+ * disk_array_40ld_t - disk array for 40LD controllers
+ * @numldrv    : number of logical drives
+ * @resvd      :
+ * @ldrv       : logical drives information
+ * @pdrv       : physical drives information
+ */
+typedef struct {
+       uint8_t         numldrv;
+       uint8_t         resvd[3];
+       logdrv_40ld_t   ldrv[MAX_LOGICAL_DRIVES_40LD];
+       phys_drive_t    pdrv[MBOX_MAX_PHYSICAL_DRIVES];
+}__attribute__ ((packed)) disk_array_40ld_t;
+
+
+/**
+ * disk_array_8ld_span8_t - disk array for 8LD controllers
+ * @numldrv    : number of logical drives
+ * @resvd      :
+ * @ldrv       : logical drives information
+ * @pdrv       : physical drives information
+ *
+ * Disk array for 8LD logical drives with upto 8 spans
+ */
+typedef struct {
+       uint8_t                 numldrv;
+       uint8_t                 resvd[3];
+       logdrv_8ld_span8_t      ldrv[MAX_LOGICAL_DRIVES_8LD];
+       phys_drive_t            pdrv[MBOX_MAX_PHYSICAL_DRIVES];
+}__attribute__ ((packed)) disk_array_8ld_span8_t;
+
+
+/**
+ * disk_array_8ld_span4_t - disk array for 8LD controllers
+ * @numldrv    : number of logical drives
+ * @resvd      :
+ * @ldrv       : logical drives information
+ * @pdrv       : physical drives information
+ *
+ * Disk array for 8LD logical drives with upto 4 spans
+ */
+typedef struct {
+       uint8_t                 numldrv;
+       uint8_t                 resvd[3];
+       logdrv_8ld_span4_t      ldrv[MAX_LOGICAL_DRIVES_8LD];
+       phys_drive_t            pdrv[MBOX_MAX_PHYSICAL_DRIVES];
+}__attribute__ ((packed)) disk_array_8ld_span4_t;
+
+
+/**
+ * private_bios_data - bios private data for boot devices
+ * @geometry   : bits 0-3 - BIOS geometry, 0x0001 - 1GB, 0x0010 - 2GB,
+ *             0x1000 - 8GB, Others values are invalid
+ * @unused     : bits 4-7 are unused
+ * @boot_drv   : logical drive set as boot drive, 0..7 - for 8LD cards,
+ *             0..39 - for 40LD cards
+ * @cksum      : 0-(sum of first 13 bytes of this structure)
+ */
+struct private_bios_data {
+       uint8_t         geometry        :4;
+       uint8_t         unused          :4;
+       uint8_t         boot_drv;
+       uint8_t         rsvd[12];
+       uint16_t        cksum;
+} __attribute__ ((packed));
+
+
+/**
+ * mbox_sgl64 - 64-bit scatter list for mailbox based controllers
+ * @address    : address of the buffer
+ * @length     : data transfer length
+ */
+typedef struct {
+       uint64_t        address;
+       uint32_t        length;
+} __attribute__ ((packed)) mbox_sgl64;
+
+/**
+ * mbox_sgl32 - 32-bit scatter list for mailbox based controllers
+ * @address    : address of the buffer
+ * @length     : data transfer length
+ */
+typedef struct {
+       uint32_t        address;
+       uint32_t        length;
+} __attribute__ ((packed)) mbox_sgl32;
+
+#endif         // _MRAID_MBOX_DEFS_H_
+
+/* vim: set ts=8 sw=8 tw=78: */
diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
new file mode 100644 (file)
index 0000000..e151175
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ *
+ *                     Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic Corporation.
+ *
+ *        This program is free software; you can redistribute it and/or
+ *        modify it under the terms of the GNU General Public License
+ *        as published by the Free Software Foundation; either version
+ *        2 of the License, or (at your option) any later version.
+ *
+ * FILE                : mega_common.h
+ *
+ * Libaray of common routine used by all low-level megaraid drivers
+ */
+
+#ifndef _MEGA_COMMON_H_
+#define _MEGA_COMMON_H_
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/blkdev.h>
+#include <linux/list.h>
+#include <linux/version.h>
+#include <linux/moduleparam.h>
+#include <asm/semaphore.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+
+#define LSI_MAX_CHANNELS               16
+#define LSI_MAX_LOGICAL_DRIVES_64LD    (64+1)
+
+
+/**
+ * scb_t - scsi command control block
+ * @param ccb          : command control block for individual driver
+ * @param list         : list of control blocks
+ * @param gp           : general purpose field for LLDs
+ * @param sno          : all SCBs have a serial number
+ * @param scp          : associated scsi command
+ * @param state                : current state of scb
+ * @param dma_dir      : direction of data transfer
+ * @param dma_type     : transfer with sg list, buffer, or no data transfer
+ * @param dev_channel  : actual channel on the device
+ * @param dev_target   : actual target on the device
+ * @param status       : completion status
+ *
+ * This is our central data structure to issue commands the each driver.
+ * Driver specific data structures are maintained in the ccb field.
+ * scb provides a field 'gp', which can be used by LLD for its own purposes
+ *
+ * dev_channel and dev_target must be initialized with the actual channel and
+ * target on the controller.
+ */
+typedef struct {
+       caddr_t                 ccb;
+       struct list_head        list;
+       unsigned long           gp;
+       unsigned int            sno;
+       struct scsi_cmnd        *scp;
+       uint32_t                state;
+       uint32_t                dma_direction;
+       uint32_t                dma_type;
+       uint16_t                dev_channel;
+       uint16_t                dev_target;
+       uint32_t                status;
+} scb_t;
+
+/*
+ * SCB states as it transitions from one state to another
+ */
+#define SCB_FREE       0x0000  /* on the free list */
+#define SCB_ACTIVE     0x0001  /* off the free list */
+#define SCB_PENDQ      0x0002  /* on the pending queue */
+#define SCB_ISSUED     0x0004  /* issued - owner f/w */
+#define SCB_ABORT      0x0008  /* Got an abort for this one */
+#define SCB_RESET      0x0010  /* Got a reset for this one */
+
+/*
+ * DMA types for scb
+ */
+#define MRAID_DMA_NONE 0x0000  /* no data transfer for this command */
+#define MRAID_DMA_WSG  0x0001  /* data transfer using a sg list */
+#define MRAID_DMA_WBUF 0x0002  /* data transfer using a contiguous buffer */
+
+
+/**
+ * struct adapter_t - driver's initialization structure
+ * @param dpc_h                        : tasklet handle
+ * @param pdev                 : pci configuration pointer for kernel
+ * @param host                 : pointer to host structure of mid-layer
+ * @param host_lock            : pointer to appropriate lock
+ * @param lock                 : synchronization lock for mid-layer and driver
+ * @param quiescent            : driver is quiescent for now.
+ * @param outstanding_cmds     : number of commands pending in the driver
+ * @param kscb_list            : pointer to the bulk of SCBs pointers for IO
+ * @param kscb_pool            : pool of free scbs for IO
+ * @param kscb_pool_lock       : lock for pool of free scbs
+ * @param pend_list            : pending commands list
+ * @param pend_list_lock       : exlusion lock for pending commands list
+ * @param completed_list       : list of completed commands
+ * @param completed_list_lock  : exclusion lock for list of completed commands
+ * @param sglen                        : max sg elements supported
+ * @param device_ids           : to convert kernel device addr to our devices.
+ * @param raid_device          : raid adapter specific pointer
+ * @param max_channel          : maximum channel number supported - inclusive
+ * @param max_target           : max target supported - inclusive
+ * @param max_lun              : max lun supported - inclusive
+ * @param unique_id            : unique identifier for each adapter
+ * @param irq                  : IRQ for this adapter
+ * @param ito                  : internal timeout value, (-1) means no timeout
+ * @param ibuf                 : buffer to issue internal commands
+ * @param ibuf_dma_h           : dma handle for the above buffer
+ * @param uscb_list            : SCB pointers for user cmds, common mgmt module
+ * @param uscb_pool            : pool of SCBs for user commands
+ * @param uscb_pool_lock       : exclusion lock for these SCBs
+ * @param max_cmds             : max outstanding commands
+ * @param fw_version           : firmware version
+ * @param bios_version         : bios version
+ * @param max_cdb_sz           : biggest CDB size supported.
+ * @param ha                   : is high availability present - clustering
+ * @param init_id              : initiator ID, the default value should be 7
+ * @param max_sectors          : max sectors per request
+ * @param cmd_per_lun          : max outstanding commands per LUN
+ * @param being_detached       : set when unloading, no more mgmt calls
+ *
+ *
+ * mraid_setup_device_map() can be called anytime after the device map is
+ * available and MRAID_GET_DEVICE_MAP() can be called whenever the mapping is
+ * required, usually from LLD's queue entry point. The formar API sets up the
+ * MRAID_IS_LOGICAL(adapter_t *, struct scsi_cmnd *) to find out if the
+ * device in question is a logical drive.
+ *
+ * quiescent flag should be set by the driver if it is not accepting more
+ * commands
+ *
+ * NOTE: The fields of this structures are placed to minimize cache misses
+ */
+
+// amount of space required to store the bios and firmware version strings
+#define VERSION_SIZE   16
+
+typedef struct {
+       struct tasklet_struct   dpc_h;
+       struct pci_dev          *pdev;
+       struct Scsi_Host        *host;
+       spinlock_t              *host_lock;
+       spinlock_t              lock;
+       uint8_t                 quiescent;
+       int                     outstanding_cmds;
+       scb_t                   *kscb_list;
+       struct list_head        kscb_pool;
+       spinlock_t              kscb_pool_lock;
+       struct list_head        pend_list;
+       spinlock_t              pend_list_lock;
+       struct list_head        completed_list;
+       spinlock_t              completed_list_lock;
+       uint16_t                sglen;
+       int                     device_ids[LSI_MAX_CHANNELS]
+                                       [LSI_MAX_LOGICAL_DRIVES_64LD];
+       caddr_t                 raid_device;
+       uint8_t                 max_channel;
+       uint16_t                max_target;
+       uint8_t                 max_lun;
+
+       uint32_t                unique_id;
+       uint8_t                 irq;
+       uint8_t                 ito;
+       caddr_t                 ibuf;
+       dma_addr_t              ibuf_dma_h;
+       scb_t                   *uscb_list;
+       struct list_head        uscb_pool;
+       spinlock_t              uscb_pool_lock;
+       int                     max_cmds;
+       uint8_t                 fw_version[VERSION_SIZE];
+       uint8_t                 bios_version[VERSION_SIZE];
+       uint8_t                 max_cdb_sz;
+       uint8_t                 ha;
+       uint16_t                init_id;
+       uint16_t                max_sectors;
+       uint16_t                cmd_per_lun;
+       atomic_t                being_detached;
+} adapter_t;
+
+#define SCSI_FREE_LIST_LOCK(adapter)   (&adapter->kscb_pool_lock)
+#define USER_FREE_LIST_LOCK(adapter)   (&adapter->uscb_pool_lock)
+#define PENDING_LIST_LOCK(adapter)     (&adapter->pend_list_lock)
+#define COMPLETED_LIST_LOCK(adapter)   (&adapter->completed_list_lock)
+
+
+// conversion from scsi command
+#define SCP2HOST(scp)                  (scp)->device->host     // to host
+#define SCP2HOSTDATA(scp)              SCP2HOST(scp)->hostdata // to soft state
+#define SCP2CHANNEL(scp)               (scp)->device->channel  // to channel
+#define SCP2TARGET(scp)                        (scp)->device->id       // to target
+#define SCP2LUN(scp)                   (scp)->device->lun      // to LUN
+
+// generic macro to convert scsi command and host to controller's soft state
+#define SCSIHOST2ADAP(host)    (((caddr_t *)(host->hostdata))[0])
+#define SCP2ADAPTER(scp)       (adapter_t *)SCSIHOST2ADAP(SCP2HOST(scp))
+
+
+/**
+ * MRAID_GET_DEVICE_MAP - device ids
+ * @param adp          - Adapter's soft state
+ * @param scp          - mid-layer scsi command pointer
+ * @param p_chan       - physical channel on the controller
+ * @param target       - target id of the device or logical drive number
+ * @param islogical    - set if the command is for the logical drive
+ *
+ * Macro to retrieve information about device class, logical or physical and
+ * the corresponding physical channel and target or logical drive number
+ **/
+#define MRAID_IS_LOGICAL(adp, scp)     \
+       (SCP2CHANNEL(scp) == (adp)->max_channel) ? 1 : 0
+
+#define MRAID_GET_DEVICE_MAP(adp, scp, p_chan, target, islogical)      \
+       /*                                                              \
+        * Is the request coming for the virtual channel                \
+        */                                                             \
+       islogical = MRAID_IS_LOGICAL(adp, scp);                         \
+                                                                       \
+       /*                                                              \
+        * Get an index into our table of drive ids mapping             \
+        */                                                             \
+       if (islogical) {                                                \
+               p_chan = 0xFF;                                          \
+               target =                                                \
+               (adp)->device_ids[(adp)->max_channel][SCP2TARGET(scp)]; \
+       }                                                               \
+       else {                                                          \
+               p_chan = ((adp)->device_ids[SCP2CHANNEL(scp)]           \
+                                       [SCP2TARGET(scp)] >> 8) & 0xFF; \
+               target = ((adp)->device_ids[SCP2CHANNEL(scp)]           \
+                                       [SCP2TARGET(scp)] & 0xFF);      \
+       }
+
+/*
+ * ### Helper routines ###
+ */
+#define LSI_DBGLVL mraid_debug_level   // each LLD must define a global
+                                       // mraid_debug_level
+
+#ifdef DEBUG
+#if defined (_ASSERT_PANIC)
+#define ASSERT_ACTION  panic
+#else
+#define ASSERT_ACTION  printk
+#endif
+
+#define ASSERT(expression)                                             \
+       if (!(expression)) {                                            \
+       ASSERT_ACTION("assertion failed:(%s), file: %s, line: %d:%s\n", \
+                       #expression, __FILE__, __LINE__, __FUNCTION__); \
+       }
+#else
+#define ASSERT(expression)
+#endif
+
+/*
+ * struct mraid_pci_blk - structure holds DMA memory block info
+ * @param vaddr                : virtual address to a memory block
+ * @param dma_addr     : DMA handle to a memory block
+ *
+ * This structure is filled up for the caller. It is the responsibilty of the
+ * caller to allocate this array big enough to store addresses for all
+ * requested elements
+ */
+struct mraid_pci_blk {
+       caddr_t         vaddr;
+       dma_addr_t      dma_addr;
+};
+
+#endif // _MEGA_COMMON_H_
+
+// vim: set ts=8 sw=8 tw=78:
diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h
new file mode 100644 (file)
index 0000000..44584ca
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ *
+ *                     Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic Corporation.
+ *
+ *        This program is free software; you can redistribute it and/or
+ *        modify it under the terms of the GNU General Public License
+ *        as published by the Free Software Foundation; either version
+ *        2 of the License, or (at your option) any later version.
+ *
+ * FILE                : megaraid_ioctl.h
+ *
+ * Definitions to interface with user level applications
+ */
+
+#ifndef _MEGARAID_IOCTL_H_
+#define _MEGARAID_IOCTL_H_
+
+#include <linux/types.h>
+#include <asm/semaphore.h>
+
+#include "mbox_defs.h"
+
+/**
+ * con_log() - console log routine
+ * @param level                : indicates the severity of the message.
+ * @fparam mt          : format string
+ *
+ * con_log displays the error messages on the console based on the current
+ * debug level. Also it attaches the appropriate kernel severity level with
+ * the message.
+ *
+ *
+ * consolge messages debug levels
+ */
+#define        CL_ANN          0       /* print unconditionally, announcements */
+#define CL_DLEVEL1     1       /* debug level 1, informative */
+#define CL_DLEVEL2     2       /* debug level 2, verbose */
+#define CL_DLEVEL3     3       /* debug level 3, very verbose */
+
+#define        con_log(level, fmt) if (LSI_DBGLVL >= level) printk fmt;
+
+/*
+ * Definitions & Declarations needed to use common management module
+ */
+
+#define MEGAIOC_MAGIC          'm'
+#define MEGAIOCCMD             _IOWR(MEGAIOC_MAGIC, 0, mimd_t)
+
+#define MEGAIOC_QNADAP         'm'     /* Query # of adapters          */
+#define MEGAIOC_QDRVRVER       'e'     /* Query driver version         */
+#define MEGAIOC_QADAPINFO      'g'     /* Query adapter information    */
+
+#define USCSICMD               0x80
+#define UIOC_RD                        0x00001
+#define UIOC_WR                        0x00002
+
+#define MBOX_CMD               0x00000
+#define GET_DRIVER_VER         0x10000
+#define GET_N_ADAP             0x20000
+#define GET_ADAP_INFO          0x30000
+#define GET_CAP                        0x40000
+#define GET_STATS              0x50000
+#define GET_IOCTL_VERSION      0x01
+
+#define EXT_IOCTL_SIGN_SZ      16
+#define EXT_IOCTL_SIGN         "$$_EXTD_IOCTL_$$"
+
+#define        MBOX_LEGACY             0x00            /* ioctl has legacy mbox*/
+#define MBOX_HPE               0x01            /* ioctl has hpe mbox   */
+
+#define        APPTYPE_MIMD            0x00            /* old existing apps    */
+#define APPTYPE_UIOC           0x01            /* new apps using uioc  */
+
+#define IOCTL_ISSUE            0x00000001      /* Issue ioctl          */
+#define IOCTL_ABORT            0x00000002      /* Abort previous ioctl */
+
+#define DRVRTYPE_MBOX          0x00000001      /* regular mbox driver  */
+#define DRVRTYPE_HPE           0x00000002      /* new hpe driver       */
+
+#define MKADAP(adapno) (MEGAIOC_MAGIC << 8 | (adapno) )
+#define GETADAP(mkadap)        ((mkadap) ^ MEGAIOC_MAGIC << 8)
+
+#define MAX_DMA_POOLS          5               /* 4k, 8k, 16k, 32k, 64k*/
+
+
+/**
+ * struct uioc_t - the common ioctl packet structure
+ *
+ * @signature  : Must be "$$_EXTD_IOCTL_$$"
+ * @mb_type    : Type of the mail box (MB_LEGACY or MB_HPE)
+ * @app_type   : Type of the issuing application (existing or new)
+ * @opcode     : Opcode of the command
+ * @adapno     : Adapter number
+ * @cmdbuf     : Pointer to buffer - can point to mbox or plain data buffer
+ * @xferlen    : xferlen for DCMD and non mailbox commands
+ * @data_dir   : Direction of the data transfer
+ * @status     : Status from the driver
+ * @reserved   : reserved bytes for future expansion
+ *
+ * @user_data  : user data transfer address is saved in this
+ * @user_data_len: length of the data buffer sent by user app
+ * @user_pthru : user passthru address is saves in this (null if DCMD)
+ * @pthru32    : kernel address passthru (allocated per kioc)
+ * @pthru32_h  : physicall address of @pthru32
+ * @list       : for kioc free pool list maintenance
+ * @done       : call back routine for llds to call when kioc is completed
+ * @buf_vaddr  : dma pool buffer attached to kioc for data transfer
+ * @buf_paddr  : physical address of the dma pool buffer
+ * @pool_index : index of the dma pool that @buf_vaddr is taken from
+ * @free_buf   : indicates if buffer needs to be freed after kioc completes
+ *
+ * Note                : All LSI drivers understand only this packet. Any other
+ *             : format sent by applications would be converted to this.
+ */
+typedef struct uioc {
+
+/* User Apps: */
+
+       uint8_t                 signature[EXT_IOCTL_SIGN_SZ];
+       uint16_t                mb_type;
+       uint16_t                app_type;
+       uint32_t                opcode;
+       uint32_t                adapno;
+       uint64_t                cmdbuf;
+       uint32_t                xferlen;
+       uint32_t                data_dir;
+       int32_t                 status;
+       uint8_t                 reserved[128];
+
+/* Driver Data: */
+       void __user *           user_data;
+       uint32_t                user_data_len;
+       mraid_passthru_t        __user *user_pthru;
+
+       mraid_passthru_t        *pthru32;
+       dma_addr_t              pthru32_h;
+
+       struct list_head        list;
+       void                    (*done)(struct uioc*);
+
+       caddr_t                 buf_vaddr;
+       dma_addr_t              buf_paddr;
+       uint8_t                 pool_index;
+       uint8_t                 free_buf;
+
+} __attribute__ ((aligned(1024),packed)) uioc_t;
+
+
+/**
+ * struct mraid_hba_info - information about the controller
+ *
+ * @param pci_vendor_id                : PCI vendor id
+ * @param pci_device_id                : PCI device id
+ * @param subsystem_vendor_id  : PCI subsystem vendor id
+ * @param subsystem_device_id  : PCI subsystem device id
+ * @param baseport             : base port of hba memory
+ * @param pci_bus              : PCI bus
+ * @param pci_dev_fn           : PCI device/function values
+ * @param irq                  : interrupt vector for the device
+ *
+ * Extended information of 256 bytes about the controller. Align on the single
+ * byte boundary so that 32-bit applications can be run on 64-bit platform
+ * drivers withoug re-compilation.
+ * NOTE: reduce the number of reserved bytes whenever new field are added, so
+ * that total size of the structure remains 256 bytes.
+ */
+typedef struct mraid_hba_info {
+
+       uint16_t        pci_vendor_id;
+       uint16_t        pci_device_id;
+       uint16_t        subsys_vendor_id;
+       uint16_t        subsys_device_id;
+
+       uint64_t        baseport;
+       uint8_t         pci_bus;
+       uint8_t         pci_dev_fn;
+       uint8_t         pci_slot;
+       uint8_t         irq;
+
+       uint32_t        unique_id;
+       uint32_t        host_no;
+
+       uint8_t         num_ldrv;
+} __attribute__ ((aligned(256), packed)) mraid_hba_info_t;
+
+
+/**
+ * mcontroller : adapter info structure for old mimd_t apps
+ *
+ * @base       : base address
+ * @irq                : irq number
+ * @numldrv    : number of logical drives
+ * @pcibus     : pci bus
+ * @pcidev     : pci device
+ * @pcifun     : pci function
+ * @pciid      : pci id
+ * @pcivendor  : vendor id
+ * @pcislot    : slot number
+ * @uid                : unique id
+ */
+typedef struct mcontroller {
+
+       uint64_t        base;
+       uint8_t         irq;
+       uint8_t         numldrv;
+       uint8_t         pcibus;
+       uint16_t        pcidev;
+       uint8_t         pcifun;
+       uint16_t        pciid;
+       uint16_t        pcivendor;
+       uint8_t         pcislot;
+       uint32_t        uid;
+
+} __attribute__ ((packed)) mcontroller_t;
+
+
+/**
+ * mm_dmapool_t        : Represents one dma pool with just one buffer
+ *
+ * @vaddr      : Virtual address
+ * @paddr      : DMA physicall address
+ * @bufsize    : In KB - 4 = 4k, 8 = 8k etc.
+ * @handle     : Handle to the dma pool
+ * @lock       : lock to synchronize access to the pool
+ * @in_use     : If pool already in use, attach new block
+ */
+typedef struct mm_dmapool {
+       caddr_t         vaddr;
+       dma_addr_t      paddr;
+       uint32_t        buf_size;
+       struct dma_pool *handle;
+       spinlock_t      lock;
+       uint8_t         in_use;
+} mm_dmapool_t;
+
+
+/**
+ * mraid_mmadp_t: Structure that drivers pass during (un)registration
+ *
+ * @unique_id          : Any unique id (usually PCI bus+dev+fn)
+ * @drvr_type          : megaraid or hpe (DRVRTYPE_MBOX or DRVRTYPE_HPE)
+ * @drv_data           : Driver specific; not touched by the common module
+ * @timeout            : timeout for issued kiocs
+ * @max_kioc           : Maximum ioctl packets acceptable by the lld
+ * @pdev               : pci dev; used for allocating dma'ble memory
+ * @issue_uioc         : Driver supplied routine to issue uioc_t commands
+ *                     : issue_uioc(drvr_data, kioc, ISSUE/ABORT, uioc_done)
+ * @list               : attach with the global list of adapters
+ * @kioc_list          : block of mem for @max_kioc number of kiocs
+ * @kioc_pool          : pool of free kiocs
+ * @kioc_pool_lock     : protection for free pool
+ * @kioc_semaphore     : so as not to exceed @max_kioc parallel ioctls
+ * @mbox_list          : block of mem for @max_kioc number of mboxes
+ * @pthru_dma_pool     : DMA pool to allocate passthru packets
+ * @dma_pool_list      : array of dma pools
+ */
+
+typedef struct mraid_mmadp {
+
+/* Filled by driver */
+
+       uint32_t                unique_id;
+       uint32_t                drvr_type;
+       unsigned long           drvr_data;
+       uint8_t                 timeout;
+       uint8_t                 max_kioc;
+
+       struct pci_dev          *pdev;
+
+       int(*issue_uioc)(unsigned long, uioc_t *, uint32_t);
+
+/* Maintained by common module */
+
+       struct list_head        list;
+       uioc_t                  *kioc_list;
+       struct list_head        kioc_pool;
+       spinlock_t              kioc_pool_lock;
+       struct semaphore        kioc_semaphore;
+
+       mbox64_t                *mbox_list;
+       struct dma_pool         *pthru_dma_pool;
+       mm_dmapool_t            dma_pool_list[MAX_DMA_POOLS];
+
+} mraid_mmadp_t;
+
+int mraid_mm_register_adp(mraid_mmadp_t *);
+int mraid_mm_unregister_adp(uint32_t);
+
+#endif /* _MEGARAID_IOCTL_H_ */
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
new file mode 100644 (file)
index 0000000..7afd6a5
--- /dev/null
@@ -0,0 +1,3891 @@
+/*
+ *
+ *                     Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic Corporation.
+ *
+ *        This program is free software; you can redistribute it and/or
+ *        modify it under the terms of the GNU General Public License
+ *        as published by the Free Software Foundation; either version
+ *        2 of the License, or (at your option) any later version.
+ *
+ * FILE                : megaraid_mbox.c
+ * Version     : v2.20.4 (September 27 2004)
+ *
+ * Authors:
+ *     Atul Mukker             <Atul.Mukker@lsil.com>
+ *     Sreenivas Bagalkote     <Sreenivas.Bagalkote@lsil.com>
+ *     Manoj Jose              <Manoj.Jose@lsil.com>
+ *
+ * List of supported controllers
+ *
+ * OEM Product Name                    VID     DID     SSVID   SSID
+ * --- ------------                    ---     ---     ----    ----
+ * Dell PERC3/QC                       101E    1960    1028    0471
+ * Dell PERC3/DC                       101E    1960    1028    0493
+ * Dell PERC3/SC                       101E    1960    1028    0475
+ * Dell PERC3/Di                       1028    1960    1028    0123
+ * Dell PERC4/SC                       1000    1960    1028    0520
+ * Dell PERC4/DC                       1000    1960    1028    0518
+ * Dell PERC4/QC                       1000    0407    1028    0531
+ * Dell PERC4/Di                       1028    000F    1028    014A
+ * Dell PERC 4e/Si                     1028    0013    1028    016c
+ * Dell PERC 4e/Di                     1028    0013    1028    016d
+ * Dell PERC 4e/Di                     1028    0013    1028    016e
+ * Dell PERC 4e/Di                     1028    0013    1028    016f
+ * Dell PERC 4e/Di                     1028    0013    1028    0170
+ * Dell PERC 4e/DC                     1000    0408    1028    0002
+ * Dell PERC 4e/SC                     1000    0408    1028    0001
+ *
+ *
+ * LSI MegaRAID SCSI 320-0             1000    1960    1000    A520
+ * LSI MegaRAID SCSI 320-1             1000    1960    1000    0520
+ * LSI MegaRAID SCSI 320-2             1000    1960    1000    0518
+ * LSI MegaRAID SCSI 320-0X            1000    0407    1000    0530
+ * LSI MegaRAID SCSI 320-2X            1000    0407    1000    0532
+ * LSI MegaRAID SCSI 320-4X            1000    0407    1000    0531
+ * LSI MegaRAID SCSI 320-1E            1000    0408    1000    0001
+ * LSI MegaRAID SCSI 320-2E            1000    0408    1000    0002
+ * LSI MegaRAID SATA 150-4             1000    1960    1000    4523
+ * LSI MegaRAID SATA 150-6             1000    1960    1000    0523
+ * LSI MegaRAID SATA 300-4X            1000    0409    1000    3004
+ * LSI MegaRAID SATA 300-8X            1000    0409    1000    3008
+ *
+ * INTEL RAID Controller SRCU42X       1000    0407    8086    0532
+ * INTEL RAID Controller SRCS16                1000    1960    8086    0523
+ * INTEL RAID Controller SRCU42E       1000    0408    8086    0002
+ * INTEL RAID Controller SRCZCRX       1000    0407    8086    0530
+ * INTEL RAID Controller SRCS28X       1000    0409    8086    3008
+ * INTEL RAID Controller SROMBU42E     1000    0408    8086    3431
+ * INTEL RAID Controller SROMBU42E     1000    0408    8086    3499
+ * INTEL RAID Controller SRCU51L       1000    1960    8086    0520
+ *
+ *
+ * FSC MegaRAID PCI Express ROMB       1000    0408    1734    1065
+ *
+ *
+ * ACER        MegaRAID ROMB-2E                1000    0408    1025    004D
+ *
+ *
+ * For history of changes, see Documentation/ChangeLog.megaraid
+ */
+
+#include "megaraid_mbox.h"
+
+static int megaraid_init(void);
+static void megaraid_exit(void);
+
+static int megaraid_probe_one(struct pci_dev*, const struct pci_device_id *);
+static void megaraid_detach_one(struct pci_dev *);
+static void megaraid_mbox_shutdown(struct device *);
+
+static int megaraid_io_attach(adapter_t *);
+static void megaraid_io_detach(adapter_t *);
+
+static int megaraid_init_mbox(adapter_t *);
+static void megaraid_fini_mbox(adapter_t *);
+
+static int megaraid_alloc_cmd_packets(adapter_t *);
+static void megaraid_free_cmd_packets(adapter_t *);
+
+static int megaraid_mbox_setup_dma_pools(adapter_t *);
+static void megaraid_mbox_teardown_dma_pools(adapter_t *);
+
+static int megaraid_abort_handler(struct scsi_cmnd *);
+static int megaraid_reset_handler(struct scsi_cmnd *);
+
+static int mbox_post_sync_cmd(adapter_t *, uint8_t []);
+static int mbox_post_sync_cmd_fast(adapter_t *, uint8_t []);
+static int megaraid_busywait_mbox(mraid_device_t *);
+static int megaraid_mbox_product_info(adapter_t *);
+static int megaraid_mbox_extended_cdb(adapter_t *);
+static int megaraid_mbox_support_ha(adapter_t *, uint16_t *);
+static int megaraid_mbox_support_random_del(adapter_t *);
+static int megaraid_mbox_get_max_sg(adapter_t *);
+static void megaraid_mbox_enum_raid_scsi(adapter_t *);
+static void megaraid_mbox_flush_cache(adapter_t *);
+
+static void megaraid_mbox_display_scb(adapter_t *, scb_t *);
+static void megaraid_mbox_setup_device_map(adapter_t *);
+
+static int megaraid_queue_command(struct scsi_cmnd *,
+               void (*)(struct scsi_cmnd *));
+static scb_t *megaraid_mbox_build_cmd(adapter_t *, struct scsi_cmnd *, int *);
+static void megaraid_mbox_runpendq(adapter_t *, scb_t *);
+static void megaraid_mbox_prepare_pthru(adapter_t *, scb_t *,
+               struct scsi_cmnd *);
+static void megaraid_mbox_prepare_epthru(adapter_t *, scb_t *,
+               struct scsi_cmnd *);
+
+static irqreturn_t megaraid_isr(int, void *, struct pt_regs *);
+
+static void megaraid_mbox_dpc(unsigned long);
+
+static int megaraid_cmm_register(adapter_t *);
+static int megaraid_cmm_unregister(adapter_t *);
+static int megaraid_mbox_mm_handler(unsigned long, uioc_t *, uint32_t);
+static int megaraid_mbox_mm_command(adapter_t *, uioc_t *);
+static void megaraid_mbox_mm_done(adapter_t *, scb_t *);
+static int gather_hbainfo(adapter_t *, mraid_hba_info_t *);
+static int wait_till_fw_empty(adapter_t *);
+
+
+
+MODULE_AUTHOR("LSI Logic Corporation");
+MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MEGARAID_VERSION);
+
+/*
+ * ### modules parameters for driver ###
+ */
+
+/**
+ * Set to enable driver to expose unconfigured disk to kernel
+ */
+static int megaraid_expose_unconf_disks = 0;
+module_param_named(unconf_disks, megaraid_expose_unconf_disks, int, 0);
+MODULE_PARM_DESC(unconf_disks,
+       "Set to expose unconfigured disks to kernel (default=0)");
+
+/**
+ * driver wait time if the adapter's mailbox is busy
+ */
+static unsigned int max_mbox_busy_wait = MBOX_BUSY_WAIT;
+module_param_named(busy_wait, max_mbox_busy_wait, int, 0);
+MODULE_PARM_DESC(busy_wait,
+       "Max wait for mailbox in microseconds if busy (default=10)");
+
+/**
+ * number of sectors per IO command
+ */
+static unsigned int megaraid_max_sectors = MBOX_MAX_SECTORS;
+module_param_named(max_sectors, megaraid_max_sectors, int, 0);
+MODULE_PARM_DESC(max_sectors,
+       "Maximum number of sectors per IO command (default=128)");
+
+/**
+ * number of commands per logical unit
+ */
+static unsigned int megaraid_cmd_per_lun = MBOX_DEF_CMD_PER_LUN;
+module_param_named(cmd_per_lun, megaraid_cmd_per_lun, int, 0);
+MODULE_PARM_DESC(cmd_per_lun,
+       "Maximum number of commands per logical unit (default=64)");
+
+
+/**
+ * Fast driver load option, skip scanning for physical devices during load.
+ * This would result in non-disk devices being skipped during driver load
+ * time. These can be later added though, using /proc/scsi/scsi
+ */
+static unsigned int megaraid_fast_load = 0;
+module_param_named(fast_load, megaraid_fast_load, int, 0);
+MODULE_PARM_DESC(fast_load,
+       "Faster loading of the driver, skips physical devices! (default=0)");
+
+
+/**
+ * mraid_debug level - threshold for amount of information to be displayed by
+ * the driver. This level can be changed through modules parameters, ioctl or
+ * sysfs/proc interface. By default, print the announcement messages only.
+ */
+int mraid_debug_level = CL_ANN;
+module_param_named(debug_level, mraid_debug_level, int, 0);
+MODULE_PARM_DESC(debug_level, "Debug level for driver (default=0)");
+
+/*
+ * ### global data ###
+ */
+static uint8_t megaraid_mbox_version[8] =
+       { 0x02, 0x20, 0x04, 0x00, 9, 27, 20, 4 };
+
+
+/*
+ * PCI table for all supported controllers.
+ */
+static struct pci_device_id pci_id_table_g[] =  {
+       {
+               PCI_VENDOR_ID_DELL,
+               PCI_DEVICE_ID_PERC4_DI_DISCOVERY,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4_DI_DISCOVERY,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_PERC4_SC,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4_SC,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_PERC4_DC,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4_DC,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_PERC4_QC,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4_QC,
+       },
+       {
+               PCI_VENDOR_ID_DELL,
+               PCI_DEVICE_ID_PERC4_DI_EVERGLADES,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4_DI_EVERGLADES,
+       },
+       {
+               PCI_VENDOR_ID_DELL,
+               PCI_DEVICE_ID_PERC4E_SI_BIGBEND,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4E_SI_BIGBEND,
+       },
+       {
+               PCI_VENDOR_ID_DELL,
+               PCI_DEVICE_ID_PERC4E_DI_KOBUK,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4E_DI_KOBUK,
+       },
+       {
+               PCI_VENDOR_ID_DELL,
+               PCI_DEVICE_ID_PERC4E_DI_CORVETTE,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4E_DI_CORVETTE,
+       },
+       {
+               PCI_VENDOR_ID_DELL,
+               PCI_DEVICE_ID_PERC4E_DI_EXPEDITION,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4E_DI_EXPEDITION,
+       },
+       {
+               PCI_VENDOR_ID_DELL,
+               PCI_DEVICE_ID_PERC4E_DI_GUADALUPE,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_PERC4E_DC_320_2E,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4E_DC_320_2E,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_PERC4E_SC_320_1E,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC4E_SC_320_1E,
+       },
+       {
+               PCI_VENDOR_ID_AMI,
+               PCI_DEVICE_ID_AMI_MEGARAID3,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC3_QC,
+       },
+       {
+               PCI_VENDOR_ID_AMI,
+               PCI_DEVICE_ID_AMI_MEGARAID3,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC3_DC,
+       },
+       {
+               PCI_VENDOR_ID_AMI,
+               PCI_DEVICE_ID_AMI_MEGARAID3,
+               PCI_VENDOR_ID_DELL,
+               PCI_SUBSYS_ID_PERC3_SC,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SCSI_320_0,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SCSI_320_0,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SCSI_320_1,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SCSI_320_1,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SCSI_320_2,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SCSI_320_2,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SCSI_320_0x,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SCSI_320_0x,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SCSI_320_2x,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SCSI_320_2x,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SCSI_320_4x,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SCSI_320_4x,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SCSI_320_1E,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SCSI_320_1E,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SCSI_320_2E,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SCSI_320_2E,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_I4_133_RAID,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_I4_133_RAID,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SATA_150_4,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SATA_150_4,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SATA_150_6,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SATA_150_6,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SATA_300_4x,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SATA_300_4x,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_SATA_300_8x,
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_SUBSYS_ID_MEGARAID_SATA_300_8x,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_INTEL_RAID_SRCU42X,
+               PCI_VENDOR_ID_INTEL,
+               PCI_SUBSYS_ID_INTEL_RAID_SRCU42X,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_INTEL_RAID_SRCS16,
+               PCI_VENDOR_ID_INTEL,
+               PCI_SUBSYS_ID_INTEL_RAID_SRCS16,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_INTEL_RAID_SRCU42E,
+               PCI_VENDOR_ID_INTEL,
+               PCI_SUBSYS_ID_INTEL_RAID_SRCU42E,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_INTEL_RAID_SRCZCRX,
+               PCI_VENDOR_ID_INTEL,
+               PCI_SUBSYS_ID_INTEL_RAID_SRCZCRX,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_INTEL_RAID_SRCS28X,
+               PCI_VENDOR_ID_INTEL,
+               PCI_SUBSYS_ID_INTEL_RAID_SRCS28X,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_ALIEF,
+               PCI_VENDOR_ID_INTEL,
+               PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_ALIEF,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_HARWICH,
+               PCI_VENDOR_ID_INTEL,
+               PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_HARWICH,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
+               PCI_VENDOR_ID_INTEL,
+               PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB,
+               PCI_SUBSYS_ID_FSC,
+               PCI_SUBSYS_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB,
+       },
+       {
+               PCI_VENDOR_ID_LSI_LOGIC,
+               PCI_DEVICE_ID_MEGARAID_ACER_ROMB_2E,
+               PCI_VENDOR_ID_AI,
+               PCI_SUBSYS_ID_MEGARAID_ACER_ROMB_2E,
+       },
+       {0}     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, pci_id_table_g);
+
+
+static struct pci_driver megaraid_pci_driver_g = {
+       .name           = "megaraid",
+       .id_table       = pci_id_table_g,
+       .probe          = megaraid_probe_one,
+       .remove         = __devexit_p(megaraid_detach_one),
+       .driver         = {
+               .shutdown       = megaraid_mbox_shutdown,
+       }
+};
+
+
+/*
+ * Scsi host template for megaraid unified driver
+ */
+static struct scsi_host_template megaraid_template_g = {
+       .module                         = THIS_MODULE,
+       .name                           = "LSI Logic MegaRAID driver",
+       .proc_name                      = "megaraid",
+       .queuecommand                   = megaraid_queue_command,
+       .eh_abort_handler               = megaraid_abort_handler,
+       .eh_device_reset_handler        = megaraid_reset_handler,
+       .eh_bus_reset_handler           = megaraid_reset_handler,
+       .eh_host_reset_handler          = megaraid_reset_handler,
+       .use_clustering                 = ENABLE_CLUSTERING,
+};
+
+
+/**
+ * megaraid_init - module load hook
+ *
+ * We register ourselves as hotplug enabled module and let PCI subsystem
+ * discover our adaters
+ **/
+static int __init
+megaraid_init(void)
+{
+       int     rval;
+
+       // Announce the driver version
+       con_log(CL_ANN, (KERN_INFO "megaraid: %s %s\n", MEGARAID_VERSION,
+               MEGARAID_EXT_VERSION));
+
+       // check validity of module parameters
+       if (megaraid_cmd_per_lun > MBOX_MAX_SCSI_CMDS) {
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid mailbox: max commands per lun reset to %d\n",
+                       MBOX_MAX_SCSI_CMDS));
+
+               megaraid_cmd_per_lun = MBOX_MAX_SCSI_CMDS;
+       }
+
+
+       // register as a PCI hot-plug driver module
+       if ((rval = pci_module_init(&megaraid_pci_driver_g))) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: could not register hotplug support.\n"));
+       }
+
+       return rval;
+}
+
+
+/**
+ * megaraid_exit - driver unload entry point
+ *
+ * We simply unwrap the megaraid_init routine here
+ */
+static void __exit
+megaraid_exit(void)
+{
+       con_log(CL_DLEVEL1, (KERN_NOTICE "megaraid: unloading framework\n"));
+
+       // unregister as PCI hotplug driver
+       pci_unregister_driver(&megaraid_pci_driver_g);
+
+       return;
+}
+
+
+/**
+ * megaraid_probe_one - PCI hotplug entry point
+ * @param pdev : handle to this controller's PCI configuration space
+ * @param id   : pci device id of the class of controllers
+ *
+ * This routine should be called whenever a new adapter is detected by the
+ * PCI hotplug susbsytem.
+ **/
+static int __devinit
+megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       adapter_t       *adapter;
+
+
+       // detected a new controller
+       con_log(CL_ANN, (KERN_INFO
+               "megaraid: probe new device %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",
+               pdev->vendor, pdev->device, pdev->subsystem_vendor,
+               pdev->subsystem_device));
+
+       con_log(CL_ANN, ("bus %d:slot %d:func %d\n", pdev->bus->number,
+               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)));
+
+       if (pci_enable_device(pdev)) {
+               con_log(CL_ANN, (KERN_WARNING
+                               "megaraid: pci_enable_device failed\n"));
+
+               return -ENODEV;
+       }
+
+       // Enable bus-mastering on this controller
+       pci_set_master(pdev);
+
+       // Allocate the per driver initialization structure
+       adapter = kmalloc(sizeof(adapter_t), GFP_KERNEL);
+
+       if (adapter == NULL) {
+               con_log(CL_ANN, (KERN_WARNING
+               "megaraid: out of memory, %s %d.\n", __FUNCTION__, __LINE__));
+
+               goto out_probe_one;
+       }
+       memset(adapter, 0, sizeof(adapter_t));
+
+
+       // set up PCI related soft state and other pre-known parameters
+       adapter->unique_id      = pdev->bus->number << 8 | pdev->devfn;
+       adapter->irq            = pdev->irq;
+       adapter->pdev           = pdev;
+
+       atomic_set(&adapter->being_detached, 0);
+
+       // Setup the default DMA mask. This would be changed later on
+       // depending on hardware capabilities
+       if (pci_set_dma_mask(adapter->pdev, 0xFFFFFFFF) != 0) {
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: pci_set_dma_mask failed:%d\n", __LINE__));
+
+               goto out_free_adapter;
+       }
+
+
+       // Initialize the synchronization lock for kernel and LLD
+       spin_lock_init(&adapter->lock);
+       adapter->host_lock = &adapter->lock;
+
+
+       // Initialize the command queues: the list of free SCBs and the list
+       // of pending SCBs.
+       INIT_LIST_HEAD(&adapter->kscb_pool);
+       spin_lock_init(SCSI_FREE_LIST_LOCK(adapter));
+
+       INIT_LIST_HEAD(&adapter->pend_list);
+       spin_lock_init(PENDING_LIST_LOCK(adapter));
+
+       INIT_LIST_HEAD(&adapter->completed_list);
+       spin_lock_init(COMPLETED_LIST_LOCK(adapter));
+
+
+       // Start the mailbox based controller
+       if (megaraid_init_mbox(adapter) != 0) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: maibox adapter did not initialize\n"));
+
+               goto out_free_adapter;
+       }
+
+       // Register with LSI Common Management Module
+       if (megaraid_cmm_register(adapter) != 0) {
+
+               con_log(CL_ANN, (KERN_WARNING
+               "megaraid: could not register with management module\n"));
+
+               goto out_fini_mbox;
+       }
+
+       // setup adapter handle in PCI soft state
+       pci_set_drvdata(pdev, adapter);
+
+       // attach with scsi mid-layer
+       if (megaraid_io_attach(adapter) != 0) {
+
+               con_log(CL_ANN, (KERN_WARNING "megaraid: io attach failed\n"));
+
+               goto out_cmm_unreg;
+       }
+
+       return 0;
+
+out_cmm_unreg:
+       pci_set_drvdata(pdev, NULL);
+       megaraid_cmm_unregister(adapter);
+out_fini_mbox:
+       megaraid_fini_mbox(adapter);
+out_free_adapter:
+       kfree(adapter);
+out_probe_one:
+       pci_disable_device(pdev);
+
+       return -ENODEV;
+}
+
+
+/**
+ * megaraid_detach_one - release the framework resources and call LLD release
+ * routine
+ * @param pdev : handle for our PCI cofiguration space
+ *
+ * This routine is called during driver unload. We free all the allocated
+ * resources and call the corresponding LLD so that it can also release all
+ * its resources.
+ *
+ * This routine is also called from the PCI hotplug system
+ **/
+static void
+megaraid_detach_one(struct pci_dev *pdev)
+{
+       adapter_t               *adapter;
+       struct Scsi_Host        *host;
+
+
+       // Start a rollback on this adapter
+       adapter = pci_get_drvdata(pdev);
+
+       if (!adapter) {
+               con_log(CL_ANN, (KERN_CRIT
+               "megaraid: Invalid detach on %#4.04x:%#4.04x:%#4.04x:%#4.04x\n",
+                       pdev->vendor, pdev->device, pdev->subsystem_vendor,
+                       pdev->subsystem_device));
+
+               return;
+       }
+       else {
+               con_log(CL_ANN, (KERN_NOTICE
+               "megaraid: detaching device %#4.04x:%#4.04x:%#4.04x:%#4.04x\n",
+                       pdev->vendor, pdev->device, pdev->subsystem_vendor,
+                       pdev->subsystem_device));
+       }
+
+
+       host = adapter->host;
+
+       // do not allow any more requests from the management module for this
+       // adapter.
+       // FIXME: How do we account for the request which might still be
+       // pending with us?
+       atomic_set(&adapter->being_detached, 1);
+
+       // detach from the IO sub-system
+       megaraid_io_detach(adapter);
+
+       // reset the device state in the PCI structure. We check this
+       // condition when we enter here. If the device state is NULL,
+       // that would mean the device has already been removed
+       pci_set_drvdata(pdev, NULL);
+
+       // Unregister from common management module
+       //
+       // FIXME: this must return success or failure for conditions if there
+       // is a command pending with LLD or not.
+       megaraid_cmm_unregister(adapter);
+
+       // finalize the mailbox based controller and release all resources
+       megaraid_fini_mbox(adapter);
+
+       kfree(adapter);
+
+       scsi_host_put(host);
+
+       pci_disable_device(pdev);
+
+       return;
+}
+
+
+/**
+ * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA
+ * @param device       : generice driver model device
+ *
+ * Shutdown notification, perform flush cache
+ */
+static void
+megaraid_mbox_shutdown(struct device *device)
+{
+       adapter_t               *adapter = pci_get_drvdata(to_pci_dev(device));
+       static int              counter;
+
+       if (!adapter) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: null device in shutdown\n"));
+               return;
+       }
+
+       // flush caches now
+       con_log(CL_ANN, (KERN_INFO "megaraid: flushing adapter %d...",
+               counter++));
+
+       megaraid_mbox_flush_cache(adapter);
+
+       con_log(CL_ANN, ("done\n"));
+}
+
+
+/**
+ * megaraid_io_attach - attach a device with the IO subsystem
+ * @param adapter      : controller's soft state
+ *
+ * Attach this device with the IO subsystem
+ **/
+static int
+megaraid_io_attach(adapter_t *adapter)
+{
+       struct Scsi_Host        *host;
+
+       // Initialize SCSI Host structure
+       host = scsi_host_alloc(&megaraid_template_g, 8);
+       if (!host) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid mbox: scsi_register failed\n"));
+
+               return -1;
+       }
+
+       SCSIHOST2ADAP(host)     = (caddr_t)adapter;
+       adapter->host           = host;
+
+       // export the parameters required by the mid-layer
+       scsi_assign_lock(host, adapter->host_lock);
+       scsi_set_device(host, &adapter->pdev->dev);
+
+       host->irq               = adapter->irq;
+       host->unique_id         = adapter->unique_id;
+       host->can_queue         = adapter->max_cmds;
+       host->this_id           = adapter->init_id;
+       host->sg_tablesize      = adapter->sglen;
+       host->max_sectors       = adapter->max_sectors;
+       host->cmd_per_lun       = adapter->cmd_per_lun;
+       host->max_channel       = adapter->max_channel;
+       host->max_id            = adapter->max_target;
+       host->max_lun           = adapter->max_lun;
+
+
+       // notify mid-layer about the new controller
+       if (scsi_add_host(host, &adapter->pdev->dev)) {
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid mbox: scsi_add_host failed\n"));
+
+               scsi_host_put(host);
+
+               return -1;
+       }
+
+       scsi_scan_host(host);
+
+       return 0;
+}
+
+
+/**
+ * megaraid_io_detach - detach a device from the IO subsystem
+ * @param adapter      : controller's soft state
+ *
+ * Detach this device from the IO subsystem
+ **/
+static void
+megaraid_io_detach(adapter_t *adapter)
+{
+       struct Scsi_Host        *host;
+
+       con_log(CL_DLEVEL1, (KERN_INFO "megaraid: io detach\n"));
+
+       host = adapter->host;
+
+       scsi_remove_host(host);
+
+       return;
+}
+
+
+/*
+ * START: Mailbox Low Level Driver
+ *
+ * This is section specific to the single mailbox based controllers
+ */
+
+/**
+ * megaraid_init_mbox - initialize controller
+ * @param adapter      - our soft state
+ *
+ * . Allocate 16-byte aligned mailbox memory for firmware handshake
+ * . Allocate controller's memory resources
+ * . Find out all initialization data
+ * . Allocate memory required for all the commands
+ * . Use internal library of FW routines, build up complete soft state
+ */
+static int __init
+megaraid_init_mbox(adapter_t *adapter)
+{
+       struct pci_dev          *pdev;
+       mraid_device_t          *raid_dev;
+       int                     i;
+
+
+       adapter->ito    = MBOX_TIMEOUT;
+       pdev            = adapter->pdev;
+
+       /*
+        * Allocate and initialize the init data structure for mailbox
+        * controllers
+        */
+       raid_dev = kmalloc(sizeof(mraid_device_t), GFP_KERNEL);
+       if (raid_dev == NULL) return -1;
+
+       memset(raid_dev, 0, sizeof(mraid_device_t));
+
+       /*
+        * Attach the adapter soft state to raid device soft state
+        */
+       adapter->raid_device    = (caddr_t)raid_dev;
+       raid_dev->fast_load     = megaraid_fast_load;
+
+
+       // our baseport
+       raid_dev->baseport = pci_resource_start(pdev, 0);
+
+       if (pci_request_regions(pdev, "MegaRAID: LSI Logic Corporation") != 0) {
+
+               con_log(CL_ANN, (KERN_WARNING
+                               "megaraid: mem region busy\n"));
+
+               goto out_free_raid_dev;
+       }
+
+       raid_dev->baseaddr = (unsigned long)
+                       ioremap_nocache(raid_dev->baseport, 128);
+
+       if (!raid_dev->baseaddr) {
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: could not map hba memory\n") );
+
+               goto out_release_regions;
+       }
+
+       //
+       // Setup the rest of the soft state using the library of FW routines
+       //
+
+       // request IRQ and register the interrupt service routine
+       if (request_irq(adapter->irq, megaraid_isr, SA_SHIRQ, "megaraid",
+               adapter)) {
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: Couldn't register IRQ %d!\n", adapter->irq));
+
+               goto out_iounmap;
+       }
+
+
+       // initialize the mutual exclusion lock for the mailbox
+       spin_lock_init(&raid_dev->mailbox_lock);
+
+       // allocate memory required for commands
+       if (megaraid_alloc_cmd_packets(adapter) != 0) {
+               goto out_free_irq;
+       }
+
+       // Product info
+       if (megaraid_mbox_product_info(adapter) != 0) {
+               goto out_alloc_cmds;
+       }
+
+       // Do we support extended CDBs
+       adapter->max_cdb_sz = 10;
+       if (megaraid_mbox_extended_cdb(adapter) == 0) {
+               adapter->max_cdb_sz = 16;
+       }
+
+       /*
+        * Do we support cluster environment, if we do, what is the initiator
+        * id.
+        * NOTE: In a non-cluster aware firmware environment, the LLD should
+        * return 7 as initiator id.
+        */
+       adapter->ha             = 0;
+       adapter->init_id        = -1;
+       if (megaraid_mbox_support_ha(adapter, &adapter->init_id) == 0) {
+               adapter->ha = 1;
+       }
+
+       /*
+        * Prepare the device ids array to have the mapping between the kernel
+        * device address and megaraid device address.
+        * We export the physical devices on their actual addresses. The
+        * logical drives are exported on a virtual SCSI channel
+        */
+       megaraid_mbox_setup_device_map(adapter);
+
+       // If the firmware supports random deletion, update the device id map
+       if (megaraid_mbox_support_random_del(adapter)) {
+
+               // Change the logical drives numbers in device_ids array one
+               // slot in device_ids is reserved for target id, that's why
+               // "<=" below
+               for (i = 0; i <= MAX_LOGICAL_DRIVES_40LD; i++) {
+                       adapter->device_ids[adapter->max_channel][i] += 0x80;
+               }
+               adapter->device_ids[adapter->max_channel][adapter->init_id] =
+                       0xFF;
+       }
+
+       /*
+        * find out the maximum number of scatter-gather elements supported by
+        * this firmware
+        */
+       adapter->sglen = megaraid_mbox_get_max_sg(adapter);
+
+       // enumerate RAID and SCSI channels so that all devices on SCSI
+       // channels can later be exported, including disk devices
+       megaraid_mbox_enum_raid_scsi(adapter);
+
+       /*
+        * Other parameters required by upper layer
+        *
+        * maximum number of sectors per IO command
+        */
+       adapter->max_sectors = megaraid_max_sectors;
+
+       /*
+        * number of queued commands per LUN.
+        */
+       adapter->cmd_per_lun = megaraid_cmd_per_lun;
+
+       // Set the DMA mask to 64-bit. All supported controllers as capable of
+       // DMA in this range
+       if (pci_set_dma_mask(adapter->pdev, 0xFFFFFFFFFFFFFFFFULL) != 0) {
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: could not set DMA mask for 64-bit.\n"));
+
+               goto out_alloc_cmds;
+       }
+
+       // setup tasklet for DPC
+       tasklet_init(&adapter->dpc_h, megaraid_mbox_dpc,
+                       (unsigned long)adapter);
+
+       con_log(CL_DLEVEL1, (KERN_INFO
+               "megaraid mbox hba successfully initialized\n"));
+
+       return 0;
+
+out_alloc_cmds:
+       megaraid_free_cmd_packets(adapter);
+out_free_irq:
+       free_irq(adapter->irq, adapter);
+out_iounmap:
+       iounmap((caddr_t)raid_dev->baseaddr);
+out_release_regions:
+       pci_release_regions(pdev);
+out_free_raid_dev:
+       kfree(raid_dev);
+
+       return -1;
+}
+
+
+/**
+ * megaraid_fini_mbox - undo controller initialization
+ * @param adapter      : our soft state
+ */
+static void
+megaraid_fini_mbox(adapter_t *adapter)
+{
+       mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
+
+       // flush all caches
+       megaraid_mbox_flush_cache(adapter);
+
+       tasklet_kill(&adapter->dpc_h);
+
+       megaraid_free_cmd_packets(adapter);
+
+       free_irq(adapter->irq, adapter);
+
+       iounmap((caddr_t)raid_dev->baseaddr);
+
+       pci_release_regions(adapter->pdev);
+
+       kfree(raid_dev);
+
+       return;
+}
+
+
+/**
+ * megaraid_alloc_cmd_packets - allocate shared mailbox
+ * @param adapter      : soft state of the raid controller
+ *
+ * Allocate and align the shared mailbox. This maibox is used to issue
+ * all the commands. For IO based controllers, the mailbox is also regsitered
+ * with the FW. Allocate memory for all commands as well.
+ * This is our big allocator
+ */
+static int
+megaraid_alloc_cmd_packets(adapter_t *adapter)
+{
+       mraid_device_t          *raid_dev = ADAP2RAIDDEV(adapter);
+       struct pci_dev          *pdev;
+       unsigned long           align;
+       scb_t                   *scb;
+       mbox_ccb_t              *ccb;
+       struct mraid_pci_blk    *epthru_pci_blk;
+       struct mraid_pci_blk    *sg_pci_blk;
+       struct mraid_pci_blk    *mbox_pci_blk;
+       int                     i;
+
+       pdev = adapter->pdev;
+
+       /*
+        * Setup the mailbox
+        * Allocate the common 16-byte aligned memory for the handshake
+        * mailbox.
+        */
+       raid_dev->una_mbox64 = pci_alloc_consistent(adapter->pdev,
+                       sizeof(mbox64_t), &raid_dev->una_mbox64_dma);
+
+       if (!raid_dev->una_mbox64) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       __LINE__));
+               return -1;
+       }
+       memset(raid_dev->una_mbox64, 0, sizeof(mbox64_t));
+
+       /*
+        * Align the mailbox at 16-byte boundary
+        */
+       raid_dev->mbox  = &raid_dev->una_mbox64->mbox32;
+
+       raid_dev->mbox  = (mbox_t *)((((unsigned long)raid_dev->mbox) + 15) &
+                               (~0UL ^ 0xFUL));
+
+       raid_dev->mbox64 = (mbox64_t *)(((unsigned long)raid_dev->mbox) - 8);
+
+       align = ((void *)raid_dev->mbox -
+                       ((void *)&raid_dev->una_mbox64->mbox32));
+
+       raid_dev->mbox_dma = (unsigned long)raid_dev->una_mbox64_dma + 8 +
+                       align;
+
+       // Allocate memory for commands issued internally
+       adapter->ibuf = pci_alloc_consistent(pdev, MBOX_IBUF_SIZE,
+                               &adapter->ibuf_dma_h);
+       if (!adapter->ibuf) {
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       __LINE__));
+
+               goto out_free_common_mbox;
+       }
+       memset(adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+       // Allocate memory for our SCSI Command Blocks and their associated
+       // memory
+
+       /*
+        * Allocate memory for the base list of scb. Later allocate memory for
+        * CCBs and embedded components of each CCB and point the pointers in
+        * scb to the allocated components
+        * NOTE: The code to allocate SCB will be duplicated in all the LLD
+        * since the calling routine does not yet know the number of available
+        * commands.
+        */
+       adapter->kscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_SCSI_CMDS,
+                       GFP_KERNEL);
+
+       if (adapter->kscb_list == NULL) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       __LINE__));
+               goto out_free_ibuf;
+       }
+       memset(adapter->kscb_list, 0, sizeof(scb_t) * MBOX_MAX_SCSI_CMDS);
+
+       // memory allocation for our command packets
+       if (megaraid_mbox_setup_dma_pools(adapter) != 0) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       __LINE__));
+               goto out_free_scb_list;
+       }
+
+       // Adjust the scb pointers and link in the free pool
+       epthru_pci_blk  = raid_dev->epthru_pool;
+       sg_pci_blk      = raid_dev->sg_pool;
+       mbox_pci_blk    = raid_dev->mbox_pool;
+
+       for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
+               scb                     = adapter->kscb_list + i;
+               ccb                     = raid_dev->ccb_list + i;
+
+               ccb->mbox       = (mbox_t *)(mbox_pci_blk[i].vaddr + 16);
+               ccb->raw_mbox   = (uint8_t *)ccb->mbox;
+               ccb->mbox64     = (mbox64_t *)(mbox_pci_blk[i].vaddr + 8);
+               ccb->mbox_dma_h = (unsigned long)mbox_pci_blk[i].dma_addr + 16;
+
+               // make sure the mailbox is aligned properly
+               if (ccb->mbox_dma_h & 0x0F) {
+                       con_log(CL_ANN, (KERN_CRIT
+                               "megaraid mbox: not aligned on 16-bytes\n"));
+
+                       goto out_teardown_dma_pools;
+               }
+
+               ccb->epthru             = (mraid_epassthru_t *)
+                                               epthru_pci_blk[i].vaddr;
+               ccb->epthru_dma_h       = epthru_pci_blk[i].dma_addr;
+               ccb->pthru              = (mraid_passthru_t *)ccb->epthru;
+               ccb->pthru_dma_h        = ccb->epthru_dma_h;
+
+
+               ccb->sgl64              = (mbox_sgl64 *)sg_pci_blk[i].vaddr;
+               ccb->sgl_dma_h          = sg_pci_blk[i].dma_addr;
+               ccb->sgl32              = (mbox_sgl32 *)ccb->sgl64;
+
+               scb->ccb                = (caddr_t)ccb;
+               scb->gp                 = 0;
+
+               scb->sno                = i;    // command index
+
+               scb->scp                = NULL;
+               scb->state              = SCB_FREE;
+               scb->dma_direction      = PCI_DMA_NONE;
+               scb->dma_type           = MRAID_DMA_NONE;
+               scb->dev_channel        = -1;
+               scb->dev_target         = -1;
+
+               // put scb in the free pool
+               list_add_tail(&scb->list, &adapter->kscb_pool);
+       }
+
+       return 0;
+
+out_teardown_dma_pools:
+       megaraid_mbox_teardown_dma_pools(adapter);
+out_free_scb_list:
+       kfree(adapter->kscb_list);
+out_free_ibuf:
+       pci_free_consistent(pdev, MBOX_IBUF_SIZE, (void *)adapter->ibuf,
+               adapter->ibuf_dma_h);
+out_free_common_mbox:
+       pci_free_consistent(adapter->pdev, sizeof(mbox64_t),
+               (caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma);
+
+       return -1;
+}
+
+
+/**
+ * megaraid_free_cmd_packets - free memory
+ * @param adapter      : soft state of the raid controller
+ *
+ * Release memory resources allocated for commands
+ */
+static void
+megaraid_free_cmd_packets(adapter_t *adapter)
+{
+       mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
+
+       megaraid_mbox_teardown_dma_pools(adapter);
+
+       kfree(adapter->kscb_list);
+
+       pci_free_consistent(adapter->pdev, MBOX_IBUF_SIZE,
+               (void *)adapter->ibuf, adapter->ibuf_dma_h);
+
+       pci_free_consistent(adapter->pdev, sizeof(mbox64_t),
+               (caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma);
+       return;
+}
+
+
+/**
+ * megaraid_mbox_setup_dma_pools - setup dma pool for command packets
+ * @param adapter      : HBA soft state
+ *
+ * setup the dma pools for mailbox, passthru and extended passthru structures,
+ * and scatter-gather lists
+ */
+static int
+megaraid_mbox_setup_dma_pools(adapter_t *adapter)
+{
+       mraid_device_t          *raid_dev = ADAP2RAIDDEV(adapter);
+       struct mraid_pci_blk    *epthru_pci_blk;
+       struct mraid_pci_blk    *sg_pci_blk;
+       struct mraid_pci_blk    *mbox_pci_blk;
+       int                     i;
+
+
+
+       // Allocate memory for 16-bytes aligned mailboxes
+       raid_dev->mbox_pool_handle = pci_pool_create("megaraid mbox pool",
+                                               adapter->pdev,
+                                               sizeof(mbox64_t) + 16,
+                                               16, 0);
+
+       if (raid_dev->mbox_pool_handle == NULL) {
+               goto fail_setup_dma_pool;
+       }
+
+       mbox_pci_blk = raid_dev->mbox_pool;
+       for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
+               mbox_pci_blk[i].vaddr = pci_pool_alloc(
+                                               raid_dev->mbox_pool_handle,
+                                               GFP_KERNEL,
+                                               &mbox_pci_blk[i].dma_addr);
+               if (!mbox_pci_blk[i].vaddr) {
+                       goto fail_setup_dma_pool;
+               }
+       }
+
+       /*
+        * Allocate memory for each embedded passthru strucuture pointer
+        * Request for a 128 bytes aligned structure for each passthru command
+        * structure
+        * Since passthru and extended passthru commands are exclusive, they
+        * share common memory pool. Passthru structures piggyback on memory
+        * allocted to extended passthru since passthru is smaller of the two
+        */
+       raid_dev->epthru_pool_handle = pci_pool_create("megaraid mbox pthru",
+                       adapter->pdev, sizeof(mraid_epassthru_t), 128, 0);
+
+       if (raid_dev->epthru_pool_handle == NULL) {
+               goto fail_setup_dma_pool;
+       }
+
+       epthru_pci_blk = raid_dev->epthru_pool;
+       for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
+               epthru_pci_blk[i].vaddr = pci_pool_alloc(
+                                               raid_dev->epthru_pool_handle,
+                                               GFP_KERNEL,
+                                               &epthru_pci_blk[i].dma_addr);
+               if (!epthru_pci_blk[i].vaddr) {
+                       goto fail_setup_dma_pool;
+               }
+       }
+
+
+       // Allocate memory for each scatter-gather list. Request for 512 bytes
+       // alignment for each sg list
+       raid_dev->sg_pool_handle = pci_pool_create("megaraid mbox sg",
+                                       adapter->pdev,
+                                       sizeof(mbox_sgl64) * MBOX_MAX_SG_SIZE,
+                                       512, 0);
+
+       if (raid_dev->sg_pool_handle == NULL) {
+               goto fail_setup_dma_pool;
+       }
+
+       sg_pci_blk = raid_dev->sg_pool;
+       for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
+               sg_pci_blk[i].vaddr = pci_pool_alloc(
+                                               raid_dev->sg_pool_handle,
+                                               GFP_KERNEL,
+                                               &sg_pci_blk[i].dma_addr);
+               if (!sg_pci_blk[i].vaddr) {
+                       goto fail_setup_dma_pool;
+               }
+       }
+
+       return 0;
+
+fail_setup_dma_pool:
+       megaraid_mbox_teardown_dma_pools(adapter);
+       return -1;
+}
+
+
+/**
+ * megaraid_mbox_teardown_dma_pools - teardown dma pools for command packets
+ * @param adapter      : HBA soft state
+ *
+ * teardown the dma pool for mailbox, passthru and extended passthru
+ * structures, and scatter-gather lists
+ */
+static void
+megaraid_mbox_teardown_dma_pools(adapter_t *adapter)
+{
+       mraid_device_t          *raid_dev = ADAP2RAIDDEV(adapter);
+       struct mraid_pci_blk    *epthru_pci_blk;
+       struct mraid_pci_blk    *sg_pci_blk;
+       struct mraid_pci_blk    *mbox_pci_blk;
+       int                     i;
+
+
+       sg_pci_blk = raid_dev->sg_pool;
+       for (i = 0; i < MBOX_MAX_SCSI_CMDS && sg_pci_blk[i].vaddr; i++) {
+               pci_pool_free(raid_dev->sg_pool_handle, sg_pci_blk[i].vaddr,
+                       sg_pci_blk[i].dma_addr);
+       }
+       if (raid_dev->sg_pool_handle)
+               pci_pool_destroy(raid_dev->sg_pool_handle);
+
+
+       epthru_pci_blk = raid_dev->epthru_pool;
+       for (i = 0; i < MBOX_MAX_SCSI_CMDS && epthru_pci_blk[i].vaddr; i++) {
+               pci_pool_free(raid_dev->epthru_pool_handle,
+                       epthru_pci_blk[i].vaddr, epthru_pci_blk[i].dma_addr);
+       }
+       if (raid_dev->epthru_pool_handle)
+               pci_pool_destroy(raid_dev->epthru_pool_handle);
+
+
+       mbox_pci_blk = raid_dev->mbox_pool;
+       for (i = 0; i < MBOX_MAX_SCSI_CMDS && mbox_pci_blk[i].vaddr; i++) {
+               pci_pool_free(raid_dev->mbox_pool_handle,
+                       mbox_pci_blk[i].vaddr, mbox_pci_blk[i].dma_addr);
+       }
+       if (raid_dev->mbox_pool_handle)
+               pci_pool_destroy(raid_dev->mbox_pool_handle);
+
+       return;
+}
+
+
+/**
+ * megaraid_alloc_scb - detach and return a scb from the free list
+ * @adapter    : controller's soft state
+ *
+ * return the scb from the head of the free list. NULL if there are none
+ * available
+ **/
+static inline scb_t *
+megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp)
+{
+       struct list_head        *head = &adapter->kscb_pool;
+       scb_t                   *scb = NULL;
+       unsigned long           flags;
+
+       // detach scb from free pool
+       spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags);
+
+       if (list_empty(head)) {
+               spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
+               return NULL;
+       }
+
+       scb = list_entry(head->next, scb_t, list);
+       list_del_init(&scb->list);
+
+       spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
+
+       scb->state      = SCB_ACTIVE;
+       scb->scp        = scp;
+       scb->dma_type   = MRAID_DMA_NONE;
+
+       return scb;
+}
+
+
+/**
+ * megaraid_dealloc_scb - return the scb to the free pool
+ * @adapter    : controller's soft state
+ * @scb                : scb to be freed
+ *
+ * return the scb back to the free list of scbs. The caller must 'flush' the
+ * SCB before calling us. E.g., performing pci_unamp and/or pci_sync etc.
+ * NOTE NOTE: Make sure the scb is not on any list before calling this
+ * routine.
+ **/
+static inline void
+megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb)
+{
+       unsigned long           flags;
+
+       // put scb in the free pool
+       scb->state      = SCB_FREE;
+       scb->scp        = NULL;
+       spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags);
+
+       list_add(&scb->list, &adapter->kscb_pool);
+
+       spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
+
+       return;
+}
+
+
+/**
+ * megaraid_mbox_mksgl - make the scatter-gather list
+ * @adapter    - controller's soft state
+ * @scb                - scsi control block
+ *
+ * prepare the scatter-gather list
+ */
+static inline int
+megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
+{
+       struct scatterlist      *sgl;
+       mbox_ccb_t              *ccb;
+       struct page             *page;
+       unsigned long           offset;
+       struct scsi_cmnd        *scp;
+       int                     sgcnt;
+       int                     i;
+
+
+       scp     = scb->scp;
+       ccb     = (mbox_ccb_t *)scb->ccb;
+
+       // no mapping required if no data to be transferred
+       if (!scp->request_buffer || !scp->request_bufflen)
+               return 0;
+
+       if (!scp->use_sg) {     /* scatter-gather list not used */
+
+               page = virt_to_page(scp->request_buffer);
+
+               offset = ((unsigned long)scp->request_buffer & ~PAGE_MASK);
+
+               ccb->buf_dma_h = pci_map_page(adapter->pdev, page, offset,
+                                                 scp->request_bufflen,
+                                                 scb->dma_direction);
+               scb->dma_type = MRAID_DMA_WBUF;
+
+               /*
+                * We need to handle special 64-bit commands that need a
+                * minimum of 1 SG
+                */
+               sgcnt = 1;
+               ccb->sgl64[0].address   = ccb->buf_dma_h;
+               ccb->sgl64[0].length    = scp->request_bufflen;
+
+               return sgcnt;
+       }
+
+       sgl = (struct scatterlist *)scp->request_buffer;
+
+       // The number of sg elements returned must not exceed our limit
+       sgcnt = pci_map_sg(adapter->pdev, sgl, scp->use_sg,
+                       scb->dma_direction);
+
+       if (sgcnt > adapter->sglen) {
+               con_log(CL_ANN, (KERN_CRIT
+                       "megaraid critical: too many sg elements:%d\n",
+                       sgcnt));
+               BUG();
+       }
+
+       scb->dma_type = MRAID_DMA_WSG;
+
+       for (i = 0; i < sgcnt; i++, sgl++) {
+               ccb->sgl64[i].address   = sg_dma_address(sgl);
+               ccb->sgl64[i].length    = sg_dma_len(sgl);
+       }
+
+       // Return count of SG nodes
+       return sgcnt;
+}
+
+
+/**
+ * mbox_post_cmd - issue a mailbox command
+ * @adapter    - controller's soft state
+ * @scb                - command to be issued
+ *
+ * post the command to the controller if mailbox is availble.
+ */
+static inline int
+mbox_post_cmd(adapter_t *adapter, scb_t *scb)
+{
+       mraid_device_t  *raid_dev = ADAP2RAIDDEV(adapter);
+       mbox64_t        *mbox64;
+       mbox_t          *mbox;
+       mbox_ccb_t      *ccb;
+       unsigned long   flags;
+       unsigned int    i = 0;
+
+
+       ccb     = (mbox_ccb_t *)scb->ccb;
+       mbox    = raid_dev->mbox;
+       mbox64  = raid_dev->mbox64;
+
+       /*
+        * Check for busy mailbox. If it is, return failure - the caller
+        * should retry later.
+        */
+       spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags);
+
+       if (unlikely(mbox->busy)) {
+               do {
+                       udelay(1);
+                       i++;
+                       rmb();
+               } while(mbox->busy && (i < max_mbox_busy_wait));
+
+               if (mbox->busy) {
+
+                       spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
+
+                       return -1;
+               }
+       }
+
+
+       // Copy this command's mailbox data into "adapter's" mailbox
+       memcpy((caddr_t)mbox64, (caddr_t)ccb->mbox64, 22);
+       mbox->cmdid = scb->sno;
+
+       adapter->outstanding_cmds++;
+
+       if (scb->dma_direction == PCI_DMA_TODEVICE) {
+               if (!scb->scp->use_sg) {        // sg list not used
+                       pci_dma_sync_single(adapter->pdev, ccb->buf_dma_h,
+                                       scb->scp->request_bufflen,
+                                       PCI_DMA_TODEVICE);
+               }
+               else {
+                       pci_dma_sync_sg(adapter->pdev, scb->scp->request_buffer,
+                               scb->scp->use_sg, PCI_DMA_TODEVICE);
+               }
+       }
+
+       mbox->busy      = 1;    // Set busy
+       mbox->poll      = 0;
+       mbox->ack       = 0;
+       wmb();
+
+       WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
+
+       spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
+
+       return 0;
+}
+
+
+/**
+ * megaraid_queue_command - generic queue entry point for all LLDs
+ * @scp                : pointer to the scsi command to be executed
+ * @done       : callback routine to be called after the cmd has be completed
+ *
+ * Queue entry point for mailbox based controllers.
+ */
+static int
+megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *))
+{
+       adapter_t       *adapter;
+       scb_t           *scb;
+       int             if_busy;
+
+       adapter         = SCP2ADAPTER(scp);
+       scp->scsi_done  = done;
+       scp->result     = 0;
+
+       ASSERT(spin_is_locked(adapter->host_lock));
+
+       spin_unlock(adapter->host_lock);
+
+       /*
+        * Allocate and build a SCB request
+        * if_busy flag will be set if megaraid_mbox_build_cmd() command could
+        * not allocate scb. We will return non-zero status in that case.
+        * NOTE: scb can be null even though certain commands completed
+        * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, it would
+        * return 0 in that case, and we would do the callback right away.
+        */
+       if_busy = 0;
+       scb     = megaraid_mbox_build_cmd(adapter, scp, &if_busy);
+
+       if (scb) {
+               megaraid_mbox_runpendq(adapter, scb);
+       }
+
+       spin_lock(adapter->host_lock);
+
+       if (!scb) {     // command already completed
+               done(scp);
+       }
+
+       return if_busy;
+}
+
+
+/**
+ * megaraid_mbox_build_cmd - transform the mid-layer scsi command to megaraid
+ * firmware lingua
+ * @adapter    - controller's soft state
+ * @scp                - mid-layer scsi command pointer
+ * @busy       - set if request could not be completed because of lack of
+ *             resources
+ *
+ * convert the command issued by mid-layer to format understood by megaraid
+ * firmware. We also complete certain command without sending them to firmware
+ */
+static scb_t *
+megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
+{
+       mraid_device_t          *rdev = ADAP2RAIDDEV(adapter);
+       int                     channel;
+       int                     target;
+       int                     islogical;
+       mbox_ccb_t              *ccb;
+       mraid_passthru_t        *pthru;
+       mbox64_t                *mbox64;
+       mbox_t                  *mbox;
+       scb_t                   *scb;
+       char                    skip[] = "skipping";
+       char                    scan[] = "scanning";
+       char                    *ss;
+
+
+       /*
+        * Get the appropriate device map for the device this command is
+        * intended for
+        */
+       MRAID_GET_DEVICE_MAP(adapter, scp, channel, target, islogical);
+
+       /*
+        * Logical drive commands
+        */
+       if (islogical) {
+               switch (scp->cmnd[0]) {
+               case TEST_UNIT_READY:
+                       /*
+                        * Do we support clustering and is the support enabled
+                        * If no, return success always
+                        */
+                       if (!adapter->ha) {
+                               scp->result = (DID_OK << 16);
+                               return NULL;
+                       }
+
+                       if (!(scb = megaraid_alloc_scb(adapter, scp))) {
+                               scp->result = (DID_ERROR << 16);
+                               *busy = 1;
+                               return NULL;
+                       }
+
+                       scb->dma_direction      = scp->sc_data_direction;
+                       scb->dev_channel        = 0xFF;
+                       scb->dev_target         = target;
+                       ccb                     = (mbox_ccb_t *)scb->ccb;
+
+                       /*
+                        * The command id will be provided by the command
+                        * issuance routine
+                        */
+                       ccb->raw_mbox[0]        = CLUSTER_CMD;
+                       ccb->raw_mbox[2]        = RESERVATION_STATUS;
+                       ccb->raw_mbox[3]        = target;
+
+                       return scb;
+
+               case MODE_SENSE:
+                       if (scp->use_sg) {
+                               struct scatterlist      *sgl;
+                               caddr_t                 vaddr;
+
+                               sgl = (struct scatterlist *)scp->request_buffer;
+                               if (sgl->page) {
+                                       vaddr = (caddr_t)
+                                               (page_address((&sgl[0])->page)
+                                               + (&sgl[0])->offset);
+
+                                       memset(vaddr, 0, scp->cmnd[4]);
+                               }
+                               else {
+                                       con_log(CL_ANN, (KERN_WARNING
+                                       "megaraid mailbox: invalid sg:%d\n",
+                                       __LINE__));
+                               }
+                       }
+                       else {
+                               memset(scp->request_buffer, 0, scp->cmnd[4]);
+                       }
+                       scp->result = (DID_OK << 16);
+                       return NULL;
+
+               case INQUIRY:
+                       /*
+                        * Display the channel scan for logical drives
+                        * Do not display scan for a channel if already done.
+                        */
+                       if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {
+
+                               con_log(CL_ANN, (KERN_INFO
+                                       "scsi[%d]: scanning scsi channel %d",
+                                       adapter->host->host_no,
+                                       SCP2CHANNEL(scp)));
+
+                               con_log(CL_ANN, (
+                                       " [virtual] for logical drives\n"));
+
+                               rdev->last_disp |= (1L << SCP2CHANNEL(scp));
+                       }
+
+                       /* Fall through */
+
+               case READ_CAPACITY:
+                       /*
+                        * Do not allow LUN > 0 for logical drives and
+                        * requests for more than 40 logical drives
+                        */
+                       if (SCP2LUN(scp)) {
+                               scp->result = (DID_BAD_TARGET << 16);
+                               return NULL;
+                       }
+                       if ((target % 0x80) >= MAX_LOGICAL_DRIVES_40LD) {
+                               scp->result = (DID_BAD_TARGET << 16);
+                               return NULL;
+                       }
+
+
+                       /* Allocate a SCB and initialize passthru */
+                       if (!(scb = megaraid_alloc_scb(adapter, scp))) {
+                               scp->result = (DID_ERROR << 16);
+                               *busy = 1;
+                               return NULL;
+                       }
+
+                       ccb                     = (mbox_ccb_t *)scb->ccb;
+                       scb->dev_channel        = 0xFF;
+                       scb->dev_target         = target;
+                       pthru                   = ccb->pthru;
+                       mbox                    = ccb->mbox;
+                       mbox64                  = ccb->mbox64;
+
+                       pthru->timeout          = 0;
+                       pthru->ars              = 1;
+                       pthru->reqsenselen      = 14;
+                       pthru->islogical        = 1;
+                       pthru->logdrv           = target;
+                       pthru->cdblen           = scp->cmd_len;
+                       memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
+
+                       mbox->cmd               = MBOXCMD_PASSTHRU64;
+                       scb->dma_direction      = scp->sc_data_direction;
+
+                       pthru->dataxferlen      = scp->request_bufflen;
+                       pthru->dataxferaddr     = ccb->sgl_dma_h;
+                       pthru->numsge           = megaraid_mbox_mksgl(adapter,
+                                                       scb);
+
+                       mbox->xferaddr          = 0xFFFFFFFF;
+                       mbox64->xferaddr_lo     = (uint32_t )ccb->pthru_dma_h;
+                       mbox64->xferaddr_hi     = 0;
+
+                       return scb;
+
+               case READ_6:
+               case WRITE_6:
+               case READ_10:
+               case WRITE_10:
+               case READ_12:
+               case WRITE_12:
+
+                       /*
+                        * Allocate a SCB and initialize mailbox
+                        */
+                       if (!(scb = megaraid_alloc_scb(adapter, scp))) {
+                               scp->result = (DID_ERROR << 16);
+                               *busy = 1;
+                               return NULL;
+                       }
+                       ccb                     = (mbox_ccb_t *)scb->ccb;
+                       scb->dev_channel        = 0xFF;
+                       scb->dev_target         = target;
+                       mbox                    = ccb->mbox;
+                       mbox64                  = ccb->mbox64;
+                       mbox->logdrv            = target;
+
+                       /*
+                        * A little HACK: 2nd bit is zero for all scsi read
+                        * commands and is set for all scsi write commands
+                        */
+                       mbox->cmd = (scp->cmnd[0] & 0x02) ?  MBOXCMD_LWRITE64:
+                                       MBOXCMD_LREAD64 ;
+
+                       /*
+                        * 6-byte READ(0x08) or WRITE(0x0A) cdb
+                        */
+                       if (scp->cmd_len == 6) {
+                               mbox->numsectors = (uint32_t)scp->cmnd[4];
+                               mbox->lba =
+                                       ((uint32_t)scp->cmnd[1] << 16)  |
+                                       ((uint32_t)scp->cmnd[2] << 8)   |
+                                       (uint32_t)scp->cmnd[3];
+
+                               mbox->lba &= 0x1FFFFF;
+                       }
+
+                       /*
+                        * 10-byte READ(0x28) or WRITE(0x2A) cdb
+                        */
+                       else if (scp->cmd_len == 10) {
+                               mbox->numsectors =
+                                       (uint32_t)scp->cmnd[8] |
+                                       ((uint32_t)scp->cmnd[7] << 8);
+                               mbox->lba =
+                                       ((uint32_t)scp->cmnd[2] << 24) |
+                                       ((uint32_t)scp->cmnd[3] << 16) |
+                                       ((uint32_t)scp->cmnd[4] << 8) |
+                                       (uint32_t)scp->cmnd[5];
+                       }
+
+                       /*
+                        * 12-byte READ(0xA8) or WRITE(0xAA) cdb
+                        */
+                       else if (scp->cmd_len == 12) {
+                               mbox->lba =
+                                       ((uint32_t)scp->cmnd[2] << 24) |
+                                       ((uint32_t)scp->cmnd[3] << 16) |
+                                       ((uint32_t)scp->cmnd[4] << 8) |
+                                       (uint32_t)scp->cmnd[5];
+
+                               mbox->numsectors =
+                                       ((uint32_t)scp->cmnd[6] << 24) |
+                                       ((uint32_t)scp->cmnd[7] << 16) |
+                                       ((uint32_t)scp->cmnd[8] << 8) |
+                                       (uint32_t)scp->cmnd[9];
+                       }
+                       else {
+                               con_log(CL_ANN, (KERN_WARNING
+                                       "megaraid: unsupported CDB length\n"));
+
+                               megaraid_dealloc_scb(adapter, scb);
+
+                               scp->result = (DID_ERROR << 16);
+                               return NULL;
+                       }
+
+                       scb->dma_direction = scp->sc_data_direction;
+
+                       // Calculate Scatter-Gather info
+                       mbox64->xferaddr_lo     = (uint32_t )ccb->sgl_dma_h;
+                       mbox->numsge            = megaraid_mbox_mksgl(adapter,
+                                                       scb);
+                       mbox->xferaddr          = 0xFFFFFFFF;
+                       mbox64->xferaddr_hi     = 0;
+
+                       return scb;
+
+               case RESERVE:
+               case RELEASE:
+                       /*
+                        * Do we support clustering and is the support enabled
+                        */
+                       if (!adapter->ha) {
+                               scp->result = (DID_BAD_TARGET << 16);
+                               return NULL;
+                       }
+
+                       /*
+                        * Allocate a SCB and initialize mailbox
+                        */
+                       if (!(scb = megaraid_alloc_scb(adapter, scp))) {
+                               scp->result = (DID_ERROR << 16);
+                               *busy = 1;
+                               return NULL;
+                       }
+
+                       ccb                     = (mbox_ccb_t *)scb->ccb;
+                       scb->dev_channel        = 0xFF;
+                       scb->dev_target         = target;
+                       ccb->raw_mbox[0]        = CLUSTER_CMD;
+                       ccb->raw_mbox[2]        =  (scp->cmnd[0] == RESERVE) ?
+                                               RESERVE_LD : RELEASE_LD;
+
+                       ccb->raw_mbox[3]        = target;
+                       scb->dma_direction      = scp->sc_data_direction;
+
+                       return scb;
+
+               default:
+                       scp->result = (DID_BAD_TARGET << 16);
+                       return NULL;
+               }
+       }
+       else { // Passthru device commands
+
+               // Do not allow access to target id > 15 or LUN > 7
+               if (target > 15 || SCP2LUN(scp) > 7) {
+                       scp->result = (DID_BAD_TARGET << 16);
+                       return NULL;
+               }
+
+               // if fast load option was set and scan for last device is
+               // over, reset the fast_load flag so that during a possible
+               // next scan, devices can be made available
+               if (rdev->fast_load && (target == 15) &&
+                       (SCP2CHANNEL(scp) == adapter->max_channel -1)) {
+
+                       con_log(CL_ANN, (KERN_INFO
+                       "megaraid[%d]: physical device scan re-enabled\n",
+                               adapter->host->host_no));
+                       rdev->fast_load = 0;
+               }
+
+               /*
+                * Display the channel scan for physical devices
+                */
+               if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {
+
+                       ss = rdev->fast_load ? skip : scan;
+
+                       con_log(CL_ANN, (KERN_INFO
+                               "scsi[%d]: %s scsi channel %d [Phy %d]",
+                               adapter->host->host_no, ss, SCP2CHANNEL(scp),
+                               channel));
+
+                       con_log(CL_ANN, (
+                               " for non-raid devices\n"));
+
+                       rdev->last_disp |= (1L << SCP2CHANNEL(scp));
+               }
+
+               // disable channel sweep if fast load option given
+               if (rdev->fast_load) {
+                       scp->result = (DID_BAD_TARGET << 16);
+                       return NULL;
+               }
+
+               // Allocate a SCB and initialize passthru
+               if (!(scb = megaraid_alloc_scb(adapter, scp))) {
+                       scp->result = (DID_ERROR << 16);
+                       *busy = 1;
+                       return NULL;
+               }
+
+               ccb                     = (mbox_ccb_t *)scb->ccb;
+               scb->dev_channel        = channel;
+               scb->dev_target         = target;
+               scb->dma_direction      = scp->sc_data_direction;
+               mbox                    = ccb->mbox;
+               mbox64                  = ccb->mbox64;
+
+               // Does this firmware support extended CDBs
+               if (adapter->max_cdb_sz == 16) {
+                       mbox->cmd               = MBOXCMD_EXTPTHRU;
+
+                       megaraid_mbox_prepare_epthru(adapter, scb, scp);
+
+                       mbox64->xferaddr_lo     = (uint32_t)ccb->epthru_dma_h;
+                       mbox64->xferaddr_hi     = 0;
+                       mbox->xferaddr          = 0xFFFFFFFF;
+               }
+               else {
+                       mbox->cmd = MBOXCMD_PASSTHRU64;
+
+                       megaraid_mbox_prepare_pthru(adapter, scb, scp);
+
+                       mbox64->xferaddr_lo     = (uint32_t)ccb->pthru_dma_h;
+                       mbox64->xferaddr_hi     = 0;
+                       mbox->xferaddr          = 0xFFFFFFFF;
+               }
+               return scb;
+       }
+
+       // NOT REACHED
+}
+
+
+/**
+ * megaraid_mbox_runpendq - execute commands queued in the pending queue
+ * @adapter    : controller's soft state
+ * @scb                : SCB to be queued in the pending list
+ *
+ * scan the pending list for commands which are not yet issued and try to
+ * post to the controller. The SCB can be a null pointer, which would indicate
+ * no SCB to be queue, just try to execute the ones in the pending list.
+ *
+ * NOTE: We do not actually traverse the pending list. The SCBs are plucked
+ * out from the head of the pending list. If it is successfully issued, the
+ * next SCB is at the head now.
+ */
+static void
+megaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q)
+{
+       scb_t                   *scb;
+       unsigned long           flags;
+
+       spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
+
+       if (scb_q) {
+               scb_q->state = SCB_PENDQ;
+               list_add_tail(&scb_q->list, &adapter->pend_list);
+       }
+
+       // if the adapter in not in quiescent mode, post the commands to FW
+       if (adapter->quiescent) {
+               spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
+               return;
+       }
+
+       while (!list_empty(&adapter->pend_list)) {
+
+               ASSERT(spin_is_locked(PENDING_LIST_LOCK(adapter)));
+
+               scb = list_entry(adapter->pend_list.next, scb_t, list);
+
+               // remove the scb from the pending list and try to
+               // issue. If we are unable to issue it, put back in
+               // the pending list and return
+
+               list_del_init(&scb->list);
+
+               spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
+
+               // if mailbox was busy, return SCB back to pending
+               // list. Make sure to add at the head, since that's
+               // where it would have been removed from
+
+               scb->state = SCB_ISSUED;
+
+               if (mbox_post_cmd(adapter, scb) != 0) {
+
+                       spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
+
+                       scb->state = SCB_PENDQ;
+
+                       list_add(&scb->list, &adapter->pend_list);
+
+                       spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter),
+                               flags);
+
+                       return;
+               }
+
+               spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
+       }
+
+       spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
+
+
+       return;
+}
+
+
+/**
+ * megaraid_mbox_prepare_pthru - prepare a command for physical devices
+ * @adapter    - pointer to controller's soft state
+ * @scb                - scsi control block
+ * @scp                - scsi command from the mid-layer
+ *
+ * prepare a command for the scsi physical devices
+ */
+static void
+megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb,
+               struct scsi_cmnd *scp)
+{
+       mbox_ccb_t              *ccb;
+       mraid_passthru_t        *pthru;
+       uint8_t                 channel;
+       uint8_t                 target;
+
+       ccb     = (mbox_ccb_t *)scb->ccb;
+       pthru   = ccb->pthru;
+       channel = scb->dev_channel;
+       target  = scb->dev_target;
+
+       pthru->timeout          = 1;    // 0=6sec, 1=60sec, 2=10min, 3=3hrs
+       pthru->ars              = 1;
+       pthru->islogical        = 0;
+       pthru->channel          = 0;
+       pthru->target           = (channel << 4) | target;
+       pthru->logdrv           = SCP2LUN(scp);
+       pthru->reqsenselen      = 14;
+       pthru->cdblen           = scp->cmd_len;
+
+       memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
+
+       if (scp->request_bufflen) {
+               pthru->dataxferlen      = scp->request_bufflen;
+               pthru->dataxferaddr     = ccb->sgl_dma_h;
+               pthru->numsge           = megaraid_mbox_mksgl(adapter, scb);
+       }
+       else {
+               pthru->dataxferaddr     = 0;
+               pthru->dataxferlen      = 0;
+               pthru->numsge           = 0;
+       }
+       return;
+}
+
+
+/**
+ * megaraid_mbox_prepare_epthru - prepare a command for physical devices
+ * @adapter    - pointer to controller's soft state
+ * @scb                - scsi control block
+ * @scp                - scsi command from the mid-layer
+ *
+ * prepare a command for the scsi physical devices. This rountine prepares
+ * commands for devices which can take extended CDBs (>10 bytes)
+ */
+static void
+megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb,
+               struct scsi_cmnd *scp)
+{
+       mbox_ccb_t              *ccb;
+       mraid_epassthru_t       *epthru;
+       uint8_t                 channel;
+       uint8_t                 target;
+
+       ccb     = (mbox_ccb_t *)scb->ccb;
+       epthru  = ccb->epthru;
+       channel = scb->dev_channel;
+       target  = scb->dev_target;
+
+       epthru->timeout         = 1;    // 0=6sec, 1=60sec, 2=10min, 3=3hrs
+       epthru->ars             = 1;
+       epthru->islogical       = 0;
+       epthru->channel         = 0;
+       epthru->target          = (channel << 4) | target;
+       epthru->logdrv          = SCP2LUN(scp);
+       epthru->reqsenselen     = 14;
+       epthru->cdblen          = scp->cmd_len;
+
+       memcpy(epthru->cdb, scp->cmnd, scp->cmd_len);
+
+       if (scp->request_bufflen) {
+               epthru->dataxferlen     = scp->request_bufflen;
+               epthru->dataxferaddr    = ccb->sgl_dma_h;
+               epthru->numsge          = megaraid_mbox_mksgl(adapter, scb);
+       }
+       else {
+               epthru->dataxferaddr    = 0;
+               epthru->dataxferlen     = 0;
+               epthru->numsge          = 0;
+       }
+       return;
+}
+
+
+/**
+ * megaraid_ack_sequence - interrupt ack sequence for memory mapped HBAs
+ * @adapter    - controller's soft state
+ *
+ * Interrupt ackrowledgement sequence for memory mapped HBAs. Find out the
+ * completed command and put them on the completed list for later processing.
+ *
+ * Returns:    1 if the interrupt is valid, 0 otherwise
+ */
+static inline int
+megaraid_ack_sequence(adapter_t *adapter)
+{
+       mraid_device_t          *raid_dev = ADAP2RAIDDEV(adapter);
+       mbox_t                  *mbox;
+       scb_t                   *scb;
+       uint8_t                 nstatus;
+       uint8_t                 completed[MBOX_MAX_FIRMWARE_STATUS];
+       struct list_head        clist;
+       int                     handled;
+       uint32_t                dword;
+       unsigned long           flags;
+       int                     i, j;
+
+
+       mbox    = raid_dev->mbox;
+
+       // move the SCBs from the firmware completed array to our local list
+       INIT_LIST_HEAD(&clist);
+
+       // loop till F/W has more commands for us to complete
+       handled = 0;
+       spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags);
+       do {
+               /*
+                * Check if a valid interrupt is pending. If found, force the
+                * interrupt line low.
+                */
+               dword = RDOUTDOOR(raid_dev);
+               if (dword != 0x10001234) break;
+
+               handled = 1;
+
+               WROUTDOOR(raid_dev, 0x10001234);
+
+               nstatus = 0;
+               // wait for valid numstatus to post
+               for (i = 0; i < 0xFFFFF; i++) {
+                       if (mbox->numstatus != 0xFF) {
+                               nstatus = mbox->numstatus;
+                               break;
+                       }
+                       rmb();
+               }
+               mbox->numstatus = 0xFF;
+
+               adapter->outstanding_cmds -= nstatus;
+
+               for (i = 0; i < nstatus; i++) {
+
+                       // wait for valid command index to post
+                       for (j = 0; j < 0xFFFFF; j++) {
+                               if (mbox->completed[i] != 0xFF) break;
+                               rmb();
+                       }
+                       completed[i]            = mbox->completed[i];
+                       mbox->completed[i]      = 0xFF;
+
+                       if (completed[i] == 0xFF) {
+                               con_log(CL_ANN, (KERN_CRIT
+                               "megaraid: command posting timed out\n"));
+
+                               BUG();
+                               continue;
+                       }
+
+                       // Get SCB associated with this command id
+                       if (completed[i] >= MBOX_MAX_SCSI_CMDS) {
+                               // a cmm command
+                               scb = adapter->uscb_list + (completed[i] -
+                                               MBOX_MAX_SCSI_CMDS);
+                       }
+                       else {
+                               // an os command
+                               scb = adapter->kscb_list + completed[i];
+                       }
+
+                       scb->status = mbox->status;
+                       list_add_tail(&scb->list, &clist);
+               }
+
+               // Acknowledge interrupt
+               WRINDOOR(raid_dev, 0x02);
+
+       } while(1);
+
+       spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
+
+
+       // put the completed commands in the completed list. DPC would
+       // complete these commands later
+       spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
+
+       list_splice(&clist, &adapter->completed_list);
+
+       spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
+
+
+       // schedule the DPC if there is some work for it
+       if (handled)
+               tasklet_schedule(&adapter->dpc_h);
+
+       return handled;
+}
+
+
+/**
+ * megaraid_isr - isr for memory based mailbox based controllers
+ * @irq                - irq
+ * @devp       - pointer to our soft state
+ * @regs       - unused
+ *
+ * Interrupt service routine for memory-mapped mailbox controllers.
+ */
+static irqreturn_t
+megaraid_isr(int irq, void *devp, struct pt_regs *regs)
+{
+       adapter_t       *adapter = devp;
+       int             handled;
+
+       handled = megaraid_ack_sequence(adapter);
+
+       /* Loop through any pending requests */
+       if (!adapter->quiescent) {
+               megaraid_mbox_runpendq(adapter, NULL);
+       }
+
+       return IRQ_RETVAL(handled);
+}
+
+
+/**
+ * megaraid_mbox_sync_scb - sync kernel buffers
+ * @adapter    : controller's soft state
+ * @scb                : pointer to the resource packet
+ *
+ * DMA sync if required.
+ */
+static inline void
+megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb)
+{
+       mbox_ccb_t      *ccb;
+
+       ccb     = (mbox_ccb_t *)scb->ccb;
+
+       switch (scb->dma_type) {
+
+       case MRAID_DMA_WBUF:
+               if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
+                       pci_dma_sync_single(adapter->pdev,
+                                       ccb->buf_dma_h,
+                                       scb->scp->request_bufflen,
+                                       PCI_DMA_FROMDEVICE);
+               }
+
+               pci_unmap_page(adapter->pdev, ccb->buf_dma_h,
+                       scb->scp->request_bufflen, scb->dma_direction);
+
+               break;
+
+       case MRAID_DMA_WSG:
+               if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
+                       pci_dma_sync_sg(adapter->pdev,
+                                       scb->scp->request_buffer,
+                                       scb->scp->use_sg, PCI_DMA_FROMDEVICE);
+               }
+
+               pci_unmap_sg(adapter->pdev, scb->scp->request_buffer,
+                       scb->scp->use_sg, scb->dma_direction);
+
+               break;
+
+       default:
+               break;
+       }
+
+       return;
+}
+
+
+/**
+ * megaraid_mbox_dpc - the tasklet to complete the commands from completed list
+ * @devp       : pointer to HBA soft state
+ *
+ * Pick up the commands from the completed list and send back to the owners.
+ * This is a reentrant function and does not assume any locks are held while
+ * it is being called.
+ */
+static void
+megaraid_mbox_dpc(unsigned long devp)
+{
+       adapter_t               *adapter = (adapter_t *)devp;
+       mraid_device_t          *raid_dev;
+       struct list_head        clist;
+       struct scatterlist      *sgl;
+       scb_t                   *scb;
+       scb_t                   *tmp;
+       struct scsi_cmnd        *scp;
+       mraid_passthru_t        *pthru;
+       mraid_epassthru_t       *epthru;
+       mbox_ccb_t              *ccb;
+       int                     islogical;
+       int                     pdev_index;
+       int                     pdev_state;
+       mbox_t                  *mbox;
+       unsigned long           flags;
+       uint8_t                 c;
+       int                     status;
+
+
+       if (!adapter) return;
+
+       raid_dev = ADAP2RAIDDEV(adapter);
+
+       // move the SCBs from the completed list to our local list
+       INIT_LIST_HEAD(&clist);
+
+       spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
+
+       list_splice_init(&adapter->completed_list, &clist);
+
+       spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
+
+
+       list_for_each_entry_safe(scb, tmp, &clist, list) {
+
+               status          = scb->status;
+               scp             = scb->scp;
+               ccb             = (mbox_ccb_t *)scb->ccb;
+               pthru           = ccb->pthru;
+               epthru          = ccb->epthru;
+               mbox            = ccb->mbox;
+
+               // Make sure f/w has completed a valid command
+               if (scb->state != SCB_ISSUED) {
+                       con_log(CL_ANN, (KERN_CRIT
+                       "megaraid critical err: invalid command %d:%d:%p\n",
+                               scb->sno, scb->state, scp));
+                       BUG();
+                       continue;       // Must never happen!
+               }
+
+               // check for the management command and complete it right away
+               if (scb->sno >= MBOX_MAX_SCSI_CMDS) {
+                       scb->state      = SCB_FREE;
+                       scb->status     = status;
+
+                       // remove from local clist
+                       list_del_init(&scb->list);
+
+                       megaraid_mbox_mm_done(adapter, scb);
+
+                       continue;
+               }
+
+               // Was an abort issued for this command earlier
+               if (scb->state & SCB_ABORT) {
+                       con_log(CL_ANN, (KERN_NOTICE
+                       "megaraid: aborted cmd %lx[%x] completed\n",
+                               scp->serial_number, scb->sno));
+               }
+
+               /*
+                * If the inquiry came of a disk drive which is not part of
+                * any RAID array, expose it to the kernel. For this to be
+                * enabled, user must set the "megaraid_expose_unconf_disks"
+                * flag to 1 by specifying it on module parameter list.
+                * This would enable data migration off drives from other
+                * configurations.
+                */
+               islogical = MRAID_IS_LOGICAL(adapter, scp);
+               if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0
+                               && IS_RAID_CH(raid_dev, scb->dev_channel)) {
+
+                       if (scp->use_sg) {
+                               sgl = (struct scatterlist *)
+                                       scp->request_buffer;
+
+                               if (sgl->page) {
+                                       c = *(unsigned char *)
+                                       (page_address((&sgl[0])->page) +
+                                               (&sgl[0])->offset);
+                               }
+                               else {
+                                       con_log(CL_ANN, (KERN_WARNING
+                                       "megaraid mailbox: invalid sg:%d\n",
+                                       __LINE__));
+                                       c = 0;
+                               }
+                       }
+                       else {
+                               c = *(uint8_t *)scp->request_buffer;
+                       }
+
+                       if ((c & 0x1F ) == TYPE_DISK) {
+                               pdev_index = (scb->dev_channel * 16) +
+                                       scb->dev_target;
+                               pdev_state =
+                                       raid_dev->pdrv_state[pdev_index] & 0x0F;
+
+                               if (pdev_state == PDRV_ONLINE           ||
+                                       pdev_state == PDRV_FAILED       ||
+                                       pdev_state == PDRV_RBLD         ||
+                                       pdev_state == PDRV_HOTSPARE     ||
+                                       megaraid_expose_unconf_disks == 0) {
+
+                                       status = 0xF0;
+                               }
+                       }
+               }
+
+               // Convert MegaRAID status to Linux error code
+               switch (status) {
+
+               case 0x00:
+
+                       scp->result = (DID_OK << 16);
+                       break;
+
+               case 0x02:
+
+                       /* set sense_buffer and result fields */
+                       if (mbox->cmd == MBOXCMD_PASSTHRU ||
+                               mbox->cmd == MBOXCMD_PASSTHRU64) {
+
+                               memcpy(scp->sense_buffer, pthru->reqsensearea,
+                                               14);
+
+                               scp->result = DRIVER_SENSE << 24 |
+                                       DID_OK << 16 | CHECK_CONDITION << 1;
+                       }
+                       else {
+                               if (mbox->cmd == MBOXCMD_EXTPTHRU) {
+
+                                       memcpy(scp->sense_buffer,
+                                               epthru->reqsensearea, 14);
+
+                                       scp->result = DRIVER_SENSE << 24 |
+                                               DID_OK << 16 |
+                                               CHECK_CONDITION << 1;
+                               } else {
+                                       scp->sense_buffer[0] = 0x70;
+                                       scp->sense_buffer[2] = ABORTED_COMMAND;
+                                       scp->result = CHECK_CONDITION << 1;
+                               }
+                       }
+                       break;
+
+               case 0x08:
+
+                       scp->result = DID_BUS_BUSY << 16 | status;
+                       break;
+
+               default:
+
+                       /*
+                        * If TEST_UNIT_READY fails, we know RESERVATION_STATUS
+                        * failed
+                        */
+                       if (scp->cmnd[0] == TEST_UNIT_READY) {
+                               scp->result = DID_ERROR << 16 |
+                                       RESERVATION_CONFLICT << 1;
+                       }
+                       else
+                       /*
+                        * Error code returned is 1 if Reserve or Release
+                        * failed or the input parameter is invalid
+                        */
+                       if (status == 1 && (scp->cmnd[0] == RESERVE ||
+                                        scp->cmnd[0] == RELEASE)) {
+
+                               scp->result = DID_ERROR << 16 |
+                                       RESERVATION_CONFLICT << 1;
+                       }
+                       else {
+                               scp->result = DID_BAD_TARGET << 16 | status;
+                       }
+               }
+
+               // print a debug message for all failed commands
+               if (status) {
+                       megaraid_mbox_display_scb(adapter, scb);
+               }
+
+               // Free our internal resources and call the mid-layer callback
+               // routine
+               megaraid_mbox_sync_scb(adapter, scb);
+
+               // remove from local clist
+               list_del_init(&scb->list);
+
+               // put back in free list
+               megaraid_dealloc_scb(adapter, scb);
+
+               // send the scsi packet back to kernel
+               spin_lock(adapter->host_lock);
+               scp->scsi_done(scp);
+               spin_unlock(adapter->host_lock);
+       }
+
+       return;
+}
+
+
+/**
+ * megaraid_abort_handler - abort the scsi command
+ * @scp                : command to be aborted
+ *
+ * Abort a previous SCSI request. Only commands on the pending list can be
+ * aborted. All the commands issued to the F/W must complete.
+ **/
+static int
+megaraid_abort_handler(struct scsi_cmnd *scp)
+{
+       adapter_t               *adapter;
+       mraid_device_t          *raid_dev;
+       scb_t                   *scb;
+       scb_t                   *tmp;
+       int                     found;
+       unsigned long           flags;
+       int                     i;
+
+
+       adapter         = SCP2ADAPTER(scp);
+       raid_dev        = ADAP2RAIDDEV(adapter);
+
+       ASSERT(spin_is_locked(adapter->host_lock));
+
+       con_log(CL_ANN, (KERN_WARNING
+               "megaraid: aborting-%ld cmd=%x <c=%d t=%d l=%d>\n",
+               scp->serial_number, scp->cmnd[0], SCP2CHANNEL(scp),
+               SCP2TARGET(scp), SCP2LUN(scp)));
+
+       // If FW has stopped responding, simply return failure
+       if (raid_dev->hw_error) {
+               con_log(CL_ANN, (KERN_NOTICE
+                       "megaraid: hw error, not aborting\n"));
+               return FAILED;
+       }
+
+       // There might a race here, where the command was completed by the
+       // firmware and now it is on the completed list. Before we could
+       // complete the command to the kernel in dpc, the abort came.
+       // Find out if this is the case to avoid the race.
+       scb = NULL;
+       spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
+       list_for_each_entry_safe(scb, tmp, &adapter->completed_list, list) {
+
+               if (scb->scp == scp) {  // Found command
+
+                       list_del_init(&scb->list);      // from completed list
+
+                       con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: %ld:%d[%d:%d], abort from completed list\n",
+                               scp->serial_number, scb->sno,
+                               scb->dev_channel, scb->dev_target));
+
+                       scp->result = (DID_ABORT << 16);
+                       scp->scsi_done(scp);
+
+                       megaraid_dealloc_scb(adapter, scb);
+
+                       spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter),
+                               flags);
+
+                       return SUCCESS;
+               }
+       }
+       spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
+
+
+       // Find out if this command is still on the pending list. If it is and
+       // was never issued, abort and return success. If the command is owned
+       // by the firmware, we must wait for it to complete by the FW.
+       spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
+       list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) {
+
+               if (scb->scp == scp) {  // Found command
+
+                       list_del_init(&scb->list);      // from pending list
+
+                       ASSERT(!(scb->state & SCB_ISSUED));
+
+                       con_log(CL_ANN, (KERN_WARNING
+                               "megaraid abort: %ld[%d:%d], driver owner\n",
+                               scp->serial_number, scb->dev_channel,
+                               scb->dev_target));
+
+                       scp->result = (DID_ABORT << 16);
+                       scp->scsi_done(scp);
+
+                       megaraid_dealloc_scb(adapter, scb);
+
+                       spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter),
+                               flags);
+
+                       return SUCCESS;
+               }
+       }
+       spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
+
+
+       // Check do we even own this command, in which case this would be
+       // owned by the firmware. The only way to locate the FW scb is to
+       // traverse through the list of all SCB, since driver does not
+       // maintain these SCBs on any list
+       found = 0;
+       for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
+               scb = adapter->kscb_list + i;
+
+               if (scb->scp == scp) {
+
+                       found = 1;
+
+                       if (!(scb->state & SCB_ISSUED)) {
+                               con_log(CL_ANN, (KERN_WARNING
+                               "megaraid abort: %ld%d[%d:%d], invalid state\n",
+                               scp->serial_number, scb->sno, scb->dev_channel,
+                               scb->dev_target));
+                               BUG();
+                       }
+                       else {
+                               con_log(CL_ANN, (KERN_WARNING
+                               "megaraid abort: %ld:%d[%d:%d], fw owner\n",
+                               scp->serial_number, scb->sno, scb->dev_channel,
+                               scb->dev_target));
+                       }
+               }
+       }
+
+       if (!found) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid abort: scsi cmd:%ld, do now own\n",
+                       scp->serial_number));
+
+               // FIXME: Should there be a callback for this command?
+               return SUCCESS;
+       }
+
+       // We cannot actually abort a command owned by firmware, return
+       // failure and wait for reset. In host reset handler, we will find out
+       // if the HBA is still live
+       return FAILED;
+}
+
+
+/**
+ * megaraid_reset_handler - device reset hadler for mailbox based driver
+ * @scp                : reference command
+ *
+ * Reset handler for the mailbox based controller. First try to find out if
+ * the FW is still live, in which case the outstanding commands counter mut go
+ * down to 0. If that happens, also issue the reservation reset command to
+ * relinquish (possible) reservations on the logical drives connected to this
+ * host
+ **/
+static int
+megaraid_reset_handler(struct scsi_cmnd *scp)
+{
+       adapter_t       *adapter;
+       scb_t           *scb;
+       scb_t           *tmp;
+       mraid_device_t  *raid_dev;
+       unsigned long   flags;
+       uint8_t         raw_mbox[sizeof(mbox_t)];
+       int             rval;
+       int             recovery_window;
+       int             recovering;
+       int             i;
+
+       adapter         = SCP2ADAPTER(scp);
+       raid_dev        = ADAP2RAIDDEV(adapter);
+
+       ASSERT(spin_is_locked(adapter->host_lock));
+
+       con_log(CL_ANN, (KERN_WARNING "megaraid: reseting the host...\n"));
+
+       // return failure if adapter is not responding
+       if (raid_dev->hw_error) {
+               con_log(CL_ANN, (KERN_NOTICE
+                       "megaraid: hw error, cannot reset\n"));
+               return FAILED;
+       }
+
+
+       // Under exceptional conditions, FW can take up to 3 minutes to
+       // complete command processing. Wait for additional 2 minutes for the
+       // pending commands counter to go down to 0. If it doesn't, let the
+       // controller be marked offline
+       // Also, reset all the commands currently owned by the driver
+       spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
+       list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) {
+
+               list_del_init(&scb->list);      // from pending list
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: %ld:%d[%d:%d], reset from pending list\n",
+                               scp->serial_number, scb->sno,
+                               scb->dev_channel, scb->dev_target));
+
+               scp->result = (DID_RESET << 16);
+               scp->scsi_done(scp);
+
+               megaraid_dealloc_scb(adapter, scb);
+       }
+       spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
+
+       if (adapter->outstanding_cmds) {
+               con_log(CL_ANN, (KERN_NOTICE
+                       "megaraid: %d outstanding commands. Max wait %d sec\n",
+                       adapter->outstanding_cmds, MBOX_RESET_WAIT));
+       }
+
+       spin_unlock(adapter->host_lock);
+
+       recovery_window = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
+
+       recovering = adapter->outstanding_cmds;
+
+       for (i = 0; i < recovery_window && adapter->outstanding_cmds; i++) {
+
+               megaraid_ack_sequence(adapter);
+
+               // print a message once every 5 seconds only
+               if (!(i % 5)) {
+                       con_log(CL_ANN, (
+                       "megaraid mbox: Wait for %d commands to complete:%d\n",
+                               adapter->outstanding_cmds,
+                               MBOX_RESET_WAIT - i));
+               }
+
+               // bailout if no recovery happended in reset time
+               if ((i == MBOX_RESET_WAIT) &&
+                       (recovering == adapter->outstanding_cmds)) {
+                       break;
+               }
+
+               msleep(1000);
+       }
+
+       spin_lock(adapter->host_lock);
+
+       // If still outstanding commands, bail out
+       if (adapter->outstanding_cmds) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid mbox: critical hardware error!\n"));
+
+               raid_dev->hw_error = 1;
+
+               return FAILED;
+       }
+       else {
+               con_log(CL_ANN, (KERN_NOTICE
+               "megaraid mbox: reset sequence completed sucessfully\n"));
+       }
+
+
+       // If the controller supports clustering, reset reservations
+       if (!adapter->ha) return SUCCESS;
+
+       // clear reservations if any
+       raw_mbox[0] = CLUSTER_CMD;
+       raw_mbox[2] = RESET_RESERVATIONS;
+
+       rval = SUCCESS;
+       if (mbox_post_sync_cmd_fast(adapter, raw_mbox) == 0) {
+               con_log(CL_ANN,
+                       (KERN_INFO "megaraid: reservation reset\n"));
+       }
+       else {
+               rval = FAILED;
+               con_log(CL_ANN, (KERN_WARNING
+                               "megaraid: reservation reset failed\n"));
+       }
+
+       return rval;
+}
+
+
+/*
+ * START: internal commands library
+ *
+ * This section of the driver has the common routine used by the driver and
+ * also has all the FW routines
+ */
+
+/**
+ * mbox_post_sync_cmd() - blocking command to the mailbox based controllers
+ * @adapter    - controller's soft state
+ * @raw_mbox   - the mailbox
+ *
+ * Issue a scb in synchronous and non-interrupt mode for mailbox based
+ * controllers
+ */
+static int
+mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[])
+{
+       mraid_device_t  *raid_dev = ADAP2RAIDDEV(adapter);
+       mbox64_t        *mbox64;
+       mbox_t          *mbox;
+       uint8_t         status;
+       int             i;
+
+
+       mbox64  = raid_dev->mbox64;
+       mbox    = raid_dev->mbox;
+
+       /*
+        * Wait until mailbox is free
+        */
+       if (megaraid_busywait_mbox(raid_dev) != 0)
+               goto blocked_mailbox;
+
+       /*
+        * Copy mailbox data into host structure
+        */
+       memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16);
+       mbox->cmdid             = 0xFE;
+       mbox->busy              = 1;
+       mbox->poll              = 0;
+       mbox->ack               = 0;
+       mbox->numstatus         = 0xFF;
+       mbox->status            = 0xFF;
+
+       wmb();
+       WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
+
+       // wait for maximum 1 second for status to post. If the status is not
+       // available within 1 second, assume FW is initializing and wait
+       // for an extended amount of time
+       if (mbox->numstatus == 0xFF) {  // status not yet available
+               udelay(25);;
+
+               for (i = 0; mbox->numstatus == 0xFF && i < 1000; i++) {
+                       rmb();
+                       msleep(1);
+               }
+
+
+               if (i == 1000) {
+                       con_log(CL_ANN, (KERN_NOTICE
+                               "megaraid mailbox: wait for FW to boot      "));
+
+                       for (i = 0; (mbox->numstatus == 0xFF) &&
+                                       (i < MBOX_RESET_WAIT); i++) {
+                               rmb();
+                               con_log(CL_ANN, ("\b\b\b\b\b[%03d]",
+                                                       MBOX_RESET_WAIT - i));
+                               msleep(1000);
+                       }
+
+                       if (i == MBOX_RESET_WAIT) {
+
+                               con_log(CL_ANN, (
+                               "\nmegaraid mailbox: status not available\n"));
+
+                               return -1;
+                       }
+                       con_log(CL_ANN, ("\b\b\b\b\b[ok] \n"));
+               }
+       }
+
+       // wait for maximum 1 second for poll semaphore
+       if (mbox->poll != 0x77) {
+               udelay(25);
+
+               for (i = 0; (mbox->poll != 0x77) && (i < 1000); i++) {
+                       rmb();
+                       msleep(1);
+               }
+
+               if (i == 1000) {
+                       con_log(CL_ANN, (KERN_WARNING
+                       "megaraid mailbox: could not get poll semaphore\n"));
+                       return -1;
+               }
+       }
+
+       WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2);
+       wmb();
+
+       // wait for maximum 1 second for acknowledgement
+       if (RDINDOOR(raid_dev) & 0x2) {
+               udelay(25);
+
+               for (i = 0; (RDINDOOR(raid_dev) & 0x2) && (i < 1000); i++) {
+                       rmb();
+                       msleep(1);
+               }
+
+               if (i == 1000) {
+                       con_log(CL_ANN, (KERN_WARNING
+                               "megaraid mailbox: could not acknowledge\n"));
+                       return -1;
+               }
+       }
+       mbox->poll      = 0;
+       mbox->ack       = 0x77;
+
+       status = mbox->status;
+
+       // invalidate the completed command id array. After command
+       // completion, firmware would write the valid id.
+       mbox->numstatus = 0xFF;
+       mbox->status    = 0xFF;
+       for (i = 0; i < MBOX_MAX_FIRMWARE_STATUS; i++) {
+               mbox->completed[i] = 0xFF;
+       }
+
+       return status;
+
+blocked_mailbox:
+
+       con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n") );
+       return -1;
+}
+
+
+/**
+ * mbox_post_sync_cmd_fast - blocking command to the mailbox based controllers
+ * @adapter    - controller's soft state
+ * @raw_mbox   - the mailbox
+ *
+ * Issue a scb in synchronous and non-interrupt mode for mailbox based
+ * controllers. This is a faster version of the synchronous command and
+ * therefore can be called in interrupt-context as well
+ */
+static int
+mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
+{
+       mraid_device_t  *raid_dev = ADAP2RAIDDEV(adapter);
+       mbox_t          *mbox;
+       long            i;
+
+
+       mbox    = raid_dev->mbox;
+
+       // return immediately if the mailbox is busy
+       if (mbox->busy) return -1;
+
+       // Copy mailbox data into host structure
+       memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 14);
+       mbox->cmdid             = 0xFE;
+       mbox->busy              = 1;
+       mbox->poll              = 0;
+       mbox->ack               = 0;
+       mbox->numstatus         = 0xFF;
+       mbox->status            = 0xFF;
+
+       wmb();
+       WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
+
+       for (i = 0; i < 0xFFFFF; i++) {
+               if (mbox->numstatus != 0xFF) break;
+       }
+
+       if (i == 0xFFFFF) {
+               // We may need to re-calibrate the counter
+               con_log(CL_ANN, (KERN_CRIT
+                       "megaraid: fast sync command timed out\n"));
+       }
+
+       WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2);
+       wmb();
+
+       return mbox->status;
+}
+
+
+/**
+ * megaraid_busywait_mbox() - Wait until the controller's mailbox is available
+ * @raid_dev   - RAID device (HBA) soft state
+ *
+ * wait until the controller's mailbox is available to accept more commands.
+ * wait for at most 1 second
+ */
+static int
+megaraid_busywait_mbox(mraid_device_t *raid_dev)
+{
+       mbox_t  *mbox = raid_dev->mbox;
+       int     i = 0;
+
+       if (mbox->busy) {
+               udelay(25);
+               for (i = 0; mbox->busy && i < 1000; i++)
+                       msleep(1);
+       }
+
+       if (i < 1000) return 0;
+       else return -1;
+}
+
+
+/**
+ * megaraid_mbox_product_info - some static information about the controller
+ * @adapter    - our soft state
+ *
+ * issue commands to the controller to grab some parameters required by our
+ * caller.
+ */
+static int
+megaraid_mbox_product_info(adapter_t *adapter)
+{
+       mraid_device_t          *raid_dev = ADAP2RAIDDEV(adapter);
+       mbox_t                  *mbox;
+       uint8_t                 raw_mbox[sizeof(mbox_t)];
+       mraid_pinfo_t           *pinfo;
+       dma_addr_t              pinfo_dma_h;
+       mraid_inquiry3_t        *mraid_inq3;
+       int                     i;
+
+
+       memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
+       mbox = (mbox_t *)raw_mbox;
+
+       /*
+        * Issue an ENQUIRY3 command to find out certain adapter parameters,
+        * e.g., max channels, max commands etc.
+        */
+       pinfo = pci_alloc_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
+                       &pinfo_dma_h);
+
+       if (pinfo == NULL) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       __LINE__));
+
+               return -1;
+       }
+       memset(pinfo, 0, sizeof(mraid_pinfo_t));
+
+       mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
+       memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+       raw_mbox[0] = FC_NEW_CONFIG;
+       raw_mbox[2] = NC_SUBOP_ENQUIRY3;
+       raw_mbox[3] = ENQ3_GET_SOLICITED_FULL;
+
+       // Issue the command
+       if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
+
+               con_log(CL_ANN, (KERN_WARNING "megaraid: Inquiry3 failed\n"));
+
+               pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
+                       pinfo, pinfo_dma_h);
+
+               return -1;
+       }
+
+       /*
+        * Collect information about state of each physical drive
+        * attached to the controller. We will expose all the disks
+        * which are not part of RAID
+        */
+       mraid_inq3 = (mraid_inquiry3_t *)adapter->ibuf;
+       for (i = 0; i < MBOX_MAX_PHYSICAL_DRIVES; i++) {
+               raid_dev->pdrv_state[i] = mraid_inq3->pdrv_state[i];
+       }
+
+       /*
+        * Get product info for information like number of channels,
+        * maximum commands supported.
+        */
+       memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
+       mbox->xferaddr = (uint32_t)pinfo_dma_h;
+
+       raw_mbox[0] = FC_NEW_CONFIG;
+       raw_mbox[2] = NC_SUBOP_PRODUCT_INFO;
+
+       if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: product info failed\n"));
+
+               pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
+                       pinfo, pinfo_dma_h);
+
+               return -1;
+       }
+
+       /*
+        * Setup some parameters for host, as required by our caller
+        */
+       adapter->max_channel = pinfo->nchannels;
+
+       /*
+        * we will export all the logical drives on a single channel.
+        * Add 1 since inquires do not come for inititor ID
+        */
+       adapter->max_target     = MAX_LOGICAL_DRIVES_40LD + 1;
+       adapter->max_lun        = 8;    // up to 8 LUNs for non-disk devices
+
+       /*
+        * These are the maximum outstanding commands for the scsi-layer
+        */
+       adapter->max_cmds       = MBOX_MAX_SCSI_CMDS;
+
+       memset(adapter->fw_version, 0, VERSION_SIZE);
+       memset(adapter->bios_version, 0, VERSION_SIZE);
+
+       memcpy(adapter->fw_version, pinfo->fw_version, 4);
+       adapter->fw_version[4] = 0;
+
+       memcpy(adapter->bios_version, pinfo->bios_version, 4);
+       adapter->bios_version[4] = 0;
+
+       con_log(CL_ANN, (KERN_NOTICE
+               "megaraid: fw version:[%s] bios version:[%s]\n",
+               adapter->fw_version, adapter->bios_version));
+
+       pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t), pinfo,
+                       pinfo_dma_h);
+
+       return 0;
+}
+
+
+
+/**
+ * megaraid_mbox_extended_cdb - check for support for extended CDBs
+ * @adapter    - soft state for the controller
+ *
+ * this routine check whether the controller in question supports extended
+ * ( > 10 bytes ) CDBs
+ */
+static int
+megaraid_mbox_extended_cdb(adapter_t *adapter)
+{
+       mbox_t          *mbox;
+       uint8_t         raw_mbox[sizeof(mbox_t)];
+       int             rval;
+
+       mbox = (mbox_t *)raw_mbox;
+
+       memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
+       mbox->xferaddr  = (uint32_t)adapter->ibuf_dma_h;
+
+       memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+       raw_mbox[0] = MAIN_MISC_OPCODE;
+       raw_mbox[2] = SUPPORT_EXT_CDB;
+
+       /*
+        * Issue the command
+        */
+       rval = 0;
+       if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
+               rval = -1;
+       }
+
+       return rval;
+}
+
+
+/**
+ * megaraid_mbox_support_ha - Do we support clustering
+ * @adapter    - soft state for the controller
+ * @init_id    - ID of the initiator
+ *
+ * Determine if the firmware supports clustering and the ID of the initiator.
+ */
+static int
+megaraid_mbox_support_ha(adapter_t *adapter, uint16_t *init_id)
+{
+       mbox_t          *mbox;
+       uint8_t         raw_mbox[sizeof(mbox_t)];
+       int             rval;
+
+
+       mbox = (mbox_t *)raw_mbox;
+
+       memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
+
+       mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
+
+       memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+       raw_mbox[0] = GET_TARGET_ID;
+
+       // Issue the command
+       *init_id = 7;
+       rval =  -1;
+       if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
+
+               *init_id = *(uint8_t *)adapter->ibuf;
+
+               con_log(CL_ANN, (KERN_INFO
+                       "megaraid: cluster firmware, initiator ID: %d\n",
+                       *init_id));
+
+               rval =  0;
+       }
+
+       return rval;
+}
+
+
+/**
+ * megaraid_mbox_support_random_del - Do we support random deletion
+ * @adapter    - soft state for the controller
+ *
+ * Determine if the firmware supports random deletion
+ * Return:     1 is operation supported, 0 otherwise
+ */
+static int
+megaraid_mbox_support_random_del(adapter_t *adapter)
+{
+       mbox_t          *mbox;
+       uint8_t         raw_mbox[sizeof(mbox_t)];
+       int             rval;
+
+
+       mbox = (mbox_t *)raw_mbox;
+
+       memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
+
+       raw_mbox[0] = FC_DEL_LOGDRV;
+       raw_mbox[0] = OP_SUP_DEL_LOGDRV;
+
+       // Issue the command
+       rval = 0;
+       if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
+
+               con_log(CL_DLEVEL1, ("megaraid: supports random deletion\n"));
+
+               rval =  1;
+       }
+
+       return rval;
+}
+
+
+/**
+ * megaraid_mbox_get_max_sg - maximum sg elements supported by the firmware
+ * @adapter    - soft state for the controller
+ *
+ * Find out the maximum number of scatter-gather elements supported by the
+ * firmware
+ */
+static int
+megaraid_mbox_get_max_sg(adapter_t *adapter)
+{
+       mbox_t          *mbox;
+       uint8_t         raw_mbox[sizeof(mbox_t)];
+       int             nsg;
+
+
+       mbox = (mbox_t *)raw_mbox;
+
+       memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
+
+       mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
+
+       memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+       raw_mbox[0] = MAIN_MISC_OPCODE;
+       raw_mbox[2] = GET_MAX_SG_SUPPORT;
+
+       // Issue the command
+       if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
+               nsg =  *(uint8_t *)adapter->ibuf;
+       }
+       else {
+               nsg =  MBOX_DEFAULT_SG_SIZE;
+       }
+
+       if (nsg > MBOX_MAX_SG_SIZE) nsg = MBOX_MAX_SG_SIZE;
+
+       return nsg;
+}
+
+
+/**
+ * megaraid_mbox_enum_raid_scsi - enumerate the RAID and SCSI channels
+ * @adapter    - soft state for the controller
+ *
+ * Enumerate the RAID and SCSI channels for ROMB platoforms so that channels
+ * can be exported as regular SCSI channels
+ */
+static void
+megaraid_mbox_enum_raid_scsi(adapter_t *adapter)
+{
+       mraid_device_t  *raid_dev = ADAP2RAIDDEV(adapter);
+       mbox_t          *mbox;
+       uint8_t         raw_mbox[sizeof(mbox_t)];
+
+
+       mbox = (mbox_t *)raw_mbox;
+
+       memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
+
+       mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
+
+       memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+       raw_mbox[0] = CHNL_CLASS;
+       raw_mbox[2] = GET_CHNL_CLASS;
+
+       // Issue the command. If the command fails, all channels are RAID
+       // channels
+       raid_dev->channel_class = 0xFF;
+       if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
+               raid_dev->channel_class =  *(uint8_t *)adapter->ibuf;
+       }
+
+       return;
+}
+
+
+/**
+ * megaraid_mbox_flush_cache - flush adapter and disks cache
+ * @param adapter      : soft state for the controller
+ *
+ * Flush adapter cache followed by disks cache
+ */
+static void
+megaraid_mbox_flush_cache(adapter_t *adapter)
+{
+       mbox_t  *mbox;
+       uint8_t raw_mbox[sizeof(mbox_t)];
+
+
+       mbox = (mbox_t *)raw_mbox;
+
+       memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
+
+       raw_mbox[0] = FLUSH_ADAPTER;
+
+       if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
+               con_log(CL_ANN, ("megaraid: flush adapter failed\n"));
+       }
+
+       raw_mbox[0] = FLUSH_SYSTEM;
+
+       if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
+               con_log(CL_ANN, ("megaraid: flush disks cache failed\n"));
+       }
+
+       return;
+}
+
+
+/**
+ * megaraid_mbox_display_scb - display SCB information, mostly debug purposes
+ * @param adapter      : controllers' soft state
+ * @param scb          : SCB to be displayed
+ * @param level        : debug level for console print
+ *
+ * Diplay information about the given SCB iff the current debug level is
+ * verbose
+ */
+static void
+megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb)
+{
+       mbox_ccb_t              *ccb;
+       struct scsi_cmnd        *scp;
+       mbox_t                  *mbox;
+       int                     level;
+       int                     i;
+
+
+       ccb     = (mbox_ccb_t *)scb->ccb;
+       scp     = scb->scp;
+       mbox    = ccb->mbox;
+
+       level = CL_DLEVEL3;
+
+       con_log(level, (KERN_NOTICE
+               "megaraid mailbox: status:%#x cmd:%#x id:%#x ", scb->status,
+               mbox->cmd, scb->sno));
+
+       con_log(level, ("sec:%#x lba:%#x addr:%#x ld:%d sg:%d\n",
+               mbox->numsectors, mbox->lba, mbox->xferaddr, mbox->logdrv,
+               mbox->numsge));
+
+       if (!scp) return;
+
+       con_log(level, (KERN_NOTICE "scsi cmnd: "));
+
+       for (i = 0; i < scp->cmd_len; i++) {
+               con_log(level, ("%#2.02x ", scp->cmnd[i]));
+       }
+
+       con_log(level, ("\n"));
+
+       return;
+}
+
+
+/**
+ * megaraid_mbox_setup_device_map - manage device ids
+ * @adapter    : Driver's soft state
+ *
+ * Manange the device ids to have an appropraite mapping between the kernel
+ * scsi addresses and megaraid scsi and logical drive addresses. We export
+ * scsi devices on their actual addresses, whereas the logical drives are
+ * exported on a virtual scsi channel.
+ **/
+static void
+megaraid_mbox_setup_device_map(adapter_t *adapter)
+{
+       uint8_t         c;
+       uint8_t         t;
+
+       /*
+        * First fill the values on the logical drive channel
+        */
+       for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++)
+               adapter->device_ids[adapter->max_channel][t] =
+                       (t < adapter->init_id) ?  t : t - 1;
+
+       adapter->device_ids[adapter->max_channel][adapter->init_id] = 0xFF;
+
+       /*
+        * Fill the values on the physical devices channels
+        */
+       for (c = 0; c < adapter->max_channel; c++)
+               for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++)
+                       adapter->device_ids[c][t] = (c << 8) | t;
+}
+
+
+/*
+ * END: internal commands library
+ */
+
+/*
+ * START: Interface for the common management module
+ *
+ * This is the module, which interfaces with the common mangement module to
+ * provide support for ioctl and sysfs
+ */
+
+/**
+ * megaraid_cmm_register - register with the mangement module
+ * @param adapter      : HBA soft state
+ *
+ * Register with the management module, which allows applications to issue
+ * ioctl calls to the drivers. This interface is used by the management module
+ * to setup sysfs support as well.
+ */
+static int
+megaraid_cmm_register(adapter_t *adapter)
+{
+       mraid_device_t  *raid_dev = ADAP2RAIDDEV(adapter);
+       mraid_mmadp_t   adp;
+       scb_t           *scb;
+       mbox_ccb_t      *ccb;
+       int             rval;
+       int             i;
+
+       // Allocate memory for the base list of scb for management module.
+       adapter->uscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_USER_CMDS,
+                       GFP_KERNEL);
+
+       if (adapter->uscb_list == NULL) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       __LINE__));
+               return -1;
+       }
+       memset(adapter->uscb_list, 0, sizeof(scb_t) * MBOX_MAX_USER_CMDS);
+
+
+       // Initialize the synchronization parameters for resources for
+       // commands for management module
+       INIT_LIST_HEAD(&adapter->uscb_pool);
+
+       spin_lock_init(USER_FREE_LIST_LOCK(adapter));
+
+
+
+       // link all the packets. Note, CCB for commands, coming from the
+       // commom management module, mailbox physical address are already
+       // setup by it. We just need placeholder for that in our local command
+       // control blocks
+       for (i = 0; i < MBOX_MAX_USER_CMDS; i++) {
+
+               scb                     = adapter->uscb_list + i;
+               ccb                     = raid_dev->uccb_list + i;
+
+               scb->ccb                = (caddr_t)ccb;
+               ccb->mbox64             = raid_dev->umbox64 + i;
+               ccb->mbox               = &ccb->mbox64->mbox32;
+               ccb->raw_mbox           = (uint8_t *)ccb->mbox;
+
+               scb->gp                 = 0;
+
+               // COMMAND ID 0 - (MBOX_MAX_SCSI_CMDS-1) ARE RESERVED FOR
+               // COMMANDS COMING FROM IO SUBSYSTEM (MID-LAYER)
+               scb->sno                = i + MBOX_MAX_SCSI_CMDS;
+
+               scb->scp                = NULL;
+               scb->state              = SCB_FREE;
+               scb->dma_direction      = PCI_DMA_NONE;
+               scb->dma_type           = MRAID_DMA_NONE;
+               scb->dev_channel        = -1;
+               scb->dev_target         = -1;
+
+               // put scb in the free pool
+               list_add_tail(&scb->list, &adapter->uscb_pool);
+       }
+
+       adp.unique_id           = adapter->unique_id;
+       adp.drvr_type           = DRVRTYPE_MBOX;
+       adp.drvr_data           = (unsigned long)adapter;
+       adp.pdev                = adapter->pdev;
+       adp.issue_uioc          = megaraid_mbox_mm_handler;
+       adp.timeout             = 30;
+       adp.max_kioc            = MBOX_MAX_USER_CMDS;
+
+       if ((rval = mraid_mm_register_adp(&adp)) != 0) {
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid mbox: did not register with CMM\n"));
+
+               kfree(adapter->uscb_list);
+       }
+
+       return rval;
+}
+
+
+/**
+ * megaraid_cmm_unregister - un-register with the mangement module
+ * @param adapter      : HBA soft state
+ *
+ * Un-register with the management module.
+ * FIXME: mgmt module must return failure for unregister if it has pending
+ * commands in LLD
+ */
+static int
+megaraid_cmm_unregister(adapter_t *adapter)
+{
+       kfree(adapter->uscb_list);
+       mraid_mm_unregister_adp(adapter->unique_id);
+       return 0;
+}
+
+
+/**
+ * megaraid_mbox_mm_handler - interface for CMM to issue commands to LLD
+ * @param drvr_data    : LLD specific data
+ * @param kioc         : CMM interface packet
+ * @param action       : command action
+ *
+ * This routine is invoked whenever the Common Mangement Module (CMM) has a
+ * command for us. The 'action' parameter specifies if this is a new command
+ * or otherwise.
+ */
+static int
+megaraid_mbox_mm_handler(unsigned long drvr_data, uioc_t *kioc, uint32_t action)
+{
+       adapter_t *adapter;
+
+       if (action != IOCTL_ISSUE) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: unsupported management action:%#2x\n",
+                       action));
+               return (-ENOTSUPP);
+       }
+
+       adapter = (adapter_t *)drvr_data;
+
+       // make sure this adapter is not being detached right now.
+       if (atomic_read(&adapter->being_detached)) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: reject management request, detaching\n"));
+               return (-ENODEV);
+       }
+
+       switch (kioc->opcode) {
+
+       case GET_ADAP_INFO:
+
+               kioc->status =  gather_hbainfo(adapter, (mraid_hba_info_t *)
+                                       (unsigned long)kioc->buf_vaddr);
+
+               kioc->done(kioc);
+
+               return kioc->status;
+
+       case MBOX_CMD:
+
+               return megaraid_mbox_mm_command(adapter, kioc);
+
+       default:
+               kioc->status = (-EINVAL);
+               kioc->done(kioc);
+               return (-EINVAL);
+       }
+
+       return 0;       // not reached
+}
+
+/**
+ * megaraid_mbox_mm_command - issues commands routed through CMM
+ * @param adapter      : HBA soft state
+ * @param kioc         : management command packet
+ *
+ * Issues commands, which are routed through the management module.
+ */
+static int
+megaraid_mbox_mm_command(adapter_t *adapter, uioc_t *kioc)
+{
+       struct list_head        *head = &adapter->uscb_pool;
+       mbox64_t                *mbox64;
+       uint8_t                 *raw_mbox;
+       scb_t                   *scb;
+       mbox_ccb_t              *ccb;
+       unsigned long           flags;
+
+       // detach one scb from free pool
+       spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags);
+
+       if (list_empty(head)) { // should never happen because of CMM
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid mbox: bug in cmm handler, lost resources\n"));
+
+               spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
+
+               return (-EINVAL);
+       }
+
+       scb = list_entry(head->next, scb_t, list);
+       list_del_init(&scb->list);
+
+       spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
+
+       scb->state      = SCB_ACTIVE;
+       scb->dma_type   = MRAID_DMA_NONE;
+
+       ccb             = (mbox_ccb_t *)scb->ccb;
+       mbox64          = (mbox64_t *)(unsigned long)kioc->cmdbuf;
+       raw_mbox        = (uint8_t *)&mbox64->mbox32;
+
+       memcpy(ccb->mbox64, mbox64, sizeof(mbox64_t));
+
+       scb->gp         = (unsigned long)kioc;
+
+       /*
+        * If it is a logdrv random delete operation, we have to wait till
+        * there are no outstanding cmds at the fw and then issue it directly
+        */
+       if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) {
+
+               if (wait_till_fw_empty(adapter)) {
+                       con_log(CL_ANN, (KERN_NOTICE
+                               "megaraid mbox: LD delete, timed out\n"));
+
+                       kioc->status = -ETIME;
+
+                       scb->status = -1;
+
+                       megaraid_mbox_mm_done(adapter, scb);
+
+                       return (-ETIME);
+               }
+
+               INIT_LIST_HEAD(&scb->list);
+
+               scb->state = SCB_ISSUED;
+               if (mbox_post_cmd(adapter, scb) != 0) {
+
+                       con_log(CL_ANN, (KERN_NOTICE
+                               "megaraid mbox: LD delete, mailbox busy\n"));
+
+                       kioc->status = -EBUSY;
+
+                       scb->status = -1;
+
+                       megaraid_mbox_mm_done(adapter, scb);
+
+                       return (-EBUSY);
+               }
+
+               return 0;
+       }
+
+       // put the command on the pending list and execute
+       megaraid_mbox_runpendq(adapter, scb);
+
+       return 0;
+}
+
+
+static int
+wait_till_fw_empty(adapter_t *adapter)
+{
+       unsigned long   flags = 0;
+       int             i;
+
+
+       /*
+        * Set the quiescent flag to stop issuing cmds to FW.
+        */
+       spin_lock_irqsave(adapter->host_lock, flags);
+       adapter->quiescent++;
+       spin_unlock_irqrestore(adapter->host_lock, flags);
+
+       /*
+        * Wait till there are no more cmds outstanding at FW. Try for at most
+        * 60 seconds
+        */
+       for (i = 0; i < 60 && adapter->outstanding_cmds; i++) {
+               con_log(CL_DLEVEL1, (KERN_INFO
+                       "megaraid: FW has %d pending commands\n",
+                       adapter->outstanding_cmds));
+
+               msleep(1000);
+       }
+
+       return adapter->outstanding_cmds;
+}
+
+
+/**
+ * megaraid_mbox_mm_done - callback for CMM commands
+ * @adapter    : HBA soft state
+ * @scb                : completed command
+ *
+ * Callback routine for internal commands originated from the management
+ * module.
+ */
+static void
+megaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb)
+{
+       uioc_t                  *kioc;
+       mbox64_t                *mbox64;
+       uint8_t                 *raw_mbox;
+       unsigned long           flags;
+
+       kioc                    = (uioc_t *)scb->gp;
+       kioc->status            = 0;
+       mbox64                  = (mbox64_t *)(unsigned long)kioc->cmdbuf;
+       mbox64->mbox32.status   = scb->status;
+       raw_mbox                = (uint8_t *)&mbox64->mbox32;
+
+
+       // put scb in the free pool
+       scb->state      = SCB_FREE;
+       scb->scp        = NULL;
+
+       spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags);
+
+       list_add(&scb->list, &adapter->uscb_pool);
+
+       spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
+
+       // if a delete logical drive operation succeeded, restart the
+       // controller
+       if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) {
+
+               adapter->quiescent--;
+
+               megaraid_mbox_runpendq(adapter, NULL);
+       }
+
+       kioc->done(kioc);
+
+       return;
+}
+
+
+/**
+ * gather_hbainfo - HBA characteristics for the applications
+ * @param adapter      : HBA soft state
+ * @param hinfo                : pointer to the caller's host info strucuture
+ */
+static int
+gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo)
+{
+       uint8_t dmajor;
+
+       dmajor                  = megaraid_mbox_version[0];
+
+       hinfo->pci_vendor_id    = adapter->pdev->vendor;
+       hinfo->pci_device_id    = adapter->pdev->device;
+       hinfo->subsys_vendor_id = adapter->pdev->subsystem_vendor;
+       hinfo->subsys_device_id = adapter->pdev->subsystem_device;
+
+       hinfo->pci_bus          = adapter->pdev->bus->number;
+       hinfo->pci_dev_fn       = adapter->pdev->devfn;
+       hinfo->pci_slot         = PCI_SLOT(adapter->pdev->devfn);
+       hinfo->irq              = adapter->host->irq;
+       hinfo->baseport         = ADAP2RAIDDEV(adapter)->baseport;
+
+       hinfo->unique_id        = (hinfo->pci_bus << 8) | adapter->pdev->devfn;
+       hinfo->host_no          = adapter->host->host_no;
+
+       return 0;
+}
+
+/*
+ * END: Interface for the common management module
+ */
+
+
+/*
+ * END: Mailbox Low Level Driver
+ */
+module_init(megaraid_init);
+module_exit(megaraid_exit);
+
+/* vim: set ts=8 sw=8 tw=78 ai si: */
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
new file mode 100644 (file)
index 0000000..2f195ab
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ *
+ *                     Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic Corporation.
+ *
+ *        This program is free software; you can redistribute it and/or
+ *        modify it under the terms of the GNU General Public License
+ *        as published by the Free Software Foundation; either version
+ *        2 of the License, or (at your option) any later version.
+ *
+ * FILE                : megaraid_mbox.h
+ */
+
+#ifndef _MEGARAID_H_
+#define _MEGARAID_H_
+
+
+#include "mega_common.h"
+#include "mbox_defs.h"
+#include "megaraid_ioctl.h"
+
+
+#define MEGARAID_VERSION       "2.20.4.0"
+#define MEGARAID_EXT_VERSION   "(Release Date: Mon Sep 27 22:15:07 EDT 2004)"
+
+
+/*
+ * Define some PCI values here until they are put in the kernel
+ */
+#define PCI_DEVICE_ID_PERC4_DI_DISCOVERY               0x000E
+#define PCI_SUBSYS_ID_PERC4_DI_DISCOVERY               0x0123
+
+#define PCI_DEVICE_ID_PERC4_SC                         0x1960
+#define PCI_SUBSYS_ID_PERC4_SC                         0x0520
+
+#define PCI_DEVICE_ID_PERC4_DC                         0x1960
+#define PCI_SUBSYS_ID_PERC4_DC                         0x0518
+
+#define PCI_DEVICE_ID_PERC4_QC                         0x0407
+#define PCI_SUBSYS_ID_PERC4_QC                         0x0531
+
+#define PCI_DEVICE_ID_PERC4_DI_EVERGLADES              0x000F
+#define PCI_SUBSYS_ID_PERC4_DI_EVERGLADES              0x014A
+
+#define PCI_DEVICE_ID_PERC4E_SI_BIGBEND                        0x0013
+#define PCI_SUBSYS_ID_PERC4E_SI_BIGBEND                        0x016c
+
+#define PCI_DEVICE_ID_PERC4E_DI_KOBUK                  0x0013
+#define PCI_SUBSYS_ID_PERC4E_DI_KOBUK                  0x016d
+
+#define PCI_DEVICE_ID_PERC4E_DI_CORVETTE               0x0013
+#define PCI_SUBSYS_ID_PERC4E_DI_CORVETTE               0x016e
+
+#define PCI_DEVICE_ID_PERC4E_DI_EXPEDITION             0x0013
+#define PCI_SUBSYS_ID_PERC4E_DI_EXPEDITION             0x016f
+
+#define PCI_DEVICE_ID_PERC4E_DI_GUADALUPE              0x0013
+#define PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE              0x0170
+
+#define PCI_DEVICE_ID_PERC4E_DC_320_2E                 0x0408
+#define PCI_SUBSYS_ID_PERC4E_DC_320_2E                 0x0002
+
+#define PCI_DEVICE_ID_PERC4E_SC_320_1E                 0x0408
+#define PCI_SUBSYS_ID_PERC4E_SC_320_1E                 0x0001
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_0              0x1960
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_0              0xA520
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_1              0x1960
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_1              0x0520
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2              0x1960
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2              0x0518
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_0x             0x0407
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_0x             0x0530
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2x             0x0407
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2x             0x0532
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_4x             0x0407
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_4x             0x0531
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_1E             0x0408
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_1E             0x0001
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2E             0x0408
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2E             0x0002
+
+#define PCI_DEVICE_ID_MEGARAID_I4_133_RAID             0x1960
+#define PCI_SUBSYS_ID_MEGARAID_I4_133_RAID             0x0522
+
+#define PCI_DEVICE_ID_MEGARAID_SATA_150_4              0x1960
+#define PCI_SUBSYS_ID_MEGARAID_SATA_150_4              0x4523
+
+#define PCI_DEVICE_ID_MEGARAID_SATA_150_6              0x1960
+#define PCI_SUBSYS_ID_MEGARAID_SATA_150_6              0x0523
+
+#define PCI_DEVICE_ID_MEGARAID_SATA_300_4x             0x0409
+#define PCI_SUBSYS_ID_MEGARAID_SATA_300_4x             0x3004
+
+#define PCI_DEVICE_ID_MEGARAID_SATA_300_8x             0x0409
+#define PCI_SUBSYS_ID_MEGARAID_SATA_300_8x             0x3008
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCU42X               0x0407
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCU42X               0x0532
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCS16                        0x1960
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCS16                        0x0523
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCU42E               0x0408
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCU42E               0x0002
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCZCRX               0x0407
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCZCRX               0x0530
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCS28X               0x0409
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCS28X               0x3008
+
+#define PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_ALIEF       0x0408
+#define PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_ALIEF       0x3431
+
+#define PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_HARWICH     0x0408
+#define PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_HARWICH     0x3499
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK   0x1960
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK   0x0520
+
+#define PCI_DEVICE_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB    0x0408
+#define PCI_SUBSYS_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB    0x1065
+
+#define PCI_DEVICE_ID_MEGARAID_ACER_ROMB_2E            0x0408
+#define PCI_SUBSYS_ID_MEGARAID_ACER_ROMB_2E            0x004D
+
+#define PCI_SUBSYS_ID_PERC3_QC                         0x0471
+#define PCI_SUBSYS_ID_PERC3_DC                         0x0493
+#define PCI_SUBSYS_ID_PERC3_SC                         0x0475
+
+#ifndef PCI_SUBSYS_ID_FSC
+#define PCI_SUBSYS_ID_FSC                              0x1734
+#endif
+
+#define MBOX_MAX_SCSI_CMDS     128     // number of cmds reserved for kernel
+#define MBOX_MAX_USER_CMDS     32      // number of cmds for applications
+#define MBOX_DEF_CMD_PER_LUN   64      // default commands per lun
+#define MBOX_DEFAULT_SG_SIZE   26      // default sg size supported by all fw
+#define MBOX_MAX_SG_SIZE       32      // maximum scatter-gather list size
+#define MBOX_MAX_SECTORS       128     // maximum sectors per IO
+#define MBOX_TIMEOUT           30      // timeout value for internal cmds
+#define MBOX_BUSY_WAIT         10      // max usec to wait for busy mailbox
+#define MBOX_RESET_WAIT                180     // wait these many seconds in reset
+#define MBOX_RESET_EXT_WAIT    120     // extended wait reset
+
+/*
+ * maximum transfer that can happen through the firmware commands issued
+ * internnaly from the driver.
+ */
+#define MBOX_IBUF_SIZE         4096
+
+
+/**
+ * mbox_ccb_t - command control block specific to mailbox based controllers
+ * @raw_mbox           : raw mailbox pointer
+ * @mbox               : mailbox
+ * @mbox64             : extended mailbox
+ * @mbox_dma_h         : maibox dma address
+ * @sgl64              : 64-bit scatter-gather list
+ * @sgl32              : 32-bit scatter-gather list
+ * @sgl_dma_h          : dma handle for the scatter-gather list
+ * @pthru              : passthru structure
+ * @pthru_dma_h                : dma handle for the passthru structure
+ * @epthru             : extended passthru structure
+ * @epthru_dma_h       : dma handle for extended passthru structure
+ * @buf_dma_h          : dma handle for buffers w/o sg list
+ *
+ * command control block specific to the mailbox based controllers
+ */
+typedef struct {
+       uint8_t                 *raw_mbox;
+       mbox_t                  *mbox;
+       mbox64_t                *mbox64;
+       dma_addr_t              mbox_dma_h;
+       mbox_sgl64              *sgl64;
+       mbox_sgl32              *sgl32;
+       dma_addr_t              sgl_dma_h;
+       mraid_passthru_t        *pthru;
+       dma_addr_t              pthru_dma_h;
+       mraid_epassthru_t       *epthru;
+       dma_addr_t              epthru_dma_h;
+       dma_addr_t              buf_dma_h;
+} mbox_ccb_t;
+
+
+/**
+ * mraid_device_t - adapter soft state structure for mailbox controllers
+ * @param una_mbox64           : 64-bit mbox - unaligned
+ * @param una_mbox64_dma       : mbox dma addr - unaligned
+ * @param mbox                 : 32-bit mbox - aligned
+ * @param mbox64               : 64-bit mbox - aligned
+ * @param mbox_dma             : mbox dma addr - aligned
+ * @param mailbox_lock         : exclusion lock for the mailbox
+ * @param baseport             : base port of hba memory
+ * @param baseaddr             : mapped addr of hba memory
+ * @param mbox_pool            : pool of mailboxes
+ * @param mbox_pool_handle     : handle for the mailbox pool memory
+ * @param epthru_pool          : a pool for extended passthru commands
+ * @param epthru_pool_handle   : handle to the pool above
+ * @param sg_pool              : pool of scatter-gather lists for this driver
+ * @param sg_pool_handle       : handle to the pool above
+ * @param ccb_list             : list of our command control blocks
+ * @param uccb_list            : list of cmd control blocks for mgmt module
+ * @param umbox64              : array of mailbox for user commands (cmm)
+ * @param pdrv_state           : array for state of each physical drive.
+ * @param last_disp            : flag used to show device scanning
+ * @param hw_error             : set if FW not responding
+ * @param fast_load            : If set, skip physical device scanning
+ * @channel_class              : channel class, RAID or SCSI
+ *
+ * Initialization structure for mailbox controllers: memory based and IO based
+ * All the fields in this structure are LLD specific and may be discovered at
+ * init() or start() time.
+ *
+ * NOTE: The fields of this structures are placed to minimize cache misses
+ */
+typedef struct {
+       mbox64_t                        *una_mbox64;
+       dma_addr_t                      una_mbox64_dma;
+       mbox_t                          *mbox;
+       mbox64_t                        *mbox64;
+       dma_addr_t                      mbox_dma;
+       spinlock_t                      mailbox_lock;
+       unsigned long                   baseport;
+       unsigned long                   baseaddr;
+       struct mraid_pci_blk            mbox_pool[MBOX_MAX_SCSI_CMDS];
+       struct dma_pool                 *mbox_pool_handle;
+       struct mraid_pci_blk            epthru_pool[MBOX_MAX_SCSI_CMDS];
+       struct dma_pool                 *epthru_pool_handle;
+       struct mraid_pci_blk            sg_pool[MBOX_MAX_SCSI_CMDS];
+       struct dma_pool                 *sg_pool_handle;
+       mbox_ccb_t                      ccb_list[MBOX_MAX_SCSI_CMDS];
+       mbox_ccb_t                      uccb_list[MBOX_MAX_USER_CMDS];
+       mbox64_t                        umbox64[MBOX_MAX_USER_CMDS];
+
+       uint8_t                         pdrv_state[MBOX_MAX_PHYSICAL_DRIVES];
+       uint32_t                        last_disp;
+       int                             hw_error;
+       int                             fast_load;
+       uint8_t                         channel_class;
+} mraid_device_t;
+
+// route to raid device from adapter
+#define ADAP2RAIDDEV(adp)      ((mraid_device_t *)((adp)->raid_device))
+
+#define MAILBOX_LOCK(rdev)     (&(rdev)->mailbox_lock)
+
+// Find out if this channel is a RAID or SCSI
+#define IS_RAID_CH(rdev, ch)   (((rdev)->channel_class >> (ch)) & 0x01)
+
+
+#define RDINDOOR(rdev)         readl((rdev)->baseaddr + 0x20)
+#define RDOUTDOOR(rdev)                readl((rdev)->baseaddr + 0x2C)
+#define WRINDOOR(rdev, value)  writel(value, (rdev)->baseaddr + 0x20)
+#define WROUTDOOR(rdev, value) writel(value, (rdev)->baseaddr + 0x2C)
+
+#endif // _MEGARAID_H_
+
+// vim: set ts=8 sw=8 tw=78:
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
new file mode 100644 (file)
index 0000000..8a6bc93
--- /dev/null
@@ -0,0 +1,1160 @@
+/*
+ *
+ *                     Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic Corporation.
+ *
+ *        This program is free software; you can redistribute it and/or
+ *        modify it under the terms of the GNU General Public License
+ *        as published by the Free Software Foundation; either version
+ *        2 of the License, or (at your option) any later version.
+ *
+ * FILE                : megaraid_mm.c
+ * Version     : v2.20.2.0 (August 19 2004)
+ *
+ * Common management module
+ */
+
+#include "megaraid_mm.h"
+
+
+// Entry points for char node driver
+static int mraid_mm_open(struct inode *, struct file *);
+static int mraid_mm_ioctl(struct inode *, struct file *, uint, unsigned long);
+
+
+// routines to convert to and from the old the format
+static int mimd_to_kioc(mimd_t __user *, mraid_mmadp_t *, uioc_t *);
+static int kioc_to_mimd(uioc_t *, mimd_t __user *);
+
+
+// Helper functions
+static int handle_drvrcmd(void __user *, uint8_t, int *);
+static int lld_ioctl(mraid_mmadp_t *, uioc_t *);
+static void ioctl_done(uioc_t *);
+static void lld_timedout(unsigned long);
+static void hinfo_to_cinfo(mraid_hba_info_t *, mcontroller_t *);
+static mraid_mmadp_t *mraid_mm_get_adapter(mimd_t __user *, int *);
+static uioc_t *mraid_mm_alloc_kioc(mraid_mmadp_t *);
+static void mraid_mm_dealloc_kioc(mraid_mmadp_t *, uioc_t *);
+static int mraid_mm_attach_buf(mraid_mmadp_t *, uioc_t *, int);
+static int mraid_mm_setup_dma_pools(mraid_mmadp_t *);
+static void mraid_mm_free_adp_resources(mraid_mmadp_t *);
+static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *);
+
+#ifdef CONFIG_COMPAT
+static int mraid_mm_compat_ioctl(unsigned int, unsigned int, unsigned long,
+               struct file *);
+#endif
+
+MODULE_AUTHOR("LSI Logic Corporation");
+MODULE_DESCRIPTION("LSI Logic Management Module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(LSI_COMMON_MOD_VERSION);
+
+static int dbglevel = CL_ANN;
+module_param_named(dlevel, dbglevel, int, 0);
+MODULE_PARM_DESC(dlevel, "Debug level (default=0)");
+
+EXPORT_SYMBOL(mraid_mm_register_adp);
+EXPORT_SYMBOL(mraid_mm_unregister_adp);
+
+static int majorno;
+static uint32_t drvr_ver       = 0x02200100;
+
+static int adapters_count_g;
+static struct list_head adapters_list_g;
+
+wait_queue_head_t wait_q;
+
+static struct file_operations lsi_fops = {
+       .open   = mraid_mm_open,
+       .ioctl  = mraid_mm_ioctl,
+       .owner  = THIS_MODULE,
+};
+
+/**
+ * mraid_mm_open - open routine for char node interface
+ * @inod       : unused
+ * @filep      : unused
+ *
+ * allow ioctl operations by apps only if they superuser privilege
+ */
+static int
+mraid_mm_open(struct inode *inode, struct file *filep)
+{
+       /*
+        * Only allow superuser to access private ioctl interface
+        */
+       if (!capable(CAP_SYS_ADMIN)) return (-EACCES);
+
+       return 0;
+}
+
+/**
+ * mraid_mm_ioctl - module entry-point for ioctls
+ * @inode      : inode (ignored)
+ * @filep      : file operations pointer (ignored)
+ * @cmd                : ioctl command
+ * @arg                : user ioctl packet
+ */
+static int
+mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
+                                                       unsigned long arg)
+{
+       uioc_t          *kioc;
+       char            signature[EXT_IOCTL_SIGN_SZ]    = {0};
+       int             rval;
+       mraid_mmadp_t   *adp;
+       uint8_t         old_ioctl;
+       int             drvrcmd_rval;
+       void __user *argp = (void __user *)arg;
+
+       /*
+        * Make sure only USCSICMD are issued through this interface.
+        * MIMD application would still fire different command.
+        */
+
+       if ((_IOC_TYPE(cmd) != MEGAIOC_MAGIC) && (cmd != USCSICMD)) {
+               return (-EINVAL);
+       }
+
+       /*
+        * Look for signature to see if this is the new or old ioctl format.
+        */
+       if (copy_from_user(signature, argp, EXT_IOCTL_SIGN_SZ)) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid cmm: copy from usr addr failed\n"));
+               return (-EFAULT);
+       }
+
+       if (memcmp(signature, EXT_IOCTL_SIGN, EXT_IOCTL_SIGN_SZ) == 0)
+               old_ioctl = 0;
+       else
+               old_ioctl = 1;
+
+       /*
+        * At present, we don't support the new ioctl packet
+        */
+       if (!old_ioctl )
+               return (-EINVAL);
+
+       /*
+        * If it is a driver ioctl (as opposed to fw ioctls), then we can
+        * handle the command locally. rval > 0 means it is not a drvr cmd
+        */
+       rval = handle_drvrcmd(argp, old_ioctl, &drvrcmd_rval);
+
+       if (rval < 0)
+               return rval;
+       else if (rval == 0)
+               return drvrcmd_rval;
+
+       rval = 0;
+       if ((adp = mraid_mm_get_adapter(argp, &rval)) == NULL) {
+               return rval;
+       }
+
+       /*
+        * The following call will block till a kioc is available
+        */
+       kioc = mraid_mm_alloc_kioc(adp);
+
+       /*
+        * User sent the old mimd_t ioctl packet. Convert it to uioc_t.
+        */
+       if ((rval = mimd_to_kioc(argp, adp, kioc))) {
+               mraid_mm_dealloc_kioc(adp, kioc);
+               return rval;
+       }
+
+       kioc->done = ioctl_done;
+
+       /*
+        * Issue the IOCTL to the low level driver
+        */
+       if ((rval = lld_ioctl(adp, kioc))) {
+               mraid_mm_dealloc_kioc(adp, kioc);
+               return rval;
+       }
+
+       /*
+        * Convert the kioc back to user space
+        */
+       rval = kioc_to_mimd(kioc, argp);
+
+       /*
+        * Return the kioc to free pool
+        */
+       mraid_mm_dealloc_kioc(adp, kioc);
+
+       return rval;
+}
+
+
+/**
+ * mraid_mm_get_adapter - Returns corresponding adapters for the mimd packet
+ * @umimd      : User space mimd_t ioctl packet
+ * @adapter    : pointer to the adapter (OUT)
+ */
+static mraid_mmadp_t *
+mraid_mm_get_adapter(mimd_t __user *umimd, int *rval)
+{
+       mraid_mmadp_t   *adapter;
+       mimd_t          mimd;
+       uint32_t        adapno;
+       int             iterator;
+
+
+       if (copy_from_user(&mimd, umimd, sizeof(mimd_t))) {
+               *rval = -EFAULT;
+               return NULL;
+       }
+
+       adapno = GETADAP(mimd.ui.fcs.adapno);
+
+       if (adapno >= adapters_count_g) {
+               *rval = -ENODEV;
+               return NULL;
+       }
+
+       adapter = NULL;
+       iterator = 0;
+
+       list_for_each_entry(adapter, &adapters_list_g, list) {
+               if (iterator++ == adapno) break;
+       }
+
+       if (!adapter) {
+               *rval = -ENODEV;
+               return NULL;
+       }
+
+       return adapter;
+}
+
+/*
+ * handle_drvrcmd - This routine checks if the opcode is a driver
+ *                       cmd and if it is, handles it.
+ * @arg                : packet sent by the user app
+ * @old_ioctl  : mimd if 1; uioc otherwise
+ */
+static int
+handle_drvrcmd(void __user *arg, uint8_t old_ioctl, int *rval)
+{
+       mimd_t          __user *umimd;
+       mimd_t          kmimd;
+       uint8_t         opcode;
+       uint8_t         subopcode;
+
+       if (old_ioctl)
+               goto old_packet;
+       else
+               goto new_packet;
+
+new_packet:
+       return (-ENOTSUPP);
+
+old_packet:
+       *rval = 0;
+       umimd = arg;
+
+       if (copy_from_user(&kmimd, umimd, sizeof(mimd_t)))
+               return (-EFAULT);
+
+       opcode          = kmimd.ui.fcs.opcode;
+       subopcode       = kmimd.ui.fcs.subopcode;
+
+       /*
+        * If the opcode is 0x82 and the subopcode is either GET_DRVRVER or
+        * GET_NUMADP, then we can handle. Otherwise we should return 1 to
+        * indicate that we cannot handle this.
+        */
+       if (opcode != 0x82)
+               return 1;
+
+       switch (subopcode) {
+
+       case MEGAIOC_QDRVRVER:
+
+               if (copy_to_user(kmimd.data, &drvr_ver, sizeof(uint32_t)))
+                       return (-EFAULT);
+
+               return 0;
+
+       case MEGAIOC_QNADAP:
+
+               *rval = adapters_count_g;
+
+               if (copy_to_user(kmimd.data, &adapters_count_g,
+                               sizeof(uint32_t)))
+                       return (-EFAULT);
+
+               return 0;
+
+       default:
+               /* cannot handle */
+               return 1;
+       }
+
+       return 0;
+}
+
+
+/**
+ * mimd_to_kioc        - Converter from old to new ioctl format
+ *
+ * @umimd      : user space old MIMD IOCTL
+ * @kioc       : kernel space new format IOCTL
+ *
+ * Routine to convert MIMD interface IOCTL to new interface IOCTL packet. The
+ * new packet is in kernel space so that driver can perform operations on it
+ * freely.
+ */
+
+static int
+mimd_to_kioc(mimd_t __user *umimd, mraid_mmadp_t *adp, uioc_t *kioc)
+{
+       mbox64_t                *mbox64;
+       mbox_t                  *mbox;
+       mraid_passthru_t        *pthru32;
+       uint32_t                adapno;
+       uint8_t                 opcode;
+       uint8_t                 subopcode;
+       mimd_t                  mimd;
+
+       if (copy_from_user(&mimd, umimd, sizeof(mimd_t)))
+               return (-EFAULT);
+
+       /*
+        * Applications are not allowed to send extd pthru
+        */
+       if ((mimd.mbox[0] == MBOXCMD_PASSTHRU64) ||
+                       (mimd.mbox[0] == MBOXCMD_EXTPTHRU))
+               return (-EINVAL);
+
+       opcode          = mimd.ui.fcs.opcode;
+       subopcode       = mimd.ui.fcs.subopcode;
+       adapno          = GETADAP(mimd.ui.fcs.adapno);
+
+       if (adapno >= adapters_count_g)
+               return (-ENODEV);
+
+       kioc->adapno    = adapno;
+       kioc->mb_type   = MBOX_LEGACY;
+       kioc->app_type  = APPTYPE_MIMD;
+
+       switch (opcode) {
+
+       case 0x82:
+
+               if (subopcode == MEGAIOC_QADAPINFO) {
+
+                       kioc->opcode    = GET_ADAP_INFO;
+                       kioc->data_dir  = UIOC_RD;
+                       kioc->xferlen   = sizeof(mraid_hba_info_t);
+
+                       if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen))
+                               return (-ENOMEM);
+               }
+               else {
+                       con_log(CL_ANN, (KERN_WARNING
+                                       "megaraid cmm: Invalid subop\n"));
+                       return (-EINVAL);
+               }
+
+               break;
+
+       case 0x81:
+
+               kioc->opcode            = MBOX_CMD;
+               kioc->xferlen           = mimd.ui.fcs.length;
+               kioc->user_data_len     = kioc->xferlen;
+               kioc->user_data         = mimd.ui.fcs.buffer;
+
+               if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen))
+                       return (-ENOMEM);
+
+               if (mimd.outlen) kioc->data_dir  = UIOC_RD;
+               if (mimd.inlen) kioc->data_dir |= UIOC_WR;
+
+               break;
+
+       case 0x80:
+
+               kioc->opcode            = MBOX_CMD;
+               kioc->xferlen           = (mimd.outlen > mimd.inlen) ?
+                                               mimd.outlen : mimd.inlen;
+               kioc->user_data_len     = kioc->xferlen;
+               kioc->user_data         = mimd.data;
+
+               if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen))
+                       return (-ENOMEM);
+
+               if (mimd.outlen) kioc->data_dir  = UIOC_RD;
+               if (mimd.inlen) kioc->data_dir |= UIOC_WR;
+
+               break;
+
+       default:
+               return (-EINVAL);
+       }
+
+       /*
+        * If driver command, nothing else to do
+        */
+       if (opcode == 0x82)
+               return 0;
+
+       /*
+        * This is a mailbox cmd; copy the mailbox from mimd
+        */
+       mbox64  = (mbox64_t *)((unsigned long)kioc->cmdbuf);
+       mbox    = &mbox64->mbox32;
+       memcpy(mbox, mimd.mbox, 14);
+
+       if (mbox->cmd != MBOXCMD_PASSTHRU) {    // regular DCMD
+
+               mbox->xferaddr  = (uint32_t)kioc->buf_paddr;
+
+               if (kioc->data_dir & UIOC_WR) {
+                       if (copy_from_user(kioc->buf_vaddr, kioc->user_data,
+                                                       kioc->xferlen)) {
+                               return (-EFAULT);
+                       }
+               }
+
+               return 0;
+       }
+
+       /*
+        * This is a regular 32-bit pthru cmd; mbox points to pthru struct.
+        * Just like in above case, the beginning for memblk is treated as
+        * a mailbox. The passthru will begin at next 1K boundary. And the
+        * data will start 1K after that.
+        */
+       pthru32                 = kioc->pthru32;
+       kioc->user_pthru        = &umimd->pthru;
+       mbox->xferaddr          = (uint32_t)kioc->pthru32_h;
+
+       if (copy_from_user(pthru32, kioc->user_pthru,
+                       sizeof(mraid_passthru_t))) {
+               return (-EFAULT);
+       }
+
+       pthru32->dataxferaddr   = kioc->buf_paddr;
+       if (kioc->data_dir & UIOC_WR) {
+               if (copy_from_user(kioc->buf_vaddr, kioc->user_data,
+                                               pthru32->dataxferlen)) {
+                       return (-EFAULT);
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * mraid_mm_attch_buf - Attach a free dma buffer for required size
+ *
+ * @adp                : Adapter softstate
+ * @kioc       : kioc that the buffer needs to be attached to
+ * @xferlen    : required length for buffer
+ *
+ * First we search for a pool with smallest buffer that is >= @xferlen. If
+ * that pool has no free buffer, we will try for the next bigger size. If none
+ * is available, we will try to allocate the smallest buffer that is >=
+ * @xferlen and attach it the pool.
+ */
+static int
+mraid_mm_attach_buf(mraid_mmadp_t *adp, uioc_t *kioc, int xferlen)
+{
+       mm_dmapool_t    *pool;
+       int             right_pool = -1;
+       unsigned long   flags;
+       int             i;
+
+       kioc->pool_index        = -1;
+       kioc->buf_vaddr         = NULL;
+       kioc->buf_paddr         = 0;
+       kioc->free_buf          = 0;
+
+       /*
+        * We need xferlen amount of memory. See if we can get it from our
+        * dma pools. If we don't get exact size, we will try bigger buffer
+        */
+
+       for (i = 0; i < MAX_DMA_POOLS; i++) {
+
+               pool = &adp->dma_pool_list[i];
+
+               if (xferlen > pool->buf_size)
+                       continue;
+
+               if (right_pool == -1)
+                       right_pool = i;
+
+               spin_lock_irqsave(&pool->lock, flags);
+
+               if (!pool->in_use) {
+
+                       pool->in_use            = 1;
+                       kioc->pool_index        = i;
+                       kioc->buf_vaddr         = pool->vaddr;
+                       kioc->buf_paddr         = pool->paddr;
+
+                       spin_unlock_irqrestore(&pool->lock, flags);
+                       return 0;
+               }
+               else {
+                       spin_unlock_irqrestore(&pool->lock, flags);
+                       continue;
+               }
+       }
+
+       /*
+        * If xferlen doesn't match any of our pools, return error
+        */
+       if (right_pool == -1)
+               return -EINVAL;
+
+       /*
+        * We did not get any buffer from the preallocated pool. Let us try
+        * to allocate one new buffer. NOTE: This is a blocking call.
+        */
+       pool = &adp->dma_pool_list[right_pool];
+
+       spin_lock_irqsave(&pool->lock, flags);
+
+       kioc->pool_index        = right_pool;
+       kioc->free_buf          = 1;
+       kioc->buf_vaddr         = pci_pool_alloc(pool->handle, GFP_KERNEL,
+                                                       &kioc->buf_paddr);
+       spin_unlock_irqrestore(&pool->lock, flags);
+
+       if (!kioc->buf_vaddr)
+               return -ENOMEM;
+
+       return 0;
+}
+
+/**
+ * mraid_mm_alloc_kioc - Returns a uioc_t from free list
+ * @adp        : Adapter softstate for this module
+ *
+ * The kioc_semaphore is initialized with number of kioc nodes in the
+ * free kioc pool. If the kioc pool is empty, this function blocks till
+ * a kioc becomes free.
+ */
+static uioc_t *
+mraid_mm_alloc_kioc(mraid_mmadp_t *adp)
+{
+       uioc_t                  *kioc;
+       struct list_head*       head;
+       unsigned long           flags;
+
+       down(&adp->kioc_semaphore);
+
+       spin_lock_irqsave(&adp->kioc_pool_lock, flags);
+
+       head = &adp->kioc_pool;
+
+       if (list_empty(head)) {
+               up(&adp->kioc_semaphore);
+               spin_unlock_irqrestore(&adp->kioc_pool_lock, flags);
+
+               con_log(CL_ANN, ("megaraid cmm: kioc list empty!\n"));
+               return NULL;
+       }
+
+       kioc = list_entry(head->next, uioc_t, list);
+       list_del_init(&kioc->list);
+
+       spin_unlock_irqrestore(&adp->kioc_pool_lock, flags);
+
+       memset((caddr_t)(unsigned long)kioc->cmdbuf, 0, sizeof(mbox64_t));
+       memset((caddr_t) kioc->pthru32, 0, sizeof(mraid_passthru_t));
+
+       kioc->buf_vaddr         = NULL;
+       kioc->buf_paddr         = 0;
+       kioc->pool_index        =-1;
+       kioc->free_buf          = 0;
+       kioc->user_data         = NULL;
+       kioc->user_data_len     = 0;
+       kioc->user_pthru        = NULL;
+
+       return kioc;
+}
+
+/**
+ * mraid_mm_dealloc_kioc - Return kioc to free pool
+ *
+ * @adp                : Adapter softstate
+ * @kioc       : uioc_t node to be returned to free pool
+ */
+static void
+mraid_mm_dealloc_kioc(mraid_mmadp_t *adp, uioc_t *kioc)
+{
+       mm_dmapool_t    *pool;
+       unsigned long   flags;
+
+       pool = &adp->dma_pool_list[kioc->pool_index];
+
+       /* This routine may be called in non-isr context also */
+       spin_lock_irqsave(&pool->lock, flags);
+
+       /*
+        * While attaching the dma buffer, if we didn't get the required
+        * buffer from the pool, we would have allocated it at the run time
+        * and set the free_buf flag. We must free that buffer. Otherwise,
+        * just mark that the buffer is not in use
+        */
+       if (kioc->free_buf == 1)
+               pci_pool_free(pool->handle, kioc->buf_vaddr, kioc->buf_paddr);
+       else
+               pool->in_use = 0;
+
+       spin_unlock_irqrestore(&pool->lock, flags);
+
+       /* Return the kioc to the free pool */
+       spin_lock_irqsave(&adp->kioc_pool_lock, flags);
+       list_add(&kioc->list, &adp->kioc_pool);
+       spin_unlock_irqrestore(&adp->kioc_pool_lock, flags);
+
+       /* increment the free kioc count */
+       up(&adp->kioc_semaphore);
+
+       return;
+}
+
+/**
+ * lld_ioctl - Routine to issue ioctl to low level drvr
+ *
+ * @adp                : The adapter handle
+ * @kioc       : The ioctl packet with kernel addresses
+ */
+static int
+lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc)
+{
+       int                     rval;
+       struct timer_list       timer;
+       struct timer_list       *tp = NULL;
+
+       kioc->status    = -ENODATA;
+       rval            = adp->issue_uioc(adp->drvr_data, kioc, IOCTL_ISSUE);
+
+       if (rval) return rval;
+
+       /*
+        * Start the timer
+        */
+       if (adp->timeout > 0) {
+               tp              = &timer;
+               init_timer(tp);
+
+               tp->function    = lld_timedout;
+               tp->data        = (unsigned long)kioc;
+               tp->expires     = jiffies + adp->timeout * HZ;
+
+               add_timer(tp);
+       }
+
+       /*
+        * Wait till the low level driver completes the ioctl. After this
+        * call, the ioctl either completed successfully or timedout.
+        */
+       wait_event(wait_q, (kioc->status != -ENODATA));
+       if (tp) {
+               del_timer_sync(tp);
+       }
+
+       return kioc->status;
+}
+
+
+/**
+ * ioctl_done - callback from the low level driver
+ *
+ * @kioc       : completed ioctl packet
+ */
+static void
+ioctl_done(uioc_t *kioc)
+{
+       /*
+        * When the kioc returns from driver, make sure it still doesn't
+        * have ENODATA in status. Otherwise, driver will hang on wait_event
+        * forever
+        */
+       if (kioc->status == -ENODATA) {
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid cmm: lld didn't change status!\n"));
+
+               kioc->status = -EINVAL;
+       }
+
+       wake_up(&wait_q);
+}
+
+
+/*
+ * lld_timedout        : callback from the expired timer
+ *
+ * @ptr                : ioctl packet that timed out
+ */
+static void
+lld_timedout(unsigned long ptr)
+{
+       uioc_t *kioc    = (uioc_t *)ptr;
+
+       kioc->status    = -ETIME;
+
+       con_log(CL_ANN, (KERN_WARNING "megaraid cmm: ioctl timed out\n"));
+
+       wake_up(&wait_q);
+}
+
+
+/**
+ * kioc_to_mimd        : Converter from new back to old format
+ *
+ * @kioc       : Kernel space IOCTL packet (successfully issued)
+ * @mimd       : User space MIMD packet
+ */
+static int
+kioc_to_mimd(uioc_t *kioc, mimd_t __user *mimd)
+{
+       mimd_t                  kmimd;
+       uint8_t                 opcode;
+       uint8_t                 subopcode;
+
+       mbox64_t                *mbox64;
+       mraid_passthru_t        __user *upthru32;
+       mraid_passthru_t        *kpthru32;
+       mcontroller_t           cinfo;
+       mraid_hba_info_t        *hinfo;
+
+
+       if (copy_from_user(&kmimd, mimd, sizeof(mimd_t)))
+               return (-EFAULT);
+
+       opcode          = kmimd.ui.fcs.opcode;
+       subopcode       = kmimd.ui.fcs.subopcode;
+
+       if (opcode == 0x82) {
+               switch (subopcode) {
+
+               case MEGAIOC_QADAPINFO:
+
+                       hinfo = (mraid_hba_info_t *)(unsigned long)
+                                       kioc->buf_vaddr;
+
+                       hinfo_to_cinfo(hinfo, &cinfo);
+
+                       if (copy_to_user(kmimd.data, &cinfo, sizeof(cinfo)))
+                               return (-EFAULT);
+
+                       return 0;
+
+               default:
+                       return (-EINVAL);
+               }
+
+               return 0;
+       }
+
+       mbox64 = (mbox64_t *)(unsigned long)kioc->cmdbuf;
+
+       if (kioc->user_pthru) {
+
+               upthru32 = kioc->user_pthru;
+               kpthru32 = kioc->pthru32;
+
+               if (copy_to_user(&upthru32->scsistatus,
+                                       &kpthru32->scsistatus,
+                                       sizeof(uint8_t))) {
+                       return (-EFAULT);
+               }
+       }
+
+       if (kioc->user_data) {
+               if (copy_to_user(kioc->user_data, kioc->buf_vaddr,
+                                       kioc->user_data_len)) {
+                       return (-EFAULT);
+               }
+       }
+
+       if (copy_to_user(&mimd->mbox[17],
+                       &mbox64->mbox32.status, sizeof(uint8_t))) {
+               return (-EFAULT);
+       }
+
+       return 0;
+}
+
+
+/**
+ * hinfo_to_cinfo - Convert new format hba info into old format
+ *
+ * @hinfo      : New format, more comprehensive adapter info
+ * @cinfo      : Old format adapter info to support mimd_t apps
+ */
+static void
+hinfo_to_cinfo(mraid_hba_info_t *hinfo, mcontroller_t *cinfo)
+{
+       if (!hinfo || !cinfo)
+               return;
+
+       cinfo->base             = hinfo->baseport;
+       cinfo->irq              = hinfo->irq;
+       cinfo->numldrv          = hinfo->num_ldrv;
+       cinfo->pcibus           = hinfo->pci_bus;
+       cinfo->pcidev           = hinfo->pci_slot;
+       cinfo->pcifun           = PCI_FUNC(hinfo->pci_dev_fn);
+       cinfo->pciid            = hinfo->pci_device_id;
+       cinfo->pcivendor        = hinfo->pci_vendor_id;
+       cinfo->pcislot          = hinfo->pci_slot;
+       cinfo->uid              = hinfo->unique_id;
+}
+
+
+/*
+ * mraid_mm_register_adp - Registration routine for low level drvrs
+ *
+ * @adp        : Adapter objejct
+ */
+int
+mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
+{
+       mraid_mmadp_t   *adapter;
+       mbox64_t        *mbox_list;
+       uioc_t          *kioc;
+       uint32_t        rval;
+       int             i;
+
+
+       if (lld_adp->drvr_type != DRVRTYPE_MBOX)
+               return (-EINVAL);
+
+       adapter = kmalloc(sizeof(mraid_mmadp_t), GFP_KERNEL);
+
+       if (!adapter) {
+               rval = -ENOMEM;
+               goto memalloc_error;
+       }
+
+       memset(adapter, 0, sizeof(mraid_mmadp_t));
+
+       adapter->unique_id      = lld_adp->unique_id;
+       adapter->drvr_type      = lld_adp->drvr_type;
+       adapter->drvr_data      = lld_adp->drvr_data;
+       adapter->pdev           = lld_adp->pdev;
+       adapter->issue_uioc     = lld_adp->issue_uioc;
+       adapter->timeout        = lld_adp->timeout;
+       adapter->max_kioc       = lld_adp->max_kioc;
+
+       /*
+        * Allocate single blocks of memory for all required kiocs,
+        * mailboxes and passthru structures.
+        */
+       adapter->kioc_list      = kmalloc(sizeof(uioc_t) * lld_adp->max_kioc,
+                                               GFP_KERNEL);
+       adapter->mbox_list      = kmalloc(sizeof(mbox64_t) * lld_adp->max_kioc,
+                                               GFP_KERNEL);
+       adapter->pthru_dma_pool = pci_pool_create("megaraid mm pthru pool",
+                                               adapter->pdev,
+                                               sizeof(mraid_passthru_t),
+                                               16, 0);
+
+       if (!adapter->kioc_list || !adapter->mbox_list ||
+                       !adapter->pthru_dma_pool) {
+
+               con_log(CL_ANN, (KERN_WARNING
+                       "megaraid cmm: out of memory, %s %d\n", __FUNCTION__,
+                       __LINE__));
+
+               rval = (-ENOMEM);
+
+               goto memalloc_error;
+       }
+
+       /*
+        * Slice kioc_list and make a kioc_pool with the individiual kiocs
+        */
+       INIT_LIST_HEAD(&adapter->kioc_pool);
+       spin_lock_init(&adapter->kioc_pool_lock);
+       sema_init(&adapter->kioc_semaphore, lld_adp->max_kioc);
+
+       mbox_list       = (mbox64_t *)adapter->mbox_list;
+
+       for (i = 0; i < lld_adp->max_kioc; i++) {
+
+               kioc            = adapter->kioc_list + i;
+               kioc->cmdbuf    = (uint64_t)(unsigned long)(mbox_list + i);
+               kioc->pthru32   = pci_pool_alloc(adapter->pthru_dma_pool,
+                                               GFP_KERNEL, &kioc->pthru32_h);
+
+               if (!kioc->pthru32) {
+
+                       con_log(CL_ANN, (KERN_WARNING
+                               "megaraid cmm: out of memory, %s %d\n",
+                                       __FUNCTION__, __LINE__));
+
+                       rval = (-ENOMEM);
+
+                       goto pthru_dma_pool_error;
+               }
+
+               list_add_tail(&kioc->list, &adapter->kioc_pool);
+       }
+
+       // Setup the dma pools for data buffers
+       if ((rval = mraid_mm_setup_dma_pools(adapter)) != 0) {
+               goto dma_pool_error;
+       }
+
+       list_add_tail(&adapter->list, &adapters_list_g);
+
+       adapters_count_g++;
+
+       return 0;
+
+dma_pool_error:
+       /* Do nothing */
+
+pthru_dma_pool_error:
+
+       for (i = 0; i < lld_adp->max_kioc; i++) {
+               kioc = adapter->kioc_list + i;
+               if (kioc->pthru32) {
+                       pci_pool_free(adapter->pthru_dma_pool, kioc->pthru32,
+                               kioc->pthru32_h);
+               }
+       }
+
+memalloc_error:
+
+       if (adapter->kioc_list)
+               kfree(adapter->kioc_list);
+
+       if (adapter->mbox_list)
+               kfree(adapter->mbox_list);
+
+       if (adapter->pthru_dma_pool)
+               pci_pool_destroy(adapter->pthru_dma_pool);
+
+       if (adapter)
+               kfree(adapter);
+
+       return rval;
+}
+
+/**
+ * mraid_mm_setup_dma_pools - Set up dma buffer pools per adapter
+ *
+ * @adp        : Adapter softstate
+ *
+ * We maintain a pool of dma buffers per each adapter. Each pool has one
+ * buffer. E.g, we may have 5 dma pools - one each for 4k, 8k ... 64k buffers.
+ * We have just one 4k buffer in 4k pool, one 8k buffer in 8k pool etc. We
+ * dont' want to waste too much memory by allocating more buffers per each
+ * pool.
+ */
+static int
+mraid_mm_setup_dma_pools(mraid_mmadp_t *adp)
+{
+       mm_dmapool_t    *pool;
+       int             bufsize;
+       int             i;
+
+       /*
+        * Create MAX_DMA_POOLS number of pools
+        */
+       bufsize = MRAID_MM_INIT_BUFF_SIZE;
+
+       for (i = 0; i < MAX_DMA_POOLS; i++){
+
+               pool = &adp->dma_pool_list[i];
+
+               pool->buf_size = bufsize;
+               spin_lock_init(&pool->lock);
+
+               pool->handle = pci_pool_create("megaraid mm data buffer",
+                                               adp->pdev, bufsize, 16, 0);
+
+               if (!pool->handle) {
+                       goto dma_pool_setup_error;
+               }
+
+               pool->vaddr = pci_pool_alloc(pool->handle, GFP_KERNEL,
+                                                       &pool->paddr);
+
+               if (!pool->vaddr)
+                       goto dma_pool_setup_error;
+
+               bufsize = bufsize * 2;
+       }
+
+       return 0;
+
+dma_pool_setup_error:
+
+       mraid_mm_teardown_dma_pools(adp);
+       return (-ENOMEM);
+}
+
+
+/*
+ * mraid_mm_unregister_adp - Unregister routine for low level drivers
+ *                               Assume no outstanding ioctls to llds.
+ *
+ * @unique_id  : UID of the adpater
+ */
+int
+mraid_mm_unregister_adp(uint32_t unique_id)
+{
+       mraid_mmadp_t   *adapter;
+       mraid_mmadp_t   *tmp;
+
+       list_for_each_entry_safe(adapter, tmp, &adapters_list_g, list) {
+
+
+               if (adapter->unique_id == unique_id) {
+
+                       adapters_count_g--;
+
+                       list_del_init(&adapter->list);
+
+                       mraid_mm_free_adp_resources(adapter);
+
+                       kfree(adapter);
+
+                       con_log(CL_ANN, (
+                               "megaraid cmm: Unregistered one adapter:%#x\n",
+                               unique_id));
+
+                       return 0;
+               }
+       }
+
+       return (-ENODEV);
+}
+
+/**
+ * mraid_mm_free_adp_resources - Free adapter softstate
+ *
+ * @adp        : Adapter softstate
+ */
+static void
+mraid_mm_free_adp_resources(mraid_mmadp_t *adp)
+{
+       uioc_t  *kioc;
+       int     i;
+
+       mraid_mm_teardown_dma_pools(adp);
+
+       for (i = 0; i < adp->max_kioc; i++) {
+
+               kioc = adp->kioc_list + i;
+
+               pci_pool_free(adp->pthru_dma_pool, kioc->pthru32,
+                               kioc->pthru32_h);
+       }
+
+       kfree(adp->kioc_list);
+
+       kfree(adp->mbox_list);
+
+       pci_pool_destroy(adp->pthru_dma_pool);
+
+
+       return;
+}
+
+
+/**
+ * mraid_mm_teardown_dma_pools - Free all per adapter dma buffers
+ *
+ * @adp        : Adapter softstate
+ */
+static void
+mraid_mm_teardown_dma_pools(mraid_mmadp_t *adp)
+{
+       int             i;
+       mm_dmapool_t    *pool;
+
+       for (i = 0; i < MAX_DMA_POOLS; i++) {
+
+               pool = &adp->dma_pool_list[i];
+
+               if (pool->handle) {
+
+                       if (pool->vaddr)
+                               pci_pool_free(pool->handle, pool->vaddr,
+                                                       pool->paddr);
+
+                       pci_pool_destroy(pool->handle);
+                       pool->handle = NULL;
+               }
+       }
+
+       return;
+}
+
+/**
+ * mraid_mm_init       : Module entry point
+ */
+static int __init
+mraid_mm_init(void)
+{
+       // Announce the driver version
+       con_log(CL_ANN, (KERN_INFO "megaraid cmm: %s %s\n",
+               LSI_COMMON_MOD_VERSION, LSI_COMMON_MOD_EXT_VERSION));
+
+       majorno = register_chrdev(0, "megadev", &lsi_fops);
+
+       if (majorno < 0) {
+               con_log(CL_ANN, ("megaraid cmm: cannot get major\n"));
+               return majorno;
+       }
+
+       init_waitqueue_head(&wait_q);
+
+       INIT_LIST_HEAD(&adapters_list_g);
+
+#ifdef CONFIG_COMPAT
+       register_ioctl32_conversion(MEGAIOCCMD, mraid_mm_compat_ioctl);
+#endif
+
+       return 0;
+}
+
+
+/**
+ * mraid_mm_compat_ioctl       : 32bit to 64bit ioctl conversion routine
+ */
+#ifdef CONFIG_COMPAT
+static int
+mraid_mm_compat_ioctl(unsigned int fd, unsigned int cmd,
+                       unsigned long arg, struct file *filep)
+{
+       struct inode *inode = filep->f_dentry->d_inode;
+
+       return mraid_mm_ioctl(inode, filep, cmd, arg);
+}
+#endif
+
+/**
+ * mraid_mm_exit       : Module exit point
+ */
+static void __exit
+mraid_mm_exit(void)
+{
+       con_log(CL_DLEVEL1 , ("exiting common mod\n"));
+
+       unregister_chrdev(majorno, "megadev");
+       unregister_ioctl32_conversion(MEGAIOCCMD);
+}
+
+module_init(mraid_mm_init);
+module_exit(mraid_mm_exit);
+
+/* vi: set ts=8 sw=8 tw=78: */
diff --git a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h
new file mode 100644 (file)
index 0000000..effc23a
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *
+ *                     Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic Corporation.
+ *
+ *        This program is free software; you can redistribute it and/or
+ *        modify it under the terms of the GNU General Public License
+ *        as published by the Free Software Foundation; either version
+ *        2 of the License, or (at your option) any later version.
+ *
+ * FILE                : megaraid_mm.h
+ */
+
+#ifndef MEGARAID_MM_H
+#define MEGARAID_MM_H
+
+#include <linux/spinlock.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/ioctl32.h>
+
+#include "mbox_defs.h"
+#include "megaraid_ioctl.h"
+
+
+#define LSI_COMMON_MOD_VERSION "2.20.2.0"
+#define LSI_COMMON_MOD_EXT_VERSION     \
+               "(Release Date: Thu Aug 19 09:58:33 EDT 2004)"
+
+
+#define LSI_DBGLVL                     dbglevel
+
+// The smallest dma pool
+#define MRAID_MM_INIT_BUFF_SIZE                4096
+
+/**
+ * mimd_t      : Old style ioctl packet structure (deprecated)
+ *
+ * @inlen      :
+ * @outlen     :
+ * @fca                :
+ * @opcode     :
+ * @subopcode  :
+ * @adapno     :
+ * @buffer     :
+ * @pad                :
+ * @length     :
+ * @mbox       :
+ * @pthru      :
+ * @data       :
+ * @pad                :
+ *
+ * Note                : This structure is DEPRECATED. New applications must use
+ *             : uioc_t structure instead. All new hba drivers use the new
+ *             : format. If we get this mimd packet, we will convert it into
+ *             : new uioc_t format and send it to the hba drivers.
+ */
+
+typedef struct mimd {
+
+       uint32_t inlen;
+       uint32_t outlen;
+
+       union {
+               uint8_t fca[16];
+               struct {
+                       uint8_t opcode;
+                       uint8_t subopcode;
+                       uint16_t adapno;
+#if BITS_PER_LONG == 32
+                       uint8_t __user *buffer;
+                       uint8_t pad[4];
+#endif
+#if BITS_PER_LONG == 64
+                       uint8_t __user *buffer;
+#endif
+                       uint32_t length;
+               } __attribute__ ((packed)) fcs;
+       } __attribute__ ((packed)) ui;
+
+       uint8_t mbox[18];               /* 16 bytes + 2 status bytes */
+       mraid_passthru_t pthru;
+
+#if BITS_PER_LONG == 32
+       char __user *data;              /* buffer <= 4096 for 0x80 commands */
+       char pad[4];
+#endif
+#if BITS_PER_LONG == 64
+       char __user *data;
+#endif
+
+} __attribute__ ((packed))mimd_t;
+
+#endif // MEGARAID_MM_H
+
+// vi: set ts=8 sw=8 tw=78:
index 29248d6..aef957b 100644 (file)
  *  If you do not delete the provisions above, a recipient may use your
  *  version of this file under either the OSL or the GPL.
  *
+ *  0.03
+ *     - Fixed a bug where the hotplug handlers for non-CK804/MCP04 were using
+ *       mmio_base, which is only set for the CK804/MCP04 case.
+ *
  *  0.02
  *     - Added support for CK804 SATA controller.
  *
 #include <linux/libata.h>
 
 #define DRV_NAME                       "sata_nv"
-#define DRV_VERSION                    "0.02"
+#define DRV_VERSION                    "0.03"
 
 #define NV_PORTS                       2
 #define NV_PIO_MASK                    0x1f
+#define NV_MWDMA_MASK                  0x07
 #define NV_UDMA_MASK                   0x7f
-#define NV_PORT0_BMDMA_REG_OFFSET      0x00
-#define NV_PORT1_BMDMA_REG_OFFSET      0x08
 #define NV_PORT0_SCR_REG_OFFSET                0x00
 #define NV_PORT1_SCR_REG_OFFSET                0x40
 
@@ -177,11 +180,12 @@ static struct pci_driver nv_pci_driver = {
 static Scsi_Host_Template nv_sht = {
        .module                 = THIS_MODULE,
        .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
        .queuecommand           = ata_scsi_queuecmd,
        .eh_strategy_handler    = ata_scsi_error,
        .can_queue              = ATA_DEF_QUEUE,
        .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = ATA_MAX_PRD,
+       .sg_tablesize           = LIBATA_MAX_PRD,
        .max_sectors            = ATA_MAX_SECTORS,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        .emulated               = ATA_SHT_EMULATED,
@@ -194,13 +198,14 @@ static Scsi_Host_Template nv_sht = {
 
 static struct ata_port_operations nv_ops = {
        .port_disable           = ata_port_disable,
-       .tf_load                = ata_tf_load_pio,
-       .tf_read                = ata_tf_read_pio,
-       .exec_command           = ata_exec_command_pio,
-       .check_status           = ata_check_status_pio,
+       .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,
        .phy_reset              = sata_phy_reset,
-       .bmdma_setup            = ata_bmdma_setup_pio,
-       .bmdma_start            = ata_bmdma_start_pio,
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
        .qc_prep                = ata_qc_prep,
        .qc_issue               = ata_qc_issue_prot,
        .eng_timeout            = ata_eng_timeout,
@@ -213,6 +218,18 @@ static struct ata_port_operations nv_ops = {
        .host_stop              = nv_host_stop,
 };
 
+static struct ata_port_info nv_port_info = {
+       .sht            = &nv_sht,
+       .host_flags     = ATA_FLAG_SATA |
+                         ATA_FLAG_SATA_RESET |
+                         ATA_FLAG_SRST |
+                         ATA_FLAG_NO_LEGACY,
+       .pio_mask       = NV_PIO_MASK,
+       .mwdma_mask     = NV_MWDMA_MASK,
+       .udma_mask      = NV_UDMA_MASK,
+       .port_ops       = &nv_ops,
+};
+
 MODULE_AUTHOR("NVIDIA");
 MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
 MODULE_LICENSE("GPL");
@@ -293,6 +310,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int printed_version = 0;
        struct nv_host *host;
+       struct ata_port_info *ppi;
        struct ata_probe_ent *probe_ent = NULL;
        int rc;
 
@@ -314,7 +332,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                goto err_out_regions;
 
-       probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+       ppi = &nv_port_info;
+       probe_ent = ata_pci_init_native_mode(pdev, &ppi);
        if (!probe_ent) {
                rc = -ENOMEM;
                goto err_out_regions;
@@ -328,39 +347,6 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 
        host->host_desc = &nv_device_tbl[ent->driver_data];
 
-       memset(probe_ent, 0, sizeof(*probe_ent));
-       INIT_LIST_HEAD(&probe_ent->node);
-
-       probe_ent->pdev = pdev;
-       probe_ent->sht = &nv_sht;
-       probe_ent->host_flags = ATA_FLAG_SATA |
-                               ATA_FLAG_SATA_RESET |
-                               ATA_FLAG_SRST |
-                               ATA_FLAG_NO_LEGACY;
-
-       probe_ent->port_ops = &nv_ops;
-       probe_ent->n_ports = NV_PORTS;
-       probe_ent->irq = pdev->irq;
-       probe_ent->irq_flags = SA_SHIRQ;
-       probe_ent->pio_mask = NV_PIO_MASK;
-       probe_ent->udma_mask = NV_UDMA_MASK;
-
-       probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-       ata_std_ports(&probe_ent->port[0]);
-       probe_ent->port[0].altstatus_addr =
-       probe_ent->port[0].ctl_addr =
-               pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-       probe_ent->port[0].bmdma_addr =
-               pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET;
-
-       probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-       ata_std_ports(&probe_ent->port[1]);
-       probe_ent->port[1].altstatus_addr =
-       probe_ent->port[1].ctl_addr =
-               pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-       probe_ent->port[1].bmdma_addr =
-               pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET;
-
        probe_ent->private_data = host;
 
        if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
@@ -369,7 +355,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5),
                                pci_resource_len(pdev, 5));
                if (probe_ent->mmio_base == NULL)
-                       goto err_out_free_ent;
+                       goto err_out_iounmap;
 
                base = (unsigned long)probe_ent->mmio_base;
 
@@ -393,12 +379,16 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 
        rc = ata_device_add(probe_ent);
        if (rc != NV_PORTS)
-               goto err_out_free_ent;
+               goto err_out_iounmap;
 
        kfree(probe_ent);
 
        return 0;
 
+err_out_iounmap:
+       if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
+               iounmap(probe_ent->mmio_base);
+
 err_out_free_ent:
        kfree(probe_ent);
 
@@ -415,33 +405,33 @@ static void nv_enable_hotplug(struct ata_probe_ent *probe_ent)
        u8 intr_mask;
 
        outb(NV_INT_STATUS_HOTPLUG,
-               (unsigned long)probe_ent->mmio_base + NV_INT_STATUS);
+               probe_ent->port[0].scr_addr + NV_INT_STATUS);
 
-       intr_mask = inb((unsigned long)probe_ent->mmio_base + NV_INT_ENABLE);
+       intr_mask = inb(probe_ent->port[0].scr_addr + NV_INT_ENABLE);
        intr_mask |= NV_INT_ENABLE_HOTPLUG;
 
-       outb(intr_mask, (unsigned long)probe_ent->mmio_base + NV_INT_ENABLE);
+       outb(intr_mask, probe_ent->port[0].scr_addr + NV_INT_ENABLE);
 }
 
 static void nv_disable_hotplug(struct ata_host_set *host_set)
 {
        u8 intr_mask;
 
-       intr_mask = inb((unsigned long)host_set->mmio_base + NV_INT_ENABLE);
+       intr_mask = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
 
        intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
 
-       outb(intr_mask, (unsigned long)host_set->mmio_base + NV_INT_ENABLE);
+       outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
 }
 
 static void nv_check_hotplug(struct ata_host_set *host_set)
 {
        u8 intr_status;
 
-       intr_status = inb((unsigned long)host_set->mmio_base + NV_INT_STATUS);
+       intr_status = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
 
        // Clear interrupt status.
-       outb(0xff, (unsigned long)host_set->mmio_base + NV_INT_STATUS);
+       outb(0xff, host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
 
        if (intr_status & NV_INT_STATUS_HOTPLUG) {
                if (intr_status & NV_INT_STATUS_PDEV_ADDED)
index b54fd87..8da7614 100644 (file)
@@ -146,8 +146,6 @@ struct pdc_host_priv {
 
 
 static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static void pdc20621_dma_setup(struct ata_queued_cmd *qc);
-static void pdc20621_dma_start(struct ata_queued_cmd *qc);
 static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
 static void pdc_eng_timeout(struct ata_port *ap);
 static void pdc_20621_phy_reset (struct ata_port *ap);
@@ -157,8 +155,6 @@ static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc20621_host_stop(struct ata_host_set *host_set);
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc, int have_err);
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
 static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, 
@@ -172,11 +168,13 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
 static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, 
                                 void *psource, u32 offset, u32 size);
 static void pdc20621_irq_clear(struct ata_port *ap);
+static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
 
 
 static Scsi_Host_Template pdc_sata_sht = {
        .module                 = THIS_MODULE,
        .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
        .queuecommand           = ata_scsi_queuecmd,
        .eh_strategy_handler    = ata_scsi_error,
        .can_queue              = ATA_DEF_QUEUE,
@@ -195,14 +193,13 @@ static Scsi_Host_Template pdc_sata_sht = {
 static struct ata_port_operations pdc_20621_ops = {
        .port_disable           = ata_port_disable,
        .tf_load                = pdc_tf_load_mmio,
-       .tf_read                = ata_tf_read_mmio,
-       .check_status           = ata_check_status_mmio,
+       .tf_read                = ata_tf_read,
+       .check_status           = ata_check_status,
        .exec_command           = pdc_exec_command_mmio,
+       .dev_select             = ata_std_dev_select,
        .phy_reset              = pdc_20621_phy_reset,
-       .bmdma_setup            = pdc20621_dma_setup,
-       .bmdma_start            = pdc20621_dma_start,
        .qc_prep                = pdc20621_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
+       .qc_issue               = pdc20621_qc_issue_prot,
        .eng_timeout            = pdc_eng_timeout,
        .irq_handler            = pdc20621_interrupt,
        .irq_clear              = pdc20621_irq_clear,
@@ -217,7 +214,8 @@ static struct ata_port_info pdc_port_info[] = {
                .sht            = &pdc_sata_sht,
                .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-               .pio_mask       = 0x03, /* pio3-4 */
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
                .port_ops       = &pdc_20621_ops,
        },
@@ -377,7 +375,10 @@ static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
 
        /* dimm dma S/G, and next-pkt */
        dw = i >> 2;
-       buf32[dw] = cpu_to_le32(dimm_sg);
+       if (tf->protocol == ATA_PROT_NODATA)
+               buf32[dw] = 0;
+       else
+               buf32[dw] = cpu_to_le32(dimm_sg);
        buf32[dw + 1] = 0;
        i += 8;
 
@@ -437,7 +438,7 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
                buf32[dw + 3]);
 }
 
-static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
+static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
 {
        struct scatterlist *sg = qc->sg;
        struct ata_port *ap = qc->ap;
@@ -449,8 +450,7 @@ static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
        unsigned int i, last, idx, total_len = 0, sgt_len;
        u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
 
-       if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-               return;
+       assert(qc->flags & ATA_QCFLAG_DMAMAP);
 
        VPRINTK("ata%u: ENTER\n", ap->id);
 
@@ -501,6 +501,56 @@ static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
        VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
 }
 
+static void pdc20621_nodata_prep(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct pdc_port_priv *pp = ap->private_data;
+       void *mmio = ap->host_set->mmio_base;
+       struct pdc_host_priv *hpriv = ap->host_set->private_data;
+       void *dimm_mmio = hpriv->dimm_mmio;
+       unsigned int portno = ap->port_no;
+       unsigned int i;
+
+       VPRINTK("ata%u: ENTER\n", ap->id);
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
+
+       if (qc->tf.flags & ATA_TFLAG_LBA48)
+               i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
+       else
+               i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
+
+       pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
+
+       /* copy three S/G tables and two packets to DIMM MMIO window */
+       memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
+                   &pp->dimm_buf, PDC_DIMM_HEADER_SZ);
+
+       /* force host FIFO dump */
+       writel(0x00000001, mmio + PDC_20621_GENERAL_CTL);
+
+       readl(dimm_mmio);       /* MMIO PCI posting flush */
+
+       VPRINTK("ata pkt buf ofs %u, mmio copied\n", i);
+}
+
+static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
+{
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+               pdc20621_dma_prep(qc);
+               break;
+       case ATA_PROT_NODATA:
+               pdc20621_nodata_prep(qc);
+               break;
+       default:
+               break;
+       }
+}
+
 static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
                                 unsigned int seq,
                                 u32 pkt_ofs)
@@ -576,13 +626,7 @@ static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
 static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { }
 #endif /* ATA_VERBOSE_DEBUG */
 
-static void pdc20621_dma_setup(struct ata_queued_cmd *qc)
-{
-       /* nothing for now.  later, we will call standard
-        * code in libata-core for ATAPI here */
-}
-
-static void pdc20621_dma_start(struct ata_queued_cmd *qc)
+static void pdc20621_packet_start(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct ata_host_set *host_set = ap->host_set;
@@ -590,24 +634,21 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc)
        void *mmio = host_set->mmio_base;
        unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
        u8 seq = (u8) (port_no + 1);
-       unsigned int doing_hdma = 0, port_ofs;
+       unsigned int port_ofs;
 
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
 
        VPRINTK("ata%u: ENTER\n", ap->id);
 
+       wmb();                  /* flush PRD, pkt writes */
+
        port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
 
        /* if writing, we (1) DMA to DIMM, then (2) do ATA command */
-       if (rw) {
-               doing_hdma = 1;
+       if (rw && qc->tf.protocol == ATA_PROT_DMA) {
                seq += 4;
-       }
-
-       wmb();                  /* flush PRD, pkt writes */
 
-       if (doing_hdma) {
                pdc20621_dump_hdma(qc);
                pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT);
                VPRINTK("queued ofs 0x%x (%u), seq %u\n",
@@ -628,6 +669,25 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc)
        }
 }
 
+static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+       case ATA_PROT_NODATA:
+               pdc20621_packet_start(qc);
+               return 0;
+
+       case ATA_PROT_ATAPI_DMA:
+               BUG();
+               break;
+
+       default:
+               break;
+       }
+
+       return ata_qc_issue_prot(qc);
+}
+
 static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc,
                                          unsigned int doing_hdma,
@@ -648,7 +708,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                if (doing_hdma) {
                        VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-                       pdc_dma_complete(ap, qc, 0);
+                       /* get drive status; clear intr; complete txn */
+                       ata_qc_complete(qc, ata_wait_idle(ap));
                        pdc20621_pop_hdma(qc);
                }
 
@@ -685,7 +746,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                else {
                        VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
                                readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-                       pdc_dma_complete(ap, qc, 0);
+                       /* get drive status; clear intr; complete txn */
+                       ata_qc_complete(qc, ata_wait_idle(ap));
                        pdc20621_pop_hdma(qc);
                }
                handled = 1;
@@ -779,16 +841,6 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
        return IRQ_RETVAL(handled);
 }
 
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc,
-                                    int have_err)
-{
-       u8 err_bit = have_err ? ATA_ERR : 0;
-
-       /* get drive status; clear intr; complete txn */
-       ata_qc_complete(qc, ata_wait_idle(ap) | err_bit);
-}
-
 static void pdc_eng_timeout(struct ata_port *ap)
 {
        u8 drv_stat;
@@ -813,17 +865,9 @@ static void pdc_eng_timeout(struct ata_port *ap)
 
        switch (qc->tf.protocol) {
        case ATA_PROT_DMA:
-               printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
-               ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
-               break;
-
        case ATA_PROT_NODATA:
-               drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-
-               printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
-                      ap->id, qc->tf.command, drv_stat);
-
-               ata_qc_complete(qc, drv_stat);
+               printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+               ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
                break;
 
        default:
@@ -842,15 +886,17 @@ out:
 
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-       if (tf->protocol != ATA_PROT_DMA)
-               ata_tf_load_mmio(ap, tf);
+       WARN_ON (tf->protocol == ATA_PROT_DMA ||
+                tf->protocol == ATA_PROT_NODATA);
+       ata_tf_load(ap, tf);
 }
 
 
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-       if (tf->protocol != ATA_PROT_DMA)
-               ata_exec_command_mmio(ap, tf);
+       WARN_ON (tf->protocol == ATA_PROT_DMA ||
+                tf->protocol == ATA_PROT_NODATA);
+       ata_exec_command(ap, tf);
 }
 
 
@@ -1384,6 +1430,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
        probe_ent->sht          = pdc_port_info[board_idx].sht;
        probe_ent->host_flags   = pdc_port_info[board_idx].host_flags;
        probe_ent->pio_mask     = pdc_port_info[board_idx].pio_mask;
+       probe_ent->mwdma_mask   = pdc_port_info[board_idx].mwdma_mask;
        probe_ent->udma_mask    = pdc_port_info[board_idx].udma_mask;
        probe_ent->port_ops     = pdc_port_info[board_idx].port_ops;
 
@@ -1394,21 +1441,11 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
        probe_ent->private_data = hpriv;
        base += PDC_CHIP0_OFS;
 
+       probe_ent->n_ports = 4;
        pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
        pdc_sata_setup_port(&probe_ent->port[1], base + 0x280);
-
-       /* notice 4-port boards */
-       switch (board_idx) {
-       case board_20621:
-                       probe_ent->n_ports = 4;
-
-               pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
-               pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
-               break;
-       default:
-               BUG();
-               break;
-       }
+       pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
+       pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
 
        pci_set_master(pdev);
 
index 1241104..09f861a 100644 (file)
@@ -53,6 +53,9 @@
 #ifndef SYM_DEFS_H
 #define SYM_DEFS_H
 
+#define SYM_VERSION "2.1.18j"
+#define SYM_DRIVER_NAME        "sym-" SYM_VERSION
+
 /*
  *  Vendor.
  */
index 2223831..0d9d1b4 100644 (file)
@@ -142,13 +142,6 @@ m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m)
        return b;
 }
 
-/*
- *  Driver host data structure.
- */
-struct host_data {
-       struct sym_hcb *ncb;
-};
-
 /*
  *  Used by the eh thread to wait for command completion.
  *  It is allocated on the eh thread stack.
@@ -220,47 +213,12 @@ static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
        return use_sg;
 }
 
-static void __sync_scsi_data_for_cpu(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-       int dma_dir = cmd->sc_data_direction;
-
-       switch(SYM_UCMD_PTR(cmd)->data_mapped) {
-       case 2:
-               pci_dma_sync_sg_for_cpu(pdev, cmd->buffer, cmd->use_sg, dma_dir);
-               break;
-       case 1:
-               pci_dma_sync_single_for_cpu(pdev, SYM_UCMD_PTR(cmd)->data_mapping,
-                                           cmd->request_bufflen, dma_dir);
-               break;
-       }
-}
-
-static void __sync_scsi_data_for_device(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-       int dma_dir = cmd->sc_data_direction;
-
-       switch(SYM_UCMD_PTR(cmd)->data_mapped) {
-       case 2:
-               pci_dma_sync_sg_for_device(pdev, cmd->buffer, cmd->use_sg, dma_dir);
-               break;
-       case 1:
-               pci_dma_sync_single_for_device(pdev, SYM_UCMD_PTR(cmd)->data_mapping,
-                                              cmd->request_bufflen, dma_dir);
-               break;
-       }
-}
-
 #define unmap_scsi_data(np, cmd)       \
                __unmap_scsi_data(np->s.device, cmd)
 #define map_scsi_single_data(np, cmd)  \
                __map_scsi_single_data(np->s.device, cmd)
 #define map_scsi_sg_data(np, cmd)      \
                __map_scsi_sg_data(np->s.device, cmd)
-#define sync_scsi_data_for_cpu(np, cmd)                \
-               __sync_scsi_data_for_cpu(np->s.device, cmd)
-#define sync_scsi_data_for_device(np, cmd)             \
-               __sync_scsi_data_for_device(np->s.device, cmd)
-
 /*
  *  Complete a pending CAM CCB.
  */
@@ -416,27 +374,6 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
 }
 
 
-/*
- *  Called on successfull INQUIRY response.
- */
-void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid)
-{
-       int retv;
-
-       if (!cmd || cmd->use_sg)
-               return;
-
-       sync_scsi_data_for_cpu(np, cmd);
-       retv = __sym_sniff_inquiry(np, cmd->device->id, cmd->device->lun,
-                                  (u_char *) cmd->request_buffer,
-                                  cmd->request_bufflen - resid);
-       sync_scsi_data_for_device(np, cmd);
-       if (retv < 0)
-               return;
-       else if (retv)
-               sym_update_trans_settings(np, &np->target[cmd->device->id]);
-}
-
 /*
  *  Build the scatter/gather array for an I/O.
  */
@@ -730,14 +667,15 @@ void sym_log_bus_error(struct sym_hcb *np)
  */
 static void sym_requeue_awaiting_cmds(struct sym_hcb *np)
 {
-       struct scsi_cmnd *cmd;
-       struct sym_ucmd *ucp = SYM_UCMD_PTR(cmd);
+       struct sym_ucmd *ucp;
        SYM_QUEHEAD tmp_cmdq;
        int sts;
 
        sym_que_move(&np->s.wait_cmdq, &tmp_cmdq);
 
        while ((ucp = (struct sym_ucmd *) sym_remque_head(&tmp_cmdq)) != 0) {
+               struct scsi_cmnd *cmd;
+
                sym_insque_tail(&ucp->link_cmdq, &np->s.busy_cmdq);
                cmd = SYM_SCMD_PTR(ucp);
                sts = sym_queue_command(np, cmd);
@@ -1118,12 +1056,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *device)
 
        np = ((struct host_data *) host->hostdata)->ncb;
        tp = &np->target[device->id];
-
-       /*
-        *  Get user settings for transfer parameters.
-        */
-       tp->inq_byte7_valid = (INQ7_SYNC|INQ7_WIDE16);
-       sym_update_trans_settings(np, tp);
+       tp->sdev = device;
 
        /*
         *  Allocate the LCB if not yet.
@@ -2283,6 +2216,7 @@ static int sym_detach(struct sym_hcb *np)
 }
 
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(SYM_VERSION);
 
 /*
  * Driver host template.
@@ -2383,13 +2317,6 @@ static void sym2_set_offset(struct scsi_device *sdev, int offset)
        struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
        struct sym_tcb *tp = &np->target[sdev->id];
 
-       if (tp->tinfo.curr.options & PPR_OPT_DT) {
-               if (offset > np->maxoffs_dt)
-                       offset = np->maxoffs_dt;
-       } else {
-               if (offset > np->maxoffs)
-                       offset = np->maxoffs;
-       }
        tp->tinfo.goal.offset = offset;
 }
 
@@ -2407,23 +2334,11 @@ static void sym2_set_period(struct scsi_device *sdev, int period)
        struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
        struct sym_tcb *tp = &np->target[sdev->id];
 
-       if (period <= 9 && np->minsync_dt) {
-               if (period < np->minsync_dt)
-                       period = np->minsync_dt;
-               tp->tinfo.goal.options = PPR_OPT_DT;
-               tp->tinfo.goal.period = period;
-               if (!tp->tinfo.curr.offset ||
-                                       tp->tinfo.curr.offset > np->maxoffs_dt)
-                       tp->tinfo.goal.offset = np->maxoffs_dt;
-       } else {
-               if (period < np->minsync)
-                       period = np->minsync;
-               tp->tinfo.goal.options = 0;
-               tp->tinfo.goal.period = period;
-               if (!tp->tinfo.curr.offset ||
-                                       tp->tinfo.curr.offset > np->maxoffs)
-                       tp->tinfo.goal.offset = np->maxoffs;
-       }
+       /* have to have DT for these transfers */
+       if (period <= np->minsync)
+               tp->tinfo.goal.options |= PPR_OPT_DT;
+
+       tp->tinfo.goal.period = period;
 }
 
 static void sym2_get_width(struct scsi_device *sdev)
@@ -2439,6 +2354,10 @@ static void sym2_set_width(struct scsi_device *sdev, int width)
        struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
        struct sym_tcb *tp = &np->target[sdev->id];
 
+       /* It is illegal to have DT set on narrow transfers */
+       if (width == 0)
+               tp->tinfo.goal.options &= ~PPR_OPT_DT;
+
        tp->tinfo.goal.width = width;
 }
 
@@ -2455,17 +2374,10 @@ static void sym2_set_dt(struct scsi_device *sdev, int dt)
        struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
        struct sym_tcb *tp = &np->target[sdev->id];
 
-       if (!dt) {
-               /* if clearing DT, then we may need to reduce the
-                * period and the offset */
-               if (tp->tinfo.curr.period < np->minsync)
-                       tp->tinfo.goal.period = np->minsync;
-               if (tp->tinfo.curr.offset > np->maxoffs)
-                       tp->tinfo.goal.offset = np->maxoffs;
-               tp->tinfo.goal.options &= ~PPR_OPT_DT;
-       } else {
+       if (dt)
                tp->tinfo.goal.options |= PPR_OPT_DT;
-       }
+       else
+               tp->tinfo.goal.options &= ~PPR_OPT_DT;
 }
        
 
index 60d48b7..5dd15fc 100644 (file)
@@ -90,7 +90,6 @@
 #define SYM_OPT_HANDLE_DIR_UNKNOWN
 #define SYM_OPT_HANDLE_DEVICE_QUEUEING
 #define SYM_OPT_NVRAM_PRE_READ
-#define SYM_OPT_SNIFF_INQUIRY
 #define SYM_OPT_LIMIT_COMMAND_REORDERING
 #define        SYM_OPT_ANNOUNCE_TRANSFER_RATE
 
@@ -289,32 +288,32 @@ typedef struct scsi_cmnd *cam_scsiio_p;/* SCSI I/O */
  *  MEMORY mapped IO input / output
  */
 
-#define INB_OFF(o)        readb((char *)np->s.mmio_va + sym_offb(o))
-#define OUTB_OFF(o, val)  writeb((val), (char *)np->s.mmio_va + sym_offb(o))
+#define INB_OFF(o)        readb(np->s.mmio_va + sym_offb(o))
+#define OUTB_OFF(o, val)  writeb((val), np->s.mmio_va + sym_offb(o))
 
 #if    defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_BIG_ENDIAN)
 
-#define INW_OFF(o)        readw_l2b((char *)np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o)        readl_l2b((char *)np->s.mmio_va + (o))
+#define INW_OFF(o)        readw_l2b(np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o)        readl_l2b(np->s.mmio_va + (o))
 
-#define OUTW_OFF(o, val)  writew_b2l((val), (char *)np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val)  writel_b2l((val), (char *)np->s.mmio_va + (o))
+#define OUTW_OFF(o, val)  writew_b2l((val), np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val)  writel_b2l((val), np->s.mmio_va + (o))
 
 #elif  defined(__LITTLE_ENDIAN) && defined(SYM_CONF_CHIP_BIG_ENDIAN)
 
-#define INW_OFF(o)        readw_b2l((char *)np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o)        readl_b2l((char *)np->s.mmio_va + (o))
+#define INW_OFF(o)        readw_b2l(np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o)        readl_b2l(np->s.mmio_va + (o))
 
-#define OUTW_OFF(o, val)  writew_l2b((val), (char *)np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val)  writel_l2b((val), (char *)np->s.mmio_va + (o))
+#define OUTW_OFF(o, val)  writew_l2b((val), np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val)  writel_l2b((val), np->s.mmio_va + (o))
 
 #else
 
-#define INW_OFF(o)        readw_raw((char *)np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o)        readl_raw((char *)np->s.mmio_va + (o))
+#define INW_OFF(o)        readw_raw(np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o)        readl_raw(np->s.mmio_va + (o))
 
-#define OUTW_OFF(o, val)  writew_raw((val), (char *)np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val)  writel_raw((val), (char *)np->s.mmio_va + (o))
+#define OUTW_OFF(o, val)  writew_raw((val), np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val)  writel_raw((val), np->s.mmio_va + (o))
 
 #endif
 
@@ -391,8 +390,8 @@ struct sym_shcb {
 
        struct Scsi_Host *host;
 
-       void *          mmio_va;        /* MMIO kernel virtual address  */
-       void *          ram_va;         /* RAM  kernel virtual address  */
+       void __iomem *  mmio_va;        /* MMIO kernel virtual address  */
+       void __iomem *  ram_va;         /* RAM  kernel virtual address  */
        u_long          io_port;        /* IO port address cookie       */
        u_short         io_ws;          /* IO window size               */
        int             irq;            /* IRQ number                   */
@@ -424,7 +423,7 @@ struct sym_slot {
        int     irq;
 /* port and address fields to fit INB, OUTB macros */
        u_long  io_port;
-       void *  mmio_va;
+       void __iomem *  mmio_va;
        char    inst_name[16];
 };
 
@@ -439,6 +438,13 @@ struct sym_device {
        u_char host_id;
 };
 
+/*
+ *  Driver host data structure.
+ */
+struct host_data {
+       struct sym_hcb *ncb;
+};
+
 /*
  *  The driver definitions (sym_hipd.h) must know about a 
  *  couple of things related to the memory allocator.
index 25a27f9..dddf88b 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-
-#define SYM_VERSION "2.1.18j"
-#define SYM_DRIVER_NAME        "sym-" SYM_VERSION
-
 #include "sym_glue.h"
 #include "sym_nvram.h"
 
@@ -1042,28 +1038,11 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
        for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {
                tcb_p tp = &np->target[i];
 
-               tp->tinfo.user.scsi_version = tp->tinfo.curr.scsi_version= 2;
-               tp->tinfo.user.spi_version  = tp->tinfo.curr.spi_version = 2;
-               tp->tinfo.user.period = np->minsync;
-               tp->tinfo.user.offset = np->maxoffs;
-               tp->tinfo.user.width  = np->maxwide ? BUS_16_BIT : BUS_8_BIT;
                tp->usrflags |= (SYM_DISC_ENABLED | SYM_TAGS_ENABLED);
                tp->usrtags = SYM_SETUP_MAX_TAG;
 
                sym_nvram_setup_target (np, i, nvram);
 
-               /*
-                * Some single-ended devices may crash on receiving a
-                * PPR negotiation attempt.  Only try PPR if we're in
-                * LVD mode.
-                */
-               if (np->features & FE_ULTRA3) {
-                       tp->tinfo.user.options |= PPR_OPT_DT;
-                       tp->tinfo.user.period = np->minsync_dt;
-                       tp->tinfo.user.offset = np->maxoffs_dt;
-                       tp->tinfo.user.spi_version = 3;
-               }
-
                if (!tp->usrtags)
                        tp->usrflags &= ~SYM_TAGS_ENABLED;
        }
@@ -1497,6 +1476,55 @@ static void sym_update_dmap_regs(hcb_p np)
 }
 #endif
 
+static void sym_check_goals(struct scsi_device *sdev)
+{
+       struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
+       struct sym_trans *st = &np->target[sdev->id].tinfo.goal;
+
+       /* here we enforce all the fiddly SPI rules */
+
+       if (!scsi_device_wide(sdev))
+               st->width = 0;
+
+       if (!scsi_device_sync(sdev)) {
+               st->options = 0;
+               st->period = 0;
+               st->offset = 0;
+               return;
+       }
+               
+       if (scsi_device_dt(sdev)) {
+               if (scsi_device_dt_only(sdev))
+                       st->options |= PPR_OPT_DT;
+
+               if (st->offset == 0)
+                       st->options &= ~PPR_OPT_DT;
+       } else {
+               st->options &= ~PPR_OPT_DT;
+       }
+
+       if (!(np->features & FE_ULTRA3))
+               st->options &= ~PPR_OPT_DT;
+
+       if (st->options & PPR_OPT_DT) {
+               /* all DT transfers must be wide */
+               st->width = 1;
+               if (st->offset > np->maxoffs_dt)
+                       st->offset = np->maxoffs_dt;
+               if (st->period < np->minsync_dt)
+                       st->period = np->minsync_dt;
+               if (st->period > np->maxsync_dt)
+                       st->period = np->maxsync_dt;
+       } else {
+               if (st->offset > np->maxoffs)
+                       st->offset = np->maxoffs;
+               if (st->period < np->minsync)
+                       st->period = np->minsync;
+               if (st->period > np->maxsync)
+                       st->period = np->maxsync;
+       }
+}              
+
 /*
  *  Prepare the next negotiation message if needed.
  *
@@ -1508,6 +1536,10 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
 {
        tcb_p tp = &np->target[cp->target];
        int msglen = 0;
+       struct scsi_device *sdev = tp->sdev;
+
+       if (likely(sdev))
+               sym_check_goals(sdev);
 
        /*
         *  Early C1010 chips need a work-around for DT 
@@ -1518,19 +1550,21 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
        /*
         *  negotiate using PPR ?
         */
-       if (tp->tinfo.goal.options & PPR_OPT_MASK)
+       if (scsi_device_dt(sdev)) {
                nego = NS_PPR;
-       /*
-        *  negotiate wide transfers ?
-        */
-       else if (tp->tinfo.curr.width != tp->tinfo.goal.width)
-               nego = NS_WIDE;
-       /*
-        *  negotiate synchronous transfers?
-        */
-       else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
-                tp->tinfo.curr.offset != tp->tinfo.goal.offset)
-               nego = NS_SYNC;
+       } else {
+               /*
+                *  negotiate wide transfers ?
+                */
+               if (tp->tinfo.curr.width != tp->tinfo.goal.width)
+                       nego = NS_WIDE;
+               /*
+                *  negotiate synchronous transfers?
+                */
+               else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
+                        tp->tinfo.curr.offset != tp->tinfo.goal.offset)
+                       nego = NS_SYNC;
+       }
 
        switch (nego) {
        case NS_SYNC:
@@ -3999,7 +4033,6 @@ int sym_compute_residual(hcb_p np, ccb_p cp)
 static int  
 sym_sync_nego_check(hcb_p np, int req, int target)
 {
-       tcb_p tp = &np->target[target];
        u_char  chg, ofs, per, fak, div;
 
        if (DEBUG_FLAGS & DEBUG_NEGO) {
@@ -4019,19 +4052,11 @@ sym_sync_nego_check(hcb_p np, int req, int target)
        if (ofs) {
                if (ofs > np->maxoffs)
                        {chg = 1; ofs = np->maxoffs;}
-               if (req) {
-                       if (ofs > tp->tinfo.user.offset)
-                               {chg = 1; ofs = tp->tinfo.user.offset;}
-               }
        }
 
        if (ofs) {
                if (per < np->minsync)
                        {chg = 1; per = np->minsync;}
-               if (req) {
-                       if (per < tp->tinfo.user.period)
-                               {chg = 1; per = tp->tinfo.user.period;}
-               }
        }
 
        /*
@@ -4151,10 +4176,6 @@ sym_ppr_nego_check(hcb_p np, int req, int target)
        }
        if (!wide || !(np->features & FE_ULTRA3))
                dt &= ~PPR_OPT_DT;
-       if (req) {
-               if (wide > tp->tinfo.user.width)
-                       {chg = 1; wide = tp->tinfo.user.width;}
-       }
 
        if (!(np->features & FE_U3EN))  /* Broken U3EN bit not supported */
                dt &= ~PPR_OPT_DT;
@@ -4168,10 +4189,6 @@ sym_ppr_nego_check(hcb_p np, int req, int target)
                }
                else if (ofs > np->maxoffs)
                        {chg = 1; ofs = np->maxoffs;}
-               if (req) {
-                       if (ofs > tp->tinfo.user.offset)
-                               {chg = 1; ofs = tp->tinfo.user.offset;}
-               }
        }
 
        if (ofs) {
@@ -4181,10 +4198,6 @@ sym_ppr_nego_check(hcb_p np, int req, int target)
                }
                else if (per < np->minsync)
                        {chg = 1; per = np->minsync;}
-               if (req) {
-                       if (per < tp->tinfo.user.period)
-                               {chg = 1; per = tp->tinfo.user.period;}
-               }
        }
 
        /*
@@ -4286,7 +4299,6 @@ reject_it:
 static int  
 sym_wide_nego_check(hcb_p np, int req, int target)
 {
-       tcb_p tp = &np->target[target];
        u_char  chg, wide;
 
        if (DEBUG_FLAGS & DEBUG_NEGO) {
@@ -4306,10 +4318,6 @@ sym_wide_nego_check(hcb_p np, int req, int target)
                chg = 1;
                wide = np->maxwide;
        }
-       if (req) {
-               if (wide > tp->tinfo.user.width)
-                       {chg = 1; wide = tp->tinfo.user.width;}
-       }
 
        if (DEBUG_FLAGS & DEBUG_NEGO) {
                PRINT_TARGET(np, target);
index aa246dd..04b5411 100644 (file)
  *        When this option is set, the driver will use a queue per 
  *        device and handle QUEUE FULL status requeuing internally.
  *
- *    SYM_OPT_SNIFF_INQUIRY
- *        When this option is set, the driver sniff out successful 
- *        INQUIRY response and performs negotiations accordingly.
- *        (set for Linux)
- *
  *    SYM_OPT_LIMIT_COMMAND_REORDERING
  *        When this option is set, the driver tries to limit tagged 
  *        command reordering to some reasonnable value.
@@ -82,7 +77,6 @@
 #if 0
 #define SYM_OPT_HANDLE_DIR_UNKNOWN
 #define SYM_OPT_HANDLE_DEVICE_QUEUEING
-#define SYM_OPT_SNIFF_INQUIRY
 #define SYM_OPT_LIMIT_COMMAND_REORDERING
 #endif
 
@@ -364,7 +358,6 @@ struct sym_trans {
 struct sym_tinfo {
        struct sym_trans curr;
        struct sym_trans goal;
-       struct sym_trans user;
 #ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
        struct sym_trans prev;
 #endif
@@ -465,18 +458,7 @@ struct sym_tcb {
         */
        u_char  usrflags;
        u_short usrtags;
-
-#ifdef SYM_OPT_SNIFF_INQUIRY
-       /*
-        *  Some minimal information from INQUIRY response.
-        */
-       u32     cmdq_map[(SYM_CONF_MAX_LUN+31)/32];
-       u_char  inq_version;
-       u_char  inq_byte7;
-       u_char  inq_byte56;
-       u_char  inq_byte7_valid;
-#endif
-
+       struct scsi_device *sdev;
 };
 
 /*
@@ -1168,26 +1150,6 @@ void sym_clock(hcb_p np);
 void sym_announce_transfer_rate(hcb_p np, int target);
 #endif
 
-/*
- *  Optionnaly, the driver may sniff inquiry data.
- */
-#ifdef SYM_OPT_SNIFF_INQUIRY
-#define        INQ7_CMDQ       (0x02)
-#define        INQ7_SYNC       (0x10)
-#define        INQ7_WIDE16     (0x20)
-
-#define INQ56_CLOCKING (3<<2)
-#define INQ56_ST_ONLY  (0<<2)
-#define INQ56_DT_ONLY  (1<<2)
-#define INQ56_ST_DT    (3<<2)
-
-void sym_update_trans_settings(hcb_p np, tcb_p tp);
-int  
-__sym_sniff_inquiry(hcb_p np, u_char tn, u_char ln,
-                    u_char *inq_data, int inq_len);
-#endif
-
-
 /*
  *  Build a scatter/gather entry.
  *
index ee2a7b2..6b3c8b8 100644 (file)
@@ -216,121 +216,3 @@ void sym_announce_transfer_rate(hcb_p np, int target)
 #undef __tprev
 #undef __tcurr
 #endif /* SYM_OPT_ANNOUNCE_TRANSFER_RATE */
-
-
-#ifdef SYM_OPT_SNIFF_INQUIRY
-/*
- *  Update transfer settings according to user settings 
- *  and bits sniffed out from INQUIRY response.
- */
-void sym_update_trans_settings(hcb_p np, tcb_p tp)
-{
-       memcpy(&tp->tinfo.goal, &tp->tinfo.user, sizeof(tp->tinfo.goal));
-
-       if (tp->inq_version >= 4) {
-               switch(tp->inq_byte56 & INQ56_CLOCKING) {
-               case INQ56_ST_ONLY:
-                       tp->tinfo.goal.options = 0;
-                       break;
-               case INQ56_DT_ONLY:
-               case INQ56_ST_DT:
-               default:
-                       break;
-               }
-       }
-
-       if (!((tp->inq_byte7 & tp->inq_byte7_valid) & INQ7_WIDE16)) {
-               tp->tinfo.goal.width   = 0;
-               tp->tinfo.goal.options = 0;
-       }
-
-       if (!((tp->inq_byte7 & tp->inq_byte7_valid) & INQ7_SYNC)) {
-               tp->tinfo.goal.offset  = 0;
-               tp->tinfo.goal.options = 0;
-       }
-
-       if (tp->tinfo.goal.options & PPR_OPT_DT) {
-               if (tp->tinfo.goal.offset > np->maxoffs_dt)
-                       tp->tinfo.goal.offset = np->maxoffs_dt;
-       }
-       else {
-               if (tp->tinfo.goal.offset > np->maxoffs)
-                       tp->tinfo.goal.offset = np->maxoffs;
-       }
-}
-
-/*
- *  Snoop target capabilities from INQUIRY response.
- *  We only believe device versions >= SCSI-2 that use 
- *  appropriate response data format (2). But it seems 
- *  that some CCS devices also support SYNC (?).
- */
-int 
-__sym_sniff_inquiry(hcb_p np, u_char tn, u_char ln,
-                    u_char *inq_data, int inq_len)
-{
-       tcb_p tp = &np->target[tn];
-       u_char inq_version;
-       u_char inq_byte7;
-       u_char inq_byte56;
-
-       if (!inq_data || inq_len < 2)
-               return -1;
-
-       /*
-        *  Check device type and qualifier.
-        */
-       if ((inq_data[0] & 0xe0) == 0x60)
-               return -1;
-
-       /*
-        *  Get SPC version.
-        */
-       if (inq_len <= 2)
-               return -1;
-       inq_version = inq_data[2] & 0x7;
-
-       /*
-        *  Get SYNC/WIDE16 capabilities.
-        */
-       inq_byte7 = tp->inq_byte7;
-       if (inq_version >= 2 && (inq_data[3] & 0xf) == 2) {
-               if (inq_len > 7)
-                       inq_byte7 = inq_data[7];
-       }
-       else if (inq_version == 1 && (inq_data[3] & 0xf) == 1)
-               inq_byte7 = INQ7_SYNC;
-
-       /*
-        *  Get Tagged Command Queuing capability.
-        */
-       if (inq_byte7 & INQ7_CMDQ)
-               sym_set_bit(tp->cmdq_map, ln);
-       else
-               sym_clr_bit(tp->cmdq_map, ln);
-       inq_byte7 &= ~INQ7_CMDQ;
-
-       /*
-        *  Get CLOCKING capability.
-        */
-       inq_byte56 = tp->inq_byte56;
-       if (inq_version >= 4 && inq_len > 56)
-               inq_byte56 = inq_data[56];
-#if 0
-printf("XXXXXX [%d] inq_version=%x inq_byte7=%x inq_byte56=%x XXXXX\n",
-       inq_len, inq_version, inq_byte7, inq_byte56);
-#endif
-       /*
-        *  Trigger a negotiation if needed.
-        */
-       if (tp->inq_version != inq_version ||
-           tp->inq_byte7   != inq_byte7   ||
-           tp->inq_byte56  != inq_byte56) {
-               tp->inq_version = inq_version;
-               tp->inq_byte7   = inq_byte7;
-               tp->inq_byte56  = inq_byte56;
-               return 1;
-       }
-       return 0;
-}
-#endif /* SYM_OPT_SNIFF_INQUIRY */
index 2bb4b3f..ca857ff 100644 (file)
 #include "sym_glue.h"
 #include "sym_nvram.h"
 
-/*
- *  Some poor and bogus sync table that refers to Tekram NVRAM layout.
- */
-static u_char Tekram_sync[16] =
-       {25,31,37,43, 50,62,75,125, 12,15,18,21, 6,7,9,10};
 #ifdef SYM_CONF_DEBUG_NVRAM
 static u_char Tekram_boot_delay[7] = {3, 5, 10, 20, 30, 60, 120};
 #endif
@@ -100,8 +95,6 @@ sym_Symbios_setup_target(struct sym_hcb *np, int target, Symbios_nvram *nvram)
        struct sym_tcb *tp = &np->target[target];
        Symbios_target *tn = &nvram->target[target];
 
-       tp->tinfo.user.period = tn->sync_period ? (tn->sync_period + 3) / 4 : 0;
-       tp->tinfo.user.width  = tn->bus_width == 0x10 ? BUS_16_BIT : BUS_8_BIT;
        tp->usrtags =
                (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? SYM_SETUP_MAX_TAG : 0;
 
@@ -121,15 +114,6 @@ sym_Tekram_setup_target(struct sym_hcb *np, int target, Tekram_nvram *nvram)
 {
        struct sym_tcb *tp = &np->target[target];
        struct Tekram_target *tn = &nvram->target[target];
-       int i;
-
-       if (tn->flags & TEKRAM_SYNC_NEGO) {
-               i = tn->sync_index & 0xf;
-               tp->tinfo.user.period = Tekram_sync[i];
-       }
-
-       tp->tinfo.user.width = (tn->flags & TEKRAM_WIDE_NEGO) ?
-               BUS_16_BIT : BUS_8_BIT;
 
        if (tn->flags & TEKRAM_TAGGED_COMMANDS) {
                tp->usrtags = 2 << nvram->max_tags_index;
index 5c499be..6dd5224 100644 (file)
@@ -435,10 +435,7 @@ static void do_softint(void *private)
                return;
 #if 0
        if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   tty->ldisc.write_wakeup)
-                       (tty->ldisc.write_wakeup)(tty);
-               wake_up_interruptible(&tty->write_wait);
+               tty_wakeup(tty);
        }
 #endif   
 }
@@ -858,10 +855,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
        cli();
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
        sti();
-       wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
 }
 
 /*
@@ -1185,11 +1179,13 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
        shutdown(info);
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+               
+       tty_ldisc_flush(tty);
        tty->closing = 0;
        info->event = 0;
        info->tty = 0;
+#warning "This is not and has never been valid so fix it"      
+#if 0
        if (tty->ldisc.num != ldiscs[N_TTY].num) {
                if (tty->ldisc.close)
                        (tty->ldisc.close)(tty);
@@ -1198,6 +1194,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
                if (tty->ldisc.open)
                        (tty->ldisc.open)(tty);
        }
+#endif 
        if (info->blocked_open) {
                if (info->close_delay) {
                        current->state = TASK_INTERRUPTIBLE;
index da0ad9b..79c0368 100644 (file)
@@ -33,6 +33,20 @@ struct old_serial_port {
        unsigned short iomem_reg_shift;
 };
 
+/*
+ * This replaces serial_uart_config in include/linux/serial.h
+ */
+struct serial8250_config {
+       const char      *name;
+       unsigned int    fifo_size;
+       unsigned int    tx_loadsz;
+       unsigned int    flags;
+};
+
+#define UART_CAP_FIFO  (1 << 8)        /* UART has FIFO */
+#define UART_CAP_EFR   (1 << 9)        /* UART has EFR */
+#define UART_CAP_SLEEP (1 << 10)       /* UART has IER sleep */
+
 #undef SERIAL_DEBUG_PCI
 
 #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
new file mode 100644 (file)
index 0000000..c15c8a0
--- /dev/null
@@ -0,0 +1,1702 @@
+/*
+  * icom.c
+  *
+  * Copyright (C) 2001 IBM Corporation. All rights reserved.
+  *
+  * Serial device driver.
+  *
+  * Based on code from serial.c
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+  * (at your option) any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  *
+  * You should have received a copy of the GNU General Public License
+  * along with this program; if not, write to the Free Software
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+  *
+  */
+#define SERIAL_DO_RESTART
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/termios.h>
+#include <linux/fs.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/kobject.h>
+#include <linux/firmware.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+
+#include "icom.h"
+
+/*#define ICOM_TRACE            enable port trace capabilities */
+
+#define ICOM_DRIVER_NAME "icom"
+#define ICOM_VERSION_STR "1.3.1"
+#define NR_PORTS              128
+#define ICOM_PORT ((struct icom_port *)port)
+#define to_icom_adapter(d) container_of(d, struct icom_adapter, kobj)
+
+static const struct pci_device_id icom_pci_table[] = {
+       {
+             .vendor = PCI_VENDOR_ID_IBM,
+             .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1,
+             .subvendor = PCI_ANY_ID,
+             .subdevice = PCI_ANY_ID,
+             .driver_data = ADAPTER_V1,
+        },
+       {
+             .vendor = PCI_VENDOR_ID_IBM,
+             .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
+             .subvendor = PCI_VENDOR_ID_IBM,
+             .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX,
+             .driver_data = ADAPTER_V2,
+        },
+       {
+             .vendor = PCI_VENDOR_ID_IBM,
+             .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
+             .subvendor = PCI_VENDOR_ID_IBM,
+             .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM,
+             .driver_data = ADAPTER_V2,
+        },
+       {
+             .vendor = PCI_VENDOR_ID_IBM,
+             .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
+             .subvendor = PCI_VENDOR_ID_IBM,
+             .subdevice = PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL,
+             .driver_data = ADAPTER_V2,
+        },
+       {}
+};
+
+struct lookup_proc_table start_proc[4] = {
+       {0, ICOM_CONTROL_START_A},
+       {0, ICOM_CONTROL_START_B},
+       {0, ICOM_CONTROL_START_C},
+       {0, ICOM_CONTROL_START_D}
+};
+
+
+struct lookup_proc_table stop_proc[4] = {
+       {0, ICOM_CONTROL_STOP_A},
+       {0, ICOM_CONTROL_STOP_B},
+       {0, ICOM_CONTROL_STOP_C},
+       {0, ICOM_CONTROL_STOP_D}
+};
+
+struct lookup_int_table int_mask_tbl[4] = {
+       {0, ICOM_INT_MASK_PRC_A},
+       {0, ICOM_INT_MASK_PRC_B},
+       {0, ICOM_INT_MASK_PRC_C},
+       {0, ICOM_INT_MASK_PRC_D},
+};
+
+
+MODULE_DEVICE_TABLE(pci, icom_pci_table);
+
+static LIST_HEAD(icom_adapter_head);
+
+/* spinlock for adapter initialization and changing adapter operations */
+static spinlock_t icom_lock;
+
+#ifdef ICOM_TRACE
+static inline void trace(struct icom_port *, char *, unsigned long) {};
+#else
+static inline void trace(struct icom_port *icom_port, char *trace_pt, unsigned long trace_data) {};
+#endif
+
+static void msleep(unsigned long msecs)
+{
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout(MSECS_TO_JIFFIES(msecs));
+}
+
+static void free_port_memory(struct icom_port *icom_port)
+{
+       struct pci_dev *dev = icom_port->adapter->pci_dev;
+
+       trace(icom_port, "RET_PORT_MEM", 0);
+       if (icom_port->recv_buf) {
+               pci_free_consistent(dev, 4096, icom_port->recv_buf,
+                                   icom_port->recv_buf_pci);
+               icom_port->recv_buf = 0;
+       }
+       if (icom_port->xmit_buf) {
+               pci_free_consistent(dev, 4096, icom_port->xmit_buf,
+                                   icom_port->xmit_buf_pci);
+               icom_port->xmit_buf = 0;
+       }
+       if (icom_port->statStg) {
+               pci_free_consistent(dev, 4096, icom_port->statStg,
+                                   icom_port->statStg_pci);
+               icom_port->statStg = 0;
+       }
+
+       if (icom_port->xmitRestart) {
+               pci_free_consistent(dev, 4096, icom_port->xmitRestart,
+                                   icom_port->xmitRestart_pci);
+               icom_port->xmitRestart = 0;
+       }
+}
+
+static int __init get_port_memory(struct icom_port *icom_port)
+{
+       int index;
+       unsigned long stgAddr;
+       unsigned long startStgAddr;
+       unsigned long offset;
+       struct pci_dev *dev = icom_port->adapter->pci_dev;
+
+       icom_port->xmit_buf =
+           pci_alloc_consistent(dev, 4096, &icom_port->xmit_buf_pci);
+       if (!icom_port->xmit_buf) {
+               dev_err(&dev->dev, "Can not allocate Transmit buffer\n");
+               return -ENOMEM;
+       }
+
+       trace(icom_port, "GET_PORT_MEM",
+             (unsigned long) icom_port->xmit_buf);
+
+       icom_port->recv_buf =
+           pci_alloc_consistent(dev, 4096, &icom_port->recv_buf_pci);
+       if (!icom_port->recv_buf) {
+               dev_err(&dev->dev, "Can not allocate Receive buffer\n");
+               free_port_memory(icom_port);
+               return -ENOMEM;
+       }
+       trace(icom_port, "GET_PORT_MEM",
+             (unsigned long) icom_port->recv_buf);
+
+       icom_port->statStg =
+           pci_alloc_consistent(dev, 4096, &icom_port->statStg_pci);
+       if (!icom_port->statStg) {
+               dev_err(&dev->dev, "Can not allocate Status buffer\n");
+               free_port_memory(icom_port);
+               return -ENOMEM;
+       }
+       trace(icom_port, "GET_PORT_MEM",
+             (unsigned long) icom_port->statStg);
+
+       icom_port->xmitRestart =
+           pci_alloc_consistent(dev, 4096, &icom_port->xmitRestart_pci);
+       if (!icom_port->xmitRestart) {
+               dev_err(&dev->dev,
+                       "Can not allocate xmit Restart buffer\n");
+               free_port_memory(icom_port);
+               return -ENOMEM;
+       }
+
+       memset(icom_port->statStg, 0, 4096);
+
+       /* FODs: Frame Out Descriptor Queue, this is a FIFO queue that
+           indicates that frames are to be transmitted
+       */
+
+       stgAddr = (unsigned long) icom_port->statStg;
+       for (index = 0; index < NUM_XBUFFS; index++) {
+               trace(icom_port, "FOD_ADDR", stgAddr);
+               stgAddr = stgAddr + sizeof(icom_port->statStg->xmit[0]);
+               if (index < (NUM_XBUFFS - 1)) {
+                       memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
+                       icom_port->statStg->xmit[index].leLengthASD =
+                           (unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
+                       trace(icom_port, "FOD_ADDR", stgAddr);
+                       trace(icom_port, "FOD_XBUFF",
+                             (unsigned long) icom_port->xmit_buf);
+                       icom_port->statStg->xmit[index].leBuffer =
+                           cpu_to_le32(icom_port->xmit_buf_pci);
+               } else if (index == (NUM_XBUFFS - 1)) {
+                       memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
+                       icom_port->statStg->xmit[index].leLengthASD =
+                           (unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
+                       trace(icom_port, "FOD_XBUFF",
+                             (unsigned long) icom_port->xmit_buf);
+                       icom_port->statStg->xmit[index].leBuffer =
+                           cpu_to_le32(icom_port->xmit_buf_pci);
+               } else {
+                       memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
+               }
+       }
+       /* FIDs */
+       startStgAddr = stgAddr;
+
+       /* fill in every entry, even if no buffer */
+       for (index = 0; index <  NUM_RBUFFS; index++) {
+               trace(icom_port, "FID_ADDR", stgAddr);
+               stgAddr = stgAddr + sizeof(icom_port->statStg->rcv[0]);
+               icom_port->statStg->rcv[index].leLength = 0;
+               icom_port->statStg->rcv[index].WorkingLength =
+                   (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
+               if (index < (NUM_RBUFFS - 1) ) {
+                       offset = stgAddr - (unsigned long) icom_port->statStg;
+                       icom_port->statStg->rcv[index].leNext =
+                             cpu_to_le32(icom_port-> statStg_pci + offset);
+                       trace(icom_port, "FID_RBUFF",
+                             (unsigned long) icom_port->recv_buf);
+                       icom_port->statStg->rcv[index].leBuffer =
+                           cpu_to_le32(icom_port->recv_buf_pci);
+               } else if (index == (NUM_RBUFFS -1) ) {
+                       offset = startStgAddr - (unsigned long) icom_port->statStg;
+                       icom_port->statStg->rcv[index].leNext =
+                           cpu_to_le32(icom_port-> statStg_pci + offset);
+                       trace(icom_port, "FID_RBUFF",
+                             (unsigned long) icom_port->recv_buf + 2048);
+                       icom_port->statStg->rcv[index].leBuffer =
+                           cpu_to_le32(icom_port->recv_buf_pci + 2048);
+               } else {
+                       icom_port->statStg->rcv[index].leNext = 0;
+                       icom_port->statStg->rcv[index].leBuffer = 0;
+               }
+       }
+
+       return 0;
+}
+
+static void stop_processor(struct icom_port *icom_port)
+{
+       unsigned long temp;
+       unsigned long flags;
+       int port;
+
+       spin_lock_irqsave(&icom_lock, flags);
+
+       port = icom_port->port;
+       if (port == 0 || port == 1)
+               stop_proc[port].global_control_reg = &icom_port->global_reg->control;
+       else
+               stop_proc[port].global_control_reg = &icom_port->global_reg->control_2;
+
+
+       if (port < 4) {
+               temp = readl(stop_proc[port].global_control_reg);
+               temp =
+                       (temp & ~start_proc[port].processor_id) | stop_proc[port].processor_id;
+               writel(temp, stop_proc[port].global_control_reg);
+
+               /* write flush */
+               readl(stop_proc[port].global_control_reg);
+       } else {
+               dev_err(&icom_port->adapter->pci_dev->dev,
+                        "Invalid port assignment\n");
+       }
+
+       spin_unlock_irqrestore(&icom_lock, flags);
+}
+
+static void start_processor(struct icom_port *icom_port)
+{
+       unsigned long temp;
+       unsigned long flags;
+       int port;
+
+       spin_lock_irqsave(&icom_lock, flags);
+
+       port = icom_port->port;
+       if (port == 0 || port == 1)
+               start_proc[port].global_control_reg = &icom_port->global_reg->control;
+       else
+               start_proc[port].global_control_reg = &icom_port->global_reg->control_2;
+       if (port < 4) {
+               temp = readl(start_proc[port].global_control_reg);
+               temp =
+                       (temp & ~stop_proc[port].processor_id) | start_proc[port].processor_id;
+               writel(temp, start_proc[port].global_control_reg);
+
+               /* write flush */
+               readl(start_proc[port].global_control_reg);
+       } else {
+               dev_err(&icom_port->adapter->pci_dev->dev,
+                        "Invalid port assignment\n");
+       }
+
+       spin_unlock_irqrestore(&icom_lock, flags);
+}
+
+static void load_code(struct icom_port *icom_port)
+{
+       const struct firmware *fw;
+       char *iram_ptr;
+       int index;
+       int status = 0;
+       char *dram_ptr = (char *) icom_port->dram;
+       dma_addr_t temp_pci;
+       unsigned char *new_page = NULL;
+       unsigned char cable_id = NO_CABLE;
+       struct pci_dev *dev = icom_port->adapter->pci_dev;
+
+       /* Clear out any pending interrupts */
+       writew(0x3FFF, (void *) icom_port->int_reg);
+
+       trace(icom_port, "CLEAR_INTERRUPTS", 0);
+
+       /* Stop processor */
+       stop_processor(icom_port);
+
+       /* Zero out DRAM */
+       memset_io(dram_ptr, 0, 512);
+
+       /* Load Call Setup into Adapter */
+       if (request_firmware(&fw, "icom_call_setup.bin", &dev->dev) < 0) {
+               dev_err(&dev->dev,"Unable to load icom_call_setup.bin firmware image\n");
+               status = -1;
+               goto load_code_exit;
+       }
+
+       if (fw->size > ICOM_DCE_IRAM_OFFSET) {
+               dev_err(&dev->dev, "Invalid firmware image for icom_call_setup.bin found.\n");
+               release_firmware(fw);
+               status = -1;
+               goto load_code_exit;
+       }
+
+       iram_ptr = (char *) icom_port->dram + ICOM_IRAM_OFFSET;
+       for (index = 0; index < fw->size; index++)
+               writeb(fw->data[index], &iram_ptr[index]);
+
+       release_firmware(fw);
+
+       /* Load Resident DCE portion of Adapter */
+       if (request_firmware(&fw, "icom_res_dce.bin", &dev->dev) < 0) {
+               dev_err(&dev->dev,"Unable to load icom_res_dce.bin firmware image\n");
+               status = -1;
+               goto load_code_exit;
+       }
+
+       if (fw->size > ICOM_IRAM_SIZE) {
+               dev_err(&dev->dev, "Invalid firmware image for icom_res_dce.bin found.\n");
+               release_firmware(fw);
+               status = -1;
+               goto load_code_exit;
+       }
+
+       iram_ptr = (char *) icom_port->dram + ICOM_IRAM_OFFSET;
+       for (index = ICOM_DCE_IRAM_OFFSET; index < fw->size; index++)
+               writeb(fw->data[index], &iram_ptr[index]);
+
+       release_firmware(fw);
+
+       /* Set Hardware level */
+       if ((icom_port->adapter->version | ADAPTER_V2) == ADAPTER_V2)
+               writeb(V2_HARDWARE, &(icom_port->dram->misc_flags));
+
+       /* Start the processor in Adapter */
+       start_processor(icom_port);
+
+       writeb((HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL),
+              &(icom_port->dram->HDLCConfigReg));
+       writeb(0x04, &(icom_port->dram->FlagFillIdleTimer));    /* 0.5 seconds */
+       writeb(0x00, &(icom_port->dram->CmdReg));
+       writeb(0x10, &(icom_port->dram->async_config3));
+       writeb((ICOM_ACFG_DRIVE1 | ICOM_ACFG_NO_PARITY | ICOM_ACFG_8BPC |
+               ICOM_ACFG_1STOP_BIT), &(icom_port->dram->async_config2));
+
+       /*Set up data in icom DRAM to indicate where personality
+        *code is located and its length.
+        */
+       new_page = pci_alloc_consistent(dev, 4096, &temp_pci);
+
+       if (!new_page) {
+               dev_err(&dev->dev, "Can not allocate DMA buffer\n");
+               status = -1;
+               goto load_code_exit;
+       }
+
+       if (request_firmware(&fw, "icom_asc.bin", &dev->dev) < 0) {
+               dev_err(&dev->dev,"Unable to load icom_asc.bin firmware image\n");
+               status = -1;
+               goto load_code_exit;
+       }
+
+       if (fw->size > ICOM_DCE_IRAM_OFFSET) {
+               dev_err(&dev->dev, "Invalid firmware image for icom_asc.bin found.\n");
+               release_firmware(fw);
+               status = -1;
+               goto load_code_exit;
+       }
+
+       for (index = 0; index < fw->size; index++)
+               new_page[index] = fw->data[index];
+
+       release_firmware(fw);
+
+       writeb((char) ((fw->size + 16)/16), &icom_port->dram->mac_length);
+       writel(temp_pci, &icom_port->dram->mac_load_addr);
+
+       /*Setting the syncReg to 0x80 causes adapter to start downloading
+          the personality code into adapter instruction RAM.
+          Once code is loaded, it will begin executing and, based on
+          information provided above, will start DMAing data from
+          shared memory to adapter DRAM.
+        */
+       /* the wait loop below verifies this write operation has been done
+          and processed
+       */
+       writeb(START_DOWNLOAD, &icom_port->dram->sync);
+
+       /* Wait max 1 Sec for data download and processor to start */
+       for (index = 0; index < 10; index++) {
+               msleep(100);
+               if (readb(&icom_port->dram->misc_flags) & ICOM_HDW_ACTIVE)
+                       break;
+       }
+
+       if (index == 10)
+               status = -1;
+
+       /*
+        * check Cable ID
+        */
+       cable_id = readb(&icom_port->dram->cable_id);
+
+       if (cable_id & ICOM_CABLE_ID_VALID) {
+               /* Get cable ID into the lower 4 bits (standard form) */
+               cable_id = (cable_id & ICOM_CABLE_ID_MASK) >> 4;
+               icom_port->cable_id = cable_id;
+       } else {
+               dev_err(&dev->dev,"Invalid or no cable attached\n");
+               icom_port->cable_id = NO_CABLE;
+       }
+
+      load_code_exit:
+
+       if (status != 0) {
+               /* Clear out any pending interrupts */
+               writew(0x3FFF, (void *) icom_port->int_reg);
+
+               /* Turn off port */
+               writeb(ICOM_DISABLE, &(icom_port->dram->disable));
+
+               /* Stop processor */
+               stop_processor(icom_port);
+
+               dev_err(&icom_port->adapter->pci_dev->dev,"Port not opertional\n");
+       }
+
+      if (new_page != NULL)
+             pci_free_consistent(dev, 4096, new_page, temp_pci);
+}
+
+static int startup(struct icom_port *icom_port)
+{
+       unsigned long temp;
+       unsigned char cable_id, raw_cable_id;
+       unsigned long flags;
+       int port;
+
+       trace(icom_port, "STARTUP", 0);
+
+       if (icom_port->dram == 0x00000000) {
+               /* should NEVER be zero */
+               dev_err(&icom_port->adapter->pci_dev->dev,
+                       "Unusable Port, port configuration missing\n");
+               return -ENODEV;
+       }
+
+       /*
+        * check Cable ID
+        */
+       raw_cable_id = readb(&icom_port->dram->cable_id);
+       trace(icom_port, "CABLE_ID", raw_cable_id);
+
+       /* Get cable ID into the lower 4 bits (standard form) */
+       cable_id = (raw_cable_id & ICOM_CABLE_ID_MASK) >> 4;
+
+       /* Check for valid Cable ID */
+       if (!(raw_cable_id & ICOM_CABLE_ID_VALID) ||
+           (cable_id != icom_port->cable_id)) {
+
+               /* reload adapter code, pick up any potential changes in cable id */
+               load_code(icom_port);
+
+               /* still no sign of cable, error out */
+               raw_cable_id = readb(&icom_port->dram->cable_id);
+               cable_id = (raw_cable_id & ICOM_CABLE_ID_MASK) >> 4;
+               if (!(raw_cable_id & ICOM_CABLE_ID_VALID) ||
+                   (icom_port->cable_id == NO_CABLE))
+                       return -EIO;
+       }
+
+       /*
+        * Finally, clear and  enable interrupts
+        */
+       spin_lock_irqsave(&icom_lock, flags);
+       port = icom_port->port;
+       if (port == 0 || port == 1)
+               int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask;
+       else
+               int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask_2;
+
+       if (port == 0 || port == 2)
+               writew(0x00FF,(void *) icom_port->int_reg);
+       else
+               writew(0x3F00,(void *) icom_port->int_reg);
+       if (port < 4) {
+               temp = readl(int_mask_tbl[port].global_int_mask);
+               writel(temp & ~int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
+
+               /* write flush */
+               readl(int_mask_tbl[port].global_int_mask);
+       } else {
+               dev_err(&icom_port->adapter->pci_dev->dev,
+                        "Invalid port assignment\n");
+       }
+
+       spin_unlock_irqrestore(&icom_lock, flags);
+       return 0;
+}
+
+static void shutdown(struct icom_port *icom_port)
+{
+       unsigned long temp;
+       unsigned char cmdReg;
+       unsigned long flags;
+       int port;
+
+       spin_lock_irqsave(&icom_lock, flags);
+       trace(icom_port, "SHUTDOWN", 0);
+
+       /*
+        * disable all interrupts
+        */
+       port = icom_port->port;
+       if (port == 0 || port == 1)
+               int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask;
+       else
+               int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask_2;
+
+       if (port < 4) {
+               temp = readl(int_mask_tbl[port].global_int_mask);
+               writel(temp | int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
+
+               /* write flush */
+               readl(int_mask_tbl[port].global_int_mask);
+       } else {
+               dev_err(&icom_port->adapter->pci_dev->dev,
+                        "Invalid port assignment\n");
+       }
+       spin_unlock_irqrestore(&icom_lock, flags);
+
+       /*
+        * disable break condition
+        */
+       cmdReg = readb(&icom_port->dram->CmdReg);
+       if ((cmdReg | CMD_SND_BREAK) == CMD_SND_BREAK) {
+               writeb(cmdReg & ~CMD_SND_BREAK, &icom_port->dram->CmdReg);
+       }
+}
+
+static int icom_write(struct uart_port *port)
+{
+       unsigned long data_count;
+       unsigned char cmdReg;
+       unsigned long offset;
+       int temp_tail = port->info->xmit.tail;
+
+       trace(ICOM_PORT, "WRITE", 0);
+
+       if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
+           SA_FLAGS_READY_TO_XMIT) {
+               trace(ICOM_PORT, "WRITE_FULL", 0);
+               return 0;
+       }
+
+       data_count = 0;
+       while ((port->info->xmit.head != temp_tail) &&
+              (data_count <= XMIT_BUFF_SZ)) {
+
+               ICOM_PORT->xmit_buf[data_count++] =
+                   port->info->xmit.buf[temp_tail];
+
+               temp_tail++;
+               temp_tail &= (UART_XMIT_SIZE - 1);
+       }
+
+       if (data_count) {
+               ICOM_PORT->statStg->xmit[0].flags =
+                   cpu_to_le16(SA_FLAGS_READY_TO_XMIT);
+               ICOM_PORT->statStg->xmit[0].leLength =
+                   cpu_to_le16(data_count);
+               offset =
+                   (unsigned long) &ICOM_PORT->statStg->xmit[0] -
+                   (unsigned long) ICOM_PORT->statStg;
+               *ICOM_PORT->xmitRestart =
+                   cpu_to_le32(ICOM_PORT->statStg_pci + offset);
+               cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+               writeb(cmdReg | CMD_XMIT_RCV_ENABLE,
+                      &ICOM_PORT->dram->CmdReg);
+               writeb(START_XMIT, &ICOM_PORT->dram->StartXmitCmd);
+               trace(ICOM_PORT, "WRITE_START", data_count);
+               /* write flush */
+               readb(&ICOM_PORT->dram->StartXmitCmd);
+       }
+
+       return data_count;
+}
+
+static inline void check_modem_status(struct icom_port *icom_port)
+{
+       static char old_status = 0;
+       char delta_status;
+       unsigned char status;
+
+       spin_lock(&icom_port->uart_port.lock);
+
+       /*modem input register */
+       status = readb(&icom_port->dram->isr);
+       trace(icom_port, "CHECK_MODEM", status);
+       delta_status = status ^ old_status;
+       if (delta_status) {
+               if (delta_status & ICOM_RI)
+                       icom_port->uart_port.icount.rng++;
+               if (delta_status & ICOM_DSR)
+                       icom_port->uart_port.icount.dsr++;
+               if (delta_status & ICOM_DCD)
+                       uart_handle_dcd_change(&icom_port->uart_port,
+                                              delta_status & ICOM_DCD);
+               if (delta_status & ICOM_CTS)
+                       uart_handle_cts_change(&icom_port->uart_port,
+                                              delta_status & ICOM_CTS);
+
+               wake_up_interruptible(&icom_port->uart_port.info->
+                                     delta_msr_wait);
+               old_status = status;
+       }
+       spin_unlock(&icom_port->uart_port.lock);
+}
+
+static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
+{
+       unsigned short int count;
+       int i;
+
+       if (port_int_reg & (INT_XMIT_COMPLETED)) {
+               trace(icom_port, "XMIT_COMPLETE", 0);
+
+               /* clear buffer in use bit */
+               icom_port->statStg->xmit[0].flags &=
+                       cpu_to_le16(~SA_FLAGS_READY_TO_XMIT);
+
+               count = (unsigned short int)
+                       cpu_to_le16(icom_port->statStg->xmit[0].leLength);
+               icom_port->uart_port.icount.tx += count;
+
+               for (i=0; i<count &&
+                       !uart_circ_empty(&icom_port->uart_port.info->xmit); i++) {
+
+                       icom_port->uart_port.info->xmit.tail++;
+                       icom_port->uart_port.info->xmit.tail &=
+                               (UART_XMIT_SIZE - 1);
+               }
+
+               if (!icom_write(&icom_port->uart_port))
+                       /* activate write queue */
+                       uart_write_wakeup(&icom_port->uart_port);
+       } else
+               trace(icom_port, "XMIT_DISABLED", 0);
+}
+
+static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
+{
+       short int count, rcv_buff;
+       struct tty_struct *tty = icom_port->uart_port.info->tty;
+       unsigned short int status;
+       struct uart_icount *icount;
+       unsigned long offset;
+
+       trace(icom_port, "RCV_COMPLETE", 0);
+       rcv_buff = icom_port->next_rcv;
+
+       status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
+       while (status & SA_FL_RCV_DONE) {
+
+               trace(icom_port, "FID_STATUS", status);
+               count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength);
+
+               trace(icom_port, "RCV_COUNT", count);
+               if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
+                       count = TTY_FLIPBUF_SIZE - tty->flip.count;
+
+               trace(icom_port, "REAL_COUNT", count);
+
+               offset =
+                       cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
+                       icom_port->recv_buf_pci;
+
+               memcpy(tty->flip.char_buf_ptr,(unsigned char *)
+                      ((unsigned long)icom_port->recv_buf + offset), count);
+
+               if (count > 0) {
+                       tty->flip.count += count - 1;
+                       tty->flip.char_buf_ptr += count - 1;
+
+                       memset(tty->flip.flag_buf_ptr, 0, count);
+                       tty->flip.flag_buf_ptr += count - 1;
+               }
+
+               icount = &icom_port->uart_port.icount;
+               icount->rx += count;
+
+               /* Break detect logic */
+               if ((status & SA_FLAGS_FRAME_ERROR)
+                   && (tty->flip.char_buf_ptr[0] == 0x00)) {
+                       status &= ~SA_FLAGS_FRAME_ERROR;
+                       status |= SA_FLAGS_BREAK_DET;
+                       trace(icom_port, "BREAK_DET", 0);
+               }
+
+               if (status &
+                   (SA_FLAGS_BREAK_DET | SA_FLAGS_PARITY_ERROR |
+                    SA_FLAGS_FRAME_ERROR | SA_FLAGS_OVERRUN)) {
+
+                       if (status & SA_FLAGS_BREAK_DET)
+                               icount->brk++;
+                       if (status & SA_FLAGS_PARITY_ERROR)
+                               icount->parity++;
+                       if (status & SA_FLAGS_FRAME_ERROR)
+                               icount->frame++;
+                       if (status & SA_FLAGS_OVERRUN)
+                               icount->overrun++;
+
+                       /*
+                        * Now check to see if character should be
+                        * ignored, and mask off conditions which
+                        * should be ignored.
+                        */
+                       if (status & icom_port->ignore_status_mask) {
+                               trace(icom_port, "IGNORE_CHAR", 0);
+                               goto ignore_char;
+                       }
+
+                       status &= icom_port->read_status_mask;
+
+                       if (status & SA_FLAGS_BREAK_DET) {
+                               *tty->flip.flag_buf_ptr = TTY_BREAK;
+                       } else if (status & SA_FLAGS_PARITY_ERROR) {
+                               trace(icom_port, "PARITY_ERROR", 0);
+                               *tty->flip.flag_buf_ptr = TTY_PARITY;
+                       } else if (status & SA_FLAGS_FRAME_ERROR)
+                               *tty->flip.flag_buf_ptr = TTY_FRAME;
+
+                       if (status & SA_FLAGS_OVERRUN) {
+                               /*
+                                * Overrun is special, since it's
+                                * reported immediately, and doesn't
+                                * affect the current character
+                                */
+                               if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+                                       tty->flip.count++;
+                                       tty->flip.flag_buf_ptr++;
+                                       tty->flip.char_buf_ptr++;
+                                       *tty->flip.flag_buf_ptr = TTY_OVERRUN;
+                               }
+                       }
+               }
+
+               tty->flip.flag_buf_ptr++;
+               tty->flip.char_buf_ptr++;
+               tty->flip.count++;
+               ignore_char:
+                       icom_port->statStg->rcv[rcv_buff].flags = 0;
+               icom_port->statStg->rcv[rcv_buff].leLength = 0;
+               icom_port->statStg->rcv[rcv_buff].WorkingLength =
+                       (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
+
+               rcv_buff++;
+               if (rcv_buff == NUM_RBUFFS)
+                       rcv_buff = 0;
+
+               status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
+       }
+       icom_port->next_rcv = rcv_buff;
+       tty_flip_buffer_push(tty);
+}
+
+static void process_interrupt(u16 port_int_reg,
+                             struct icom_port *icom_port)
+{
+
+       spin_lock(&icom_port->uart_port.lock);
+       trace(icom_port, "INTERRUPT", port_int_reg);
+
+       if (port_int_reg & (INT_XMIT_COMPLETED | INT_XMIT_DISABLED))
+               xmit_interrupt(port_int_reg, icom_port);
+
+       if (port_int_reg & INT_RCV_COMPLETED)
+               recv_interrupt(port_int_reg, icom_port);
+
+       spin_unlock(&icom_port->uart_port.lock);
+}
+
+static irqreturn_t icom_interrupt(int irq, void *dev_id,
+                                 struct pt_regs *regs)
+{
+       unsigned long int_reg;
+       u32 adapter_interrupts;
+       u16 port_int_reg;
+       struct icom_adapter *icom_adapter;
+       struct icom_port *icom_port;
+
+       /* find icom_port for this interrupt */
+       icom_adapter = (struct icom_adapter *) dev_id;
+
+       if ((icom_adapter->version | ADAPTER_V2) == ADAPTER_V2) {
+               int_reg = icom_adapter->base_addr + 0x8024;
+
+               adapter_interrupts = readl((void *) int_reg);
+
+               if (adapter_interrupts & 0x00003FFF) {
+                       /* port 2 interrupt,  NOTE:  for all ADAPTER_V2, port 2 will be active */
+                       icom_port = &icom_adapter->port_info[2];
+                       port_int_reg = (u16) adapter_interrupts;
+                       process_interrupt(port_int_reg, icom_port);
+                       check_modem_status(icom_port);
+               }
+               if (adapter_interrupts & 0x3FFF0000) {
+                       /* port 3 interrupt */
+                       icom_port = &icom_adapter->port_info[3];
+                       if (icom_port->status == ICOM_PORT_ACTIVE) {
+                               port_int_reg =
+                                   (u16) (adapter_interrupts >> 16);
+                               process_interrupt(port_int_reg, icom_port);
+                               check_modem_status(icom_port);
+                       }
+               }
+
+               /* Clear out any pending interrupts */
+               writel(adapter_interrupts, (void *) int_reg);
+
+               int_reg = icom_adapter->base_addr + 0x8004;
+       } else {
+               int_reg = icom_adapter->base_addr + 0x4004;
+       }
+
+       adapter_interrupts = readl((void *) int_reg);
+
+       if (adapter_interrupts & 0x00003FFF) {
+               /* port 0 interrupt, NOTE:  for all adapters, port 0 will be active */
+               icom_port = &icom_adapter->port_info[0];
+               port_int_reg = (u16) adapter_interrupts;
+               process_interrupt(port_int_reg, icom_port);
+               check_modem_status(icom_port);
+       }
+       if (adapter_interrupts & 0x3FFF0000) {
+               /* port 1 interrupt */
+               icom_port = &icom_adapter->port_info[1];
+               if (icom_port->status == ICOM_PORT_ACTIVE) {
+                       port_int_reg = (u16) (adapter_interrupts >> 16);
+                       process_interrupt(port_int_reg, icom_port);
+                       check_modem_status(icom_port);
+               }
+       }
+
+       /* Clear out any pending interrupts */
+       writel(adapter_interrupts, (void *) int_reg);
+
+       /* flush the write */
+       adapter_interrupts = readl((void *) int_reg);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * ------------------------------------------------------------------
+ * Begin serial-core API
+ * ------------------------------------------------------------------
+ */
+static unsigned int icom_tx_empty(struct uart_port *port)
+{
+       int ret;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->lock, flags);
+       if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
+           SA_FLAGS_READY_TO_XMIT)
+               ret = TIOCSER_TEMT;
+       else
+               ret = 0;
+
+       spin_unlock_irqrestore(&port->lock, flags);
+       return ret;
+}
+
+static void icom_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       unsigned char local_osr;
+
+       trace(ICOM_PORT, "SET_MODEM", 0);
+       local_osr = readb(&ICOM_PORT->dram->osr);
+
+       if (mctrl & TIOCM_RTS) {
+               trace(ICOM_PORT, "RAISE_RTS", 0);
+               local_osr |= ICOM_RTS;
+       } else {
+               trace(ICOM_PORT, "LOWER_RTS", 0);
+               local_osr &= ~ICOM_RTS;
+       }
+
+       if (mctrl & TIOCM_DTR) {
+               trace(ICOM_PORT, "RAISE_DTR", 0);
+               local_osr |= ICOM_DTR;
+       } else {
+               trace(ICOM_PORT, "LOWER_DTR", 0);
+               local_osr &= ~ICOM_DTR;
+       }
+
+       writeb(local_osr, &ICOM_PORT->dram->osr);
+}
+
+static unsigned int icom_get_mctrl(struct uart_port *port)
+{
+       unsigned char status;
+       unsigned int result;
+
+       trace(ICOM_PORT, "GET_MODEM", 0);
+
+       status = readb(&ICOM_PORT->dram->isr);
+
+       result = ((status & ICOM_DCD) ? TIOCM_CAR : 0)
+           | ((status & ICOM_RI) ? TIOCM_RNG : 0)
+           | ((status & ICOM_DSR) ? TIOCM_DSR : 0)
+           | ((status & ICOM_CTS) ? TIOCM_CTS : 0);
+       return result;
+}
+
+static void icom_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+       unsigned char cmdReg;
+
+       if (tty_stop) {
+               trace(ICOM_PORT, "STOP", 0);
+               cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+               writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
+       }
+}
+
+static void icom_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+       unsigned char cmdReg;
+
+       trace(ICOM_PORT, "START", 0);
+       cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+       if ((cmdReg & CMD_HOLD_XMIT) == CMD_HOLD_XMIT)
+               writeb(cmdReg & ~CMD_HOLD_XMIT,
+                      &ICOM_PORT->dram->CmdReg);
+
+       icom_write(port);
+}
+
+static void icom_send_xchar(struct uart_port *port, char ch)
+{
+       unsigned char xdata;
+       int index;
+       unsigned long flags;
+
+       trace(ICOM_PORT, "SEND_XCHAR", ch);
+
+       /* wait .1 sec to send char */
+       for (index = 0; index < 10; index++) {
+               spin_lock_irqsave(&port->lock, flags);
+               xdata = readb(&ICOM_PORT->dram->xchar);
+               if (xdata == 0x00) {
+                       trace(ICOM_PORT, "QUICK_WRITE", 0);
+                       writeb(ch, &ICOM_PORT->dram->xchar);
+
+                       /* flush write operation */
+                       xdata = readb(&ICOM_PORT->dram->xchar);
+                       spin_unlock_irqrestore(&port->lock, flags);
+                       break;
+               }
+               spin_unlock_irqrestore(&port->lock, flags);
+               msleep(10);
+       }
+}
+
+static void icom_stop_rx(struct uart_port *port)
+{
+       unsigned char cmdReg;
+
+       cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+       writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
+}
+
+static void icom_enable_ms(struct uart_port *port)
+{
+       /* no-op */
+}
+
+static void icom_break(struct uart_port *port, int break_state)
+{
+       unsigned char cmdReg;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->lock, flags);
+       trace(ICOM_PORT, "BREAK", 0);
+       cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+       if (break_state == -1) {
+               writeb(cmdReg | CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
+       } else {
+               writeb(cmdReg & ~CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
+       }
+       spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int icom_open(struct uart_port *port)
+{
+       int retval;
+
+       kobject_get(&ICOM_PORT->adapter->kobj);
+       retval = startup(ICOM_PORT);
+
+       if (retval) {
+               kobject_put(&ICOM_PORT->adapter->kobj);
+               trace(ICOM_PORT, "STARTUP_ERROR", 0);
+               return retval;
+       }
+
+       return 0;
+}
+
+static void icom_close(struct uart_port *port)
+{
+       unsigned char cmdReg;
+
+       trace(ICOM_PORT, "CLOSE", 0);
+
+       /* stop receiver */
+       cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+       writeb(cmdReg & (unsigned char) ~CMD_RCV_ENABLE,
+              &ICOM_PORT->dram->CmdReg);
+
+       shutdown(ICOM_PORT);
+
+       kobject_put(&ICOM_PORT->adapter->kobj);
+}
+
+static void icom_set_termios(struct uart_port *port,
+                            struct termios *termios,
+                            struct termios *old_termios)
+{
+       int baud;
+       unsigned cflag, iflag;
+       int bits;
+       char new_config2;
+       char new_config3 = 0;
+       char tmp_byte;
+       int index;
+       int rcv_buff, xmit_buff;
+       unsigned long offset;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->lock, flags);
+       trace(ICOM_PORT, "CHANGE_SPEED", 0);
+
+       cflag = termios->c_cflag;
+       iflag = termios->c_iflag;
+
+       new_config2 = ICOM_ACFG_DRIVE1;
+
+       /* byte size and parity */
+       switch (cflag & CSIZE) {
+       case CS5:               /* 5 bits/char */
+               new_config2 |= ICOM_ACFG_5BPC;
+               bits = 7;
+               break;
+       case CS6:               /* 6 bits/char */
+               new_config2 |= ICOM_ACFG_6BPC;
+               bits = 8;
+               break;
+       case CS7:               /* 7 bits/char */
+               new_config2 |= ICOM_ACFG_7BPC;
+               bits = 9;
+               break;
+       case CS8:               /* 8 bits/char */
+               new_config2 |= ICOM_ACFG_8BPC;
+               bits = 10;
+               break;
+       default:
+               bits = 10;
+               break;
+       }
+       if (cflag & CSTOPB) {
+               /* 2 stop bits */
+               new_config2 |= ICOM_ACFG_2STOP_BIT;
+               bits++;
+       }
+       if (cflag & PARENB) {
+               /* parity bit enabled */
+               new_config2 |= ICOM_ACFG_PARITY_ENAB;
+               trace(ICOM_PORT, "PARENB", 0);
+               bits++;
+       }
+       if (cflag & PARODD) {
+               /* odd parity */
+               new_config2 |= ICOM_ACFG_PARITY_ODD;
+               trace(ICOM_PORT, "PARODD", 0);
+       }
+
+       /* Determine divisor based on baud rate */
+       baud = uart_get_baud_rate(port, termios, old_termios,
+                                 icom_acfg_baud[0],
+                                 icom_acfg_baud[BAUD_TABLE_LIMIT]);
+       if (!baud)
+               baud = 9600;    /* B0 transition handled in rs_set_termios */
+
+       for (index = 0; index < BAUD_TABLE_LIMIT; index++) {
+               if (icom_acfg_baud[index] == baud) {
+                       new_config3 = index;
+                       break;
+               }
+       }
+
+       uart_update_timeout(port, cflag, baud);
+
+       /* CTS flow control flag and modem status interrupts */
+       tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
+       if (cflag & CRTSCTS)
+               tmp_byte |= HDLC_HDW_FLOW;
+       else
+               tmp_byte &= ~HDLC_HDW_FLOW;
+       writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
+
+       /*
+        * Set up parity check flag
+        */
+       ICOM_PORT->read_status_mask = SA_FLAGS_OVERRUN | SA_FL_RCV_DONE;
+       if (iflag & INPCK)
+               ICOM_PORT->read_status_mask |=
+                   SA_FLAGS_FRAME_ERROR | SA_FLAGS_PARITY_ERROR;
+
+       if ((iflag & BRKINT) || (iflag & PARMRK))
+               ICOM_PORT->read_status_mask |= SA_FLAGS_BREAK_DET;
+
+       /*
+        * Characters to ignore
+        */
+       ICOM_PORT->ignore_status_mask = 0;
+       if (iflag & IGNPAR)
+               ICOM_PORT->ignore_status_mask |=
+                   SA_FLAGS_PARITY_ERROR | SA_FLAGS_FRAME_ERROR;
+       if (iflag & IGNBRK) {
+               ICOM_PORT->ignore_status_mask |= SA_FLAGS_BREAK_DET;
+               /*
+                * If we're ignore parity and break indicators, ignore
+                * overruns too.  (For real raw support).
+                */
+               if (iflag & IGNPAR)
+                       ICOM_PORT->ignore_status_mask |= SA_FLAGS_OVERRUN;
+       }
+
+       /*
+        * !!! ignore all characters if CREAD is not set
+        */
+       if ((cflag & CREAD) == 0)
+               ICOM_PORT->ignore_status_mask |= SA_FL_RCV_DONE;
+
+       /* Turn off Receiver to prepare for reset */
+       writeb(CMD_RCV_DISABLE, &ICOM_PORT->dram->CmdReg);
+
+       for (index = 0; index < 10; index++) {
+               if (readb(&ICOM_PORT->dram->PrevCmdReg) == 0x00) {
+                       break;
+               }
+       }
+
+       /* clear all current buffers of data */
+       for (rcv_buff = 0; rcv_buff < NUM_RBUFFS; rcv_buff++) {
+               ICOM_PORT->statStg->rcv[rcv_buff].flags = 0;
+               ICOM_PORT->statStg->rcv[rcv_buff].leLength = 0;
+               ICOM_PORT->statStg->rcv[rcv_buff].WorkingLength =
+                   (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
+       }
+
+       for (xmit_buff = 0; xmit_buff < NUM_XBUFFS; xmit_buff++) {
+               ICOM_PORT->statStg->xmit[xmit_buff].flags = 0;
+       }
+
+       /* activate changes and start xmit and receiver here */
+       /* Enable the receiver */
+       writeb(new_config3, &(ICOM_PORT->dram->async_config3));
+       writeb(new_config2, &(ICOM_PORT->dram->async_config2));
+       tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
+       tmp_byte |= HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL;
+       writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
+       writeb(0x04, &(ICOM_PORT->dram->FlagFillIdleTimer));    /* 0.5 seconds */
+       writeb(0xFF, &(ICOM_PORT->dram->ier));  /* enable modem signal interrupts */
+
+       /* reset processor */
+       writeb(CMD_RESTART, &ICOM_PORT->dram->CmdReg);
+
+       for (index = 0; index < 10; index++) {
+               if (readb(&ICOM_PORT->dram->CmdReg) == 0x00) {
+                       break;
+               }
+       }
+
+       /* Enable Transmitter and Reciever */
+       offset =
+           (unsigned long) &ICOM_PORT->statStg->rcv[0] -
+           (unsigned long) ICOM_PORT->statStg;
+       writel(ICOM_PORT->statStg_pci + offset,
+              &ICOM_PORT->dram->RcvStatusAddr);
+       ICOM_PORT->next_rcv = 0;
+       ICOM_PORT->put_length = 0;
+       *ICOM_PORT->xmitRestart = 0;
+       writel(ICOM_PORT->xmitRestart_pci,
+              &ICOM_PORT->dram->XmitStatusAddr);
+       trace(ICOM_PORT, "XR_ENAB", 0);
+       writeb(CMD_XMIT_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
+
+       spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *icom_type(struct uart_port *port)
+{
+       return "icom";
+}
+
+static void icom_release_port(struct uart_port *port)
+{
+}
+
+static int icom_request_port(struct uart_port *port)
+{
+       return 0;
+}
+
+static void icom_config_port(struct uart_port *port, int flags)
+{
+       port->type = PORT_ICOM;
+}
+
+static struct uart_ops icom_ops = {
+       .tx_empty = icom_tx_empty,
+       .set_mctrl = icom_set_mctrl,
+       .get_mctrl = icom_get_mctrl,
+       .stop_tx = icom_stop_tx,
+       .start_tx = icom_start_tx,
+       .send_xchar = icom_send_xchar,
+       .stop_rx = icom_stop_rx,
+       .enable_ms = icom_enable_ms,
+       .break_ctl = icom_break,
+       .startup = icom_open,
+       .shutdown = icom_close,
+       .set_termios = icom_set_termios,
+       .type = icom_type,
+       .release_port = icom_release_port,
+       .request_port = icom_request_port,
+       .config_port = icom_config_port,
+};
+
+#define ICOM_CONSOLE NULL
+
+static struct uart_driver icom_uart_driver = {
+       .owner = THIS_MODULE,
+       .driver_name = ICOM_DRIVER_NAME,
+       .dev_name = "ttyA",
+       .major = ICOM_MAJOR,
+       .minor = ICOM_MINOR_START,
+       .nr = NR_PORTS,
+       .cons = ICOM_CONSOLE,
+};
+
+static int __devinit icom_init_ports(struct icom_adapter *icom_adapter)
+{
+       u32 subsystem_id = icom_adapter->subsystem_id;
+       int retval = 0;
+       int i;
+       struct icom_port *icom_port;
+
+       if (icom_adapter->version == ADAPTER_V1) {
+               icom_adapter->numb_ports = 2;
+
+               for (i = 0; i < 2; i++) {
+                       icom_port = &icom_adapter->port_info[i];
+                       icom_port->port = i;
+                       icom_port->status = ICOM_PORT_ACTIVE;
+                       icom_port->imbed_modem = ICOM_UNKNOWN;
+               }
+       } else {
+               if (subsystem_id == PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL) {
+                       icom_adapter->numb_ports = 4;
+
+                       for (i = 0; i < 4; i++) {
+                               icom_port = &icom_adapter->port_info[i];
+
+                               icom_port->port = i;
+                               icom_port->status = ICOM_PORT_ACTIVE;
+                               icom_port->imbed_modem = ICOM_IMBED_MODEM;
+                       }
+               } else {
+                       icom_adapter->numb_ports = 4;
+
+                       icom_adapter->port_info[0].port = 0;
+                       icom_adapter->port_info[0].status = ICOM_PORT_ACTIVE;
+
+                       if (subsystem_id ==
+                           PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM) {
+                               icom_adapter->port_info[0].imbed_modem = ICOM_IMBED_MODEM;
+                       } else {
+                               icom_adapter->port_info[0].imbed_modem = ICOM_RVX;
+                       }
+
+                       icom_adapter->port_info[1].status = ICOM_PORT_OFF;
+
+                       icom_adapter->port_info[2].port = 2;
+                       icom_adapter->port_info[2].status = ICOM_PORT_ACTIVE;
+                       icom_adapter->port_info[2].imbed_modem = ICOM_RVX;
+                       icom_adapter->port_info[3].status = ICOM_PORT_OFF;
+               }
+       }
+
+       return retval;
+}
+
+static void icom_port_active(struct icom_port *icom_port, struct icom_adapter *icom_adapter, int port_num)
+{
+       if (icom_adapter->version == ADAPTER_V1) {
+               icom_port->global_reg = (struct icom_regs *) ((char *)
+                       icom_adapter->base_addr + 0x4000);
+               icom_port->int_reg = (unsigned long) icom_adapter->base_addr +
+                   0x4004 + 2 - 2 * port_num;
+       } else {
+               icom_port->global_reg = (struct icom_regs *) ((char *)
+                       icom_adapter->base_addr + 0x8000);
+               if (icom_port->port < 2)
+                       icom_port->int_reg = (unsigned long) icom_adapter->base_addr +
+                           0x8004 + 2 - 2 * icom_port->port;
+               else
+                       icom_port->int_reg = (unsigned long) icom_adapter->base_addr +
+                           0x8024 + 2 - 2 * (icom_port->port - 2);
+       }
+}
+static int __init icom_load_ports(struct icom_adapter *icom_adapter)
+{
+       struct icom_port *icom_port;
+       int port_num;
+       int retval;
+
+       for (port_num = 0; port_num < icom_adapter->numb_ports; port_num++) {
+
+               icom_port = &icom_adapter->port_info[port_num];
+
+               if (icom_port->status == ICOM_PORT_ACTIVE) {
+                       icom_port_active(icom_port, icom_adapter, port_num);
+                       icom_port->dram = (struct func_dram *) ((char *)
+                                       icom_adapter->base_addr +
+                                       0x2000 * icom_port->port);
+
+                       icom_port->adapter = icom_adapter;
+
+                       /* get port memory */
+                       if ((retval = get_port_memory(icom_port)) != 0) {
+                               dev_err(&icom_port->adapter->pci_dev->dev,
+                                       "Memory allocation for port FAILED\n");
+                       }
+               }
+       }
+       return 0;
+}
+
+static int __devinit icom_alloc_adapter(struct icom_adapter
+                                       **icom_adapter_ref)
+{
+       int adapter_count = 0;
+       struct icom_adapter *icom_adapter;
+       struct icom_adapter *cur_adapter_entry;
+       struct list_head *tmp;
+
+       icom_adapter = (struct icom_adapter *)
+           kmalloc(sizeof(struct icom_adapter), GFP_KERNEL);
+
+       if (!icom_adapter) {
+               return -ENOMEM;
+       }
+
+       memset(icom_adapter, 0, sizeof(struct icom_adapter));
+
+       list_for_each(tmp, &icom_adapter_head) {
+               cur_adapter_entry =
+                   list_entry(tmp, struct icom_adapter,
+                              icom_adapter_entry);
+               if (cur_adapter_entry->index != adapter_count) {
+                       break;
+               }
+               adapter_count++;
+       }
+
+       icom_adapter->index = adapter_count;
+       list_add_tail(&icom_adapter->icom_adapter_entry, tmp);
+
+       *icom_adapter_ref = icom_adapter;
+       return 0;
+}
+
+static void icom_free_adapter(struct icom_adapter *icom_adapter)
+{
+       list_del(&icom_adapter->icom_adapter_entry);
+       kfree(icom_adapter);
+}
+
+static void icom_remove_adapter(struct icom_adapter *icom_adapter)
+{
+       struct icom_port *icom_port;
+       int index;
+
+       for (index = 0; index < icom_adapter->numb_ports; index++) {
+               icom_port = &icom_adapter->port_info[index];
+
+               if (icom_port->status == ICOM_PORT_ACTIVE) {
+                       dev_info(&icom_adapter->pci_dev->dev,
+                                "Device removed\n");
+
+                       uart_remove_one_port(&icom_uart_driver,
+                                            &icom_port->uart_port);
+
+                       /* be sure that DTR and RTS are dropped */
+                       writeb(0x00, &icom_port->dram->osr);
+
+                       /* Wait 0.1 Sec for simple Init to complete */
+                       msleep(100);
+
+                       /* Stop proccessor */
+                       stop_processor(icom_port);
+
+                       free_port_memory(icom_port);
+               }
+       }
+
+       free_irq(icom_adapter->irq_number, (void *) icom_adapter);
+       iounmap((void *) icom_adapter->base_addr);
+       icom_free_adapter(icom_adapter);
+       pci_release_regions(icom_adapter->pci_dev);
+}
+
+static void icom_kobj_release(struct kobject *kobj)
+{
+       struct icom_adapter *icom_adapter;
+
+       icom_adapter = to_icom_adapter(kobj);
+       icom_remove_adapter(icom_adapter);
+}
+
+static struct kobj_type icom_kobj_type = {
+       .release = icom_kobj_release,
+};
+
+static int __devinit icom_probe(struct pci_dev *dev,
+                               const struct pci_device_id *ent)
+{
+       int index;
+        unsigned int command_reg;
+        int retval;
+        struct icom_adapter *icom_adapter;
+        struct icom_port *icom_port;
+
+        retval = pci_enable_device(dev);
+        if (retval) {
+               dev_err(&dev->dev, "Device enable FAILED\n");
+                return retval;
+       }
+
+       if ( (retval = pci_request_regions(dev, "icom"))) {
+                dev_err(&dev->dev, "pci_request_region FAILED\n");
+                pci_disable_device(dev);
+                return retval;
+        }
+
+        pci_set_master(dev);
+
+        if ( (retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg))) {
+               dev_err(&dev->dev, "PCI Config read FAILED\n");
+                return retval;
+        }
+
+       pci_write_config_dword(dev, PCI_COMMAND,
+               command_reg | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
+               | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+
+        if (ent->driver_data == ADAPTER_V1) {
+               pci_write_config_dword(dev, 0x44, 0x8300830A);
+        } else {
+               pci_write_config_dword(dev, 0x44, 0x42004200);
+               pci_write_config_dword(dev, 0x48, 0x42004200);
+         }
+
+
+       retval = icom_alloc_adapter(&icom_adapter);
+       if (retval) {
+                dev_err(&dev->dev, "icom_alloc_adapter FAILED\n");
+                retval = -EIO;
+                goto probe_exit0;
+       }
+
+        icom_adapter->base_addr_pci = pci_resource_start(dev, 0);
+        icom_adapter->irq_number = dev->irq;
+        icom_adapter->pci_dev = dev;
+        icom_adapter->version = ent->driver_data;
+        icom_adapter->subsystem_id = ent->subdevice;
+
+
+       retval = icom_init_ports(icom_adapter);
+       if (retval) {
+               dev_err(&dev->dev, "Port configuration failed\n");
+               goto probe_exit1;
+       }
+
+        icom_adapter->base_addr =
+            (unsigned long) ioremap(icom_adapter->base_addr_pci,
+                                               pci_resource_len(dev, 0));
+
+       if (!icom_adapter->base_addr)
+               goto probe_exit1;
+
+        /* save off irq and request irq line */
+        if ( (retval = request_irq(dev->irq, icom_interrupt,
+                                  SA_INTERRUPT | SA_SHIRQ, ICOM_DRIVER_NAME,
+                                  (void *) icom_adapter))) {
+                 goto probe_exit2;
+        }
+
+       retval = icom_load_ports(icom_adapter);
+
+        for (index = 0; index < icom_adapter->numb_ports; index++) {
+               icom_port = &icom_adapter->port_info[index];
+
+               if (icom_port->status == ICOM_PORT_ACTIVE) {
+                       icom_port->uart_port.irq = icom_port->adapter->irq_number;
+                       icom_port->uart_port.type = PORT_ICOM;
+                       icom_port->uart_port.iotype = UPIO_MEM;
+                       icom_port->uart_port.membase =
+                                              (char *) icom_adapter->base_addr_pci;
+                       icom_port->uart_port.fifosize = 16;
+                       icom_port->uart_port.ops = &icom_ops;
+                       icom_port->uart_port.line =
+                       icom_port->port + icom_adapter->index * 4;
+                       if (uart_add_one_port (&icom_uart_driver, &icom_port->uart_port)) {
+                               icom_port->status = ICOM_PORT_OFF;
+                               dev_err(&dev->dev, "Device add failed\n");
+                        } else
+                               dev_info(&dev->dev, "Device added\n");
+               }
+       }
+
+       kobject_init(&icom_adapter->kobj);
+       icom_adapter->kobj.ktype = &icom_kobj_type;
+       return 0;
+
+probe_exit2:
+       iounmap((void *) icom_adapter->base_addr);
+probe_exit1:
+       icom_free_adapter(icom_adapter);
+
+probe_exit0:
+       pci_release_regions(dev);
+       pci_disable_device(dev);
+
+        return retval;
+
+
+}
+
+static void __devexit icom_remove(struct pci_dev *dev)
+{
+       struct icom_adapter *icom_adapter;
+       struct list_head *tmp;
+
+       list_for_each(tmp, &icom_adapter_head) {
+               icom_adapter = list_entry(tmp, struct icom_adapter,
+                                         icom_adapter_entry);
+               if (icom_adapter->pci_dev == dev) {
+                       kobject_put(&icom_adapter->kobj);
+                       return;
+               }
+       }
+
+       dev_err(&dev->dev, "Unable to find device to remove\n");
+}
+
+static struct pci_driver icom_pci_driver = {
+       .name = ICOM_DRIVER_NAME,
+       .id_table = icom_pci_table,
+       .probe = icom_probe,
+       .remove = __devexit_p(icom_remove),
+};
+
+static int __init icom_init(void)
+{
+       int ret;
+
+       spin_lock_init(&icom_lock);
+       icom_lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+
+       ret = uart_register_driver(&icom_uart_driver);
+       if (ret)
+               return ret;
+
+       ret = pci_register_driver(&icom_pci_driver);
+
+       if (ret < 0)
+               uart_unregister_driver(&icom_uart_driver);
+
+       return ret;
+}
+
+static void __exit icom_exit(void)
+{
+       pci_unregister_driver(&icom_pci_driver);
+       uart_unregister_driver(&icom_uart_driver);
+}
+
+module_init(icom_init);
+module_exit(icom_exit);
+
+#ifdef ICOM_TRACE
+static inline void trace(struct icom_port *icom_port, char *trace_pt,
+                 unsigned long trace_data)
+{
+       dev_info(&icom_port->adapter->pci_dev->dev, ":%d:%s - %lx\n",
+                icom_port->port, trace_pt, trace_data);
+}
+#endif
+
+MODULE_AUTHOR("Michael Anderson <mjanders@us.ibm.com>");
+MODULE_DESCRIPTION("IBM iSeries Serial IOA driver");
+MODULE_SUPPORTED_DEVICE
+    ("IBM iSeries 2745, 2771, 2772, 2742, 2793 and 2805 Communications adapters");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/serial/icom.h b/drivers/serial/icom.h
new file mode 100644 (file)
index 0000000..479b52d
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * icom.h
+ *
+ * Copyright (C) 2001 Michael Anderson, IBM Corporation
+ *
+ * Serial device driver include file.
+ *
+ * This program is free software; you can redistribute 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/serial_core.h>
+
+#define BAUD_TABLE_LIMIT       ((sizeof(icom_acfg_baud)/sizeof(int)) - 1)
+static int icom_acfg_baud[] = {
+       300,
+       600,
+       900,
+       1200,
+       1800,
+       2400,
+       3600,
+       4800,
+       7200,
+       9600,
+       14400,
+       19200,
+       28800,
+       38400,
+       57600,
+       76800,
+       115200,
+       153600,
+       230400,
+       307200,
+       460800,
+};
+
+struct icom_regs {
+       u32 control;            /* Adapter Control Register     */
+       u32 interrupt;          /* Adapter Interrupt Register   */
+       u32 int_mask;           /* Adapter Interrupt Mask Reg   */
+       u32 int_pri;            /* Adapter Interrupt Priority r */
+       u32 int_reg_b;          /* Adapter non-masked Interrupt */
+       u32 resvd01;
+       u32 resvd02;
+       u32 resvd03;
+       u32 control_2;          /* Adapter Control Register 2   */
+       u32 interrupt_2;        /* Adapter Interrupt Register 2 */
+       u32 int_mask_2;         /* Adapter Interrupt Mask 2     */
+       u32 int_pri_2;          /* Adapter Interrupt Prior 2    */
+       u32 int_reg_2b;         /* Adapter non-masked 2         */
+};
+
+struct func_dram {
+       u32 reserved[108];      /* 0-1B0   reserved by personality code */
+       u32 RcvStatusAddr;      /* 1B0-1B3 Status Address for Next rcv */
+       u8 RcvStnAddr;          /* 1B4     Receive Station Addr */
+       u8 IdleState;           /* 1B5     Idle State */
+       u8 IdleMonitor;         /* 1B6     Idle Monitor */
+       u8 FlagFillIdleTimer;   /* 1B7     Flag Fill Idle Timer */
+       u32 XmitStatusAddr;     /* 1B8-1BB Transmit Status Address */
+       u8 StartXmitCmd;        /* 1BC     Start Xmit Command */
+       u8 HDLCConfigReg;       /* 1BD     Reserved */
+       u8 CauseCode;           /* 1BE     Cause code for fatal error */
+       u8 xchar;               /* 1BF     High priority send */
+       u32 reserved3;          /* 1C0-1C3 Reserved */
+       u8 PrevCmdReg;          /* 1C4     Reserved */
+       u8 CmdReg;              /* 1C5     Command Register */
+       u8 async_config2;       /* 1C6     Async Config Byte 2 */
+       u8 async_config3;       /* 1C7     Async Config Byte 3 */
+       u8 dce_resvd[20];       /* 1C8-1DB DCE Rsvd           */
+       u8 dce_resvd21;         /* 1DC     DCE Rsvd (21st byte */
+       u8 misc_flags;          /* 1DD     misc flags         */
+#define V2_HARDWARE     0x40
+#define ICOM_HDW_ACTIVE 0x01
+       u8 call_length;         /* 1DE     Phone #/CFI buff ln */
+       u8 call_length2;        /* 1DF     Upper byte (unused) */
+       u32 call_addr;          /* 1E0-1E3 Phn #/CFI buff addr */
+       u16 timer_value;        /* 1E4-1E5 general timer value */
+       u8 timer_command;       /* 1E6     general timer cmd  */
+       u8 dce_command;         /* 1E7     dce command reg    */
+       u8 dce_cmd_status;      /* 1E8     dce command stat   */
+       u8 x21_r1_ioff;         /* 1E9     dce ready counter  */
+       u8 x21_r0_ioff;         /* 1EA     dce not ready ctr  */
+       u8 x21_ralt_ioff;       /* 1EB     dce CNR counter    */
+       u8 x21_r1_ion;          /* 1EC     dce ready I on ctr */
+       u8 rsvd_ier;            /* 1ED     Rsvd for IER (if ne */
+       u8 ier;                 /* 1EE     Interrupt Enable   */
+       u8 isr;                 /* 1EF     Input Signal Reg   */
+       u8 osr;                 /* 1F0     Output Signal Reg  */
+       u8 reset;               /* 1F1     Reset/Reload Reg   */
+       u8 disable;             /* 1F2     Disable Reg        */
+       u8 sync;                /* 1F3     Sync Reg           */
+       u8 error_stat;          /* 1F4     Error Status       */
+       u8 cable_id;            /* 1F5     Cable ID           */
+       u8 cs_length;           /* 1F6     CS Load Length     */
+       u8 mac_length;          /* 1F7     Mac Load Length    */
+       u32 cs_load_addr;       /* 1F8-1FB Call Load PCI Addr */
+       u32 mac_load_addr;      /* 1FC-1FF Mac Load PCI Addr  */
+};
+
+/*
+ * adapter defines and structures
+ */
+#define ICOM_CONTROL_START_A         0x00000008
+#define ICOM_CONTROL_STOP_A          0x00000004
+#define ICOM_CONTROL_START_B         0x00000002
+#define ICOM_CONTROL_STOP_B          0x00000001
+#define ICOM_CONTROL_START_C         0x00000008
+#define ICOM_CONTROL_STOP_C          0x00000004
+#define ICOM_CONTROL_START_D         0x00000002
+#define ICOM_CONTROL_STOP_D          0x00000001
+#define ICOM_IRAM_OFFSET             0x1000
+#define ICOM_IRAM_SIZE               0x0C00
+#define ICOM_DCE_IRAM_OFFSET         0x0A00
+#define ICOM_CABLE_ID_VALID          0x01
+#define ICOM_CABLE_ID_MASK           0xF0
+#define ICOM_DISABLE                 0x80
+#define CMD_XMIT_RCV_ENABLE          0xC0
+#define CMD_XMIT_ENABLE              0x40
+#define CMD_RCV_DISABLE              0x00
+#define CMD_RCV_ENABLE               0x80
+#define CMD_RESTART                  0x01
+#define CMD_HOLD_XMIT                0x02
+#define CMD_SND_BREAK                0x04
+#define RS232_CABLE                  0x06
+#define V24_CABLE                    0x0E
+#define V35_CABLE                    0x0C
+#define V36_CABLE                    0x02
+#define NO_CABLE                     0x00
+#define START_DOWNLOAD               0x80
+#define ICOM_INT_MASK_PRC_A          0x00003FFF
+#define ICOM_INT_MASK_PRC_B          0x3FFF0000
+#define ICOM_INT_MASK_PRC_C          0x00003FFF
+#define ICOM_INT_MASK_PRC_D          0x3FFF0000
+#define INT_RCV_COMPLETED            0x1000
+#define INT_XMIT_COMPLETED           0x2000
+#define INT_IDLE_DETECT              0x0800
+#define INT_RCV_DISABLED             0x0400
+#define INT_XMIT_DISABLED            0x0200
+#define INT_RCV_XMIT_SHUTDOWN        0x0100
+#define INT_FATAL_ERROR              0x0080
+#define INT_CABLE_PULL               0x0020
+#define INT_SIGNAL_CHANGE            0x0010
+#define HDLC_PPP_PURE_ASYNC          0x02
+#define HDLC_FF_FILL                 0x00
+#define HDLC_HDW_FLOW                0x01
+#define START_XMIT                   0x80
+#define ICOM_ACFG_DRIVE1             0x20
+#define ICOM_ACFG_NO_PARITY          0x00
+#define ICOM_ACFG_PARITY_ENAB        0x02
+#define ICOM_ACFG_PARITY_ODD         0x01
+#define ICOM_ACFG_8BPC               0x00
+#define ICOM_ACFG_7BPC               0x04
+#define ICOM_ACFG_6BPC               0x08
+#define ICOM_ACFG_5BPC               0x0C
+#define ICOM_ACFG_1STOP_BIT          0x00
+#define ICOM_ACFG_2STOP_BIT          0x10
+#define ICOM_DTR                     0x80
+#define ICOM_RTS                     0x40
+#define ICOM_RI                      0x08
+#define ICOM_DSR                     0x80
+#define ICOM_DCD                     0x20
+#define ICOM_CTS                     0x40
+
+#define NUM_XBUFFS 1
+#define NUM_RBUFFS 2
+#define RCV_BUFF_SZ 0x0200
+#define XMIT_BUFF_SZ 0x1000
+struct statusArea {
+    /**********************************************/
+       /* Transmit Status Area                       */
+    /**********************************************/
+       struct xmit_status_area{
+               u32 leNext;     /* Next entry in Little Endian on Adapter */
+               u32 leNextASD;
+               u32 leBuffer;   /* Buffer for entry in LE for Adapter */
+               u16 leLengthASD;
+               u16 leOffsetASD;
+               u16 leLength;   /* Length of data in segment */
+               u16 flags;
+#define SA_FLAGS_DONE           0x0080 /* Done with Segment */
+#define SA_FLAGS_CONTINUED      0x8000 /* More Segments */
+#define SA_FLAGS_IDLE           0x4000 /* Mark IDLE after frm */
+#define SA_FLAGS_READY_TO_XMIT  0x0800
+#define SA_FLAGS_STAT_MASK      0x007F
+       } xmit[NUM_XBUFFS];
+
+    /**********************************************/
+       /* Receive Status Area                        */
+    /**********************************************/
+       struct {
+               u32 leNext;     /* Next entry in Little Endian on Adapter */
+               u32 leNextASD;
+               u32 leBuffer;   /* Buffer for entry in LE for Adapter */
+               u16 WorkingLength;      /* size of segment */
+               u16 reserv01;
+               u16 leLength;   /* Length of data in segment */
+               u16 flags;
+#define SA_FL_RCV_DONE           0x0010        /* Data ready */
+#define SA_FLAGS_OVERRUN         0x0040
+#define SA_FLAGS_PARITY_ERROR    0x0080
+#define SA_FLAGS_FRAME_ERROR     0x0001
+#define SA_FLAGS_FRAME_TRUNC     0x0002
+#define SA_FLAGS_BREAK_DET       0x0004        /* set conditionally by device driver, not hardware */
+#define SA_FLAGS_RCV_MASK        0xFFE6
+       } rcv[NUM_RBUFFS];
+};
+
+struct icom_adapter;
+
+
+#define ICOM_MAJOR       243
+#define ICOM_MINOR_START 0
+
+struct icom_port {
+       struct uart_port uart_port;
+       u8 imbed_modem;
+#define ICOM_UNKNOWN           1
+#define ICOM_RVX               2
+#define ICOM_IMBED_MODEM       3
+       unsigned char cable_id;
+       unsigned char read_status_mask;
+       unsigned char ignore_status_mask;
+       unsigned long int_reg;
+       struct icom_regs *global_reg;
+       struct func_dram *dram;
+       int port;
+       struct statusArea *statStg;
+       dma_addr_t statStg_pci;
+       u32 *xmitRestart;
+       dma_addr_t xmitRestart_pci;
+       unsigned char *xmit_buf;
+       dma_addr_t xmit_buf_pci;
+       unsigned char *recv_buf;
+       dma_addr_t recv_buf_pci;
+       int next_rcv;
+       int put_length;
+       int status;
+#define ICOM_PORT_ACTIVE       1       /* Port exists. */
+#define ICOM_PORT_OFF          0       /* Port does not exist. */
+       int load_in_progress;
+       struct icom_adapter *adapter;
+};
+
+struct icom_adapter {
+       unsigned long base_addr;
+       unsigned long base_addr_pci;
+       unsigned char irq_number;
+       struct pci_dev *pci_dev;
+       struct icom_port port_info[4];
+       int index;
+       int version;
+#define ADAPTER_V1     0x0001
+#define ADAPTER_V2     0x0002
+       u32 subsystem_id;
+#define FOUR_PORT_MODEL                                0x0252
+#define V2_TWO_PORTS_RVX                       0x021A
+#define V2_ONE_PORT_RVX_ONE_PORT_IMBED_MDM     0x0251
+       int numb_ports;
+       struct list_head icom_adapter_entry;
+       struct kobject kobj;
+};
+
+/* prototype */
+extern void iCom_sercons_init(void);
+
+struct lookup_proc_table {
+       u32     *global_control_reg;
+       unsigned long   processor_id;
+};
+
+struct lookup_int_table {
+       u32     *global_int_mask;
+       unsigned long   processor_id;
+};
+
+#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000)
index dfed452..7f1b9ee 100644 (file)
@@ -424,11 +424,7 @@ static void mcfrs_offintr(void *private)
        tty = info->tty;
        if (!tty)
                return;
-
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
-       wake_up_interruptible(&tty->write_wait);
+       tty_wakeup(tty);
 }
 
 
@@ -835,10 +831,7 @@ static void mcfrs_flush_buffer(struct tty_struct *tty)
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
        local_irq_restore(flags);
 
-       wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
 }
 
 /*
@@ -1232,11 +1225,12 @@ static void mcfrs_close(struct tty_struct *tty, struct file * filp)
        shutdown(info);
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+       tty_ldisc_flush(tty);
+       
        tty->closing = 0;
        info->event = 0;
        info->tty = 0;
+#if 0  
        if (tty->ldisc.num != ldiscs[N_TTY].num) {
                if (tty->ldisc.close)
                        (tty->ldisc.close)(tty);
@@ -1245,6 +1239,7 @@ static void mcfrs_close(struct tty_struct *tty, struct file * filp)
                if (tty->ldisc.open)
                        (tty->ldisc.open)(tty);
        }
+#endif 
        if (info->blocked_open) {
                if (info->close_delay) {
                        current->state = TASK_INTERRUPTIBLE;
index 22a02bd..70d2f83 100644 (file)
@@ -26,8 +26,6 @@
 #include <asm/hardware.h>
 #include <asm/arch/regs-serial.h>
 
-#include <asm/mach-types.h>
-
 #if 0
 #include <asm/debug-ll.h>
 #define dbg(x...) llprintk(x)
@@ -677,7 +675,7 @@ serial_s3c2410_get_options(struct uart_port *port, int *baud,
 
                default:
                case S3C2410_LCON_PNONE:
-                       /* nothing */
+                       *parity = 'n';
                }
 
                /* now calculate the baud rate */
index c3e6eb2..8557ed1 100644 (file)
@@ -363,9 +363,10 @@ next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
 
 /*====================================================================*/
 
-static int simple_config(dev_link_t * link)
+static int simple_config(dev_link_t *link)
 {
        static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+       static int size_table[2] = { 8, 16 };
        client_handle_t handle = link->handle;
        struct serial_info *info = link->priv;
        tuple_t tuple;
@@ -374,6 +375,7 @@ static int simple_config(dev_link_t * link)
        cistpl_cftable_entry_t *cf = &parse.cftable_entry;
        config_info_t config;
        int i, j, try;
+       int s;
 
        /* If the card is already configured, look up the port and irq */
        i = pcmcia_get_configuration_info(handle, &config);
@@ -399,29 +401,30 @@ static int simple_config(dev_link_t * link)
        tuple.Attributes = 0;
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
        /* Two tries: without IO aliases, then with aliases */
-       for (try = 0; try < 2; try++) {
-               i = first_tuple(handle, &tuple, &parse);
-               while (i != CS_NO_MORE_ITEMS) {
-                       if (i != CS_SUCCESS)
-                               goto next_entry;
-                       if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-                               link->conf.Vpp1 = link->conf.Vpp2 =
-                                   cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-                       if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
-                           (cf->io.win[0].base != 0)) {
-                               link->conf.ConfigIndex = cf->index;
-                               link->io.BasePort1 = cf->io.win[0].base;
-                               link->io.IOAddrLines = (try == 0) ?
-                                   16 : cf->io.flags & CISTPL_IO_LINES_MASK;
-                               i = pcmcia_request_io(link->handle, &link->io);
-                               if (i == CS_SUCCESS)
-                                       goto found_port;
+       for (s = 0; s < 2; s++) {
+               for (try = 0; try < 2; try++) {
+                       i = first_tuple(handle, &tuple, &parse);
+                       while (i != CS_NO_MORE_ITEMS) {
+                               if (i != CS_SUCCESS)
+                                       goto next_entry;
+                               if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+                                       link->conf.Vpp1 = link->conf.Vpp2 =
+                                           cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+                               if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
+                                           (cf->io.win[0].base != 0)) {
+                                       link->conf.ConfigIndex = cf->index;
+                                       link->io.BasePort1 = cf->io.win[0].base;
+                                       link->io.IOAddrLines = (try == 0) ?
+                                           16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+                                       i = pcmcia_request_io(link->handle, &link->io);
+                                       if (i == CS_SUCCESS)
+                                               goto found_port;
+                               }
+next_entry:
+                               i = next_tuple(handle, &tuple, &parse);
                        }
-                     next_entry:
-                       i = next_tuple(handle, &tuple, &parse);
                }
        }
-
        /* Second pass: try to find an entry that isn't picky about
           its base address, then try to grab any standard serial port
           address, and finally try to get any free port. */
index 98b96c5..200bbce 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/miscdevice.h>
 #include <linux/serial_core.h>
 
+#include <asm/io.h>
 #include <asm/sn/simulator.h>
 #include <asm/sn/sn2/sn_private.h>
 #include <asm/sn/sn_sal.h>
 #define DEVICE_MAJOR 204
 #define DEVICE_MINOR 40
 
+#ifdef CONFIG_MAGIC_SYSRQ
+static char sysrq_serial_str[] = "\eSYS";
+static char *sysrq_serial_ptr = sysrq_serial_str;
+static unsigned long sysrq_requested;
+#endif /* CONFIG_MAGIC_SYSRQ */
+
 /*
  * Port definition - this kinda drives it all
  */
@@ -532,13 +539,15 @@ sn_debug_printf(const char *fmt, ...)
  * sn_receive_chars - Grab characters, pass them to tty layer
  * @port: Port to operate on
  * @regs: Saved registers (needed by uart_handle_sysrq_char)
+ * @flags: irq flags
  *
  * Note: If we're not registered with the serial core infrastructure yet,
  * we don't try to send characters to it...
  *
  */
 static void
-sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs)
+sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs,
+                unsigned long flags)
 {
        int ch;
        struct tty_struct *tty;
@@ -569,10 +578,34 @@ sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs)
                               "obtaining data from the console (0x%0x)\n", ch);
                        break;
                }
-#if defined(CONFIG_SERIAL_SGI_L1_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-               if (uart_handle_sysrq_char(&port->sc_port, ch, regs))
-                       continue;
-#endif                         /* CONFIG_SERIAL_SGI_L1_CONSOLE && CONFIG_MAGIC_SYSRQ */
+#ifdef CONFIG_MAGIC_SYSRQ
+                if (sysrq_requested) {
+                        unsigned long sysrq_timeout = sysrq_requested + HZ*5;
+
+                        sysrq_requested = 0;
+                        if (ch && time_before(jiffies, sysrq_timeout)) {
+                                spin_unlock_irqrestore(&port->sc_port.lock, flags);
+                                handle_sysrq(ch, regs, NULL);
+                                spin_lock_irqsave(&port->sc_port.lock, flags);
+                                /* ignore actual sysrq command char */
+                                continue;
+                        }
+                }
+                if (ch == *sysrq_serial_ptr) {
+                        if (!(*++sysrq_serial_ptr)) {
+                                sysrq_requested = jiffies;
+                                sysrq_serial_ptr = sysrq_serial_str;
+                        }
+                       /*
+                        * ignore the whole sysrq string except for the
+                        * leading escape
+                        */
+                       if (ch != '\e')
+                               continue;
+                }
+                else
+                       sysrq_serial_ptr = sysrq_serial_str;
+#endif /* CONFIG_MAGIC_SYSRQ */
 
                /* record the character to pass up to the tty layer */
                if (tty) {
@@ -583,8 +616,6 @@ sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs)
                        if (tty->flip.count == TTY_FLIPBUF_SIZE)
                                break;
                }
-               else {
-               }
                port->sc_port.icount.rx++;
        }
 
@@ -695,7 +726,7 @@ sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        spin_lock_irqsave(&port->sc_port.lock, flags);
        if (status & SAL_CONSOLE_INTR_RECV) {
-               sn_receive_chars(port, regs);
+               sn_receive_chars(port, regs, flags);
        }
        if (status & SAL_CONSOLE_INTR_XMIT) {
                sn_transmit_chars(port, TRANSMIT_BUFFERED);
@@ -714,7 +745,8 @@ sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static int
 sn_sal_connect_interrupt(struct sn_cons_port *port)
 {
-       if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, SA_INTERRUPT,
+       if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt,
+                       SA_INTERRUPT | SA_SHIRQ,
                        "SAL console driver", port) >= 0) {
                return SGI_UART_VECTOR;
        }
@@ -743,7 +775,7 @@ sn_sal_timer_poll(unsigned long data)
 
        if (!port->sc_port.irq) {
                spin_lock_irqsave(&port->sc_port.lock, flags);
-               sn_receive_chars(port, NULL);
+               sn_receive_chars(port, NULL, flags);
                sn_transmit_chars(port, TRANSMIT_RAW);
                spin_unlock_irqrestore(&port->sc_port.lock, flags);
                mod_timer(&port->sc_timer,
@@ -851,7 +883,6 @@ sn_sal_switch_to_interrupts(struct sn_cons_port *port)
  * Kernel console definitions
  */
 
-#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
 static void sn_sal_console_write(struct console *, const char *, unsigned);
 static int __init sn_sal_console_setup(struct console *, char *);
 extern struct uart_driver sal_console_uart;
@@ -867,9 +898,6 @@ static struct console sal_console = {
 };
 
 #define SAL_CONSOLE    &sal_console
-#else
-#define SAL_CONSOLE    0
-#endif                         /* CONFIG_SERIAL_SGI_L1_CONSOLE */
 
 static struct uart_driver sal_console_uart = {
        .owner = THIS_MODULE,
@@ -895,11 +923,11 @@ sn_sal_module_init(void)
 {
        int retval;
 
-       printk(KERN_INFO "sn_console: Console driver init\n");
-
        if (!ia64_platform_is("sn2"))
                return -ENODEV;
 
+       printk(KERN_INFO "sn_console: Console driver init\n");
+
        if (USE_DYNAMIC_MINOR == 1) {
                misc.minor = MISC_DYNAMIC_MINOR;
                misc.name = DEVICE_NAME_DYNAMIC;
@@ -969,8 +997,6 @@ sn_sal_module_exit(void)
 module_init(sn_sal_module_init);
 module_exit(sn_sal_module_exit);
 
-#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
-
 /**
  * puts_raw_fixed - sn_sal_console_write helper for adding \r's as required
  * @puts_raw : puts function to do the writing
@@ -1085,7 +1111,9 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count)
                        spin_unlock_irqrestore(&port->sc_port.lock, flags);
 
                        puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
                }
+#endif
        }
        else {
                /* Not yet registered with serial core - simple case */
@@ -1190,5 +1218,3 @@ sn_sal_serial_console_init(void)
 }
 
 console_initcall(sn_sal_serial_console_init);
-
-#endif                         /* CONFIG_SERIAL_SGI_L1_CONSOLE */
index bf72f27..cc26d95 100644 (file)
@@ -70,7 +70,7 @@
  */
 
 struct acm_line {
-       __u32 speed;
+       __le32 speed;
        __u8 stopbits;
        __u8 parity;
        __u8 databits;
index 050b078..1a9ff61 100644 (file)
@@ -60,3 +60,40 @@ config USB_DYNAMIC_MINORS
 
          If you are unsure about this, say N here.
 
+config USB_SUSPEND
+       bool "USB suspend/resume (EXPERIMENTAL)"
+       depends on USB && PM && EXPERIMENTAL
+       help
+         If you say Y here, you can use driver calls or the sysfs
+         "power/state" file to suspend or resume individual USB
+         peripherals.  There are many related features, such as
+         remote wakeup and driver-specific suspend processing, that
+         may not yet work as expected.
+
+         If you are unsure about this, say N here.
+
+
+config USB_OTG
+       bool
+       depends on USB && EXPERIMENTAL
+       select USB_SUSPEND
+       default n
+
+
+config USB_OTG_WHITELIST
+       bool "Rely on OTG Targeted Peripherals List"
+       depends on USB_OTG
+       default y
+       help
+         If you say Y here, the "otg_whitelist.h" file will be used as a
+         product whitelist, so USB peripherals not listed there will be
+         rejected during enumeration.  This behavior is required by the
+         USB OTG specification for all devices not on your product's
+         "Targeted Peripherals List".
+
+         Otherwise, peripherals not listed there will only generate a
+         warning and enumeration will continue.  That's more like what
+         normal Linux-USB hosts do (other than the warning), and is
+         convenient for many stages of product development.
+
+
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
new file mode 100644 (file)
index 0000000..8bf4e81
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * drivers/usb/core/otg_whitelist.h
+ *
+ * Copyright (C) 2004 Texas Instruments
+ *
+ * This program is free software; you can redistribute 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 OTG Whitelist is the OTG "Targeted Peripheral List".  It should
+ * mostly use of USB_DEVICE() or USB_DEVICE_VER() entries..
+ *
+ * YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
+ */ 
+
+static struct usb_device_id whitelist_table [] = {
+
+/* hubs are optional in OTG, but very handy ... */
+{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
+{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
+
+#ifdef CONFIG_USB_PRINTER              /* ignoring nonstatic linkage! */
+/* FIXME actually, printers are NOT supposed to use device classes;
+ * they're supposed to use interface classes...
+ */
+{ USB_DEVICE_INFO(7, 1, 1) },
+{ USB_DEVICE_INFO(7, 1, 2) },
+{ USB_DEVICE_INFO(7, 1, 3) },
+#endif
+
+#ifdef CONFIG_USB_CDCETHER
+/* Linux-USB CDC Ethernet gadget */
+{ USB_DEVICE(0x0525, 0xa4a1), },
+/* Linux-USB CDC Ethernet + RNDIS gadget */
+{ USB_DEVICE(0x0525, 0xa4a2), },
+#endif
+
+#if    defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
+/* gadget zero, for testing */
+{ USB_DEVICE(0x0525, 0xa4a0), },
+#endif
+
+{ }    /* Terminating entry */
+};
+
+static int is_targeted(struct usb_device *dev)
+{
+       struct usb_device_id    *id = whitelist_table;
+
+       /* possible in developer configs only! */
+       if (!dev->bus->otg_port)
+               return 1;
+
+       /* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
+       if (dev->descriptor.idVendor == 0x1a0a
+                       && dev->descriptor.idProduct == 0xbadd)
+               return 0;
+
+       /* NOTE: can't use usb_match_id() since interface caches
+        * aren't set up yet. this is cut/paste from that code.
+        */
+       for (id = whitelist_table; id->match_flags; id++) {
+               if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
+                   id->idVendor != dev->descriptor.idVendor)
+                       continue;
+
+               if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
+                   id->idProduct != dev->descriptor.idProduct)
+                       continue;
+
+               /* No need to test id->bcdDevice_lo != 0, since 0 is never
+                  greater than any unsigned number. */
+               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
+                   (id->bcdDevice_lo > dev->descriptor.bcdDevice))
+                       continue;
+
+               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
+                   (id->bcdDevice_hi < dev->descriptor.bcdDevice))
+                       continue;
+
+               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
+                   (id->bDeviceClass != dev->descriptor.bDeviceClass))
+                       continue;
+
+               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
+                   (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+                       continue;
+
+               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
+                   (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
+                       continue;
+
+               return 1;
+       }
+
+       /* add other match criteria here ... */
+
+
+       /* OTG MESSAGE: report errors here, customize to match your product */
+       dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
+                       dev->descriptor.idVendor,
+                       dev->descriptor.idProduct);
+#ifdef CONFIG_USB_OTG_WHITELIST
+       return 0;
+#else
+       return 1;
+#endif
+}
+
index 645d15c..03c639b 100644 (file)
@@ -5,13 +5,15 @@ obj-$(CONFIG_USB_DUMMY_HCD)   += dummy_hcd.o
 obj-$(CONFIG_USB_NET2280)      += net2280.o
 obj-$(CONFIG_USB_PXA2XX)       += pxa2xx_udc.o
 obj-$(CONFIG_USB_GOKU)         += goku_udc.o
+obj-$(CONFIG_USB_OMAP)         += omap_udc.o
+obj-$(CONFIG_USB_LH7A40X)      += lh7a40x_udc.o
 
 #
 # USB gadget drivers
 #
 g_zero-objs                    := zero.o usbstring.o config.o epautoconf.o
 g_ether-objs                   := ether.o usbstring.o config.o epautoconf.o
-g_serial-objs                  := serial.o usbstring.o
+g_serial-objs                  := serial.o usbstring.o epautoconf.o
 gadgetfs-objs                  := inode.o
 g_file_storage-objs            := file_storage.o usbstring.o config.o \
                                        epautoconf.o
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
new file mode 100644 (file)
index 0000000..772627e
--- /dev/null
@@ -0,0 +1,2168 @@
+/*
+ * linux/drivers/usb/gadget/lh7a40x_udc.c
+ * Sharp LH7A40x on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004 Mikko Lahteenmaki, Nordic ID
+ * Copyright (C) 2004 Bo Henriksen, Nordic ID
+ *
+ * This program is free software; you can redistribute 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 "lh7a40x_udc.h"
+
+//#define DEBUG printk
+//#define DEBUG_EP0 printk
+//#define DEBUG_SETUP printk
+
+#ifndef DEBUG_EP0
+# define DEBUG_EP0(fmt,args...)
+#endif
+#ifndef DEBUG_SETUP
+# define DEBUG_SETUP(fmt,args...)
+#endif
+#ifndef DEBUG
+# define NO_STATES
+# define DEBUG(fmt,args...)
+#endif
+
+#define        DRIVER_DESC                     "LH7A40x USB Device Controller"
+#define        DRIVER_VERSION          __DATE__
+
+#ifndef _BIT                   /* FIXME - what happended to _BIT in 2.6.7bk18? */
+#define _BIT(x) (1<<(x))
+#endif
+
+struct lh7a40x_udc *the_controller;
+
+static const char driver_name[] = "lh7a40x_udc";
+static const char driver_desc[] = DRIVER_DESC;
+static const char ep0name[] = "ep0-control";
+
+/*
+  Local definintions.
+*/
+#define UDC_PROC_FILE
+
+#ifndef NO_STATES
+static char *state_names[] = {
+       "WAIT_FOR_SETUP",
+       "DATA_STATE_XMIT",
+       "DATA_STATE_NEED_ZLP",
+       "WAIT_FOR_OUT_STATUS",
+       "DATA_STATE_RECV"
+};
+#endif
+
+/*
+  Local declarations.
+*/
+static int lh7a40x_ep_enable(struct usb_ep *ep,
+                            const struct usb_endpoint_descriptor *);
+static int lh7a40x_ep_disable(struct usb_ep *ep);
+static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, int);
+static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *);
+static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned, dma_addr_t *,
+                                 int);
+static void lh7a40x_free_buffer(struct usb_ep *ep, void *, dma_addr_t,
+                               unsigned);
+static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, int);
+static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
+static int lh7a40x_set_halt(struct usb_ep *ep, int);
+static int lh7a40x_fifo_status(struct usb_ep *ep);
+static int lh7a40x_fifo_status(struct usb_ep *ep);
+static void lh7a40x_fifo_flush(struct usb_ep *ep);
+static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep);
+static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr);
+
+static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req,
+                int status);
+static void pio_irq_enable(int bEndpointAddress);
+static void pio_irq_disable(int bEndpointAddress);
+static void stop_activity(struct lh7a40x_udc *dev,
+                         struct usb_gadget_driver *driver);
+static void flush(struct lh7a40x_ep *ep);
+static void udc_enable(struct lh7a40x_udc *dev);
+static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address);
+
+static struct usb_ep_ops lh7a40x_ep_ops = {
+       .enable = lh7a40x_ep_enable,
+       .disable = lh7a40x_ep_disable,
+
+       .alloc_request = lh7a40x_alloc_request,
+       .free_request = lh7a40x_free_request,
+
+       .alloc_buffer = lh7a40x_alloc_buffer,
+       .free_buffer = lh7a40x_free_buffer,
+
+       .queue = lh7a40x_queue,
+       .dequeue = lh7a40x_dequeue,
+
+       .set_halt = lh7a40x_set_halt,
+       .fifo_status = lh7a40x_fifo_status,
+       .fifo_flush = lh7a40x_fifo_flush,
+};
+
+/* Inline code */
+
+static __inline__ int write_packet(struct lh7a40x_ep *ep,
+                                  struct lh7a40x_request *req, int max)
+{
+       u8 *buf;
+       int length, count;
+       volatile u32 *fifo = (volatile u32 *)ep->fifo;
+
+       buf = req->req.buf + req->req.actual;
+       prefetch(buf);
+
+       length = req->req.length - req->req.actual;
+       length = min(length, max);
+       req->req.actual += length;
+
+       DEBUG("Write %d (max %d), fifo %p\n", length, max, fifo);
+
+       count = length;
+       while (count--) {
+               *fifo = *buf++;
+       }
+
+       return length;
+}
+
+static __inline__ void usb_set_index(u32 ep)
+{
+       *(volatile u32 *)io_p2v(USB_INDEX) = ep;
+}
+
+static __inline__ u32 usb_read(u32 port)
+{
+       return *(volatile u32 *)io_p2v(port);
+}
+
+static __inline__ void usb_write(u32 val, u32 port)
+{
+       *(volatile u32 *)io_p2v(port) = val;
+}
+
+static __inline__ void usb_set(u32 val, u32 port)
+{
+       volatile u32 *ioport = (volatile u32 *)io_p2v(port);
+       u32 after = (*ioport) | val;
+       *ioport = after;
+}
+
+static __inline__ void usb_clear(u32 val, u32 port)
+{
+       volatile u32 *ioport = (volatile u32 *)io_p2v(port);
+       u32 after = (*ioport) & ~val;
+       *ioport = after;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define GPIO_PORTC_DR  (0x80000E08)
+#define GPIO_PORTC_DDR         (0x80000E18)
+#define GPIO_PORTC_PDR         (0x80000E70)
+
+/* get port C pin data register */
+#define get_portc_pdr(bit)             ((usb_read(GPIO_PORTC_PDR) & _BIT(bit)) != 0)
+/* get port C data direction register */
+#define get_portc_ddr(bit)             ((usb_read(GPIO_PORTC_DDR) & _BIT(bit)) != 0)
+/* set port C data register */
+#define set_portc_dr(bit, val)         (val ? usb_set(_BIT(bit), GPIO_PORTC_DR) : usb_clear(_BIT(bit), GPIO_PORTC_DR))
+/* set port C data direction register */
+#define set_portc_ddr(bit, val) (val ? usb_set(_BIT(bit), GPIO_PORTC_DDR) : usb_clear(_BIT(bit), GPIO_PORTC_DDR))
+
+/*
+ * LPD7A404 GPIO's:
+ * Port C bit 1 = USB Port 1 Power Enable
+ * Port C bit 2 = USB Port 1 Data Carrier Detect
+ */
+#define is_usb_connected()             get_portc_pdr(2)
+
+#ifdef UDC_PROC_FILE
+
+static const char proc_node_name[] = "driver/udc";
+
+static int
+udc_proc_read(char *page, char **start, off_t off, int count,
+             int *eof, void *_dev)
+{
+       char *buf = page;
+       struct lh7a40x_udc *dev = _dev;
+       char *next = buf;
+       unsigned size = count;
+       unsigned long flags;
+       int t;
+
+       if (off != 0)
+               return 0;
+
+       local_irq_save(flags);
+
+       /* basic device status */
+       t = scnprintf(next, size,
+                     DRIVER_DESC "\n"
+                     "%s version: %s\n"
+                     "Gadget driver: %s\n"
+                     "Host: %s\n\n",
+                     driver_name, DRIVER_VERSION,
+                     dev->driver ? dev->driver->driver.name : "(none)",
+                     is_usb_connected()? "full speed" : "disconnected");
+       size -= t;
+       next += t;
+
+       t = scnprintf(next, size,
+                     "GPIO:\n"
+                     " Port C bit 1: %d, dir %d\n"
+                     " Port C bit 2: %d, dir %d\n\n",
+                     get_portc_pdr(1), get_portc_ddr(1),
+                     get_portc_pdr(2), get_portc_ddr(2)
+           );
+       size -= t;
+       next += t;
+
+       t = scnprintf(next, size,
+                     "DCP pullup: %d\n\n",
+                     (usb_read(USB_PM) & PM_USB_DCP) != 0);
+       size -= t;
+       next += t;
+
+       local_irq_restore(flags);
+       *eof = 1;
+       return count - size;
+}
+
+#define create_proc_files()    create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev)
+#define remove_proc_files()    remove_proc_entry(proc_node_name, NULL)
+
+#else                          /* !UDC_PROC_FILE */
+
+#define create_proc_files() do {} while (0)
+#define remove_proc_files() do {} while (0)
+
+#endif                         /* UDC_PROC_FILE */
+
+/*
+ *     udc_disable - disable USB device controller
+ */
+static void udc_disable(struct lh7a40x_udc *dev)
+{
+       DEBUG("%s, %p\n", __FUNCTION__, dev);
+
+       udc_set_address(dev, 0);
+
+       /* Disable interrupts */
+       usb_write(0, USB_IN_INT_EN);
+       usb_write(0, USB_OUT_INT_EN);
+       usb_write(0, USB_INT_EN);
+
+       /* Disable the USB */
+       usb_write(0, USB_PM);
+
+#ifdef CONFIG_ARCH_LH7A404
+       /* Disable USB power */
+       set_portc_dr(1, 0);
+#endif
+
+       /* if hardware supports it, disconnect from usb */
+       /* make_usb_disappear(); */
+
+       dev->ep0state = WAIT_FOR_SETUP;
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+       dev->usb_address = 0;
+}
+
+/*
+ *     udc_reinit - initialize software state
+ */
+static void udc_reinit(struct lh7a40x_udc *dev)
+{
+       u32 i;
+
+       DEBUG("%s, %p\n", __FUNCTION__, dev);
+
+       /* device/ep0 records init */
+       INIT_LIST_HEAD(&dev->gadget.ep_list);
+       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+       dev->ep0state = WAIT_FOR_SETUP;
+
+       /* basic endpoint records init */
+       for (i = 0; i < UDC_MAX_ENDPOINTS; i++) {
+               struct lh7a40x_ep *ep = &dev->ep[i];
+
+               if (i != 0)
+                       list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+
+               ep->desc = 0;
+               ep->stopped = 0;
+               INIT_LIST_HEAD(&ep->queue);
+               ep->pio_irqs = 0;
+       }
+
+       /* the rest was statically initialized, and is read-only */
+}
+
+#define BYTES2MAXP(x)  (x / 8)
+#define MAXP2BYTES(x)  (x * 8)
+
+/* until it's enabled, this UDC should be completely invisible
+ * to any USB host.
+ */
+static void udc_enable(struct lh7a40x_udc *dev)
+{
+       int ep;
+
+       DEBUG("%s, %p\n", __FUNCTION__, dev);
+
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+#ifdef CONFIG_ARCH_LH7A404
+       /* Set Port C bit 1 & 2 as output */
+       set_portc_ddr(1, 1);
+       set_portc_ddr(2, 1);
+
+       /* Enable USB power */
+       set_portc_dr(1, 0);
+#endif
+
+       /*
+        * C.f Chapter 18.1.3.1 Initializing the USB
+        */
+
+       /* Disable the USB */
+       usb_clear(PM_USB_ENABLE, USB_PM);
+
+       /* Reset APB & I/O sides of the USB */
+       usb_set(USB_RESET_APB | USB_RESET_IO, USB_RESET);
+       mdelay(5);
+       usb_clear(USB_RESET_APB | USB_RESET_IO, USB_RESET);
+
+       /* Set MAXP values for each */
+       for (ep = 0; ep < UDC_MAX_ENDPOINTS; ep++) {
+               struct lh7a40x_ep *ep_reg = &dev->ep[ep];
+               u32 csr;
+
+               usb_set_index(ep);
+
+               switch (ep_reg->ep_type) {
+               case ep_bulk_in:
+               case ep_interrupt:
+                       usb_clear(USB_IN_CSR2_USB_DMA_EN | USB_IN_CSR2_AUTO_SET,
+                                 ep_reg->csr2);
+                       /* Fall through */
+               case ep_control:
+                       usb_write(BYTES2MAXP(ep_maxpacket(ep_reg)),
+                                 USB_IN_MAXP);
+                       break;
+               case ep_bulk_out:
+                       usb_clear(USB_OUT_CSR2_USB_DMA_EN |
+                                 USB_OUT_CSR2_AUTO_CLR, ep_reg->csr2);
+                       usb_write(BYTES2MAXP(ep_maxpacket(ep_reg)),
+                                 USB_OUT_MAXP);
+                       break;
+               }
+
+               /* Read & Write CSR1, just in case */
+               csr = usb_read(ep_reg->csr1);
+               usb_write(csr, ep_reg->csr1);
+
+               flush(ep_reg);
+       }
+
+       /* Disable interrupts */
+       usb_write(0, USB_IN_INT_EN);
+       usb_write(0, USB_OUT_INT_EN);
+       usb_write(0, USB_INT_EN);
+
+       /* Enable interrupts */
+       usb_set(USB_IN_INT_EP0, USB_IN_INT_EN);
+       usb_set(USB_INT_RESET_INT | USB_INT_RESUME_INT, USB_INT_EN);
+       /* Dont enable rest of the interrupts */
+       /* usb_set(USB_IN_INT_EP3 | USB_IN_INT_EP1 | USB_IN_INT_EP0, USB_IN_INT_EN);
+          usb_set(USB_OUT_INT_EP2, USB_OUT_INT_EN); */
+
+       /* Enable SUSPEND */
+       usb_set(PM_ENABLE_SUSPEND, USB_PM);
+
+       /* Enable the USB */
+       usb_set(PM_USB_ENABLE, USB_PM);
+
+#ifdef CONFIG_ARCH_LH7A404
+       /* NOTE: DOES NOT WORK! */
+       /* Let host detect UDC:
+        * Software must write a 0 to the PMR:DCP_CTRL bit to turn this
+        * transistor on and pull the USBDP pin HIGH.
+        */
+       /* usb_clear(PM_USB_DCP, USB_PM);
+          usb_set(PM_USB_DCP, USB_PM); */
+#endif
+}
+
+/*
+  Register entry point for the peripheral controller driver.
+*/
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+       struct lh7a40x_udc *dev = the_controller;
+       int retval;
+
+       DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name);
+
+       if (!driver
+           || driver->speed != USB_SPEED_FULL
+           || !driver->bind
+           || !driver->unbind || !driver->disconnect || !driver->setup)
+               return -EINVAL;
+       if (!dev)
+               return -ENODEV;
+       if (dev->driver)
+               return -EBUSY;
+
+       /* first hook up the driver ... */
+       dev->driver = driver;
+       dev->gadget.dev.driver = &driver->driver;
+
+       device_add(&dev->gadget.dev);
+       retval = driver->bind(&dev->gadget);
+       if (retval) {
+               printk("%s: bind to driver %s --> error %d\n", dev->gadget.name,
+                      driver->driver.name, retval);
+               device_del(&dev->gadget.dev);
+
+               dev->driver = 0;
+               dev->gadget.dev.driver = 0;
+               return retval;
+       }
+
+       /* ... then enable host detection and ep0; and we're ready
+        * for set_configuration as well as eventual disconnect.
+        * NOTE:  this shouldn't power up until later.
+        */
+       printk("%s: registered gadget driver '%s'\n", dev->gadget.name,
+              driver->driver.name);
+
+       udc_enable(dev);
+
+       return 0;
+}
+
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+/*
+  Unregister entry point for the peripheral controller driver.
+*/
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+       struct lh7a40x_udc *dev = the_controller;
+       unsigned long flags;
+
+       if (!dev)
+               return -ENODEV;
+       if (!driver || driver != dev->driver)
+               return -EINVAL;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       dev->driver = 0;
+       stop_activity(dev, driver);
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       driver->unbind(&dev->gadget);
+       device_del(&dev->gadget.dev);
+
+       udc_disable(dev);
+
+       DEBUG("unregistered gadget driver '%s'\n", driver->driver.name);
+       return 0;
+}
+
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/*-------------------------------------------------------------------------*/
+
+/** Write request to FIFO (max write == maxp size)
+ *  Return:  0 = still running, 1 = completed, negative = errno
+ *  NOTE: INDEX register must be set for EP
+ */
+static int write_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+{
+       u32 max;
+       u32 csr;
+
+       max = le16_to_cpu(ep->desc->wMaxPacketSize);
+
+       csr = usb_read(ep->csr1);
+       DEBUG("CSR: %x %d\n", csr, csr & USB_IN_CSR1_FIFO_NOT_EMPTY);
+
+       if (!(csr & USB_IN_CSR1_FIFO_NOT_EMPTY)) {
+               unsigned count;
+               int is_last, is_short;
+
+               count = write_packet(ep, req, max);
+               usb_set(USB_IN_CSR1_IN_PKT_RDY, ep->csr1);
+
+               /* last packet is usually short (or a zlp) */
+               if (unlikely(count != max))
+                       is_last = is_short = 1;
+               else {
+                       if (likely(req->req.length != req->req.actual)
+                           || req->req.zero)
+                               is_last = 0;
+                       else
+                               is_last = 1;
+                       /* interrupt/iso maxpacket may not fill the fifo */
+                       is_short = unlikely(max < ep_maxpacket(ep));
+               }
+
+               DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __FUNCTION__,
+                     ep->ep.name, count,
+                     is_last ? "/L" : "", is_short ? "/S" : "",
+                     req->req.length - req->req.actual, req);
+
+               /* requests complete when all IN data is in the FIFO */
+               if (is_last) {
+                       done(ep, req, 0);
+                       if (list_empty(&ep->queue)) {
+                               pio_irq_disable(ep_index(ep));
+                       }
+                       return 1;
+               }
+       } else {
+               DEBUG("Hmm.. %d ep FIFO is not empty!\n", ep_index(ep));
+       }
+
+       return 0;
+}
+
+/** Read to request from FIFO (max read == bytes in fifo)
+ *  Return:  0 = still running, 1 = completed, negative = errno
+ *  NOTE: INDEX register must be set for EP
+ */
+static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+{
+       u32 csr;
+       u8 *buf;
+       unsigned bufferspace, count, is_short;
+       volatile u32 *fifo = (volatile u32 *)ep->fifo;
+
+       /* make sure there's a packet in the FIFO. */
+       csr = usb_read(ep->csr1);
+       if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY)) {
+               DEBUG("%s: Packet NOT ready!\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       buf = req->req.buf + req->req.actual;
+       prefetchw(buf);
+       bufferspace = req->req.length - req->req.actual;
+
+       /* read all bytes from this packet */
+       count = usb_read(USB_OUT_FIFO_WC1);
+       req->req.actual += min(count, bufferspace);
+
+       is_short = (count < ep->ep.maxpacket);
+       DEBUG("read %s %02x, %d bytes%s req %p %d/%d\n",
+             ep->ep.name, csr, count,
+             is_short ? "/S" : "", req, req->req.actual, req->req.length);
+
+       while (likely(count-- != 0)) {
+               u8 byte = (u8) (*fifo & 0xff);
+
+               if (unlikely(bufferspace == 0)) {
+                       /* this happens when the driver's buffer
+                        * is smaller than what the host sent.
+                        * discard the extra data.
+                        */
+                       if (req->req.status != -EOVERFLOW)
+                               printk("%s overflow %d\n", ep->ep.name, count);
+                       req->req.status = -EOVERFLOW;
+               } else {
+                       *buf++ = byte;
+                       bufferspace--;
+               }
+       }
+
+       usb_clear(USB_OUT_CSR1_OUT_PKT_RDY, ep->csr1);
+
+       /* completion */
+       if (is_short || req->req.actual == req->req.length) {
+               done(ep, req, 0);
+               usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1);
+
+               if (list_empty(&ep->queue))
+                       pio_irq_disable(ep_index(ep));
+               return 1;
+       }
+
+       /* finished that packet.  the next one may be waiting... */
+       return 0;
+}
+
+/*
+ *     done - retire a request; caller blocked irqs
+ *  INDEX register is preserved to keep same
+ */
+static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, int status)
+{
+       unsigned int stopped = ep->stopped;
+       u32 index;
+
+       DEBUG("%s, %p\n", __FUNCTION__, ep);
+       list_del_init(&req->queue);
+
+       if (likely(req->req.status == -EINPROGRESS))
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       if (status && status != -ESHUTDOWN)
+               DEBUG("complete %s req %p stat %d len %u/%u\n",
+                     ep->ep.name, &req->req, status,
+                     req->req.actual, req->req.length);
+
+       /* don't modify queue heads during completion callback */
+       ep->stopped = 1;
+       /* Read current index (completion may modify it) */
+       index = usb_read(USB_INDEX);
+
+       spin_unlock(&ep->dev->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&ep->dev->lock);
+
+       /* Restore index */
+       usb_set_index(index);
+       ep->stopped = stopped;
+}
+
+/** Enable EP interrupt */
+static void pio_irq_enable(int ep)
+{
+       DEBUG("%s: %d\n", __FUNCTION__, ep);
+
+       switch (ep) {
+       case 1:
+               usb_set(USB_IN_INT_EP1, USB_IN_INT_EN);
+               break;
+       case 2:
+               usb_set(USB_OUT_INT_EP2, USB_OUT_INT_EN);
+               break;
+       case 3:
+               usb_set(USB_IN_INT_EP3, USB_IN_INT_EN);
+               break;
+       default:
+               DEBUG("Unknown endpoint: %d\n", ep);
+               break;
+       }
+}
+
+/** Disable EP interrupt */
+static void pio_irq_disable(int ep)
+{
+       DEBUG("%s: %d\n", __FUNCTION__, ep);
+
+       switch (ep) {
+       case 1:
+               usb_clear(USB_IN_INT_EP1, USB_IN_INT_EN);
+               break;
+       case 2:
+               usb_clear(USB_OUT_INT_EP2, USB_OUT_INT_EN);
+               break;
+       case 3:
+               usb_clear(USB_IN_INT_EP3, USB_IN_INT_EN);
+               break;
+       default:
+               DEBUG("Unknown endpoint: %d\n", ep);
+               break;
+       }
+}
+
+/*
+ *     nuke - dequeue ALL requests
+ */
+void nuke(struct lh7a40x_ep *ep, int status)
+{
+       struct lh7a40x_request *req;
+
+       DEBUG("%s, %p\n", __FUNCTION__, ep);
+
+       /* Flush FIFO */
+       flush(ep);
+
+       /* called with irqs blocked */
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
+               done(ep, req, status);
+       }
+
+       /* Disable IRQ if EP is enabled (has decriptor) */
+       if (ep->desc)
+               pio_irq_disable(ep_index(ep));
+}
+
+/*
+void nuke_all(struct lh7a40x_udc *dev)
+{
+       int n;
+       for(n=0; n<UDC_MAX_ENDPOINTS; n++) {
+               struct lh7a40x_ep *ep = &dev->ep[n];
+               usb_set_index(n);
+               nuke(ep, 0);
+       }
+}*/
+
+/*
+static void flush_all(struct lh7a40x_udc *dev)
+{
+       int n;
+    for (n = 0; n < UDC_MAX_ENDPOINTS; n++)
+    {
+               struct lh7a40x_ep *ep = &dev->ep[n];
+               flush(ep);
+    }
+}
+*/
+
+/** Flush EP
+ * NOTE: INDEX register must be set before this call
+ */
+static void flush(struct lh7a40x_ep *ep)
+{
+       DEBUG("%s, %p\n", __FUNCTION__, ep);
+
+       switch (ep->ep_type) {
+       case ep_control:
+               /* check, by implication c.f. 15.1.2.11 */
+               break;
+
+       case ep_bulk_in:
+       case ep_interrupt:
+               /* if(csr & USB_IN_CSR1_IN_PKT_RDY) */
+               usb_set(USB_IN_CSR1_FIFO_FLUSH, ep->csr1);
+               break;
+
+       case ep_bulk_out:
+               /* if(csr & USB_OUT_CSR1_OUT_PKT_RDY) */
+               usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1);
+               break;
+       }
+}
+
+/**
+ * lh7a40x_in_epn - handle IN interrupt
+ */
+static void lh7a40x_in_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+{
+       u32 csr;
+       struct lh7a40x_ep *ep = &dev->ep[ep_idx];
+       struct lh7a40x_request *req;
+
+       usb_set_index(ep_idx);
+
+       csr = usb_read(ep->csr1);
+       DEBUG("%s: %d, csr %x\n", __FUNCTION__, ep_idx, csr);
+
+       if (csr & USB_IN_CSR1_SENT_STALL) {
+               DEBUG("USB_IN_CSR1_SENT_STALL\n");
+               usb_set(USB_IN_CSR1_SENT_STALL /*|USB_IN_CSR1_SEND_STALL */ ,
+                       ep->csr1);
+               return;
+       }
+
+       if (!ep->desc) {
+               DEBUG("%s: NO EP DESC\n", __FUNCTION__);
+               return;
+       }
+
+       if (list_empty(&ep->queue))
+               req = 0;
+       else
+               req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
+
+       DEBUG("req: %p\n", req);
+
+       if (!req)
+               return;
+
+       write_fifo(ep, req);
+}
+
+/* ********************************************************************************************* */
+/* Bulk OUT (recv)
+ */
+
+static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+{
+       struct lh7a40x_ep *ep = &dev->ep[ep_idx];
+       struct lh7a40x_request *req;
+
+       DEBUG("%s: %d\n", __FUNCTION__, ep_idx);
+
+       usb_set_index(ep_idx);
+
+       if (ep->desc) {
+               u32 csr;
+               csr = usb_read(ep->csr1);
+
+               while ((csr =
+                       usb_read(ep->
+                                csr1)) & (USB_OUT_CSR1_OUT_PKT_RDY |
+                                          USB_OUT_CSR1_SENT_STALL)) {
+                       DEBUG("%s: %x\n", __FUNCTION__, csr);
+
+                       if (csr & USB_OUT_CSR1_SENT_STALL) {
+                               DEBUG("%s: stall sent, flush fifo\n",
+                                     __FUNCTION__);
+                               /* usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); */
+                               flush(ep);
+                       } else if (csr & USB_OUT_CSR1_OUT_PKT_RDY) {
+                               if (list_empty(&ep->queue))
+                                       req = 0;
+                               else
+                                       req =
+                                           list_entry(ep->queue.next,
+                                                      struct lh7a40x_request,
+                                                      queue);
+
+                               if (!req) {
+                                       printk("%s: NULL REQ %d\n",
+                                              __FUNCTION__, ep_idx);
+                                       flush(ep);
+                                       break;
+                               } else {
+                                       read_fifo(ep, req);
+                               }
+                       }
+
+               }
+
+       } else {
+               /* Throw packet away.. */
+               printk("%s: No descriptor?!?\n", __FUNCTION__);
+               flush(ep);
+       }
+}
+
+static void stop_activity(struct lh7a40x_udc *dev,
+                         struct usb_gadget_driver *driver)
+{
+       int i;
+
+       /* don't disconnect drivers more than once */
+       if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+               driver = 0;
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+       /* prevent new request submissions, kill any outstanding requests  */
+       for (i = 0; i < UDC_MAX_ENDPOINTS; i++) {
+               struct lh7a40x_ep *ep = &dev->ep[i];
+               ep->stopped = 1;
+
+               usb_set_index(i);
+               nuke(ep, -ESHUTDOWN);
+       }
+
+       /* report disconnect; the driver is already quiesced */
+       if (driver) {
+               spin_unlock(&dev->lock);
+               driver->disconnect(&dev->gadget);
+               spin_lock(&dev->lock);
+       }
+
+       /* re-init driver-visible data structures */
+       udc_reinit(dev);
+}
+
+/** Handle USB RESET interrupt
+ */
+static void lh7a40x_reset_intr(struct lh7a40x_udc *dev)
+{
+#if 0                          /* def CONFIG_ARCH_LH7A404 */
+       /* Does not work always... */
+
+       DEBUG("%s: %d\n", __FUNCTION__, dev->usb_address);
+
+       if (!dev->usb_address) {
+               /*usb_set(USB_RESET_IO, USB_RESET);
+                  mdelay(5);
+                  usb_clear(USB_RESET_IO, USB_RESET); */
+               return;
+       }
+       /* Put the USB controller into reset. */
+       usb_set(USB_RESET_IO, USB_RESET);
+
+       /* Set Device ID to 0 */
+       udc_set_address(dev, 0);
+
+       /* Let PLL2 settle down */
+       mdelay(5);
+
+       /* Release the USB controller from reset */
+       usb_clear(USB_RESET_IO, USB_RESET);
+
+       /* Re-enable UDC */
+       udc_enable(dev);
+
+#endif
+       dev->gadget.speed = USB_SPEED_FULL;
+}
+
+/*
+ *     lh7a40x usb client interrupt handler.
+ */
+static irqreturn_t lh7a40x_udc_irq(int irq, void *_dev, struct pt_regs *r)
+{
+       struct lh7a40x_udc *dev = _dev;
+
+       DEBUG("\n\n");
+
+       spin_lock(&dev->lock);
+
+       for (;;) {
+               u32 intr_in = usb_read(USB_IN_INT);
+               u32 intr_out = usb_read(USB_OUT_INT);
+               u32 intr_int = usb_read(USB_INT);
+
+               /* Test also against enable bits.. (lh7a40x errata).. Sigh.. */
+               u32 in_en = usb_read(USB_IN_INT_EN);
+               u32 out_en = usb_read(USB_OUT_INT_EN);
+
+               if (!intr_out && !intr_in && !intr_int)
+                       break;
+
+               DEBUG("%s (on state %s)\n", __FUNCTION__,
+                     state_names[dev->ep0state]);
+               DEBUG("intr_out = %x\n", intr_out);
+               DEBUG("intr_in  = %x\n", intr_in);
+               DEBUG("intr_int = %x\n", intr_int);
+
+               if (intr_in) {
+                       usb_write(intr_in, USB_IN_INT);
+
+                       if ((intr_in & USB_IN_INT_EP1)
+                           && (in_en & USB_IN_INT_EP1)) {
+                               DEBUG("USB_IN_INT_EP1\n");
+                               lh7a40x_in_epn(dev, 1, intr_in);
+                       }
+                       if ((intr_in & USB_IN_INT_EP3)
+                           && (in_en & USB_IN_INT_EP3)) {
+                               DEBUG("USB_IN_INT_EP3\n");
+                               lh7a40x_in_epn(dev, 3, intr_in);
+                       }
+                       if (intr_in & USB_IN_INT_EP0) {
+                               DEBUG("USB_IN_INT_EP0 (control)\n");
+                               lh7a40x_handle_ep0(dev, intr_in);
+                       }
+               }
+
+               if (intr_out) {
+                       usb_write(intr_out, USB_OUT_INT);
+
+                       if ((intr_out & USB_OUT_INT_EP2)
+                           && (out_en & USB_OUT_INT_EP2)) {
+                               DEBUG("USB_OUT_INT_EP2\n");
+                               lh7a40x_out_epn(dev, 2, intr_out);
+                       }
+               }
+
+               if (intr_int) {
+                       usb_write(intr_int, USB_INT);
+
+                       if (intr_int & USB_INT_RESET_INT) {
+                               lh7a40x_reset_intr(dev);
+                       }
+
+                       if (intr_int & USB_INT_RESUME_INT) {
+                               DEBUG("USB resume\n");
+
+                               if (dev->gadget.speed != USB_SPEED_UNKNOWN
+                                   && dev->driver
+                                   && dev->driver->resume
+                                   && is_usb_connected()) {
+                                       dev->driver->resume(&dev->gadget);
+                               }
+                       }
+
+                       if (intr_int & USB_INT_SUSPEND_INT) {
+                               DEBUG("USB suspend%s\n",
+                                     is_usb_connected()? "" : "+disconnect");
+                               if (!is_usb_connected()) {
+                                       stop_activity(dev, dev->driver);
+                               } else if (dev->gadget.speed !=
+                                          USB_SPEED_UNKNOWN && dev->driver
+                                          && dev->driver->suspend) {
+                                       dev->driver->suspend(&dev->gadget);
+                               }
+                       }
+
+               }
+       }
+
+       spin_unlock(&dev->lock);
+
+       return IRQ_HANDLED;
+}
+
+static int lh7a40x_ep_enable(struct usb_ep *_ep,
+                            const struct usb_endpoint_descriptor *desc)
+{
+       struct lh7a40x_ep *ep;
+       struct lh7a40x_udc *dev;
+       unsigned long flags;
+
+       DEBUG("%s, %p\n", __FUNCTION__, _ep);
+
+       ep = container_of(_ep, struct lh7a40x_ep, ep);
+       if (!_ep || !desc || ep->desc || _ep->name == ep0name
+           || desc->bDescriptorType != USB_DT_ENDPOINT
+           || ep->bEndpointAddress != desc->bEndpointAddress
+           || ep_maxpacket(ep) < le16_to_cpu(desc->wMaxPacketSize)) {
+               DEBUG("%s, bad ep or descriptor\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* xfer types must match, except that interrupt ~= bulk */
+       if (ep->bmAttributes != desc->bmAttributes
+           && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+           && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+               DEBUG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
+               return -EINVAL;
+       }
+
+       /* hardware _could_ do smaller, but driver doesn't */
+       if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+            && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(ep))
+           || !desc->wMaxPacketSize) {
+               DEBUG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
+               return -ERANGE;
+       }
+
+       dev = ep->dev;
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+               DEBUG("%s, bogus device state\n", __FUNCTION__);
+               return -ESHUTDOWN;
+       }
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+
+       ep->stopped = 0;
+       ep->desc = desc;
+       ep->pio_irqs = 0;
+       ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+
+       /* Reset halt state (does flush) */
+       lh7a40x_set_halt(_ep, 0);
+
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+       DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name);
+       return 0;
+}
+
+/** Disable EP
+ *  NOTE: Sets INDEX register
+ */
+static int lh7a40x_ep_disable(struct usb_ep *_ep)
+{
+       struct lh7a40x_ep *ep;
+       unsigned long flags;
+
+       DEBUG("%s, %p\n", __FUNCTION__, _ep);
+
+       ep = container_of(_ep, struct lh7a40x_ep, ep);
+       if (!_ep || !ep->desc) {
+               DEBUG("%s, %s not enabled\n", __FUNCTION__,
+                     _ep ? ep->ep.name : NULL);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+
+       usb_set_index(ep_index(ep));
+
+       /* Nuke all pending requests (does flush) */
+       nuke(ep, -ESHUTDOWN);
+
+       /* Disable ep IRQ */
+       pio_irq_disable(ep_index(ep));
+
+       ep->desc = 0;
+       ep->stopped = 1;
+
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+       DEBUG("%s: disabled %s\n", __FUNCTION__, _ep->name);
+       return 0;
+}
+
+static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
+                                                int gfp_flags)
+{
+       struct lh7a40x_request *req;
+
+       DEBUG("%s, %p\n", __FUNCTION__, ep);
+
+       req = kmalloc(sizeof *req, gfp_flags);
+       if (!req)
+               return 0;
+
+       memset(req, 0, sizeof *req);
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req)
+{
+       struct lh7a40x_request *req;
+
+       DEBUG("%s, %p\n", __FUNCTION__, ep);
+
+       req = container_of(_req, struct lh7a40x_request, req);
+       WARN_ON(!list_empty(&req->queue));
+       kfree(req);
+}
+
+static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes,
+                                 dma_addr_t * dma, int gfp_flags)
+{
+       char *retval;
+
+       DEBUG("%s (%p, %d, %d)\n", __FUNCTION__, ep, bytes, gfp_flags);
+
+       retval = kmalloc(bytes, gfp_flags & ~(__GFP_DMA | __GFP_HIGHMEM));
+       if (retval)
+               *dma = virt_to_bus(retval);
+       return retval;
+}
+
+static void lh7a40x_free_buffer(struct usb_ep *ep, void *buf, dma_addr_t dma,
+                               unsigned bytes)
+{
+       DEBUG("%s, %p\n", __FUNCTION__, ep);
+       kfree(buf);
+}
+
+/** Queue one request
+ *  Kickstart transfer if needed
+ *  NOTE: Sets INDEX register
+ */
+static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req,
+                        int gfp_flags)
+{
+       struct lh7a40x_request *req;
+       struct lh7a40x_ep *ep;
+       struct lh7a40x_udc *dev;
+       unsigned long flags;
+
+       DEBUG("\n\n\n%s, %p\n", __FUNCTION__, _ep);
+
+       req = container_of(_req, struct lh7a40x_request, req);
+       if (unlikely
+           (!_req || !_req->complete || !_req->buf
+            || !list_empty(&req->queue))) {
+               DEBUG("%s, bad params\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       ep = container_of(_ep, struct lh7a40x_ep, ep);
+       if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+               DEBUG("%s, bad ep\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       dev = ep->dev;
+       if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+               DEBUG("%s, bogus device state %p\n", __FUNCTION__, dev->driver);
+               return -ESHUTDOWN;
+       }
+
+       DEBUG("%s queue req %p, len %d buf %p\n", _ep->name, _req, _req->length,
+             _req->buf);
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       /* kickstart this i/o queue? */
+       DEBUG("Add to %d Q %d %d\n", ep_index(ep), list_empty(&ep->queue),
+             ep->stopped);
+       if (list_empty(&ep->queue) && likely(!ep->stopped)) {
+               u32 csr;
+
+               if (unlikely(ep_index(ep) == 0)) {
+                       /* EP0 */
+                       list_add_tail(&req->queue, &ep->queue);
+                       lh7a40x_ep0_kick(dev, ep);
+                       req = 0;
+               } else if (ep_is_in(ep)) {
+                       /* EP1 & EP3 */
+                       usb_set_index(ep_index(ep));
+                       csr = usb_read(ep->csr1);
+                       pio_irq_enable(ep_index(ep));
+                       if ((csr & USB_IN_CSR1_FIFO_NOT_EMPTY) == 0) {
+                               if (write_fifo(ep, req) == 1)
+                                       req = 0;
+                       }
+               } else {
+                       /* EP2 */
+                       usb_set_index(ep_index(ep));
+                       csr = usb_read(ep->csr1);
+                       pio_irq_enable(ep_index(ep));
+                       if (!(csr & USB_OUT_CSR1_FIFO_FULL)) {
+                               if (read_fifo(ep, req) == 1)
+                                       req = 0;
+                       }
+               }
+       }
+
+       /* pio or dma irq handler advances the queue. */
+       if (likely(req != 0))
+               list_add_tail(&req->queue, &ep->queue);
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return 0;
+}
+
+/* dequeue JUST ONE request */
+static int lh7a40x_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct lh7a40x_ep *ep;
+       struct lh7a40x_request *req;
+       unsigned long flags;
+
+       DEBUG("%s, %p\n", __FUNCTION__, _ep);
+
+       ep = container_of(_ep, struct lh7a40x_ep, ep);
+       if (!_ep || ep->ep.name == ep0name)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               spin_unlock_irqrestore(&ep->dev->lock, flags);
+               return -EINVAL;
+       }
+
+       done(ep, req, -ECONNRESET);
+
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+       return 0;
+}
+
+/** Halt specific EP
+ *  Return 0 if success
+ *  NOTE: Sets INDEX register to EP !
+ */
+static int lh7a40x_set_halt(struct usb_ep *_ep, int value)
+{
+       struct lh7a40x_ep *ep;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct lh7a40x_ep, ep);
+       if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+               DEBUG("%s, bad ep\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       usb_set_index(ep_index(ep));
+
+       DEBUG("%s, ep %d, val %d\n", __FUNCTION__, ep_index(ep), value);
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+
+       if (ep_index(ep) == 0) {
+               /* EP0 */
+               usb_set(EP0_SEND_STALL, ep->csr1);
+       } else if (ep_is_in(ep)) {
+               u32 csr = usb_read(ep->csr1);
+               if (value && ((csr & USB_IN_CSR1_FIFO_NOT_EMPTY)
+                             || !list_empty(&ep->queue))) {
+                       /*
+                        * Attempts to halt IN endpoints will fail (returning -EAGAIN)
+                        * if any transfer requests are still queued, or if the controller
+                        * FIFO still holds bytes that the host hasn\92t collected.
+                        */
+                       spin_unlock_irqrestore(&ep->dev->lock, flags);
+                       DEBUG
+                           ("Attempt to halt IN endpoint failed (returning -EAGAIN) %d %d\n",
+                            (csr & USB_IN_CSR1_FIFO_NOT_EMPTY),
+                            !list_empty(&ep->queue));
+                       return -EAGAIN;
+               }
+               flush(ep);
+               if (value)
+                       usb_set(USB_IN_CSR1_SEND_STALL, ep->csr1);
+               else {
+                       usb_clear(USB_IN_CSR1_SEND_STALL, ep->csr1);
+                       usb_set(USB_IN_CSR1_CLR_DATA_TOGGLE, ep->csr1);
+               }
+
+       } else {
+
+               flush(ep);
+               if (value)
+                       usb_set(USB_OUT_CSR1_SEND_STALL, ep->csr1);
+               else {
+                       usb_clear(USB_OUT_CSR1_SEND_STALL, ep->csr1);
+                       usb_set(USB_OUT_CSR1_CLR_DATA_REG, ep->csr1);
+               }
+       }
+
+       if (value) {
+               ep->stopped = 1;
+       } else {
+               ep->stopped = 0;
+       }
+
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+       DEBUG("%s %s halted\n", _ep->name, value == 0 ? "NOT" : "IS");
+
+       return 0;
+}
+
+/** Return bytes in EP FIFO
+ *  NOTE: Sets INDEX register to EP
+ */
+static int lh7a40x_fifo_status(struct usb_ep *_ep)
+{
+       u32 csr;
+       int count = 0;
+       struct lh7a40x_ep *ep;
+
+       ep = container_of(_ep, struct lh7a40x_ep, ep);
+       if (!_ep) {
+               DEBUG("%s, bad ep\n", __FUNCTION__);
+               return -ENODEV;
+       }
+
+       DEBUG("%s, %d\n", __FUNCTION__, ep_index(ep));
+
+       /* LPD can't report unclaimed bytes from IN fifos */
+       if (ep_is_in(ep))
+               return -EOPNOTSUPP;
+
+       usb_set_index(ep_index(ep));
+
+       csr = usb_read(ep->csr1);
+       if (ep->dev->gadget.speed != USB_SPEED_UNKNOWN ||
+           csr & USB_OUT_CSR1_OUT_PKT_RDY) {
+               count = usb_read(USB_OUT_FIFO_WC1);
+       }
+
+       return count;
+}
+
+/** Flush EP FIFO
+ *  NOTE: Sets INDEX register to EP
+ */
+static void lh7a40x_fifo_flush(struct usb_ep *_ep)
+{
+       struct lh7a40x_ep *ep;
+
+       ep = container_of(_ep, struct lh7a40x_ep, ep);
+       if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+               DEBUG("%s, bad ep\n", __FUNCTION__);
+               return;
+       }
+
+       usb_set_index(ep_index(ep));
+       flush(ep);
+}
+
+/****************************************************************/
+/* End Point 0 related functions                                */
+/****************************************************************/
+
+/* return:  0 = still running, 1 = completed, negative = errno */
+static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+{
+       u32 max;
+       unsigned count;
+       int is_last;
+
+       max = ep_maxpacket(ep);
+
+       DEBUG_EP0("%s\n", __FUNCTION__);
+
+       count = write_packet(ep, req, max);
+
+       /* last packet is usually short (or a zlp) */
+       if (unlikely(count != max))
+               is_last = 1;
+       else {
+               if (likely(req->req.length != req->req.actual) || req->req.zero)
+                       is_last = 0;
+               else
+                       is_last = 1;
+       }
+
+       DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __FUNCTION__,
+                 ep->ep.name, count,
+                 is_last ? "/L" : "", req->req.length - req->req.actual, req);
+
+       /* requests complete when all IN data is in the FIFO */
+       if (is_last) {
+               done(ep, req, 0);
+               return 1;
+       }
+
+       return 0;
+}
+
+static __inline__ int lh7a40x_fifo_read(struct lh7a40x_ep *ep,
+                                       unsigned char *cp, int max)
+{
+       int bytes;
+       int count = usb_read(USB_OUT_FIFO_WC1);
+       volatile u32 *fifo = (volatile u32 *)ep->fifo;
+
+       if (count > max)
+               count = max;
+       bytes = count;
+       while (count--)
+               *cp++ = *fifo & 0xFF;
+       return bytes;
+}
+
+static __inline__ void lh7a40x_fifo_write(struct lh7a40x_ep *ep,
+                                         unsigned char *cp, int count)
+{
+       volatile u32 *fifo = (volatile u32 *)ep->fifo;
+       DEBUG_EP0("fifo_write: %d %d\n", ep_index(ep), count);
+       while (count--)
+               *fifo = *cp++;
+}
+
+static int read_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+{
+       u32 csr;
+       u8 *buf;
+       unsigned bufferspace, count, is_short;
+       volatile u32 *fifo = (volatile u32 *)ep->fifo;
+
+       DEBUG_EP0("%s\n", __FUNCTION__);
+
+       csr = usb_read(USB_EP0_CSR);
+       if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY))
+               return 0;
+
+       buf = req->req.buf + req->req.actual;
+       prefetchw(buf);
+       bufferspace = req->req.length - req->req.actual;
+
+       /* read all bytes from this packet */
+       if (likely(csr & EP0_OUT_PKT_RDY)) {
+               count = usb_read(USB_OUT_FIFO_WC1);
+               req->req.actual += min(count, bufferspace);
+       } else                  /* zlp */
+               count = 0;
+
+       is_short = (count < ep->ep.maxpacket);
+       DEBUG_EP0("read %s %02x, %d bytes%s req %p %d/%d\n",
+                 ep->ep.name, csr, count,
+                 is_short ? "/S" : "", req, req->req.actual, req->req.length);
+
+       while (likely(count-- != 0)) {
+               u8 byte = (u8) (*fifo & 0xff);
+
+               if (unlikely(bufferspace == 0)) {
+                       /* this happens when the driver's buffer
+                        * is smaller than what the host sent.
+                        * discard the extra data.
+                        */
+                       if (req->req.status != -EOVERFLOW)
+                               DEBUG_EP0("%s overflow %d\n", ep->ep.name,
+                                         count);
+                       req->req.status = -EOVERFLOW;
+               } else {
+                       *buf++ = byte;
+                       bufferspace--;
+               }
+       }
+
+       /* completion */
+       if (is_short || req->req.actual == req->req.length) {
+               done(ep, req, 0);
+               return 1;
+       }
+
+       /* finished that packet.  the next one may be waiting... */
+       return 0;
+}
+
+/**
+ * udc_set_address - set the USB address for this device
+ * @address:
+ *
+ * Called from control endpoint function after it decodes a set address setup packet.
+ */
+static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address)
+{
+       DEBUG_EP0("%s: %d\n", __FUNCTION__, address);
+       /* c.f. 15.1.2.2 Table 15-4 address will be used after DATA_END is set */
+       dev->usb_address = address;
+       usb_set((address & USB_FA_FUNCTION_ADDR), USB_FA);
+       usb_set(USB_FA_ADDR_UPDATE | (address & USB_FA_FUNCTION_ADDR), USB_FA);
+       /* usb_read(USB_FA); */
+}
+
+/*
+ * DATA_STATE_RECV (OUT_PKT_RDY)
+ *      - if error
+ *              set EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL bits
+ *      - else
+ *              set EP0_CLR_OUT bit
+                               if last set EP0_DATA_END bit
+ */
+static void lh7a40x_ep0_out(struct lh7a40x_udc *dev, u32 csr)
+{
+       struct lh7a40x_request *req;
+       struct lh7a40x_ep *ep = &dev->ep[0];
+       int ret;
+
+       DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+
+       if (list_empty(&ep->queue))
+               req = 0;
+       else
+               req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
+
+       if (req) {
+
+               if (req->req.length == 0) {
+                       DEBUG_EP0("ZERO LENGTH OUT!\n");
+                       usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
+                       dev->ep0state = WAIT_FOR_SETUP;
+                       return;
+               }
+               ret = read_fifo_ep0(ep, req);
+               if (ret) {
+                       /* Done! */
+                       DEBUG_EP0("%s: finished, waiting for status\n",
+                                 __FUNCTION__);
+
+                       usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
+                       dev->ep0state = WAIT_FOR_SETUP;
+               } else {
+                       /* Not done yet.. */
+                       DEBUG_EP0("%s: not finished\n", __FUNCTION__);
+                       usb_set(EP0_CLR_OUT, USB_EP0_CSR);
+               }
+       } else {
+               DEBUG_EP0("NO REQ??!\n");
+       }
+}
+
+/*
+ * DATA_STATE_XMIT
+ */
+static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
+{
+       struct lh7a40x_request *req;
+       struct lh7a40x_ep *ep = &dev->ep[0];
+       int ret, need_zlp = 0;
+
+       DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+
+       if (list_empty(&ep->queue))
+               req = 0;
+       else
+               req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
+
+       if (!req) {
+               DEBUG_EP0("%s: NULL REQ\n", __FUNCTION__);
+               return 0;
+       }
+
+       if (req->req.length == 0) {
+
+               usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+               dev->ep0state = WAIT_FOR_SETUP;
+               return 1;
+       }
+
+       if (req->req.length - req->req.actual == EP0_PACKETSIZE) {
+               /* Next write will end with the packet size, */
+               /* so we need Zero-length-packet */
+               need_zlp = 1;
+       }
+
+       ret = write_fifo_ep0(ep, req);
+
+       if (ret == 1 && !need_zlp) {
+               /* Last packet */
+               DEBUG_EP0("%s: finished, waiting for status\n", __FUNCTION__);
+
+               usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+               dev->ep0state = WAIT_FOR_SETUP;
+       } else {
+               DEBUG_EP0("%s: not finished\n", __FUNCTION__);
+               usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
+       }
+
+       if (need_zlp) {
+               DEBUG_EP0("%s: Need ZLP!\n", __FUNCTION__);
+               usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
+               dev->ep0state = DATA_STATE_NEED_ZLP;
+       }
+
+       return 1;
+}
+
+static int lh7a40x_handle_get_status(struct lh7a40x_udc *dev,
+                                    struct usb_ctrlrequest *ctrl)
+{
+       struct lh7a40x_ep *ep0 = &dev->ep[0];
+       struct lh7a40x_ep *qep;
+       int reqtype = (ctrl->bRequestType & USB_RECIP_MASK);
+       u16 val = 0;
+
+       if (reqtype == USB_RECIP_INTERFACE) {
+               /* This is not supported.
+                * And according to the USB spec, this one does nothing..
+                * Just return 0
+                */
+               DEBUG_SETUP("GET_STATUS: USB_RECIP_INTERFACE\n");
+       } else if (reqtype == USB_RECIP_DEVICE) {
+               DEBUG_SETUP("GET_STATUS: USB_RECIP_DEVICE\n");
+               val |= (1 << 0);        /* Self powered */
+               /*val |= (1<<1); *//* Remote wakeup */
+       } else if (reqtype == USB_RECIP_ENDPOINT) {
+               int ep_num = (ctrl->wIndex & ~USB_DIR_IN);
+
+               DEBUG_SETUP
+                   ("GET_STATUS: USB_RECIP_ENDPOINT (%d), ctrl->wLength = %d\n",
+                    ep_num, ctrl->wLength);
+
+               if (ctrl->wLength > 2 || ep_num > 3)
+                       return -EOPNOTSUPP;
+
+               qep = &dev->ep[ep_num];
+               if (ep_is_in(qep) != ((ctrl->wIndex & USB_DIR_IN) ? 1 : 0)
+                   && ep_index(qep) != 0) {
+                       return -EOPNOTSUPP;
+               }
+
+               usb_set_index(ep_index(qep));
+
+               /* Return status on next IN token */
+               switch (qep->ep_type) {
+               case ep_control:
+                       val =
+                           (usb_read(qep->csr1) & EP0_SEND_STALL) ==
+                           EP0_SEND_STALL;
+                       break;
+               case ep_bulk_in:
+               case ep_interrupt:
+                       val =
+                           (usb_read(qep->csr1) & USB_IN_CSR1_SEND_STALL) ==
+                           USB_IN_CSR1_SEND_STALL;
+                       break;
+               case ep_bulk_out:
+                       val =
+                           (usb_read(qep->csr1) & USB_OUT_CSR1_SEND_STALL) ==
+                           USB_OUT_CSR1_SEND_STALL;
+                       break;
+               }
+
+               /* Back to EP0 index */
+               usb_set_index(0);
+
+               DEBUG_SETUP("GET_STATUS, ep: %d (%x), val = %d\n", ep_num,
+                           ctrl->wIndex, val);
+       } else {
+               DEBUG_SETUP("Unknown REQ TYPE: %d\n", reqtype);
+               return -EOPNOTSUPP;
+       }
+
+       /* Clear "out packet ready" */
+       usb_set((EP0_CLR_OUT), USB_EP0_CSR);
+       /* Put status to FIFO */
+       lh7a40x_fifo_write(ep0, (u8 *) & val, sizeof(val));
+       /* Issue "In packet ready" */
+       usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+
+       return 0;
+}
+
+/*
+ * WAIT_FOR_SETUP (OUT_PKT_RDY)
+ *      - read data packet from EP0 FIFO
+ *      - decode command
+ *      - if error
+ *              set EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL bits
+ *      - else
+ *              set EP0_CLR_OUT | EP0_DATA_END bits
+ */
+static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
+{
+       struct lh7a40x_ep *ep = &dev->ep[0];
+       struct usb_ctrlrequest ctrl;
+       int i, bytes, is_in;
+
+       DEBUG_SETUP("%s: %x\n", __FUNCTION__, csr);
+
+       /* Nuke all previous transfers */
+       nuke(ep, -EPROTO);
+
+       /* read control req from fifo (8 bytes) */
+       bytes = lh7a40x_fifo_read(ep, (unsigned char *)&ctrl, 8);
+
+       DEBUG_SETUP("Read CTRL REQ %d bytes\n", bytes);
+       DEBUG_SETUP("CTRL.bRequestType = %d (is_in %d)\n", ctrl.bRequestType,
+                   ctrl.bRequestType == USB_DIR_IN);
+       DEBUG_SETUP("CTRL.bRequest = %d\n", ctrl.bRequest);
+       DEBUG_SETUP("CTRL.wLength = %d\n", ctrl.wLength);
+       DEBUG_SETUP("CTRL.wValue = %d (%d)\n", ctrl.wValue, ctrl.wValue >> 8);
+       DEBUG_SETUP("CTRL.wIndex = %d\n", ctrl.wIndex);
+
+       /* Set direction of EP0 */
+       if (likely(ctrl.bRequestType & USB_DIR_IN)) {
+               ep->bEndpointAddress |= USB_DIR_IN;
+               is_in = 1;
+       } else {
+               ep->bEndpointAddress &= ~USB_DIR_IN;
+               is_in = 0;
+       }
+
+       dev->req_pending = 1;
+
+       /* Handle some SETUP packets ourselves */
+       switch (ctrl.bRequest) {
+       case USB_REQ_SET_ADDRESS:
+               if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE))
+                       break;
+
+               DEBUG_SETUP("USB_REQ_SET_ADDRESS (%d)\n", ctrl.wValue);
+               udc_set_address(dev, ctrl.wValue);
+               usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
+               return;
+
+       case USB_REQ_GET_STATUS:{
+                       if (lh7a40x_handle_get_status(dev, &ctrl) == 0)
+                               return;
+
+       case USB_REQ_CLEAR_FEATURE:
+       case USB_REQ_SET_FEATURE:
+                       if (ctrl.bRequestType == USB_RECIP_ENDPOINT) {
+                               struct lh7a40x_ep *qep;
+                               int ep_num = (ctrl.wIndex & 0x0f);
+
+                               /* Support only HALT feature */
+                               if (ctrl.wValue != 0 || ctrl.wLength != 0
+                                   || ep_num > 3 || ep_num < 1)
+                                       break;
+
+                               qep = &dev->ep[ep_num];
+                               if (ctrl.bRequest == USB_REQ_SET_FEATURE) {
+                                       DEBUG_SETUP("SET_FEATURE (%d)\n",
+                                                   ep_num);
+                                       lh7a40x_set_halt(&qep->ep, 1);
+                               } else {
+                                       DEBUG_SETUP("CLR_FEATURE (%d)\n",
+                                                   ep_num);
+                                       lh7a40x_set_halt(&qep->ep, 0);
+                               }
+                               usb_set_index(0);
+
+                               /* Reply with a ZLP on next IN token */
+                               usb_set((EP0_CLR_OUT | EP0_DATA_END),
+                                       USB_EP0_CSR);
+                               return;
+                       }
+                       break;
+               }
+
+       default:
+               break;
+       }
+
+       if (likely(dev->driver)) {
+               /* device-2-host (IN) or no data setup command, process immediately */
+               spin_unlock(&dev->lock);
+               i = dev->driver->setup(&dev->gadget, &ctrl);
+               spin_lock(&dev->lock);
+
+               if (i < 0) {
+                       /* setup processing failed, force stall */
+                       DEBUG_SETUP
+                           ("  --> ERROR: gadget setup FAILED (stalling), setup returned %d\n",
+                            i);
+                       usb_set_index(0);
+                       usb_set((EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL),
+                               USB_EP0_CSR);
+
+                       /* ep->stopped = 1; */
+                       dev->ep0state = WAIT_FOR_SETUP;
+               }
+       }
+}
+
+/*
+ * DATA_STATE_NEED_ZLP
+ */
+static void lh7a40x_ep0_in_zlp(struct lh7a40x_udc *dev, u32 csr)
+{
+       DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+
+       /* c.f. Table 15-14 */
+       usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+       dev->ep0state = WAIT_FOR_SETUP;
+}
+
+/*
+ * handle ep0 interrupt
+ */
+static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+{
+       struct lh7a40x_ep *ep = &dev->ep[0];
+       u32 csr;
+
+       /* Set index 0 */
+       usb_set_index(0);
+       csr = usb_read(USB_EP0_CSR);
+
+       DEBUG_EP0("%s: csr = %x\n", __FUNCTION__, csr);
+
+       /*
+        * For overview of what we should be doing see c.f. Chapter 18.1.2.4
+        * We will follow that outline here modified by our own global state
+        * indication which provides hints as to what we think should be
+        * happening..
+        */
+
+       /*
+        * if SENT_STALL is set
+        *      - clear the SENT_STALL bit
+        */
+       if (csr & EP0_SENT_STALL) {
+               DEBUG_EP0("%s: EP0_SENT_STALL is set: %x\n", __FUNCTION__, csr);
+               usb_clear((EP0_SENT_STALL | EP0_SEND_STALL), USB_EP0_CSR);
+               nuke(ep, -ECONNABORTED);
+               dev->ep0state = WAIT_FOR_SETUP;
+               return;
+       }
+
+       /*
+        * if a transfer is in progress && IN_PKT_RDY and OUT_PKT_RDY are clear
+        *      - fill EP0 FIFO
+        *      - if last packet
+        *      -       set IN_PKT_RDY | DATA_END
+        *      - else
+        *              set IN_PKT_RDY
+        */
+       if (!(csr & (EP0_IN_PKT_RDY | EP0_OUT_PKT_RDY))) {
+               DEBUG_EP0("%s: IN_PKT_RDY and OUT_PKT_RDY are clear\n",
+                         __FUNCTION__);
+
+               switch (dev->ep0state) {
+               case DATA_STATE_XMIT:
+                       DEBUG_EP0("continue with DATA_STATE_XMIT\n");
+                       lh7a40x_ep0_in(dev, csr);
+                       return;
+               case DATA_STATE_NEED_ZLP:
+                       DEBUG_EP0("continue with DATA_STATE_NEED_ZLP\n");
+                       lh7a40x_ep0_in_zlp(dev, csr);
+                       return;
+               default:
+                       /* Stall? */
+                       DEBUG_EP0("Odd state!! state = %s\n",
+                                 state_names[dev->ep0state]);
+                       dev->ep0state = WAIT_FOR_SETUP;
+                       /* nuke(ep, 0); */
+                       /* usb_set(EP0_SEND_STALL, ep->csr1); */
+                       break;
+               }
+       }
+
+       /*
+        * if SETUP_END is set
+        *      - abort the last transfer
+        *      - set SERVICED_SETUP_END_BIT
+        */
+       if (csr & EP0_SETUP_END) {
+               DEBUG_EP0("%s: EP0_SETUP_END is set: %x\n", __FUNCTION__, csr);
+
+               usb_set(EP0_CLR_SETUP_END, USB_EP0_CSR);
+
+               nuke(ep, 0);
+               dev->ep0state = WAIT_FOR_SETUP;
+       }
+
+       /*
+        * if EP0_OUT_PKT_RDY is set
+        *      - read data packet from EP0 FIFO
+        *      - decode command
+        *      - if error
+        *              set SERVICED_OUT_PKT_RDY | DATA_END bits | SEND_STALL
+        *      - else
+        *              set SERVICED_OUT_PKT_RDY | DATA_END bits
+        */
+       if (csr & EP0_OUT_PKT_RDY) {
+
+               DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __FUNCTION__,
+                         csr);
+
+               switch (dev->ep0state) {
+               case WAIT_FOR_SETUP:
+                       DEBUG_EP0("WAIT_FOR_SETUP\n");
+                       lh7a40x_ep0_setup(dev, csr);
+                       break;
+
+               case DATA_STATE_RECV:
+                       DEBUG_EP0("DATA_STATE_RECV\n");
+                       lh7a40x_ep0_out(dev, csr);
+                       break;
+
+               default:
+                       /* send stall? */
+                       DEBUG_EP0("strange state!! 2. send stall? state = %d\n",
+                                 dev->ep0state);
+                       break;
+               }
+       }
+}
+
+static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep)
+{
+       u32 csr;
+
+       usb_set_index(0);
+       csr = usb_read(USB_EP0_CSR);
+
+       DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+
+       /* Clear "out packet ready" */
+       usb_set(EP0_CLR_OUT, USB_EP0_CSR);
+
+       if (ep_is_in(ep)) {
+               dev->ep0state = DATA_STATE_XMIT;
+               lh7a40x_ep0_in(dev, csr);
+       } else {
+               dev->ep0state = DATA_STATE_RECV;
+               lh7a40x_ep0_out(dev, csr);
+       }
+}
+
+/* ---------------------------------------------------------------------------
+ *     device-scoped parts of the api to the usb controller hardware
+ * ---------------------------------------------------------------------------
+ */
+
+static int lh7a40x_udc_get_frame(struct usb_gadget *_gadget)
+{
+       u32 frame1 = usb_read(USB_FRM_NUM1);    /* Least significant 8 bits */
+       u32 frame2 = usb_read(USB_FRM_NUM2);    /* Most significant 3 bits */
+       DEBUG("%s, %p\n", __FUNCTION__, _gadget);
+       return ((frame2 & 0x07) << 8) | (frame1 & 0xff);
+}
+
+static int lh7a40x_udc_wakeup(struct usb_gadget *_gadget)
+{
+       /* host may not have enabled remote wakeup */
+       /*if ((UDCCS0 & UDCCS0_DRWF) == 0)
+          return -EHOSTUNREACH;
+          udc_set_mask_UDCCR(UDCCR_RSM); */
+       return -ENOTSUPP;
+}
+
+static const struct usb_gadget_ops lh7a40x_udc_ops = {
+       .get_frame = lh7a40x_udc_get_frame,
+       .wakeup = lh7a40x_udc_wakeup,
+       /* current versions must always be self-powered */
+};
+
+static void nop_release(struct device *dev)
+{
+       DEBUG("%s %s\n", __FUNCTION__, dev->bus_id);
+}
+
+static struct lh7a40x_udc memory = {
+       .usb_address = 0,
+
+       .gadget = {
+                  .ops = &lh7a40x_udc_ops,
+                  .ep0 = &memory.ep[0].ep,
+                  .name = driver_name,
+                  .dev = {
+                          .bus_id = "gadget",
+                          .release = nop_release,
+                          },
+                  },
+
+       /* control endpoint */
+       .ep[0] = {
+                 .ep = {
+                        .name = ep0name,
+                        .ops = &lh7a40x_ep_ops,
+                        .maxpacket = EP0_PACKETSIZE,
+                        },
+                 .dev = &memory,
+
+                 .bEndpointAddress = 0,
+                 .bmAttributes = 0,
+
+                 .ep_type = ep_control,
+                 .fifo = io_p2v(USB_EP0_FIFO),
+                 .csr1 = USB_EP0_CSR,
+                 .csr2 = USB_EP0_CSR,
+                 },
+
+       /* first group of endpoints */
+       .ep[1] = {
+                 .ep = {
+                        .name = "ep1in-bulk",
+                        .ops = &lh7a40x_ep_ops,
+                        .maxpacket = 64,
+                        },
+                 .dev = &memory,
+
+                 .bEndpointAddress = USB_DIR_IN | 1,
+                 .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+                 .ep_type = ep_bulk_in,
+                 .fifo = io_p2v(USB_EP1_FIFO),
+                 .csr1 = USB_IN_CSR1,
+                 .csr2 = USB_IN_CSR2,
+                 },
+
+       .ep[2] = {
+                 .ep = {
+                        .name = "ep2out-bulk",
+                        .ops = &lh7a40x_ep_ops,
+                        .maxpacket = 64,
+                        },
+                 .dev = &memory,
+
+                 .bEndpointAddress = 2,
+                 .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+                 .ep_type = ep_bulk_out,
+                 .fifo = io_p2v(USB_EP2_FIFO),
+                 .csr1 = USB_OUT_CSR1,
+                 .csr2 = USB_OUT_CSR2,
+                 },
+
+       .ep[3] = {
+                 .ep = {
+                        .name = "ep3in-int",
+                        .ops = &lh7a40x_ep_ops,
+                        .maxpacket = 64,
+                        },
+                 .dev = &memory,
+
+                 .bEndpointAddress = USB_DIR_IN | 3,
+                 .bmAttributes = USB_ENDPOINT_XFER_INT,
+
+                 .ep_type = ep_interrupt,
+                 .fifo = io_p2v(USB_EP3_FIFO),
+                 .csr1 = USB_IN_CSR1,
+                 .csr2 = USB_IN_CSR2,
+                 },
+};
+
+/*
+ *     probe - binds to the platform device
+ */
+static int lh7a40x_udc_probe(struct device *_dev)
+{
+       struct lh7a40x_udc *dev = &memory;
+       int retval;
+
+       DEBUG("%s: %p\n", __FUNCTION__, _dev);
+
+       spin_lock_init(&dev->lock);
+       dev->dev = _dev;
+
+       device_initialize(&dev->gadget.dev);
+       dev->gadget.dev.parent = _dev;
+
+       the_controller = dev;
+       dev_set_drvdata(_dev, dev);
+
+       udc_disable(dev);
+       udc_reinit(dev);
+
+       /* irq setup after old hardware state is cleaned up */
+       retval =
+           request_irq(IRQ_USBINTR, lh7a40x_udc_irq, SA_INTERRUPT, driver_name,
+                       dev);
+       if (retval != 0) {
+               DEBUG(KERN_ERR "%s: can't get irq %i, err %d\n", driver_name,
+                     IRQ_USBINTR, retval);
+               return -EBUSY;
+       }
+
+       create_proc_files();
+
+       return retval;
+}
+
+static int lh7a40x_udc_remove(struct device *_dev)
+{
+       struct lh7a40x_udc *dev = _dev->driver_data;
+
+       DEBUG("%s: %p\n", __FUNCTION__, dev);
+
+       udc_disable(dev);
+       remove_proc_files();
+       usb_gadget_unregister_driver(dev->driver);
+
+       free_irq(IRQ_USBINTR, dev);
+
+       dev_set_drvdata(_dev, 0);
+
+       the_controller = 0;
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct device_driver udc_driver = {
+       .name = (char *)driver_name,
+       .bus = &platform_bus_type,
+       .probe = lh7a40x_udc_probe,
+       .remove = lh7a40x_udc_remove
+           /* FIXME power management support */
+           /* .suspend = ... disable UDC */
+           /* .resume = ... re-enable UDC */
+};
+
+static int __init udc_init(void)
+{
+       DEBUG("%s: %s version %s\n", __FUNCTION__, driver_name, DRIVER_VERSION);
+       return driver_register(&udc_driver);
+}
+
+static void __exit udc_exit(void)
+{
+       driver_unregister(&udc_driver);
+}
+
+module_init(udc_init);
+module_exit(udc_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Mikko Lahteenmaki, Bo Henriksen");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/lh7a40x_udc.h b/drivers/usb/gadget/lh7a40x_udc.h
new file mode 100644 (file)
index 0000000..1bb455c
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * linux/drivers/usb/gadget/lh7a40x_udc.h
+ * Sharp LH7A40x on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004 Mikko Lahteenmaki, Nordic ID
+ * Copyright (C) 2004 Bo Henriksen, Nordic ID
+ *
+ * This program is free software; you can redistribute 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 __LH7A40X_H_
+#define __LH7A40X_H_
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/byteorder.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/hardware.h>
+
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+
+/*
+ * Memory map
+ */
+
+#define USB_FA                                 0x80000200      // function address register
+#define USB_PM                                 0x80000204      // power management register
+
+#define USB_IN_INT                             0x80000208      // IN interrupt register bank (EP0-EP3)
+#define USB_OUT_INT                            0x80000210      // OUT interrupt register bank (EP2)
+#define USB_INT                                        0x80000218      // interrupt register bank
+
+#define USB_IN_INT_EN                  0x8000021C      // IN interrupt enable register bank
+#define USB_OUT_INT_EN                 0x80000224      // OUT interrupt enable register bank
+#define USB_INT_EN                             0x8000022C      // USB interrupt enable register bank
+
+#define USB_FRM_NUM1                   0x80000230      // Frame number1 register
+#define USB_FRM_NUM2                   0x80000234      // Frame number2 register
+#define USB_INDEX                              0x80000238      // index register
+
+#define USB_IN_MAXP                            0x80000240      // IN MAXP register
+#define USB_IN_CSR1                            0x80000244      // IN CSR1 register/EP0 CSR register
+#define USB_EP0_CSR                            0x80000244      // IN CSR1 register/EP0 CSR register
+#define USB_IN_CSR2                            0x80000248      // IN CSR2 register
+#define USB_OUT_MAXP                   0x8000024C      // OUT MAXP register
+
+#define USB_OUT_CSR1                   0x80000250      // OUT CSR1 register
+#define USB_OUT_CSR2                   0x80000254      // OUT CSR2 register
+#define USB_OUT_FIFO_WC1               0x80000258      // OUT FIFO write count1 register
+#define USB_OUT_FIFO_WC2               0x8000025C      // OUT FIFO write count2 register
+
+#define USB_RESET                              0x8000044C      // USB reset register
+
+#define        USB_EP0_FIFO                    0x80000280
+#define        USB_EP1_FIFO                    0x80000284
+#define        USB_EP2_FIFO                    0x80000288
+#define        USB_EP3_FIFO                    0x8000028c
+
+/*
+ * USB reset register
+ */
+#define USB_RESET_APB                  (1<<1)  //resets USB APB control side WRITE
+#define USB_RESET_IO                   (1<<0)  //resets USB IO side WRITE
+
+/*
+ * USB function address register
+ */
+#define USB_FA_ADDR_UPDATE             (1<<7)
+#define USB_FA_FUNCTION_ADDR   (0x7F)
+
+/*
+ * Power Management register
+ */
+#define PM_USB_DCP                             (1<<5)
+#define PM_USB_ENABLE                  (1<<4)
+#define PM_USB_RESET                   (1<<3)
+#define PM_UC_RESUME                   (1<<2)
+#define PM_SUSPEND_MODE                        (1<<1)
+#define PM_ENABLE_SUSPEND              (1<<0)
+
+/*
+ * IN interrupt register
+ */
+#define USB_IN_INT_EP3                         (1<<3)
+#define USB_IN_INT_EP1                         (1<<1)
+#define USB_IN_INT_EP0                         (1<<0)
+
+/*
+ * OUT interrupt register
+ */
+#define USB_OUT_INT_EP2                                (1<<2)
+
+/*
+ * USB interrupt register
+ */
+#define USB_INT_RESET_INT                      (1<<2)
+#define USB_INT_RESUME_INT                     (1<<1)
+#define USB_INT_SUSPEND_INT                    (1<<0)
+
+/*
+ * USB interrupt enable register
+ */
+#define USB_INT_EN_USB_RESET_INTER             (1<<2)
+#define USB_INT_EN_RESUME_INTER                        (1<<1)
+#define USB_INT_EN_SUSPEND_INTER               (1<<0)
+
+/*
+ * INCSR1 register
+ */
+#define USB_IN_CSR1_CLR_DATA_TOGGLE            (1<<6)
+#define USB_IN_CSR1_SENT_STALL                 (1<<5)
+#define USB_IN_CSR1_SEND_STALL                 (1<<4)
+#define USB_IN_CSR1_FIFO_FLUSH                 (1<<3)
+#define USB_IN_CSR1_FIFO_NOT_EMPTY             (1<<1)
+#define USB_IN_CSR1_IN_PKT_RDY                 (1<<0)
+
+/*
+ * INCSR2 register
+ */
+#define USB_IN_CSR2_AUTO_SET                   (1<<7)
+#define USB_IN_CSR2_USB_DMA_EN                 (1<<4)
+
+/*
+ * OUT CSR1 register
+ */
+#define USB_OUT_CSR1_CLR_DATA_REG              (1<<7)
+#define USB_OUT_CSR1_SENT_STALL                        (1<<6)
+#define USB_OUT_CSR1_SEND_STALL                        (1<<5)
+#define USB_OUT_CSR1_FIFO_FLUSH                        (1<<4)
+#define USB_OUT_CSR1_FIFO_FULL                 (1<<1)
+#define USB_OUT_CSR1_OUT_PKT_RDY               (1<<0)
+
+/*
+ * OUT CSR2 register
+ */
+#define USB_OUT_CSR2_AUTO_CLR                  (1<<7)
+#define USB_OUT_CSR2_USB_DMA_EN                        (1<<4)
+
+/*
+ * EP0 CSR
+ */
+#define EP0_CLR_SETUP_END              (1<<7)  /* Clear "Setup Ends" Bit (w) */
+#define EP0_CLR_OUT                            (1<<6)  /* Clear "Out packet ready" Bit (w) */
+#define EP0_SEND_STALL                 (1<<5)  /* Send STALL Handshake (rw) */
+#define EP0_SETUP_END                  (1<<4)  /* Setup Ends (r) */
+
+#define EP0_DATA_END                   (1<<3)  /* Data end (rw) */
+#define EP0_SENT_STALL                 (1<<2)  /* Sent Stall Handshake (r) */
+#define EP0_IN_PKT_RDY                 (1<<1)  /* In packet ready (rw) */
+#define EP0_OUT_PKT_RDY                        (1<<0)  /* Out packet ready (r) */
+
+/* general CSR */
+#define OUT_PKT_RDY            (1<<0)
+#define IN_PKT_RDY             (1<<0)
+
+/*
+ * IN/OUT MAXP register
+ */
+#define USB_OUT_MAXP_MAXP                      (0xF)
+#define USB_IN_MAXP_MAXP                       (0xF)
+
+// Max packet size
+//#define EP0_PACKETSIZE        0x10
+#define EP0_PACKETSIZE         0x8
+#define EP0_MAXPACKETSIZE      0x10
+
+#define UDC_MAX_ENDPOINTS       4
+
+#define WAIT_FOR_SETUP          0
+#define DATA_STATE_XMIT         1
+#define DATA_STATE_NEED_ZLP     2
+#define WAIT_FOR_OUT_STATUS     3
+#define DATA_STATE_RECV         4
+
+/* ********************************************************************************************* */
+/* IO
+ */
+
+typedef enum ep_type {
+       ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt
+} ep_type_t;
+
+struct lh7a40x_ep {
+       struct usb_ep ep;
+       struct lh7a40x_udc *dev;
+
+       const struct usb_endpoint_descriptor *desc;
+       struct list_head queue;
+       unsigned long pio_irqs;
+
+       u8 stopped;
+       u8 bEndpointAddress;
+       u8 bmAttributes;
+
+       ep_type_t ep_type;
+       u32 fifo;
+       u32 csr1;
+       u32 csr2;
+};
+
+struct lh7a40x_request {
+       struct usb_request req;
+       struct list_head queue;
+};
+
+struct lh7a40x_udc {
+       struct usb_gadget gadget;
+       struct usb_gadget_driver *driver;
+       struct device *dev;
+       spinlock_t lock;
+
+       int ep0state;
+       struct lh7a40x_ep ep[UDC_MAX_ENDPOINTS];
+
+       unsigned char usb_address;
+
+       unsigned req_pending:1, req_std:1, req_config:1;
+};
+
+extern struct lh7a40x_udc *the_controller;
+
+#define ep_is_in(EP)           (((EP)->bEndpointAddress&USB_DIR_IN)==USB_DIR_IN)
+#define ep_index(EP)           ((EP)->bEndpointAddress&0xF)
+#define ep_maxpacket(EP)       ((EP)->ep.maxpacket)
+
+#endif
index ec9d6f7..8033c4e 100644 (file)
@@ -446,7 +446,7 @@ struct net2280_ep_regs {    /* [11.9] */
  */
 
 static inline u32
-get_idx_reg (struct net2280_regs *regs, u32 index)
+get_idx_reg (struct net2280_regs __iomem *regs, u32 index)
 {
        writel (index, &regs->idxaddr);
        /* NOTE:  synchs device/cpu memory views */
@@ -454,7 +454,7 @@ get_idx_reg (struct net2280_regs *regs, u32 index)
 }
 
 static inline void
-set_idx_reg (struct net2280_regs *regs, u32 index, u32 value)
+set_idx_reg (struct net2280_regs __iomem *regs, u32 index, u32 value)
 {
        writel (index, &regs->idxaddr);
        writel (value, &regs->idxdata);
@@ -507,8 +507,8 @@ struct net2280_dma {
 
 struct net2280_ep {
        struct usb_ep                           ep;
-       struct net2280_ep_regs                  *regs;
-       struct net2280_dma_regs                 *dma;
+       struct net2280_ep_regs                  __iomem *regs;
+       struct net2280_dma_regs                 __iomem *dma;
        struct net2280_dma                      *dummy;
        dma_addr_t                              td_dma; /* of dummy */
        struct net2280                          *dev;
@@ -539,7 +539,7 @@ static inline void allow_status (struct net2280_ep *ep)
 /* count (<= 4) bytes in the next fifo write will be valid */
 static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count)
 {
-       writeb (count, 2 + (u8 *) &ep->regs->ep_cfg);
+       writeb (count, 2 + (u8 __iomem *) &ep->regs->ep_cfg);
 }
 
 struct net2280_request {
@@ -559,18 +559,19 @@ struct net2280 {
        struct usb_gadget_driver        *driver;
        unsigned                        enabled : 1,
                                        protocol_stall : 1,
+                                       softconnect : 1,
                                        got_irq : 1,
                                        region : 1;
        u16                             chiprev;
 
        /* pci state used to access those endpoints */
        struct pci_dev                  *pdev;
-       struct net2280_regs             *regs;
-       struct net2280_usb_regs         *usb;
-       struct net2280_pci_regs         *pci;
-       struct net2280_dma_regs         *dma;
-       struct net2280_dep_regs         *dep;
-       struct net2280_ep_regs          *epregs;
+       struct net2280_regs             __iomem *regs;
+       struct net2280_usb_regs         __iomem *usb;
+       struct net2280_pci_regs         __iomem *pci;
+       struct net2280_dma_regs         __iomem *dma;
+       struct net2280_dep_regs         __iomem *dep;
+       struct net2280_ep_regs          __iomem *epregs;
 
        struct pci_pool                 *requests;
        // statistics...
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
new file mode 100644 (file)
index 0000000..e40089d
--- /dev/null
@@ -0,0 +1,2695 @@
+/*
+ * omap_udc.c -- for OMAP 1610 udc, with OTG support
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ * Copyright (C) 2004 David Brownell
+ *
+ * This program is free software; you can redistribute 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
+ */
+
+#undef DEBUG
+#undef VERBOSE
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+#include <linux/usb_otg.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+
+#include "omap_udc.h"
+
+#undef USB_TRACE
+
+/* OUT-dma seems to be behaving */
+#define        USE_DMA
+
+/* ISO too */
+#define        USE_ISO
+
+
+#define        DRIVER_DESC     "OMAP UDC driver"
+#define        DRIVER_VERSION  "24 August 2004"
+
+#define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
+
+
+/*
+ * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
+ * D+ pullup to allow enumeration.  That's too early for the gadget
+ * framework to use from usb_endpoint_enable(), which happens after
+ * enumeration as part of activating an interface.  (But if we add an
+ * optional new "UDC not yet running" state to the gadget driver model,
+ * even just during driver binding, the endpoint autoconfig logic is the
+ * natural spot to manufacture new endpoints.)
+ *
+ * So instead of using endpoint enable calls to control the hardware setup,
+ * this driver defines a "fifo mode" parameter.  It's used during driver
+ * initialization to choose among a set of pre-defined endpoint configs.
+ * See omap_udc_setup() for available modes, or to add others.  That code
+ * lives in an init section, so use this driver as a module if you need
+ * to change the fifo mode after the kernel boots.
+ *
+ * Gadget drivers normally ignore endpoints they don't care about, and
+ * won't include them in configuration descriptors.  That means only
+ * misbehaving hosts would even notice they exist.
+ */
+#ifdef USE_ISO
+static unsigned fifo_mode = 3;
+#else
+static unsigned fifo_mode = 0;
+#endif
+
+/* "modprobe omap_udc fifo_mode=42", or else as a kernel
+ * boot parameter "omap_udc:fifo_mode=42"
+ */
+module_param (fifo_mode, uint, 0);
+MODULE_PARM_DESC (fifo_mode, "endpoint setup (0 == default)");
+
+
+#ifdef USE_DMA
+static unsigned use_dma = 1;
+
+/* "modprobe omap_udc use_dma=y", or else as a kernel
+ * boot parameter "omap_udc:use_dma=y"
+ */
+module_param (use_dma, bool, 0);
+MODULE_PARM_DESC (use_dma, "enable/disable DMA");
+#else  /* !USE_DMA */
+
+/* save a bit of code */
+#define        use_dma         0
+#endif /* !USE_DMA */
+
+
+static const char driver_name [] = "omap_udc";
+static const char driver_desc [] = DRIVER_DESC;
+
+/*-------------------------------------------------------------------------*/
+
+/* there's a notion of "current endpoint" for modifying endpoint
+ * state, and PIO access to its FIFO.  
+ */
+
+static void use_ep(struct omap_ep *ep, u16 select)
+{
+       u16     num = ep->bEndpointAddress & 0x0f;
+
+       if (ep->bEndpointAddress & USB_DIR_IN)
+               num |= UDC_EP_DIR;
+       UDC_EP_NUM_REG = num | select;
+       /* when select, MUST deselect later !! */
+}
+
+static inline void deselect_ep(void)
+{
+       UDC_EP_NUM_REG &= ~UDC_EP_SEL;
+       /* 6 wait states before TX will happen */
+}
+
+static void dma_channel_claim(struct omap_ep *ep, unsigned preferred);
+
+/*-------------------------------------------------------------------------*/
+
+static int omap_ep_enable(struct usb_ep *_ep,
+               const struct usb_endpoint_descriptor *desc)
+{
+       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
+       struct omap_udc *udc;
+       unsigned long   flags;
+       u16             maxp;
+
+       /* catch various bogus parameters */
+       if (!_ep || !desc || ep->desc
+                       || desc->bDescriptorType != USB_DT_ENDPOINT
+                       || ep->bEndpointAddress != desc->bEndpointAddress
+                       || ep->maxpacket < le16_to_cpu
+                                               (desc->wMaxPacketSize)) {
+               DBG("%s, bad ep or descriptor\n", __FUNCTION__);
+               return -EINVAL;
+       }
+       maxp = le16_to_cpu (desc->wMaxPacketSize);
+       if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+                               && maxp != ep->maxpacket)
+                       || desc->wMaxPacketSize > ep->maxpacket
+                       || !desc->wMaxPacketSize) {
+               DBG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
+               return -ERANGE;
+       }
+
+#ifdef USE_ISO
+       if ((desc->bmAttributes == USB_ENDPOINT_XFER_ISOC
+                               && desc->bInterval != 1)) {
+               /* hardware wants period = 1; USB allows 2^(Interval-1) */
+               DBG("%s, unsupported ISO period %dms\n", _ep->name,
+                               1 << (desc->bInterval - 1));
+               return -EDOM;
+       }
+#else
+       if (desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+               DBG("%s, ISO nyet\n", _ep->name);
+               return -EDOM;
+       }
+#endif
+
+       /* xfer types must match, except that interrupt ~= bulk */
+       if (ep->bmAttributes != desc->bmAttributes
+                       && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+                       && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+               DBG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
+               return -EINVAL;
+       }
+
+       udc = ep->udc;
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+               DBG("%s, bogus device state\n", __FUNCTION__);
+               return -ESHUTDOWN;
+       }
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       ep->desc = desc;
+       ep->irqs = 0;
+       ep->stopped = 0;
+       ep->ep.maxpacket = maxp;
+
+       /* set endpoint to initial state */
+       ep->dma_channel = 0;
+       ep->has_dma = 0;
+       ep->lch = -1;
+       use_ep(ep, UDC_EP_SEL);
+       UDC_CTRL_REG = UDC_RESET_EP;
+       ep->ackwait = 0;
+       deselect_ep();
+
+       if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+               list_add(&ep->iso, &udc->iso);
+
+       /* maybe assign a DMA channel to this endpoint */
+       if (use_dma && desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+                       && !(ep->bEndpointAddress & USB_DIR_IN))
+                       /* FIXME ISO can dma, but prefers first channel.
+                        * IN can dma, but lacks debugging.
+                        */
+               dma_channel_claim(ep, 0);
+
+       /* PIO OUT may RX packets */
+       if (desc->bmAttributes != USB_ENDPOINT_XFER_ISOC
+                       && !ep->has_dma
+                       && !(ep->bEndpointAddress & USB_DIR_IN))
+               UDC_CTRL_REG = UDC_SET_FIFO_EN;
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       VDBG("%s enabled\n", _ep->name);
+       return 0;
+}
+
+static void nuke(struct omap_ep *, int status);
+
+static int omap_ep_disable(struct usb_ep *_ep)
+{
+       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
+       unsigned long   flags;
+
+       if (!_ep || !ep->desc) {
+               DBG("%s, %s not enabled\n", __FUNCTION__,
+                       _ep ? ep->ep.name : NULL);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+       ep->desc = 0;
+       nuke (ep, -ESHUTDOWN);
+       ep->ep.maxpacket = ep->maxpacket;
+       ep->has_dma = 0;
+       UDC_CTRL_REG = UDC_SET_HALT;
+       list_del_init(&ep->iso);
+
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+
+       VDBG("%s disabled\n", _ep->name);
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_request *
+omap_alloc_request(struct usb_ep *ep, int gfp_flags)
+{
+       struct omap_req *req;
+
+       req = kmalloc(sizeof *req, gfp_flags);
+       if (req) {
+               memset (req, 0, sizeof *req);
+               req->req.dma = DMA_ADDR_INVALID;
+               INIT_LIST_HEAD (&req->queue);
+       }
+       return &req->req;
+}
+
+static void
+omap_free_request(struct usb_ep *ep, struct usb_request *_req)
+{
+       struct omap_req *req = container_of(_req, struct omap_req, req);
+
+       if (_req)
+               kfree (req);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void *
+omap_alloc_buffer(
+       struct usb_ep   *_ep,
+       unsigned        bytes,
+       dma_addr_t      *dma,
+       int             gfp_flags
+)
+{
+       void            *retval;
+       struct omap_ep  *ep;
+
+       ep = container_of(_ep, struct omap_ep, ep);
+       if (use_dma && ep->has_dma) {
+               static int      warned;
+               if (!warned && bytes < PAGE_SIZE) {
+                       dev_warn(ep->udc->gadget.dev.parent,
+                               "using dma_alloc_coherent for "
+                               "small allocations wastes memory\n");
+                       warned++;
+               }
+               return dma_alloc_coherent(ep->udc->gadget.dev.parent,
+                               bytes, dma, gfp_flags);
+       }
+
+       retval = kmalloc(bytes, gfp_flags);
+       if (retval)
+               *dma = virt_to_phys(retval);
+       return retval;
+}
+
+static void omap_free_buffer(
+       struct usb_ep   *_ep,
+       void            *buf,
+       dma_addr_t      dma,
+       unsigned        bytes
+)
+{
+       struct omap_ep  *ep;
+
+       ep = container_of(_ep, struct omap_ep, ep);
+       if (use_dma && _ep && ep->has_dma)
+               dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma);
+       else
+               kfree (buf);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+done(struct omap_ep *ep, struct omap_req *req, int status)
+{
+       unsigned                stopped = ep->stopped;
+
+       list_del_init(&req->queue);
+
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       if (use_dma && ep->has_dma) {
+               if (req->mapped) {
+                       dma_unmap_single(ep->udc->gadget.dev.parent,
+                               req->req.dma, req->req.length,
+                               (ep->bEndpointAddress & USB_DIR_IN)
+                                       ? DMA_TO_DEVICE
+                                       : DMA_FROM_DEVICE);
+                       req->req.dma = DMA_ADDR_INVALID;
+                       req->mapped = 0;
+               } else
+                       dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
+                               req->req.dma, req->req.length,
+                               (ep->bEndpointAddress & USB_DIR_IN)
+                                       ? DMA_TO_DEVICE
+                                       : DMA_FROM_DEVICE);
+       }
+
+#ifndef        USB_TRACE
+       if (status && status != -ESHUTDOWN)
+#endif
+               VDBG("complete %s req %p stat %d len %u/%u\n",
+                       ep->ep.name, &req->req, status,
+                       req->req.actual, req->req.length);
+
+       /* don't modify queue heads during completion callback */
+       ep->stopped = 1;
+       spin_unlock(&ep->udc->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&ep->udc->lock);
+       ep->stopped = stopped;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define        FIFO_FULL       (UDC_NON_ISO_FIFO_FULL | UDC_ISO_FIFO_FULL)
+#define        FIFO_UNWRITABLE (UDC_EP_HALTED | FIFO_FULL)
+
+#define FIFO_EMPTY     (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY)
+#define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY)
+
+static inline int 
+write_packet(u8 *buf, struct omap_req *req, unsigned max)
+{
+       unsigned        len;
+       u16             *wp;
+
+       len = min(req->req.length - req->req.actual, max);
+       req->req.actual += len;
+
+       max = len;
+       if (likely((((int)buf) & 1) == 0)) {
+               wp = (u16 *)buf;
+               while (max >= 2) {
+                       UDC_DATA_REG = *wp++;
+                       max -= 2;
+               }
+               buf = (u8 *)wp;
+       }
+       while (max--)
+               *(volatile u8 *)&UDC_DATA_REG = *buf++;
+       return len;
+}
+
+// FIXME change r/w fifo calling convention
+
+
+// return:  0 = still running, 1 = completed, negative = errno
+static int write_fifo(struct omap_ep *ep, struct omap_req *req)
+{
+       u8              *buf;
+       unsigned        count;
+       int             is_last;
+       u16             ep_stat;
+
+       buf = req->req.buf + req->req.actual;
+       prefetch(buf);
+
+       /* PIO-IN isn't double buffered except for iso */
+       ep_stat = UDC_STAT_FLG_REG;
+       if (ep_stat & FIFO_UNWRITABLE)
+               return 0;
+
+       count = ep->ep.maxpacket;
+       count = write_packet(buf, req, count);
+       UDC_CTRL_REG = UDC_SET_FIFO_EN;
+       ep->ackwait = 1;
+
+       /* last packet is often short (sometimes a zlp) */
+       if (count != ep->ep.maxpacket)
+               is_last = 1;
+       else if (req->req.length == req->req.actual
+                       && !req->req.zero)
+               is_last = 1;
+       else
+               is_last = 0;
+
+       /* NOTE:  requests complete when all IN data is in a
+        * FIFO (or sometimes later, if a zlp was needed).
+        * Use usb_ep_fifo_status() where needed.
+        */
+       if (is_last)
+               done(ep, req, 0);
+       return is_last;
+}
+
+static inline int 
+read_packet(u8 *buf, struct omap_req *req, unsigned avail)
+{
+       unsigned        len;
+       u16             *wp;
+
+       len = min(req->req.length - req->req.actual, avail);
+       req->req.actual += len;
+       avail = len;
+
+       if (likely((((int)buf) & 1) == 0)) {
+               wp = (u16 *)buf;
+               while (avail >= 2) {
+                       *wp++ = UDC_DATA_REG;
+                       avail -= 2;
+               }
+               buf = (u8 *)wp;
+       }
+       while (avail--)
+               *buf++ = *(volatile u8 *)&UDC_DATA_REG;
+       return len;
+}
+
+// return:  0 = still running, 1 = queue empty, negative = errno
+static int read_fifo(struct omap_ep *ep, struct omap_req *req)
+{
+       u8              *buf;
+       unsigned        count, avail;
+       int             is_last;
+
+       buf = req->req.buf + req->req.actual;
+       prefetchw(buf);
+
+       for (;;) {
+               u16     ep_stat = UDC_STAT_FLG_REG;
+
+               is_last = 0;
+               if (ep_stat & FIFO_UNREADABLE)
+                       break;
+
+               if (ep_stat & (UDC_NON_ISO_FIFO_FULL|UDC_ISO_FIFO_FULL))
+                       avail = ep->ep.maxpacket;
+               else 
+                       avail = UDC_RXFSTAT_REG;
+               count = read_packet(buf, req, avail);
+
+               // FIXME double buffered PIO OUT wasn't behaving...
+
+               /* partial packet reads may not be errors */
+               if (count < ep->ep.maxpacket) {
+                       is_last = 1;
+                       /* overflowed this request?  flush extra data */
+                       if (count != avail) {
+                               req->req.status = -EOVERFLOW;
+                               avail -= count;
+                               while (avail--)
+                                       (void) *(volatile u8 *)&UDC_DATA_REG;
+                       }
+               } else if (req->req.length == req->req.actual)
+                       is_last = 1;
+               else
+                       is_last = 0;
+
+               if (!ep->bEndpointAddress)
+                       break;
+               if (!ep->double_buf) {
+                       UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                       if (!is_last)
+                               break;
+               }
+
+               if (is_last) {
+                       done(ep, req, 0);
+                       if (list_empty(&ep->queue) || !ep->double_buf)
+                               break;
+                       req = container_of(ep->queue.next,
+                                       struct omap_req, queue);
+                       is_last = 0;
+               }
+       }
+       return is_last;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Each USB transfer request using DMA maps to one or more DMA transfers.
+ * When DMA completion isn't request completion, the UDC continues with
+ * the next DMA transfer for that USB transfer.
+ */
+
+static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
+{
+       u16             txdma_ctrl;
+       unsigned        length = req->req.length - req->req.actual;
+
+       /* measure length in either bytes or packets */
+       if (length <= (UDC_TXN_TSC + 1)) {
+               txdma_ctrl = UDC_TXN_EOT | length;
+               omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
+                               length, 1, OMAP_DMA_SYNC_ELEMENT);
+       } else {
+               length = max(length / ep->maxpacket,
+                               (unsigned) UDC_TXN_TSC + 1);
+               txdma_ctrl = length;
+               omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
+                               ep->ep.maxpacket, length,
+                               OMAP_DMA_SYNC_ELEMENT);
+               length *= ep->maxpacket;
+       }
+
+       omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
+               OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+
+       omap_start_dma(ep->lch);
+       UDC_DMA_IRQ_EN_REG |= UDC_TX_DONE_IE(ep->dma_channel);
+       UDC_TXDMA_REG(ep->dma_channel) = UDC_TXN_START | txdma_ctrl;
+       req->dma_bytes = length;
+}
+
+static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status)
+{
+       if (status == 0) {
+               req->req.actual += req->dma_bytes;
+
+               /* return if this request needs to send data or zlp */
+               if (req->req.actual < req->req.length)
+                       return;
+               if (req->req.zero
+                               && req->dma_bytes != 0
+                               && (req->req.actual % ep->maxpacket) == 0)
+                       return;
+       } else {
+               u32     last;
+
+               // FIXME this surely isn't #bytes transferred
+               last = (omap_readw(OMAP_DMA_CSSA_U(ep->lch)) << 16)
+                               | omap_readw(OMAP_DMA_CSSA_L(ep->lch));
+               req->req.actual = last - req->req.dma;
+       }
+
+       /* tx completion */
+       omap_stop_dma(ep->lch);
+       UDC_DMA_IRQ_EN_REG &= ~UDC_TX_DONE_IE(ep->dma_channel);
+       done(ep, req, status);
+}
+
+static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
+{
+       unsigned packets;
+
+       /* NOTE:  we filtered out "short reads" before, so we know
+        * the buffer has only whole numbers of packets.
+        */
+
+       /* set up this DMA transfer, enable the fifo, start */
+       packets = (req->req.length - req->req.actual) / ep->ep.maxpacket;
+       packets = min(packets, (unsigned)UDC_RXN_TC + 1);
+       req->dma_bytes = packets * ep->ep.maxpacket;
+       omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
+                       ep->ep.maxpacket, packets,
+                       OMAP_DMA_SYNC_ELEMENT);
+       omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
+               OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+
+       UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1);
+       UDC_DMA_IRQ_EN_REG |= UDC_RX_EOT_IE(ep->dma_channel);
+       UDC_EP_NUM_REG = (ep->bEndpointAddress & 0xf);
+       UDC_CTRL_REG = UDC_SET_FIFO_EN;
+
+       omap_start_dma(ep->lch);
+}
+
+static void
+finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status)
+{
+       u16     count;
+
+       /* FIXME must be a better way to see how much dma
+        * happened, even when it never got going...
+        */
+       count = omap_readw(OMAP_DMA_CDAC(ep->lch));
+       count -= 0xffff & (req->req.dma + req->req.actual);
+       count += req->req.actual;
+       if (count <= req->req.length)
+               req->req.actual = count;
+       
+       if (count != req->dma_bytes || status)
+               omap_stop_dma(ep->lch);
+
+       /* if this wasn't short, request may need another transfer */
+       else if (req->req.actual < req->req.length)
+               return;
+
+       /* rx completion */
+       UDC_DMA_IRQ_EN_REG &= ~UDC_RX_EOT_IE(ep->dma_channel);
+       done(ep, req, status);
+}
+
+static void dma_irq(struct omap_udc *udc, u16 irq_src)
+{
+       u16             dman_stat = UDC_DMAN_STAT_REG;
+       struct omap_ep  *ep;
+       struct omap_req *req;
+
+       /* IN dma: tx to host */
+       if (irq_src & UDC_TXN_DONE) {
+               ep = &udc->ep[16 + UDC_DMA_TX_SRC(dman_stat)];
+               ep->irqs++;
+               /* can see TXN_DONE after dma abort */
+               if (!list_empty(&ep->queue)) {
+                       req = container_of(ep->queue.next,
+                                               struct omap_req, queue);
+                       finish_in_dma(ep, req, 0);
+               }
+               UDC_IRQ_SRC_REG = UDC_TXN_DONE;
+
+               if (!list_empty (&ep->queue)) {
+                       req = container_of(ep->queue.next,
+                                       struct omap_req, queue);
+                       next_in_dma(ep, req);
+               }
+       }
+
+       /* OUT dma: rx from host */
+       if (irq_src & UDC_RXN_EOT) {
+               ep = &udc->ep[UDC_DMA_RX_SRC(dman_stat)];
+               ep->irqs++;
+               /* can see RXN_EOT after dma abort */
+               if (!list_empty(&ep->queue)) {
+                       req = container_of(ep->queue.next,
+                                       struct omap_req, queue);
+                       finish_out_dma(ep, req, 0);
+               }
+               UDC_IRQ_SRC_REG = UDC_RXN_EOT;
+
+               if (!list_empty (&ep->queue)) {
+                       req = container_of(ep->queue.next,
+                                       struct omap_req, queue);
+                       next_out_dma(ep, req);
+               }
+       }
+
+       if (irq_src & UDC_RXN_CNT) {
+               ep = &udc->ep[UDC_DMA_RX_SRC(dman_stat)];
+               DBG("%s, RX_CNT irq?\n", ep->ep.name);
+               UDC_IRQ_SRC_REG = UDC_RXN_CNT;
+       }
+}
+
+static void dma_error(int lch, u16 ch_status, void *data)
+{
+       struct omap_ep  *ep = data;
+
+       /* if ch_status & OMAP_DMA_DROP_IRQ ... */
+       /* if ch_status & OMAP_DMA_TOUT_IRQ ... */
+       ERR("%s dma error, lch %d status %02x\n", ep->ep.name, lch, ch_status);
+
+       /* complete current transfer ... */
+}
+
+static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
+{
+       u16     reg;
+       int     status, restart, is_in;
+
+       is_in = ep->bEndpointAddress & USB_DIR_IN;
+       if (is_in)
+               reg = UDC_TXDMA_CFG_REG;
+       else
+               reg = UDC_RXDMA_CFG_REG;
+       reg |= 1 << 12;         /* "pulse" activated */
+
+       ep->dma_channel = 0;
+       ep->lch = -1;
+       if (channel == 0 || channel > 3) {
+               if ((reg & 0x0f00) == 0)
+                       channel = 3;
+               else if ((reg & 0x00f0) == 0)
+                       channel = 2;
+               else if ((reg & 0x000f) == 0)   /* preferred for ISO */
+                       channel = 1;
+               else {
+                       status = -EMLINK;
+                       goto just_restart;
+               }
+       }
+       reg |= (0x0f & ep->bEndpointAddress) << (4 * (channel - 1));
+       ep->dma_channel = channel;
+
+       if (is_in) {
+               status = omap_request_dma(OMAP_DMA_USB_W2FC_TX0 - 1 + channel,
+                       ep->ep.name, dma_error, ep, &ep->lch);
+               if (status == 0) {
+                       UDC_TXDMA_CFG_REG = reg;
+                       omap_set_dma_dest_params(ep->lch,
+                               OMAP_DMA_PORT_TIPB,
+                               OMAP_DMA_AMODE_CONSTANT,
+                               (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
+               }
+       } else {
+               status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel,
+                       ep->ep.name, dma_error, ep, &ep->lch);
+               if (status == 0) {
+                       UDC_RXDMA_CFG_REG = reg;
+                       omap_set_dma_src_params(ep->lch,
+                               OMAP_DMA_PORT_TIPB,
+                               OMAP_DMA_AMODE_CONSTANT,
+                               (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
+               }
+       }
+       if (status)
+               ep->dma_channel = 0;
+       else {
+               ep->has_dma = 1;
+               omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
+
+               /* channel type P: hw synch (fifo) */
+               omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch));
+       }
+
+just_restart:
+       /* restart any queue, even if the claim failed  */
+       restart = !ep->stopped && !list_empty(&ep->queue);
+
+       if (status)
+               DBG("%s no dma channel: %d%s\n", ep->ep.name, status,
+                       restart ? " (restart)" : "");
+       else
+               DBG("%s claimed %cxdma%d lch %d%s\n", ep->ep.name,
+                       is_in ? 't' : 'r',
+                       ep->dma_channel - 1, ep->lch,
+                       restart ? " (restart)" : "");
+
+       if (restart) {
+               struct omap_req *req;
+               req = container_of(ep->queue.next, struct omap_req, queue);
+               if (ep->has_dma)
+                       (is_in ? next_in_dma : next_out_dma)(ep, req);
+               else {
+                       use_ep(ep, UDC_EP_SEL);
+                       (is_in ? write_fifo : read_fifo)(ep, req);
+                       deselect_ep();
+                       /* IN: 6 wait states before it'll tx */
+               }
+       }
+}
+
+static void dma_channel_release(struct omap_ep *ep)
+{
+       int             shift = 4 * (ep->dma_channel - 1);
+       u16             mask = 0x0f << shift;
+       struct omap_req *req;
+       int             active;
+
+       /* abort any active usb transfer request */
+       if (!list_empty(&ep->queue))
+               req = container_of(ep->queue.next, struct omap_req, queue);
+       else
+               req = 0;
+
+       active = ((1 << 7) & omap_readl(OMAP_DMA_CCR(ep->lch))) != 0;
+
+       DBG("%s release %s %cxdma%d %p\n", ep->ep.name,
+                       active ? "active" : "idle",
+                       (ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r',
+                       ep->dma_channel - 1, req);
+
+       /* wait till current packet DMA finishes, and fifo empties */
+       if (ep->bEndpointAddress & USB_DIR_IN) {
+               UDC_TXDMA_CFG_REG &= ~mask;
+
+               if (req) {
+                       if (active)
+                               udelay(50);
+                       finish_in_dma(ep, req, -ECONNRESET);
+                       if (UDC_TXDMA_CFG_REG & mask)
+                               WARN("%s, SPIN abort TX dma\n", ep->ep.name);
+               }
+
+               /* host may empty the fifo (or not...) */
+               while (UDC_TXDMA_CFG_REG & mask)
+                       udelay(10);
+
+       } else {
+               UDC_RXDMA_CFG_REG &= ~mask;
+
+               /* dma empties the fifo */
+               while (active && (UDC_RXDMA_CFG_REG & mask))
+                       udelay(10);
+               omap_stop_dma(ep->lch);
+               if (req)
+                       finish_out_dma(ep, req, -ECONNRESET);
+       }
+       omap_free_dma(ep->lch);
+       ep->dma_channel = 0;
+       ep->lch = -1;
+       /* has_dma still set, till endpoint is fully quiesced */
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static int
+omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
+{
+       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
+       struct omap_req *req = container_of(_req, struct omap_req, req);
+       struct omap_udc *udc;
+       unsigned long   flags;
+       int             is_iso = 0;
+
+       /* catch various bogus parameters */
+       if (!_req || !req->req.complete || !req->req.buf
+                       || !list_empty(&req->queue)) {
+               DBG("%s, bad params\n", __FUNCTION__);
+               return -EINVAL;
+       }
+       if (!_ep || (!ep->desc && ep->bEndpointAddress)) {
+               DBG("%s, bad ep\n", __FUNCTION__);
+               return -EINVAL;
+       }
+       if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+               if (req->req.length > ep->ep.maxpacket)
+                       return -EMSGSIZE;
+               is_iso = 1;
+       }
+
+       /* this isn't bogus, but OMAP DMA isn't the only hardware to
+        * have a hard time with partial packet reads...  reject it.
+        */
+       if (use_dma
+                       && ep->has_dma
+                       && ep->bEndpointAddress != 0
+                       && (ep->bEndpointAddress & USB_DIR_IN) == 0
+                       && (req->req.length % ep->ep.maxpacket) != 0) {
+               DBG("%s, no partial packet OUT reads\n", __FUNCTION__);
+               return -EMSGSIZE;
+       }
+
+       udc = ep->udc;
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       if (use_dma && ep->has_dma) {
+               if (req->req.dma == DMA_ADDR_INVALID) {
+                       req->req.dma = dma_map_single(
+                               ep->udc->gadget.dev.parent,
+                               req->req.buf,
+                               req->req.length,
+                               (ep->bEndpointAddress & USB_DIR_IN)
+                                       ? DMA_TO_DEVICE
+                                       : DMA_FROM_DEVICE);
+                       req->mapped = 1;
+               } else {
+                       dma_sync_single_for_device(
+                               ep->udc->gadget.dev.parent,
+                               req->req.dma, req->req.length,
+                               (ep->bEndpointAddress & USB_DIR_IN)
+                                       ? DMA_TO_DEVICE
+                                       : DMA_FROM_DEVICE);
+                       req->mapped = 0;
+               }
+       }
+
+       VDBG("%s queue req %p, len %d buf %p\n",
+               ep->ep.name, _req, _req->length, _req->buf);
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+
+       /* maybe kickstart non-iso i/o queues */
+       if (is_iso)
+               UDC_IRQ_EN_REG |= UDC_SOF_IE;
+       else if (list_empty(&ep->queue) && !ep->stopped && !ep->ackwait) {
+               int     is_in;
+
+               if (ep->bEndpointAddress == 0) {
+                       if (!udc->ep0_pending || !list_empty (&ep->queue)) {
+                               spin_unlock_irqrestore(&udc->lock, flags);
+                               return -EL2HLT;
+                       }
+
+                       /* empty DATA stage? */
+                       is_in = udc->ep0_in;
+                       if (!req->req.length) {
+
+                               /* chip became CONFIGURED or ADDRESSED
+                                * earlier; drivers may already have queued
+                                * requests to non-control endpoints
+                                */
+                               if (udc->ep0_set_config) {
+                                       u16     irq_en = UDC_IRQ_EN_REG;
+
+                                       irq_en |= UDC_DS_CHG_IE | UDC_EP0_IE;
+                                       if (!udc->ep0_reset_config)
+                                               irq_en |= UDC_EPN_RX_IE
+                                                       | UDC_EPN_TX_IE;
+                                       UDC_IRQ_EN_REG = irq_en;
+                               }
+
+                               /* STATUS is reverse direction */
+                               UDC_EP_NUM_REG = is_in
+                                               ? UDC_EP_SEL
+                                               : (UDC_EP_SEL|UDC_EP_DIR);
+                               UDC_CTRL_REG = UDC_CLR_EP;
+                               UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                               UDC_EP_NUM_REG = udc->ep0_in ? 0 : UDC_EP_DIR;
+
+                               /* cleanup */
+                               udc->ep0_pending = 0;
+                               done(ep, req, 0);
+                               req = 0;
+
+                       /* non-empty DATA stage */
+                       } else if (is_in) {
+                               UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
+                       } else {
+                               if (udc->ep0_setup)
+                                       goto irq_wait;
+                               UDC_EP_NUM_REG = UDC_EP_SEL;
+                       }
+               } else {
+                       is_in = ep->bEndpointAddress & USB_DIR_IN;
+                       if (!ep->has_dma)
+                               use_ep(ep, UDC_EP_SEL);
+                       /* if ISO: SOF IRQs must be enabled/disabled! */
+               }
+
+               if (ep->has_dma)
+                       (is_in ? next_in_dma : next_out_dma)(ep, req);
+               else if (req) {
+                       if ((is_in ? write_fifo : read_fifo)(ep, req) == 1)
+                               req = 0;
+                       deselect_ep();
+                       /* IN: 6 wait states before it'll tx */
+               }
+       }
+
+irq_wait:
+       /* irq handler advances the queue */
+       if (req != 0)
+               list_add_tail(&req->queue, &ep->queue);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
+       struct omap_req *req;
+       unsigned long   flags;
+
+       if (!_ep || !_req)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry (req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               spin_unlock_irqrestore(&ep->udc->lock, flags);
+               return -EINVAL;
+       }
+
+       if (use_dma && ep->dma_channel && ep->queue.next == &req->queue) {
+               int channel = ep->dma_channel;
+
+               /* releasing the dma completion cancels the request,
+                * reclaiming the channel restarts the queue
+                */
+               dma_channel_release(ep);
+               dma_channel_claim(ep, channel);
+       } else 
+               done(ep, req, -ECONNRESET);
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int omap_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
+       unsigned long   flags;
+       int             status = -EOPNOTSUPP;
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+
+       /* just use protocol stalls for ep0; real halts are annoying */
+       if (ep->bEndpointAddress == 0) {
+               if (!ep->udc->ep0_pending)
+                       status = -EINVAL;
+               else if (value) {
+                       if (ep->udc->ep0_set_config) {
+                               WARN("error changing config?\n");
+                               UDC_SYSCON2_REG = UDC_CLR_CFG;
+                       }
+                       UDC_SYSCON2_REG = UDC_STALL_CMD;
+                       ep->udc->ep0_pending = 0;
+                       status = 0;
+               } else /* NOP */
+                       status = 0;
+
+       /* otherwise, all active non-ISO endpoints can halt */
+       } else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->desc) {
+
+               /* IN endpoints must already be idle */
+               if ((ep->bEndpointAddress & USB_DIR_IN)
+                               && !list_empty(&ep->queue)) { 
+                       status = -EAGAIN;
+                       goto done;
+               }
+
+               if (value) {
+                       int     channel;
+
+                       if (use_dma && ep->dma_channel
+                                       && !list_empty(&ep->queue)) {
+                               channel = ep->dma_channel;
+                               dma_channel_release(ep);
+                       } else
+                               channel = 0;
+
+                       use_ep(ep, UDC_EP_SEL);
+                       if (UDC_STAT_FLG_REG & UDC_NON_ISO_FIFO_EMPTY) {
+                               UDC_CTRL_REG = UDC_SET_HALT;
+                               status = 0;
+                       } else
+                               status = -EAGAIN;
+                       deselect_ep();
+
+                       if (channel)
+                               dma_channel_claim(ep, channel);
+               } else {
+                       use_ep(ep, 0);
+                       UDC_CTRL_REG = UDC_RESET_EP;
+                       ep->ackwait = 0;
+                       if (!(ep->bEndpointAddress & USB_DIR_IN))
+                               UDC_CTRL_REG = UDC_SET_FIFO_EN;
+               }
+       }
+done:
+       VDBG("%s %s halt stat %d\n", ep->ep.name,
+               value ? "set" : "clear", status);
+
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+       return status;
+}
+
+static struct usb_ep_ops omap_ep_ops = {
+       .enable         = omap_ep_enable,
+       .disable        = omap_ep_disable,
+
+       .alloc_request  = omap_alloc_request,
+       .free_request   = omap_free_request,
+
+       .alloc_buffer   = omap_alloc_buffer,
+       .free_buffer    = omap_free_buffer,
+
+       .queue          = omap_ep_queue,
+       .dequeue        = omap_ep_dequeue,
+
+       .set_halt       = omap_ep_set_halt,
+       // fifo_status ... report bytes in fifo
+       // fifo_flush ... flush fifo
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int omap_get_frame(struct usb_gadget *gadget)
+{
+       u16     sof = UDC_SOF_REG;
+       return (sof & UDC_TS_OK) ? (sof & UDC_TS) : -EL2NSYNC;
+}
+
+static int omap_wakeup(struct usb_gadget *gadget)
+{
+       struct omap_udc *udc;
+       unsigned long   flags;
+       int             retval = -EHOSTUNREACH;
+
+       udc = container_of(gadget, struct omap_udc, gadget);
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (udc->devstat & UDC_SUS) {
+               /* NOTE:  OTG spec erratum says that OTG devices may
+                * issue wakeups without host enable.
+                */
+               if (udc->devstat & (UDC_B_HNP_ENABLE|UDC_R_WK_OK)) {
+                       DBG("remote wakeup...\n");
+                       UDC_SYSCON2_REG = UDC_RMT_WKP;
+                       retval = 0;
+               }
+
+       /* NOTE:  non-OTG systems may use SRP TOO... */
+       } else if (!(udc->devstat & UDC_ATT)) {
+               if (udc->transceiver)
+                       retval = otg_start_srp(udc->transceiver);
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return retval;
+}
+
+static int
+omap_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
+{
+       struct omap_udc *udc;
+       unsigned long   flags;
+       u16             syscon1;
+
+       udc = container_of(gadget, struct omap_udc, gadget);
+       spin_lock_irqsave(&udc->lock, flags);
+       syscon1 = UDC_SYSCON1_REG;
+       if (is_selfpowered)
+               syscon1 |= UDC_SELF_PWR;
+       else
+               syscon1 &= ~UDC_SELF_PWR;
+       UDC_SYSCON1_REG = syscon1;
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static int can_pullup(struct omap_udc *udc)
+{
+       return udc->driver && udc->softconnect && udc->vbus_active;
+}
+
+static void pullup_enable(struct omap_udc *udc)
+{
+       UDC_SYSCON1_REG |= UDC_PULLUP_EN;
+#ifndef CONFIG_USB_OTG
+       OTG_CTRL_REG |= OTG_BSESSVLD;
+#endif
+       UDC_IRQ_EN_REG = UDC_DS_CHG_IE;
+}
+
+static void pullup_disable(struct omap_udc *udc)
+{
+#ifndef CONFIG_USB_OTG
+       OTG_CTRL_REG &= ~OTG_BSESSVLD;
+#endif
+       UDC_IRQ_EN_REG = UDC_DS_CHG_IE;
+       UDC_SYSCON1_REG &= ~UDC_PULLUP_EN;
+}
+
+/*
+ * Called by whatever detects VBUS sessions:  external transceiver
+ * driver, or maybe GPIO0 VBUS IRQ.
+ */
+static int omap_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       struct omap_udc *udc;
+       unsigned long   flags;
+
+       udc = container_of(gadget, struct omap_udc, gadget);
+       spin_lock_irqsave(&udc->lock, flags);
+       VDBG("VBUS %s\n", is_active ? "on" : "off");
+       udc->vbus_active = (is_active != 0);
+       if (can_pullup(udc))
+               pullup_enable(udc);
+       else
+               pullup_disable(udc);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int omap_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+       struct omap_udc *udc;
+
+       udc = container_of(gadget, struct omap_udc, gadget);
+       if (udc->transceiver)
+               return otg_set_power(udc->transceiver, mA);
+       return -EOPNOTSUPP;
+}
+
+static int omap_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct omap_udc *udc;
+       unsigned long   flags;
+
+       udc = container_of(gadget, struct omap_udc, gadget);
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->softconnect = (is_on != 0);
+       if (can_pullup(udc))
+               pullup_enable(udc);
+       else
+               pullup_disable(udc);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static struct usb_gadget_ops omap_gadget_ops = {
+       .get_frame              = omap_get_frame,
+       .wakeup                 = omap_wakeup,
+       .set_selfpowered        = omap_set_selfpowered,
+       .vbus_session           = omap_vbus_session,
+       .vbus_draw              = omap_vbus_draw,
+       .pullup                 = omap_pullup,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* dequeue ALL requests; caller holds udc->lock */
+static void nuke(struct omap_ep *ep, int status)
+{
+       struct omap_req *req;
+
+       ep->stopped = 1;
+
+       if (use_dma && ep->dma_channel)
+               dma_channel_release(ep);
+
+       use_ep(ep, 0);
+       UDC_CTRL_REG = UDC_CLR_EP;
+       if (ep->bEndpointAddress && ep->bmAttributes != USB_ENDPOINT_XFER_ISOC)
+               UDC_CTRL_REG = UDC_SET_HALT;
+
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct omap_req, queue);
+               done(ep, req, status);
+       }
+}
+
+/* caller holds udc->lock */
+static void udc_quiesce(struct omap_udc *udc)
+{
+       struct omap_ep  *ep;
+
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       nuke(&udc->ep[0], -ESHUTDOWN);
+       list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list)
+               nuke(ep, -ESHUTDOWN);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void update_otg(struct omap_udc *udc)
+{
+       u16     devstat;
+
+       if (!udc->gadget.is_otg)
+               return;
+
+       if (OTG_CTRL_REG & OTG_ID)
+               devstat = UDC_DEVSTAT_REG;
+       else
+               devstat = 0;
+
+       udc->gadget.b_hnp_enable = !!(devstat & UDC_B_HNP_ENABLE);
+       udc->gadget.a_hnp_support = !!(devstat & UDC_A_HNP_SUPPORT);
+       udc->gadget.a_alt_hnp_support = !!(devstat & UDC_A_ALT_HNP_SUPPORT);
+
+       /* Enable HNP early, avoiding races on suspend irq path.
+        * ASSUMES OTG state machine B_BUS_REQ input is true.
+        */
+       if (udc->gadget.b_hnp_enable)
+               OTG_CTRL_REG = (OTG_CTRL_REG | OTG_B_HNPEN | OTG_B_BUSREQ)
+                               & ~OTG_PULLUP;
+}
+
+static void ep0_irq(struct omap_udc *udc, u16 irq_src)
+{
+       struct omap_ep  *ep0 = &udc->ep[0];
+       struct omap_req *req = 0;
+
+       ep0->irqs++;
+
+       /* Clear any pending requests and then scrub any rx/tx state
+        * before starting to handle the SETUP request.
+        */
+       if (irq_src & UDC_SETUP)
+               nuke(ep0, 0);
+
+       /* IN/OUT packets mean we're in the DATA or STATUS stage.  
+        * This driver uses only uses protocol stalls (ep0 never halts),
+        * and if we got this far the gadget driver already had a
+        * chance to stall.  Tries to be forgiving of host oddities.
+        *
+        * NOTE:  the last chance gadget drivers have to stall control
+        * requests is during their request completion callback.
+        */
+       if (!list_empty(&ep0->queue))
+               req = container_of(ep0->queue.next, struct omap_req, queue);
+
+       /* IN == TX to host */
+       if (irq_src & UDC_EP0_TX) {
+               int     stat;
+
+               UDC_IRQ_SRC_REG = UDC_EP0_TX;
+               UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
+               stat = UDC_STAT_FLG_REG;
+               if (stat & UDC_ACK) {
+                       if (udc->ep0_in) {
+                               /* write next IN packet from response,
+                                * or set up the status stage.
+                                */
+                               if (req)
+                                       stat = write_fifo(ep0, req);
+                               UDC_EP_NUM_REG = UDC_EP_DIR;
+                               if (!req && udc->ep0_pending) {
+                                       UDC_EP_NUM_REG = UDC_EP_SEL;
+                                       UDC_CTRL_REG = UDC_CLR_EP;
+                                       UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                                       UDC_EP_NUM_REG = 0;
+                                       udc->ep0_pending = 0;
+                               } /* else:  6 wait states before it'll tx */
+                       } else {
+                               /* ack status stage of OUT transfer */
+                               UDC_EP_NUM_REG = UDC_EP_DIR;
+                               if (req)
+                                       done(ep0, req, 0);
+                       }
+                       req = 0;
+               } else if (stat & UDC_STALL) {
+                       UDC_CTRL_REG = UDC_CLR_HALT;
+                       UDC_EP_NUM_REG = UDC_EP_DIR;
+               } else {
+                       UDC_EP_NUM_REG = UDC_EP_DIR;
+               }
+       }
+
+       /* OUT == RX from host */
+       if (irq_src & UDC_EP0_RX) {
+               int     stat;
+
+               UDC_IRQ_SRC_REG = UDC_EP0_RX;
+               UDC_EP_NUM_REG = UDC_EP_SEL;
+               stat = UDC_STAT_FLG_REG;
+               if (stat & UDC_ACK) {
+                       if (!udc->ep0_in) {
+                               stat = 0;
+                               /* read next OUT packet of request, maybe
+                                * reactiviting the fifo; stall on errors.
+                                */
+                               if (!req || (stat = read_fifo(ep0, req)) < 0) {
+                                       UDC_SYSCON2_REG = UDC_STALL_CMD;
+                                       udc->ep0_pending = 0;
+                                       stat = 0;
+                               } else if (stat == 0)
+                                       UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                               UDC_EP_NUM_REG = 0;
+                               
+                               /* activate status stage */
+                               if (stat == 1) {
+                                       done(ep0, req, 0);
+                                       /* that may have STALLed ep0... */
+                                       UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
+                                       UDC_CTRL_REG = UDC_CLR_EP;
+                                       UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                                       UDC_EP_NUM_REG = UDC_EP_DIR;
+                                       udc->ep0_pending = 0;
+                               }
+                       } else {
+                               /* ack status stage of IN transfer */
+                               UDC_EP_NUM_REG = 0;
+                               if (req)
+                                       done(ep0, req, 0);
+                       }
+               } else if (stat & UDC_STALL) {
+                       UDC_CTRL_REG = UDC_CLR_HALT;
+                       UDC_EP_NUM_REG = 0;
+               } else {
+                       UDC_EP_NUM_REG = 0;
+               }
+       }
+
+       /* SETUP starts all control transfers */
+       if (irq_src & UDC_SETUP) {
+               union u {
+                       u16                     word[4];
+                       struct usb_ctrlrequest  r;
+               } u;
+               int                     status = -EINVAL;
+               struct omap_ep          *ep;
+
+               /* read the (latest) SETUP message */
+               do {
+                       UDC_EP_NUM_REG = UDC_SETUP_SEL;
+                       /* two bytes at a time */
+                       u.word[0] = UDC_DATA_REG;
+                       u.word[1] = UDC_DATA_REG;
+                       u.word[2] = UDC_DATA_REG;
+                       u.word[3] = UDC_DATA_REG;
+                       UDC_EP_NUM_REG = 0;
+               } while (UDC_IRQ_SRC_REG & UDC_SETUP);
+               le16_to_cpus (&u.r.wValue);
+               le16_to_cpus (&u.r.wIndex);
+               le16_to_cpus (&u.r.wLength);
+
+               /* Delegate almost all control requests to the gadget driver,
+                * except for a handful of ch9 status/feature requests that
+                * hardware doesn't autodecode _and_ the gadget API hides.
+                */
+               udc->ep0_in = (u.r.bRequestType & USB_DIR_IN) != 0;
+               udc->ep0_set_config = 0;
+               udc->ep0_pending = 1;
+               ep0->stopped = 0;
+               ep0->ackwait = 0;
+               switch (u.r.bRequest) {
+               case USB_REQ_SET_CONFIGURATION:
+                       /* udc needs to know when ep != 0 is valid */
+                       if (u.r.bRequestType != USB_RECIP_DEVICE)
+                               goto delegate;
+                       if (u.r.wLength != 0)
+                               goto do_stall;
+                       udc->ep0_set_config = 1;
+                       udc->ep0_reset_config = (u.r.wValue == 0);
+                       VDBG("set config %d\n", u.r.wValue);
+
+                       /* update udc NOW since gadget driver may start
+                        * queueing requests immediately; clear config
+                        * later if it fails the request.
+                        */
+                       if (udc->ep0_reset_config)
+                               UDC_SYSCON2_REG = UDC_CLR_CFG;
+                       else
+                               UDC_SYSCON2_REG = UDC_DEV_CFG;
+                       update_otg(udc);
+                       goto delegate;
+               case USB_REQ_CLEAR_FEATURE:
+                       /* clear endpoint halt */
+                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+                               goto delegate;
+                       if (u.r.wValue != USB_ENDPOINT_HALT
+                                       || u.r.wLength != 0)
+                               goto do_stall;
+                       ep = &udc->ep[u.r.wIndex & 0xf];
+                       if (ep != ep0) {
+                               if (u.r.wIndex & USB_DIR_IN)
+                                       ep += 16;
+                               if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+                                               || !ep->desc)
+                                       goto do_stall;
+                               use_ep(ep, 0);
+                               UDC_CTRL_REG = UDC_RESET_EP;
+                               ep->ackwait = 0;
+                               if (!(ep->bEndpointAddress & USB_DIR_IN))
+                                       UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                       }
+                       VDBG("%s halt cleared by host\n", ep->name);
+                       goto ep0out_status_stage;
+               case USB_REQ_SET_FEATURE:
+                       /* set endpoint halt */
+                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+                               goto delegate;
+                       if (u.r.wValue != USB_ENDPOINT_HALT
+                                       || u.r.wLength != 0)
+                               goto do_stall;
+                       ep = &udc->ep[u.r.wIndex & 0xf];
+                       if (u.r.wIndex & USB_DIR_IN)
+                               ep += 16;
+                       if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+                                       || ep == ep0 || !ep->desc)
+                               goto do_stall;
+                       if (use_dma && ep->has_dma) {
+                               /* this has rude side-effects (aborts) and
+                                * can't really work if DMA-IN is active
+                                */
+                               DBG("%s host set_halt, NYET \n", ep->name);
+                               goto do_stall;
+                       }
+                       use_ep(ep, 0);
+                       /* can't halt if fifo isn't empty... */
+                       UDC_CTRL_REG = UDC_CLR_EP;
+                       UDC_CTRL_REG = UDC_SET_HALT;
+                       VDBG("%s halted by host\n", ep->name);
+ep0out_status_stage:
+                       status = 0;
+                       UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
+                       UDC_CTRL_REG = UDC_CLR_EP;
+                       UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                       UDC_EP_NUM_REG = UDC_EP_DIR;
+                       udc->ep0_pending = 0;
+                       break;
+               case USB_REQ_GET_STATUS:
+                       /* return interface status.  if we were pedantic,
+                        * we'd detect non-existent interfaces, and stall.
+                        */
+                       if (u.r.bRequestType
+                                       != (USB_DIR_IN|USB_RECIP_INTERFACE))
+                               goto delegate;
+                       /* return two zero bytes */
+                       UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
+                       UDC_DATA_REG = 0;
+                       UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                       UDC_EP_NUM_REG = UDC_EP_DIR;
+                       status = 0;
+                       VDBG("GET_STATUS, interface %d\n", u.r.wIndex);
+                       /* next, status stage */
+                       break;
+               default:
+delegate:
+                       /* activate the ep0out fifo right away */
+                       if (!udc->ep0_in && u.r.wLength) {
+                               UDC_EP_NUM_REG = 0;
+                               UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                       }
+
+                       /* gadget drivers see class/vendor specific requests,
+                        * {SET,GET}_{INTERFACE,DESCRIPTOR,CONFIGURATION},
+                        * and more
+                        */
+                       VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n",
+                               u.r.bRequestType, u.r.bRequest,
+                               u.r.wValue, u.r.wIndex, u.r.wLength);
+
+                       /* The gadget driver may return an error here,
+                        * causing an immediate protocol stall.
+                        *
+                        * Else it must issue a response, either queueing a
+                        * response buffer for the DATA stage, or halting ep0
+                        * (causing a protocol stall, not a real halt).  A
+                        * zero length buffer means no DATA stage.
+                        *
+                        * It's fine to issue that response after the setup()
+                        * call returns, and this IRQ was handled.
+                        */
+                       udc->ep0_setup = 1;
+                       spin_unlock(&udc->lock);
+                       status = udc->driver->setup (&udc->gadget, &u.r);
+                       spin_lock(&udc->lock);
+                       udc->ep0_setup = 0;
+               }
+
+               if (status < 0) {
+do_stall:
+                       VDBG("req %02x.%02x protocol STALL; stat %d\n",
+                                       u.r.bRequestType, u.r.bRequest, status);
+                       if (udc->ep0_set_config) {
+                               if (udc->ep0_reset_config)
+                                       WARN("error resetting config?\n");
+                               else
+                                       UDC_SYSCON2_REG = UDC_CLR_CFG;
+                       }
+                       UDC_SYSCON2_REG = UDC_STALL_CMD;
+                       udc->ep0_pending = 0;
+               }
+       }
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define OTG_FLAGS (UDC_B_HNP_ENABLE|UDC_A_HNP_SUPPORT|UDC_A_ALT_HNP_SUPPORT)
+
+static void devstate_irq(struct omap_udc *udc, u16 irq_src)
+{
+       u16     devstat, change;
+
+       devstat = UDC_DEVSTAT_REG;
+       change = devstat ^ udc->devstat;
+       udc->devstat = devstat;
+
+       if (change & (UDC_USB_RESET|UDC_ATT)) {
+               udc_quiesce(udc);
+
+               if (change & UDC_ATT) {
+                       /* driver for any external transceiver will
+                        * have called omap_vbus_session() already
+                        */
+                       if (devstat & UDC_ATT) {
+                               udc->gadget.speed = USB_SPEED_FULL;
+                               VDBG("connect\n");
+                               if (!udc->transceiver)
+                                       pullup_enable(udc);
+                               // if (driver->connect) call it
+                       } else if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+                               udc->gadget.speed = USB_SPEED_UNKNOWN;
+                               if (!udc->transceiver)
+                                       pullup_disable(udc);
+                               DBG("disconnect, gadget %s\n",
+                                       udc->driver->driver.name);
+                               if (udc->driver->disconnect) {
+                                       spin_unlock(&udc->lock);
+                                       udc->driver->disconnect(&udc->gadget);
+                                       spin_lock(&udc->lock);
+                               }
+                       }
+                       change &= ~UDC_ATT;
+               }
+
+               if (change & UDC_USB_RESET) {
+                       if (devstat & UDC_USB_RESET) {
+                               VDBG("RESET=1\n");
+                       } else {
+                               udc->gadget.speed = USB_SPEED_FULL;
+                               INFO("USB reset done, gadget %s\n",
+                                       udc->driver->driver.name);
+                               /* ep0 traffic is legal from now on */
+                               UDC_IRQ_EN_REG = UDC_DS_CHG_IE | UDC_EP0_IE;
+                       }
+                       change &= ~UDC_USB_RESET;
+               }
+       }
+       if (change & UDC_SUS) {
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+                       // FIXME tell isp1301 to suspend/resume (?)
+                       if (devstat & UDC_SUS) {
+                               VDBG("suspend\n");
+                               update_otg(udc);
+                               /* HNP could be under way already */
+                               if (udc->gadget.speed == USB_SPEED_FULL
+                                               && udc->driver->suspend) {
+                                       spin_unlock(&udc->lock);
+                                       udc->driver->suspend(&udc->gadget);
+                                       spin_lock(&udc->lock);
+                               }
+                       } else {
+                               VDBG("resume\n");
+                               if (udc->gadget.speed == USB_SPEED_FULL
+                                               && udc->driver->resume) {
+                                       spin_unlock(&udc->lock);
+                                       udc->driver->resume(&udc->gadget);
+                                       spin_lock(&udc->lock);
+                               }
+                       }
+               }
+               change &= ~UDC_SUS;
+       }
+       if (change & OTG_FLAGS) {
+               update_otg(udc);
+               change &= ~OTG_FLAGS;
+       }
+
+       change &= ~(UDC_CFG|UDC_DEF|UDC_ADD);
+       if (change)
+               VDBG("devstat %03x, ignore change %03x\n",
+                       devstat,  change);
+
+       UDC_IRQ_SRC_REG = UDC_DS_CHG;
+}
+
+static irqreturn_t
+omap_udc_irq(int irq, void *_udc, struct pt_regs *r)
+{
+       struct omap_udc *udc = _udc;
+       u16             irq_src;
+       irqreturn_t     status = IRQ_NONE;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       irq_src = UDC_IRQ_SRC_REG;
+
+       /* Device state change (usb ch9 stuff) */
+       if (irq_src & UDC_DS_CHG) {
+               devstate_irq(_udc, irq_src);
+               status = IRQ_HANDLED;
+               irq_src &= ~UDC_DS_CHG;
+       }
+
+       /* EP0 control transfers */
+       if (irq_src & (UDC_EP0_RX|UDC_SETUP|UDC_EP0_TX)) {
+               ep0_irq(_udc, irq_src);
+               status = IRQ_HANDLED;
+               irq_src &= ~(UDC_EP0_RX|UDC_SETUP|UDC_EP0_TX);
+       }
+
+       /* DMA transfer completion */
+       if (use_dma && (irq_src & (UDC_TXN_DONE|UDC_RXN_CNT|UDC_RXN_EOT))) {
+               dma_irq(_udc, irq_src);
+               status = IRQ_HANDLED;
+               irq_src &= ~(UDC_TXN_DONE|UDC_RXN_CNT|UDC_RXN_EOT);
+       }
+
+       irq_src &= ~(UDC_SOF|UDC_EPN_TX|UDC_EPN_RX);
+       if (irq_src)
+               DBG("udc_irq, unhandled %03x\n", irq_src);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return status;
+}
+
+static irqreturn_t
+omap_udc_pio_irq(int irq, void *_dev, struct pt_regs *r)
+{
+       u16             epn_stat, irq_src;
+       irqreturn_t     status = IRQ_NONE;
+       struct omap_ep  *ep;
+       int             epnum;
+       struct omap_udc *udc = _dev;
+       struct omap_req *req;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       epn_stat = UDC_EPN_STAT_REG;
+       irq_src = UDC_IRQ_SRC_REG;
+
+       /* handle OUT first, to avoid some wasteful NAKs */
+       if (irq_src & UDC_EPN_RX) {
+               epnum = (epn_stat >> 8) & 0x0f;
+               UDC_IRQ_SRC_REG = UDC_EPN_RX;
+               status = IRQ_HANDLED;
+               ep = &udc->ep[epnum];
+               ep->irqs++;
+
+               if (!list_empty(&ep->queue)) {
+                       UDC_EP_NUM_REG = epnum | UDC_EP_SEL;
+                       if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+                               int stat;
+                               req = container_of(ep->queue.next,
+                                               struct omap_req, queue);
+                               stat = read_fifo(ep, req);
+                               // FIXME double buffered PIO OUT should work
+                       }
+                       UDC_EP_NUM_REG = epnum;
+               }
+       }
+
+       /* then IN transfers */
+       if (irq_src & UDC_EPN_TX) {
+               epnum = epn_stat & 0x0f;
+               UDC_IRQ_SRC_REG = UDC_EPN_TX;
+               status = IRQ_HANDLED;
+               ep = &udc->ep[16 + epnum];
+               ep->irqs++;
+               ep->ackwait = 0;
+
+               if (!list_empty(&ep->queue)) {
+                       UDC_EP_NUM_REG = epnum | UDC_EP_DIR | UDC_EP_SEL;
+                       if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+                               req = container_of(ep->queue.next,
+                                               struct omap_req, queue);
+                               (void) write_fifo(ep, req);
+                       }
+                       UDC_EP_NUM_REG = epnum | UDC_EP_DIR;
+                       /* 6 wait states before it'll tx */
+               }
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return status;
+}
+
+#ifdef USE_ISO
+static irqreturn_t
+omap_udc_iso_irq(int irq, void *_dev, struct pt_regs *r)
+{
+       struct omap_udc *udc = _dev;
+       struct omap_ep  *ep;
+       int             pending = 0;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* handle all non-DMA ISO transfers */
+       list_for_each_entry (ep, &udc->iso, iso) {
+               u16             stat;
+               struct omap_req *req;
+
+               if (ep->has_dma || list_empty(&ep->queue))
+                       continue;
+               req = list_entry(ep->queue.next, struct omap_req, queue);
+
+               use_ep(ep, UDC_EP_SEL);
+               stat = UDC_STAT_FLG_REG;
+
+               /* NOTE: like the other controller drivers, this isn't
+                * currently reporting lost or damaged frames.
+                */
+               if (ep->bEndpointAddress & USB_DIR_IN) {
+                       if (stat & UDC_MISS_IN)
+                               /* done(ep, req, -EPROTO) */;
+                       else
+                               write_fifo(ep, req);
+               } else {
+                       int     status = 0;
+
+                       if (stat & UDC_NO_RXPACKET)
+                               status = -EREMOTEIO;
+                       else if (stat & UDC_ISO_ERR)
+                               status = -EILSEQ;
+                       else if (stat & UDC_DATA_FLUSH)
+                               status = -ENOSR;
+
+                       if (status)
+                               /* done(ep, req, status) */;
+                       else
+                               read_fifo(ep, req);
+               }
+               deselect_ep();
+               /* 6 wait states before next EP */
+
+               ep->irqs++;
+               if (!list_empty(&ep->queue))
+                       pending = 1;
+       }
+       if (!pending)
+               UDC_IRQ_EN_REG &= ~UDC_SOF_IE;
+       UDC_IRQ_SRC_REG = UDC_SOF;
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return IRQ_HANDLED;
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static struct omap_udc *udc;
+
+int usb_gadget_register_driver (struct usb_gadget_driver *driver)
+{
+       int             status = -ENODEV;
+       struct omap_ep  *ep;
+       unsigned long   flags;
+
+       /* basic sanity tests */
+       if (!udc)
+               return -ENODEV;
+       if (!driver
+                       // FIXME if otg, check:  driver->is_otg
+                       || driver->speed < USB_SPEED_FULL
+                       || !driver->bind
+                       || !driver->unbind
+                       || !driver->setup)
+               return -EINVAL;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (udc->driver) {
+               spin_unlock_irqrestore(&udc->lock, flags);
+               return -EBUSY;
+       }
+
+       /* reset state */
+       list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
+               ep->irqs = 0;
+               if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+                       continue;
+               use_ep(ep, 0);
+               UDC_CTRL_REG = UDC_SET_HALT;
+       }
+       udc->ep0_pending = 0;
+       udc->ep[0].irqs = 0;
+       udc->softconnect = 1;
+
+       /* hook up the driver */
+       driver->driver.bus = 0;
+       udc->driver = driver;
+       udc->gadget.dev.driver = &driver->driver;
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       status = driver->bind (&udc->gadget);
+       if (status) {
+               DBG("bind to %s --> %d\n", driver->driver.name, status);
+               udc->gadget.dev.driver = 0;
+               udc->driver = 0;
+               goto done;
+       }
+       DBG("bound to driver %s\n", driver->driver.name);
+
+       UDC_IRQ_SRC_REG = UDC_IRQ_SRC_MASK;
+
+       /* connect to bus through transceiver */
+       if (udc->transceiver) {
+               status = otg_set_peripheral(udc->transceiver, &udc->gadget);
+               if (status < 0) {
+                       ERR("can't bind to transceiver\n");
+                       driver->unbind (&udc->gadget);
+                       udc->gadget.dev.driver = 0;
+                       udc->driver = 0;
+                       goto done;
+               }
+       } else {
+               if (can_pullup(udc))
+                       pullup_enable (udc);
+               else
+                       pullup_disable (udc);
+       }
+
+done:
+       return status;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+{
+       unsigned long   flags;
+       int             status = -ENODEV;
+
+       if (!udc)
+               return -ENODEV;
+       if (!driver || driver != udc->driver)
+               return -EINVAL;
+
+       if (udc->transceiver)
+               (void) otg_set_peripheral(udc->transceiver, 0);
+       else
+               pullup_disable(udc);
+
+       spin_lock_irqsave(&udc->lock, flags);
+       udc_quiesce(udc);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       driver->unbind(&udc->gadget);
+       udc->gadget.dev.driver = 0;
+       udc->driver = 0;
+
+
+       DBG("unregistered driver '%s'\n", driver->driver.name);
+       return status;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_USB_OMAP_PROC
+
+#include <linux/seq_file.h>
+
+static const char proc_filename[] = "driver/udc";
+
+#define FOURBITS "%s%s%s%s"
+#define EIGHTBITS FOURBITS FOURBITS
+
+static void proc_ep_show(struct seq_file *s, struct omap_ep *ep)
+{
+       u16             stat_flg;
+       struct omap_req *req;
+       char            buf[20];
+
+       use_ep(ep, 0);
+
+       if (use_dma && ep->has_dma)
+               snprintf(buf, sizeof buf, "(%cxdma%d lch%d) ",
+                       (ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r',
+                       ep->dma_channel - 1, ep->lch);
+       else
+               buf[0] = 0;
+
+       stat_flg = UDC_STAT_FLG_REG;
+       seq_printf(s,
+               "\n%s %sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",
+               ep->name, buf, ep->irqs, stat_flg,
+               (stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "",
+               (stat_flg & UDC_MISS_IN) ? "miss_in " : "",
+               (stat_flg & UDC_DATA_FLUSH) ? "data_flush " : "",
+               (stat_flg & UDC_ISO_ERR) ? "iso_err " : "",
+               (stat_flg & UDC_ISO_FIFO_EMPTY) ? "iso_fifo_empty " : "",
+               (stat_flg & UDC_ISO_FIFO_FULL) ? "iso_fifo_full " : "",
+               (stat_flg & UDC_EP_HALTED) ? "HALT " : "",
+               (stat_flg & UDC_STALL) ? "STALL " : "",
+               (stat_flg & UDC_NAK) ? "NAK " : "",
+               (stat_flg & UDC_ACK) ? "ACK " : "",
+               (stat_flg & UDC_FIFO_EN) ? "fifo_en " : "",
+               (stat_flg & UDC_NON_ISO_FIFO_EMPTY) ? "fifo_empty " : "",
+               (stat_flg & UDC_NON_ISO_FIFO_FULL) ? "fifo_full " : "");
+
+       if (list_empty (&ep->queue))
+               seq_printf(s, "\t(queue empty)\n");
+       else
+               list_for_each_entry (req, &ep->queue, queue)
+                       seq_printf(s, "\treq %p len %d/%d buf %p\n",
+                                       &req->req, req->req.actual,
+                                       req->req.length, req->req.buf);
+}
+
+static char *trx_mode(unsigned m)
+{
+       switch (m) {
+       case 3:
+       case 0:         return "6wire";
+       case 1:         return "4wire";
+       case 2:         return "3wire";
+       default:        return "unknown";
+       }
+}
+
+static int proc_udc_show(struct seq_file *s, void *_)
+{
+       u32             tmp;
+       struct omap_ep  *ep;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       seq_printf(s, "%s, version: " DRIVER_VERSION
+#ifdef USE_ISO
+               " (iso)"
+#endif
+               "%s\n",
+               driver_desc,
+               use_dma ?  " (dma)" : "");
+
+       tmp = UDC_REV_REG & 0xff; 
+       seq_printf(s,
+               "UDC rev %d.%d, OTG rev %d.%d, fifo mode %d, gadget %s\n"
+               "hmc %d, transceiver %08x %s\n",
+               tmp >> 4, tmp & 0xf,
+               OTG_REV_REG >> 4, OTG_REV_REG & 0xf,
+               fifo_mode,
+               udc->driver ? udc->driver->driver.name : "(none)",
+               HMC, USB_TRANSCEIVER_CTRL_REG,
+               udc->transceiver ? udc->transceiver->label : "");
+
+       /* OTG controller registers */
+       tmp = OTG_SYSCON_1_REG;
+       seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
+                       FOURBITS "\n", tmp,
+               trx_mode(USB2_TRX_MODE(tmp)),
+               trx_mode(USB1_TRX_MODE(tmp)),
+               trx_mode(USB0_TRX_MODE(tmp)),
+               (tmp & OTG_IDLE_EN) ? " !otg" : "",
+               (tmp & HST_IDLE_EN) ? " !host" : "",
+               (tmp & DEV_IDLE_EN) ? " !dev" : "",
+               (tmp & OTG_RESET_DONE) ? " reset_done" : " reset_active");
+       tmp = OTG_SYSCON_2_REG;
+       seq_printf(s, "otg_syscon2 %08x%s" EIGHTBITS
+                       " b_ase_brst=%d hmc=%d\n", tmp,
+               (tmp & OTG_EN) ? " otg_en" : "",
+               (tmp & USBX_SYNCHRO) ? " synchro" : "",
+               // much more SRP stuff
+               (tmp & SRP_DATA) ? " srp_data" : "",
+               (tmp & SRP_VBUS) ? " srp_vbus" : "",
+               (tmp & OTG_PADEN) ? " otg_paden" : "",
+               (tmp & HMC_PADEN) ? " hmc_paden" : "",
+               (tmp & UHOST_EN) ? " uhost_en" : "",
+               (tmp & HMC_TLLSPEED) ? " tllspeed" : "",
+               (tmp & HMC_TLLATTACH) ? " tllattach" : "",
+               B_ASE_BRST(tmp),
+               OTG_HMC(tmp));
+       tmp = OTG_CTRL_REG;
+       seq_printf(s, "otg_ctrl    %06x" EIGHTBITS EIGHTBITS "%s\n", tmp,
+               (tmp & OTG_ASESSVLD) ? " asess" : "",
+               (tmp & OTG_BSESSEND) ? " bsess_end" : "",
+               (tmp & OTG_BSESSVLD) ? " bsess" : "",
+               (tmp & OTG_VBUSVLD) ? " vbus" : "",
+               (tmp & OTG_ID) ? " id" : "",
+               (tmp & OTG_DRIVER_SEL) ? " DEVICE" : " HOST",
+               (tmp & OTG_A_SETB_HNPEN) ? " a_setb_hnpen" : "",
+               (tmp & OTG_A_BUSREQ) ? " a_bus" : "",
+               (tmp & OTG_B_HNPEN) ? " b_hnpen" : "",
+               (tmp & OTG_B_BUSREQ) ? " b_bus" : "",
+               (tmp & OTG_BUSDROP) ? " busdrop" : "",
+               (tmp & OTG_PULLDOWN) ? " down" : "",
+               (tmp & OTG_PULLUP) ? " up" : "",
+               (tmp & OTG_DRV_VBUS) ? " drv" : "",
+               (tmp & OTG_PD_VBUS) ? " pd_vb" : "",
+               (tmp & OTG_PU_VBUS) ? " pu_vb" : "",
+               (tmp & OTG_PU_ID) ? " pu_id" : ""
+               );
+       tmp = OTG_IRQ_EN_REG;
+       seq_printf(s, "otg_irq_en  %04x" "\n", tmp);
+       tmp = OTG_IRQ_SRC_REG;
+       seq_printf(s, "otg_irq_src %04x" "\n", tmp);
+       tmp = OTG_OUTCTRL_REG;
+       seq_printf(s, "otg_outctrl %04x" "\n", tmp);
+       tmp = OTG_TEST_REG;
+       seq_printf(s, "otg_test    %04x" "\n", tmp);
+
+       tmp = UDC_SYSCON1_REG;
+       seq_printf(s, "\nsyscon1     %04x" EIGHTBITS "\n", tmp,
+               (tmp & UDC_CFG_LOCK) ? " cfg_lock" : "",
+               (tmp & UDC_DATA_ENDIAN) ? " data_endian" : "",
+               (tmp & UDC_DMA_ENDIAN) ? " dma_endian" : "",
+               (tmp & UDC_NAK_EN) ? " nak" : "",
+               (tmp & UDC_AUTODECODE_DIS) ? " autodecode_dis" : "",
+               (tmp & UDC_SELF_PWR) ? " self_pwr" : "",
+               (tmp & UDC_SOFF_DIS) ? " soff_dis" : "",
+               (tmp & UDC_PULLUP_EN) ? " PULLUP" : "");
+       // syscon2 is write-only
+
+       /* UDC controller registers */
+       if (!(tmp & UDC_PULLUP_EN)) {
+               seq_printf(s, "(suspended)\n");
+               spin_unlock_irqrestore(&udc->lock, flags);
+               return 0;
+       }
+
+       tmp = UDC_DEVSTAT_REG;
+       seq_printf(s, "devstat     %04x" EIGHTBITS "%s%s\n", tmp,
+               (tmp & UDC_B_HNP_ENABLE) ? " b_hnp" : "",
+               (tmp & UDC_A_HNP_SUPPORT) ? " a_hnp" : "",
+               (tmp & UDC_A_ALT_HNP_SUPPORT) ? " a_alt_hnp" : "",
+               (tmp & UDC_R_WK_OK) ? " r_wk_ok" : "",
+               (tmp & UDC_USB_RESET) ? " usb_reset" : "",
+               (tmp & UDC_SUS) ? " SUS" : "",
+               (tmp & UDC_CFG) ? " CFG" : "",
+               (tmp & UDC_ADD) ? " ADD" : "",
+               (tmp & UDC_DEF) ? " DEF" : "",
+               (tmp & UDC_ATT) ? " ATT" : "");
+       seq_printf(s, "sof         %04x\n", UDC_SOF_REG);
+       tmp = UDC_IRQ_EN_REG;
+       seq_printf(s, "irq_en      %04x" FOURBITS "%s\n", tmp,
+               (tmp & UDC_SOF_IE) ? " sof" : "",
+               (tmp & UDC_EPN_RX_IE) ? " epn_rx" : "",
+               (tmp & UDC_EPN_TX_IE) ? " epn_tx" : "",
+               (tmp & UDC_DS_CHG_IE) ? " ds_chg" : "",
+               (tmp & UDC_EP0_IE) ? " ep0" : "");
+       tmp = UDC_IRQ_SRC_REG;
+       seq_printf(s, "irq_src     %04x" EIGHTBITS "%s%s\n", tmp,
+               (tmp & UDC_TXN_DONE) ? " txn_done" : "",
+               (tmp & UDC_RXN_CNT) ? " rxn_cnt" : "",
+               (tmp & UDC_RXN_EOT) ? " rxn_eot" : "",
+               (tmp & UDC_SOF) ? " sof" : "",
+               (tmp & UDC_EPN_RX) ? " epn_rx" : "",
+               (tmp & UDC_EPN_TX) ? " epn_tx" : "",
+               (tmp & UDC_DS_CHG) ? " ds_chg" : "",
+               (tmp & UDC_SETUP) ? " setup" : "",
+               (tmp & UDC_EP0_RX) ? " ep0out" : "",
+               (tmp & UDC_EP0_TX) ? " ep0in" : "");
+       if (use_dma) {
+               unsigned i;
+
+               tmp = UDC_DMA_IRQ_EN_REG;
+               seq_printf(s, "dma_irq_en  %04x%s" EIGHTBITS "\n", tmp,
+                       (tmp & UDC_TX_DONE_IE(3)) ? " tx2_done" : "",
+                       (tmp & UDC_RX_CNT_IE(3)) ? " rx2_cnt" : "",
+                       (tmp & UDC_RX_EOT_IE(3)) ? " rx2_eot" : "",
+
+                       (tmp & UDC_TX_DONE_IE(2)) ? " tx1_done" : "",
+                       (tmp & UDC_RX_CNT_IE(2)) ? " rx1_cnt" : "",
+                       (tmp & UDC_RX_EOT_IE(2)) ? " rx1_eot" : "",
+
+                       (tmp & UDC_TX_DONE_IE(1)) ? " tx0_done" : "",
+                       (tmp & UDC_RX_CNT_IE(1)) ? " rx0_cnt" : "",
+                       (tmp & UDC_RX_EOT_IE(1)) ? " rx0_eot" : "");
+
+               tmp = UDC_RXDMA_CFG_REG;
+               seq_printf(s, "rxdma_cfg   %04x\n", tmp);
+               if (tmp) {
+                       for (i = 0; i < 3; i++) {
+                               if ((tmp & (0x0f << (i * 4))) == 0)
+                                       continue;
+                               seq_printf(s, "rxdma[%d]    %04x\n", i,
+                                               UDC_RXDMA_REG(i + 1));
+                       }
+               }
+               tmp = UDC_TXDMA_CFG_REG;
+               seq_printf(s, "txdma_cfg   %04x\n", tmp);
+               if (tmp) {
+                       for (i = 0; i < 3; i++) {
+                               if (!(tmp & (0x0f << (i * 4))))
+                                       continue;
+                               seq_printf(s, "txdma[%d]    %04x\n", i,
+                                               UDC_TXDMA_REG(i + 1));
+                       }
+               }
+       }
+
+       tmp = UDC_DEVSTAT_REG;
+       if (tmp & UDC_ATT) {
+               proc_ep_show(s, &udc->ep[0]);
+               if (tmp & UDC_ADD) {
+                       list_for_each_entry (ep, &udc->gadget.ep_list,
+                                       ep.ep_list) {
+                               if (ep->desc)
+                                       proc_ep_show(s, ep);
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int proc_udc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, proc_udc_show, 0);
+}
+
+static struct file_operations proc_ops = {
+       .open           = proc_udc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static void create_proc_file(void)
+{
+       struct proc_dir_entry *pde;
+
+       pde = create_proc_entry (proc_filename, 0, NULL);
+       if (pde)
+               pde->proc_fops = &proc_ops;
+}
+
+static void remove_proc_file(void)
+{
+       remove_proc_entry(proc_filename, 0);
+}
+
+#else
+
+static inline void create_proc_file(void) {}
+static inline void remove_proc_file(void) {}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* Before this controller can enumerate, we need to pick an endpoint
+ * configuration, or "fifo_mode"  That involves allocating 2KB of packet
+ * buffer space among the endpoints we'll be operating.
+ */
+static unsigned __init
+omap_ep_setup(char *name, u8 addr, u8 type,
+               unsigned buf, unsigned maxp, int dbuf)
+{
+       struct omap_ep  *ep;
+       u16             epn_rxtx = 0;
+
+       /* OUT endpoints first, then IN */
+       ep = &udc->ep[addr & 0xf];
+       if (addr & USB_DIR_IN)
+               ep += 16;
+
+       /* in case of ep init table bugs */
+       BUG_ON(ep->name[0]);
+
+       /* chip setup ... bit values are same for IN, OUT */
+       if (type == USB_ENDPOINT_XFER_ISOC) {
+               switch (maxp) {
+               case 8:         epn_rxtx = 0 << 12; break;
+               case 16:        epn_rxtx = 1 << 12; break;
+               case 32:        epn_rxtx = 2 << 12; break;
+               case 64:        epn_rxtx = 3 << 12; break;
+               case 128:       epn_rxtx = 4 << 12; break;
+               case 256:       epn_rxtx = 5 << 12; break;
+               case 512:       epn_rxtx = 6 << 12; break;
+               default:        BUG();
+               }
+               epn_rxtx |= UDC_EPN_RX_ISO;
+               dbuf = 1;
+       } else {
+               /* pio-out could potentially double-buffer,
+                * as can (should!) DMA-IN
+                */
+               if (!use_dma || (addr & USB_DIR_IN))
+                       dbuf = 0;
+
+               switch (maxp) {
+               case 8:         epn_rxtx = 0 << 12; break;
+               case 16:        epn_rxtx = 1 << 12; break;
+               case 32:        epn_rxtx = 2 << 12; break;
+               case 64:        epn_rxtx = 3 << 12; break;
+               default:        BUG();
+               }
+               if (dbuf && addr)
+                       epn_rxtx |= UDC_EPN_RX_DB;
+       }
+       if (addr)
+               epn_rxtx |= UDC_EPN_RX_VALID;
+       BUG_ON(buf & 0x07);
+       epn_rxtx |= buf >> 3;
+
+       DBG("%s addr %02x rxtx %04x maxp %d%s buf %d\n",
+               name, addr, epn_rxtx, maxp, dbuf ? "x2" : "", buf);
+
+       if (addr & USB_DIR_IN)
+               UDC_EP_TX_REG(addr & 0xf) = epn_rxtx;
+       else
+               UDC_EP_RX_REG(addr) = epn_rxtx;
+
+       /* next endpoint's buffer starts after this one's */
+       buf += maxp;
+       if (dbuf)
+               buf += maxp;
+       BUG_ON(buf > 2048);
+
+       /* set up driver data structures */
+       BUG_ON(strlen(name) >= sizeof ep->name);
+       strlcpy(ep->name, name, sizeof ep->name);
+       INIT_LIST_HEAD(&ep->queue);
+       INIT_LIST_HEAD(&ep->iso);
+       ep->bEndpointAddress = addr;
+       ep->bmAttributes = type;
+       ep->double_buf = dbuf;
+       ep->udc = udc; 
+
+       ep->ep.name = ep->name;
+       ep->ep.ops = &omap_ep_ops;
+       ep->ep.maxpacket = ep->maxpacket = maxp;
+       list_add_tail (&ep->ep.ep_list, &udc->gadget.ep_list);
+
+       return buf;
+}
+
+static void omap_udc_release(struct device *dev)
+{
+       complete(udc->done);
+       kfree (udc);
+       udc = 0;
+}
+
+static int __init
+omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv)
+{
+       unsigned        tmp, buf;
+
+       /* abolish any previous hardware state */
+       UDC_SYSCON1_REG = 0;
+       UDC_IRQ_EN_REG = 0;
+       UDC_IRQ_SRC_REG = UDC_IRQ_SRC_MASK;
+       UDC_DMA_IRQ_EN_REG = 0;
+       UDC_RXDMA_CFG_REG = 0;
+       UDC_TXDMA_CFG_REG = 0;
+
+       /* UDC_PULLUP_EN gates the chip clock */
+       // OTG_SYSCON_1_REG |= DEV_IDLE_EN;
+
+       udc = kmalloc (sizeof *udc, SLAB_KERNEL);
+       if (!udc)
+               return -ENOMEM;
+
+       memset(udc, 0, sizeof *udc);
+       spin_lock_init (&udc->lock);
+
+       udc->gadget.ops = &omap_gadget_ops;
+       udc->gadget.ep0 = &udc->ep[0].ep;
+       INIT_LIST_HEAD(&udc->gadget.ep_list);
+       INIT_LIST_HEAD(&udc->iso);
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       udc->gadget.name = driver_name;
+
+       device_initialize(&udc->gadget.dev);
+       strcpy (udc->gadget.dev.bus_id, "gadget");
+       udc->gadget.dev.release = omap_udc_release;
+       udc->gadget.dev.parent = &odev->dev;
+       if (use_dma)
+               udc->gadget.dev.dma_mask = odev->dev.dma_mask;
+
+       udc->transceiver = xceiv;
+
+       /* ep0 is special; put it right after the SETUP buffer */
+       buf = omap_ep_setup("ep0", 0, USB_ENDPOINT_XFER_CONTROL,
+                       8 /* after SETUP */, 64 /* maxpacket */, 0);
+       list_del_init(&udc->ep[0].ep.ep_list);
+
+       /* initially disable all non-ep0 endpoints */
+       for (tmp = 1; tmp < 15; tmp++) {
+               UDC_EP_RX_REG(tmp) = 0;
+               UDC_EP_TX_REG(tmp) = 0;
+       }
+
+#define OMAP_BULK_EP(name,addr) \
+       buf = omap_ep_setup(name "-bulk", addr, \
+                       USB_ENDPOINT_XFER_BULK, buf, 64, 1);
+#define OMAP_INT_EP(name,addr, maxp) \
+       buf = omap_ep_setup(name "-int", addr, \
+                       USB_ENDPOINT_XFER_INT, buf, maxp, 0);
+#define OMAP_ISO_EP(name,addr, maxp) \
+       buf = omap_ep_setup(name "-iso", addr, \
+                       USB_ENDPOINT_XFER_ISOC, buf, maxp, 1);
+
+       switch (fifo_mode) {
+       case 0:
+               OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
+               OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
+               OMAP_INT_EP("ep3in",   USB_DIR_IN  | 3, 16);
+               break;
+       case 1:
+               OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
+               OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
+               OMAP_BULK_EP("ep3in",  USB_DIR_IN  | 3);
+               OMAP_BULK_EP("ep4out", USB_DIR_OUT | 4);
+
+               OMAP_BULK_EP("ep5in",  USB_DIR_IN  | 5);
+               OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5);
+               OMAP_BULK_EP("ep6in",  USB_DIR_IN  | 6);
+               OMAP_BULK_EP("ep6out", USB_DIR_OUT | 6);
+
+               OMAP_BULK_EP("ep7in",  USB_DIR_IN  | 7);
+               OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7);
+               OMAP_BULK_EP("ep8in",  USB_DIR_IN  | 8);
+               OMAP_BULK_EP("ep8out", USB_DIR_OUT | 8);
+
+               OMAP_INT_EP("ep9in",   USB_DIR_IN  | 9, 16);
+               OMAP_INT_EP("ep10out", USB_DIR_IN  | 10, 16);
+               OMAP_INT_EP("ep11in",  USB_DIR_IN  | 9, 16);
+               OMAP_INT_EP("ep12out", USB_DIR_IN  | 10, 16);
+               break;
+
+#ifdef USE_ISO
+       case 2:                 /* mixed iso/bulk */
+               OMAP_ISO_EP("ep1in",   USB_DIR_IN  | 1, 256);
+               OMAP_ISO_EP("ep2out",  USB_DIR_OUT | 2, 256);
+               OMAP_ISO_EP("ep3in",   USB_DIR_IN  | 3, 128);
+               OMAP_ISO_EP("ep4out",  USB_DIR_OUT | 4, 128);
+
+               OMAP_INT_EP("ep5in",   USB_DIR_IN  | 5, 16);
+
+               OMAP_BULK_EP("ep6in",  USB_DIR_IN  | 6);
+               OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7);
+               OMAP_INT_EP("ep8in",   USB_DIR_IN  | 8, 16);
+               break;
+       case 3:                 /* mixed bulk/iso */
+               OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
+               OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
+               OMAP_INT_EP("ep3in",   USB_DIR_IN  | 3, 16);
+
+               OMAP_BULK_EP("ep4in",  USB_DIR_IN  | 4);
+               OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5);
+               OMAP_INT_EP("ep6in",   USB_DIR_IN  | 6, 16);
+
+               OMAP_ISO_EP("ep7in",   USB_DIR_IN  | 7, 256);
+               OMAP_ISO_EP("ep8out",  USB_DIR_OUT | 8, 256);
+               OMAP_INT_EP("ep9in",   USB_DIR_IN  | 9, 16);
+               break;
+#endif
+
+       /* add more modes as needed */
+
+       default:
+               ERR("unsupported fifo_mode #%d\n", fifo_mode);
+               return -ENODEV;
+       }
+       UDC_SYSCON1_REG = UDC_CFG_LOCK|UDC_SELF_PWR;
+       INFO("fifo mode %d, %d bytes not used\n", fifo_mode, 2048 - buf);
+       return 0;
+}
+
+static int __init omap_udc_probe(struct device *dev)
+{
+       struct platform_device  *odev = to_platform_device(dev);
+       int                     status = -ENODEV;
+       int                     hmc;
+       struct otg_transceiver  *xceiv = 0;
+       const char              *type = 0;
+       struct omap_usb_config  *config = dev->platform_data;
+
+       /* NOTE:  "knows" the order of the resources! */
+       if (!request_mem_region(odev->resource[0].start, 
+                       odev->resource[0].end - odev->resource[0].start + 1,
+                       driver_name)) {
+               DBG("request_mem_region failed\n");
+               return -EBUSY;
+       }
+
+       INFO("OMAP UDC rev %d.%d, OTG rev %d.%d, %s receptacle\n",
+               UDC_REV_REG >> 4, UDC_REV_REG & 0xf,
+               OTG_REV_REG >> 4, OTG_REV_REG & 0xf,
+               config->otg ? "Mini-AB" : "B/Mini-B");
+
+       /* use the mode given to us by board init code */
+       hmc = HMC;
+       switch (hmc) {
+       case 3:
+       case 11:
+       case 19:
+       case 25:
+               xceiv = otg_get_transceiver();
+               if (!xceiv) {
+                       DBG("external transceiver not registered!\n");
+                       goto cleanup0;
+               }
+               type = xceiv->label;
+               break;
+       case 0:                 /* POWERUP DEFAULT == 0 */
+       case 4:
+       case 12:
+       case 20:
+               type = "INTEGRATED";
+               break;
+       case 21:                        /* internal loopback */
+               type = "(loopback)";
+               break;
+       case 14:                        /* transceiverless */
+               type = "(none)";
+               break;
+
+       default:
+               ERR("unrecognized UDC HMC mode %d\n", hmc);
+               return -ENODEV;
+       }
+       INFO("hmc mode %d, transceiver %s\n", hmc, type);
+
+       /* a "gadget" abstracts/virtualizes the controller */
+       status = omap_udc_setup(odev, xceiv);
+       if (status) {
+               goto cleanup0;
+       }
+       xceiv = 0;
+       // "udc" is now valid
+       pullup_disable(udc);
+       udc->gadget.is_otg = (config->otg != 0);
+
+       /* USB general purpose IRQ:  ep0, state changes, dma, etc */
+       status = request_irq(odev->resource[1].start, omap_udc_irq,
+                       SA_SAMPLE_RANDOM, driver_name, udc);
+       if (status != 0) {
+               ERR( "can't get irq %ld, err %d\n",
+                       odev->resource[1].start, status);
+               goto cleanup1;
+       }
+
+       /* USB "non-iso" IRQ (PIO for all but ep0) */
+       status = request_irq(odev->resource[2].start, omap_udc_pio_irq,
+                       SA_SAMPLE_RANDOM, "omap_udc pio", udc);
+       if (status != 0) {
+               ERR( "can't get irq %ld, err %d\n",
+                       odev->resource[2].start, status);
+               goto cleanup2;
+       }
+#ifdef USE_ISO
+       status = request_irq(odev->resource[3].start, omap_udc_iso_irq,
+                       SA_INTERRUPT, "omap_udc iso", udc);
+       if (status != 0) {
+               ERR("can't get irq %ld, err %d\n",
+                       odev->resource[3].start, status);
+               goto cleanup3;
+       }
+#endif
+
+       create_proc_file();
+       device_add(&udc->gadget.dev);
+       return 0;
+
+#ifdef USE_ISO
+cleanup3:
+       free_irq(odev->resource[2].start, udc);
+#endif
+
+cleanup2:
+       free_irq(odev->resource[1].start, udc);
+
+cleanup1:
+       kfree (udc);
+       udc = 0;
+
+cleanup0:
+       if (xceiv)
+               put_device(xceiv->dev);
+       release_mem_region(odev->resource[0].start,
+                       odev->resource[0].end - odev->resource[0].start + 1);
+       return status;
+}
+
+static int __exit omap_udc_remove(struct device *dev)
+{
+       struct platform_device  *odev = to_platform_device(dev);
+       DECLARE_COMPLETION(done);
+
+       if (!udc)
+               return -ENODEV;
+
+       udc->done = &done;
+
+       pullup_disable(udc);
+       if (udc->transceiver) {
+               put_device(udc->transceiver->dev);
+               udc->transceiver = 0;
+       }
+       UDC_SYSCON1_REG = 0;
+
+       remove_proc_file();
+
+#ifdef USE_ISO
+       free_irq(odev->resource[3].start, udc);
+#endif
+       free_irq(odev->resource[2].start, udc);
+       free_irq(odev->resource[1].start, udc);
+
+       release_mem_region(odev->resource[0].start,
+                       odev->resource[0].end - odev->resource[0].start + 1);
+
+       device_unregister(&udc->gadget.dev);
+       wait_for_completion(&done);
+
+       return 0;
+}
+
+/* suspend/resume/wakeup from sysfs (echo > power/state) */
+
+static int omap_udc_suspend(struct device *dev, u32 state, u32 level)
+{
+       if (level != 0)
+               return 0;
+
+       DBG("suspend, state %d\n", state);
+       omap_pullup(&udc->gadget, 0);
+       udc->gadget.dev.power.power_state = 3;
+       udc->gadget.dev.parent->power.power_state = 3;
+       return 0;
+}
+
+static int omap_udc_resume(struct device *dev, u32 level)
+{
+       if (level != 0)
+               return 0;
+
+       DBG("resume + wakeup/SRP\n");
+       udc->gadget.dev.parent->power.power_state = 0;
+       udc->gadget.dev.power.power_state = 0;
+       omap_pullup(&udc->gadget, 1);
+
+       /* maybe the host would enumerate us if we nudged it */
+       msleep(100);
+       return omap_wakeup(&udc->gadget);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct device_driver udc_driver = {
+       .name           = (char *) driver_name,
+       .bus            = &platform_bus_type,
+       .probe          = omap_udc_probe,
+       .remove         = __exit_p(omap_udc_remove),
+       .suspend        = omap_udc_suspend,
+       .resume         = omap_udc_resume,
+};
+
+static int __init udc_init(void)
+{
+       /* should work on many OMAP systems with at most minor changes,
+        * but the 1510 doesn't have an OTG controller.
+        */
+       if (cpu_is_omap1510()) {
+               DBG("no OMAP1510 support yet\n");
+               return -ENODEV;
+       }
+       INFO("%s, version: " DRIVER_VERSION "%s\n", driver_desc,
+               use_dma ?  " (dma)" : "");
+       return driver_register(&udc_driver);
+}
+module_init(udc_init);
+
+static void __exit udc_exit(void)
+{
+       driver_unregister(&udc_driver);
+}
+module_exit(udc_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
new file mode 100644 (file)
index 0000000..bd5420c
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * omap_udc.h -- for omap 3.2 udc, with OTG support
+ *
+ * 2004 (C) Texas Instruments, Inc.
+ * 2004 (C) David Brownell
+ */
+
+/*
+ * USB device/endpoint management registers
+ */
+#define UDC_REG(offset)              __REG16(UDC_BASE + (offset))
+
+#define        UDC_REV_REG                     UDC_REG(0x0)    /* Revision */
+#define        UDC_EP_NUM_REG                  UDC_REG(0x4)    /* Which endpoint */
+#      define  UDC_SETUP_SEL           (1 << 6)
+#      define  UDC_EP_SEL              (1 << 5)
+#      define  UDC_EP_DIR              (1 << 4)
+       /* low 4 bits for endpoint number */
+#define        UDC_DATA_REG                    UDC_REG(0x08)   /* Endpoint FIFO */
+#define        UDC_CTRL_REG                    UDC_REG(0x0C)   /* Endpoint control */
+#      define  UDC_CLR_HALT            (1 << 7)
+#      define  UDC_SET_HALT            (1 << 6)
+#      define  UDC_SET_FIFO_EN         (1 << 2)
+#      define  UDC_CLR_EP              (1 << 1)
+#      define  UDC_RESET_EP            (1 << 0)
+#define        UDC_STAT_FLG_REG                UDC_REG(0x10)   /* Endpoint status */
+#      define  UDC_NO_RXPACKET         (1 << 15)
+#      define  UDC_MISS_IN             (1 << 14)
+#      define  UDC_DATA_FLUSH          (1 << 13)
+#      define  UDC_ISO_ERR             (1 << 12)
+#      define  UDC_ISO_FIFO_EMPTY      (1 << 9)
+#      define  UDC_ISO_FIFO_FULL       (1 << 8)
+#      define  UDC_EP_HALTED           (1 << 6)
+#      define  UDC_STALL               (1 << 5)
+#      define  UDC_NAK                 (1 << 4)
+#      define  UDC_ACK                 (1 << 3)
+#      define  UDC_FIFO_EN             (1 << 2)
+#      define  UDC_NON_ISO_FIFO_EMPTY  (1 << 1)
+#      define  UDC_NON_ISO_FIFO_FULL   (1 << 0)
+#define        UDC_RXFSTAT_REG                 UDC_REG(0x14)   /* OUT bytecount */
+#define        UDC_SYSCON1_REG                 UDC_REG(0x18)   /* System config 1 */
+#      define  UDC_CFG_LOCK            (1 << 8)
+#      define  UDC_DATA_ENDIAN         (1 << 7)
+#      define  UDC_DMA_ENDIAN          (1 << 6)
+#      define  UDC_NAK_EN              (1 << 4)
+#      define  UDC_AUTODECODE_DIS      (1 << 3)
+#      define  UDC_SELF_PWR            (1 << 2)
+#      define  UDC_SOFF_DIS            (1 << 1)
+#      define  UDC_PULLUP_EN           (1 << 0)
+#define        UDC_SYSCON2_REG                 UDC_REG(0x1C)   /* System config 2 */
+#      define  UDC_RMT_WKP             (1 << 6)
+#      define  UDC_STALL_CMD           (1 << 5)
+#      define  UDC_DEV_CFG             (1 << 3)
+#      define  UDC_CLR_CFG             (1 << 2)
+#define        UDC_DEVSTAT_REG                 UDC_REG(0x20)   /* Device status */
+#      define  UDC_B_HNP_ENABLE        (1 << 9)
+#      define  UDC_A_HNP_SUPPORT       (1 << 8)
+#      define  UDC_A_ALT_HNP_SUPPORT   (1 << 7)
+#      define  UDC_R_WK_OK             (1 << 6)
+#      define  UDC_USB_RESET           (1 << 5)
+#      define  UDC_SUS                 (1 << 4)
+#      define  UDC_CFG                 (1 << 3)
+#      define  UDC_ADD                 (1 << 2)
+#      define  UDC_DEF                 (1 << 1)
+#      define  UDC_ATT                 (1 << 0)
+#define        UDC_SOF_REG                     UDC_REG(0x24)   /* Start of frame */
+#      define  UDC_FT_LOCK             (1 << 12)
+#      define  UDC_TS_OK               (1 << 11)
+#      define  UDC_TS                  0x03ff
+#define        UDC_IRQ_EN_REG                  UDC_REG(0x28)   /* Interrupt enable */
+#      define  UDC_SOF_IE              (1 << 7)
+#      define  UDC_EPN_RX_IE           (1 << 5)
+#      define  UDC_EPN_TX_IE           (1 << 4)
+#      define  UDC_DS_CHG_IE           (1 << 3)
+#      define  UDC_EP0_IE              (1 << 0)
+#define        UDC_DMA_IRQ_EN_REG              UDC_REG(0x2C)   /* DMA irq enable */
+       /* rx/tx dma channels numbered 1-3 not 0-2 */
+#      define  UDC_TX_DONE_IE(n)       (1 << (4 * (n) - 2))
+#      define  UDC_RX_CNT_IE(n)        (1 << (4 * (n) - 3))
+#      define  UDC_RX_EOT_IE(n)        (1 << (4 * (n) - 4))
+#define        UDC_IRQ_SRC_REG                 UDC_REG(0x30)   /* Interrupt source */
+#      define  UDC_TXN_DONE            (1 << 10)
+#      define  UDC_RXN_CNT             (1 << 9)
+#      define  UDC_RXN_EOT             (1 << 8)
+#      define  UDC_SOF                 (1 << 7)
+#      define  UDC_EPN_RX              (1 << 5)
+#      define  UDC_EPN_TX              (1 << 4)
+#      define  UDC_DS_CHG              (1 << 3)
+#      define  UDC_SETUP               (1 << 2)
+#      define  UDC_EP0_RX              (1 << 1)
+#      define  UDC_EP0_TX              (1 << 0)
+#      define  UDC_IRQ_SRC_MASK        0x7bf
+#define        UDC_EPN_STAT_REG                UDC_REG(0x34)   /* EP irq status */
+#define        UDC_DMAN_STAT_REG               UDC_REG(0x38)   /* DMA irq status */
+#      define  UDC_DMA_RX_SB           (1 << 12)
+#      define  UDC_DMA_RX_SRC(x)       (((x)>>8) & 0xf)
+#      define  UDC_DMA_TX_SRC(x)       (((x)>>0) & 0xf)
+
+
+/* DMA configuration registers:  up to three channels in each direction.  */
+#define        UDC_RXDMA_CFG_REG               UDC_REG(0x40)   /* 3 eps for RX DMA */
+#define        UDC_TXDMA_CFG_REG               UDC_REG(0x44)   /* 3 eps for TX DMA */
+#define        UDC_DATA_DMA_REG                UDC_REG(0x48)   /* rx/tx fifo addr */
+
+/* rx/tx dma control, numbering channels 1-3 not 0-2 */
+#define        UDC_TXDMA_REG(chan)             UDC_REG(0x50 - 4 + 4 * (chan))
+#      define UDC_TXN_EOT              (1 << 15)       /* bytes vs packets */
+#      define UDC_TXN_START            (1 << 14)       /* start transfer */
+#      define UDC_TXN_TSC              0x03ff          /* units in xfer */
+#define        UDC_RXDMA_REG(chan)             UDC_REG(0x60 - 4 + 4 * (chan))
+#      define UDC_RXN_STOP             (1 << 15)       /* enable EOT irq */
+#      define UDC_RXN_TC               0x00ff          /* packets in xfer */
+
+
+/*
+ * Endpoint configuration registers (used before CFG_LOCK is set)
+ * UDC_EP_TX_REG(0) is unused
+ */
+#define        UDC_EP_RX_REG(endpoint)         UDC_REG(0x80 + (endpoint)*4)
+#      define  UDC_EPN_RX_VALID        (1 << 15)
+#      define  UDC_EPN_RX_DB           (1 << 14)
+       /* buffer size in bits 13, 12 */
+#      define  UDC_EPN_RX_ISO          (1 << 11)
+       /* buffer pointer in low 11 bits */
+#define        UDC_EP_TX_REG(endpoint)         UDC_REG(0xc0 + (endpoint)*4)
+       /* same bitfields as in RX_REG */
+
+/*-------------------------------------------------------------------------*/
+
+struct omap_req {
+       struct usb_request              req;
+       struct list_head                queue;
+       unsigned                        dma_bytes;
+       unsigned                        mapped:1;
+};
+
+struct omap_ep {
+       struct usb_ep                   ep;
+       struct list_head                queue;
+       unsigned long                   irqs;
+       struct list_head                iso;
+       const struct usb_endpoint_descriptor    *desc;
+       char                            name[14];
+       u16                             maxpacket;
+       u8                              bEndpointAddress;
+       u8                              bmAttributes;
+       unsigned                        double_buf:1;
+       unsigned                        stopped:1;
+       unsigned                        ackwait:1;
+       unsigned                        has_dma:1;
+       u8                              dma_channel;
+       int                             lch;
+       struct omap_udc                 *udc;
+};
+
+struct omap_udc {
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+       spinlock_t                      lock;
+       struct omap_ep                  ep[32];
+       u16                             devstat;
+       struct otg_transceiver          *transceiver;
+       struct list_head                iso;
+       unsigned                        softconnect:1;
+       unsigned                        vbus_active:1;
+       unsigned                        ep0_pending:1;
+       unsigned                        ep0_in:1;
+       unsigned                        ep0_set_config:1;
+       unsigned                        ep0_reset_config:1;
+       unsigned                        ep0_setup:1;
+       unsigned                        hmc:6;
+
+       struct completion               *done;
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+#define DBG(stuff...)          printk(KERN_DEBUG "udc: " stuff)
+#else
+#define DBG(stuff...)          do{}while(0)
+#endif
+
+#ifdef VERBOSE
+#    define VDBG               DBG
+#else
+#    define VDBG(stuff...)     do{}while(0)
+#endif
+
+#define ERR(stuff...)          printk(KERN_ERR "udc: " stuff)
+#define WARN(stuff...)         printk(KERN_WARNING "udc: " stuff)
+#define INFO(stuff...)         printk(KERN_INFO "udc: " stuff)
+
+/*-------------------------------------------------------------------------*/
+
+// #define     HMC_1510        ((MOD_CONF_CTRL_0_REG >> 1) & 0x3f)
+#define        HMC_1610        (OTG_SYSCON_2_REG & 0x3f)
+#define        HMC              HMC_1610
+
index 946898a..c6e6362 100644 (file)
@@ -52,6 +52,7 @@ config USB_EHCI_ROOT_HUB_TT
 config USB_OHCI_HCD
        tristate "OHCI HCD support"
        depends on USB
+       select ISP1301_OMAP if MACH_OMAP_H2
        ---help---
          The Open Host Controller Interface (OHCI) is a standard for accessing
          USB 1.1 host controller hardware.  It does more in hardware than Intel's
index 5bda712..b57f1fe 100644 (file)
@@ -106,14 +106,14 @@ int SL11StartXaction (hci_t * hci, __u8 addr, __u8 epaddr, int pid, int len,
 
 static int sofWaitCnt = 0;
 
-MODULE_PARM (urb_debug, "i");
+module_param(urb_debug, int, 0);
 MODULE_PARM_DESC (urb_debug, "debug urb messages, default is 0 (no)");
 
-MODULE_PARM (base_addr, "i");
+module_param(base_addr, int, 0);
 MODULE_PARM_DESC (base_addr, "sl811 base address 0xd3800000");
-MODULE_PARM (data_reg_addr, "i");
+module_param(data_reg_addr, int, 0);
 MODULE_PARM_DESC (data_reg_addr, "sl811 data register address 0xd3810000");
-MODULE_PARM (irq, "i");
+module_param(irq, int, 0);
 MODULE_PARM_DESC (irq, "IRQ 34 (default)");
 
 static int hc_reset (hci_t * hci);
index fc9cb47..62ff214 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/types.h>
 #include <linux/param.h>
 #include <linux/rwsem.h>
+#include <asm/semaphore.h>
 
 #include "sn9c102_sensor.h"
 
@@ -39,6 +40,7 @@
 #define SN9C102_DEBUG
 #define SN9C102_DEBUG_LEVEL       2
 #define SN9C102_MAX_DEVICES       64
+#define SN9C102_PRESERVE_IMGSCALE 0
 #define SN9C102_MAX_FRAMES        32
 #define SN9C102_URBS              2
 #define SN9C102_ISO_PACKETS       7
@@ -51,8 +53,8 @@
 #define SN9C102_MODULE_AUTHOR   "(C) 2004 Luca Risolia"
 #define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
 #define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.01-beta"
-#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 1)
+#define SN9C102_MODULE_VERSION  "1:1.08"
+#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 8)
 
 SN9C102_ID_TABLE;
 SN9C102_SENSOR_TABLE;
index bcd9fbd..9f775f7 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/time.h>
 #include <linux/delay.h>
 #include <linux/stddef.h>
+#include <linux/compiler.h>
 #include <linux/ioctl.h>
 #include <linux/poll.h>
 #include <linux/stat.h>
@@ -83,7 +84,7 @@ MODULE_PARM_DESC(debug,
 
 /*****************************************************************************/
 
-typedef char sn9c102_sof_header_t[7];
+typedef char sn9c102_sof_header_t[12];
 typedef char sn9c102_eof_header_t[4];
 
 static sn9c102_sof_header_t sn9c102_sof_header[] = {
@@ -91,8 +92,6 @@ static sn9c102_sof_header_t sn9c102_sof_header[] = {
        {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01},
 };
 
-/* Number of random bytes that complete the SOF above headers */
-#define SN9C102_SOFLEN 5
 
 static sn9c102_eof_header_t sn9c102_eof_header[] = {
        {0x00, 0x00, 0x00, 0x00},
@@ -237,9 +236,6 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
        u8* buff = cam->control_buffer;
        int res;
 
-       if (index == 0x18)
-               value = (value & 0xcf) | (cam->reg[0x18] & 0x30);
-
        *buff = value;
 
        res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
@@ -443,14 +439,15 @@ int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
 
 static void* sn9c102_find_sof_header(void* mem, size_t len)
 {
-       size_t soflen=sizeof(sn9c102_sof_header_t), SOFLEN=SN9C102_SOFLEN, i;
+       size_t soflen = sizeof(sn9c102_sof_header_t), i;
        u8 j, n = sizeof(sn9c102_sof_header) / soflen;
 
-       for (i = 0; (len >= soflen+SOFLEN) && (i <= len-soflen-SOFLEN); i++)
+       for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
                for (j = 0; j < n; j++)
-                       if (!memcmp(mem + i, sn9c102_sof_header[j], soflen))
+                       /* It's enough to compare 7 bytes */
+                       if (!memcmp(mem + i, sn9c102_sof_header[j], 7))
                                /* Skips the header */
-                               return mem + i + soflen + SOFLEN;
+                               return mem + i + soflen;
 
        return NULL;
 }
@@ -517,10 +514,12 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
 
                PDBGG("Isochrnous frame: length %u, #%u i", len, i)
 
-               /* NOTE: It is probably correct to assume that SOF and EOF
+               /*
+                  NOTE: It is probably correct to assume that SOF and EOF
                         headers do not occur between two consecutive packets,
                         but who knows..Whatever is the truth, this assumption
-                        doesn't introduce bugs. */
+                        doesn't introduce bugs.
+               */
 
 redo:
                sof = sn9c102_find_sof_header(pos, len);
@@ -764,9 +763,11 @@ static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count)
        return (u8)val;
 }
 
-/* NOTE 1: being inside one of the following methods implies that the v4l
+/*
+   NOTE 1: being inside one of the following methods implies that the v4l
            device exists for sure (see kobjects and reference counters)
-   NOTE 2: buffers are PAGE_SIZE long */
+   NOTE 2: buffers are PAGE_SIZE long
+*/
 
 static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf)
 {
@@ -1018,24 +1019,6 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
 }
 
 
-static ssize_t
-sn9c102_store_redblue(struct class_device* cd, const char* buf, size_t len)
-{
-       ssize_t res = 0;
-       u8 value;
-       ssize_t count;
-
-       value = sn9c102_strtou8(buf, len, &count);
-       if (!count)
-               return -EINVAL;
-
-       if ((res = sn9c102_store_reg(cd, "0x10", 4)) >= 0)
-               res = sn9c102_store_val(cd, buf, len);
-
-       return res;
-}
-
-
 static ssize_t
 sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
 {
@@ -1062,7 +1045,6 @@ static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
                          sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
 static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
                          sn9c102_show_i2c_val, sn9c102_store_i2c_val);
-static CLASS_DEVICE_ATTR(redblue, S_IWUGO, NULL, sn9c102_store_redblue);
 static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
 
 
@@ -1072,7 +1054,6 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam)
 
        video_device_create_file(v4ldev, &class_device_attr_reg);
        video_device_create_file(v4ldev, &class_device_attr_val);
-       video_device_create_file(v4ldev, &class_device_attr_redblue);
        video_device_create_file(v4ldev, &class_device_attr_green);
        if (cam->sensor->slave_write_id && cam->sensor->slave_read_id) {
                video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
@@ -1118,10 +1099,6 @@ static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
           ae_endy = v_size / 2;
        int err = 0;
 
-       /* These are a sort of stroboscopic signal for some sensors */
-       err += sn9c102_write_reg(cam, h_size, 0x1a);
-       err += sn9c102_write_reg(cam, v_size, 0x1b);
-
        err += sn9c102_write_reg(cam, h_start, 0x12);
        err += sn9c102_write_reg(cam, v_start, 0x13);
        err += sn9c102_write_reg(cam, h_size, 0x15);
@@ -1134,8 +1111,7 @@ static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
                return -EIO;
 
        PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
-             "%u %u %u %u %u %u", h_start, v_start, h_size, v_size, ho_size,
-             vo_size)
+             "%u %u %u %u", h_start, v_start, h_size, v_size)
 
        return 0;
 }
@@ -1229,7 +1205,10 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
        struct sn9c102_device* cam;
        int err = 0;
 
-       /* This the only safe way to prevent race conditions with disconnect */
+       /*
+          This is the only safe way to prevent race conditions with
+          disconnect
+       */
        if (!down_read_trylock(&sn9c102_disconnect))
                return -ERESTARTSYS;
 
@@ -1727,6 +1706,12 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
                                return -EINVAL;
                        }
 
+               /* Preserve R,G or B origin */
+               rect->left = (s->_rect.left & 1L) ?
+                            rect->left | 1L : rect->left & ~1L;
+               rect->top = (s->_rect.top & 1L) ?
+                           rect->top | 1L : rect->top & ~1L;
+
                if (rect->width < 16)
                        rect->width = 16;
                if (rect->height < 16)
@@ -1747,13 +1732,15 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
                rect->width &= ~15L;
                rect->height &= ~15L;
 
-               { /* calculate the scaling factor */
+               if (SN9C102_PRESERVE_IMGSCALE) {
+                       /* Calculate the actual scaling factor */
                        u32 a, b;
                        a = rect->width * rect->height;
                        b = pix_format->width * pix_format->height;
-                       scale = b ? (u8)((a / b) <= 1 ? 1 : ((a / b) == 3 ? 2 :
-                                   ((a / b) > 4 ? 4 : (a / b)))) : 1;
-               }
+                       scale = b ? (u8)((a / b) < 4 ? 1 :
+                                       ((a / b) < 16 ? 2 : 4)) : 1;
+               } else
+                       scale = 1;
 
                if (cam->stream == STREAM_ON) {
                        cam->stream = STREAM_INTERRUPT;
@@ -1879,12 +1866,12 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
 
                memcpy(&rect, &(s->_rect), sizeof(rect));
 
-               { /* calculate the scaling factor */
+               { /* calculate the actual scaling factor */
                        u32 a, b;
                        a = rect.width * rect.height;
                        b = pix->width * pix->height;
-                       scale = b ? (u8)((a / b) <= 1 ? 1 : ((a / b) == 3 ? 2 :
-                                   ((a / b) > 4 ? 4 : (a / b)))) : 1;
+                       scale = b ? (u8)((a / b) < 4 ? 1 :
+                                       ((a / b) < 16 ? 2 : 4)) : 1;
                }
 
                rect.width = scale * pix->width;
@@ -1895,13 +1882,21 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
                if (rect.height < 16)
                        rect.height = 16;
                if (rect.width > bounds->left + bounds->width - rect.left)
-                       rect.width = bounds->left+bounds->width - rect.left;
+                       rect.width = bounds->left + bounds->width - rect.left;
                if (rect.height > bounds->top + bounds->height - rect.top)
                        rect.height = bounds->top + bounds->height - rect.top;
 
                rect.width &= ~15L;
                rect.height &= ~15L;
 
+               { /* adjust the scaling factor */
+                       u32 a, b;
+                       a = rect.width * rect.height;
+                       b = pix->width * pix->height;
+                       scale = b ? (u8)((a / b) < 4 ? 1 :
+                                       ((a / b) < 16 ? 2 : 4)) : 1;
+               }
+
                pix->width = rect.width / scale;
                pix->height = rect.height / scale;
 
@@ -2119,7 +2114,7 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
                spin_lock_irqsave(&cam->queue_lock, lock_flags);
                f = list_entry(cam->outqueue.next, struct sn9c102_frame_t,
                               frame);
-               list_del(&cam->outqueue);
+               list_del(cam->outqueue.next);
                spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
 
                f->state = F_UNUSED;
index 34bdfcf..a302a48 100644 (file)
@@ -40,13 +40,12 @@ static int pas106b_init(struct sn9c102_device* cam)
        err += sn9c102_i2c_write(cam, 0x02, 0x0c);
        err += sn9c102_i2c_write(cam, 0x03, 0x12);
        err += sn9c102_i2c_write(cam, 0x04, 0x05);
-       err += sn9c102_i2c_write(cam, 0x05, 0x22);
-       err += sn9c102_i2c_write(cam, 0x06, 0xac);
-       err += sn9c102_i2c_write(cam, 0x07, 0x00);
+       err += sn9c102_i2c_write(cam, 0x05, 0x5a);
+       err += sn9c102_i2c_write(cam, 0x06, 0x88);
+       err += sn9c102_i2c_write(cam, 0x07, 0x80);
        err += sn9c102_i2c_write(cam, 0x08, 0x01);
-       err += sn9c102_i2c_write(cam, 0x0a, 0x00);
+       err += sn9c102_i2c_write(cam, 0x0a, 0x01);
        err += sn9c102_i2c_write(cam, 0x0b, 0x00);
-       err += sn9c102_i2c_write(cam, 0x0d, 0x00);
        err += sn9c102_i2c_write(cam, 0x10, 0x06);
        err += sn9c102_i2c_write(cam, 0x11, 0x06);
        err += sn9c102_i2c_write(cam, 0x12, 0x00);
@@ -64,11 +63,30 @@ static int pas106b_get_ctrl(struct sn9c102_device* cam,
 {
        switch (ctrl->id) {
        case V4L2_CID_RED_BALANCE:
-               return (ctrl->value = sn9c102_i2c_read(cam, 0x0c))<0 ? -EIO:0;
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x1f;
+               return 0;
        case V4L2_CID_BLUE_BALANCE:
-               return (ctrl->value = sn9c102_i2c_read(cam, 0x09))<0 ? -EIO:0;
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x1f;
+               return 0;
+       case V4L2_CID_GAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0e)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x1f;
+               return 0;
        case V4L2_CID_BRIGHTNESS:
-               return (ctrl->value = sn9c102_i2c_read(cam, 0x0e))<0 ? -EIO:0;
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x1f;
+               return 0;
+       case V4L2_CID_CONTRAST:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x07;
+               return 0;
        default:
                return -EINVAL;
        }
@@ -87,9 +105,15 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam,
        case V4L2_CID_BLUE_BALANCE:
                err += sn9c102_i2c_write(cam, 0x09, ctrl->value & 0x1f);
                break;
-       case V4L2_CID_BRIGHTNESS:
+       case V4L2_CID_GAIN:
                err += sn9c102_i2c_write(cam, 0x0e, ctrl->value & 0x1f);
                break;
+       case V4L2_CID_BRIGHTNESS:
+               err += sn9c102_i2c_write(cam, 0x0d, 0x1f-(ctrl->value & 0x1f));
+               break;
+       case V4L2_CID_CONTRAST:
+               err += sn9c102_i2c_write(cam, 0x0f, ctrl->value & 0x03);
+               break;
        default:
                return -EINVAL;
        }
@@ -130,7 +154,7 @@ static struct sn9c102_sensor pas106b = {
                        .minimum = 0x00,
                        .maximum = 0x1f,
                        .step = 0x01,
-                       .default_value = 0x03,
+                       .default_value = 0x04,
                        .flags = 0,
                },
                {
@@ -140,7 +164,17 @@ static struct sn9c102_sensor pas106b = {
                        .minimum = 0x00,
                        .maximum = 0x1f,
                        .step = 0x01,
-                       .default_value = 0x02,
+                       .default_value = 0x06,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0x1f,
+                       .step = 0x01,
+                       .default_value = 0x0d,
                        .flags = 0,
                },
                {
@@ -150,7 +184,17 @@ static struct sn9c102_sensor pas106b = {
                        .minimum = 0x00,
                        .maximum = 0x1f,
                        .step = 0x01,
-                       .default_value = 0x06,
+                       .default_value = 0x1f,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_CONTRAST,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "contrast",
+                       .minimum = 0x00,
+                       .maximum = 0x07,
+                       .step = 0x01,
+                       .default_value = 0x00, /* 0x00~0x03 have same effect */
                        .flags = 0,
                },
        },
@@ -185,11 +229,13 @@ int sn9c102_probe_pas106b(struct sn9c102_device* cam)
        int r0 = 0, r1 = 0, err = 0;
        unsigned int pid = 0;
 
-       /* Minimal initialization to enable the I2C communication
-          NOTE: do NOT change the values! */
+       /*
+          Minimal initialization to enable the I2C communication
+          NOTE: do NOT change the values!
+       */
        err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
        err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */
-       err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 48 MHz */
+       err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
        if (err)
                return -EIO;
 
diff --git a/drivers/usb/media/sn9c102_pas202bcb.c b/drivers/usb/media/sn9c102_pas202bcb.c
new file mode 100644 (file)
index 0000000..26944ea
--- /dev/null
@@ -0,0 +1,238 @@
+/***************************************************************************
+ * Driver for PAS202BCB image sensor connected to the SN9C10[12] PC Camera *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio                  *
+ *                       <medaglia@undl.org.br>                            *
+ *                       http://cadu.homelinux.com:8080/                   *
+ *                                                                         *
+ * This program is free software; you can redistribute 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/delay.h>
+#include "sn9c102_sensor.h"
+
+
+static struct sn9c102_sensor pas202bcb;
+
+
+static int pas202bcb_init(struct sn9c102_device* cam)
+{
+       int err = 0;
+
+       err += sn9c102_write_reg(cam, 0x00, 0x10);
+       err += sn9c102_write_reg(cam, 0x00, 0x11);
+       err += sn9c102_write_reg(cam, 0x00, 0x14);
+       err += sn9c102_write_reg(cam, 0x20, 0x17);
+       err += sn9c102_write_reg(cam, 0x20, 0x19);
+       err += sn9c102_write_reg(cam, 0x09, 0x18);
+
+       err += sn9c102_i2c_write(cam, 0x02, 0x0c);
+       err += sn9c102_i2c_write(cam, 0x03, 0x40);
+       err += sn9c102_i2c_write(cam, 0x04, 0x07);
+       err += sn9c102_i2c_write(cam, 0x05, 0x25);
+       err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
+       err += sn9c102_i2c_write(cam, 0x0e, 0x01);
+       err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
+       err += sn9c102_i2c_write(cam, 0x08, 0x01);
+       err += sn9c102_i2c_write(cam, 0x0b, 0x01);
+       err += sn9c102_i2c_write(cam, 0x13, 0x63);
+       err += sn9c102_i2c_write(cam, 0x15, 0x70);
+       err += sn9c102_i2c_write(cam, 0x11, 0x01);
+
+       msleep(400);
+
+       return err;
+}
+
+
+static int pas202bcb_get_ctrl(struct sn9c102_device* cam, 
+                              struct v4l2_control* ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_RED_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x0f;
+               return 0;
+       case V4L2_CID_BLUE_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x0f;
+               return 0;
+       case V4L2_CID_GAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x1f;
+               return 0;
+       case V4L2_CID_BRIGHTNESS:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x06)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x0f;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+
+static int pas202bcb_set_ctrl(struct sn9c102_device* cam, 
+                              const struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_RED_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x09, ctrl->value & 0x0f);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x07, ctrl->value & 0x0f);
+               break;
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_write(cam, 0x10, ctrl->value & 0x1f);
+               break;
+       case V4L2_CID_BRIGHTNESS:
+               err += sn9c102_i2c_write(cam, 0x06, 0x0f-(ctrl->value & 0x0f));
+               break;
+       default:
+               return -EINVAL;
+       }
+       err += sn9c102_i2c_write(cam, 0x11, 0x01);
+
+       return err;
+}
+
+
+static int pas202bcb_set_crop(struct sn9c102_device* cam, 
+                              const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = &pas202bcb;
+       int err = 0;
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       return err;
+}
+
+
+static struct sn9c102_sensor pas202bcb = {
+       .name = "PAS202BCB",
+       .maintainer = "Carlos Eduardo Medaglia Dyonisio "
+                     "<medaglia@undl.org.br>",
+       .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .slave_read_id = 0x40,
+       .slave_write_id = 0x40,
+       .init = &pas202bcb_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_RED_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "red balance",
+                       .minimum = 0x00,
+                       .maximum = 0x0f,
+                       .step = 0x01,
+                       .default_value = 0x01,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BLUE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "blue balance",
+                       .minimum = 0x00,
+                       .maximum = 0x0f,
+                       .step = 0x01,
+                       .default_value = 0x05,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0x1f,
+                       .step = 0x01,
+                       .default_value = 0x0c,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BRIGHTNESS,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "brightness",
+                       .minimum = 0x00,
+                       .maximum = 0x0f,
+                       .step = 0x01,
+                       .default_value = 0x0f,
+                       .flags = 0,
+               },
+       },
+       .get_ctrl = &pas202bcb_get_ctrl,
+       .set_ctrl = &pas202bcb_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .set_crop = &pas202bcb_set_crop,
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .priv = 8,
+       }
+};
+
+
+int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
+{       
+       int r0 = 0, r1 = 0, err = 0;
+       unsigned int pid = 0;
+
+       /*
+        *  Minimal initialization to enable the I2C communication
+        *  NOTE: do NOT change the values!
+        */
+       err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
+       err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */
+       err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
+       if (err)
+               return -EIO;
+
+       r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
+       r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
+       
+       if (r0 < 0 || r1 < 0)
+               return -EIO;
+
+       pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
+       if (pid != 0x017)
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &pas202bcb);
+
+       return 0;
+}
index 54a3499..3e7e4a2 100644 (file)
@@ -33,7 +33,8 @@ struct sn9c102_sensor;
 
 /*****************************************************************************/
 
-/* OVERVIEW.
+/*
+   OVERVIEW.
    This is a small interface that allows you to add support for any CCD/CMOS
    image sensors connected to the SN9C10X bridges. The entire API is documented
    below. In the most general case, to support a sensor there are three steps
@@ -48,26 +49,33 @@ struct sn9c102_sensor;
    "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
    NOT need to touch the source code of the core module for the things to work
    properly, unless you find bugs or flaws in it. Finally, do not forget to
-   read the V4L2 API for completeness. */
+   read the V4L2 API for completeness.
+*/
 
 /*****************************************************************************/
-/* Probing functions: on success, you must attach the sensor to the camera
+
+/*
+   Probing functions: on success, you must attach the sensor to the camera
    by calling sn9c102_attach_sensor() provided below.
    To enable the I2C communication, you might need to perform a really basic
    initialization of the SN9C10X chip by using the write function declared 
    ahead.
-   Functions must return 0 on success, the appropriate error otherwise. */
+   Functions must return 0 on success, the appropriate error otherwise.
+*/
 extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
+extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
 extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
 extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
 
-/* Add the above entries to this table. Be sure to add the entry in the right
+/*
+   Add the above entries to this table. Be sure to add the entry in the right
    place, since, on failure, the next probing routine is called according to 
-   the order of the list below, from top to bottom */
+   the order of the list below, from top to bottom.
+*/
 #define SN9C102_SENSOR_TABLE                                                  \
 static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {              \
-       &sn9c102_probe_pas106b, /* strong detection based on SENSOR vid/pid */\
+       &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */    \
+       &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */  \
        &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */       \
        &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */       \
        NULL,                                                                 \
@@ -81,28 +89,29 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
 /* Each SN9C10X camera has proper PID/VID identifiers. Add them here in case.*/
 #define SN9C102_ID_TABLE                                                      \
 static const struct usb_device_id sn9c102_id_table[] = {                      \
-       { USB_DEVICE(0xc45, 0x6001), },                                       \
+       { USB_DEVICE(0xc45, 0x6001), }, /* TAS5110C1B */                      \
        { USB_DEVICE(0xc45, 0x6005), }, /* TAS5110C1B */                      \
        { USB_DEVICE(0xc45, 0x6009), }, /* PAS106B */                         \
        { USB_DEVICE(0xc45, 0x600d), }, /* PAS106B */                         \
        { USB_DEVICE(0xc45, 0x6024), },                                       \
-       { USB_DEVICE(0xc45, 0x6025), }, /* TAS5130D1B Maybe also TAS5110C1B */\
-       { USB_DEVICE(0xc45, 0x6028), }, /* Maybe PAS202B */                   \
-       { USB_DEVICE(0xc45, 0x6029), },                                       \
-       { USB_DEVICE(0xc45, 0x602a), }, /* Maybe HV7131[D|E1] */              \
-       { USB_DEVICE(0xc45, 0x602c), }, /* Maybe OV7620 */                    \
-       { USB_DEVICE(0xc45, 0x6030), }, /* Maybe MI03 */                      \
-       { USB_DEVICE(0xc45, 0x8001), },                                       \
+       { USB_DEVICE(0xc45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */       \
+       { USB_DEVICE(0xc45, 0x6028), }, /* PAS202BCB */                       \
+       { USB_DEVICE(0xc45, 0x6029), }, /* PAS106B */                         \
+       { USB_DEVICE(0xc45, 0x602a), }, /* HV7131[D|E1] */                    \
+       { USB_DEVICE(0xc45, 0x602c), }, /* OV7620 */                          \
+       { USB_DEVICE(0xc45, 0x6030), }, /* MI03 */                            \
        { }                                                                   \
 };
 
 /*****************************************************************************/
 
-/* Read/write routines: they always return -1 on error, 0 or the read value
+/*
+   Read/write routines: they always return -1 on error, 0 or the read value
    otherwise. NOTE that a real read operation is not supported by the SN9C10X
    chip for some of its registers. To work around this problem, a pseudo-read
    call is provided instead: it returns the last successfully written value 
-   on the register (0 if it has never been written), the usual -1 on error. */
+   on the register (0 if it has never been written), the usual -1 on error.
+*/
 
 /* The "try" I2C I/O versions are used when probing the sensor */
 extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
@@ -110,10 +119,12 @@ extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
 extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
                                 u8 address);
 
-/* This must be used if and only if the sensor doesn't implement the standard
-   I2C protocol, like the TASC sensors. There a number of good reasons why you
-   must use the single-byte versions of this function: do not abuse. It writes
-   n bytes, from data0 to datan, (registers 0x09 - 0x09+n of SN9C10X chip) */
+/*
+   This must be used if and only if the sensor doesn't implement the standard
+   I2C protocol. There a number of good reasons why you must use the 
+   single-byte versions of this function: do not abuse. It writes n bytes, 
+   from data0 to datan, (registers 0x09 - 0x09+n of SN9C10X chip).
+*/
 extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
                                      struct sn9c102_sensor* sensor, u8 n, 
                                      u8 data0, u8 data1, u8 data2, u8 data3,
@@ -127,12 +138,14 @@ extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
 extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
 extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
 
-/* NOTE: there are no debugging functions here. To uniform the output you must
+/*
+   NOTE: there are no debugging functions here. To uniform the output you must
    use the dev_info()/dev_warn()/dev_err() macros defined in device.h, already
    included here, the argument being the struct device 'dev' of the sensor
    structure. Do NOT use these macros before the sensor is attached or the
    kernel will crash! However you should not need to notify the user about
-   common errors or other messages, since this is done by the master module. */
+   common errors or other messages, since this is done by the master module.
+*/
 
 /*****************************************************************************/
 
@@ -150,24 +163,31 @@ struct sn9c102_sensor {
        char name[32], /* sensor name */
             maintainer[64]; /* name of the mantainer <email> */
 
-       /* These sensor capabilities must be provided if the SN9C10X controller
+       /*
+          These sensor capabilities must be provided if the SN9C10X controller
           needs to communicate through the sensor serial interface by using
-          at least one of the i2c functions available */
+          at least one of the i2c functions available.
+       */
        enum sn9c102_i2c_frequency frequency;
        enum sn9c102_i2c_interface interface;
 
-       /* These identifiers must be provided if the image sensor implements
+       /*
+          These identifiers must be provided if the image sensor implements
           the standard I2C protocol. TASC sensors don't, although they have a
           serial interface: so this is a case where the "raw" I2C version
-          could be helpful. */
+          could be helpful.
+       */
        u8 slave_read_id, slave_write_id; /* reg. 0x09 */
 
-       /* NOTE: Where not noted,most of the functions below are not mandatory.
+       /*
+          NOTE: Where not noted,most of the functions below are not mandatory.
                 Set to null if you do not implement them. If implemented,
-                they must return 0 on success, the proper error otherwise. */
+                they must return 0 on success, the proper error otherwise.
+       */
 
        int (*init)(struct sn9c102_device* cam);
-       /* This function is called after the sensor has been attached. 
+       /*
+          This function is called after the sensor has been attached. 
           It should be used to initialize the sensor only, but may also
           configure part of the SN9C10X chip if necessary. You don't need to
           setup picture settings like brightness, contrast, etc.. here, if
@@ -177,23 +197,29 @@ struct sn9c102_sensor {
           specified in the v4l2_queryctrl list of supported controls;
           Same suggestions apply for other settings, _if_ the corresponding
           methods are present; if not, the initialization must configure the
-          sensor according to the default configuration structures below. */
+          sensor according to the default configuration structures below.
+       */
 
        struct v4l2_queryctrl qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE];
-       /* Optional list of default controls, defined as indicated in the 
-          V4L2 API. Menu type controls are not handled by this interface. */
+       /*
+          Optional list of default controls, defined as indicated in the 
+          V4L2 API. Menu type controls are not handled by this interface.
+       */
 
        int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl);
        int (*set_ctrl)(struct sn9c102_device* cam,
                        const struct v4l2_control* ctrl);
-       /* You must implement at least the set_ctrl method if you have defined
+       /*
+          You must implement at least the set_ctrl method if you have defined
           the list above. The returned value must follow the V4L2
           specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER
           are not supported by this driver, so do not implement them. Also,
-          passed values are NOT checked to see if they are out of bounds. */
+          passed values are NOT checked to see if they are out of bounds.
+       */
 
        struct v4l2_cropcap cropcap;
-       /* Think the image sensor as a grid of R,G,B monochromatic pixels
+       /*
+          Think the image sensor as a grid of R,G,B monochromatic pixels
           disposed according to a particular Bayer pattern, which describes
           the complete array of pixels, from (0,0) to (xmax, ymax). We will
           use this coordinate system from now on. It is assumed the sensor
@@ -221,11 +247,13 @@ struct sn9c102_sensor {
           NOTE: once you have defined the bounds of the active window
                 (struct cropcap.bounds) you must not change them.anymore.
           Only 'bounds' and 'defrect' fields are mandatory, other fields
-          will be ignored. */
+          will be ignored.
+       */
 
        int (*set_crop)(struct sn9c102_device* cam,
                        const struct v4l2_rect* rect);
-       /* To be called on VIDIOC_C_SETCROP. The core module always calls a
+       /*
+          To be called on VIDIOC_C_SETCROP. The core module always calls a
           default routine which configures the appropriate SN9C10X regs (also
           scaling), but you may need to override/adjust specific stuff.
           'rect' contains width and height values that are multiple of 16: in
@@ -237,10 +265,12 @@ struct sn9c102_sensor {
                 frame after each HSYNC or VSYNC, so that the image starts with
                 real RGB data (see regs 0x12,0x13) (having set H_SIZE and,
                 V_SIZE you don't have to care about blank pixels or blank
-                lines at the end of each line or frame). */
+                lines at the end of each line or frame).
+       */
 
        struct v4l2_pix_format pix_format;
-       /* What you have to define here are: initial 'width' and 'height' of
+       /*
+          What you have to define here are: initial 'width' and 'height' of
           the target rectangle, the bayer 'pixelformat' and 'priv' which we'll
           be used to indicate the number of bits per pixel, 8 or 9. 
           Nothing more.
@@ -249,20 +279,27 @@ struct sn9c102_sensor {
                   suggest 1/1.
           NOTE 2: as said above, you have to program the SN9C10X chip to get
                   rid of any blank pixels, so that the output of the sensor
-                  matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). */
+                  matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
+       */
 
        const struct device* dev;
-       /* This is the argument for dev_err(), dev_info() and dev_warn(). It
+       /*
+          This is the argument for dev_err(), dev_info() and dev_warn(). It
           is used for debugging purposes. You must not access the struct
-          before the sensor is attached. */
+          before the sensor is attached.
+       */
 
        const struct usb_device* usbdev;
-       /* Points to the usb_device struct after the sensor is attached.
-          Do not touch unless you know what you are doing. */
+       /*
+          Points to the usb_device struct after the sensor is attached.
+          Do not touch unless you know what you are doing.
+       */
 
-       /* Do NOT write to the data below, it's READ ONLY. It is used by the
+       /*
+          Do NOT write to the data below, it's READ ONLY. It is used by the
           core module to store successfully updated values of the above
-          settings, for rollbacks..etc..in case of errors during atomic I/O */
+          settings, for rollbacks..etc..in case of errors during atomic I/O
+       */
        struct v4l2_queryctrl _qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE];
        struct v4l2_rect _rect;
 };
index d674700..68e1b2e 100644 (file)
@@ -33,15 +33,33 @@ static int tas5110c1b_init(struct sn9c102_device* cam)
        err += sn9c102_write_reg(cam, 0x44, 0x01);
        err += sn9c102_write_reg(cam, 0x00, 0x10);
        err += sn9c102_write_reg(cam, 0x00, 0x11);
-       err += sn9c102_write_reg(cam, 0x00, 0x14);
+       err += sn9c102_write_reg(cam, 0x0a, 0x14);
        err += sn9c102_write_reg(cam, 0x60, 0x17);
        err += sn9c102_write_reg(cam, 0x06, 0x18);
-       err += sn9c102_write_reg(cam, 0xcb, 0x19);
+       err += sn9c102_write_reg(cam, 0xfb, 0x19);
+
+       err += sn9c102_i2c_try_raw_write(cam, &tas5110c1b, 4, 0x11, 0x00, 0xc0,
+                                        0x80, 0, 0);
 
        return err;
 }
 
 
+static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, 
+                               const struct v4l2_control* ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               return sn9c102_i2c_try_raw_write(cam, &tas5110c1b, 4, 0x11,
+                                                0x02, 0x20,
+                                                0xff - (ctrl->value & 0xff),
+                                                0, 0);
+       default:
+               return -EINVAL;
+       }
+}
+
+
 static int tas5110c1b_set_crop(struct sn9c102_device* cam, 
                                const struct v4l2_rect* rect)
 {
@@ -53,6 +71,11 @@ static int tas5110c1b_set_crop(struct sn9c102_device* cam,
        err += sn9c102_write_reg(cam, h_start, 0x12);
        err += sn9c102_write_reg(cam, v_start, 0x13);
 
+       /* Don't change ! */
+       err += sn9c102_write_reg(cam, 0x14, 0x1a);
+       err += sn9c102_write_reg(cam, 0x0a, 0x1b);
+       err += sn9c102_write_reg(cam, 0xfb, 0x19);
+
        return err;
 }
 
@@ -60,7 +83,22 @@ static int tas5110c1b_set_crop(struct sn9c102_device* cam,
 static struct sn9c102_sensor tas5110c1b = {
        .name = "TAS5110C1B",
        .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_3WIRES,
        .init = &tas5110c1b_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 0x01,
+                       .default_value = 0x48,
+                       .flags = 0,
+               },
+       },
+       .set_ctrl = &tas5110c1b_set_ctrl,
        .cropcap = {
                .bounds = {
                        .left = 0,
@@ -90,8 +128,9 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
        /* This sensor has no identifiers, so let's attach it anyway */
        sn9c102_attach_sensor(cam, &tas5110c1b);
 
-       /* At the moment, only devices whose PID is 0x6005 have this sensor */
-       if (tas5110c1b.usbdev->descriptor.idProduct != 0x6005)
+       /* At the moment, sensor detection is based on USB pid/vid */
+       if (tas5110c1b.usbdev->descriptor.idProduct != 0x6001 &&
+           tas5110c1b.usbdev->descriptor.idProduct != 0x6005)
                return -ENODEV;
 
        return 0;
index 5f1b0f9..0bab194 100644 (file)
@@ -37,38 +37,45 @@ static int tas5130d1b_init(struct sn9c102_device* cam)
        err += sn9c102_write_reg(cam, 0x00, 0x14);
        err += sn9c102_write_reg(cam, 0x60, 0x17);
        err += sn9c102_write_reg(cam, 0x07, 0x18);
-       err += sn9c102_write_reg(cam, 0x33, 0x19);
 
        err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0x40,
                                         0x47, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x02, 0x20,
-                                        0xa9, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0xc0,
-                                        0x49, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x02, 0x20,
-                                        0x6c, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0xc0,
-                                        0x08, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0x20,
-                                        0x00, 0, 0);
-
-       err += sn9c102_write_reg(cam, 0x63, 0x19);
 
        return err;
 }
 
 
+static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, 
+                               const struct v4l2_control* ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               return sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11,
+                                                0x02, 0x20,
+                                                0xff - (ctrl->value & 0xff),
+                                                0, 0);
+       default:
+               return -EINVAL;
+       }
+}
+
+
 static int tas5130d1b_set_crop(struct sn9c102_device* cam, 
                                const struct v4l2_rect* rect)
 {
        struct sn9c102_sensor* s = &tas5130d1b;
-       int err = 0;
        u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
           v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
+       int err = 0;
 
        err += sn9c102_write_reg(cam, h_start, 0x12);
        err += sn9c102_write_reg(cam, v_start, 0x13);
 
+       /* Do NOT change! */
+       err += sn9c102_write_reg(cam, 0x1d, 0x1a);
+       err += sn9c102_write_reg(cam, 0x10, 0x1b);
+       err += sn9c102_write_reg(cam, 0xf3, 0x19);
+
        return err;
 }
 
@@ -79,6 +86,19 @@ static struct sn9c102_sensor tas5130d1b = {
        .frequency = SN9C102_I2C_100KHZ,
        .interface = SN9C102_I2C_3WIRES,
        .init = &tas5130d1b_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+       },
+       .set_ctrl = &tas5130d1b_set_ctrl,
        .cropcap = {
                .bounds = {
                        .left = 0,
@@ -108,13 +128,9 @@ int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
        /* This sensor has no identifiers, so let's attach it anyway */
        sn9c102_attach_sensor(cam, &tas5130d1b);
 
-       /* At the moment, only devices whose PID is 0x6025 have this sensor */
+       /* At the moment, sensor detection is based on USB pid/vid */
        if (tas5130d1b.usbdev->descriptor.idProduct != 0x6025)
                return -ENODEV;
 
-       dev_info(tas5130d1b.dev, "TAS5130D1B detected, but the support for it "
-                                "is disabled at the moment - needs further "
-                                "testing -\n");
-
-       return -ENODEV;
+       return 0;
 }
index b89b534..8cca7e7 100644 (file)
@@ -12,8 +12,6 @@
  * controllers available at: http://www.phidgets.com/ 
  *
  * Note that the driver takes input as: degrees.minutes
- * -23 < degrees < 203
- * 0 < minutes < 59
  *
  * CAUTION: Generally you should use 0 < degrees < 180 as anything else
  * is probably beyond the range of your servo and may damage it.
  * Jun 16, 2004: Sean Young <sean@mess.org>
  *  - cleanups
  *  - was using memory after kfree()
+ * Aug 8, 2004: Sean Young <sean@mess.org>
+ *  - set the highest angle as high as the hardware allows, there are 
+ *    some odd servos out there
+ *
  */
 
 #include <linux/config.h>
@@ -87,6 +89,9 @@ change_position_v30(struct phidget_servo *servo, int servo_no, int degrees,
        int retval;
        unsigned char *buffer;
 
+       if (degrees < -23 || degrees > 362)
+               return -EINVAL;
+
        buffer = kmalloc(6, GFP_KERNEL);
        if (!buffer) {
                dev_err(&servo->udev->dev, "%s - out of memory\n",
@@ -157,6 +162,9 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
        int retval;
        unsigned char *buffer;
 
+       if (degrees < -23 || degrees > 278)
+               return -EINVAL;
+
        buffer = kmalloc(2, GFP_KERNEL);
        if (!buffer) {
                dev_err(&servo->udev->dev, "%s - out of memory\n",
@@ -212,10 +220,8 @@ static ssize_t set_servo##value (struct device *dev,                       \
                return -EINVAL;                                         \
        }                                                               \
                                                                        \
-       if (degrees < -23 || degrees > (180 + 23) ||                    \
-           minutes < 0 || minutes > 59) {                              \
+       if (minutes < 0 || minutes > 59)                                \
                return -EINVAL;                                         \
-       }                                                               \
                                                                        \
        if (servo->type & SERVO_VERSION_30)                             \
                retval = change_position_v30 (servo, value, degrees,    \
index de9bf86..455fe6e 100644 (file)
@@ -242,7 +242,7 @@ static void catc_rx_done(struct urb *urb, struct pt_regs *regs)
 
        do {
                if(!catc->is_f5u011) {
-                       pkt_len = le16_to_cpup((u16*)pkt_start);
+                       pkt_len = le16_to_cpup((__le16*)pkt_start);
                        if (pkt_len > urb->actual_length) {
                                catc->stats.rx_length_errors++;
                                catc->stats.rx_errors++;
@@ -303,7 +303,7 @@ static void catc_irq_done(struct urb *urb, struct pt_regs *regs)
                else if (data[1] & 0x20)
                        linksts = LinkBad;
        } else {
-               hasdata = (unsigned int)(be16_to_cpup((u16*)data) & 0x0fff);
+               hasdata = (unsigned int)(be16_to_cpup((__be16*)data) & 0x0fff);
                if (data[0] == 0x90)
                        linksts = LinkGood;
                else if (data[0] == 0xA0)
index 245740e..d01ec7b 100644 (file)
@@ -17,7 +17,7 @@
                unsigned short  Addr;
                unsigned short  Len;
                unsigned char   Data[0];
-       } __attribute ((packed));
+       } __attribute__ ((packed));
 
        struct edge_firmware_version_info {
                unsigned char   MajorVersion;
@@ -36,11 +36,11 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
 
 // Segment #1, Start Address 00ff0000, Length 6
 0xff,0x00,0x00,0x00,0x06,0x00,
-    0x02, 0x00, 0x80, 0x02, 0x49, 0x39
+    0x02, 0x00, 0x80, 0x02, 0x44, 0xb0
 
 // Segment #2, Start Address 00ff000b, Length 3
 0xff,0x00,0x0b,0x00,0x03,0x00,
-    0x02, 0x44, 0x1a
+    0x02, 0x44, 0x72
 
 // Segment #3, Start Address 00ff0013, Length 3
 0xff,0x00,0x13,0x00,0x03,0x00,
@@ -72,11 +72,11 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
 
 // Segment #10, Start Address 00ff004b, Length 3
 0xff,0x00,0x4b,0x00,0x03,0x00,
-    0x02, 0x70, 0xd4, 
+    0x02, 0x6e, 0xc4, 
 
 // Segment #11, Start Address 00ff0053, Length 3
 0xff,0x00,0x53,0x00,0x03,0x00,
-    0x02, 0x77, 0x9d, 
+    0x02, 0x75, 0x8d, 
 
 // Segment #12, Start Address 00ff007b, Length 3
 0xff,0x00,0x7b,0x00,0x03,0x00,
@@ -86,657 +86,745 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
 0xff,0x00,0x80,0x00,0x07,0x00,
     0x7e, 0x14, 0x00, 0x00, 0x02, 0x40, 0x51, 
 
-// Segment #14, Start Address 00ff4000, Length 15920
-0xff,0x00,0x00,0x40,0x30,0x3e,
+// Segment #14, Start Address 00ff3000, Length 2178
+0xff,0x00,0x00,0x30,0x82,0x08,
+    0x12, 0x37, 0x28, 0x12, 0x30, 0x3e, 0x12, 0x30, 0x54, 0x12, 0x30, 0xe5, 0x12, 0x31, 0x68, 0x12, 
+    0x35, 0x20, 0x12, 0x38, 0x58, 0x12, 0x31, 0x15, 0x12, 0x31, 0x40, 0x12, 0x30, 0xa0, 0x80, 0xe0, 
+    0xe5, 0x23, 0x60, 0x19, 0x7e, 0x14, 0x00, 0x00, 0x09, 0xb1, 0x01, 0xcf, 0xb4, 0x00, 0x02, 0x80, 
+    0x05, 0x14, 0x19, 0xb1, 0x01, 0xcf, 0xa5, 0x0b, 0xbe, 0x31, 0x2f, 0x78, 0xeb, 0x22, 0xc2, 0xaf, 
+    0x7e, 0xb3, 0x3f, 0xf1, 0xb4, 0x01, 0x0a, 0xc0, 0xf1, 0x75, 0xf1, 0x02, 0x12, 0x70, 0xef, 0xd0, 
+    0xf1, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x22, 0x60, 0x43, 0x7e, 0x07, 0x01, 0xe1, 0xbe, 0x04, 
+    0x03, 0x80, 0x38, 0x39, 0x7e, 0x04, 0x80, 0x00, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x21, 0x09, 0xa0, 
+    0x00, 0x04, 0x4e, 0xa0, 0x05, 0x19, 0xa0, 0x00, 0x04, 0x0a, 0x32, 0x09, 0x53, 0x67, 0x8e, 0x5e, 
+    0x51, 0x27, 0x68, 0x0b, 0x09, 0xa0, 0x00, 0x10, 0x4e, 0xa0, 0x01, 0x19, 0xa0, 0x00, 0x10, 0x2e, 
+    0x04, 0x01, 0x00, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xd1, 0x75, 0x22, 0x00, 0xd2, 0xaf, 0x22, 
+    0xc2, 0xaf, 0x7e, 0x20, 0x00, 0x7e, 0x30, 0x01, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x32, 0x01, 
+    0x8f, 0xbe, 0x34, 0x00, 0x00, 0x68, 0x12, 0x7e, 0xb1, 0x21, 0xa5, 0x4b, 0x7a, 0xb1, 0x21, 0xca, 
+    0x19, 0x49, 0x22, 0x30, 0xd5, 0x99, 0x24, 0xda, 0x19, 0x3e, 0x30, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 
+    0x78, 0xd6, 0xd2, 0xaf, 0x22, 0x46, 0x0f, 0x49, 0x67, 0x4c, 0xbf, 0x50, 0x17, 0x53, 0x6f, 0x56, 
+    0xc7, 0x5a, 0x1f, 0x5d, 0x77, 0xc2, 0xaf, 0xe5, 0x32, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 
+    0x07, 0xca, 0xb8, 0x12, 0x31, 0x02, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 
+    0xaf, 0x22, 0xca, 0x28, 0x12, 0x67, 0xab, 0xda, 0x28, 0x40, 0x09, 0x0a, 0x22, 0x09, 0xb2, 0x67, 
+    0x8e, 0xf4, 0x52, 0x32, 0x22, 0xc2, 0xaf, 0xe5, 0x34, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 
+    0x07, 0xca, 0xb8, 0x12, 0x31, 0x32, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 
+    0xaf, 0x22, 0xca, 0x28, 0x0a, 0x22, 0x09, 0x42, 0x00, 0x3e, 0x12, 0x69, 0xc2, 0xda, 0x28, 0x22, 
+    0xc2, 0xaf, 0xe5, 0x35, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x31, 
+    0x5d, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 0xaf, 0x22, 0xca, 0x28, 0x7e, 
+    0x40, 0x00, 0x12, 0x6c, 0x5b, 0xda, 0x28, 0x22, 0xc2, 0xaf, 0xe5, 0x23, 0x60, 0x14, 0x7e, 0x20, 
+    0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x31, 0x85, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 
+    0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x31, 0x90, 0x89, 0x24, 
+    0x31, 0xa0, 0x32, 0x10, 0x32, 0x80, 0x32, 0xf0, 0x33, 0x60, 0x33, 0xd0, 0x34, 0x40, 0x34, 0xb0, 
+    0x7e, 0x27, 0x01, 0x8f, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x49, 0x30, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0x9f, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x9f, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xcf, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xcf, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x18, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xcf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x91, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x4c, 0x88, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa1, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa1, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd0, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd0, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x19, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd0, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x93, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x82, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x4f, 0xe0, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa3, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa3, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd1, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd1, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1a, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd1, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x95, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x53, 0x38, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa5, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa5, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd2, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd2, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1b, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd2, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x97, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x56, 0x90, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa7, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa7, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd3, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd3, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1c, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd3, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x99, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x59, 0xe8, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa9, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa9, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd4, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd4, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1d, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd4, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x9b, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x5d, 0x40, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xab, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xab, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd5, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd5, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1e, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd5, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x9d, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x87, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x60, 0x98, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xad, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xad, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd6, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd6, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1f, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd6, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0xc2, 0xaf, 0xe5, 0x24, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x35, 
+    0x3d, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 
+    0x0a, 0x2b, 0x49, 0x22, 0x35, 0x48, 0x89, 0x24, 0x35, 0x58, 0x35, 0x92, 0x35, 0xcc, 0x36, 0x06, 
+    0x36, 0x40, 0x36, 0x7a, 0x36, 0xb4, 0x36, 0xee, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, 0x14, 
+    0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x49, 0x30, 
+    0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 
+    0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x20, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 
+    0xf1, 0x22, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 
+    0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4c, 0x88, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 
+    0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 
+    0x21, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x82, 0x00, 
+    0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 
+    0x12, 0x12, 0x4f, 0xe0, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 
+    0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x22, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 
+    0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 
+    0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x53, 0x38, 0x7d, 0x21, 
+    0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 
+    0x12, 0x7c, 0x15, 0xc2, 0x23, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 
+    0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x56, 0x90, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 
+    0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x24, 0xc0, 
+    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x59, 0xe8, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 
+    0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x25, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 
+    0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 
+    0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5d, 0x40, 0x7d, 0x21, 0xda, 0x19, 
+    0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 
+    0x15, 0xc2, 0x26, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 
+    0x87, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 
+    0x19, 0x7d, 0x12, 0x12, 0x60, 0x98, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 
+    0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x27, 0xc0, 0xf1, 0x75, 
+    0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0xc2, 0xaf, 0xe5, 0x33, 0x60, 0x14, 0x7e, 0x20, 
+    0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x37, 0x45, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 
+    0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x37, 0x50, 0x89, 0x24, 
+    0x37, 0x60, 0x37, 0x7f, 0x37, 0x9e, 0x37, 0xbd, 0x37, 0xdc, 0x37, 0xfb, 0x38, 0x1a, 0x38, 0x39, 
+    0x7e, 0x24, 0x80, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x48, 0x1b, 0xda, 0x19, 0x10, 0x04, 0x02, 
+    0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 
+    0x24, 0x81, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4b, 0x73, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 
+    0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 
+    0x82, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4e, 0xcb, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 
+    0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x83, 
+    0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x52, 0x23, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 
+    0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x84, 0x00, 
+    0xca, 0x19, 0x7d, 0x12, 0x12, 0x55, 0x7b, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 
+    0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x85, 0x00, 0xca, 
+    0x19, 0x7d, 0x12, 0x12, 0x58, 0xd3, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, 
+    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x86, 0x00, 0xca, 0x19, 
+    0x7d, 0x12, 0x12, 0x5c, 0x2b, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 
+    0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x87, 0x00, 0xca, 0x19, 0x7d, 
+    0x12, 0x12, 0x5f, 0x83, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, 
+    0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0xc2, 0xaf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0xa9, 
+    0x32, 0xf2, 0x1a, 0x7e, 0x07, 0x01, 0xe1, 0xbe, 0x04, 0x00, 0x00, 0x78, 0x10, 0xe5, 0xf5, 0x33, 
+    0x82, 0xe7, 0x40, 0x09, 0x85, 0x31, 0x31, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x00, 0xd0, 0xf1, 0xd2, 
+    0xaf, 0x22, 
+
+// Segment #15, Start Address 00ff4000, Length 15381
+0xff,0x00,0x00,0x40,0x15,0x3c,
     0x7e, 0x04, 0x00, 0x01, 0x7e, 0x14, 0x7f, 0xf8, 0x7e, 0x24, 0x00, 0xfe, 0x7d, 0x31, 0x0b, 0x1a, 
-    0x50, 0x1b, 0x0a, 0x50, 0x7e, 0x14, 0x40, 0x1b, 0x02, 0x40, 0x6a, 0x7e, 0xf8, 0x00, 0x59, 0xd2, 
-    0x04, 0xc2, 0x94, 0xd2, 0x95, 0x7e, 0xf4, 0x40, 0x2c, 0x02, 0x40, 0x7c, 0x12, 0x7f, 0x3f, 0xf5, 
-    0x2e, 0x7a, 0xa1, 0x2d, 0x7a, 0x11, 0x58, 0x12, 0x77, 0xda, 0x12, 0x40, 0xdc, 0x7e, 0xb3, 0x3f, 
-    0xf1, 0x60, 0x03, 0x12, 0x43, 0x68, 0x75, 0xf1, 0x00, 0x12, 0x78, 0x7f, 0xd2, 0xaf, 0x02, 0x44
-    0x06, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x5f, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xa9, 
+    0x50, 0x1b, 0x0a, 0x50, 0x7e, 0x14, 0x40, 0x1b, 0x02, 0x40, 0x6a, 0x7e, 0xf8, 0x00, 0x6f, 0xd2, 
+    0x04, 0xc2, 0x94, 0xd2, 0x95, 0x7e, 0xf4, 0x40, 0x2c, 0x02, 0x40, 0x7c, 0x12, 0x7d, 0x30, 0xf5, 
+    0x2f, 0x7a, 0xa1, 0x30, 0x7a, 0x11, 0x6e, 0x12, 0x75, 0xca, 0x12, 0x40, 0xdc, 0x7e, 0xb3, 0x3f, 
+    0xf1, 0x60, 0x03, 0x12, 0x43, 0xd4, 0x75, 0xf1, 0x00, 0x12, 0x76, 0x6f, 0xd2, 0xaf, 0x02, 0x30
+    0x00, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x5f, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xa9, 
     0x25, 0x87, 0x03, 0xa9, 0xd5, 0x87, 0xd2, 0x93, 0x89, 0x08, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 
     0x40, 0x78, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xc2, 0x93, 0x89, 0x08, 0x7e, 0x08, 0x00, 0x20, 
-    0x7e, 0x44, 0x04, 0x00, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0x8e, 0x02, 0x7e, 0x4b, 0x7e, 0x08, 
-    0x01, 0x59, 0x7e, 0x44, 0x28, 0x7c, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0xa0, 0x02, 0x7e, 0x4b
-    0x7e, 0x08, 0x00, 0x59, 0x7e, 0x44, 0x01, 0x00, 0x7e, 0x40, 0x53, 0x7e, 0xe4, 0x40, 0xb2, 0x02, 
-    0x7e, 0x4b, 0x75, 0x57, 0x20, 0x75, 0x56, 0x30, 0x7e, 0x04, 0x00, 0x08, 0x75, 0x54, 0x58, 0x75, 
-    0x55, 0x08, 0x75, 0x51, 0x08, 0x75, 0x53, 0x01, 0x75, 0x89, 0x01, 0x75, 0x8a, 0x01, 0x75, 0x8c, 
-    0x00, 0xd2, 0x8c, 0x7e, 0x04, 0x00, 0x02, 0x7a, 0x05, 0x42, 0x89, 0xf4, 0x75, 0xb7, 0x7f, 0x75, 
+    0x7e, 0x44, 0x04, 0x00, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0x8e, 0x02, 0x7c, 0x30, 0x7e, 0x08, 
+    0x01, 0x6f, 0x7e, 0x44, 0x28, 0x7c, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0xa0, 0x02, 0x7c, 0x30
+    0x7e, 0x08, 0x00, 0x6f, 0x7e, 0x44, 0x01, 0x00, 0x7e, 0x40, 0x53, 0x7e, 0xe4, 0x40, 0xb2, 0x02, 
+    0x7c, 0x30, 0x75, 0x6d, 0x20, 0x75, 0x6c, 0x30, 0x7e, 0x04, 0x00, 0x08, 0x75, 0x6a, 0x58, 0x75, 
+    0x6b, 0x08, 0x75, 0x67, 0x08, 0x75, 0x69, 0x01, 0x75, 0x89, 0x01, 0x75, 0x8a, 0x01, 0x75, 0x8c, 
+    0x00, 0xd2, 0x8c, 0x7e, 0x04, 0x00, 0x02, 0x7a, 0x05, 0x58, 0x89, 0xf4, 0x75, 0xb7, 0x7f, 0x75, 
     0xb8, 0x7f, 0x75, 0xb3, 0x07, 0x75, 0xb2, 0x07, 0xd2, 0xa9, 0x22, 0xd2, 0x92, 0xe4, 0xd5, 0xe0, 
-    0xfd, 0xc2, 0x92, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x2e, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, 
-    0x10, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xf2, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x72, 0x0b, 0x20, 
-    0xbe, 0x21, 0x2e, 0x78, 0xf6, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x74, 0xbf, 0x19, 0xb0, 
+    0xfd, 0xc2, 0x92, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x2f, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, 
+    0x10, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xf2, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x7e, 0x0b, 0x20, 
+    0xbe, 0x21, 0x2f, 0x78, 0xf6, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x74, 0xbf, 0x19, 0xb0, 
     0x00, 0x0c, 0x74, 0x10, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x80, 0x19, 0xb0, 0x00, 0x0c, 0x7e, 0x54, 
     0x00, 0x02, 0x19, 0xa0, 0x00, 0x04, 0x19, 0xb0, 0x00, 0x00, 0x74, 0x03, 0x19, 0xb0, 0x00, 0x0c, 
-    0x74, 0x07, 0x20, 0x68, 0x02, 0x74, 0x0f, 0x19, 0xb0, 0x00, 0x04, 0x30, 0x6b, 0x17, 0x74, 0xbf, 
-    0x19, 0xb0, 0x00, 0x0c, 0x74, 0x28, 0x20, 0x68, 0x02, 0x74, 0x20, 0x19, 0xb0, 0x00, 0x04, 0x74, 
-    0x03, 0x19, 0xb0, 0x00, 0x0c, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x0c, 0x19, 0xb0, 0x00, 
-    0x10, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0xe4, 0x19, 0xb0, 0x00, 0x04, 0x09, 0xb0, 0x00, 
-    0x10, 0x54, 0x08, 0x19, 0xb0, 0x00, 0x10, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x22, 0x7c, 0xb2, 
-    0x23, 0x0a, 0x2b, 0x49, 0x22, 0x41, 0x99, 0x89, 0x24, 0x41, 0xa9, 0x41, 0xc6, 0x41, 0xe3, 0x42, 
-    0x00, 0x42, 0x1d, 0x42, 0x3a, 0x42, 0x57, 0x42, 0x74, 0xc2, 0x10, 0xc2, 0x18, 0xc2, 0x08, 0x7e, 
-    0x04, 0x09, 0xcd, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 0x01, 0x69, 0x6d, 0x00, 0x7a, 0x07, 0x01, 
-    0x79, 0x7a, 0x07, 0x01, 0x89, 0x22, 0xc2, 0x11, 0xc2, 0x19, 0xc2, 0x09, 0x7e, 0x04, 0x0d, 0xcd, 
-    0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 0x07, 
-    0x01, 0x8b, 0x22, 0xc2, 0x12, 0xc2, 0x1a, 0xc2, 0x0a, 0x7e, 0x04, 0x11, 0xcd, 0x7a, 0x07, 0x01, 
-    0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7d, 0x7a, 0x07, 0x01, 0x8d, 0x22, 
-    0xc2, 0x13, 0xc2, 0x1b, 0xc2, 0x0b, 0x7e, 0x04, 0x15, 0xcd, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 0x07, 
-    0x01, 0x6f, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7f, 0x7a, 0x07, 0x01, 0x8f, 0x22, 0xc2, 0x14, 0xc2, 
-    0x1c, 0xc2, 0x0c, 0x7e, 0x04, 0x19, 0xcd, 0x7a, 0x07, 0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 0x6d, 
-    0x00, 0x7a, 0x07, 0x01, 0x81, 0x7a, 0x07, 0x01, 0x91, 0x22, 0xc2, 0x15, 0xc2, 0x1d, 0xc2, 0x0d, 
-    0x7e, 0x04, 0x1d, 0xcd, 0x7a, 0x07, 0x01, 0x63, 0x7a, 0x07, 0x01, 0x73, 0x6d, 0x00, 0x7a, 0x07, 
-    0x01, 0x83, 0x7a, 0x07, 0x01, 0x93, 0x22, 0xc2, 0x16, 0xc2, 0x1e, 0xc2, 0x0e, 0x7e, 0x04, 0x21, 
-    0xcd, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x85, 0x7a, 
-    0x07, 0x01, 0x95, 0x22, 0xc2, 0x17, 0xc2, 0x1f, 0xc2, 0x0f, 0x7e, 0x04, 0x25, 0xcd, 0x7a, 0x07, 
-    0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x87, 0x7a, 0x07, 0x01, 0x97, 
-    0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x42, 0x9c, 0x89, 0x24, 0x42, 0xac, 0x42, 0xc3, 
-    0x42, 0xda, 0x42, 0xf1, 0x43, 0x08, 0x43, 0x1f, 0x43, 0x36, 0x43, 0x4d, 0x30, 0x40, 0x07, 0x20, 
-    0x58, 0x04, 0xc2, 0x28, 0x80, 0x0c, 0x30, 0x48, 0x07, 0x20, 0x50, 0x04, 0xc2, 0x28, 0x80, 0x02, 
-    0xd2, 0x28, 0x22, 0x30, 0x41, 0x07, 0x20, 0x59, 0x04, 0xc2, 0x29, 0x80, 0x0c, 0x30, 0x49, 0x07, 
-    0x20, 0x51, 0x04, 0xc2, 0x29, 0x80, 0x02, 0xd2, 0x29, 0x22, 0x30, 0x42, 0x07, 0x20, 0x5a, 0x04, 
-    0xc2, 0x2a, 0x80, 0x0c, 0x30, 0x4a, 0x07, 0x20, 0x52, 0x04, 0xc2, 0x2a, 0x80, 0x02, 0xd2, 0x2a, 
-    0x22, 0x30, 0x43, 0x07, 0x20, 0x5b, 0x04, 0xc2, 0x2b, 0x80, 0x0c, 0x30, 0x4b, 0x07, 0x20, 0x53, 
-    0x04, 0xc2, 0x2b, 0x80, 0x02, 0xd2, 0x2b, 0x22, 0x30, 0x44, 0x07, 0x20, 0x5c, 0x04, 0xc2, 0x2c, 
-    0x80, 0x0c, 0x30, 0x4c, 0x07, 0x20, 0x54, 0x04, 0xc2, 0x2c, 0x80, 0x02, 0xd2, 0x2c, 0x22, 0x30, 
-    0x45, 0x07, 0x20, 0x5d, 0x04, 0xc2, 0x2d, 0x80, 0x0c, 0x30, 0x4d, 0x07, 0x20, 0x55, 0x04, 0xc2, 
-    0x2d, 0x80, 0x02, 0xd2, 0x2d, 0x22, 0x30, 0x46, 0x07, 0x20, 0x5e, 0x04, 0xc2, 0x2e, 0x80, 0x0c, 
-    0x30, 0x4e, 0x07, 0x20, 0x56, 0x04, 0xc2, 0x2e, 0x80, 0x02, 0xd2, 0x2e, 0x22, 0x30, 0x47, 0x07, 
-    0x20, 0x5f, 0x04, 0xc2, 0x2f, 0x80, 0x0c, 0x30, 0x4f, 0x07, 0x20, 0x57, 0x04, 0xc2, 0x2f, 0x80, 
-    0x02, 0xd2, 0x2f, 0x22, 0x43, 0xcc, 0x43, 0x79, 0xbe, 0xb0, 0x02, 0x40, 0x01, 0x22, 0x23, 0x0a, 
-    0x5b, 0x49, 0x55, 0x43, 0x64, 0x99, 0x54, 0xd3, 0x22, 0xa9, 0xc5, 0x87, 0x12, 0x43, 0xd7, 0x7e, 
-    0x04, 0x05, 0xcd, 0x7a, 0x07, 0x01, 0xc1, 0x7a, 0x07, 0x01, 0xc3, 0x7e, 0x04, 0x01, 0xcd, 0x7a, 
-    0x07, 0x01, 0xc7, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x04, 0x76, 0xbd, 0x7a, 0x05, 0x4b, 0x75, 0xf1, 
-    0x01, 0x75, 0xe1, 0x1f, 0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x75, 0xf1, 0x02, 0x75, 0xe1, 0x03, 
-    0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x43, 0xa2, 0x1c, 0x12, 0x40, 0xeb, 0x7e, 0x20, 0x00, 0x12, 
-    0x41, 0x8e, 0x0b, 0x20, 0xbe, 0x21, 0x2e, 0x78, 0xf6, 0xd2, 0xa8, 0x22, 0xa9, 0xd5, 0x87, 0x12, 
-    0x43, 0xd7, 0xd2, 0x92, 0xc2, 0xa8, 0x22, 0x75, 0xa3, 0x00, 0x53, 0xa2, 0x03, 0x75, 0xc1, 0x00, 
-    0x53, 0xc0, 0x03, 0x7e, 0x00, 0x05, 0x7a, 0x01, 0xf1, 0x43, 0xf4, 0x80, 0x43, 0xe4, 0x80, 0xe5, 
-    0xf2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xf2, 0xe5, 0xe2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xe2, 0x75, 
-    0xe1, 0x10, 0xa5, 0xd8, 0xe1, 0x22, 0x12, 0x44, 0x76, 0x12, 0x44, 0x8c, 0x12, 0x45, 0x27, 0x12, 
-    0x45, 0x57, 0x12, 0x49, 0x0f, 0x12, 0x44, 0xd8, 0x80, 0xec, 0xca, 0x09, 0x12, 0x44, 0x58, 0x10, 
-    0x01, 0x12, 0xd5, 0x51, 0x1e, 0x63, 0x53, 0x01, 0x7e, 0x00, 0x54, 0x2e, 0x01, 0x53, 0xa5, 0xe6, 
-    0xf5, 0x51, 0x80, 0x12, 0x20, 0x02, 0x1e, 0x75, 0x53, 0x00, 0x85, 0x54, 0x51, 0xd2, 0x02, 0x74, 
-    0x00, 0x80, 0x0d, 0x30, 0x02, 0x0f, 0xc2, 0x02, 0x7e, 0x00, 0x56, 0x2e, 0x01, 0x53, 0xa5, 0xe6, 
-    0x53, 0x90, 0xcf, 0x42, 0x90, 0xda, 0x09, 0x32, 0xe5, 0x23, 0x60, 0x19, 0x7e, 0x14, 0x00, 0x00, 
-    0x09, 0xb1, 0x01, 0xb9, 0xb4, 0x00, 0x02, 0x80, 0x05, 0x14, 0x19, 0xb1, 0x01, 0xb9, 0xa5, 0x0a, 
-    0xbe, 0x21, 0x2e, 0x78, 0xeb, 0x22, 0xc2, 0xaf, 0x7e, 0xb3, 0x3f, 0xf1, 0xb4, 0x01, 0x0a, 0xc0, 
-    0xf1, 0x75, 0xf1, 0x02, 0x12, 0x72, 0xff, 0xd0, 0xf1, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x22, 
-    0x60, 0x43, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, 0x03, 0x80, 0x38, 0x39, 0x7e, 0x04, 0x80, 0x00, 
-    0x7e, 0x20, 0x00, 0x13, 0x50, 0x21, 0x09, 0xa0, 0x00, 0x04, 0x4e, 0xa0, 0x05, 0x19, 0xa0, 0x00, 
-    0x04, 0x0a, 0x32, 0x09, 0x53, 0x6a, 0x93, 0x5e, 0x51, 0x27, 0x68, 0x0b, 0x09, 0xa0, 0x00, 0x10, 
-    0x4e, 0xa0, 0x01, 0x19, 0xa0, 0x00, 0x10, 0x2e, 0x04, 0x01, 0x00, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 
-    0x78, 0xd1, 0x75, 0x22, 0x00, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x26, 0x60, 0x36, 0x7e, 0x20, 
-    0x00, 0x7e, 0x30, 0x01, 0xe5, 0x26, 0xa5, 0x5b, 0x68, 0x21, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 
-    0x32, 0x01, 0x79, 0xbe, 0x34, 0x00, 0x00, 0x68, 0x12, 0x7e, 0xb1, 0x21, 0xa5, 0x4b, 0x7a, 0xb1, 
-    0x21, 0xca, 0x19, 0x49, 0x22, 0x45, 0x17, 0x99, 0x24, 0xda, 0x19, 0x3e, 0x30, 0xa5, 0x0a, 0xbe, 
-    0x21, 0x2e, 0x78, 0xd0, 0xd2, 0xaf, 0x22, 0x4a, 0x98, 0x4d, 0xcd, 0x51, 0x02, 0x54, 0x37, 0x57, 
-    0x6c, 0x5a, 0xa1, 0x5d, 0xd6, 0x61, 0x0b, 0xc2, 0xaf, 0xe5, 0x24, 0x60, 0x14, 0x7e, 0x20, 0x00, 
-    0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x45, 0x44, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 
-    0xef, 0xd2, 0xaf, 0x22, 0xca, 0x28, 0x12, 0x6a, 0xac, 0xda, 0x28, 0x40, 0x09, 0x0a, 0x22, 0x09, 
-    0xb2, 0x6a, 0x93, 0xf4, 0x52, 0x24, 0x22, 0xc2, 0xaf, 0xe5, 0x23, 0x60, 0x14, 0x7e, 0x20, 0x00, 
-    0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x45, 0x74, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 
-    0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x45, 0x7f, 0x89, 0x24, 0x45, 
-    0x8f, 0x45, 0xff, 0x46, 0x6f, 0x46, 0xdf, 0x47, 0x4f, 0x47, 0xbf, 0x48, 0x2f, 0x48, 0x9f, 0x7e, 
-    0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4d, 
-    0x96, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x89, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x89, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xb9, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xb9, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x18, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xb9, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x7b, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x50, 
-    0xcb, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x8b, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8b, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xba, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xba, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x19, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xba, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x7d, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x82, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x54, 
-    0x00, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x8d, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8d, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbb, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbb, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1a, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbb, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x57, 
-    0x35, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x8f, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8f, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbc, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbc, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1b, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbc, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x81, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5a, 
-    0x6a, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x91, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x91, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbd, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbd, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1c, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbd, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5d, 
-    0x9f, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x93, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x93, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbe, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbe, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1d, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbe, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x85, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x60, 
-    0xd4, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x95, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x95, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbf, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbf, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1e, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x87, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x87, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x64, 
-    0x09, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x97, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x97, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xc0, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xc0, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1f, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xc0, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0xc2, 
-    0xaf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0xa9, 0x32, 0xf2, 0x1a, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, 
-    0x00, 0x00, 0x78, 0x10, 0xe5, 0xf5, 0x33, 0x82, 0xe7, 0x40, 0x09, 0x85, 0x31, 0x2f, 0x12, 0x7e, 
-    0x30, 0x75, 0xf6, 0x00, 0xd0, 0xf1, 0xd2, 0xaf, 0x22, 0xc0, 0xd0, 0xc0, 0xd1, 0xc0, 0xe0, 0xc0, 
-    0xf0, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xd2, 0x01, 0x75, 0x2f, 0x89, 0x12, 0x7e, 0x30, 0x7e, 
-    0x14, 0x80, 0x00, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x49, 0xd8, 0x20, 0x70, 0x5a, 
-    0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x49, 0xf0, 0x20, 0x71, 0x4b, 0xa5, 
-    0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x08, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 
-    0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x20, 0x20, 0x72, 0x30, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 
-    0x20, 0xe0, 0x03, 0x02, 0x4a, 0x38, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 
-    0x4a, 0x50, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x68, 0xa5, 0x0a, 
-    0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x80, 0x30, 0x04, 0x0c, 0xc2, 0x04, 0xc0, 
-    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0xd0, 
-    0xf0, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 0x32, 0x75, 0x2f, 0x80, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x66, 0x34, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x81, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x66, 0x74, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x82, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x66, 0xb4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x83, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x66, 0xf4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x84, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x67, 0x34, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x85, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x67, 0x74, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x86, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x67, 0xb4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x87, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x67, 0xf4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x10, 0x08, 0x01, 0x22, 0x20, 0x28, 0x03, 0xd2, 
-    0x08, 0x22, 0x75, 0x2f, 0xa0, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x80, 0x00, 0x80, 0x06, 0x20, 0x28, 
-    0x03, 0xd2, 0x08, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 
-    0x03, 0x12, 0x4d, 0x96, 0x30, 0x30, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x08, 0x22, 0x30, 0xe6, 0x02, 
-    0xd2, 0x60, 0x7e, 0x37, 0x01, 0x79, 0x7e, 0x27, 0x01, 0x99, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 
-    0x2e, 0x05, 0x32, 0x7a, 0x05, 0x32, 0x7a, 0x37, 0x01, 0x79, 0x7e, 0x37, 0x01, 0x59, 0x7d, 0x43, 
-    0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x59, 0x75, 0x2f, 0x94, 0x12, 
-    0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x60, 0xc4, 0x22, 0xc2, 
-    0x60, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, 
-    0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x99, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x99, 0x7e, 0x37, 0x01, 
-    0x79, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x32, 0x7a, 0x05, 0x32, 0x7a, 0x37, 0x01, 0x79, 0x7e, 
-    0x37, 0x01, 0x59, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 
-    0x59, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x0d, 0xcd, 
-    0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x09, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 
-    0x59, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4b, 0x0b, 0x22, 0xd2, 0x08, 0x7e, 
-    0x04, 0x09, 0xcd, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 0x01, 0x69, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
-    0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 
-    0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 
-    0x7e, 0x27, 0x01, 0xa9, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 
-    0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 
-    0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 
-    0x00, 0x00, 0x2e, 0x27, 0x01, 0xa9, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 
-    0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x38, 0x0a, 0x09, 
-    0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0x80, 0x7f, 0x7a, 0x51, 
-    0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x00, 0x00, 0x2e, 0x67, 
-    0x01, 0xa9, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 
-    0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 
-    0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 
-    0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x00, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 
-    0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 
-    0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 
-    0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 
-    0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 
-    0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 
-    0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 
-    0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 
-    0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 
-    0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x4c, 0x6f, 0x75, 
-    0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 
-    0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0xda, 
-    0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4c, 0x6f, 0xda, 0xb8, 0x02, 
-    0x4d, 0x96, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 
-    0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 
-    0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 
-    0x50, 0x80, 0x02, 0xc2, 0x50, 0x12, 0x42, 0xac, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 
-    0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 
-    0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 
-    0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 
-    0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4c, 0xc3, 0x75, 
-    0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x09, 0x01, 
-    0x22, 0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x75, 0x2f, 0xa1, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x81, 
-    0x00, 0x80, 0x06, 0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 
-    0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x50, 0xcb, 0x30, 0x31, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 
-    0x09, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x61, 0x7e, 0x37, 0x01, 0x7b, 0x7e, 0x27, 0x01, 0x9b, 0x9d, 
-    0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, 0x7a, 0x37, 0x01, 0x7b, 0x7e, 
-    0x37, 0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 
-    0x5b, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 
-    0x10, 0x61, 0xc4, 0x22, 0xc2, 0x61, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 
-    0x01, 0x7b, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9b, 0x28, 0x04, 0x7e, 0x27, 
-    0x01, 0x9b, 0x7e, 0x37, 0x01, 0x7b, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, 
-    0x7a, 0x37, 0x01, 0x7b, 0x7e, 0x37, 0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xcc, 
-    0x38, 0x13, 0x7a, 0x47, 0x01, 0x5b, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 
-    0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0x9e, 0x44, 0x11, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x0d, 0xcd, 0x7d, 0x24, 
-    0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5b, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4e, 
-    0x40, 0x22, 0xd2, 0x09, 0x7e, 0x04, 0x0d, 0xcd, 0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 
-    0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 
-    0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xab, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 
-    0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 
-    0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 
-    0x47, 0x01, 0xc9, 0x7e, 0x24, 0x01, 0x00, 0x2e, 0x27, 0x01, 0xab, 0x1b, 0x38, 0x20, 0x0b, 0x35, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 
-    0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 
-    0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 
-    0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 
-    0x64, 0x01, 0x00, 0x2e, 0x67, 0x01, 0xab, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 
-    0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 
-    0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 
-    0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x01, 0x7a, 
-    0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 
-    0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 
-    0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 
-    0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 
-    0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 
-    0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 
-    0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 
-    0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 
-    0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 
-    0xe7, 0x02, 0x4f, 0xa4, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 
-    0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 
-    0x10, 0xd2, 0x11, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 
-    0x4f, 0xa4, 0xda, 0xb8, 0x02, 0x50, 0xcb, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 
-    0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 
-    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0xa5, 0xfd, 0x5e, 
-    0x50, 0x80, 0x68, 0x04, 0xd2, 0x51, 0x80, 0x02, 0xc2, 0x51, 0x12, 0x42, 0xc3, 0x02, 0x65, 0x9c, 
-    0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 
-    0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 
-    0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 
-    0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 
-    0x22, 0x02, 0x4f, 0xf8, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 
-    0x30, 0x22, 0x10, 0x0a, 0x01, 0x22, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x75, 0x2f, 0xa2, 0x12, 
-    0x7e, 0x30, 0x7e, 0x14, 0x82, 0x00, 0x80, 0x06, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x09, 0xb1, 
-    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x54, 0x00, 0x30, 0x32, 
-    0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0a, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x62, 0x7e, 0x37, 0x01, 0x7d, 
-    0x7e, 0x27, 0x01, 0x9d, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x36, 0x7a, 0x05, 0x36, 
-    0x7a, 0x37, 0x01, 0x7d, 0x7e, 0x37, 0x01, 0x5d, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xcc, 
-    0x38, 0x68, 0x7a, 0x47, 0x01, 0x5d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 
-    0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x62, 0xc4, 0x22, 0xc2, 0x62, 0x2d, 0x23, 0x68, 0x78, 0x6d, 
-    0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7d, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 
-    0x9d, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 
-    0x05, 0x36, 0x7a, 0x05, 0x36, 0x7a, 0x37, 0x01, 0x7d, 0x7e, 0x37, 0x01, 0x5d, 0x7d, 0x43, 0x2d, 
-    0x42, 0xbe, 0x44, 0x15, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
-    0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x15, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 
-    0x34, 0x11, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5d, 0x12, 0x68, 0x34, 0xbe, 0x25, 
-    0x20, 0x78, 0x03, 0x02, 0x51, 0x75, 0x22, 0xd2, 0x0a, 0x7e, 0x04, 0x11, 0xcd, 0x7a, 0x07, 0x01, 
-    0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 
-    0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 
-    0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xad, 0x2e, 0x24, 
-    0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 
-    0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
-    0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x02, 0x00, 0x2e, 0x27, 0x01, 0xad, 
-    0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 
-    0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 
-    0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 
-    0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 
-    0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x02, 0x00, 0x2e, 0x67, 0x01, 0xad, 0x9e, 0x24, 0x00, 0x02, 
-    0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 
-    0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 
-    0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 
-    0x23, 0x23, 0x44, 0x02, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 
-    0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 
-    0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 
-    0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 
-    0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 
-    0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 
-    0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 
-    0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 
-    0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 
-    0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x52, 0xd9, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 
-    0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 
-    0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 
-    0x68, 0x07, 0xca, 0xb8, 0x12, 0x52, 0xd9, 0xda, 0xb8, 0x02, 0x54, 0x00, 0x09, 0xb1, 0x00, 0x18, 
-    0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 
-    0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 
-    0xc2, 0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x12, 
-    0x42, 0xda, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
-    0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 
-    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
-    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 
-    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x53, 0x2d, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 
-    0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0b, 0x01, 0x22, 0x20, 0x2b, 0x03, 0xd2, 0x0b, 
-    0x22, 0x75, 0x2f, 0xa3, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x83, 0x00, 0x80, 0x06, 0x20, 0x2b, 0x03, 
+    0x74, 0x07, 0xa9, 0x20, 0x30, 0x0b, 0xa9, 0x35, 0x30, 0x05, 0xbe, 0x20, 0x01, 0x28, 0x02, 0x74, 
+    0x0f, 0x19, 0xb0, 0x00, 0x04, 0xa9, 0x33, 0x30, 0x18, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x74, 
+    0x28, 0xa9, 0x20, 0x30, 0x02, 0x74, 0x20, 0x19, 0xb0, 0x00, 0x04, 0x74, 0x03, 0x19, 0xb0, 0x00, 
+    0x0c, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x0c, 0x19, 0xb0, 0x00, 0x10, 0x22, 0x7e, 0x04, 
+    0x80, 0x00, 0x4c, 0x02, 0xe4, 0x19, 0xb0, 0x00, 0x04, 0x09, 0xb0, 0x00, 0x10, 0x54, 0x08, 0x19, 
+    0xb0, 0x00, 0x10, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 
+    0x22, 0x41, 0xa5, 0x89, 0x24, 0x41, 0xb5, 0x41, 0xd4, 0x41, 0xf3, 0x42, 0x12, 0x42, 0x31, 0x42, 
+    0x50, 0x42, 0x6f, 0x42, 0x8e, 0xc2, 0x10, 0xc2, 0x18, 0xc2, 0x20, 0xc2, 0x08, 0x7e, 0x04, 0x09, 
+    0xe3, 0x7a, 0x07, 0x01, 0x6f, 0x7a, 0x07, 0x01, 0x7f, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x8f, 0x7a, 
+    0x07, 0x01, 0x9f, 0x22, 0xc2, 0x11, 0xc2, 0x19, 0xc2, 0x21, 0xc2, 0x09, 0x7e, 0x04, 0x0d, 0xe3, 
+    0x7a, 0x07, 0x01, 0x71, 0x7a, 0x07, 0x01, 0x81, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x91, 0x7a, 0x07, 
+    0x01, 0xa1, 0x22, 0xc2, 0x12, 0xc2, 0x1a, 0xc2, 0x22, 0xc2, 0x0a, 0x7e, 0x04, 0x11, 0xe3, 0x7a, 
+    0x07, 0x01, 0x73, 0x7a, 0x07, 0x01, 0x83, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x93, 0x7a, 0x07, 0x01, 
+    0xa3, 0x22, 0xc2, 0x13, 0xc2, 0x1b, 0xc2, 0x23, 0xc2, 0x0b, 0x7e, 0x04, 0x15, 0xe3, 0x7a, 0x07, 
+    0x01, 0x75, 0x7a, 0x07, 0x01, 0x85, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x95, 0x7a, 0x07, 0x01, 0xa5, 
+    0x22, 0xc2, 0x14, 0xc2, 0x1c, 0xc2, 0x24, 0xc2, 0x0c, 0x7e, 0x04, 0x19, 0xe3, 0x7a, 0x07, 0x01, 
+    0x77, 0x7a, 0x07, 0x01, 0x87, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x97, 0x7a, 0x07, 0x01, 0xa7, 0x22, 
+    0xc2, 0x15, 0xc2, 0x1d, 0xc2, 0x25, 0xc2, 0x0d, 0x7e, 0x04, 0x1d, 0xe3, 0x7a, 0x07, 0x01, 0x79, 
+    0x7a, 0x07, 0x01, 0x89, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x99, 0x7a, 0x07, 0x01, 0xa9, 0x22, 0xc2, 
+    0x16, 0xc2, 0x1e, 0xc2, 0x26, 0xc2, 0x0e, 0x7e, 0x04, 0x21, 0xe3, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 
+    0x07, 0x01, 0x8b, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x9b, 0x7a, 0x07, 0x01, 0xab, 0x22, 0xc2, 0x17, 
+    0xc2, 0x1f, 0xc2, 0x27, 0xc2, 0x0f, 0x7e, 0x04, 0x25, 0xe3, 0x7a, 0x07, 0x01, 0x7d, 0x7a, 0x07, 
+    0x01, 0x8d, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x9d, 0x7a, 0x07, 0x01, 0xad, 0x22, 0x7c, 0xb2, 0x23, 
+    0x0a, 0x2b, 0x49, 0x22, 0x42, 0xb8, 0x89, 0x24, 0x42, 0xc8, 0x42, 0xe9, 0x43, 0x0a, 0x43, 0x2b, 
+    0x43, 0x4c, 0x43, 0x6d, 0x43, 0x8e, 0x43, 0xaf, 0x30, 0x50, 0x07, 0x20, 0x68, 0x04, 0xc2, 0x28, 
+    0x80, 0x16, 0x30, 0x40, 0x07, 0x20, 0x60, 0x04, 0xc2, 0x28, 0x80, 0x0c, 0x30, 0x48, 0x07, 0x20, 
+    0x58, 0x04, 0xc2, 0x28, 0x80, 0x02, 0xd2, 0x28, 0x22, 0x30, 0x51, 0x07, 0x20, 0x69, 0x04, 0xc2, 
+    0x29, 0x80, 0x16, 0x30, 0x41, 0x07, 0x20, 0x61, 0x04, 0xc2, 0x29, 0x80, 0x0c, 0x30, 0x49, 0x07, 
+    0x20, 0x59, 0x04, 0xc2, 0x29, 0x80, 0x02, 0xd2, 0x29, 0x22, 0x30, 0x52, 0x07, 0x20, 0x6a, 0x04, 
+    0xc2, 0x2a, 0x80, 0x16, 0x30, 0x42, 0x07, 0x20, 0x62, 0x04, 0xc2, 0x2a, 0x80, 0x0c, 0x30, 0x4a, 
+    0x07, 0x20, 0x5a, 0x04, 0xc2, 0x2a, 0x80, 0x02, 0xd2, 0x2a, 0x22, 0x30, 0x53, 0x07, 0x20, 0x6b, 
+    0x04, 0xc2, 0x2b, 0x80, 0x16, 0x30, 0x43, 0x07, 0x20, 0x63, 0x04, 0xc2, 0x2b, 0x80, 0x0c, 0x30, 
+    0x4b, 0x07, 0x20, 0x5b, 0x04, 0xc2, 0x2b, 0x80, 0x02, 0xd2, 0x2b, 0x22, 0x30, 0x54, 0x07, 0x20, 
+    0x6c, 0x04, 0xc2, 0x2c, 0x80, 0x16, 0x30, 0x44, 0x07, 0x20, 0x64, 0x04, 0xc2, 0x2c, 0x80, 0x0c, 
+    0x30, 0x4c, 0x07, 0x20, 0x5c, 0x04, 0xc2, 0x2c, 0x80, 0x02, 0xd2, 0x2c, 0x22, 0x30, 0x55, 0x07, 
+    0x20, 0x6d, 0x04, 0xc2, 0x2d, 0x80, 0x16, 0x30, 0x45, 0x07, 0x20, 0x65, 0x04, 0xc2, 0x2d, 0x80, 
+    0x0c, 0x30, 0x4d, 0x07, 0x20, 0x5d, 0x04, 0xc2, 0x2d, 0x80, 0x02, 0xd2, 0x2d, 0x22, 0x30, 0x56, 
+    0x07, 0x20, 0x6e, 0x04, 0xc2, 0x2e, 0x80, 0x16, 0x30, 0x46, 0x07, 0x20, 0x66, 0x04, 0xc2, 0x2e, 
+    0x80, 0x0c, 0x30, 0x4e, 0x07, 0x20, 0x5e, 0x04, 0xc2, 0x2e, 0x80, 0x02, 0xd2, 0x2e, 0x22, 0x30, 
+    0x57, 0x07, 0x20, 0x6f, 0x04, 0xc2, 0x2f, 0x80, 0x16, 0x30, 0x47, 0x07, 0x20, 0x67, 0x04, 0xc2, 
+    0x2f, 0x80, 0x0c, 0x30, 0x4f, 0x07, 0x20, 0x5f, 0x04, 0xc2, 0x2f, 0x80, 0x02, 0xd2, 0x2f, 0x22, 
+    0x44, 0x38, 0x43, 0xe5, 0xbe, 0xb0, 0x02, 0x40, 0x01, 0x22, 0x23, 0x0a, 0x5b, 0x49, 0x55, 0x43, 
+    0xd0, 0x99, 0x54, 0xd3, 0x22, 0xa9, 0xc5, 0x87, 0x12, 0x44, 0x43, 0x7e, 0x04, 0x05, 0xe3, 0x7a, 
+    0x07, 0x01, 0xd7, 0x7a, 0x07, 0x01, 0xd9, 0x7e, 0x04, 0x01, 0xe3, 0x7a, 0x07, 0x01, 0xdd, 0x7a, 
+    0x07, 0x01, 0xdf, 0x7e, 0x04, 0x74, 0xad, 0x7a, 0x05, 0x61, 0x75, 0xf1, 0x01, 0x75, 0xe1, 0x1f, 
+    0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x75, 0xf1, 0x02, 0x75, 0xe1, 0x03, 0x75, 0xe4, 0x04, 0x75, 
+    0xf4, 0x04, 0x43, 0xa2, 0x1c, 0x12, 0x40, 0xeb, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x9a, 0x0b, 0x20, 
+    0xbe, 0x21, 0x2f, 0x78, 0xf6, 0xd2, 0xa8, 0x22, 0xa9, 0xd5, 0x87, 0x12, 0x44, 0x43, 0xd2, 0x92, 
+    0xc2, 0xa8, 0x22, 0x75, 0xa3, 0x00, 0x53, 0xa2, 0x03, 0x75, 0xc1, 0x00, 0x53, 0xc0, 0x03, 0x7e, 
+    0x00, 0x05, 0x7a, 0x01, 0xf1, 0x43, 0xf4, 0x80, 0x43, 0xe4, 0x80, 0xe5, 0xf2, 0x54, 0x7f, 0x44, 
+    0x08, 0xf5, 0xf2, 0xe5, 0xe2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xe2, 0x75, 0xe1, 0x10, 0xa5, 0xd8, 
+    0xe1, 0x22, 0xca, 0x09, 0x12, 0x30, 0x20, 0x10, 0x01, 0x12, 0xd5, 0x67, 0x1e, 0x63, 0x69, 0x01, 
+    0x7e, 0x00, 0x6a, 0x2e, 0x01, 0x69, 0xa5, 0xe6, 0xf5, 0x67, 0x80, 0x12, 0x20, 0x02, 0x1e, 0x75, 
+    0x69, 0x00, 0x85, 0x6a, 0x67, 0xd2, 0x02, 0x74, 0x00, 0x80, 0x0d, 0x30, 0x02, 0x0f, 0xc2, 0x02, 
+    0x7e, 0x00, 0x6c, 0x2e, 0x01, 0x69, 0xa5, 0xe6, 0x53, 0x90, 0xcf, 0x42, 0x90, 0xda, 0x09, 0x32, 
+    0xc0, 0xd0, 0xc0, 0xd1, 0xc0, 0xe0, 0xc0, 0xf0, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xd2, 0x01, 
+    0x75, 0x31, 0x89, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x80, 0x00, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 
+    0x03, 0x02, 0x45, 0x4f, 0x20, 0x78, 0x5a, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 
+    0x02, 0x45, 0x67, 0x20, 0x79, 0x4b, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 
+    0x45, 0x7f, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0x97, 0x20, 0x7a, 
+    0x30, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0xaf, 0xa5, 0x0a, 0x09, 
+    0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0xc7, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 
+    0xe0, 0x03, 0x02, 0x45, 0xdf, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 
+    0xf7, 0x30, 0x04, 0x0c, 0xc2, 0x04, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 
+    0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0xd0, 0xf0, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 0x32, 0x75, 
+    0x31, 0x80, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 
+    0x2b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x81, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 0x6b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 
+    0x31, 0x82, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 
+    0xab, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x83, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 0xeb, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 
+    0x31, 0x84, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 
+    0x2b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x85, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 0x6b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 
+    0x31, 0x86, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 
+    0xab, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x87, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 0xeb, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x10, 
+    0x08, 0x01, 0x22, 0x20, 0x28, 0x03, 0xd2, 0x08, 0x22, 0x75, 0x31, 0xa0, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x80, 0x00, 0x80, 0x06, 0x20, 0x28, 0x03, 0xd2, 0x08, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x49, 0x30, 0x20, 0xe6, 0x03, 0xd2, 0x08, 
+    0x22, 0x30, 0x30, 0x49, 0xd2, 0x70, 0x7e, 0x37, 0x01, 0x8f, 0x7e, 0x27, 0x01, 0xaf, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x48, 0x7a, 0x05, 0x48, 0x7a, 0x37, 0x01, 0x8f, 0x7e, 0x37, 
+    0x01, 0x6f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x6f, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x70, 0xc4, 0x22, 0xc2, 0x70, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x8f, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xaf, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xaf, 0x7e, 0x37, 0x01, 0x8f, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x48, 0x7a, 0x05, 0x48, 0x7a, 
+    0x37, 0x01, 0x8f, 0x7e, 0x37, 0x01, 0x6f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x6f, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x0d, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x09, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x6f, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x46, 0x7f, 
+    0x22, 0xd2, 0x08, 0x7e, 0x04, 0x09, 0xe3, 0x7a, 0x07, 0x01, 0x6f, 0x7a, 0x07, 0x01, 0x7f, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xbf, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x00, 0x00, 0x2e, 0x27, 0x01, 0xbf, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x30, 0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x00, 0x00, 0x2e, 0x67, 0x01, 0xbf, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x00, 0x7a, 0x69, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
+    0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
+    0x02, 0x47, 0xe3, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0xb1, 0x00, 0x04, 0x30, 0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
+    0xd2, 0x10, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x47, 
+    0xe3, 0xda, 0xb8, 0x02, 0x49, 0x30, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x68, 0x80, 0x02, 0xc2, 0x68, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x60, 0x80, 0x02, 
+    0xc2, 0x60, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0x12, 
+    0x42, 0xc8, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x48, 0x35, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x09, 0x01, 0x22, 0x20, 0x29, 0x03, 0xd2, 0x09, 
+    0x22, 0x75, 0x31, 0xa1, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x81, 0x00, 0x80, 0x06, 0x20, 0x29, 0x03, 
+    0xd2, 0x09, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
+    0x12, 0x4c, 0x88, 0x20, 0xe6, 0x03, 0xd2, 0x09, 0x22, 0x30, 0x31, 0x49, 0xd2, 0x71, 0x7e, 0x37, 
+    0x01, 0x91, 0x7e, 0x27, 0x01, 0xb1, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4a, 0x7a, 
+    0x05, 0x4a, 0x7a, 0x37, 0x01, 0x91, 0x7e, 0x37, 0x01, 0x71, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x11, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x71, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x71, 0xc4, 0x22, 0xc2, 0x71, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x91, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xb1, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb1, 0x7e, 0x37, 0x01, 0x91, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x4a, 0x7a, 0x05, 0x4a, 0x7a, 0x37, 0x01, 0x91, 0x7e, 0x37, 0x01, 0x71, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x71, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x11, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x0d, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x71, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x49, 0xd7, 0x22, 0xd2, 0x09, 0x7e, 0x04, 0x0d, 0xe3, 0x7a, 
+    0x07, 0x01, 0x71, 0x7a, 0x07, 0x01, 0x81, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc1, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x01, 0x00, 0x2e, 0x27, 
+    0x01, 0xc1, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x01, 0x00, 0x2e, 0x67, 0x01, 0xc1, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x01, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x4b, 0x3b, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4b, 0x3b, 0xda, 0xb8, 0x02, 0x4c, 0x88, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x69, 0x80, 0x02, 0xc2, 0x69, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x61, 0x80, 0x02, 0xc2, 0x61, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0x12, 0x42, 0xe9, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4b, 
+    0x8d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 
+    0x0a, 0x01, 0x22, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x75, 0x31, 0xa2, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x82, 0x00, 0x80, 0x06, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x4f, 0xe0, 0x20, 0xe6, 0x03, 0xd2, 0x0a, 
+    0x22, 0x30, 0x32, 0x49, 0xd2, 0x72, 0x7e, 0x37, 0x01, 0x93, 0x7e, 0x27, 0x01, 0xb3, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4c, 0x7a, 0x05, 0x4c, 0x7a, 0x37, 0x01, 0x93, 0x7e, 0x37, 
+    0x01, 0x73, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x73, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x72, 0xc4, 0x22, 0xc2, 0x72, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x93, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xb3, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xb3, 0x7e, 0x37, 0x01, 0x93, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x4c, 0x7a, 0x05, 0x4c, 0x7a, 
+    0x37, 0x01, 0x93, 0x7e, 0x37, 0x01, 0x73, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x73, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x15, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x11, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x73, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4d, 0x2f, 
+    0x22, 0xd2, 0x0a, 0x7e, 0x04, 0x11, 0xe3, 0x7a, 0x07, 0x01, 0x73, 0x7a, 0x07, 0x01, 0x83, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc3, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x02, 0x00, 0x2e, 0x27, 0x01, 0xc3, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x02, 0x00, 0x2e, 0x67, 0x01, 0xc3, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x02, 0x7a, 0x69, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
+    0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
+    0x02, 0x4e, 0x93, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
+    0xd2, 0x12, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4e, 
+    0x93, 0xda, 0xb8, 0x02, 0x4f, 0xe0, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x6a, 0x80, 0x02, 0xc2, 0x6a, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x62, 0x80, 0x02, 
+    0xc2, 0x62, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0x12, 
+    0x43, 0x0a, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4e, 0xe5, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0b, 0x01, 0x22, 0x20, 0x2b, 0x03, 0xd2, 0x0b, 
+    0x22, 0x75, 0x31, 0xa3, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x83, 0x00, 0x80, 0x06, 0x20, 0x2b, 0x03, 
     0xd2, 0x0b, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
-    0x12, 0x57, 0x35, 0x30, 0x33, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0b, 0x22, 0x30, 0xe6, 0x02, 0xd2, 
-    0x63, 0x7e, 0x37, 0x01, 0x7f, 0x7e, 0x27, 0x01, 0x9f, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 
-    0x05, 0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, 0x01, 0x5f, 0x7d, 0x43, 0x2d, 
-    0x42, 0xbe, 0x44, 0x19, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x5f, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
-    0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x63, 0xc4, 0x22, 0xc2, 0x63, 
-    0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, 
-    0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9f, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9f, 0x7e, 0x37, 0x01, 0x7f, 
-    0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, 
-    0x01, 0x5f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x19, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5f, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x19, 0xcd, 0x9d, 
-    0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x15, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5f, 
-    0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x54, 0xaa, 0x22, 0xd2, 0x0b, 0x7e, 0x04, 
-    0x15, 0xcd, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 0x07, 0x01, 0x6f, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 
-    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 
-    0x27, 0x01, 0xaf, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 
-    0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 
-    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x03, 
-    0x00, 0x2e, 0x27, 0x01, 0xaf, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
-    0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 
-    0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 
-    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 
-    0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x03, 0x00, 0x2e, 0x67, 0x01, 
-    0xaf, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 
-    0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 
-    0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 
-    0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x03, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 
-    0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 
-    0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 
-    0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 
-    0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 
-    0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 
-    0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 
-    0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 
-    0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 
-    0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x56, 0x0e, 0x75, 0x2f, 
-    0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 
-    0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0xda, 0xb8, 
-    0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x56, 0x0e, 0xda, 0xb8, 0x02, 0x57, 
-    0x35, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 
-    0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 
-    0x04, 0xd2, 0x5b, 0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x53, 
-    0x80, 0x02, 0xc2, 0x53, 0x12, 0x42, 0xf1, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 
-    0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 
-    0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 
-    0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 
-    0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x56, 0x62, 0x75, 0x2f, 
-    0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0c, 0x01, 0x22, 
-    0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x75, 0x2f, 0xa4, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x84, 0x00, 
-    0x80, 0x06, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 
-    0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5a, 0x6a, 0x30, 0x34, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0c, 
-    0x22, 0x30, 0xe6, 0x02, 0xd2, 0x64, 0x7e, 0x37, 0x01, 0x81, 0x7e, 0x27, 0x01, 0xa1, 0x9d, 0x32, 
-    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3a, 0x7a, 0x05, 0x3a, 0x7a, 0x37, 0x01, 0x81, 0x7e, 0x37, 
-    0x01, 0x61, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x61, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 
-    0x64, 0xc4, 0x22, 0xc2, 0x64, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
-    0x81, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa1, 0x28, 0x04, 0x7e, 0x27, 0x01, 
-    0xa1, 0x7e, 0x37, 0x01, 0x81, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3a, 0x7a, 0x05, 0x3a, 0x7a, 
-    0x37, 0x01, 0x81, 0x7e, 0x37, 0x01, 0x61, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xcc, 0x38, 
-    0x13, 0x7a, 0x47, 0x01, 0x61, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
-    0x9e, 0x44, 0x1d, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x19, 0xcd, 0x7d, 0x24, 0x2d, 
-    0x43, 0x7a, 0x47, 0x01, 0x61, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x57, 0xdf, 
-    0x22, 0xd2, 0x0c, 0x7e, 0x04, 0x19, 0xcd, 0x7a, 0x07, 0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 
-    0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
-    0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb1, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
-    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 
-    0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 
-    0x01, 0xc9, 0x7e, 0x24, 0x04, 0x00, 0x2e, 0x27, 0x01, 0xb1, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
-    0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 
-    0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x12, 0x53, 0x38, 0x20, 0xe6, 0x03, 0xd2, 0x0b, 0x22, 0x30, 0x33, 0x49, 0xd2, 0x73, 0x7e, 0x37, 
+    0x01, 0x95, 0x7e, 0x27, 0x01, 0xb5, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4e, 0x7a, 
+    0x05, 0x4e, 0x7a, 0x37, 0x01, 0x95, 0x7e, 0x37, 0x01, 0x75, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x19, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x75, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x73, 0xc4, 0x22, 0xc2, 0x73, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x95, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xb5, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb5, 0x7e, 0x37, 0x01, 0x95, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x4e, 0x7a, 0x05, 0x4e, 0x7a, 0x37, 0x01, 0x95, 0x7e, 0x37, 0x01, 0x75, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x19, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x75, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x19, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x15, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x75, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x50, 0x87, 0x22, 0xd2, 0x0b, 0x7e, 0x04, 0x15, 0xe3, 0x7a, 
+    0x07, 0x01, 0x75, 0x7a, 0x07, 0x01, 0x85, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc5, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x03, 0x00, 0x2e, 0x27, 
+    0x01, 0xc5, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x03, 0x00, 0x2e, 0x67, 0x01, 0xc5, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x03, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x51, 0xeb, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x51, 0xeb, 0xda, 0xb8, 0x02, 0x53, 0x38, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6b, 0x80, 0x02, 0xc2, 0x6b, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x63, 0x80, 0x02, 0xc2, 0x63, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x5b, 0x80, 0x02, 0xc2, 0x5b, 0x12, 0x43, 0x2b, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x52, 
+    0x3d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 
+    0x0c, 0x01, 0x22, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x75, 0x31, 0xa4, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x84, 0x00, 0x80, 0x06, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x56, 0x90, 0x20, 0xe6, 0x03, 0xd2, 0x0c, 
+    0x22, 0x30, 0x34, 0x49, 0xd2, 0x74, 0x7e, 0x37, 0x01, 0x97, 0x7e, 0x27, 0x01, 0xb7, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x50, 0x7a, 0x05, 0x50, 0x7a, 0x37, 0x01, 0x97, 0x7e, 0x37, 
+    0x01, 0x77, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x77, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x74, 0xc4, 0x22, 0xc2, 0x74, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x97, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xb7, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xb7, 0x7e, 0x37, 0x01, 0x97, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x50, 0x7a, 0x05, 0x50, 0x7a, 
+    0x37, 0x01, 0x97, 0x7e, 0x37, 0x01, 0x77, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x77, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x1d, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x19, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x77, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x53, 0xdf, 
+    0x22, 0xd2, 0x0c, 0x7e, 0x04, 0x19, 0xe3, 0x7a, 0x07, 0x01, 0x77, 0x7a, 0x07, 0x01, 0x87, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc7, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x04, 0x00, 0x2e, 0x27, 0x01, 0xc7, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
     0x30, 0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x14, 0x22, 
-    0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 
-    0x04, 0x00, 0x2e, 0x67, 0x01, 0xb1, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
-    0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9
-    0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x04, 0x00, 0x2e, 0x67, 0x01, 0xc7, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
     0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x04, 0x7a, 0x69, 
-    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
-    0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 
-    0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 
-    0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80
-    0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
-    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
-    0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
     0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
     0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
-    0x02, 0x59, 0x43, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0x02, 0x55, 0x43, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
     0xb1, 0x00, 0x04, 0x30, 0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
-    0xd2, 0x14, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x59, 
-    0x43, 0xda, 0xb8, 0x02, 0x5a, 0x6a, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 
-    0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 
-    0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, 0x50, 
-    0x80, 0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 0x54, 0x12, 0x43, 0x08, 0x02, 0x65, 0x9c, 0x75, 
-    0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 
-    0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 
-    0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 
-    0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 
-    0x02, 0x59, 0x97, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 
-    0x22, 0x10, 0x0d, 0x01, 0x22, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x75, 0x2f, 0xa5, 0x12, 0x7e, 
-    0x30, 0x7e, 0x14, 0x85, 0x00, 0x80, 0x06, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x09, 0xb1, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5d, 0x9f, 0x30, 0x35, 0x06, 
-    0x20, 0xe6, 0x4f, 0xd2, 0x0d, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x65, 0x7e, 0x37, 0x01, 0x83, 0x7e, 
-    0x27, 0x01, 0xa3, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3c, 0x7a, 0x05, 0x3c, 0x7a, 
-    0x37, 0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x21, 0xcc, 0x38, 
-    0x68, 0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0x12, 0x68, 0x34, 0x10, 0x65, 0xc4, 0x22, 0xc2, 0x65, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 
-    0x80, 0x1a, 0x7e, 0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa3, 
-    0x28, 0x04, 0x7e, 0x27, 0x01, 0xa3, 0x7e, 0x37, 0x01, 0x83, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 
-    0x3c, 0x7a, 0x05, 0x3c, 0x7a, 0x37, 0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, 
-    0xbe, 0x44, 0x21, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 
-    0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x21, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 
-    0x1d, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x63, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 
-    0x78, 0x03, 0x02, 0x5b, 0x14, 0x22, 0xd2, 0x0d, 0x7e, 0x04, 0x1d, 0xcd, 0x7a, 0x07, 0x01, 0x63, 
-    0x7a, 0x07, 0x01, 0x73, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 
-    0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 
-    0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb3, 0x2e, 0x24, 0x00, 
-    0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 
-    0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 
-    0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x05, 0x00, 0x2e, 0x27, 0x01, 0xb3, 0x1b, 
-    0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 
-    0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 
-    0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 
-    0x00, 0x10, 0xd2, 0x15, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 
-    0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x05, 0x00, 0x2e, 0x67, 0x01, 0xb3, 0x9e, 0x24, 0x00, 0x02, 0x40, 
-    0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 
-    0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 
-    0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 
-    0x23, 0x44, 0x05, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 
-    0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 
-    0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 
-    0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 
-    0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 
-    0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 
-    0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 
-    0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 
-    0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 
-    0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5c, 0x78, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 
+    0xd2, 0x14, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x55, 
+    0x43, 0xda, 0xb8, 0x02, 0x56, 0x90, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x6c, 0x80, 0x02, 0xc2, 0x6c, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x64, 0x80, 0x02, 
+    0xc2, 0x64, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0x12, 
+    0x43, 0x4c, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x55, 0x95, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0d, 0x01, 0x22, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 
+    0x22, 0x75, 0x31, 0xa5, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x85, 0x00, 0x80, 0x06, 0x20, 0x2d, 0x03, 
+    0xd2, 0x0d, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
+    0x12, 0x59, 0xe8, 0x20, 0xe6, 0x03, 0xd2, 0x0d, 0x22, 0x30, 0x35, 0x49, 0xd2, 0x75, 0x7e, 0x37, 
+    0x01, 0x99, 0x7e, 0x27, 0x01, 0xb9, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x52, 0x7a, 
+    0x05, 0x52, 0x7a, 0x37, 0x01, 0x99, 0x7e, 0x37, 0x01, 0x79, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x21, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x79, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x75, 0xc4, 0x22, 0xc2, 0x75, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x99, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xb9, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb9, 0x7e, 0x37, 0x01, 0x99, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x52, 0x7a, 0x05, 0x52, 0x7a, 0x37, 0x01, 0x99, 0x7e, 0x37, 0x01, 0x79, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x21, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x79, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x21, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x1d, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x79, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x57, 0x37, 0x22, 0xd2, 0x0d, 0x7e, 0x04, 0x1d, 0xe3, 0x7a, 
+    0x07, 0x01, 0x79, 0x7a, 0x07, 0x01, 0x89, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc9, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x05, 0x00, 0x2e, 0x27, 
+    0x01, 0xc9, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
     0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
-    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 
-    0x07, 0xca, 0xb8, 0x12, 0x5c, 0x78, 0xda, 0xb8, 0x02, 0x5d, 0x9f, 0x09, 0xb1, 0x00, 0x18, 0x7e, 
-    0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 
-    0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 
-    0x5d, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x55, 0x80, 0x02, 0xc2, 0x55, 0x12, 0x43, 
-    0x1f, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 
-    0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 
-    0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 
-    0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 
-    0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5c, 0xcc, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 
-    0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0e, 0x01, 0x22, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 
-    0x75, 0x2f, 0xa6, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x86, 0x00, 0x80, 0x06, 0x20, 0x2e, 0x03, 0xd2, 
-    0x0e, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 
-    0x60, 0xd4, 0x30, 0x36, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0e, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x66, 
-    0x7e, 0x37, 0x01, 0x85, 0x7e, 0x27, 0x01, 0xa5, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 
-    0x3e, 0x7a, 0x05, 0x3e, 0x7a, 0x37, 0x01, 0x85, 0x7e, 0x37, 0x01, 0x65, 0x7d, 0x43, 0x2d, 0x42, 
-    0xbe, 0x44, 0x25, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x65, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x66, 0xc4, 0x22, 0xc2, 0x66, 0x2d, 
-    0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x85, 0xbe, 0x24, 0x00, 0x00, 0x68, 
-    0x6a, 0xbe, 0x27, 0x01, 0xa5, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa5, 0x7e, 0x37, 0x01, 0x85, 0x9d, 
-    0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3e, 0x7a, 0x05, 0x3e, 0x7a, 0x37, 0x01, 0x85, 0x7e, 0x37, 0x01, 
-    0x65, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x65, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 
-    0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x25, 0xcd, 0x9d, 0x24, 
-    0x12, 0x68, 0x34, 0x7e, 0x34, 0x21, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x65, 0x12, 
-    0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5e, 0x49, 0x22, 0xd2, 0x0e, 0x7e, 0x04, 0x21, 
-    0xcd, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 
-    0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 
-    0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 
-    0x01, 0xb5, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 
-    0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 
-    0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x06, 0x00, 
-    0x2e, 0x27, 0x01, 0xb5, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 
-    0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 
-    0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 
-    0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 
-    0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x06, 0x00, 0x2e, 0x67, 0x01, 0xb5, 
-    0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 
-    0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 
-    0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 
-    0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x06, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 
-    0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 
-    0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 
-    0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 
-    0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 
-    0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 
-    0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 
-    0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 
-    0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 
-    0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5f, 0xad, 0x75, 0x2f, 0x99, 
-    0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 
-    0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0xda, 0xb8, 0x30, 
-    0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5f, 0xad, 0xda, 0xb8, 0x02, 0x60, 0xd4, 
-    0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 
-    0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 
-    0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, 
-    0x02, 0xc2, 0x56, 0x12, 0x43, 0x36, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 
-    0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 
-    0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 
-    0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 
-    0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x60, 0x01, 0x75, 0x2f, 0x95, 
-    0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0f, 0x01, 0x22, 0x20, 
-    0x2f, 0x03, 0xd2, 0x0f, 0x22, 0x75, 0x2f, 0xa7, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x87, 0x00, 0x80, 
-    0x06, 0x20, 0x2f, 0x03, 0xd2, 0x0f, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 
-    0xda, 0xb8, 0x68, 0x03, 0x12, 0x64, 0x09, 0x30, 0x37, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0f, 0x22, 
-    0x30, 0xe6, 0x02, 0xd2, 0x67, 0x7e, 0x37, 0x01, 0x87, 0x7e, 0x27, 0x01, 0xa7, 0x9d, 0x32, 0x40, 
-    0x31, 0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, 0x01, 0x87, 0x7e, 0x37, 0x01, 
-    0x67, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x67, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x67, 
-    0xc4, 0x22, 0xc2, 0x67, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x87, 
-    0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa7, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa7, 
-    0x7e, 0x37, 0x01, 0x87, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, 
-    0x01, 0x87, 0x7e, 0x37, 0x01, 0x67, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xcc, 0x38, 0x13, 
-    0x7a, 0x47, 0x01, 0x67, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
-    0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 
-    0x44, 0x29, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x25, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 
-    0x7a, 0x47, 0x01, 0x67, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x61, 0x7e, 0x22, 
-    0xd2, 0x0f, 0x7e, 0x04, 0x25, 0xcd, 0x7a, 0x07, 0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x75, 0x2f, 
-    0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 
-    0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 
-    0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb7, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 
-    0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 
-    0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 
-    0xc9, 0x7e, 0x24, 0x07, 0x00, 0x2e, 0x27, 0x01, 0xb7, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 
-    0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 
-    0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 
-    0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0x80, 
-    0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x07, 
-    0x00, 0x2e, 0x67, 0x01, 0xb7, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 
-    0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 
-    0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 
-    0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x07, 0x7a, 0x69, 0xb0, 
-    0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 
-    0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 
-    0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
-    0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 
-    0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 
-    0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 
-    0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 
-    0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 
-    0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 
-    0x62, 0xe2, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 
-    0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 
-    0x17, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x62, 0xe2, 
-    0xda, 0xb8, 0x02, 0x64, 0x09, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 
-    0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 
-    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
-    0x68, 0x04, 0xd2, 0x57, 0x80, 0x02, 0xc2, 0x57, 0x12, 0x43, 0x4d, 0x02, 0x65, 0x9c, 0x75, 0x2f, 
-    0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 
-    0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 
-    0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 
-    0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 
-    0x63, 0x36, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 
-    0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 
-    0x20, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 
-    0xd2, 0x50, 0x80, 0x02, 0xc2, 0x50, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 
-    0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 
-    0xc2, 0x59, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x51, 0x80, 0x02, 0xc2, 0x51, 0x02, 
-    0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 
-    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
-    0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 
-    0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5b, 
-    0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x53, 0x80, 0x02, 0xc2, 
-    0x53, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 
-    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, 
-    0x50, 0x80, 0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 0x54, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 
-    0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 
-    0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x55, 0x80, 
-    0x02, 0xc2, 0x55, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 
-    0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, 
-    0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, 0x02, 0xc2, 0x56, 0x02, 0x65, 0x88, 0x7c, 
-    0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 
-    0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 
-    0x57, 0x80, 0x02, 0xc2, 0x57, 0x02, 0x65, 0x88, 0x54, 0xf0, 0xc4, 0xa5, 0xff, 0xc4, 0xa5, 0x4f, 
-    0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0x22, 0xca, 0x19, 0x5e, 0x20, 
-    0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xcd, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 
-    0xb0, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x02, 0x7e, 0x64, 0x00, 0x02, 0x02, 0x65, 0xe7, 0xca, 
-    0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xcd, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 
-    0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0x7a, 0x79, 0x60, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x03, 
-    0x7e, 0x64, 0x00, 0x03, 0x02, 0x65, 0xe7, 0xd2, 0x04, 0x7e, 0x27, 0x01, 0xcb, 0x2d, 0x26, 0xbe, 
-    0x24, 0x04, 0x00, 0x38, 0x2e, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7e, 0x79, 0xa0, 
-    0x7a, 0x09, 0xa0, 0x0b, 0x04, 0x0b, 0x74, 0xbd, 0x04, 0x68, 0x23, 0xa5, 0xdb, 0xef, 0x7a, 0x27, 
-    0x01, 0xcb, 0x7e, 0x25, 0x30, 0x2d, 0x26, 0x7a, 0x25, 0x30, 0x7a, 0x07, 0x01, 0xc9, 0xda, 0x19, 
-    0xc2, 0xd7, 0x22, 0x75, 0x2f, 0x9a, 0x12, 0x7e, 0x30, 0xda, 0x19, 0xd2, 0xd7, 0x22, 0x7e, 0x04, 
-    0x01, 0xcd, 0x80, 0xd7, 0x4d, 0x42, 0x4a, 0xae, 0x4b, 0xa8, 0x4d, 0x7b, 0x49, 0x4f, 0x49, 0x4f, 
-    0x4c, 0xa7, 0x49, 0x4f, 0x4d, 0xbf, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x4d, 0xc6, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x50, 0x77, 0x4d, 0xe3, 0x4e, 0xdd, 0x50, 0xb0, 0x49, 0x4f, 0x49, 0x4f, 
-    0x4f, 0xdc, 0x49, 0x4f, 0x50, 0xf4, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x50, 0xfb, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x53, 0xac, 0x51, 0x18, 0x52, 0x12, 0x53, 0xe5, 0x49, 0x4f, 0x49, 0x4f, 
-    0x53, 0x11, 0x49, 0x4f, 0x54, 0x29, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x54, 0x30, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x56, 0xe1, 0x54, 0x4d, 0x55, 0x47, 0x57, 0x1a, 0x49, 0x4f, 0x49, 0x4f, 
-    0x56, 0x46, 0x49, 0x4f, 0x57, 0x5e, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x57, 0x65, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5a, 0x16, 0x57, 0x82, 0x58, 0x7c, 0x5a, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x59, 0x7b, 0x49, 0x4f, 0x5a, 0x93, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5a, 0x9a, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5d, 0x4b, 0x5a, 0xb7, 0x5b, 0xb1, 0x5d, 0x84, 0x49, 0x4f, 0x49, 0x4f, 
-    0x5c, 0xb0, 0x49, 0x4f, 0x5d, 0xc8, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5d, 0xcf, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x60, 0x80, 0x5d, 0xec, 0x5e, 0xe6, 0x60, 0xb9, 0x49, 0x4f, 0x49, 0x4f, 
-    0x5f, 0xe5, 0x49, 0x4f, 0x60, 0xfd, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x61, 0x04, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x63, 0xb5, 0x61, 0x21, 0x62, 0x1b, 0x63, 0xee, 0x49, 0x4f, 0x49, 0x4f, 
-    0x63, 0x1a, 0x49, 0x4f, 0x64, 0x32, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x64, 0x39, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0xca, 0x29, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 0x54, 0x0b, 0x10, 0x9c, 0xb5, 
-    0xa4, 0x2e, 0x54, 0x68, 0x51, 0x89, 0x54, 0x7e, 0x39, 0x00, 0x7a, 0x19, 0x00, 0x0b, 0x34, 0x80, 
-    0xe9, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 
-    0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 
-    0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 
-    0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x05, 0x00, 0x2e, 0x67, 0x01, 0xc9, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x05, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x58, 0x9b, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x58, 0x9b, 0xda, 0xb8, 0x02, 0x59, 0xe8, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6d, 0x80, 0x02, 0xc2, 0x6d, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x65, 0x80, 0x02, 0xc2, 0x65, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 0x12, 0x43, 0x6d, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x58, 
+    0xed, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 
+    0x0e, 0x01, 0x22, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 0x75, 0x31, 0xa6, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x86, 0x00, 0x80, 0x06, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5d, 0x40, 0x20, 0xe6, 0x03, 0xd2, 0x0e, 
+    0x22, 0x30, 0x36, 0x49, 0xd2, 0x76, 0x7e, 0x37, 0x01, 0x9b, 0x7e, 0x27, 0x01, 0xbb, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x54, 0x7a, 0x05, 0x54, 0x7a, 0x37, 0x01, 0x9b, 0x7e, 0x37, 
+    0x01, 0x7b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x7b, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x76, 0xc4, 0x22, 0xc2, 0x76, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x9b, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xbb, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xbb, 0x7e, 0x37, 0x01, 0x9b, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x54, 0x7a, 0x05, 0x54, 0x7a, 
+    0x37, 0x01, 0x9b, 0x7e, 0x37, 0x01, 0x7b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x7b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x25, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x21, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x7b, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5a, 0x8f, 
+    0x22, 0xd2, 0x0e, 0x7e, 0x04, 0x21, 0xe3, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 0x07, 0x01, 0x8b, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xcb, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x06, 0x00, 0x2e, 0x27, 0x01, 0xcb, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x06, 0x00, 0x2e, 0x67, 0x01, 0xcb, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x06, 0x7a, 0x69, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
+    0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
+    0x02, 0x5b, 0xf3, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
+    0xd2, 0x16, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5b, 
+    0xf3, 0xda, 0xb8, 0x02, 0x5d, 0x40, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x6e, 0x80, 0x02, 0xc2, 0x6e, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x66, 0x80, 0x02, 
+    0xc2, 0x66, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0x12, 
+    0x43, 0x8e, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5c, 0x45, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0f, 0x01, 0x22, 0x20, 0x2f, 0x03, 0xd2, 0x0f, 
+    0x22, 0x75, 0x31, 0xa7, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x87, 0x00, 0x80, 0x06, 0x20, 0x2f, 0x03, 
+    0xd2, 0x0f, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
+    0x12, 0x60, 0x98, 0x20, 0xe6, 0x03, 0xd2, 0x0f, 0x22, 0x30, 0x37, 0x49, 0xd2, 0x77, 0x7e, 0x37, 
+    0x01, 0x9d, 0x7e, 0x27, 0x01, 0xbd, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x56, 0x7a, 
+    0x05, 0x56, 0x7a, 0x37, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x29, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x7d, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x77, 0xc4, 0x22, 0xc2, 0x77, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x9d, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xbd, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xbd, 0x7e, 0x37, 0x01, 0x9d, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x56, 0x7a, 0x05, 0x56, 0x7a, 0x37, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x7d, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x29, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x25, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x7d, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5d, 0xe7, 0x22, 0xd2, 0x0f, 0x7e, 0x04, 0x25, 0xe3, 0x7a, 
+    0x07, 0x01, 0x7d, 0x7a, 0x07, 0x01, 0x8d, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xcd, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x07, 0x00, 0x2e, 0x27, 
+    0x01, 0xcd, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x07, 0x00, 0x2e, 0x67, 0x01, 0xcd, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x07, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5f, 0x4b, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5f, 0x4b, 0xda, 0xb8, 0x02, 0x60, 0x98, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6f, 0x80, 0x02, 0xc2, 0x6f, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x67, 0x80, 0x02, 0xc2, 0x67, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0x12, 0x43, 0xaf, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5f, 
+    0x9d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x7c, 
+    0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 
+    0x68, 0x04, 0xd2, 0x68, 0x80, 0x02, 0xc2, 0x68, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 
+    0x60, 0x80, 0x02, 0xc2, 0x60, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 
+    0xc2, 0x58, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 
+    0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x69, 0x80, 0x02, 0xc2, 0x69, 0xa5, 0xfd, 
+    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x61, 0x80, 0x02, 0xc2, 0x61, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
+    0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 
+    0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6a, 
+    0x80, 0x02, 0xc2, 0x6a, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x62, 0x80, 0x02, 0xc2, 
+    0x62, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0x02, 0x62, 
+    0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x10, 0x68, 0x04, 0xd2, 0x6b, 0x80, 0x02, 0xc2, 0x6b, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 
+    0x04, 0xd2, 0x63, 0x80, 0x02, 0xc2, 0x63, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5b, 
+    0x80, 0x02, 0xc2, 0x5b, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 
+    0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6c, 0x80, 0x02, 0xc2, 0x6c, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x64, 0x80, 0x02, 0xc2, 0x64, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x80, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 
+    0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 
+    0xd2, 0x6d, 0x80, 0x02, 0xc2, 0x6d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x65, 0x80, 
+    0x02, 0xc2, 0x65, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 
+    0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 
+    0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6e, 0x80, 0x02, 0xc2, 0x6e, 0xa5, 0xfd, 0x5e, 0x50, 
+    0x20, 0x68, 0x04, 0xd2, 0x66, 0x80, 0x02, 0xc2, 0x66, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 
+    0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 
+    0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6f, 0x80, 0x02, 
+    0xc2, 0x6f, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x67, 0x80, 0x02, 0xc2, 0x67, 0xa5, 
+    0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0x02, 0x62, 0x7f, 0x54, 
+    0xf0, 0xc4, 0xa5, 0xff, 0xc4, 0xa5, 0x4f, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 
+    0x7c, 0x15, 0x22, 0xca, 0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xe3, 0xca, 0x79, 
+    0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x02, 0x7e, 
+    0x64, 0x00, 0x02, 0x02, 0x62, 0xde, 0xca, 0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 
+    0xe3, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0x7a, 0x79, 0x60, 
+    0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x03, 0x7e, 0x64, 0x00, 0x03, 0x02, 0x62, 0xde, 0xd2, 0x04, 
+    0x7e, 0x27, 0x01, 0xe1, 0x2d, 0x26, 0xbe, 0x24, 0x04, 0x00, 0x38, 0x2e, 0x7e, 0x07, 0x01, 0xdf, 
+    0x7e, 0x44, 0x05, 0xe3, 0x7e, 0x79, 0xa0, 0x7a, 0x09, 0xa0, 0x0b, 0x04, 0x0b, 0x74, 0xbd, 0x04, 
+    0x68, 0x23, 0xa5, 0xdb, 0xef, 0x7a, 0x27, 0x01, 0xe1, 0x7e, 0x25, 0x46, 0x2d, 0x26, 0x7a, 0x25, 
+    0x46, 0x7a, 0x07, 0x01, 0xdf, 0xda, 0x19, 0xc2, 0xd7, 0x22, 0x75, 0x31, 0x9a, 0x12, 0x7c, 0x15, 
+    0xda, 0x19, 0xd2, 0xd7, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd7, 0x48, 0xb6, 0x46, 0x25, 0x47, 
+    0x1c, 0x49, 0x15, 0x44, 0xc6, 0x44, 0xc6, 0x48, 0x1b, 0x44, 0xc6, 0x49, 0x59, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x49, 0x60, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4c, 0x0e, 0x49, 0x7d, 0x4a, 
+    0x74, 0x4c, 0x6d, 0x44, 0xc6, 0x44, 0xc6, 0x4b, 0x73, 0x44, 0xc6, 0x4c, 0xb1, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4c, 0xb8, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4f, 0x66, 0x4c, 0xd5, 0x4d, 
+    0xcc, 0x4f, 0xc5, 0x44, 0xc6, 0x44, 0xc6, 0x4e, 0xcb, 0x44, 0xc6, 0x50, 0x09, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x50, 0x10, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x52, 0xbe, 0x50, 0x2d, 0x51, 
+    0x24, 0x53, 0x1d, 0x44, 0xc6, 0x44, 0xc6, 0x52, 0x23, 0x44, 0xc6, 0x53, 0x61, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x53, 0x68, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x56, 0x16, 0x53, 0x85, 0x54, 
+    0x7c, 0x56, 0x75, 0x44, 0xc6, 0x44, 0xc6, 0x55, 0x7b, 0x44, 0xc6, 0x56, 0xb9, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x56, 0xc0, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x59, 0x6e, 0x56, 0xdd, 0x57, 
+    0xd4, 0x59, 0xcd, 0x44, 0xc6, 0x44, 0xc6, 0x58, 0xd3, 0x44, 0xc6, 0x5a, 0x11, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5a, 0x18, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5c, 0xc6, 0x5a, 0x35, 0x5b, 
+    0x2c, 0x5d, 0x25, 0x44, 0xc6, 0x44, 0xc6, 0x5c, 0x2b, 0x44, 0xc6, 0x5d, 0x69, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5d, 0x70, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x60, 0x1e, 0x5d, 0x8d, 0x5e, 
+    0x84, 0x60, 0x7d, 0x44, 0xc6, 0x44, 0xc6, 0x5f, 0x83, 0x44, 0xc6, 0x60, 0xc1, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x60, 0xc8, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0xca, 0x29, 0x1e, 0x50, 0x40, 
+    0x0d, 0x7e, 0x54, 0x0b, 0x10, 0x9c, 0xb5, 0xa4, 0x2e, 0x54, 0x65, 0x48, 0x89, 0x54, 0x7e, 0x39, 
+    0x00, 0x7a, 0x19, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 
     0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 
     0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 
     0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 
@@ -744,12 +832,12 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
     0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 
     0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 
     0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 
-    0x35, 0xda, 0x29, 0x22, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 0x54, 0x0b, 0x1c, 0x9c, 0xb5, 0xa4, 0x2e
-    0x54, 0x69, 0x1f, 0x89, 0x54, 0x7e, 0x19, 0x00, 0x7a, 0x39, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x7e
-    0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 
-    0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35
-    0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19
-    0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 
+    0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a
+    0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10
+    0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 
+    0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0xda, 0x29, 0x22, 0x1e, 0x50, 0x40, 0x0d, 0x7e
+    0x54, 0x0b, 0x1c, 0x9c, 0xb5, 0xa4, 0x2e, 0x54, 0x66, 0x16, 0x89, 0x54, 0x7e, 0x19, 0x00, 0x7a
+    0x39, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 
     0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 
     0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 
     0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 
@@ -765,157 +853,176 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
     0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 
     0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 
     0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 
-    0x00, 0x0b, 0x35, 0x22, 0x6a, 0x9b, 0x6c, 0x4f, 0x6c, 0x67, 0x6c, 0x82, 0x6d, 0x1d, 0x6d, 0xb5, 
-    0x6d, 0xd0, 0x6e, 0x62, 0x6d, 0xeb, 0x6e, 0x2c, 0x7c, 0xb3, 0xbe, 0xb0, 0x09, 0x28, 0x14, 0x75, 
-    0x2f, 0x09, 0x12, 0x7e, 0x30, 0x75, 0x57, 0x10, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x43, 0xe1, 0xc0, 
-    0xd0, 0xf1, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0x23, 0x6c, 0xaa, 0x2e, 0x54, 0x6a, 0x54, 0x0b, 0x58, 
-    0x50, 0x89, 0x54, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x2f, 0xb0, 0x12, 0x7e, 
-    0x30, 0x0a, 0x22, 0x09, 0xb2, 0x6a, 0x93, 0x42, 0x24, 0xd0, 0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 
-    0x3b, 0x49, 0x33, 0x6a, 0xb7, 0x89, 0x34, 0x6a, 0xc7, 0x6a, 0xf5, 0x6b, 0x23, 0x6b, 0x51, 0x6b, 
-    0x7f, 0x6b, 0xad, 0x6b, 0xdb, 0x6c, 0x09, 0x12, 0x41, 0xa9, 0xd2, 0x28, 0xd2, 0x08, 0xc2, 0x40, 
-    0xc2, 0x48, 0xc2, 0x38, 0xc2, 0x30, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xb9, 0x7e, 0x04, 0x00, 0x20, 
-    0x7a, 0x07, 0x01, 0x99, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xa9, 0x12, 0x41, 0x16, 0x12, 
-    0x64, 0x40, 0x02, 0x6c, 0x37, 0x12, 0x41, 0xc6, 0xd2, 0x29, 0xd2, 0x09, 0xc2, 0x41, 0xc2, 0x49, 
-    0xc2, 0x39, 0xc2, 0x31, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xba, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 
-    0x01, 0x9b, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xab, 0x12, 0x41, 0x16, 0x12, 0x64, 0x69, 
-    0x02, 0x6c, 0x37, 0x12, 0x41, 0xe3, 0xd2, 0x2a, 0xd2, 0x0a, 0xc2, 0x42, 0xc2, 0x4a, 0xc2, 0x3a, 
-    0xc2, 0x32, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbb, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9d, 
-    0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xad, 0x12, 0x41, 0x16, 0x12, 0x64, 0x92, 0x02, 0x6c, 
-    0x37, 0x12, 0x42, 0x00, 0xd2, 0x2b, 0xd2, 0x0b, 0xc2, 0x43, 0xc2, 0x4b, 0xc2, 0x3b, 0xc2, 0x33, 
-    0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbc, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9f, 0x7e, 0x04, 
-    0x00, 0x38, 0x7a, 0x07, 0x01, 0xaf, 0x12, 0x41, 0x16, 0x12, 0x64, 0xbb, 0x02, 0x6c, 0x37, 0x12, 
-    0x42, 0x1d, 0xd2, 0x2c, 0xd2, 0x0c, 0xc2, 0x44, 0xc2, 0x4c, 0xc2, 0x3c, 0xc2, 0x34, 0x6d, 0x00, 
-    0x7a, 0x03, 0x01, 0xbd, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa1, 0x7e, 0x04, 0x00, 0x38, 
-    0x7a, 0x07, 0x01, 0xb1, 0x12, 0x41, 0x16, 0x12, 0x64, 0xe4, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x3a, 
-    0xd2, 0x2d, 0xd2, 0x0d, 0xc2, 0x45, 0xc2, 0x4d, 0xc2, 0x3d, 0xc2, 0x35, 0x6d, 0x00, 0x7a, 0x03, 
-    0x01, 0xbe, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa3, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 
-    0x01, 0xb3, 0x12, 0x41, 0x16, 0x12, 0x65, 0x0d, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x57, 0xd2, 0x2e, 
-    0xd2, 0x0e, 0xc2, 0x46, 0xc2, 0x4e, 0xc2, 0x3e, 0xc2, 0x36, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbf, 
-    0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa5, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb5, 
-    0x12, 0x41, 0x16, 0x12, 0x65, 0x36, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x74, 0xd2, 0x2f, 0xd2, 0x0f, 
-    0xc2, 0x47, 0xc2, 0x4f, 0xc2, 0x3f, 0xc2, 0x37, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xc0, 0x7e, 0x04, 
-    0x00, 0x20, 0x7a, 0x07, 0x01, 0xa7, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb7, 0x12, 0x41, 
-    0x16, 0x12, 0x65, 0x5f, 0x02, 0x6c, 0x37, 0x7e, 0xa0, 0xd0, 0x7e, 0x60, 0x0f, 0x12, 0x65, 0xbf, 
-    0x40, 0x0c, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xc2, 0xd7, 0x22, 0x75, 
-    0x2f, 0xb1, 0x12, 0x7e, 0x30, 0x0a, 0x52, 0x23, 0x6d, 0x00, 0x59, 0x05, 0x00, 0x32, 0x12, 0x41, 
-    0x72, 0x12, 0x41, 0x8e, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb2, 0x12, 0x7e, 0x30, 0x0a, 0x22, 0x09, 
-    0xb2, 0x6a, 0x93, 0x42, 0x23, 0x7e, 0xb0, 0x9c, 0x19, 0xb2, 0x01, 0xb9, 0x12, 0x45, 0x74, 0xd0, 
-    0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 
-    0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 
-    0x12, 0x44, 0x40, 0xca, 0xb8, 0x09, 0xb0, 0x00, 0x10, 0x44, 0x02, 0x19, 0xb0, 0x00, 0x10, 0xda, 
-    0xb8, 0x80, 0x02, 0x54, 0xbf, 0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x08, 0x80, 0x02, 
-    0x54, 0xf7, 0x09, 0x30, 0x00, 0x0c, 0xca, 0xb8, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xda, 0xb8, 
-    0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 0x62, 0x09, 0xb6, 0x6a, 0x93, 0x3e, 0x20, 
-    0x0a, 0x62, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x20, 0x42, 0x27, 0xca, 0xb8, 0x74, 0x61, 0x19, 
-    0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x10, 0x59, 0x46, 0x01, 0xa9, 0x09, 0xb0, 0x00, 0x10, 0x44, 
-    0x01, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x11, 0xf4, 0x52, 0x27, 0x74, 0xa1, 0x19, 0xb0, 
-    0x00, 0x08, 0x7e, 0x44, 0x00, 0x38, 0x59, 0x46, 0x01, 0xa9, 0xd0, 0xa8, 0x22, 0x7c, 0x74, 0x7e, 
-    0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 
-    0xb0, 0x00, 0x08, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x04, 0x44, 0x80, 0x80, 0x02, 0x54, 0x7f, 
-    0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x02, 0x80, 0x02, 0x54, 0xfd, 0x19, 0xb0, 0x00, 
-    0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 0x62, 0x09, 0xb6, 0x6a, 0x93, 0xa5, 0xfd, 0xf4, 0xa5, 0xfe, 
-    0xca, 0x28, 0x3e, 0x20, 0x0a, 0x62, 0xda, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x10, 0xa5, 
-    0xed, 0x42, 0x28, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0x99, 0x80, 0x04, 0xa5, 
-    0xee, 0x52, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x04, 0x68, 0x10, 0xa5, 0xed, 0x42, 0x29, 0x42, 0x26, 
-    0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0x99, 0x80, 0x15, 0xa5, 0xee, 0x52, 0x29, 0x7c, 0x74, 
-    0x5e, 0x70, 0x02, 0x78, 0x0a, 0x52, 0x26, 0x7e, 0x44, 0x00, 0x20, 0x59, 0x46, 0x01, 0x99, 0x12, 
-    0x42, 0x91, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 
-    0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 0x00, 0x10, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 
-    0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 
-    0x19, 0x40, 0x00, 0x18, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb5, 0x12, 0x7e, 
-    0x30, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0xb0, 0x00, 0x0c, 0x44, 0x40, 0x19, 0xb0, 0x00, 
-    0x0c, 0xe5, 0x58, 0xb4, 0x07, 0x23, 0x09, 0xb0, 0x00, 0x10, 0x4e, 0xb0, 0x02, 0x19, 0xb0, 0x00, 
-    0x10, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x54, 
-    0xf7, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb6, 0x12, 
-    0x7e, 0x30, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0xe5, 0x58, 0xb4, 0x07, 0x18, 0x09, 0x30, 0x00, 
-    0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x44, 0x08, 0x19, 0xb0, 0x00, 
-    0x04, 0x19, 0x30, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x0c, 0x54, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xd0, 
-    0xa8, 0x22, 0x75, 0x2f, 0xb4, 0x12, 0x7e, 0x30, 0x7a, 0x21, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x41, 
-    0x2f, 0x12, 0x7e, 0x30, 0x7e, 0xb0, 0x01, 0x7e, 0xa0, 0xc8, 0x7c, 0x64, 0x12, 0x65, 0xbf, 0xc0, 
-    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xd0, 0xa8, 0x22, 0x6e, 0x9c, 0x6e, 0xe3, 
-    0x6f, 0x2a, 0x6f, 0x71, 0x6f, 0xb8, 0x6f, 0xff, 0x70, 0x46, 0x70, 0x8d, 0x75, 0x2f, 0x55, 0x12, 
-    0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 
-    0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x69, 0x7e, 0x27, 0x01, 0x79, 0x2d, 0x23, 0x7e, 0x09, 
-    0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x0d, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 
-    0x78, 0xec, 0x7a, 0x17, 0x01, 0x69, 0x7a, 0x27, 0x01, 0x79, 0x02, 0x4a, 0x98, 0x7e, 0x14, 0x09, 
-    0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x01, 0x12, 0x7e, 0x30, 0x7a, 
-    0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6b, 0x7e, 
-    0x27, 0x01, 0x7b, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 
-    0x14, 0x11, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6b, 0x7a, 0x27, 0x01, 
-    0x7b, 0x02, 0x4d, 0xcd, 0x7e, 0x14, 0x0d, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 
-    0x75, 0x2f, 0x02, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
-    0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6d, 0x7e, 0x27, 0x01, 0x7d, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 
-    0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x15, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 
-    0x7a, 0x17, 0x01, 0x6d, 0x7a, 0x27, 0x01, 0x7d, 0x02, 0x51, 0x02, 0x7e, 0x14, 0x11, 0xcd, 0x80, 
-    0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x03, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 
-    0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6f, 0x7e, 0x27, 0x01, 
-    0x7f, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x19, 
-    0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6f, 0x7a, 0x27, 0x01, 0x7f, 0x02, 
-    0x54, 0x37, 0x7e, 0x14, 0x15, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 
-    0x04, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 
-    0x7e, 0x17, 0x01, 0x71, 0x7e, 0x27, 0x01, 0x81, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 
-    0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x1d, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 
-    0x01, 0x71, 0x7a, 0x27, 0x01, 0x81, 0x02, 0x57, 0x6c, 0x7e, 0x14, 0x19, 0xcd, 0x80, 0xeb, 0x75, 
-    0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x05, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 
-    0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x73, 0x7e, 0x27, 0x01, 0x83, 0x2d, 
-    0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x21, 0xcc, 0x38, 
-    0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x73, 0x7a, 0x27, 0x01, 0x83, 0x02, 0x5a, 0xa1, 
-    0x7e, 0x14, 0x1d, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x06, 0x12, 
-    0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 
-    0x01, 0x75, 0x7e, 0x27, 0x01, 0x85, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 
-    0x0b, 0x14, 0xbe, 0x14, 0x25, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x75, 
-    0x7a, 0x27, 0x01, 0x85, 0x02, 0x5d, 0xd6, 0x7e, 0x14, 0x21, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 
-    0x12, 0x7e, 0x30, 0x75, 0x2f, 0x07, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 
-    0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x77, 0x7e, 0x27, 0x01, 0x87, 0x2d, 0x23, 0x7e, 
-    0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x29, 0xcc, 0x38, 0x0f, 0x1b, 
-    0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x77, 0x7a, 0x27, 0x01, 0x87, 0x02, 0x61, 0x0b, 0x7e, 0x14, 
-    0x25, 0xcd, 0x80, 0xeb, 0xca, 0xb8, 0xc0, 0xf1, 0x75, 0x2f, 0x02, 0x12, 0x7e, 0x30, 0xe5, 0xc0, 
-    0x54, 0x03, 0x68, 0x05, 0x12, 0x77, 0xdd, 0x80, 0xf5, 0x30, 0xc2, 0x08, 0x75, 0xf1, 0x01, 0x12, 
-    0x71, 0xe9, 0x80, 0x14, 0x30, 0xc3, 0x08, 0x75, 0xf1, 0x01, 0x12, 0x71, 0x0d, 0x80, 0x09, 0x30, 
-    0xc4, 0x06, 0x75, 0xf1, 0x02, 0x12, 0x72, 0xf9, 0xd0, 0xf1, 0xda, 0xb8, 0x32, 0x75, 0x2f, 0x10, 
-    0x12, 0x7e, 0x30, 0xca, 0x0b, 0xca, 0x39, 0xca, 0x59, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x5c, 0xe5, 
-    0xe5, 0x54, 0xc0, 0x68, 0x4f, 0xe5, 0xe6, 0x6c, 0xaa, 0x7e, 0x37, 0x01, 0xc5, 0x2d, 0x35, 0xbe, 
-    0x34, 0x04, 0x00, 0x38, 0x4a, 0x7a, 0x37, 0x01, 0xc5, 0x7e, 0x37, 0x01, 0xc3, 0x7d, 0x43, 0x2d, 
-    0x45, 0xbe, 0x44, 0x09, 0xcc, 0x38, 0x40, 0x7a, 0x47, 0x01, 0xc3, 0x75, 0x2f, 0x11, 0x12, 0x7e, 
-    0x30, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x73, 0xc8, 0xa9, 0x21, 0xe5, 0x1f, 0xa9, 0xd4, 
+    0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 
+    0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 
+    0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 
+    0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x22, 0x67, 0x96, 0x69, 0x63, 0x69, 
+    0x7b, 0x6a, 0x49, 0x6a, 0xe4, 0x6b, 0x8e, 0x6b, 0xa9, 0x6c, 0x3b, 0x6b, 0xc4, 0x6c, 0x05, 0x69, 
+    0x96, 0x69, 0xaa, 0x7c, 0xb3, 0xbe, 0xb0, 0x0b, 0x28, 0x14, 0x75, 0x31, 0x09, 0x12, 0x7c, 0x15, 
+    0x75, 0x6d, 0x10, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x43, 0xe1, 0xc0, 0xd0, 0xf1, 0x22, 0xc0, 0xa8, 
+    0xc2, 0xaf, 0x23, 0x6c, 0xaa, 0x2e, 0x54, 0x67, 0x4b, 0x0b, 0x58, 0x50, 0x89, 0x54, 0x01, 0x02, 
+    0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x31, 0xb0, 0x12, 0x7c, 0x15, 0x0a, 0x32, 0x09, 0xb3, 
+    0x67, 0x8e, 0x42, 0x32, 0x19, 0x43, 0x00, 0x36, 0xd0, 0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x3b, 
+    0x49, 0x33, 0x67, 0xcb, 0x0a, 0x22, 0x09, 0x32, 0x00, 0x36, 0x09, 0xb2, 0x67, 0x8e, 0xa5, 0xbb, 
+    0x00, 0x05, 0xf4, 0x52, 0x33, 0x80, 0x02, 0x42, 0x33, 0x89, 0x34, 0x67, 0xdb, 0x68, 0x09, 0x68, 
+    0x37, 0x68, 0x65, 0x68, 0x93, 0x68, 0xc1, 0x68, 0xef, 0x69, 0x1d, 0x12, 0x41, 0xb5, 0xd2, 0x28, 
+    0xd2, 0x08, 0xc2, 0x40, 0xc2, 0x48, 0xc2, 0x38, 0xc2, 0x30, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xcf, 
+    0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xaf, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xbf, 
+    0x12, 0x41, 0x16, 0x12, 0x60, 0xcf, 0x02, 0x69, 0x4b, 0x12, 0x41, 0xd4, 0xd2, 0x29, 0xd2, 0x09, 
+    0xc2, 0x41, 0xc2, 0x49, 0xc2, 0x39, 0xc2, 0x31, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd0, 0x7e, 0x04, 
+    0x00, 0x20, 0x7a, 0x07, 0x01, 0xb1, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc1, 0x12, 0x41, 
+    0x16, 0x12, 0x61, 0x05, 0x02, 0x69, 0x4b, 0x12, 0x41, 0xf3, 0xd2, 0x2a, 0xd2, 0x0a, 0xc2, 0x42, 
+    0xc2, 0x4a, 0xc2, 0x3a, 0xc2, 0x32, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd1, 0x7e, 0x04, 0x00, 0x20, 
+    0x7a, 0x07, 0x01, 0xb3, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc3, 0x12, 0x41, 0x16, 0x12, 
+    0x61, 0x3b, 0x02, 0x69, 0x4b, 0x12, 0x42, 0x12, 0xd2, 0x2b, 0xd2, 0x0b, 0xc2, 0x43, 0xc2, 0x4b, 
+    0xc2, 0x3b, 0xc2, 0x33, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd2, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 
+    0x01, 0xb5, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc5, 0x12, 0x41, 0x16, 0x12, 0x61, 0x71, 
+    0x02, 0x69, 0x4b, 0x12, 0x42, 0x31, 0xd2, 0x2c, 0xd2, 0x0c, 0xc2, 0x44, 0xc2, 0x4c, 0xc2, 0x3c, 
+    0xc2, 0x34, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd3, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xb7, 
+    0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc7, 0x12, 0x41, 0x16, 0x12, 0x61, 0xa7, 0x02, 0x69, 
+    0x4b, 0x12, 0x42, 0x50, 0xd2, 0x2d, 0xd2, 0x0d, 0xc2, 0x45, 0xc2, 0x4d, 0xc2, 0x3d, 0xc2, 0x35, 
+    0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd4, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xb9, 0x7e, 0x04, 
+    0x00, 0x38, 0x7a, 0x07, 0x01, 0xc9, 0x12, 0x41, 0x16, 0x12, 0x61, 0xdd, 0x02, 0x69, 0x4b, 0x12, 
+    0x42, 0x6f, 0xd2, 0x2e, 0xd2, 0x0e, 0xc2, 0x46, 0xc2, 0x4e, 0xc2, 0x3e, 0xc2, 0x36, 0x6d, 0x00, 
+    0x7a, 0x03, 0x01, 0xd5, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xbb, 0x7e, 0x04, 0x00, 0x38, 
+    0x7a, 0x07, 0x01, 0xcb, 0x12, 0x41, 0x16, 0x12, 0x62, 0x13, 0x02, 0x69, 0x4b, 0x12, 0x42, 0x8e, 
+    0xd2, 0x2f, 0xd2, 0x0f, 0xc2, 0x47, 0xc2, 0x4f, 0xc2, 0x3f, 0xc2, 0x37, 0x6d, 0x00, 0x7a, 0x03, 
+    0x01, 0xd6, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xbd, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 
+    0x01, 0xcd, 0x12, 0x41, 0x16, 0x12, 0x62, 0x49, 0x02, 0x69, 0x4b, 0x7e, 0xa0, 0xd0, 0x7e, 0x60, 
+    0x0f, 0x12, 0x62, 0xb6, 0x40, 0x0c, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 
+    0xc2, 0xd7, 0x22, 0x75, 0x31, 0xb1, 0x12, 0x7c, 0x15, 0x0a, 0x52, 0x23, 0x6d, 0x00, 0x59, 0x05, 
+    0x00, 0x48, 0x12, 0x41, 0x7e, 0x12, 0x41, 0x9a, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb2, 0x12, 0x7c, 
+    0x15, 0x0a, 0x22, 0x09, 0xb2, 0x67, 0x8e, 0x42, 0x23, 0x7e, 0xb0, 0x9c, 0x19, 0xb2, 0x01, 0xcf, 
+    0x12, 0x31, 0x85, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb7, 0x12, 0x7c, 0x15, 0x0a, 0x22, 0x09, 0xb2, 
+    0x67, 0x8e, 0x42, 0x24, 0x12, 0x35, 0x3d, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb9, 0x12, 0x7c, 0x15, 
+    0x0a, 0x32, 0x09, 0xb3, 0x67, 0x8e, 0x42, 0x34, 0x19, 0x43, 0x00, 0x3e, 0x12, 0x69, 0xc2, 0xd0, 
+    0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x0b, 0x7c, 0xb4, 0x20, 0xe0, 0x04, 0x6d, 0x33, 0x80, 0x04, 
+    0x49, 0x30, 0x01, 0x8f, 0x7e, 0xa0, 0xd8, 0xa5, 0xef, 0xca, 0x0b, 0xca, 0x29, 0x12, 0x62, 0xb6, 
+    0xda, 0x29, 0xda, 0x0b, 0x40, 0x62, 0x75, 0x31, 0xba, 0x12, 0x7c, 0x15, 0x7c, 0xb4, 0x30, 0xe0, 
+    0x1e, 0x6d, 0x33, 0x59, 0x30, 0x01, 0x8f, 0x7e, 0x34, 0x09, 0xe3, 0x0a, 0x82, 0x7e, 0x94, 0x04, 
+    0x00, 0xad, 0x89, 0x2d, 0x39, 0x59, 0x30, 0x01, 0x6f, 0x59, 0x30, 0x01, 0x7f, 0x7c, 0xb4, 0x30, 
+    0xe1, 0x10, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0xb0, 0x00, 0x08, 0x44, 0x04, 0x19, 0xb0, 
+    0x00, 0x08, 0x0a, 0x02, 0x09, 0xb0, 0x67, 0x8e, 0x42, 0x21, 0xf4, 0x52, 0x34, 0x7c, 0xb2, 0x23, 
+    0x0a, 0x0b, 0xca, 0x19, 0x49, 0x00, 0x30, 0xd5, 0x99, 0x04, 0xda, 0x19, 0xc0, 0xf1, 0x75, 0xf1, 
+    0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0xc2, 0xd7, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 
+    0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 
+    0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x12, 0x44, 0x40, 0xca, 0xb8, 0x09, 0xb0, 0x00, 0x10, 
+    0x44, 0x02, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x02, 0x54, 0xbf, 0x7c, 0x74, 0x5e, 0x70, 
+    0x08, 0x68, 0x04, 0x44, 0x08, 0x80, 0x02, 0x54, 0xf7, 0x09, 0x30, 0x00, 0x0c, 0xca, 0xb8, 0x74, 
+    0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xda, 0xb8, 0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 
+    0x62, 0x09, 0xb6, 0x67, 0x8e, 0x3e, 0x20, 0x0a, 0x62, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x20, 
+    0x42, 0x27, 0xca, 0xb8, 0x74, 0x61, 0x19, 0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x10, 0x59, 0x46, 
+    0x01, 0xbf, 0x09, 0xb0, 0x00, 0x10, 0x44, 0x01, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x11, 
+    0xf4, 0x52, 0x27, 0x74, 0xa1, 0x19, 0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x38, 0x59, 0x46, 0x01, 
+    0xbf, 0xd0, 0xa8, 0x22, 0x7c, 0x74, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x0a, 0x62, 0x09, 0xb6, 
+    0x67, 0x8e, 0xa5, 0xfd, 0xf4, 0xa5, 0xfe, 0xca, 0x28, 0x3e, 0x20, 0x0a, 0x62, 0xa5, 0xee, 0x52, 
+    0x26, 0x7e, 0x44, 0x00, 0x20, 0x59, 0x46, 0x01, 0xaf, 0xda, 0x28, 0x09, 0x30, 0x00, 0x0c, 0x74, 
+    0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x0c, 
+    0x44, 0x80, 0xca, 0xb8, 0xa5, 0xed, 0x42, 0x2a, 0xda, 0xb8, 0x80, 0x0a, 0x54, 0x7f, 0xca, 0xb8, 
+    0xa5, 0xee, 0x52, 0x2a, 0xda, 0xb8, 0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x02, 0x80, 
+    0x02, 0x54, 0xfd, 0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x02, 
+    0x68, 0x10, 0xa5, 0xed, 0x42, 0x28, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0xaf, 
+    0x80, 0x04, 0xa5, 0xee, 0x52, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x04, 0x68, 0x10, 0xa5, 0xed, 0x42, 
+    0x29, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0xaf, 0x80, 0x0b, 0xa5, 0xee, 0x52, 
+    0x29, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x78, 0x00, 0x12, 0x42, 0xad, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 
+    0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 
+    0x00, 0x10, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 
+    0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 0x00, 0x18, 0x19, 0x30, 0x00, 
+    0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb5, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 
+    0x09, 0xb0, 0x00, 0x0c, 0x44, 0x40, 0x19, 0xb0, 0x00, 0x0c, 0xe5, 0x6e, 0xb4, 0x07, 0x23, 0x09, 
+    0xb0, 0x00, 0x10, 0x4e, 0xb0, 0x02, 0x19, 0xb0, 0x00, 0x10, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 
+    0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x54, 0xf7, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 
+    0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb6, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x80, 0x00, 0x4c, 
+    0x02, 0xe5, 0x6e, 0xb4, 0x07, 0x18, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 
+    0x09, 0xb0, 0x00, 0x04, 0x44, 0x08, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 0x00, 0x0c, 0x09, 0xb0, 
+    0x00, 0x0c, 0x54, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb4, 0x12, 0x7c, 
+    0x15, 0x7a, 0x21, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x41, 0x31, 0x12, 0x7c, 0x15, 0x0a, 0x32, 0x09, 
+    0xb3, 0x67, 0x8e, 0x42, 0x35, 0x12, 0x6c, 0x5b, 0xd0, 0xa8, 0x22, 0x7e, 0xb0, 0x01, 0x7e, 0xa0, 
+    0xc8, 0x7c, 0x64, 0x12, 0x62, 0xb6, 0x40, 0x13, 0x0a, 0x32, 0x09, 0xb3, 0x67, 0x8e, 0xf4, 0x52, 
+    0x35, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x6c, 0x8c, 0x6c, 0xd3, 
+    0x6d, 0x1a, 0x6d, 0x61, 0x6d, 0xa8, 0x6d, 0xef, 0x6e, 0x36, 0x6e, 0x7d, 0x75, 0x31, 0x55, 0x12, 
+    0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 
+    0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x7f, 0x7e, 0x27, 0x01, 0x8f, 0x2d, 0x23, 0x7e, 0x09, 
+    0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x0d, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 
+    0x78, 0xec, 0x7a, 0x17, 0x01, 0x7f, 0x7a, 0x27, 0x01, 0x8f, 0x02, 0x46, 0x0f, 0x7e, 0x14, 0x09, 
+    0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x01, 0x12, 0x7c, 0x15, 0x7a, 
+    0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x81, 0x7e, 
+    0x27, 0x01, 0x91, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 
+    0x14, 0x11, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x81, 0x7a, 0x27, 0x01, 
+    0x91, 0x02, 0x49, 0x67, 0x7e, 0x14, 0x0d, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 
+    0x75, 0x31, 0x02, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0x7e, 0x17, 0x01, 0x83, 0x7e, 0x27, 0x01, 0x93, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 
+    0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x15, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 
+    0x7a, 0x17, 0x01, 0x83, 0x7a, 0x27, 0x01, 0x93, 0x02, 0x4c, 0xbf, 0x7e, 0x14, 0x11, 0xe3, 0x80, 
+    0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x03, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 
+    0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x85, 0x7e, 0x27, 0x01, 
+    0x95, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x19, 
+    0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x85, 0x7a, 0x27, 0x01, 0x95, 0x02, 
+    0x50, 0x17, 0x7e, 0x14, 0x15, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 
+    0x04, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 
+    0x7e, 0x17, 0x01, 0x87, 0x7e, 0x27, 0x01, 0x97, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 
+    0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x1d, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 
+    0x01, 0x87, 0x7a, 0x27, 0x01, 0x97, 0x02, 0x53, 0x6f, 0x7e, 0x14, 0x19, 0xe3, 0x80, 0xeb, 0x75, 
+    0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x05, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 
+    0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x89, 0x7e, 0x27, 0x01, 0x99, 0x2d, 
+    0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x21, 0xe2, 0x38, 
+    0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x89, 0x7a, 0x27, 0x01, 0x99, 0x02, 0x56, 0xc7, 
+    0x7e, 0x14, 0x1d, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x06, 0x12, 
+    0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 
+    0x01, 0x8b, 0x7e, 0x27, 0x01, 0x9b, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 
+    0x0b, 0x14, 0xbe, 0x14, 0x25, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x8b, 
+    0x7a, 0x27, 0x01, 0x9b, 0x02, 0x5a, 0x1f, 0x7e, 0x14, 0x21, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 
+    0x12, 0x7c, 0x15, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 
+    0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x8d, 0x7e, 0x27, 0x01, 0x9d, 0x2d, 0x23, 0x7e, 
+    0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x29, 0xe2, 0x38, 0x0f, 0x1b, 
+    0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x8d, 0x7a, 0x27, 0x01, 0x9d, 0x02, 0x5d, 0x77, 0x7e, 0x14, 
+    0x25, 0xe3, 0x80, 0xeb, 0xca, 0xb8, 0xc0, 0xf1, 0x75, 0x31, 0x02, 0x12, 0x7c, 0x15, 0xe5, 0xc0, 
+    0x54, 0x03, 0x68, 0x05, 0x12, 0x75, 0xcd, 0x80, 0xf5, 0x30, 0xc2, 0x08, 0x75, 0xf1, 0x01, 0x12, 
+    0x6f, 0xd9, 0x80, 0x14, 0x30, 0xc3, 0x08, 0x75, 0xf1, 0x01, 0x12, 0x6e, 0xfd, 0x80, 0x09, 0x30, 
+    0xc4, 0x06, 0x75, 0xf1, 0x02, 0x12, 0x70, 0xe9, 0xd0, 0xf1, 0xda, 0xb8, 0x32, 0x75, 0x31, 0x10, 
+    0x12, 0x7c, 0x15, 0xca, 0x0b, 0xca, 0x39, 0xca, 0x59, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x5c, 0xe5, 
+    0xe5, 0x54, 0xc0, 0x68, 0x4f, 0xe5, 0xe6, 0x6c, 0xaa, 0x7e, 0x37, 0x01, 0xdb, 0x2d, 0x35, 0xbe, 
+    0x34, 0x04, 0x00, 0x38, 0x4a, 0x7a, 0x37, 0x01, 0xdb, 0x7e, 0x37, 0x01, 0xd9, 0x7d, 0x43, 0x2d, 
+    0x45, 0xbe, 0x44, 0x09, 0xe2, 0x38, 0x40, 0x7a, 0x47, 0x01, 0xd9, 0x75, 0x31, 0x11, 0x12, 0x7c, 
+    0x15, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x71, 0xb8, 0xa9, 0x21, 0xe5, 0x1f, 0xa9, 0xd4, 
     0xe4, 0xa9, 0x24, 0xe4, 0xfc, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x3b, 0xe5, 0xe5, 0x54, 0xc0, 0x78, 
-    0xb4, 0x12, 0x76, 0x6a, 0xda, 0x59, 0xda, 0x39, 0xda, 0x0b, 0x22, 0x80, 0x29, 0x80, 0x58, 0x75, 
-    0x2f, 0x16, 0x12, 0x7e, 0x30, 0x80, 0xed, 0x75, 0x2f, 0x12, 0x12, 0x7e, 0x30, 0x7a, 0xb1, 0x2f
-    0x12, 0x7e, 0x30, 0x9e, 0x44, 0x09, 0xcd, 0x9d, 0x54, 0x12, 0x73, 0xc8, 0x7e, 0x34, 0x05, 0xcd
-    0x7d, 0x54, 0x2d, 0x43, 0x80, 0xa1, 0xe5, 0xe5, 0x54, 0x03, 0x78, 0x12, 0x75, 0x2f, 0x13, 0x12, 
-    0x7e, 0x30, 0x7e, 0x0f, 0x29, 0xe9, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xe9, 0x80, 0xa7, 0x75, 0x2f
-    0x14, 0x12, 0x7e, 0x30, 0x7e, 0x0f, 0x29, 0xed, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xed, 0xa9, 0xd7, 
-    0xe4, 0xa9, 0x27, 0xe4, 0xfc, 0x80, 0x9d, 0x75, 0x2f, 0x15, 0x12, 0x7e, 0x30, 0x7e, 0x0f, 0x29
-    0xf1, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf1, 0x80, 0xe5, 0x75, 0x2f, 0x18, 0x12, 0x7e, 0x30, 0xca, 
+    0xb4, 0x12, 0x74, 0x5a, 0xda, 0x59, 0xda, 0x39, 0xda, 0x0b, 0x22, 0x80, 0x29, 0x80, 0x58, 0x75, 
+    0x31, 0x16, 0x12, 0x7c, 0x15, 0x80, 0xed, 0x75, 0x31, 0x12, 0x12, 0x7c, 0x15, 0x7a, 0xb1, 0x31
+    0x12, 0x7c, 0x15, 0x9e, 0x44, 0x09, 0xe3, 0x9d, 0x54, 0x12, 0x71, 0xb8, 0x7e, 0x34, 0x05, 0xe3
+    0x7d, 0x54, 0x2d, 0x43, 0x80, 0xa1, 0xe5, 0xe5, 0x54, 0x03, 0x78, 0x12, 0x75, 0x31, 0x13, 0x12, 
+    0x7c, 0x15, 0x7e, 0x0f, 0x29, 0xff, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xff, 0x80, 0xa7, 0x75, 0x31
+    0x14, 0x12, 0x7c, 0x15, 0x7e, 0x0f, 0x2a, 0x03, 0x0b, 0x0c, 0x7a, 0x0f, 0x2a, 0x03, 0xa9, 0xd7, 
+    0xe4, 0xa9, 0x27, 0xe4, 0xfc, 0x80, 0x9d, 0x75, 0x31, 0x15, 0x12, 0x7c, 0x15, 0x7e, 0x0f, 0x2a
+    0x07, 0x0b, 0x0c, 0x7a, 0x0f, 0x2a, 0x07, 0x80, 0xe5, 0x75, 0x31, 0x18, 0x12, 0x7c, 0x15, 0xca, 
     0x09, 0xca, 0x39, 0xca, 0x2b, 0xc2, 0xc2, 0xa9, 0x21, 0xf2, 0x52, 0xe5, 0xf5, 0x33, 0x82, 0xe7, 
-    0x40, 0x44, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x54, 0x00, 0x40, 0x9d, 0x35, 0x40, 0x43, 0x7a, 0x37, 
-    0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc7, 0x7d, 0x43, 0x2d, 0x45, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x52, 
-    0x7a, 0x47, 0x01, 0xc7, 0x7d, 0x45, 0x12, 0x75, 0x26, 0xa9, 0x20, 0xf5, 0x22, 0x75, 0x2f, 0x19, 
-    0x12, 0x7e, 0x30, 0x7a, 0x91, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x81, 0xf7, 0x7a, 0x91, 0xf6, 0xe5, 
+    0x40, 0x44, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x54, 0x00, 0x40, 0x9d, 0x35, 0x40, 0x43, 0x7a, 0x37, 
+    0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdd, 0x7d, 0x43, 0x2d, 0x45, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x52, 
+    0x7a, 0x47, 0x01, 0xdd, 0x7d, 0x45, 0x12, 0x73, 0x16, 0xa9, 0x20, 0xf5, 0x22, 0x75, 0x31, 0x19, 
+    0x12, 0x7c, 0x15, 0x7a, 0x91, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x81, 0xf7, 0x7a, 0x91, 0xf6, 0xe5, 
     0xf5, 0x33, 0x82, 0xe7, 0x50, 0xbc, 0xda, 0x2b, 0xda, 0x39, 0xda, 0x09, 0x22, 0x80, 0x41, 0x80, 
-    0x64, 0x2d, 0x53, 0x6d, 0x33, 0x70, 0xb7, 0x7e, 0x04, 0x01, 0xcd, 0x7a, 0x07, 0x01, 0xc9, 0x7a, 
-    0x07, 0x01, 0xc7, 0xa9, 0x32, 0xf2, 0xdf, 0x85, 0x30, 0x2f, 0x12, 0x7e, 0x30, 0x75, 0xf6, 0x00, 
-    0x80, 0xd4, 0xca, 0x59, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x54, 0x12, 0x75, 0x26, 0x7e, 0x34, 0x01, 
-    0xcd, 0x7d, 0x54, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc7, 0x12, 0x75, 0x26, 0xda, 0x49, 0x80, 0x99, 
-    0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x0f, 0x29, 0xd9, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xd9
-    0x80, 0x9d, 0x7e, 0x0f, 0x29, 0xe1, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xe1, 0xa9, 0xd7, 0xf4, 0xa9, 
-    0x27, 0xf4, 0xfc, 0x80, 0x8a, 0x7e, 0x0f, 0x29, 0xdd, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xdd, 0x80, 
-    0xeb, 0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x2f, 0x29, 0xf9, 0x0b, 0x2c, 0x7a, 0x2f, 0x29
-    0xf9, 0x80, 0x34, 0x7e, 0x2f, 0x2a, 0x01, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x01, 0xa9, 0xd7, 0xf4, 
-    0xa9, 0x27, 0xf4, 0xfc, 0x80, 0x21, 0x7e, 0x2f, 0x29, 0xfd, 0x0b, 0x2c, 0x7a, 0x2f, 0x29, 0xfd
-    0x80, 0xeb, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x75, 0x2f, 0x28, 0x12, 0x7e, 0x30, 0xca, 
+    0x64, 0x2d, 0x53, 0x6d, 0x33, 0x70, 0xb7, 0x7e, 0x04, 0x01, 0xe3, 0x7a, 0x07, 0x01, 0xdf, 0x7a, 
+    0x07, 0x01, 0xdd, 0xa9, 0x32, 0xf2, 0xdf, 0x85, 0x30, 0x31, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x00, 
+    0x80, 0xd4, 0xca, 0x59, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x54, 0x12, 0x73, 0x16, 0x7e, 0x34, 0x01, 
+    0xe3, 0x7d, 0x54, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdd, 0x12, 0x73, 0x16, 0xda, 0x49, 0x80, 0x99, 
+    0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x0f, 0x29, 0xef, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xef
+    0x80, 0x9d, 0x7e, 0x0f, 0x29, 0xf7, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf7, 0xa9, 0xd7, 0xf4, 0xa9, 
+    0x27, 0xf4, 0xfc, 0x80, 0x8a, 0x7e, 0x0f, 0x29, 0xf3, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf3, 0x80, 
+    0xeb, 0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x2f, 0x2a, 0x0f, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a
+    0x0f, 0x80, 0x34, 0x7e, 0x2f, 0x2a, 0x17, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x17, 0xa9, 0xd7, 0xf4, 
+    0xa9, 0x27, 0xf4, 0xfc, 0x80, 0x21, 0x7e, 0x2f, 0x2a, 0x13, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x13
+    0x80, 0xeb, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x75, 0x31, 0x28, 0x12, 0x7c, 0x15, 0xca, 
     0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xc2, 0xc4, 0xa9, 0x21, 0xf2, 0xb6, 0xe5, 0xf5, 0x33, 0x72, 0xe7, 
-    0x40, 0xe0, 0x7e, 0x0d, 0x30, 0x7e, 0x1d, 0x34, 0x7e, 0x2d, 0x38, 0x7e, 0x3d, 0x3c, 0x7e, 0x85, 
-    0x40, 0x7d, 0x90, 0x4d, 0x91, 0x4d, 0x92, 0x4d, 0x93, 0x4d, 0x94, 0x4d, 0x95, 0x4d, 0x96, 0x4d, 
+    0x40, 0xe0, 0x7e, 0x0d, 0x46, 0x7e, 0x1d, 0x4a, 0x7e, 0x2d, 0x4e, 0x7e, 0x3d, 0x52, 0x7e, 0x85, 
+    0x56, 0x7d, 0x90, 0x4d, 0x91, 0x4d, 0x92, 0x4d, 0x93, 0x4d, 0x94, 0x4d, 0x95, 0x4d, 0x96, 0x4d, 
     0x97, 0x4d, 0x98, 0x68, 0x72, 0x7a, 0x11, 0xf3, 0x7a, 0x01, 0xf3, 0x7a, 0x31, 0xf3, 0x7a, 0x21, 
     0xf3, 0x7a, 0x51, 0xf3, 0x7a, 0x41, 0xf3, 0x7a, 0x71, 0xf3, 0x7a, 0x61, 0xf3, 0x7a, 0x91, 0xf3, 
-    0x7a, 0x81, 0xf3, 0x30, 0x73, 0x1a, 0x7a, 0xb1, 0xf3, 0x7a, 0xa1, 0xf3, 0x7a, 0xd1, 0xf3, 0x7a, 
+    0x7a, 0x81, 0xf3, 0x30, 0x7b, 0x1a, 0x7a, 0xb1, 0xf3, 0x7a, 0xa1, 0xf3, 0x7a, 0xd1, 0xf3, 0x7a, 
     0xc1, 0xf3, 0x7a, 0xf1, 0xf3, 0x7a, 0xe1, 0xf3, 0x7d, 0x78, 0x7a, 0xf1, 0xf3, 0x7a, 0xe1, 0xf3, 
-    0xa9, 0x30, 0xf5, 0x03, 0x02, 0x72, 0xe6, 0x75, 0x2f, 0x29, 0x12, 0x7e, 0x30, 0x20, 0x73, 0x0b, 
-    0x75, 0x2f, 0x0a, 0x12, 0x7e, 0x30, 0x75, 0xf6, 0x0a, 0x80, 0x09, 0x75, 0x2f, 0x12, 0x12, 0x7e
-    0x30, 0x75, 0xf6, 0x12, 0x6d, 0x00, 0x7d, 0x10, 0x7a, 0x0d, 0x30, 0x7a, 0x0d, 0x34, 0x7a, 0x0d, 
-    0x38, 0x7a, 0x0d, 0x3c, 0x7a, 0x05, 0x40, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x1e, 0xb0, 
-    0x40, 0x0c, 0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x75, 0x0b, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0xa1, 
+    0xa9, 0x30, 0xf5, 0x03, 0x02, 0x70, 0xd6, 0x75, 0x31, 0x29, 0x12, 0x7c, 0x15, 0x20, 0x7b, 0x0b, 
+    0x75, 0x31, 0x0a, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x0a, 0x80, 0x09, 0x75, 0x31, 0x12, 0x12, 0x7c
+    0x15, 0x75, 0xf6, 0x12, 0x6d, 0x00, 0x7d, 0x10, 0x7a, 0x0d, 0x46, 0x7a, 0x0d, 0x4a, 0x7a, 0x0d, 
+    0x4e, 0x7a, 0x0d, 0x52, 0x7a, 0x05, 0x56, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x1e, 0xb0, 
+    0x40, 0x0c, 0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x72, 0xfb, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0xa1, 
     0xe3, 0x7a, 0x39, 0xa0, 0x0b, 0x34, 0x80, 0xea, 0xb4, 0x40, 0xe3, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 
     0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 
     0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 
@@ -937,7 +1044,7 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
     0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 
     0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 
     0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x22, 0x1e, 0xb0, 0x40, 0x0c, 
-    0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x76, 0x69, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0x39, 0xa0, 0x7a, 
+    0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x74, 0x59, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0x39, 0xa0, 0x7a, 
     0xa1, 0xf3, 0x0b, 0x34, 0x80, 0xea, 0xb4, 0x40, 0xe3, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 
     0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 
     0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 
@@ -958,144 +1065,144 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
     0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 
     0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 
     0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 
-    0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x22, 0xc2, 0xaf, 0x7e, 0x37, 0x01, 0xc5
-    0x4d, 0x33, 0x68, 0x3b, 0x7e, 0x07, 0x01, 0xc1, 0x7e, 0x54, 0x09, 0xcd, 0x9d, 0x50, 0xbd, 0x35, 
-    0x40, 0x02, 0x7d, 0x35, 0xca, 0x39, 0x7e, 0x65, 0x4b, 0x99, 0x64, 0xda, 0x39, 0x7e, 0x07, 0x01, 
-    0xc5, 0x9d, 0x03, 0x7a, 0x07, 0x01, 0xc5, 0x2e, 0x37, 0x01, 0xc1, 0x7a, 0x37, 0x01, 0xc1, 0xbe, 
-    0x34, 0x09, 0xcc, 0x28, 0xc7, 0x7e, 0x34, 0x05, 0xcd, 0x7a, 0x37, 0x01, 0xc1, 0x80, 0xbd, 0xd2, 
-    0xaf, 0x22, 0x75, 0x2f, 0x53, 0x12, 0x7e, 0x30, 0x7e, 0x15, 0x4d, 0x80, 0x11, 0x75, 0x2f, 0x51, 
-    0x12, 0x7e, 0x30, 0x0b, 0x08, 0x10, 0x0b, 0x05, 0x9e, 0x34, 0x00, 0x02, 0x28, 0x4d, 0x7c, 0xb2, 
-    0x20, 0xe7, 0x27, 0x54, 0x07, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x6e, 0x8c, 0x7c, 0xb2, 0x54, 0x78, 
-    0x03, 0x03, 0x03, 0x7c, 0x2b, 0x9d, 0x13, 0x40, 0x1a, 0x68, 0x12, 0x7a, 0x15, 0x4d, 0x7a, 0x25, 
-    0x4f, 0x7e, 0x64, 0x77, 0x47, 0x7a, 0x65, 0x4b, 0x89, 0x24, 0x02, 0x77, 0x55, 0x7e, 0x64, 0x76
-    0xbd, 0x80, 0xf2, 0x2d, 0x13, 0x9d, 0x31, 0xca, 0x39, 0x7d, 0x31, 0x2d, 0x10, 0xca, 0x19, 0xca, 
-    0x29, 0x99, 0x24, 0xda, 0x29, 0xda, 0x09, 0xda, 0x39, 0x80, 0xa2, 0x7a, 0x15, 0x4d, 0x7e, 0x64, 
-    0x77, 0x33, 0x4d, 0x33, 0x78, 0x09, 0x7c, 0xb2, 0x20, 0xe7, 0x2a, 0x7e, 0x64, 0x76, 0xb2, 0x7a, 
-    0x65, 0x4b, 0x22, 0x75, 0x2f, 0x52, 0x12, 0x7e, 0x30, 0x7e, 0x21, 0x4d, 0x7e, 0x09, 0x30, 0x0b, 
-    0x04, 0x1b, 0x34, 0x78, 0x89, 0x80, 0xd4, 0x75, 0x2f, 0x54, 0x12, 0x7e, 0x30, 0x7e, 0x15, 0x4d
-    0x7e, 0x25, 0x4f, 0x80, 0x90, 0x5e, 0x20, 0x07, 0x54, 0x78, 0x7e, 0x44, 0x77, 0xd1, 0x30, 0xe6, 
-    0x16, 0x4d, 0x33, 0x68, 0x26, 0x1b, 0x34, 0x7e, 0x09, 0x40, 0x0b, 0x04, 0x7e, 0x44, 0x6a, 0x68
-    0x20, 0xe3, 0x04, 0x7e, 0x44, 0x77, 0xd9, 0xca, 0x09, 0xca, 0x39, 0x99, 0x44, 0xda, 0x39, 0xda, 
-    0x09, 0x7e, 0x64, 0x76, 0xbd, 0x4d, 0x33, 0x68, 0xa6, 0x89, 0x64, 0x7a, 0x15, 0x4d, 0xf5, 0x4f
-    0x7e, 0x64, 0x77, 0x96, 0x80, 0x99, 0x7e, 0x15, 0x4d, 0xe5, 0x4f, 0x80, 0xc4, 0xc0, 0xd0, 0xc0, 
-    0xd1, 0xc0, 0xe0, 0xca, 0x19, 0xa9, 0x20, 0xdf, 0x12, 0xa9, 0x21, 0xdf, 0x1b, 0x75, 0x2f, 0x01, 
-    0x12, 0x7e, 0x30, 0x53, 0xdf, 0xf7, 0x12, 0x40, 0xdc, 0x80, 0x0d, 0x75, 0x2f, 0xfe, 0x12, 0x7e
-    0x30, 0x7e, 0x14, 0x00, 0x53, 0x02, 0x40, 0x51, 0xda, 0x19, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 
-    0x32, 0x03, 0xa5, 0xcb, 0x19, 0xb1, 0x80, 0x00, 0x22, 0x22, 0x02, 0x78, 0x52, 0xca, 0x0b, 0xca, 
+    0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x22, 0xc2, 0xaf, 0x7e, 0x37, 0x01, 0xdb
+    0x4d, 0x33, 0x68, 0x3b, 0x7e, 0x07, 0x01, 0xd7, 0x7e, 0x54, 0x09, 0xe3, 0x9d, 0x50, 0xbd, 0x35, 
+    0x40, 0x02, 0x7d, 0x35, 0xca, 0x39, 0x7e, 0x65, 0x61, 0x99, 0x64, 0xda, 0x39, 0x7e, 0x07, 0x01, 
+    0xdb, 0x9d, 0x03, 0x7a, 0x07, 0x01, 0xdb, 0x2e, 0x37, 0x01, 0xd7, 0x7a, 0x37, 0x01, 0xd7, 0xbe, 
+    0x34, 0x09, 0xe2, 0x28, 0xc7, 0x7e, 0x34, 0x05, 0xe3, 0x7a, 0x37, 0x01, 0xd7, 0x80, 0xbd, 0xd2, 
+    0xaf, 0x22, 0x75, 0x31, 0x53, 0x12, 0x7c, 0x15, 0x7e, 0x15, 0x63, 0x80, 0x11, 0x75, 0x31, 0x51, 
+    0x12, 0x7c, 0x15, 0x0b, 0x08, 0x10, 0x0b, 0x05, 0x9e, 0x34, 0x00, 0x02, 0x28, 0x4d, 0x7c, 0xb2, 
+    0x20, 0xe7, 0x27, 0x54, 0x07, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x6c, 0x7c, 0x7c, 0xb2, 0x54, 0x78, 
+    0x03, 0x03, 0x03, 0x7c, 0x2b, 0x9d, 0x13, 0x40, 0x1a, 0x68, 0x12, 0x7a, 0x15, 0x63, 0x7a, 0x25, 
+    0x65, 0x7e, 0x64, 0x75, 0x37, 0x7a, 0x65, 0x61, 0x89, 0x24, 0x02, 0x75, 0x45, 0x7e, 0x64, 0x74
+    0xad, 0x80, 0xf2, 0x2d, 0x13, 0x9d, 0x31, 0xca, 0x39, 0x7d, 0x31, 0x2d, 0x10, 0xca, 0x19, 0xca, 
+    0x29, 0x99, 0x24, 0xda, 0x29, 0xda, 0x09, 0xda, 0x39, 0x80, 0xa2, 0x7a, 0x15, 0x63, 0x7e, 0x64, 
+    0x75, 0x23, 0x4d, 0x33, 0x78, 0x09, 0x7c, 0xb2, 0x20, 0xe7, 0x2a, 0x7e, 0x64, 0x74, 0xa2, 0x7a, 
+    0x65, 0x61, 0x22, 0x75, 0x31, 0x52, 0x12, 0x7c, 0x15, 0x7e, 0x21, 0x63, 0x7e, 0x09, 0x30, 0x0b, 
+    0x04, 0x1b, 0x34, 0x78, 0x89, 0x80, 0xd4, 0x75, 0x31, 0x54, 0x12, 0x7c, 0x15, 0x7e, 0x15, 0x63
+    0x7e, 0x25, 0x65, 0x80, 0x90, 0x5e, 0x20, 0x07, 0x54, 0x78, 0x7e, 0x44, 0x75, 0xc1, 0x30, 0xe6, 
+    0x16, 0x4d, 0x33, 0x68, 0x26, 0x1b, 0x34, 0x7e, 0x09, 0x40, 0x0b, 0x04, 0x7e, 0x44, 0x67, 0x63
+    0x20, 0xe3, 0x04, 0x7e, 0x44, 0x75, 0xc9, 0xca, 0x09, 0xca, 0x39, 0x99, 0x44, 0xda, 0x39, 0xda, 
+    0x09, 0x7e, 0x64, 0x74, 0xad, 0x4d, 0x33, 0x68, 0xa6, 0x89, 0x64, 0x7a, 0x15, 0x63, 0xf5, 0x65
+    0x7e, 0x64, 0x75, 0x86, 0x80, 0x99, 0x7e, 0x15, 0x63, 0xe5, 0x65, 0x80, 0xc4, 0xc0, 0xd0, 0xc0, 
+    0xd1, 0xc0, 0xe0, 0xca, 0x19, 0xa9, 0x20, 0xdf, 0x12, 0xa9, 0x21, 0xdf, 0x1b, 0x75, 0x31, 0x01, 
+    0x12, 0x7c, 0x15, 0x53, 0xdf, 0xf7, 0x12, 0x40, 0xdc, 0x80, 0x0d, 0x75, 0x31, 0xfe, 0x12, 0x7c
+    0x15, 0x7e, 0x14, 0x00, 0x53, 0x02, 0x40, 0x51, 0xda, 0x19, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 
+    0x32, 0x03, 0xa5, 0xcb, 0x19, 0xb1, 0x80, 0x00, 0x22, 0x22, 0x02, 0x76, 0x42, 0xca, 0x0b, 0xca, 
     0x1b, 0xca, 0x2b, 0xca, 0x3b, 0xca, 0x4b, 0xca, 0x5b, 0xca, 0x6b, 0xca, 0x7b, 0xca, 0xeb, 0xc0, 
-    0xf1, 0x7e, 0xb3, 0x2a, 0x1d, 0xb4, 0x00, 0x02, 0x80, 0x19, 0xb4, 0x01, 0x16, 0x30, 0xc0, 0x08, 
-    0x75, 0xf1, 0x00, 0x12, 0x78, 0x3c, 0x80, 0x1f, 0x30, 0xc1, 0x1c, 0x75, 0xf1, 0x00, 0x12, 0x78
-    0xcd, 0x80, 0x14, 0x30, 0xc1, 0x08, 0x75, 0xf1, 0x00, 0x12, 0x78, 0xcd, 0x80, 0x09, 0x30, 0xc0, 
-    0x06, 0x75, 0xf1, 0x00, 0x12, 0x78, 0x3c, 0xd0, 0xf1, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, 
+    0xf1, 0x7e, 0xb3, 0x2a, 0x33, 0xb4, 0x00, 0x02, 0x80, 0x19, 0xb4, 0x01, 0x16, 0x30, 0xc0, 0x08, 
+    0x75, 0xf1, 0x00, 0x12, 0x76, 0x2c, 0x80, 0x1f, 0x30, 0xc1, 0x1c, 0x75, 0xf1, 0x00, 0x12, 0x76
+    0xbd, 0x80, 0x14, 0x30, 0xc1, 0x08, 0x75, 0xf1, 0x00, 0x12, 0x76, 0xbd, 0x80, 0x09, 0x30, 0xc0, 
+    0x06, 0x75, 0xf1, 0x00, 0x12, 0x76, 0x2c, 0xd0, 0xf1, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, 
     0x5b, 0xda, 0x4b, 0xda, 0x3b, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0xc2, 0xc0, 0x7e, 0xb3, 
-    0x2a, 0x1d, 0xb4, 0x02, 0x07, 0x12, 0x78, 0x5e, 0x02, 0x78, 0x52, 0x22, 0xb4, 0x01, 0xfc, 0x02, 
-    0x78, 0x98, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x2a, 0x1d, 0x7a, 0x03, 0x2a, 0x1e, 0x22, 0x7e, 0xb3, 
-    0x2a, 0x15, 0x54, 0x60, 0x60, 0x05, 0xb4, 0x40, 0x15, 0x80, 0x13, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 
-    0x05, 0x0c, 0x75, 0x2f, 0x71, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xf5, 0x8f, 0x22, 0x75, 
-    0xf6, 0x00, 0x22, 0xbe, 0x57, 0x2a, 0x1b, 0x28, 0x04, 0x7e, 0x57, 0x2a, 0x1b, 0x7a, 0x0f, 0x2a, 
-    0x20, 0x7a, 0x57, 0x2a, 0x24, 0x02, 0x78, 0x98, 0x7e, 0xef, 0x2a, 0x20, 0x7e, 0xf7, 0x2a, 0x24
-    0x7e, 0x07, 0x2a, 0x24, 0x4d, 0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0x7e, 0xeb, 0xb0, 0xf5, 0xf3, 
-    0xa3, 0xa5, 0x08, 0x1b, 0xf4, 0x68, 0x04, 0xa5, 0xb8, 0x08, 0xf0, 0x7a, 0xef, 0x2a, 0x20, 0x7a, 
-    0xf7, 0x2a, 0x24, 0x75, 0x2f, 0x06, 0x12, 0x7e, 0x30, 0x7a, 0x01, 0xf6, 0x22, 0xc2, 0xc1, 0x75, 
-    0x2f, 0x03, 0x12, 0x7e, 0x30, 0xa9, 0x36, 0xe2, 0x16, 0xe5, 0xf5, 0x54, 0xc0, 0x68, 0x07, 0xa9, 
-    0xd7, 0xf4, 0xa9, 0x27, 0xf4, 0xfc, 0x53, 0xe1, 0x3f, 0x43, 0xf2, 0x88, 0x02, 0x79, 0x44, 0x7e, 
-    0xb3, 0x2a, 0x1e, 0xb4, 0x02, 0x0f, 0xa9, 0xd4, 0xe4, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x2a, 0x1e
-    0x7a, 0xb3, 0x2a, 0x1d, 0x22, 0xb4, 0x01, 0x39, 0x7e, 0x21, 0xe6, 0x7c, 0x32, 0x7e, 0x13, 0x2a
-    0x1f, 0x2c, 0x21, 0x7a, 0x23, 0x2a, 0x1f, 0x7e, 0x00, 0x00, 0x2e, 0x04, 0x2a, 0x26, 0xe5, 0xe3
-    0x7a, 0x09, 0xb0, 0x0b, 0x04, 0xa5, 0xdb, 0xf6, 0xa9, 0xd4, 0xe4, 0x75, 0x2f, 0x70, 0x12, 0x7e
-    0x30, 0x7e, 0xb3, 0x2a, 0x1f, 0x7e, 0xa3, 0x2a, 0x1c, 0xbc, 0xab, 0x78, 0x03, 0x12, 0x79, 0xdb
-    0x22, 0x02, 0x7d, 0x44, 0xe5, 0xe6, 0xb4, 0x08, 0x65, 0xa9, 0xc4, 0xe2, 0x7e, 0x01, 0xe3, 0x7e
-    0x11, 0xe3, 0x7e, 0x31, 0xe3, 0x7e, 0x21, 0xe3, 0x7e, 0x51, 0xe3, 0x7e, 0x41, 0xe3, 0x7e, 0x71
-    0xe3, 0x7e, 0x61, 0xe3, 0x7a, 0x0f, 0x2a, 0x15, 0x7a, 0x1f, 0x2a, 0x19, 0x75, 0x2f, 0x04, 0x12
-    0x7e, 0x30, 0x7a, 0x01, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x21
-    0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x31, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x41, 0x2f, 0x12, 0x7e, 0x30
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
-    0x7e, 0x30, 0xa9, 0xd4, 0xe4, 0xa9, 0xd7, 0xf4, 0xa9, 0xc6, 0xe2, 0x12, 0x79, 0xaf, 0x22, 0x6d
-    0x00, 0x7e, 0x14, 0x01, 0x02, 0x7a, 0x07, 0x2a, 0x24, 0x7a, 0x03, 0x2a, 0x1f, 0x7e, 0xb3, 0x2a, 
-    0x15, 0x20, 0xe7, 0x0f, 0x7a, 0x23, 0x2a, 0x1e, 0x7a, 0x33, 0x2a, 0x1d, 0xbe, 0x07, 0x2a, 0x1b
-    0x68, 0x09, 0x22, 0x7a, 0x33, 0x2a, 0x1e, 0x7a, 0x23, 0x2a, 0x1d, 0x7e, 0xb3, 0x2a, 0x15, 0x54
-    0xe3, 0x23, 0x23, 0x30, 0xe0, 0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02, 0xd2, 0xe4, 0x30, 0xe5, 0x06
-    0x30, 0xe4, 0x03, 0x02, 0x7d, 0x44, 0x54, 0x3e, 0xf5, 0xf0, 0x03, 0x54, 0x1f, 0xc3, 0x25, 0xf0
-    0x90, 0x7a, 0x07, 0x75, 0x84, 0xff, 0x73, 0x02, 0x7b, 0x5b, 0x02, 0x7a, 0x4f, 0x02, 0x7b, 0xf8
-    0x02, 0x7c, 0x13, 0x02, 0x7a, 0xf4, 0x02, 0x7a, 0xb5, 0x02, 0x7c, 0x2c, 0x02, 0x7c, 0x2c, 0x02
-    0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c
-    0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x35, 0x02, 0x7c, 0xe9, 0x02, 0x7c, 0x32
-    0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x7e
-    0xb3, 0x2a, 0x16, 0xb4, 0x06, 0x2a, 0x7e, 0xb3, 0x2a, 0x17, 0x60, 0x56, 0x7c, 0x0b, 0x7e, 0x13
-    0x2a, 0x18, 0x7e, 0x17, 0x2a, 0x19, 0x75, 0x2f, 0x72, 0x12, 0x7e, 0x30, 0x7a, 0x01, 0x2f, 0x12
-    0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x7d, 0x4e, 0x40, 0x35, 0x02, 0x78, 0x83, 
-    0xb4, 0x08, 0x10, 0x75, 0x2f, 0x74, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x3f, 0xf1, 0xf5, 0xf3, 0x75
-    0xf6, 0x01, 0x22, 0xb4, 0x00, 0x1c, 0x75, 0x2f, 0x75, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x3f, 0xf2
-    0x30, 0xe0, 0x05, 0x75, 0xf3, 0x02, 0x80, 0x03, 0x75, 0xf3, 0x00, 0x75, 0xf3, 0x00, 0x75, 0xf6
-    0x02, 0x22, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x00, 0x35, 0x75, 0x2f, 0x76, 0x12
-    0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0xf5, 0xf1, 0x7e, 0xb3, 0x2a, 0x1a, 0x20, 0xe7
-    0x09, 0xe5, 0xe1, 0x30, 0xe7, 0x0d, 0x74, 0x01, 0x80, 0x0b, 0xe5, 0xe1, 0x30, 0xe6, 0x04, 0x74
-    0x01, 0x80, 0x02, 0x74, 0x00, 0x53, 0xf1, 0x80, 0xf5, 0xf3, 0x75, 0xf3, 0x00, 0x75, 0xf6, 0x02
-    0x22, 0x02, 0x7d, 0x44, 0xc0, 0xf1, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0x42, 0xf1, 0x7e, 0xb3
-    0x2a, 0x18, 0xb4, 0x00, 0x45, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x01, 0x24, 0x75, 0x2f, 0x77, 0x12
-    0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0x78, 0x05, 0x53, 0xe1, 0x3f, 0x80, 0x37, 0x7e
-    0xb3, 0x2a, 0x1a, 0x20, 0xe7, 0x05, 0x53, 0xe1, 0x7f, 0x80, 0x2b, 0x53, 0xe1, 0xbf, 0x80, 0x26
-    0xb4, 0x03, 0x17, 0x75, 0x2f, 0x78, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x20, 0xe7, 0x05
-    0x43, 0xe1, 0x80, 0x80, 0x11, 0x43, 0xe1, 0x40, 0x80, 0x0c, 0x43, 0xe1, 0xc0, 0xd0, 0xf1, 0x75
-    0x2f, 0x07, 0x12, 0x7e, 0x30, 0x22, 0xd0, 0xf1, 0x02, 0x78, 0x7f, 0x7e, 0xb3, 0x2a, 0x16, 0xb4
-    0x09, 0x23, 0x75, 0x2f, 0x79, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xbe, 0xb3, 0x3f, 0xf1, 
-    0x68, 0x11, 0xca, 0xb8, 0xc0, 0xf1, 0x12, 0x43, 0x68, 0xd0, 0xf1, 0xda, 0xb8, 0x50, 0x76, 0x7a, 
-    0xb3, 0x3f, 0xf1, 0x80, 0x6d, 0xb4, 0x05, 0x08, 0x75, 0x2f, 0x7a, 0x12, 0x7e, 0x30, 0x80, 0x62
-    0xb4, 0x03, 0x19, 0x75, 0x2f, 0x7b, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xb4, 0x01, 0x55
-    0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x46, 0xb4, 0x01, 0x19, 0x75
-    0x2f, 0x7c, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xb4, 0x01, 0x39, 0x7e, 0xb3, 0x3f, 0xf2
-    0x54, 0xfe, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a, 0x7e, 0xb3, 0x2a, 0x17, 0x60
-    0x24, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x18, 0x7e, 0x17, 0x2a, 0x19, 0x75, 0x2f, 0x73, 0x12, 0x7e
-    0x30, 0x7a, 0x01, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x7d, 0x7a, 
-    0x40, 0x03, 0x02, 0x78, 0x7f, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x0b, 0xf6, 0x75
-    0x2f, 0x7d, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0x7e, 0xa3, 0x2a, 0x1a, 0x4c, 0xab, 0x78
-    0xe4, 0x80, 0xdf, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x0a, 0xdb, 0x75, 0x2f, 0x7e, 0x12, 0x7e, 0x30
-    0x7e, 0xb3, 0x2a, 0x18, 0x70, 0xcf, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 0x22, 0x02, 0x7d, 0x44, 0x02
-    0x7d, 0x44, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x04, 0x20, 0x75, 0x2f, 0xc3, 0x12
-    0x7e, 0x30, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x17, 0x7e, 0x18, 0x2a, 0x26, 0x7a, 0x1c
-    0x00, 0x00, 0x7e, 0x47, 0x2a, 0x1b, 0x12, 0x7e, 0x3c, 0x02, 0x7c, 0xe3, 0xb4, 0x06, 0x3a, 0x75
-    0x2f, 0xc1, 0x12, 0x7e, 0x30, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7d, 0xca, 0x7e
-    0xd7, 0x2a, 0x17, 0x7e, 0x78, 0x2a, 0x26, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2a, 0x1b, 0x75
-    0x2f, 0xc1, 0x12, 0x7e, 0x30, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7e
-    0x75, 0xd0, 0x87, 0xd0, 0xa8, 0x40, 0x4f, 0x80, 0x4a, 0xb4, 0x00, 0x1c, 0xc2, 0xaf, 0xa9, 0xd5
-    0x87, 0x12, 0x78, 0x7f, 0xe4, 0x8d, 0xef, 0x8d, 0xef, 0x8d, 0xef, 0xd5, 0xe0, 0xf7, 0xc0, 0xd1
-    0xca, 0x02, 0xff, 0xca, 0x06, 0x00, 0x00, 0x32, 0xb4, 0x09, 0x12, 0x7e, 0x57, 0x2a, 0x17, 0x4d
-    0x55, 0x68, 0x05, 0xa9, 0xd2, 0xb1, 0x80, 0x03, 0xa9, 0xc2, 0xb1, 0x80, 0x16, 0xb4, 0x07, 0x16
-    0xc2, 0xaf, 0x7e, 0x07, 0x2a, 0x19, 0x7e, 0x17, 0x2a, 0x17, 0xc0, 0xd1, 0xca, 0x18, 0xca, 0x38
-    0xca, 0x28, 0x32, 0x02, 0x78, 0x7f, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x03, 0x15
-    0x75, 0x2f, 0xc2, 0x12, 0x7e, 0x30, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x17, 0x7e, 0x57
-    0x2a, 0x1b, 0x02, 0x78, 0x83, 0xb4, 0x05, 0x39, 0x75, 0x2f, 0xc0, 0x12, 0x7e, 0x30, 0xc0, 0xa8
-    0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x7e, 0x08, 0x2a, 0x26, 0x7a, 0x0c, 0x00, 0x00, 0x7e
-    0x24, 0x00, 0xfe, 0x7e, 0x37, 0x2a, 0x17, 0x7e, 0x47, 0x2a, 0x1b, 0x12, 0x7e, 0x3c, 0xd0, 0x87
-    0xd0, 0xa8, 0x7e, 0x08, 0x2a, 0x26, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x57, 0x2a, 0x1b, 0x02, 0x78
-    0x83, 0x02, 0x7d, 0x44, 0x75, 0x2f, 0x07, 0x12, 0x7e, 0x30, 0x43, 0xe1, 0xc0, 0x22, 0xc0, 0xa8
-    0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7d, 0xb9, 0x40, 0x19, 0x7e, 0x08, 0x2a, 0x26
-    0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0xca, 0x49, 0x12, 0x7e, 0x3c, 0xda, 0x59, 0xda, 0x0b, 0xd0, 
-    0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0x22, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf
-    0xa9, 0xd5, 0x87, 0x12, 0x7d, 0xb9, 0x40, 0x2b, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 
-    0x7f, 0x61, 0x7e, 0x78, 0x2a, 0x26, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2a, 0x1b, 0xbd, 0x74
-    0x78, 0x11, 0x75, 0x2f, 0xc1, 0x12, 0x7e, 0x30, 0x12, 0x7e, 0x75, 0x40, 0x06, 0xd0, 0x87, 0xd0
-    0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0xd3, 0x22, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x34, 0x7f
-    0xca, 0x0b, 0x1a, 0x50, 0xc5, 0xf0, 0x7d, 0x62, 0x7d, 0x75, 0x7d, 0x87, 0x7e, 0x34, 0x7f, 0xc2
-    0x7e, 0x1b, 0xb0, 0x7e, 0x34, 0x7f, 0x03, 0xb4, 0x01, 0x04, 0x7e, 0x34, 0x7f, 0xcc, 0x7e, 0x1b
-    0xb0, 0xbc, 0x0b, 0x50, 0x49, 0x3e, 0x00, 0x3e, 0x00, 0x0a, 0x50, 0x2d, 0x75, 0x0b, 0x3a, 0x30
-    0x69, 0x53, 0x00, 0x02, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbc, 0x1b, 0x50, 0x30, 0x3e, 0x10
-    0x3e, 0x10, 0x0a, 0x51, 0x2d, 0x35, 0x69, 0x41, 0x00, 0x02, 0x0b, 0x1a, 0x30, 0xbd, 0x38, 0x50
-    0x02, 0x2d, 0x38, 0xbe, 0x44, 0xff, 0xff, 0x78, 0x05, 0x7e, 0x1b, 0x90, 0x0a, 0x49, 0x4d, 0x44
-    0x68, 0x0c, 0xbe, 0x44, 0x00, 0xff, 0x28, 0x04, 0x7e, 0x44, 0x00, 0xff, 0xc3, 0x22, 0xd3, 0x22, 
+    0x2a, 0x33, 0xb4, 0x02, 0x07, 0x12, 0x76, 0x4e, 0x02, 0x76, 0x42, 0x22, 0xb4, 0x01, 0xfc, 0x02, 
+    0x76, 0x88, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x2a, 0x33, 0x7a, 0x03, 0x2a, 0x34, 0x22, 0x7e, 0xb3, 
+    0x2a, 0x2b, 0x54, 0x60, 0x60, 0x05, 0xb4, 0x40, 0x15, 0x80, 0x13, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 
+    0x05, 0x0c, 0x75, 0x31, 0x71, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0xf5, 0x8f, 0x22, 0x75, 
+    0xf6, 0x00, 0x22, 0xbe, 0x57, 0x2a, 0x31, 0x28, 0x04, 0x7e, 0x57, 0x2a, 0x31, 0x7a, 0x0f, 0x2a, 
+    0x36, 0x7a, 0x57, 0x2a, 0x3a, 0x02, 0x76, 0x88, 0x7e, 0xef, 0x2a, 0x36, 0x7e, 0xf7, 0x2a, 0x3a
+    0x7e, 0x07, 0x2a, 0x3a, 0x4d, 0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0x7e, 0xeb, 0xb0, 0xf5, 0xf3, 
+    0xa3, 0xa5, 0x08, 0x1b, 0xf4, 0x68, 0x04, 0xa5, 0xb8, 0x08, 0xf0, 0x7a, 0xef, 0x2a, 0x36, 0x7a, 
+    0xf7, 0x2a, 0x3a, 0x75, 0x31, 0x06, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0xf6, 0x22, 0xc2, 0xc1, 0x75, 
+    0x31, 0x03, 0x12, 0x7c, 0x15, 0xa9, 0x36, 0xe2, 0x16, 0xe5, 0xf5, 0x54, 0xc0, 0x68, 0x07, 0xa9, 
+    0xd7, 0xf4, 0xa9, 0x27, 0xf4, 0xfc, 0x53, 0xe1, 0x3f, 0x43, 0xf2, 0x88, 0x02, 0x77, 0x29, 0x7e, 
+    0xb3, 0x2a, 0x34, 0xb4, 0x02, 0x04, 0xa9, 0xd4, 0xe4, 0x22, 0xb4, 0x01, 0x39, 0x7e, 0x21, 0xe6
+    0x7c, 0x32, 0x7e, 0x13, 0x2a, 0x35, 0x2c, 0x21, 0x7a, 0x23, 0x2a, 0x35, 0x7e, 0x00, 0x00, 0x2e
+    0x04, 0x2a, 0x3c, 0xe5, 0xe3, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0xa5, 0xdb, 0xf6, 0xa9, 0xd4, 0xe4
+    0x75, 0x31, 0x70, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x35, 0x7e, 0xa3, 0x2a, 0x32, 0xbc, 0xab
+    0x78, 0x03, 0x12, 0x77, 0xc0, 0x22, 0x02, 0x7b, 0x29, 0xe5, 0xe6, 0xb4, 0x08, 0x65, 0xa9, 0xc4
+    0xe2, 0x7e, 0x01, 0xe3, 0x7e, 0x11, 0xe3, 0x7e, 0x31, 0xe3, 0x7e, 0x21, 0xe3, 0x7e, 0x51, 0xe3
+    0x7e, 0x41, 0xe3, 0x7e, 0x71, 0xe3, 0x7e, 0x61, 0xe3, 0x7a, 0x0f, 0x2a, 0x2b, 0x7a, 0x1f, 0x2a
+    0x2f, 0x75, 0x31, 0x04, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31
+    0x12, 0x7c, 0x15, 0x7a, 0x21, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x31, 0x31, 0x12, 0x7c, 0x15, 0x7a
+    0x41, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c
+    0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xa9, 0xd4, 0xe4, 0xa9, 0xd7, 0xf4, 0xa9, 0xc6, 0xe2, 
+    0x12, 0x77, 0x94, 0x22, 0x6d, 0x00, 0x7e, 0x14, 0x01, 0x02, 0x7a, 0x07, 0x2a, 0x3a, 0x7a, 0x03
+    0x2a, 0x35, 0x7e, 0xb3, 0x2a, 0x2b, 0x20, 0xe7, 0x0f, 0x7a, 0x23, 0x2a, 0x34, 0x7a, 0x33, 0x2a, 
+    0x33, 0xbe, 0x07, 0x2a, 0x31, 0x68, 0x09, 0x22, 0x7a, 0x33, 0x2a, 0x34, 0x7a, 0x23, 0x2a, 0x33
+    0x7e, 0xb3, 0x2a, 0x2b, 0x54, 0xe3, 0x23, 0x23, 0x30, 0xe0, 0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02
+    0xd2, 0xe4, 0x30, 0xe5, 0x06, 0x30, 0xe4, 0x03, 0x02, 0x7b, 0x29, 0x54, 0x3e, 0xf5, 0xf0, 0x03
+    0x54, 0x1f, 0xc3, 0x25, 0xf0, 0x90, 0x77, 0xec, 0x75, 0x84, 0xff, 0x73, 0x02, 0x79, 0x40, 0x02
+    0x78, 0x34, 0x02, 0x79, 0xdd, 0x02, 0x79, 0xf8, 0x02, 0x78, 0xd9, 0x02, 0x78, 0x9a, 0x02, 0x7a
+    0x11, 0x02, 0x7a, 0x11, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14
+    0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x1a, 0x02
+    0x7a, 0xce, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a
+    0x17, 0x02, 0x7a, 0x17, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x06, 0x2a, 0x7e, 0xb3, 0x2a, 0x2d, 0x60
+    0x56, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x2e, 0x7e, 0x17, 0x2a, 0x2f, 0x75, 0x31, 0x72, 0x12, 0x7c
+    0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x7b, 0x33
+    0x40, 0x35, 0x02, 0x76, 0x73, 0xb4, 0x08, 0x10, 0x75, 0x31, 0x74, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 
+    0x3f, 0xf1, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 0x22, 0xb4, 0x00, 0x1c, 0x75, 0x31, 0x75, 0x12, 0x7c
+    0x15, 0x7e, 0xb3, 0x3f, 0xf2, 0x30, 0xe0, 0x05, 0x75, 0xf3, 0x02, 0x80, 0x03, 0x75, 0xf3, 0x00
+    0x75, 0xf3, 0x00, 0x75, 0xf6, 0x02, 0x22, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x00
+    0x35, 0x75, 0x31, 0x76, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x30, 0x54, 0x0f, 0xf5, 0xf1, 0x7e
+    0xb3, 0x2a, 0x30, 0x20, 0xe7, 0x09, 0xe5, 0xe1, 0x30, 0xe7, 0x0d, 0x74, 0x01, 0x80, 0x0b, 0xe5
+    0xe1, 0x30, 0xe6, 0x04, 0x74, 0x01, 0x80, 0x02, 0x74, 0x00, 0x53, 0xf1, 0x80, 0xf5, 0xf3, 0x75
+    0xf3, 0x00, 0x75, 0xf6, 0x02, 0x22, 0x02, 0x7b, 0x29, 0xc0, 0xf1, 0x7e, 0xb3, 0x2a, 0x30, 0x54
+    0x0f, 0x42, 0xf1, 0x7e, 0xb3, 0x2a, 0x2e, 0xb4, 0x00, 0x45, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x01
+    0x24, 0x75, 0x31, 0x77, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x30, 0x54, 0x0f, 0x78, 0x05, 0x53
+    0xe1, 0x3f, 0x80, 0x37, 0x7e, 0xb3, 0x2a, 0x30, 0x20, 0xe7, 0x05, 0x53, 0xe1, 0x7f, 0x80, 0x2b
+    0x53, 0xe1, 0xbf, 0x80, 0x26, 0xb4, 0x03, 0x17, 0x75, 0x31, 0x78, 0x12, 0x7c, 0x15, 0x7e, 0xb3
+    0x2a, 0x30, 0x20, 0xe7, 0x05, 0x43, 0xe1, 0x80, 0x80, 0x11, 0x43, 0xe1, 0x40, 0x80, 0x0c, 0x43
+    0xe1, 0xc0, 0xd0, 0xf1, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x22, 0xd0, 0xf1, 0x02, 0x76, 0x6f
+    0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x09, 0x23, 0x75, 0x31, 0x79, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a
+    0x2e, 0xbe, 0xb3, 0x3f, 0xf1, 0x68, 0x11, 0xca, 0xb8, 0xc0, 0xf1, 0x12, 0x43, 0xd4, 0xd0, 0xf1, 
+    0xda, 0xb8, 0x50, 0x76, 0x7a, 0xb3, 0x3f, 0xf1, 0x80, 0x6d, 0xb4, 0x05, 0x08, 0x75, 0x31, 0x7a, 
+    0x12, 0x7c, 0x15, 0x80, 0x62, 0xb4, 0x03, 0x19, 0x75, 0x31, 0x7b, 0x12, 0x7c, 0x15, 0x7e, 0xb3
+    0x2a, 0x2e, 0xb4, 0x01, 0x55, 0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80
+    0x46, 0xb4, 0x01, 0x19, 0x75, 0x31, 0x7c, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0xb4, 0x01
+    0x39, 0x7e, 0xb3, 0x3f, 0xf2, 0x54, 0xfe, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a
+    0x7e, 0xb3, 0x2a, 0x2d, 0x60, 0x24, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x2e, 0x7e, 0x17, 0x2a, 0x2f
+    0x75, 0x31, 0x73, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31, 0x12
+    0x7c, 0x15, 0x12, 0x7b, 0x5f, 0x40, 0x03, 0x02, 0x76, 0x6f, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, 
+    0x2c, 0xb4, 0x0b, 0xf6, 0x75, 0x31, 0x7d, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0x7e, 0xa3
+    0x2a, 0x30, 0x4c, 0xab, 0x78, 0xe4, 0x80, 0xdf, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x0a, 0xdb, 0x75
+    0x31, 0x7e, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0x70, 0xcf, 0xf5, 0xf3, 0x75, 0xf6, 0x01
+    0x22, 0x02, 0x7b, 0x29, 0x02, 0x7b, 0x29, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x04
+    0x20, 0x75, 0x31, 0xc3, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x2d, 0x7e
+    0x18, 0x2a, 0x3c, 0x7a, 0x1c, 0x00, 0x00, 0x7e, 0x47, 0x2a, 0x31, 0x12, 0x7c, 0x21, 0x02, 0x7a
+    0xc8, 0xb4, 0x06, 0x3a, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c
+    0x00, 0xfe, 0x7d, 0xca, 0x7e, 0xd7, 0x2a, 0x2d, 0x7e, 0x78, 0x2a, 0x3c, 0x7a, 0x7c, 0x00, 0x00
+    0x7e, 0x77, 0x2a, 0x31, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf
+    0xa9, 0xd5, 0x87, 0x12, 0x7c, 0x5a, 0xd0, 0x87, 0xd0, 0xa8, 0x40, 0x4f, 0x80, 0x4a, 0xb4, 0x00
+    0x1c, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x76, 0x6f, 0xe4, 0x8d, 0xef, 0x8d, 0xef, 0x8d, 0xef
+    0xd5, 0xe0, 0xf7, 0xc0, 0xd1, 0xca, 0x02, 0xff, 0xca, 0x06, 0x00, 0x00, 0x32, 0xb4, 0x09, 0x12
+    0x7e, 0x57, 0x2a, 0x2d, 0x4d, 0x55, 0x68, 0x05, 0xa9, 0xd2, 0xb1, 0x80, 0x03, 0xa9, 0xc2, 0xb1
+    0x80, 0x16, 0xb4, 0x07, 0x16, 0xc2, 0xaf, 0x7e, 0x07, 0x2a, 0x2f, 0x7e, 0x17, 0x2a, 0x2d, 0xc0
+    0xd1, 0xca, 0x18, 0xca, 0x38, 0xca, 0x28, 0x32, 0x02, 0x76, 0x6f, 0x02, 0x7b, 0x29, 0x7e, 0xb3
+    0x2a, 0x2c, 0xb4, 0x03, 0x15, 0x75, 0x31, 0xc2, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x00, 0x01, 0x7e
+    0x17, 0x2a, 0x2d, 0x7e, 0x57, 0x2a, 0x31, 0x02, 0x76, 0x73, 0xb4, 0x05, 0x39, 0x75, 0x31, 0xc0
+    0x12, 0x7c, 0x15, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x7e, 0x08, 0x2a, 0x3c
+    0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x37, 0x2a, 0x2d, 0x7e, 0x47, 0x2a, 0x31
+    0x12, 0x7c, 0x21, 0xd0, 0x87, 0xd0, 0xa8, 0x7e, 0x08, 0x2a, 0x3c, 0x7a, 0x0c, 0x00, 0x00, 0x7e
+    0x57, 0x2a, 0x31, 0x02, 0x76, 0x73, 0x02, 0x7b, 0x29, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x43
+    0xe1, 0xc0, 0x22, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7b, 0x9e, 0x40
+    0x19, 0x7e, 0x08, 0x2a, 0x3c, 0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0xca, 0x49, 0x12, 0x7c, 0x21
+    0xda, 0x59, 0xda, 0x0b, 0xd0, 0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0x22, 0xc0, 
+    0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7b, 0x9e, 0x40, 0x2b, 0x7e, 0x58, 0x00
+    0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7f, 0x61, 0x7e, 0x78, 0x2a, 0x3c, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 
+    0x77, 0x2a, 0x31, 0xbd, 0x74, 0x78, 0x11, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0x12, 0x7c, 0x5a
+    0x40, 0x06, 0xd0, 0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0xd3, 0x22, 0x7e, 0x24
+    0x00, 0xfe, 0x7e, 0x34, 0x7f, 0xca, 0x0b, 0x1a, 0x50, 0xc5, 0xf0, 0x7d, 0x62, 0x7d, 0x75, 0x7d
+    0x87, 0x7e, 0x34, 0x7f, 0xc2, 0x7e, 0x1b, 0xb0, 0x7e, 0x34, 0x7f, 0x03, 0xb4, 0x01, 0x04, 0x7e
+    0x34, 0x7f, 0xcc, 0x7e, 0x1b, 0xb0, 0xbc, 0x0b, 0x50, 0x49, 0x3e, 0x00, 0x3e, 0x00, 0x0a, 0x50
+    0x2d, 0x75, 0x0b, 0x3a, 0x30, 0x69, 0x53, 0x00, 0x02, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbc
+    0x1b, 0x50, 0x30, 0x3e, 0x10, 0x3e, 0x10, 0x0a, 0x51, 0x2d, 0x35, 0x69, 0x41, 0x00, 0x02, 0x0b
+    0x1a, 0x30, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbe, 0x44, 0xff, 0xff, 0x78, 0x05, 0x7e, 0x1b
+    0x90, 0x0a, 0x49, 0x4d, 0x44, 0x68, 0x0c, 0xbe, 0x44, 0x00, 0xff, 0x28, 0x04, 0x7e, 0x44, 0x00
+    0xff, 0xc3, 0x22, 0xd3, 0x22, 
 
-// Segment #15, Start Address 00ff7fc6, Length 4
+// Segment #16, Start Address 00ff7fc6, Length 4
 0xff,0x00,0xc6,0x7f,0x04,0x00,
-    0x01, 0x0c, 0x03, 0x00, 
+    0x01, 0x10, 0x04, 0x00, 
 
-// Segment #16, Start Address 00ff7e30, Length 315
-0xff,0x00,0x30,0x7e,0x3b,0x01,
-    0xca, 0x08, 0x7e, 0x01, 0x2f, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x7e, 0x1b, 0xc0, 0x7a, 
+// Segment #17, Start Address 00ff7c15, Length 330
+0xff,0x00,0x15,0x7c,0x4a,0x01,
+    0xca, 0x08, 0x7e, 0x01, 0x31, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x7e, 0x1b, 0xc0, 0x7a, 
     0x0b, 0xc0, 0x0b, 0x14, 0x0b, 0x34, 0x1b, 0x44, 0x78, 0xf2, 0x22, 0x7f, 0x6f, 0x7f, 0xf0, 0x1b, 
     0xfc, 0x7c, 0x54, 0x7d, 0x32, 0x80, 0x08, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0x9e, 
     0x44, 0x00, 0x10, 0x50, 0xf2, 0x2e, 0x44, 0x00, 0x10, 0x68, 0x06, 0xca, 0x48, 0x1b, 0x44, 0x78, 
     0xfa, 0x7f, 0xf6, 0x89, 0xe4, 0xca, 0x6b, 0x5e, 0xd4, 0x00, 0x3f, 0x68, 0x20, 0x7e, 0x84, 0x00, 
-    0x40, 0x9d, 0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x7e, 0x9f
+    0x40, 0x9d, 0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x7c, 0x84
     0xda, 0x79, 0x40, 0x08, 0x9d, 0x78, 0x68, 0x02, 0x80, 0x05, 0xc2, 0xd7, 0x22, 0xda, 0x6b, 0x43, 
     0x90, 0x30, 0x74, 0xaa, 0x39, 0xb5, 0x55, 0x55, 0x74, 0x55, 0x39, 0xb5, 0x2a, 0xaa, 0x74, 0xa0, 
     0x39, 0xb5, 0x55, 0x55, 0x7e, 0x04, 0x00, 0x40, 0x9d, 0x70, 0x50, 0x06, 0x2d, 0x70, 0x7d, 0x07, 
@@ -1104,16 +1211,17 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
     0x1b, 0x54, 0x78, 0xf5, 0x80, 0x2c, 0x6d, 0x00, 0x7c, 0x20, 0x7f, 0x16, 0x9f, 0x10, 0x7f, 0x27, 
     0x9f, 0x20, 0x7e, 0x2b, 0x00, 0x7e, 0x1b, 0x10, 0xbc, 0x01, 0x78, 0x16, 0x0b, 0x2c, 0x0b, 0x1c, 
     0xa5, 0xdb, 0xef, 0x7c, 0xb6, 0x20, 0xe0, 0x03, 0x63, 0x90, 0x30, 0x4d, 0x77, 0x78, 0x93, 0xc2, 
-    0xd7, 0x22, 0xd2, 0xd7, 0x22, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x06, 0x04, 0x02, 0x04, 0x00, 
-    0x02, 0x01, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 
-    0x02, 0x02, 0x04, 0x00, 0x08, 0x10, 0x02, 0x10, 0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x7e, 
-    0x18, 0x7f, 0xbd, 0x7a, 0x1c, 0x00, 0xfe, 0x0b, 0x1a, 0x00, 0xbe, 0x10, 0x14, 0x38, 0x1a, 0x0a, 
-    0x51, 0x23, 0x7e, 0x18, 0x7f, 0x15, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, 
-    0x08, 0xa5, 0xb8, 0x02, 0x03, 0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, 
+    0xd7, 0x22, 0xd2, 0xd7, 0x22, 0x00, 0x04, 0x00, 0x04, 0x42, 0x08, 0x06, 0x04, 0x02, 0x04, 0x00, 
+    0x02, 0x01, 0x04, 0x01, 0x02, 0x82, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 
+    0x02, 0x02, 0x04, 0x02, 0x08, 0x10, 0x02, 0x10, 0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x00, 
+    0x01, 0x00, 0x02, 0x00, 0x02, 0x02, 0x08, 0x02, 0x04, 0x20, 0x04, 0x7e, 0x18, 0x7f, 0xbd, 0x7a, 
+    0x1c, 0x00, 0xfe, 0x0b, 0x1a, 0x00, 0x5e, 0x10, 0x1f, 0xbe, 0x10, 0x1a, 0x38, 0x1a, 0x0a, 0x51, 
+    0x23, 0x7e, 0x18, 0x7c, 0xfa, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, 0x08, 
+    0xa5, 0xb8, 0x02, 0x03, 0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, 
 };
 
 static struct edge_firmware_version_info IMAGE_VERSION_NAME = {
-       1, 12, 3 };             // Major, Minor, Build
+       1, 16, 4 };             // Major, Minor, Build
 
 #undef IMAGE_VERSION_NAME
 
index 20eecb3..93b56d6 100644 (file)
@@ -1,11 +1,11 @@
 //**************************************************************
 //* Edgeport Binary Image (for TI based products)
-//* Generated by TIBin2C v1.00
+//* Generated by TIBin2C v2.00 (watchport)
 //* Copyright (C) 2001 Inside Out Networks, All rights reserved.
 //**************************************************************
 
 
-static int IMAGE_SIZE = 12166;
+static int IMAGE_SIZE = 12749;
 
 struct EDGE_FIRMWARE_VERSION_INFO
 {
@@ -16,7 +16,7 @@ struct EDGE_FIRMWARE_VERSION_INFO
 
 static struct EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME =
 {
-       4, 1, 0         // Major, Minor, Build
+       4, 10, 0                // Major, Minor, Build
 
 };
 
@@ -27,20 +27,20 @@ static unsigned char IMAGE_ARRAY_NAME[] =
 //      WORD    Length;
 //      BYTE    CheckSum;
 //  };
-0x83, 0x2f
-0x33
+0xca, 0x31
+0xa8
 
-0x02, 0x24, 0x84, 0x02, 0x1f, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x45
-0x8c, 0x85, 0x46, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
-0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x44
-0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x44, 0x75, 
-0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x92, 0xe5, 0x81, 
-0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x1a, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, 
-0xfa, 0x74, 0x08, 0x25, 0x44, 0xf8, 0x05, 0x44, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x44
-0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x44, 0x00, 0x80, 0xef, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0x86, 
-0x81, 0xe5, 0x44, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 
-0x78, 0x92, 0xe5, 0x81, 0x04, 0xc3, 0x98, 0xf9, 0xe0, 0xf6, 0x08, 0xa3, 0xd9, 0xfa, 0xd0, 0x07, 
+0x02, 0x26, 0xfe, 0x02, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x3f
+0x8c, 0x85, 0x40, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
+0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3e
+0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x3e, 0x75, 
+0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x8c, 0xe5, 0x81, 
+0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x94, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, 
+0xfa, 0x74, 0x08, 0x25, 0x3e, 0xf8, 0x05, 0x3e, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x3e
+0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x3e, 0x00, 0x80, 0xef, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0x86, 
+0x81, 0xe5, 0x3e, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 
+0x78, 0x8c, 0xe5, 0x81, 0x04, 0xc3, 0x98, 0xf9, 0xe0, 0xf6, 0x08, 0xa3, 0xd9, 0xfa, 0xd0, 0x07, 
 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 
 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x30, 0x01, 0x4d, 0x30, 0xb4, 0x48, 0x10, 
 0x00, 0x45, 0x90, 0xff, 0x08, 0xe0, 0x54, 0x20, 0xf8, 0x90, 0xff, 0x48, 0xe0, 0x54, 0x20, 0xf9, 
@@ -50,747 +50,783 @@ static unsigned char IMAGE_ARRAY_NAME[] =
 0xa3, 0xe0, 0xcb, 0xf0, 0x6b, 0x60, 0x02, 0x7e, 0x04, 0x22, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 
 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 
 0xc0, 0x06, 0xc0, 0x07, 0x90, 0xff, 0x93, 0x74, 0x01, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, 
-0x02, 0x11, 0x1a, 0x85, 0x47, 0x8d, 0x85, 0x48, 0x8b, 0x74, 0xae, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 
+0x02, 0x11, 0x94, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xaf, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 
 0x83, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, 
 0x90, 0xff, 0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 
-0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25
-0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 
+0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27
+0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 
 0xa3, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, 
-0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 
-0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25, 
-0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 
-0x20, 0x02, 0x03, 0x30, 0x01, 0x7b, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, 
-0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 0x7e, 
-0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x22, 0x12, 0x00, 0xc9, 0xee, 0x64, 
-0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 0x02, 
-0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x22, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 0x22, 
-0x7c, 0x0a, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 
-0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 0x80, 
-0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 0xd2, 
-0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 0x60, 
-0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x43, 0x60, 
-0x13, 0x14, 0xf5, 0x43, 0x70, 0x0e, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x10, 0x95, 
-0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 
-0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x90, 
-0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb5, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 
-0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 0x01, 
-0x7f, 0x08, 0x8e, 0x34, 0x8f, 0x35, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff, 
-0xea, 0x90, 0xfa, 0xb9, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x18, 0x49, 0x78, 0x24, 0x7c, 0x00, 0x7d, 
-0x00, 0x12, 0x19, 0x6c, 0x7e, 0x00, 0x7f, 0x05, 0x12, 0x13, 0x8f, 0xe4, 0xf5, 0x53, 0xe5, 0x53, 
-0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x18, 0x2a, 0xe4, 0x12, 0x13, 0xfb, 0x05, 0x53, 0x04, 0x12, 
-0x18, 0x1b, 0x80, 0xea, 0x12, 0x18, 0x49, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 0xc0, 
-0x70, 0x03, 0x02, 0x08, 0xb8, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 
-0xfe, 0x54, 0x0f, 0xf5, 0x53, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x90, 
-0xff, 0x01, 0xe0, 0x12, 0x15, 0x0f, 0x03, 0x55, 0x00, 0x04, 0x28, 0x01, 0x05, 0x2f, 0x03, 0x05, 
-0xf6, 0x05, 0x06, 0x38, 0x06, 0x07, 0x9a, 0x08, 0x07, 0xe2, 0x09, 0x08, 0x3e, 0x0a, 0x08, 0x7e, 
-0x0b, 0x00, 0x00, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 
-0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x02, 0x45, 0x34, 
-0x60, 0x03, 0x02, 0x0e, 0xac, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 0x02, 
-0x60, 0x03, 0x02, 0x0e, 0xac, 0xee, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0x2a, 0x74, 0x01, 
-0x12, 0x13, 0xfb, 0x78, 0x6d, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x18, 0x2a, 0x74, 0x02, 0x12, 0x13, 
-0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 
-0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 
-0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x60, 
-0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x53, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb, 
-0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb, 0x80, 0x19, 0x15, 0x53, 0x30, 
-0x0a, 0x0b, 0x12, 0x18, 0xbd, 0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x80, 0x09, 0x12, 0x18, 0xcb, 
-0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0x60, 0x05, 0x74, 0x01, 
-0x12, 0x13, 0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14, 
-0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3, 
-0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0x78, 0x6d, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 
-0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb5, 0xe0, 
-0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94, 
-0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 
-0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x07, 
-0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 0x54, 
-0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x53, 0x24, 0xfe, 0x60, 0x1b, 
-0x04, 0x70, 0x2e, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce, 
-0x80, 0x1f, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce, 0x80, 0x16, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 
-0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2a, 0xce, 0x80, 0x07, 0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2a, 
-0xce, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 
-0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 
-0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 
-0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 
-0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 
-0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x78, 0x6d, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 
-0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 
-0x30, 0xe0, 0x07, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0a, 0xe5, 
-0x53, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa, 
-0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 
-0x12, 0x2f, 0x3b, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 
-0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x19, 0x7a, 0x02, 0x19, 0x3e, 
-0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd, 
-0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x44, 0x08, 
-0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 
-0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 
-0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x03, 0x02, 0x0e, 0xac, 
-0x90, 0xfa, 0xba, 0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x2c, 0x01, 0x80, 0x03, 
-0x53, 0x2c, 0xfe, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x35, 0x45, 0x34, 0x70, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0x90, 0xfa, 0xb9, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 
-0x75, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xed, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 
-0x49, 0x12, 0x19, 0x73, 0x7d, 0x03, 0x12, 0x0e, 0xf3, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e, 
-0xb0, 0x90, 0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80, 
-0x04, 0xae, 0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x18, 0x49, 0x90, 0xf9, 0x65, 0xe0, 0x30, 
-0xe4, 0x0d, 0x12, 0x19, 0x73, 0x7d, 0x14, 0x12, 0x0e, 0xf3, 0x60, 0x10, 0x02, 0x0e, 0xac, 0x12, 
-0x19, 0x73, 0x7d, 0x04, 0x12, 0x0f, 0x47, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e, 0xb0, 0x90, 
-0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80, 0x04, 0xae, 
-0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x19, 0x73, 0x7d, 0x05, 0x12, 0x0f, 0x47, 0x60, 0x03, 
-0x02, 0x0e, 0xac, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x12, 0x18, 0x90, 0x7d, 0x01, 0x12, 0x23, 
-0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xba, 0xe0, 0x90, 
-0xfa, 0xb1, 0xf0, 0xe4, 0xf5, 0x52, 0x90, 0xfa, 0xb1, 0xe0, 0xff, 0xe5, 0x52, 0xc3, 0x9f, 0x50, 
-0x24, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0xff, 0xfd, 0x90, 0xfa, 0xb3, 0xe4, 0x8d, 0xf0, 0x12, 
-0x14, 0x2f, 0x90, 0xfa, 0xb2, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0e, 
-0xac, 0x05, 0x52, 0x80, 0xd1, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0x24, 0xfe, 0xff, 0x90, 0xfa, 
-0xb2, 0xf0, 0xfd, 0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0x7a, 0xf9, 0x79, 0x6e, 0x7b, 
-0x01, 0x8b, 0x2d, 0x8a, 0x2e, 0x89, 0x2f, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x18, 
-0x90, 0x12, 0x23, 0xee, 0x8f, 0x52, 0x05, 0x52, 0x05, 0x52, 0x12, 0x18, 0x2a, 0xe5, 0x52, 0x12, 
-0x13, 0xfb, 0x12, 0x18, 0x2a, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x14, 0x0d, 0xaf, 0x52, 0x7e, 
-0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x50, 0x02, 0x80, 0x04, 0xae, 0x34, 0xaf, 0x35, 
-0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 
-0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 
-0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 
-0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06, 
-0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x75, 0x2d, 0x00, 0x75, 0x2e, 0x00, 0x75, 0x2f, 0x29, 0x02, 
-0x0f, 0x2f, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 
-0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3, 0x90, 0xfa, 0xba, 
-0xe0, 0x94, 0x01, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 
-0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0e, 
-0xac, 0x90, 0xfa, 0xba, 0xe0, 0xf5, 0x29, 0xe5, 0x29, 0x70, 0x08, 0x43, 0x2c, 0x01, 0x53, 0x2c, 
-0xfd, 0x80, 0x06, 0x53, 0x2c, 0xfe, 0x43, 0x2c, 0x02, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 
-0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02, 
-0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x7f, 0x01, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 
-0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3, 
-0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e, 
-0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03, 
-0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xff, 0x01, 0x12, 0x19, 0x8a, 0xef, 0x12, 
-0x13, 0xfb, 0x90, 0xfa, 0xb5, 0x12, 0x19, 0x8a, 0x90, 0x00, 0x01, 0xef, 0x12, 0x14, 0x0d, 0x90, 
-0x00, 0x02, 0xe4, 0x12, 0x14, 0x0d, 0x74, 0x03, 0x12, 0x18, 0x1b, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 
-0xa3, 0xe0, 0x85, 0x2f, 0x82, 0x85, 0x2e, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 
-0xe0, 0x12, 0x15, 0x0f, 0x09, 0x3d, 0x02, 0x09, 0x5f, 0x04, 0x09, 0x81, 0x05, 0x09, 0xad, 0x06, 
-0x09, 0xcb, 0x07, 0x09, 0xe9, 0x08, 0x0a, 0x07, 0x09, 0x0a, 0x25, 0x0b, 0x0a, 0xda, 0x80, 0x0c, 
-0xfa, 0x81, 0x0d, 0x1c, 0x82, 0x0b, 0x21, 0x83, 0x0b, 0x6a, 0x84, 0x0b, 0x89, 0x85, 0x0b, 0xc5, 
-0x86, 0x0c, 0x07, 0x87, 0x0c, 0x95, 0x88, 0x0c, 0xd0, 0x89, 0x0a, 0x43, 0x92, 0x0a, 0x43, 0x93, 
-0x0d, 0xcf, 0xc0, 0x0e, 0x00, 0xc1, 0x0e, 0x11, 0xc2, 0x00, 0x00, 0x0e, 0x9b, 0xe5, 0x2c, 0x20, 
-0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 
-0xfd, 0x7c, 0x00, 0x7f, 0x07, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c, 0xc0, 0xe5, 
-0x2c, 0x20, 0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 
-0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c, 
-0xc0, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x19, 0x99, 0x50, 0x06, 0xe5, 0x35, 
-0x45, 0x34, 0x70, 0x05, 0x7f, 0x02, 0x02, 0x2e, 0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x24, 0xfe, 0x24, 
-0xfd, 0x50, 0x02, 0x80, 0x03, 0x02, 0x2f, 0x28, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 
-0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 
-0x00, 0x7f, 0x08, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 
-0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 
-0x09, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 
-0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 
-0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 
-0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x10, 0x9c, 
-0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 
-0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x10, 0x9c, 0x7f, 0x07, 
-0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x56, 0x12, 0x18, 0xd9, 0x70, 0x4a, 0x90, 0xff, 0x02, 
-0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61, 0x80, 0x12, 0xe5, 0x52, 0xb4, 
-0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x52, 0x12, 
-0x17, 0x8b, 0x12, 0x19, 0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x05, 
-0x12, 0x2f, 0x76, 0x80, 0x06, 0x85, 0x2a, 0x30, 0x85, 0x2b, 0x31, 0x75, 0x2d, 0x01, 0x75, 0x2e, 
-0xf9, 0x75, 0x2f, 0x71, 0x02, 0x29, 0x2d, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x12, 0x18, 
-0xd9, 0x60, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x19, 0x99, 0x40, 0x05, 0x7f, 0x03, 0x02, 
-0x2e, 0xa5, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61, 
-0x80, 0x12, 0xe5, 0x52, 0xb4, 0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54, 
-0xf0, 0x04, 0xf5, 0x52, 0x12, 0x17, 0x8b, 0x02, 0x2f, 0x28, 0x12, 0x19, 0xa3, 0x12, 0x27, 0x19, 
-0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x78, 
-0x6e, 0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 
-0xe4, 0x12, 0x14, 0x0d, 0x90, 0xfa, 0xb6, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x82, 0xe6, 0xfc, 
-0x08, 0xe6, 0x8c, 0x83, 0x12, 0x18, 0xa3, 0xef, 0xf0, 0x12, 0x2f, 0x80, 0xe4, 0xff, 0x02, 0x2e, 
-0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00, 
-0x70, 0x06, 0xa3, 0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 
-0xba, 0xe0, 0x42, 0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00, 0x70, 
-0x06, 0xa3, 0xe0, 0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xba, 
-0xe0, 0x42, 0xb0, 0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x49, 0x90, 0xfa, 0xb5, 
-0xe0, 0xb4, 0x01, 0x0a, 0x12, 0x18, 0x2a, 0xe5, 0x90, 0x12, 0x13, 0xfb, 0x80, 0x08, 0x12, 0x18, 
-0x2a, 0xe5, 0xb0, 0x12, 0x13, 0xfb, 0x02, 0x0f, 0x2f, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x30, 
-0x12, 0x18, 0x53, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 
-0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x19, 0xad, 0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb6, 
-0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x04, 0x12, 0x19, 0xb4, 0xf0, 
-0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x36, 0x12, 0x18, 0x53, 0x60, 
-0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 
-0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0, 
-0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 
-0xdf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x46, 0x04, 0x60, 0x03, 0x02, 
-0x0c, 0x90, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x04, 0xf0, 0x90, 
-0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x6a, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x61, 0x90, 
-0xff, 0xa4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x53, 0x30, 0x95, 0x09, 
-0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x47, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 
-0x80, 0x3e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x04, 0xf0, 0x90, 
-0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x2a, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x21, 0x90, 
-0xff, 0xb4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x13, 0x30, 0x93, 0x09, 
-0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfd, 0xf0, 
-0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6, 
-0xe0, 0x60, 0x09, 0x90, 0xff, 0xa2, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa2, 0xe0, 
-0x54, 0xbf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb2, 0xe0, 0x44, 
-0x40, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 
-0x12, 0x18, 0x49, 0x12, 0x18, 0x5b, 0x60, 0x0f, 0x04, 0x70, 0x16, 0x90, 0xff, 0xa4, 0xe0, 0x12, 
-0x18, 0x2a, 0x12, 0x13, 0xfb, 0x80, 0x0a, 0x90, 0xff, 0xb4, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13, 
-0xfb, 0x75, 0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x12, 
-0x19, 0x46, 0x7f, 0x03, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0xff, 
-0x7e, 0x00, 0x12, 0x2d, 0xee, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 0xe4, 0xf5, 0x54, 0xf5, 
-0x55, 0x90, 0xfa, 0xbb, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 0xb3, 0xf0, 0xa3, 0x74, 
-0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 0xb8, 0xf0, 0xd3, 0x94, 
-0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e, 
-0xd6, 0xe5, 0x23, 0x45, 0x22, 0x70, 0x73, 0x12, 0x18, 0x62, 0x90, 0xfa, 0xbb, 0x12, 0x19, 0x65, 
-0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 0xfa, 0xb8, 0x74, 0x40, 
-0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e, 0xd6, 0xe5, 0x23, 
-0x45, 0x22, 0x70, 0x46, 0x12, 0x18, 0x62, 0x80, 0xd1, 0x75, 0x52, 0x02, 0x90, 0xfa, 0xbb, 0xe4, 
-0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb3, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 0xf0, 0x7b, 0x00, 0x7a, 
-0x00, 0x79, 0x52, 0x90, 0xfa, 0xbc, 0xe0, 0xf5, 0x50, 0x7d, 0x0f, 0x7c, 0x00, 0x12, 0x26, 0x25, 
-0x75, 0x22, 0x00, 0x8f, 0x23, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 0x40, 0xf5, 0x41, 
-0x7d, 0x01, 0x12, 0x23, 0xee, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0xaf, 0x23, 0x02, 0x2e, 0xa5, 0x90, 
-0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x62, 
-0xf0, 0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0f, 
-0x90, 0xf9, 0x61, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 
-0x12, 0x19, 0xa3, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x2e, 
-0xa5, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, 
-0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, 
-0x12, 0x19, 0xad, 0x12, 0x0e, 0xfe, 0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, 
-0x44, 0x10, 0x12, 0x0e, 0xfe, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, 
-0x19, 0xad, 0xf0, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, 
-0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, 
-0x92, 0x80, 0x23, 0x12, 0x19, 0xb4, 0x12, 0x0f, 0x1e, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, 
-0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x1e, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, 
-0xd2, 0x92, 0x12, 0x19, 0xb4, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x07, 
-0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x2f, 0x76, 0x22, 
-0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 
-0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0xab, 
-0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x22, 0xaa, 0x54, 0xa9, 0x55, 0x7b, 0xff, 0x90, 0xfa, 0xb3, 0xe0, 
-0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xb8, 0xe0, 0xf5, 0x50, 0x12, 0x26, 0x25, 0x75, 0x22, 0x00, 
-0x8f, 0x23, 0x22, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23, 0xef, 0x22, 0xf0, 0x7f, 
-0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x12, 
-0x23, 0xee, 0x8f, 0x52, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x22, 0xf0, 0x7f, 
-0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x75, 
-0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x02, 0x2f, 0x3b, 
-0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23, 
-0xef, 0x22, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb0, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, 
-0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, 
-0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, 
-0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 
-0x04, 0xc0, 0x05, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, 
-0x0f, 0xfe, 0x7f, 0x00, 0x7e, 0x00, 0xe5, 0x49, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x19, 0xe0, 0x54, 
-0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, 
-0x49, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, 
-0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 
-0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 
-0x12, 0x10, 0x95, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, 
-0x4a, 0x75, 0xa8, 0x88, 0xec, 0x70, 0x02, 0x7c, 0x3f, 0x8c, 0x43, 0x22, 0xe5, 0x44, 0x24, 0x08, 
-0xf8, 0x76, 0x00, 0x12, 0x10, 0xec, 0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 
-0xc0, 0x06, 0x7c, 0xff, 0x12, 0x0f, 0xfe, 0xe5, 0x49, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x19, 0xe0, 
-0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x49, 0x80, 0x07, 
-0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, 
-0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 
-0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, 
-0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, 
-0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 0xee, 0x12, 0x10, 0x95, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, 
-0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 0x43, 0x00, 0x85, 0x4a, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 
-0xc0, 0x83, 0xc3, 0xe5, 0x49, 0x24, 0xe8, 0x50, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf4, 0xef, 0x60, 
-0x31, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x0f, 
-0xfe, 0xd0, 0x04, 0x43, 0x07, 0x80, 0xe5, 0x49, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x19, 0xf5, 0x82, 
-0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x49, 0x12, 
-0x10, 0x95, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x02, 0x11, 0x1a, 0xc0, 0x04, 0x7c, 0x20, 
-0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, 
-0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, 
-0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, 
-0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, 
-0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 
-0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0xd2, 0xb0, 0xd2, 
-0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 
-0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, 
-0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x48, 0x8e, 
-0x47, 0x22, 0xc3, 0xef, 0x94, 0xbc, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, 
-0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x46, 0x8e, 0x45, 0x22, 0xef, 
-0x70, 0x01, 0x22, 0xc0, 0x00, 0xe5, 0x44, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x44, 0x24, 0x08, 
-0xf8, 0xc6, 0x54, 0x7f, 0xf6, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x10, 0xec, 0x80, 
+0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25, 
+0xb4, 0x02, 0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, 
+0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 
+0x80, 0x03, 0x02, 0x02, 0x62, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04, 
+0xf1, 0x20, 0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 
+0x14, 0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 
+0x7e, 0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x33, 0x12, 0x00, 0xc9, 0xee, 
+0x64, 0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 
+0x02, 0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x33, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 
+0x33, 0x7c, 0x0a, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 
+0xa3, 0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 
+0x80, 0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 
+0xd2, 0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 
+0x60, 0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d, 
+0x60, 0x13, 0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 
+0x0f, 0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 
+0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 
+0x90, 0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 
+0xec, 0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 
+0x01, 0x7f, 0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 
+0xff, 0xea, 0x90, 0xfa, 0xba, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0x30, 0xe4, 0xf5, 0x4d, 0xe5, 
+0x4d, 0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0x11, 0xe4, 0x12, 0x1a, 0x38, 0x05, 0x4d, 0x04, 
+0x12, 0x1c, 0x02, 0x80, 0xea, 0x12, 0x1c, 0x30, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 
+0xc0, 0x70, 0x03, 0x02, 0x08, 0xc5, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 
+0xe0, 0xfe, 0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 
+0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0x4c, 0x03, 0x56, 0x00, 0x04, 0x29, 0x01, 0x05, 0x3c, 0x03, 
+0x06, 0x03, 0x05, 0x06, 0x45, 0x06, 0x07, 0xa7, 0x08, 0x07, 0xef, 0x09, 0x08, 0x4b, 0x0a, 0x08, 
+0x8b, 0x0b, 0x00, 0x00, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x02, 0x45, 
+0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 
+0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x11, 0x74, 
+0x01, 0x12, 0x1a, 0x38, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0x11, 0x74, 0x02, 0x12, 
+0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb6, 0xe0, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 
+0x26, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 
+0x60, 0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, 
+0x26, 0xe5, 0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 
+0x38, 0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 0x38, 0x80, 0x19, 0x15, 0x4d, 
+0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x80, 0x09, 0x12, 0x1c, 
+0xb3, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x12, 0x1c, 0x11, 0x12, 0x19, 0xf2, 0x60, 0x05, 0x74, 
+0x01, 0x12, 0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 
+0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x14, 0x60, 0x2d, 
+0x14, 0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x04, 
+0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 
+0x0f, 0x26, 0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 
+0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb6, 
+0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 
+0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 
+0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, 
+0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 
+0x07, 0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 
+0x54, 0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60, 
+0x20, 0x24, 0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 
+0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 
+0x1d, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x0e, 
+0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0x32, 0x15, 0x4d, 
+0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1c, 
+0xb3, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 
+0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 
+0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 
+0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 
+0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x07, 
+0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94, 
+0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 0x70, 
+0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x12, 0x31, 0x82, 
+0x40, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 
+0xe5, 0x4d, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1d, 0x64, 0x02, 0x1d, 0x2f, 0xe5, 0x35, 0x20, 
+0xe1, 0x03, 0x02, 0x0f, 0x26, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 
+0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x1c, 0xb3, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff, 
+0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 
+0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xbb, 
+0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe, 
+0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 
+0x3b, 0x70, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xba, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x30, 0x12, 0x1d, 
+0x5d, 0x7d, 0x03, 0x12, 0x0f, 0x6d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 
+0xb3, 0xe0, 0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 
+0xaf, 0x3c, 0x02, 0x0f, 0xba, 0x12, 0x1c, 0x30, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x0d, 0x12, 
+0x1d, 0x5d, 0x7d, 0x14, 0x12, 0x0f, 0x6d, 0x60, 0x10, 0x02, 0x0f, 0x26, 0x12, 0x1d, 0x5d, 0x7d, 
+0x04, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 0xb3, 0xe0, 
+0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 
+0x02, 0x0f, 0xba, 0x12, 0x1d, 0x5d, 0x7d, 0x05, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 
+0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x12, 0x1c, 0x78, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 
+0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb2, 0xf0, 
+0xe4, 0xf5, 0x4c, 0x90, 0xfa, 0xb2, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1c, 
+0x72, 0x12, 0x0f, 0xcc, 0xff, 0xfd, 0x90, 0xfa, 0xb4, 0xe4, 0x8d, 0xf0, 0x12, 0x1a, 0x6c, 0x90, 
+0xfa, 0xb3, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x26, 0x05, 0x4c, 
+0x80, 0xd1, 0x12, 0x1c, 0x72, 0x12, 0x0f, 0xcc, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb3, 0xf0, 0xfd, 
+0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0x7a, 0xf9, 0x79, 0x6f, 0x7b, 0x01, 0x8b, 0x36, 
+0x8a, 0x37, 0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1c, 0x78, 0x12, 0x25, 
+0xd7, 0x8f, 0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0x11, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x12, 
+0x1c, 0x11, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0x4a, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 
+0x95, 0x3c, 0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f, 
+0x3a, 0x02, 0x2c, 0x07, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 
+0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 
+0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 
+0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 
+0x02, 0x0f, 0x26, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xa9, 0xe5, 
+0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 
+0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 0xe0, 0x94, 0x01, 
+0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 
+0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xbb, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06, 
+0x53, 0x35, 0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 
+0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 
+0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 
+0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x7f, 0x01, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 
+0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 
+0xe0, 0x94, 0x00, 0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 
+0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 
+0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xff, 0x01, 0x12, 0x1d, 0x74, 0xef, 0x12, 0x1a, 0x38, 0x90, 
+0xfa, 0xb6, 0x12, 0x1d, 0x74, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0x4a, 0x90, 0x00, 0x02, 0xe4, 
+0x12, 0x1a, 0x4a, 0x74, 0x03, 0x12, 0x1c, 0x02, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0xa3, 0xe0, 0x85, 
+0x38, 0x82, 0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 
+0x4c, 0x09, 0x4a, 0x02, 0x09, 0x6c, 0x04, 0x09, 0x8e, 0x05, 0x09, 0xba, 0x06, 0x09, 0xd8, 0x07, 
+0x09, 0xf6, 0x08, 0x0a, 0x14, 0x09, 0x0a, 0x32, 0x0b, 0x0a, 0xe7, 0x80, 0x0d, 0x6f, 0x81, 0x0d, 
+0xa0, 0x82, 0x0b, 0x2e, 0x83, 0x0b, 0x77, 0x84, 0x0b, 0x96, 0x85, 0x0b, 0xdb, 0x86, 0x0c, 0x26, 
+0x87, 0x0c, 0xb7, 0x88, 0x0d, 0x42, 0x89, 0x0a, 0x50, 0x92, 0x0a, 0x50, 0x93, 0x0e, 0x53, 0xc0, 
+0x0e, 0x7f, 0xc1, 0x0e, 0x90, 0xc2, 0x00, 0x00, 0x0f, 0x15, 0xe5, 0x35, 0x20, 0xe7, 0x05, 0x7f, 
+0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 
+0x7f, 0x07, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 0x20, 0xe7, 
+0x05, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 
+0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 
+0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1d, 0x92, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b, 0x70, 
+0x05, 0x7f, 0x02, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50, 0x02, 
+0x80, 0x03, 0x02, 0x31, 0x6f, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 
+0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x08, 
+0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 
+0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02, 0x11, 
+0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 
+0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x16, 0x7f, 
+0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 
+0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 
+0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 
+0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 
+0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1c, 0xc9, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c, 
+0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75, 
+0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1b, 0x72, 0x12, 
+0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x05, 0x12, 0x31, 0xbd, 
+0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 
+0x72, 0x02, 0x2c, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0x18, 0x12, 0x1c, 0xc9, 0x60, 0x05, 
+0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1d, 0x92, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x30, 0xec, 0x90, 
+0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 
+0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 
+0x4c, 0x12, 0x1b, 0x72, 0x02, 0x31, 0x6f, 0x12, 0x1d, 0x9c, 0x12, 0x2a, 0x06, 0x12, 0x1c, 0x83, 
+0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x78, 0x68, 0x12, 0x1b, 
+0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a, 
+0x4a, 0x90, 0xfa, 0xb7, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6, 0x8c, 
+0x83, 0x12, 0x1c, 0x8b, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 
+0xb6, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 
+0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 
+0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 0xe0, 
+0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 0xb0, 
+0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0xb4, 0x01, 
+0x0a, 0x12, 0x1c, 0x11, 0xe5, 0x90, 0x12, 0x1a, 0x38, 0x80, 0x08, 0x12, 0x1c, 0x11, 0xe5, 0xb0, 
+0x12, 0x1a, 0x38, 0x02, 0x0f, 0xa9, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0x12, 0x12, 0x1c, 0x41, 
+0x20, 0xe1, 0x33, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, 
+0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1d, 0xa6, 
+0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, 
+0x80, 0x04, 0x12, 0x1d, 0xad, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 
+0x24, 0x12, 0x12, 0x1c, 0x41, 0x20, 0xe1, 0x39, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x1b, 
+0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 
+0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 
+0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 
+0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x12, 0x1c, 0xc1, 0x60, 0x4d, 0x04, 0x60, 
+0x03, 0x02, 0x0c, 0xb2, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c, 0x3a, 
+0x30, 0xe1, 0x6f, 0x12, 0x1d, 0x7c, 0x02, 0x0c, 0xb2, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb, 0x12, 
+0x1c, 0x3d, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1d, 0x7c, 0x80, 
+0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1d, 0x7c, 
+0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 
+0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0x3a, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 
+0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0x3d, 0x30, 0xe1, 0x13, 0x30, 
+0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 
+0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 
+0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0, 0x44, 
+0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 
+0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0, 0x44, 
+0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 
+0x80, 0x3b, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0, 0xa3, 
+0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3, 0xef, 
+0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0, 0xc2, 
+0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, 
+0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70, 0x16, 
+0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x80, 0x0a, 0x90, 0xff, 0xb6, 0xe0, 
+0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0x07, 0xe4, 
+0xff, 0x12, 0x30, 0xec, 0x12, 0x1d, 0x37, 0x7f, 0x03, 0x12, 0x12, 0x19, 0x90, 0xf9, 0x15, 0xe0, 
+0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80, 0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54, 
+0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30, 0x16, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 
+0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbc, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 
+0xb4, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 
+0xb9, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 
+0xb9, 0xf0, 0x12, 0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x73, 0x12, 0x1c, 0x4a, 0x90, 0xfa, 
+0xbc, 0x12, 0x1d, 0x56, 0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 
+0xfa, 0xb9, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x12, 
+0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46, 0x12, 0x1c, 0x4a, 0x80, 0xd1, 0x75, 0x4c, 0x02, 
+0x90, 0xfa, 0xbc, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb4, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 
+0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90, 0xfa, 0xbd, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c, 
+0x00, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4, 
+0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31, 
+0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x64, 0xf0, 
+0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb7, 0xe0, 0x54, 0x0f, 0x90, 
+0xf9, 0x63, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 
+0x1d, 0x9c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x30, 0xec, 
+0x12, 0x1c, 0xd0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 
+0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, 0x12, 0x1d, 0xa6, 0x12, 0x0f, 0x78, 
+0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x78, 0xff, 
+0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, 0x1d, 0xa6, 0xf0, 0x90, 0xfa, 0xb7, 
+0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 
+0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1d, 0xad, 
+0x12, 0x0f, 0x98, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 
+0x0f, 0x98, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, 0xd2, 0x92, 0x12, 0x1d, 0xad, 0xf0, 
+0xe4, 0xff, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 
+0x18, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x31, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 
+0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 
+0xfa, 0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 
+0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa, 0xb4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 
+0xb9, 0xe0, 0xf5, 0x4a, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x22, 0xa0, 
+0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, 
+0xa6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x12, 0x25, 0xd7, 0x8f, 0x4c, 0x7e, 0x00, 
+0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, 
+0xb6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 
+0x2c, 0x07, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x02, 0x31, 0x82, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c, 
+0x07, 0x12, 0x22, 0xa0, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x25, 
+0xd7, 0x90, 0xfa, 0xb1, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 
+0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 
+0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 
+0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24, 
+0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, 0x10, 0x78, 0x7f, 0x00, 0x7e, 0x00, 
+0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 
+0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 
+0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 
+0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 
+0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x12, 0x11, 0x0f, 0xd0, 0x05, 0xd0, 
+0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70, 
+0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x66, 
+0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10, 
+0x78, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 
+0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 
+0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 
+0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 
+0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 
+0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 
+0xee, 0x12, 0x11, 0x0f, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 
+0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24, 
+0xe8, 0x50, 0x05, 0x12, 0x11, 0x66, 0x80, 0xf4, 0xef, 0x60, 0x31, 0x90, 0x30, 0x54, 0xe4, 0x93, 
+0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x10, 0x78, 0xd0, 0x04, 0x43, 0x07, 0x80, 
+0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1b, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 
+0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x43, 0x12, 0x11, 0x0f, 0xd0, 0x83, 0xd0, 0x82, 
+0xd0, 0xf0, 0x22, 0x02, 0x11, 0x94, 0xc0, 0x04, 0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 
+0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 
+0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 
+0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 
+0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 
+0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 
+0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0xd2, 0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 
+0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 
+0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 
+0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc, 
+0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 
+0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f, 0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0, 
+0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6, 
+0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0x66, 0x80, 
 0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, 
-0x12, 0x10, 0xec, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
-0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0xa0, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 
+0x12, 0x11, 0x66, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
+0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 
 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, 
-0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x0e, 0xf5, 0x82, 
-0xe5, 0xf0, 0x34, 0x2e, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 
+0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x36, 0xf5, 0x82, 
+0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 
 0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24, 0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, 
-0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x44, 0x00, 0x75, 0x49
+0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43
 0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76, 0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, 
-0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 
+0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x30, 0x54, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 
 0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f, 0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, 
-0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x91, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 
-0xe5, 0x49, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x19, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 
+0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 
+0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 
 0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6, 0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, 
-0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x11, 0xc1, 0xad, 0x07, 0xaf, 0x02, 
-0x12, 0x11, 0xd8, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x10, 0xec, 0x80, 0xc1, 0xe7, 
-0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 
-0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 
-0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 
-0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf, 
-0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80, 
-0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80, 
-0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89, 
-0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 
-0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d, 
-0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, 
-0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 
-0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8, 
-0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 
-0xf0, 0xef, 0x60, 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 
-0x50, 0xb9, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 
-0x23, 0x90, 0x13, 0x0f, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 
-0xe7, 0x22, 0xbb, 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 
-0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 
-0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 
-0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 
-0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01, 
-0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06, 
-0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xc5, 
-0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 
-0x83, 0xe0, 0x38, 0xf0, 0x22, 0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 
-0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82, 
-0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09, 
-0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8, 
-0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3, 
-0xe9, 0x93, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 
-0x50, 0x06, 0xf7, 0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3, 
-0x19, 0x22, 0xf8, 0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 
-0xe8, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6, 
-0xf0, 0x22, 0xbb, 0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 0x22, 0xa4, 
-0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xfa, 
-0x08, 0xe6, 0xf9, 0x22, 0xeb, 0xf6, 0x08, 0xea, 0xf6, 0x08, 0xe9, 0xf6, 0x22, 0xe0, 0xfb, 0xa3, 
-0xe0, 0xfa, 0xa3, 0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 
-0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 
-0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 
-0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, 
-0xff, 0xf9, 0x74, 0x02, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 0x00, 
-0x7a, 0x00, 0x79, 0x37, 0x75, 0x40, 0x00, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0xe5, 0x37, 
-0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x37, 0x64, 0x07, 0x60, 0x0b, 0xe5, 0x37, 0x64, 0x06, 
-0x60, 0x05, 0xe5, 0x37, 0xb4, 0x14, 0x1b, 0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0xe5, 
-0x37, 0xb4, 0x07, 0x08, 0x90, 0xf9, 0x65, 0x74, 0x02, 0xf0, 0x80, 0x06, 0x90, 0xf9, 0x65, 0x74, 
-0x01, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x17, 0x71, 0x90, 0xff, 
-0xf5, 0xe5, 0x37, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90, 
-0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x12, 0x17, 0x71, 0xe5, 0x37, 0x30, 0xe7, 
-0x02, 0xd2, 0x02, 0xe4, 0xf5, 0x2c, 0xf5, 0x2a, 0xf5, 0x2b, 0xf5, 0x29, 0x12, 0x19, 0x92, 0x12, 
-0x18, 0x49, 0x12, 0x19, 0x6c, 0x90, 0xf9, 0x66, 0x12, 0x15, 0x06, 0x90, 0xf9, 0x6b, 0x12, 0x15, 
-0x06, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, 0x74, 
-0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x37, 0xe5, 0x37, 0x12, 
-0x18, 0xbf, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x37, 0x12, 0x18, 0xcd, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 
-0x37, 0xe5, 0x37, 0xb4, 0x07, 0xe7, 0x78, 0x80, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x2f, 0x06, 
-0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x2f, 0x13, 0xe4, 0x93, 0xff, 0x08, 
-0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x18, 0xaf, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, 0x08, 
-0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, 0x9f, 
-0x78, 0x81, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x18, 0x41, 0xce, 0xc3, 0x13, 0xce, 0x13, 
-0xd8, 0xf9, 0xff, 0xed, 0x12, 0x19, 0x07, 0xef, 0xf0, 0xed, 0x12, 0x19, 0x2d, 0xe4, 0xf5, 0x37, 
-0xe5, 0x37, 0x90, 0x2f, 0x00, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xe5, 0x37, 0x25, 0xe0, 0x24, 
-0x07, 0xf5, 0x82, 0xe4, 0x34, 0x2f, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, 0x53, 
-0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xaf, 0x12, 0x19, 0x15, 0x24, 0x47, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, 0x19, 
-0x07, 0xef, 0xf0, 0x12, 0x18, 0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a, 
-0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x19, 0x2d, 0xe9, 
-0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 
-0x02, 0x17, 0x46, 0x78, 0x7e, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xf9, 0x12, 0x19, 0x15, 0x24, 
-0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 
-0x12, 0x19, 0x1a, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, 0x18, 
-0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a, 0x24, 0x05, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x37, 0xe5, 0x37, 0x64, 0x04, 0x60, 0x03, 0x02, 0x16, 
-0x70, 0x90, 0x2f, 0x05, 0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0x12, 0x18, 0xf7, 0xe4, 0xf0, 0x90, 
-0x2f, 0x04, 0x93, 0xff, 0xf6, 0x12, 0x18, 0xad, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, 0xf0, 
-0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 
-0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 
-0x2f, 0xe5, 0x52, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 
-0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0x74, 0x11, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 
-0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x06, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 
-0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0xab, 0x2d, 
-0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 
-0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 
-0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x04, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13, 
-0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x05, 0xe0, 
-0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 
-0x35, 0x2e, 0xf5, 0x2e, 0x22, 0xf5, 0x83, 0xe0, 0x54, 0x08, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 
-0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, 0x78, 0x81, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 
-0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, 0x75, 0x2d, 0x01, 0x75, 0x2e, 0xf9, 0x75, 
-0x2f, 0x6e, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xfa, 0xb5, 0xe0, 0x24, 
-0xfc, 0x22, 0x90, 0xfa, 0xb8, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xbc, 0xe0, 0x9f, 0xf0, 
-0x90, 0xfa, 0xbb, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xb3, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef, 
-0x25, 0x55, 0xf5, 0x55, 0xee, 0x35, 0x54, 0xf5, 0x54, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb0, 
-0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x22, 0x78, 0x82, 0xe6, 0xfe, 0x08, 
-0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 
-0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x53, 0x75, 
-0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0xe5, 0x53, 0x75, 0xf0, 0x08, 
-0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, 
-0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x75, 0x2a, 0x00, 0x8f, 0x2b, 0x90, 0xf9, 0x6b, 
-0x12, 0x14, 0xfd, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 
-0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 
-0x22, 0x74, 0xae, 0x25, 0x36, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 
-0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, 0xff, 
-0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, 0xfc, 
-0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x6d, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x65, 
-0xf0, 0x22, 0x12, 0x14, 0xdf, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 
-0x79, 0x6e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 
-0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x66, 0x02, 
-0x14, 0xfd, 0x75, 0x30, 0x01, 0x75, 0x31, 0x09, 0x22, 0xd3, 0xe5, 0x35, 0x94, 0x08, 0xe5, 0x34, 
-0x94, 0x01, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x90, 0xfa, 0xb6, 0xf0, 0x22, 0x90, 0xff, 0xa4, 
-0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xef, 0x22, 0x8f, 0x38, 0x12, 0x27, 0x19, 
-0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xe0, 0xfd, 
-0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x12, 0x20, 0x7c, 0x24, 
-0x07, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x12, 0x20, 0xbe, 0x24, 0x09, 0x12, 0x20, 0x25, 0xef, 0xf0, 
-0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x20, 0x2f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 
-0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x33, 0xd0, 
-0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xe0, 0xfc, 0xa3, 0xe0, 
-0xfd, 0xec, 0xff, 0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xef, 0xf0, 0xed, 
-0x12, 0x20, 0xbe, 0x24, 0x07, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 
-0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x12, 0x20, 0x69, 0xa3, 0xe0, 
-0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90, 
-0x2f, 0x4d, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x12, 0x20, 0xae, 0x24, 0x06, 0x12, 0x20, 0x25, 
-0xe0, 0x60, 0x03, 0x43, 0x07, 0x04, 0x53, 0x07, 0xfc, 0x78, 0x86, 0x12, 0x20, 0x96, 0x24, 0x04, 
-0x12, 0x20, 0x25, 0xe0, 0x42, 0x07, 0x43, 0x07, 0x80, 0x12, 0x20, 0xa6, 0xf5, 0x82, 0x8a, 0x83, 
-0xa3, 0xa3, 0xef, 0xf0, 0x12, 0x20, 0xbe, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x8d, 0x82, 
-0x8c, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, 
-0x03, 0x43, 0x07, 0x20, 0xec, 0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, 
-0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60, 0x4c, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x42, 
-0x12, 0x20, 0xae, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14, 0x60, 0x31, 0x14, 0x60, 0x29, 0x14, 
-0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5, 0x38, 0xb4, 0x03, 0x0d, 0x30, 0x95, 
-0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 0x43, 0x07, 
-0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 0x07, 0xfd, 
-0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x20, 0x94, 0x24, 0x04, 0x12, 0x20, 0x25, 0xef, 0xf0, 0x8d, 
-0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60, 
-0x4a, 0xee, 0x30, 0xe1, 0x43, 0x08, 0x12, 0x20, 0xb0, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14, 
-0x60, 0x2c, 0x14, 0x60, 0x2e, 0x14, 0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5, 
-0x38, 0xb4, 0x03, 0x0d, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x1f, 0x43, 0x07, 0x80, 0x80, 
-0x1a, 0x30, 0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x12, 0x43, 0x07, 0x80, 0x80, 0x0d, 0x53, 0x07, 
-0x7f, 0x80, 0x08, 0x43, 0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x86, 0x12, 0x20, 0x65, 
-0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, 
-0xec, 0x30, 0xe3, 0x05, 0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, 
-0x43, 0x07, 0x10, 0x80, 0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, 
-0x03, 0x53, 0x07, 0xf7, 0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, 
-0xed, 0x30, 0xe6, 0x05, 0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, 
-0x43, 0x07, 0x02, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x78, 0x84, 0x12, 0x20, 0x65, 0xa3, 0xef, 0xf0, 
-0x12, 0x2f, 0x80, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x8e, 0xef, 0xf6, 0x12, 0x27, 0x19, 
-0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0xfd, 0x12, 0x20, 0x53, 0x90, 
-0x00, 0x0a, 0x12, 0x20, 0x78, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x14, 
-0x0d, 0x12, 0x20, 0x70, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x59, 0x12, 0x20, 
-0x7c, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xf5, 0x5a, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 
-0xf5, 0x5b, 0xe5, 0x59, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x8e, 0xf6, 0xd3, 0x94, 0x00, 
-0x40, 0x06, 0xe5, 0x5a, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x8e, 0xe6, 0x12, 0x20, 0x52, 0x90, 0x00, 
-0x0c, 0xef, 0x12, 0x14, 0x0d, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 
-0xff, 0x53, 0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x59, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 
-0x5a, 0x20, 0xe5, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59, 0x20, 0xe7, 0x03, 0x43, 
-0x07, 0x02, 0xe5, 0x59, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x59, 0x30, 0xe2, 0x03, 0x43, 
-0x07, 0x20, 0xe5, 0x59, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x59, 0x30, 0xe1, 0x03, 
-0x43, 0x07, 0x80, 0xe5, 0x59, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x59, 0x30, 0xe6, 0x03, 
-0x43, 0x06, 0x08, 0xe5, 0x5a, 0x20, 0xe4, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59, 
-0x20, 0xe7, 0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 
-0x8f, 0xf0, 0x12, 0x14, 0xb2, 0xe5, 0x5b, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 
-0x12, 0x20, 0x52, 0x90, 0x00, 0x08, 0xef, 0x12, 0x14, 0x0d, 0x80, 0x0a, 0x12, 0x20, 0x53, 0x90, 
-0x00, 0x08, 0xe4, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x03, 0x12, 0x20, 0x52, 0x90, 0x00, 0x07, 
-0xef, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x14, 
-0x0d, 0x90, 0x00, 0x07, 0x12, 0x13, 0xce, 0x70, 0x13, 0x12, 0x20, 0x53, 0xe9, 0x24, 0x09, 0xf9, 
-0xe4, 0x3a, 0xfa, 0x12, 0x13, 0xb5, 0xff, 0xc3, 0x13, 0x12, 0x13, 0xfb, 0x12, 0x20, 0x94, 0x24, 
-0x08, 0x12, 0x20, 0x25, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x20, 
-0x25, 0xe0, 0xfd, 0xee, 0xed, 0x12, 0x20, 0x52, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x14, 
-0xb2, 0x12, 0x2f, 0x80, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c, 0x90, 0xfa, 
-0xe2, 0xe0, 0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 
-0xfa, 0xd6, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xff, 0x7e, 0x00, 
-0x90, 0xfa, 0xd2, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 
-0x12, 0x14, 0x5b, 0xff, 0x90, 0xfa, 0xd4, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 
-0x01, 0x8e, 0x56, 0x8f, 0x57, 0x74, 0x0a, 0x25, 0x57, 0xf5, 0x57, 0xe4, 0x35, 0x56, 0xf5, 0x56, 
-0x90, 0xfa, 0xd7, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd5, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 
-0xff, 0x90, 0xfa, 0xd9, 0xf0, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0x90, 0xfa, 0xd2, 0xe0, 0x94, 
-0x00, 0x50, 0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d, 0x60, 0x03, 0xe0, 0xff, 
-0x22, 0x12, 0x2a, 0x80, 0x90, 0xfa, 0xd2, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 
-0xfa, 0xd6, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 
-0xfa, 0xd9, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d, 
-0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 0x2a, 0x80, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x58, 
-0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7f, 0x00, 0x22, 0xaa, 0x56, 0xa9, 
-0x57, 0x7b, 0x01, 0x90, 0xfa, 0xd4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xd9, 0xe0, 0xf5, 
-0x50, 0x12, 0x26, 0x25, 0x90, 0xfa, 0xd8, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 
-0xfe, 0x60, 0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x1e, 0xed, 0x24, 0x06, 0x60, 0x03, 0x02, 0x1f, 
-0x35, 0x78, 0x77, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0, 
-0x74, 0x33, 0x90, 0xfa, 0x90, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xae, 0x74, 0x01, 0xf0, 
-0x22, 0x78, 0x78, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0, 
-0x74, 0x43, 0x90, 0xfa, 0x92, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, 
-0x22, 0x90, 0xfa, 0x9c, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x1f, 0x35, 0x90, 0xff, 0xa6, 0xe0, 
-0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 
-0x90, 0xff, 0xa6, 0x12, 0x20, 0x83, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6, 
-0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x57, 0x90, 0xfa, 
-0xca, 0xe0, 0xff, 0x74, 0x34, 0x90, 0xfa, 0x94, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa6, 
-0xe0, 0xa3, 0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90, 
-0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x20, 0x83, 0x90, 
-0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44, 
-0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 
-0x96, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 
-0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 
-0x06, 0xc0, 0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc8, 0xf0, 0x90, 0xff, 0x92, 0xe4, 
-0xf0, 0xef, 0x12, 0x15, 0x0f, 0x1f, 0xed, 0x26, 0x1f, 0xed, 0x2e, 0x1f, 0x90, 0x30, 0x1f, 0x90, 
-0x32, 0x1f, 0x9e, 0x38, 0x1f, 0xb0, 0x3a, 0x1f, 0xe2, 0x3e, 0x1f, 0xcd, 0x44, 0x1f, 0xc2, 0x46, 
-0x1f, 0xd8, 0x50, 0x1f, 0xd8, 0x52, 0x1f, 0xd8, 0x54, 0x1f, 0xd8, 0x56, 0x00, 0x00, 0x1f, 0xf2, 
-0x90, 0xfa, 0xc8, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x10, 0x9c, 0x80, 0x62, 0x7c, 0x00, 
-0x7d, 0x01, 0x7f, 0x03, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 
-0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x02, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 
-0x80, 0x3e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x10, 0x9c, 0x80, 0x33, 0x7c, 0x00, 0x7d, 
-0x01, 0x7f, 0x06, 0x12, 0x10, 0x9c, 0x80, 0x28, 0x90, 0xfa, 0xc8, 0xe0, 0xff, 0x12, 0x1e, 0x4a, 
-0x80, 0x1e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x10, 0x9c, 0x80, 0x13, 0x12, 0x25, 0x13, 
-0x80, 0x0e, 0x90, 0xfa, 0xc8, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x29, 0xda, 
-0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 
-0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x82, 0xe6, 0xfe, 0x08, 
-0xe6, 0x24, 0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x78, 0x82, 0xe6, 
-0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 
-0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 0xff, 0x7a, 0x2f, 0x79, 0x52, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 
-0x13, 0x8f, 0xff, 0x90, 0xf9, 0x6b, 0x02, 0x14, 0xfd, 0x90, 0xf9, 0x66, 0x12, 0x14, 0xfd, 0x90, 
-0x00, 0x04, 0x02, 0x13, 0xce, 0xe6, 0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 
-0x78, 0x84, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xed, 0x12, 0x14, 0x0d, 0x8f, 0x82, 0x8e, 0x83, 
-0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 
-0xf0, 0x4e, 0xf0, 0x22, 0x78, 0x84, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 0x83, 0x22, 0xa6, 0x07, 
-0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x22, 0x78, 0x84, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0x22, 0x78, 0x86, 
-0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, 
-0x8a, 0x83, 0xe5, 0x82, 0x22, 0x8b, 0x38, 0x8a, 0x39, 0x89, 0x3a, 0x8d, 0x3b, 0x90, 0xfa, 0xce, 
-0xe4, 0xf0, 0xa3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe0, 
-0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xcd, 0xe0, 0x65, 
-0x3b, 0x60, 0x46, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x21, 
-0x54, 0x90, 0xfa, 0xcd, 0xe0, 0xff, 0x90, 0xfa, 0xd0, 0xe4, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0x12, 
-0x21, 0x54, 0x90, 0xfa, 0xd0, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xce, 0xcf, 0xf0, 0xa3, 0xef, 
-0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xa3, 0x75, 0xf0, 0x00, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xce, 0xe4, 
-0x75, 0xf0, 0x04, 0x12, 0x14, 0x2f, 0x02, 0x20, 0xd6, 0x90, 0xfa, 0xcf, 0xe0, 0x24, 0x01, 0xff, 
-0x90, 0xfa, 0xce, 0xe0, 0x34, 0x00, 0xab, 0x38, 0xaa, 0x39, 0xa9, 0x3a, 0x8f, 0xf0, 0x12, 0x14, 
-0x93, 0x7f, 0x00, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe4, 0x75, 0xf0, 
-0x01, 0x12, 0x14, 0x2f, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x8f, 0x68, 
-0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xfb, 
-0xf0, 0x44, 0x02, 0xf0, 0x08, 0x12, 0x20, 0x65, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x20, 0x7c, 
-0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x82, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 
-0xf5, 0x82, 0x8e, 0x83, 0xe0, 0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x68, 0x24, 0xfe, 0x44, 0x20, 0xfc, 
-0x4d, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 
-0x82, 0x8e, 0x83, 0xa3, 0x74, 0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 
-0x05, 0x12, 0x20, 0x25, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x95, 0x25, 0x68, 0xf5, 0x82, 
-0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 
-0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 
-0x25, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x68, 0xf8, 0x74, 0x04, 0x46, 
-0xf6, 0x7f, 0x00, 0x22, 0x8b, 0x62, 0x8a, 0x63, 0x89, 0x64, 0x12, 0x2a, 0x62, 0x90, 0xfa, 0xbf, 
-0x12, 0x15, 0x06, 0xaa, 0x63, 0xa9, 0x64, 0x90, 0xfa, 0xc2, 0x12, 0x15, 0x06, 0x90, 0xfa, 0xc3, 
-0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xc2, 0x12, 0x14, 0xfd, 0xe9, 0x24, 0x01, 
-0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc5, 0x12, 0x15, 0x06, 0xab, 0x62, 0xaa, 0x63, 0xa9, 0x64, 
-0x12, 0x2a, 0x6e, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x88, 0xf6, 0x90, 0xfa, 0xbd, 0xe0, 
-0xff, 0x78, 0x88, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xbf, 0x12, 0x2a, 0x43, 0xff, 0x78, 
-0x89, 0xf6, 0x90, 0xfa, 0xc2, 0x12, 0x2a, 0x43, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x89, 0xf6, 0x12, 
-0x2a, 0x40, 0x5e, 0x4f, 0xff, 0x78, 0x89, 0xf6, 0x12, 0x2a, 0x49, 0x75, 0xf0, 0x02, 0x12, 0x14, 
-0x2f, 0x90, 0xfa, 0xc3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0xab, 0x62, 0xaa, 0x63, 0xa9, 
-0x64, 0x90, 0x00, 0x04, 0x12, 0x13, 0xce, 0x30, 0xe4, 0x03, 0x12, 0x2a, 0x58, 0x78, 0x88, 0x06, 
-0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x22, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x90, 0xfa, 
-0xbe, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbd, 0xf0, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x26, 
-0x14, 0x70, 0x70, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x22, 0x14, 0x80, 
-0x62, 0x12, 0x2a, 0x79, 0x12, 0x1d, 0x5e, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0x80, 0x55, 0x90, 0xfa, 
-0xbe, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, 0x12, 
-0x29, 0x85, 0x80, 0x3f, 0xe5, 0x5e, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5d, 0xfa, 0x7b, 0x01, 0xc0, 
-0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xfd, 0x90, 
-0x00, 0x08, 0x12, 0x14, 0x5b, 0xf5, 0x41, 0x85, 0xf0, 0x40, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 
-0x12, 0x23, 0xee, 0x90, 0xfa, 0xbd, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, 0xbe, 
-0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbe, 0xe0, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x02, 0x12, 0x14, 0x0d, 
-0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x22, 0x12, 0x0f, 0x89, 0x7f, 0x02, 0x12, 0x11, 0x9f, 0x78, 0x6d, 
-0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, 0xb1, 0xd2, 0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 
-0x7a, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 
-0x78, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 
-0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, 0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 
-0xe3, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, 0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 
-0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7a, 
-0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x78, 
-0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x15, 
-0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe3, 0xe0, 0xf5, 0xa8, 0x02, 0x10, 0x0c, 0x8b, 0x3c, 
-0x8a, 0x3d, 0x89, 0x3e, 0x8d, 0x3f, 0xe5, 0x3f, 0x70, 0x03, 0xaf, 0x3f, 0x22, 0x12, 0x2a, 0xa8, 
-0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x40, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x2e, 0xd4, 0x50, 0xf2, 
-0x12, 0x24, 0x7b, 0x40, 0x0b, 0x7f, 0x00, 0x22, 0x12, 0x2a, 0xc7, 0x12, 0x24, 0x7b, 0x50, 0xf8, 
-0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, 0x3f, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 
-0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, 0xf5, 0x42, 0xe5, 0x3f, 0x14, 0xff, 0xe5, 0x42, 0xc3, 
-0x9f, 0x50, 0x2a, 0x12, 0x2e, 0xbd, 0x40, 0x03, 0xaf, 0x42, 0x22, 0xc3, 0xe5, 0x3f, 0x95, 0x42, 
-0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2a, 0xba, 0x05, 0x42, 
-0x74, 0x01, 0x25, 0x3e, 0xf5, 0x3e, 0xe4, 0x35, 0x3d, 0xf5, 0x3d, 0x80, 0xcc, 0x12, 0x2e, 0xbd, 
-0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xba, 0xaf, 0x3f, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x41, 
-0xf0, 0x02, 0x2e, 0xd4, 0x75, 0xa8, 0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x91, 
-0x02, 0x24, 0xce, 0x02, 0x2e, 0x88, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 
-0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 
-0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 
-0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x28, 
-0xcb, 0xe4, 0x7e, 0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 
-0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 
-0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 
-0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 
-0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x36, 0x12, 0x19, 0x21, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x36, 0x24, 
-0x03, 0xff, 0x12, 0x2d, 0x4f, 0x12, 0x19, 0x21, 0xe4, 0xf0, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94, 
-0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x36, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x90, 0x12, 0x19, 
-0x62, 0x60, 0x2c, 0x12, 0x29, 0xda, 0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 
-0x90, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x36, 0x90, 0xfa, 0x9c, 
-0x12, 0x14, 0xdf, 0xe0, 0xa3, 0x30, 0xe6, 0x33, 0x12, 0x19, 0x21, 0x74, 0x04, 0xf0, 0x22, 0x75, 
-0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x19, 0x62, 0x60, 0x16, 0x12, 0x29, 0xda, 0xef, 
-0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3, 
-0xf0, 0x22, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 
-0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 
-0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xfb, 0x0f, 0x12, 0x18, 0x19, 0x80, 
-0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x31, 0x9d, 0xf5, 0x31, 0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0xd3, 
-0xe5, 0x31, 0x94, 0x00, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 
-0x12, 0x19, 0x3e, 0x12, 0x19, 0x92, 0x12, 0x19, 0x8c, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x1e, 
-0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x13, 0xce, 0xff, 0x24, 0xfc, 
-0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x10, 0x9c, 0x12, 0x19, 
-0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4, 
-0xff, 0x12, 0x2f, 0x6a, 0x22, 0x8b, 0x4b, 0x8a, 0x4c, 0x89, 0x4d, 0x8c, 0x4e, 0x8d, 0x4f, 0xd2, 
-0x00, 0x12, 0x2a, 0xa8, 0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x4e, 0x90, 0xff, 0xf1, 0xf0, 0x12, 
-0x2e, 0xd4, 0x50, 0xf2, 0x12, 0x26, 0x9a, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xc7, 0x12, 
-0x26, 0x9a, 0x50, 0xf8, 0xe4, 0xf5, 0x51, 0xe5, 0x50, 0x14, 0xff, 0xe5, 0x51, 0xc3, 0x9f, 0x50, 
-0x17, 0x12, 0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x05, 0x51, 0x74, 0x01, 0x25, 0x4d, 0xf5, 
-0x4d, 0xe4, 0x35, 0x4c, 0xf5, 0x4c, 0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 
-0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x7f, 0x00, 0x22, 0xab, 0x4b, 0xaa, 0x4c, 0xa9, 0x4d, 
-0x12, 0x13, 0xb5, 0x90, 0xff, 0xf1, 0xf0, 0x02, 0x2e, 0xd4, 0x90, 0xff, 0xf1, 0xe5, 0x4f, 0xf0, 
-0x02, 0x2e, 0xd4, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90, 0xfa, 
-0xcb, 0xe4, 0x75, 0xf0, 0x09, 0x12, 0x14, 0x2f, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 
-0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x12, 
-0x23, 0xee, 0x90, 0xff, 0xf7, 0xe5, 0x37, 0x12, 0x26, 0xfe, 0x90, 0xff, 0xf6, 0xe5, 0x37, 0xf0, 
-0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x06, 0x12, 0x26, 0xfe, 0xe5, 0x37, 0x30, 0xe0, 0x07, 
-0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, 0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 
-0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85, 
-0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x15, 0x6b, 0xa8, 0x6b, 0xa6, 0x07, 0x30, 
-0x08, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x6b, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 
-0x78, 0x82, 0x76, 0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 
-0x82, 0x76, 0xff, 0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x86, 0x76, 0xfa, 
-0x08, 0x76, 0x9a, 0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x20, 0xb7, 0x7b, 
-0x01, 0x7a, 0xff, 0x79, 0x48, 0x78, 0x6e, 0x12, 0x14, 0xf4, 0xa8, 0x6b, 0xe6, 0x24, 0xfd, 0x75, 
-0xf0, 0x08, 0xa4, 0xff, 0xae, 0xf0, 0x78, 0x70, 0x12, 0x20, 0xb7, 0x79, 0x08, 0x78, 0x71, 0x12, 
-0x14, 0xf4, 0x78, 0x73, 0xef, 0x12, 0x20, 0xb7, 0x05, 0x6b, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 
-0xab, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe2, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 
-0x79, 0xcb, 0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7e, 0x00, 0x90, 0xfa, 
-0xe0, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x52, 
-0x09, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe0, 0xe0, 0x70, 0x04, 
-0xa3, 0xe0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x65, 
-0xe0, 0x44, 0x10, 0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe2, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 
-0x54, 0xef, 0xf0, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x90, 0xff, 0x93, 0x74, 0x2a, 
-0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, 0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 
-0xe0, 0x44, 0x90, 0xf0, 0x12, 0x27, 0x8b, 0x12, 0x15, 0x35, 0x12, 0x2d, 0xa5, 0x7e, 0x07, 0x7f, 
-0xd0, 0x12, 0x11, 0x68, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0x82, 0xe4, 0x78, 0x7d, 0xf6, 0x78, 
-0x7d, 0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x74, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x7d, 
-0x06, 0x80, 0xec, 0x7f, 0x03, 0x12, 0x2c, 0x5b, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe4, 0x05, 0x7f, 
-0x04, 0x12, 0x2c, 0x5b, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, 
-0xe0, 0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x90, 0xef, 0xf6, 0x12, 0x27, 
-0x19, 0x12, 0x20, 0x59, 0x30, 0xe0, 0x25, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x7f, 0xf0, 0x78, 0x71, 
-0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, 0xe4, 
-0x12, 0x14, 0x0d, 0x80, 0xe9, 0x12, 0x20, 0x2d, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x20, 0x59, 0x30, 
-0xe1, 0x1e, 0x12, 0x20, 0x1b, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x2f, 0x15, 0x78, 0x6e, 0x12, 0x14, 
-0xeb, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x14, 0x0d, 0x12, 0x20, 0x1b, 0xe0, 0x44, 0x80, 0xf0, 
-0x12, 0x2f, 0x80, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x03, 0x6e, 0x01, 0xff, 0x48, 
-0x03, 0x71, 0x01, 0xff, 0x08, 0x02, 0x6c, 0x00, 0x00, 0x44, 0xfa, 0x94, 0x00, 0x00, 0x00, 0x00, 
-0x44, 0xfa, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xae, 0x00, 0x00, 0x42, 0xfa, 0x7a, 0x00, 
-0x00, 0x42, 0xfa, 0x78, 0x00, 0x00, 0x42, 0xf9, 0x69, 0xff, 0xff, 0x42, 0xfa, 0x76, 0x00, 0x00, 
-0x43, 0xf9, 0x16, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x63, 0x20, 0x41, 0xf9, 0x64, 0x20, 0x41, 0xf9, 
-0x61, 0x00, 0x41, 0xf9, 0x62, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf9, 0x65, 
-0x00, 0x41, 0xf9, 0x15, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 0x19, 0x82, 
-0xe5, 0x31, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x31, 0x94, 
-0x08, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x11, 0x7f, 0x08, 0xef, 0xe5, 0x31, 0x94, 0x08, 0xf5, 0x31, 
-0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0x80, 0x05, 0xaf, 0x31, 0x12, 0x19, 0x92, 0xe4, 0xfe, 0xee, 
-0xc3, 0x9f, 0x50, 0x19, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 
-0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, 0xf0, 0x0e, 0x12, 0x18, 0x19, 0x80, 0xe2, 0xef, 0x54, 0x7f, 
-0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, 0x5f, 0x8a, 0x60, 0x89, 0x61, 0x12, 0x2a, 0x6e, 0x70, 0x05, 
-0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, 0x5f, 0xaa, 0x60, 0xa9, 0x61, 0x12, 0x2a, 0x62, 0x90, 0xfa, 
-0xc5, 0x12, 0x15, 0x06, 0xe5, 0x61, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x60, 0xfa, 0x90, 0xfa, 0xbf, 
-0x12, 0x15, 0x06, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x78, 0x91, 0xf6, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 
-0x78, 0x91, 0xe6, 0xc3, 0x9f, 0x50, 0x12, 0x12, 0x2a, 0x40, 0xff, 0x12, 0x2a, 0x49, 0x12, 0x2a, 
-0x5c, 0x78, 0x91, 0x06, 0x12, 0x2a, 0x58, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x2f, 
-0x06, 0xe4, 0x93, 0xff, 0x78, 0x7a, 0xf6, 0x54, 0x0f, 0x12, 0x19, 0x07, 0xe0, 0x08, 0x76, 0x00, 
-0x08, 0xf6, 0x18, 0x12, 0x18, 0x42, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x7b, 
-0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, 0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 
-0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, 0x22, 0x78, 0x7b, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 
-0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 
-0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0x00, 0x03, 0x12, 0x13, 0xce, 0x54, 0xf0, 0x24, 0xa0, 0x22, 
-0x90, 0xfa, 0xc5, 0x12, 0x14, 0xfd, 0x02, 0x13, 0xb5, 0x90, 0xfa, 0xbf, 0x12, 0x14, 0xfd, 0xef, 
-0x12, 0x13, 0xfb, 0x90, 0xfa, 0xc6, 0xe4, 0x22, 0x90, 0xfa, 0xc0, 0xe4, 0x75, 0xf0, 0x01, 0x02, 
-0x14, 0x2f, 0x90, 0x00, 0x08, 0x12, 0x14, 0x5b, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 
-0x05, 0x12, 0x13, 0xce, 0x90, 0xfa, 0xbd, 0xf0, 0x22, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x22, 
-0x90, 0xfa, 0xd9, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 
-0xd2, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xd4, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef, 0x25, 0x57, 
-0xf5, 0x57, 0xee, 0x35, 0x56, 0xf5, 0x56, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 
-0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe2, 0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x3c, 
-0xaa, 0x3d, 0xa9, 0x3e, 0x02, 0x13, 0xfb, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x6a, 
-0xed, 0x70, 0x0f, 0xe5, 0x6a, 0xb4, 0x03, 0x05, 0x7f, 0x01, 0x02, 0x2e, 0xeb, 0x7f, 0x02, 0x02, 
-0x2e, 0xeb, 0xaf, 0x6a, 0x12, 0x27, 0x19, 0x74, 0x74, 0x25, 0x6a, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 
-0xd2, 0x09, 0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x6a, 0xb4, 
-0x03, 0x07, 0x7f, 0x81, 0x12, 0x2e, 0xeb, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x2e, 0xeb, 0x30, 0x09, 
-0x07, 0x12, 0x18, 0x9b, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x22, 0x12, 0x0f, 0x89, 0x90, 
-0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, 0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 
-0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, 0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x2c, 0x80, 
-0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x0d, 0x12, 0x19, 0x3e, 0x53, 0x2c, 0x7f, 0x90, 
-0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, 0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0x9f, 
-0x12, 0x19, 0x46, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78, 0x8a, 0x12, 0x20, 0x9e, 0x30, 0xe1, 
-0x07, 0x7f, 0x13, 0x12, 0x2e, 0xa5, 0x80, 0x34, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60, 0x16, 
-0x78, 0x8a, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, 0x90, 
-0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x04, 0xf0, 0x78, 0x8a, 
-0xe6, 0xff, 0x12, 0x20, 0x59, 0xfd, 0x12, 0x2d, 0x21, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12, 
-0x0f, 0x89, 0x78, 0x8f, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x27, 0x19, 0x90, 0xf9, 0x66, 0x12, 0x14, 
-0xfd, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 
-0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x20, 0x4b, 0x12, 0x2f, 0x80, 0x78, 
-0x8f, 0xe6, 0xff, 0x12, 0x19, 0xbb, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78, 
-0x8b, 0xef, 0xf6, 0x12, 0x2e, 0x4c, 0x12, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60, 
-0x16, 0x78, 0x8b, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 
-0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x14, 0xf0, 0xe0, 0x70, 0x02, 
-0xd2, 0xb3, 0x02, 0x10, 0x0c, 0x8f, 0x69, 0x12, 0x27, 0x19, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x3f, 
-0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, 
-0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0x74, 
-0x74, 0x25, 0x69, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 0x7f, 0x00, 0x22, 0x8f, 0x37, 0xc2, 0x08, 0x12, 
-0x27, 0x19, 0x12, 0x20, 0x38, 0x78, 0x84, 0x12, 0x20, 0x1d, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x20, 
-0x70, 0x12, 0x20, 0x21, 0xe0, 0x20, 0xe0, 0xf6, 0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 
-0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0xaf, 0x37, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f, 
-0x89, 0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x24, 0x06, 0x12, 0x20, 0x23, 0xe0, 0xfd, 0x12, 0x20, 
-0x53, 0x90, 0x00, 0x03, 0x12, 0x20, 0x78, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x04, 
-0x12, 0x14, 0x0d, 0x12, 0x2f, 0x80, 0x7d, 0x02, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c, 
-0xae, 0x05, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x35, 
-0xe4, 0x95, 0x34, 0x40, 0x02, 0xae, 0x35, 0xee, 0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, 
-0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 0x12, 0x14, 0x0d, 0xaf, 0x06, 0x12, 0x2f, 0x6a, 
-0x22, 0x12, 0x0f, 0x89, 0x78, 0x8c, 0x12, 0x20, 0x9e, 0x30, 0xe2, 0x07, 0x7f, 0x13, 0x12, 0x2e, 
-0xa5, 0x80, 0x1b, 0x78, 0x8c, 0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x20, 0xe1, 0x07, 0x7f, 0x12, 0x12, 
-0x2e, 0xa5, 0x80, 0x0a, 0x78, 0x8c, 0xe6, 0xff, 0x12, 0x21, 0x6e, 0x12, 0x2e, 0xa5, 0x02, 0x10, 
-0x0c, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, 
-0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 0x74, 0x74, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, 
-0x74, 0x95, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, 
-0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, 
-0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x80, 0xf0, 0x74, 
-0x74, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31, 0x64, 
-0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, 
-0xc3, 0xe5, 0x31, 0x9f, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x05, 0x12, 0x25, 0x9c, 0x80, 0x03, 0x12, 
-0x2f, 0x76, 0x02, 0x10, 0x0c, 0x90, 0xff, 0xfc, 0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, 
-0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, 
-0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0x80, 0xef, 0x22, 0x12, 0x0f, 0x89, 0x78, 
-0x6c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, 
-0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x11, 0x9f, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x8e, 0x65, 
-0x8f, 0x66, 0xe5, 0x66, 0x15, 0x66, 0xae, 0x65, 0x70, 0x02, 0x15, 0x65, 0xd3, 0x94, 0x00, 0xee, 
-0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 0x12, 0x0f, 0x62, 0x80, 0xe5, 0x22, 0x11, 0x1a, 
-0x2b, 0x1c, 0x23, 0x56, 0x2f, 0x5c, 0x2d, 0xcc, 0x2d, 0x7a, 0x2e, 0x6b, 0x2c, 0x8e, 0x2b, 0x66, 
-0x2b, 0xec, 0x2c, 0xf1, 0x2e, 0x2d, 0x1b, 0xe6, 0x2b, 0xaf, 0x28, 0x67, 0x0e, 0x12, 0x0f, 0x89, 
-0x78, 0x8d, 0x12, 0x20, 0x9e, 0x20, 0xe2, 0x07, 0x7f, 0x11, 0x12, 0x2e, 0xa5, 0x80, 0x0a, 0x78, 
-0x8d, 0xe6, 0xff, 0x12, 0x2c, 0x25, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x8f, 0x67, 0x12, 0x2c, 
-0x25, 0xaf, 0x67, 0x12, 0x27, 0x19, 0x12, 0x20, 0x38, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x67, 
-0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x67, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31, 
-0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x05, 0x12, 0x29, 0x2d, 0x80, 0x06, 0x12, 
-0x19, 0x7a, 0x12, 0x19, 0x82, 0x02, 0x10, 0x0c, 0x12, 0x27, 0xfb, 0x12, 0x12, 0x3b, 0x90, 0xf8, 
-0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x11, 0xd8, 0x12, 0x26, 0xa3, 0x12, 0x12, 0x77, 
-0x12, 0x10, 0xfa, 0x80, 0xe3, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0xe4, 0xf5, 0x2a, 0xf5, 
-0x2b, 0xef, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4, 0xff, 0x12, 0x2f, 0x6a, 0x22, 0x90, 0xff, 0xf0, 
-0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 
-0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, 
-0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, 
-0x18, 0xad, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 0x18, 0xf7, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 
-0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 
-0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x84, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 
-0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 0x34, 0x30, 0x85, 0x35, 0x31, 0x90, 0xff, 
-0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x2f, 
-0x00, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, 
-0x38, 0x28, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0f, 0x89, 0x7f, 
-0x02, 0x12, 0x10, 0x18, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x12, 
-0x18, 0x49, 0x12, 0x29, 0x2d, 0x22, 0x12, 0x19, 0x82, 0x12, 0x19, 0x3e, 0x12, 0x19, 0x7a, 0x22, 
-0xc2, 0x08, 0x22, 
+0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x12, 0x41, 0xad, 0x07, 0xaf, 0x02, 
+0x12, 0x12, 0x58, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x11, 0x66, 0x80, 0xc1, 0x8f, 
+0x24, 0x12, 0x2a, 0x06, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 
+0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xed, 0xf0, 
+0x12, 0x22, 0x56, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x12, 0x22, 0x99, 0x24, 0x09, 0x12, 
+0x21, 0xf3, 0xef, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0x09, 0xc0, 
+0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 
+0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x80, 0x12, 0x22, 0x09, 
+0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x21, 
+0xf3, 0xef, 0xf0, 0xed, 0x12, 0x22, 0x99, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xed, 0xf0, 0x12, 0x21, 
+0xfb, 0xe0, 0xff, 0x30, 0xe7, 0x19, 0x12, 0x22, 0x6e, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x09, 0x12, 
+0x21, 0xfb, 0xef, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x12, 0x21, 0xfb, 0xef, 0x54, 0xfd, 0xf0, 0x78, 
+0x7e, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 
+0xfd, 0x12, 0x22, 0x43, 0xa3, 0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 
+0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x31, 0x94, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x78, 0x80, 
+0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x06, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x03, 0x43, 0x07, 
+0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x22, 0x7a, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x42, 
+0x07, 0x43, 0x07, 0x80, 0x12, 0x22, 0x8a, 0xf5, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12, 
+0x22, 0x99, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0, 
+0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, 0x03, 0x43, 0x07, 0x20, 0xec, 
+0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 
+0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x69, 0x78, 0x80, 0x12, 0x22, 0x6f, 
+0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x14, 0xa6, 0x00, 0x14, 0xda, 0x01, 0x14, 0xdf, 0x03, 
+0x14, 0xda, 0x05, 0x14, 0xdf, 0x07, 0x14, 0xda, 0x09, 0x14, 0xdf, 0x0b, 0x14, 0xda, 0x0d, 0x14, 
+0xdf, 0x0f, 0x00, 0x00, 0x14, 0xe7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x21, 0x90, 0xf9, 0x15, 0xe0, 
+0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80, 0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27, 
+0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 
+0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 
+0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x22, 0x78, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xef, 
+0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 0x54, 
+0x03, 0x70, 0x03, 0x02, 0x15, 0xd7, 0xee, 0x20, 0xe1, 0x03, 0x02, 0x15, 0xd4, 0x12, 0x22, 0x6e, 
+0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x15, 0x36, 0x00, 0x15, 0x6c, 0x01, 0x15, 0x6c, 0x03, 
+0x15, 0xa0, 0x05, 0x15, 0xa0, 0x07, 0x15, 0x86, 0x09, 0x15, 0x86, 0x0b, 0x15, 0xba, 0x0d, 0x15, 
+0xba, 0x0f, 0x00, 0x00, 0x15, 0xd7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x15, 0xe0, 
+0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53, 0x07, 0x7f, 0x02, 0x15, 0xd7, 0x43, 0x07, 0x80, 0x02, 
+0x15, 0xd7, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30, 
+0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70, 0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03, 
+0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 
+0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 
+0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37, 
+0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 
+0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 
+0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43, 
+0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x80, 0x12, 0x22, 0x3f, 0xe0, 0xfc, 0xa3, 0xe0, 
+0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05, 
+0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80, 
+0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7, 
+0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05, 
+0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80, 
+0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0x3f, 0xa3, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0x7f, 
+0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74, 
+0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 
+0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x12, 0x18, 0xe2, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2, 
+0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa, 0xcc, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 
+0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 
+0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe5, 
+0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23, 0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64, 
+0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12, 0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5, 
+0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02, 0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16, 
+0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 
+0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4, 0x41, 0x12, 0x90, 0xf9, 0x15, 0xe0, 0x44, 
+0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1, 0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x15, 
+0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60, 
+0x05, 0xe5, 0x23, 0xb4, 0x43, 0x0c, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x80, 0xf0, 0xa3, 0xe0, 0x44, 
+0x80, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x18, 0xe2, 0x90, 0xff, 
+0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1d, 0x84, 
+0x12, 0x1c, 0x30, 0x12, 0x1d, 0x8b, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x43, 0x90, 0xf9, 0x6c, 0x12, 
+0x1b, 0x43, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, 
+0x74, 0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x23, 0xe5, 0x23, 
+0x12, 0x1c, 0xa7, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1c, 0xb5, 0xf5, 0x83, 0xe4, 0xf0, 
+0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x31, 
+0x4d, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x31, 0x5a, 0xe4, 0x93, 0xff, 
+0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1c, 0x97, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, 
+0x08, 0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, 
+0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0x28, 0xce, 0xc3, 0x13, 0xce, 
+0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1c, 0xf8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0x1e, 0xe4, 0xf5, 
+0x23, 0xe5, 0x23, 0x90, 0x31, 0x47, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0, 
+0x24, 0x4e, 0xf5, 0x82, 0xe4, 0x34, 0x31, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, 
+0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0x97, 0x12, 0x1d, 0x06, 0x24, 0x47, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, 
+0x1c, 0xf8, 0xef, 0xf0, 0x12, 0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 
+0x0b, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0x1e, 
+0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 
+0xf0, 0x02, 0x18, 0xb7, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0xea, 0x12, 0x1d, 0x06, 
+0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 
+0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, 
+0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x05, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x23, 0xe5, 0x23, 0x64, 0x04, 0x60, 0x03, 0x02, 
+0x17, 0xe1, 0x90, 0x31, 0x4c, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1c, 0xe8, 0xe4, 0xf0, 
+0x90, 0x31, 0x4b, 0x93, 0xff, 0xf6, 0x12, 0x1c, 0x95, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, 
+0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 
+0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0xe7, 0x09, 0xf6, 0x08, 
+0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, 
+0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, 
+0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, 
+0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x58, 
+0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80, 0xd2, 0x80, 0xfa, 
+0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80, 0xa6, 0x80, 0xea, 
+0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89, 0x82, 0x8a, 0x83, 
+0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 
+0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d, 0x89, 0x82, 0x8a, 
+0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, 0xfb, 0x22, 0x89, 
+0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 
+0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8, 0x80, 0xdb, 0x89, 
+0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, 
+0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, 
+0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x19, 
+0x4c, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 
+0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, 
+0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, 
+0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, 
+0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 
+0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 
+0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 
+0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xc5, 0xf0, 0xf8, 0xa3, 
+0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0x38, 
+0xf0, 0x22, 0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 
+0x15, 0x83, 0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 
+0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 
+0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 
+0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22, 
+0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x06, 0xf7, 
+0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3, 0x19, 0x22, 0xf8, 
+0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0xe5, 
+0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6, 0xf0, 0x22, 0xbb, 
+0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 0x22, 0xa4, 0x25, 0x82, 0xf5, 
+0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xfa, 0x08, 0xe6, 0xf9, 
+0x22, 0xeb, 0xf6, 0x08, 0xea, 0xf6, 0x08, 0xe9, 0xf6, 0x22, 0xe0, 0xfb, 0xa3, 0xe0, 0xfa, 0xa3, 
+0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 0x83, 0xd0, 0x82, 
+0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 
+0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 
+0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 
+0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0x74, 0x11, 0x12, 
+0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06, 
+0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 
+0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0x38, 0x04, 0x25, 
+0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 
+0x38, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab, 
+0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 
+0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 
+0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x22, 0xf5, 0x83, 0xe0, 0x54, 
+0x08, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, 
+0x78, 0x7b, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, 
+0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x6f, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x12, 
+0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 
+0x00, 0xc3, 0x90, 0xfa, 0xbd, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbc, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 
+0xb4, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5, 
+0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb1, 0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 
+0xf5, 0x2e, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, 
+0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, 
+0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, 
+0x34, 0xff, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, 
+0x22, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, 
+0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9, 
+0x6c, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 
+0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, 
+0xa4, 0x22, 0x74, 0xaf, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, 
+0x08, 0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, 
+0xff, 0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, 
+0xfc, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x67, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, 
+0x65, 0xf0, 0x22, 0x12, 0x1b, 0x1c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, 
+0xfa, 0x79, 0xb4, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, 
+0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x67, 0x02, 0x1b, 0x3a, 0x90, 0xff, 0xa4, 0xe0, 
+0x44, 0x02, 0xf0, 0x22, 0x75, 0x39, 0x01, 0x75, 0x3a, 0x09, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 0x79, 
+0x6f, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbb, 0xe0, 
+0xff, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, 
+0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0x06, 0x12, 0x22, 
+0x4a, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x0a, 
+0x12, 0x22, 0x52, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0x4a, 0x12, 
+0x22, 0x4a, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x22, 0x56, 0x24, 
+0x04, 0x12, 0x21, 0xf3, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55, 
+0xe5, 0x53, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x88, 0xf6, 0xd3, 0x94, 0x00, 0x40, 0x06, 
+0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x0c, 0xef, 
+0x12, 0x1a, 0x4a, 0x78, 0x80, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53, 
+0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20, 
+0xe5, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02, 
+0xe5, 0x53, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20, 
+0xe5, 0x53, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07, 
+0x80, 0xe5, 0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06, 
+0x08, 0xe5, 0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 
+0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0, 
+0x12, 0x1a, 0xef, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22, 
+0x2c, 0x90, 0x00, 0x08, 0xef, 0x12, 0x1a, 0x4a, 0x80, 0x0a, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x08, 
+0xe4, 0x12, 0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x07, 0xef, 0x12, 
+0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0x4a, 0x90, 
+0x00, 0x07, 0x12, 0x1a, 0x0b, 0x70, 0x13, 0x12, 0x22, 0x2d, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a, 
+0xfa, 0x12, 0x19, 0xf2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0x38, 0x12, 0x22, 0x78, 0x24, 0x08, 0x12, 
+0x21, 0xf3, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 
+0xfd, 0xee, 0xed, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0xef, 0x12, 
+0x31, 0xc7, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0x90, 0xfa, 0xe3, 0xe0, 
+0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xd7, 
+0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xff, 0x7e, 0x00, 0x90, 0xfa, 
+0xd3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1a, 
+0x98, 0xff, 0x90, 0xfa, 0xd5, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e, 
+0x50, 0x8f, 0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa, 
+0xd8, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd6, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90, 
+0xfa, 0xda, 0xf0, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0x90, 0xfa, 0xd3, 0xe0, 0x94, 0x00, 0x50, 
+0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 
+0x2d, 0x5a, 0x90, 0xfa, 0xd3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xd7, 
+0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xda, 
+0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd4, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 
+0xe0, 0xff, 0x22, 0x12, 0x2d, 0x5a, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 
+0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b, 
+0x01, 0x90, 0xfa, 0xd5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xda, 0xe0, 0xf5, 0x4a, 0x12, 
+0x28, 0x9f, 0x90, 0xfa, 0xd9, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60, 
+0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x20, 0xbb, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0x03, 0x78, 
+0x71, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33, 
+0x90, 0xfa, 0x91, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, 0x22, 0x78, 
+0x72, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43, 
+0x90, 0xfa, 0x93, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb0, 0x74, 0x01, 0xf0, 0x22, 0x90, 
+0xfa, 0x9d, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0x03, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 
+0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 
+0xa6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 
+0xcb, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x2c, 0xb4, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xcb, 0xe0, 
+0xff, 0x74, 0x34, 0x90, 0xfa, 0x95, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa7, 0xe0, 0xa3, 
+0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 
+0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xb6, 
+0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12, 
+0x2c, 0xb4, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x97, 0xf0, 
+0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 
+0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 
+0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc9, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef, 
+0x12, 0x1b, 0x4c, 0x21, 0xbb, 0x26, 0x21, 0xbb, 0x2e, 0x21, 0x5e, 0x30, 0x21, 0x5e, 0x32, 0x21, 
+0x6c, 0x38, 0x21, 0x7e, 0x3a, 0x21, 0xb0, 0x3e, 0x21, 0x9b, 0x44, 0x21, 0x90, 0x46, 0x21, 0xa6, 
+0x50, 0x21, 0xa6, 0x52, 0x21, 0xa6, 0x54, 0x21, 0xa6, 0x56, 0x00, 0x00, 0x21, 0xc0, 0x90, 0xfa, 
+0xc9, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x16, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01, 
+0x7f, 0x03, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00, 
+0x7d, 0x01, 0x7f, 0x02, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e, 
+0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x16, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 
+0x06, 0x12, 0x11, 0x16, 0x80, 0x28, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x12, 0x20, 0x18, 0x80, 0x1e, 
+0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x16, 0x80, 0x13, 0x12, 0x27, 0x8d, 0x80, 0x0e, 
+0x90, 0xfa, 0xc9, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2c, 0xb4, 0xd0, 0x07, 
+0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 
+0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24, 
+0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x12, 0x25, 0x24, 0xf5, 
+0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 
+0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 
+0xff, 0x7a, 0x31, 0x79, 0x99, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x19, 0xcc, 0xff, 0x90, 0xf9, 0x6c, 
+0x02, 0x1b, 0x3a, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x04, 0x02, 0x1a, 0x0b, 0xe6, 
+0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6, 
+0xff, 0x22, 0xed, 0x12, 0x1a, 0x4a, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, 
+0xfa, 0xcb, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x08, 0xe6, 
+0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x09, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 
+0x83, 0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6, 
+0xfb, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82, 0x22, 
+0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x02, 
+0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 
+0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xce, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3, 0xe0, 
+0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xce, 0xe0, 
+0xff, 0x90, 0xfa, 0xd1, 0xe4, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xd1, 
+0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xcf, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xce, 0xe0, 
+0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x04, 0x12, 0x1a, 
+0x6c, 0x02, 0x22, 0xb1, 0x90, 0xfa, 0xd0, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xcf, 0xe0, 0x34, 
+0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1a, 0xd0, 0x7f, 0x00, 0x22, 0x7b, 
+0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x6c, 0x85, 
+0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0x8f, 0x62, 0x12, 0x2a, 0x06, 0x12, 0x22, 
+0x4a, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0, 0x08, 
+0x12, 0x22, 0x3f, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x22, 0x56, 0x24, 0x0b, 0x12, 0x21, 0xf3, 
+0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 
+0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82, 0x24, 
+0x04, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0x74, 
+0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x21, 0xf3, 0xc0, 
+0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x96, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 
+0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 
+0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 
+0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 
+0x10, 0x03, 0x7f, 0x02, 0x12, 0x12, 0x19, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, 
+0xb1, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36, 0xd2, 
+0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7c, 
+0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x7a, 
+0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, 
+0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe4, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, 
+0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, 
+0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0, 
+0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7a, 0xe0, 
+0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe4, 0xe0, 
+0xf5, 0xa8, 0x02, 0x10, 0x86, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 
+0xc0, 0x12, 0x1b, 0x43, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x43, 0x90, 0xfa, 
+0xc4, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x3a, 0xe9, 0x24, 
+0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, 
+0x5e, 0x12, 0x2d, 0x48, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa, 0xbe, 
+0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc0, 0x12, 0x2d, 0x1d, 0xff, 
+0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0x1d, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83, 0xf6, 
+0x12, 0x2d, 0x1a, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0x23, 0x75, 0xf0, 0x02, 0x12, 
+0x1a, 0x6c, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0xab, 0x5c, 0xaa, 0x5d, 
+0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x0b, 0x30, 0xe4, 0x03, 0x12, 0x2d, 0x32, 0x78, 0x82, 
+0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbf, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58, 0x90, 
+0xfa, 0xbf, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 
+0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x24, 0x95, 
+0x80, 0x62, 0x12, 0x2d, 0x53, 0x12, 0x1f, 0x2c, 0x90, 0xfa, 0xbf, 0xef, 0xf0, 0x80, 0x55, 0x90, 
+0xfa, 0xbf, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, 
+0x12, 0x2c, 0x5f, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b, 0x01, 
+0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xfd, 
+0x90, 0x00, 0x08, 0x12, 0x1a, 0x98, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 
+0x03, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, 
+0xbf, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x02, 0x12, 0x1a, 
+0x4a, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c, 0xe5, 
+0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2d, 0x82, 0x70, 0x16, 0x12, 0x2d, 0xa1, 0xe5, 0x2d, 
+0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x26, 0x64, 0x40, 0x0b, 0x7f, 0x00, 
+0x22, 0x12, 0x2d, 0xa1, 0x12, 0x26, 0x64, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, 
+0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, 
+0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0x04, 0x40, 
+0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, 
+0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2d, 0x94, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b, 0xe4, 
+0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0x04, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2d, 
+0x94, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0x1b, 0x12, 0x10, 0x03, 
+0x78, 0x84, 0x12, 0x22, 0x82, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x30, 0xec, 0x02, 0x26, 0xfb, 
+0x78, 0x84, 0xe6, 0xf9, 0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54, 0x03, 
+0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44, 0x04, 
+0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x39, 
+0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x80, 
+0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef, 0x54, 
+0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, 
+0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x17, 0xe0, 0x04, 0xf0, 0xaf, 
+0x01, 0x12, 0x22, 0x33, 0xfd, 0x12, 0x2f, 0x49, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x75, 0xa8, 
+0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x27, 0x48, 0x02, 0x30, 0xcf, 
+0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 
+0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 
+0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 
+0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0x4c, 0xe4, 0x7e, 0x01, 0x93, 0x60, 
+0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 
+0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 
+0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 
+0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x22, 
+0x12, 0x1d, 0x12, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x2f, 0x77, 0x12, 
+0x1d, 0x12, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x22, 
+0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1d, 0x53, 0x60, 0x2c, 0x12, 0x2c, 0xb4, 
+0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 
+0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0x9d, 0x12, 0x1b, 0x1c, 0xe0, 0xa3, 0x30, 
+0xe6, 0x33, 0x12, 0x1d, 0x12, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 
+0x95, 0x12, 0x1d, 0x53, 0x60, 0x16, 0x12, 0x2c, 0xb4, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, 
+0x22, 0x90, 0xfa, 0x95, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5, 0x22, 
+0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, 
+0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, 
+0x1c, 0x11, 0x12, 0x1a, 0x38, 0x0f, 0x12, 0x1c, 0x00, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x3a, 
+0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5, 0x39, 
+0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x84, 
+0x12, 0x1d, 0x76, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, 
+0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0x0b, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, 
+0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x16, 0x12, 0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 
+0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 0x12, 0x31, 0xb1, 0x22, 0x8b, 
+0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2d, 0x82, 0x70, 0x16, 
+0x12, 0x2d, 0xa1, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x29, 
+0x14, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2d, 0xa1, 0x12, 0x29, 0x14, 0x50, 0xf8, 0xe4, 0xf5, 
+0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0x04, 0x40, 0x03, 
+0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5, 0x46, 
+0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0x04, 0x40, 0x03, 0x7f, 0x18, 
+0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x19, 0xf2, 0x90, 0xff, 0xf1, 
+0xf0, 0x02, 0x31, 0x1b, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0x1b, 0x7b, 0x01, 0x7a, 
+0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x09, 0x12, 
+0x1a, 0x6c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 
+0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xff, 0xf7, 0xe5, 
+0x23, 0x12, 0x29, 0x78, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 
+0x74, 0x06, 0x12, 0x29, 0x78, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, 
+0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 
+0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 
+0x02, 0x25, 0xd7, 0x90, 0xff, 0x93, 0x74, 0x2a, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, 
+0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9, 0x15, 
+0xf0, 0xa3, 0xf0, 0x12, 0x2a, 0x78, 0x12, 0x16, 0x42, 0x12, 0x2f, 0xcd, 0x7e, 0x07, 0x7f, 0xd0, 
+0x12, 0x11, 0xe2, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0xfc, 0xe4, 0x78, 0x77, 0xf6, 0x78, 0x77, 
+0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77, 0x06, 
+0x80, 0xec, 0x7f, 0x03, 0x12, 0x2e, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x20, 0xe4, 0x05, 0x7f, 0x04, 
+0x12, 0x2e, 0xb3, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, 0xe0, 
+0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05, 0x12, 
+0x11, 0x66, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c, 0x76, 
+0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76, 0xff, 
+0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76, 0x9b, 
+0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x22, 0x92, 0x7b, 0x01, 0x7a, 0xff, 
+0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0x31, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08, 0xa4, 
+0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x22, 0x92, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0x31, 0x78, 
+0x6d, 0xef, 0x12, 0x22, 0x92, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0, 0xe0, 
+0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 
+0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7e, 0x00, 0x90, 0xfa, 0xe1, 0xee, 0xf0, 
+0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x52, 0x09, 0x90, 0xf9, 
+0x15, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe1, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 
+0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x10, 
+0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe3, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x54, 0xef, 0xf0, 
+0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x12, 0x10, 0x03, 0x78, 0x8a, 0xef, 0xf6, 0x12, 
+0x2a, 0x06, 0x12, 0x22, 0x33, 0x30, 0xe0, 0x25, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x7f, 0xf0, 0x78, 
+0x6b, 0x12, 0x1b, 0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, 
+0xe4, 0x12, 0x1a, 0x4a, 0x80, 0xe9, 0x12, 0x22, 0x07, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x22, 0x33, 
+0x30, 0xe1, 0x1e, 0x12, 0x21, 0xe9, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x31, 0x5c, 0x78, 0x68, 0x12, 
+0x1b, 0x28, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0x4a, 0x12, 0x21, 0xe9, 0xe0, 0x44, 0x80, 
+0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x03, 0x68, 0x01, 0xff, 
+0x48, 0x03, 0x6b, 0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x95, 0x00, 0x00, 0x00, 
+0x00, 0x44, 0xfa, 0x91, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xaf, 0x00, 0x00, 0x42, 0xfa, 0x7b, 
+0x00, 0x00, 0x42, 0xfa, 0x79, 0x00, 0x00, 0x42, 0xf9, 0x6a, 0xff, 0xff, 0x42, 0xfa, 0x77, 0x00, 
+0x00, 0x43, 0xf9, 0x18, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x65, 0x20, 0x41, 0xf9, 0x66, 0x20, 0x41, 
+0xf9, 0x63, 0x00, 0x41, 0xf9, 0x64, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9, 
+0x15, 0x00, 0x00, 0x41, 0xf9, 0x17, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 
+0x10, 0x03, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x30, 0x93, 0x12, 0x30, 0xec, 0x78, 0x85, 0xe6, 0xff, 
+0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 
+0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80, 0x19, 
+0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 
+0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x14, 0xf0, 0xe0, 
+0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0x86, 0x12, 0x1d, 0x6c, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 
+0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00, 0x40, 
+0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 
+0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1d, 0x84, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12, 0x1c, 
+0x11, 0x12, 0x19, 0xf2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, 
+0xf0, 0x0e, 0x12, 0x1c, 0x00, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, 
+0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2d, 0x48, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, 
+0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xe5, 0x5b, 
+0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x43, 0xe4, 0x90, 0xfa, 
+0xbf, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f, 0x50, 
+0x12, 0x12, 0x2d, 0x1a, 0xff, 0x12, 0x2d, 0x23, 0x12, 0x2d, 0x36, 0x78, 0x8b, 0x06, 0x12, 0x2d, 
+0x32, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x31, 0x4d, 0xe4, 0x93, 0xff, 0x78, 0x74, 
+0xf6, 0x54, 0x0f, 0x12, 0x1c, 0xf8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c, 0x29, 
+0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, 
+0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, 
+0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 
+0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x90, 
+0x00, 0x03, 0x12, 0x1a, 0x0b, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x3a, 
+0x02, 0x19, 0xf2, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x3a, 0xef, 0x12, 0x1a, 0x38, 0x90, 0xfa, 0xc7, 
+0xe4, 0x22, 0x90, 0xfa, 0xc1, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1a, 0x6c, 0x90, 0x00, 0x08, 0x12, 
+0x1a, 0x98, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0x90, 0xfa, 
+0xbe, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xda, 0xe0, 0xff, 0x7e, 
+0x00, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd3, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 
+0xd5, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50, 0xf5, 
+0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe3, 
+0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02, 0x1a, 
+0x38, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64, 0xb4, 
+0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0x32, 0x7f, 0x02, 0x02, 0x31, 0x32, 0xaf, 0x64, 0x12, 0x2a, 
+0x06, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1c, 0x83, 0xe0, 
+0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12, 0x31, 
+0x32, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0x32, 0x30, 0x09, 0x07, 0x12, 0x1c, 0x83, 0xe0, 0x44, 
+0x80, 0xf0, 0x12, 0x31, 0xc7, 0x22, 0x12, 0x10, 0x03, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, 
+0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, 
+0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, 
+0xf0, 0x80, 0x0d, 0x12, 0x1d, 0x2f, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, 
+0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xb0, 0x12, 0x1d, 0x37, 0x02, 0x10, 0x86, 
+0x12, 0x10, 0x03, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0x06, 0x90, 0xf9, 0x67, 0x12, 
+0x1b, 0x3a, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe, 0x08, 
+0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0x25, 0x12, 0x31, 0xc7, 
+0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x3f, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x8f, 0x63, 0x12, 
+0x2a, 0x06, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 
+0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 
+0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 
+0x7f, 0x00, 0x22, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 0x78, 0x7e, 0x12, 
+0x21, 0xeb, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x22, 0x4a, 0x12, 0x21, 0xef, 0xe0, 0x20, 0xe0, 0xf6, 
+0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 
+0xaf, 0x23, 0x12, 0x13, 0x3f, 0x22, 0x12, 0x10, 0x03, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x4a, 0x24, 
+0x06, 0x12, 0x21, 0xf1, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x03, 0x12, 0x22, 0x52, 0x24, 
+0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x4a, 0x12, 0x31, 0xc7, 0x7d, 0x02, 
+0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0xae, 0x05, 0x12, 0x1c, 0xde, 0xef, 0x12, 0x1a, 
+0x4a, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee, 
+0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 
+0x12, 0x1a, 0x4a, 0xaf, 0x06, 0x12, 0x31, 0xb1, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 
+0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 
+0x74, 0x6e, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, 0x74, 0x96, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 
+0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 
+0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 
+0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 
+0x00, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 
+0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00, 
+0x40, 0x05, 0x12, 0x28, 0x16, 0x80, 0x03, 0x12, 0x31, 0xbd, 0x02, 0x10, 0x86, 0x90, 0xff, 0xfc, 
+0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 
+0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 
+0xf0, 0x80, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 
+0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x19, 
+0x12, 0x1d, 0x46, 0x02, 0x10, 0x86, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f, 
+0x70, 0x02, 0x15, 0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 
+0x12, 0x0f, 0xdc, 0x80, 0xe5, 0x22, 0x11, 0x94, 0x2d, 0xf6, 0x23, 0xef, 0x31, 0xa3, 0x2f, 0xf4, 
+0x2f, 0xa2, 0x30, 0xb2, 0x2e, 0xe6, 0x26, 0x6d, 0x2b, 0xaf, 0x30, 0x55, 0x30, 0x74, 0x1d, 0xb4, 
+0x2e, 0x40, 0x2a, 0xe8, 0x0e, 0x12, 0x10, 0x03, 0x78, 0x86, 0x12, 0x22, 0x82, 0x20, 0xe1, 0x07, 
+0x7f, 0x12, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x23, 0x49, 0x12, 0x30, 
+0xec, 0x02, 0x10, 0x86, 0x12, 0x10, 0x03, 0x78, 0x87, 0x12, 0x22, 0x82, 0x20, 0xe2, 0x07, 0x7f, 
+0x11, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2e, 0x7d, 0x12, 0x30, 0xec, 
+0x02, 0x10, 0x86, 0x8f, 0x61, 0x12, 0x2e, 0x7d, 0xaf, 0x61, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 
+0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13, 
+0x3f, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 
+0x05, 0x12, 0x2c, 0x07, 0x80, 0x06, 0x12, 0x1d, 0x64, 0x12, 0x1d, 0x6c, 0x02, 0x10, 0x86, 0x12, 
+0x29, 0x93, 0x12, 0x12, 0xbb, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12, 
+0x58, 0x12, 0x29, 0x1d, 0x12, 0x12, 0xf7, 0x12, 0x11, 0x74, 0x80, 0xe3, 0x12, 0x1c, 0xde, 0xef, 
+0x12, 0x1a, 0x4a, 0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 
+0x12, 0x31, 0xb1, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 
+0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 
+0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 
+0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, 0x1c, 0x95, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 
+0x1c, 0xe8, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 
+0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22, 
+0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 
+0x3b, 0x39, 0x85, 0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 
+0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x31, 0x47, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 
+0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x12, 0x10, 0x03, 0x7f, 0x02, 0x12, 0x10, 0x92, 0x12, 0x1d, 0x46, 0x02, 0x10, 
+0x86, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x12, 0x1c, 0x30, 0x12, 0x2c, 0x07, 0x22, 0x12, 0x1d, 0x6c, 
+0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x64, 0x22, 0xc2, 0x08, 0x22, 
 };
 
 #undef IMAGE_VERSION_NAME
index f4567f1..d43b9e6 100644 (file)
 #ifndef IO_TABLES_H
 #define IO_TABLES_H
 
-static struct usb_device_id edgeport_1port_id_table [] = {
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT) },
-       { }
-};
-
 static struct usb_device_id edgeport_2port_id_table [] = {
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2I) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_421) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_21) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2_DIN) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2I) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_421) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_21) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2_DIN) },
        { }
 };
 
@@ -41,12 +31,9 @@ static struct usb_device_id edgeport_4port_id_table [] = {
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4I) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4_DIN) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_22I) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_4) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_COMPATIBLE) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4T) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4I) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4_DIN) },
        { }
 };
 
@@ -54,9 +41,9 @@ static struct usb_device_id edgeport_8port_id_table [] = {
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8I) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8I) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8R) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8RR) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_8) },
        { }
 };
 
@@ -69,7 +56,6 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4I) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2I) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_421) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_21) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU) },
@@ -77,51 +63,18 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2_DIN) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4_DIN) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_22I) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_4) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_COMPATIBLE) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8I) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2I) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_421) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_21) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2_DIN) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4T) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4I) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4_DIN) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU) },
-       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8I) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8R) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8RR) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_8) },
        { }                                                     /* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
-static struct usb_serial_device_type edgeport_1port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "Edgeport 1 port adapter",
-       .short_name             = "edgeport_1",
-       .id_table               = edgeport_1port_id_table,
-       .num_interrupt_in       = 1,
-       .num_bulk_in            = 1,
-       .num_bulk_out           = 1,
-       .num_ports              = 1,
-       .open                   = edge_open,
-       .close                  = edge_close,
-       .throttle               = edge_throttle,
-       .unthrottle             = edge_unthrottle,
-       .attach                 = edge_startup,
-       .shutdown               = edge_shutdown,
-       .ioctl                  = edge_ioctl,
-       .set_termios            = edge_set_termios,
-       .tiocmget               = edge_tiocmget,
-       .tiocmset               = edge_tiocmset,
-       .write                  = edge_write,
-       .write_room             = edge_write_room,
-       .chars_in_buffer        = edge_chars_in_buffer,
-       .break_ctl              = edge_break,
-};
-
 static struct usb_serial_device_type edgeport_2port_device = {
        .owner                  = THIS_MODULE,
        .name                   = "Edgeport 2 port adapter",
index 26a8c5a..6507340 100644 (file)
 #if !defined(_USBVEND_H)
 #define        _USBVEND_H
 
-#ifndef __KERNEL__
-#include "ionprag.h"   /* Extra I/O Networks pragmas */
-
-#include <usbdi.h>
-
-#include "iondef.h"    /* Standard I/O Networks definitions */
-#endif
-
 /************************************************************************
  *
  *             D e f i n e s   /   T y p e d e f s
@@ -37,6 +29,7 @@
 // 
 
 #define        USB_VENDOR_ID_ION       0x1608          // Our VID
+#define        USB_VENDOR_ID_TI        0x0451          // TI VID
 
 //
 // Definitions of USB product IDs (PID)
 
 // ION-device OEM IDs
 #define        ION_OEM_ID_ION          0               // 00h Inside Out Networks
-#define        ION_OEM_ID_NLYNX        1               // 01h NLynx Systems      
+#define        ION_OEM_ID_NLYNX        1               // 01h NLynx Systems
 #define        ION_OEM_ID_GENERIC      2               // 02h Generic OEM
 #define        ION_OEM_ID_MAC          3               // 03h Mac Version
 #define        ION_OEM_ID_MEGAWOLF     4               // 04h Lupusb OEM Mac version (MegaWolf)
 #define        ION_OEM_ID_MULTITECH    5               // 05h Multitech Rapidports
+#define        ION_OEM_ID_AGILENT      6               // 06h AGILENT board
+
 
-       
 // ION-device Device IDs
-// Product IDs - assigned to match middle digit of serial number
+// Product IDs - assigned to match middle digit of serial number (No longer true)
 
+#define ION_DEVICE_ID_80251_NETCHIP    0x020   // This bit is set in the PID if this edgeport hardware$
+                                               // is based on the 80251+Netchip.  
 
-// The ION_DEVICE_ID_GENERATION_2 bit (0x20) will be ORed into the existing edgeport
-// PIDs to identify 80251+Netchip hardware.  This will guarantee that if a second
-// generation edgeport device is plugged into a PC with an older (pre 2.0) driver,
-// it will not enumerate.
+#define ION_DEVICE_ID_GENERATION_1     0x00    // Value for 930 based edgeports
+#define ION_DEVICE_ID_GENERATION_2     0x01    // Value for 80251+Netchip.
+#define ION_DEVICE_ID_GENERATION_3     0x02    // Value for Texas Instruments TUSB5052 chip
+#define ION_DEVICE_ID_GENERATION_4     0x03    // Watchport Family of products
+#define ION_GENERATION_MASK            0x03
 
-#define ION_DEVICE_ID_GENERATION_2     0x020   // This bit is set in the PID if this edgeport hardware
-                                                                                                                       // is based on the 80251+Netchip.  
+#define ION_DEVICE_ID_HUB_MASK         0x0080  // This bit in the PID designates a HUB device
+                                               // for example 8C would be a 421 4 port hub
+                                               // and 8D would be a 2 port embedded hub
 
-#define EDGEPORT_DEVICE_ID_MASK                        0x3df   // Not including GEN_2 bit
+#define EDGEPORT_DEVICE_ID_MASK                        0x0ff   // Not including OEM or GENERATION fields
 
 #define        ION_DEVICE_ID_UNCONFIGURED_EDGE_DEVICE  0x000   // In manufacturing only
 #define ION_DEVICE_ID_EDGEPORT_4               0x001   // Edgeport/4 RS232
-//     ION_DEVICE_ID_HUBPORT_7                 0x002   // Hubport/7 (Placeholder, not used by software)
+#define        ION_DEVICE_ID_EDGEPORT_8R               0x002   // Edgeport with RJ45 no Ring
 #define ION_DEVICE_ID_RAPIDPORT_4              0x003   // Rapidport/4
 #define ION_DEVICE_ID_EDGEPORT_4T              0x004   // Edgeport/4 RS232 for Telxon (aka "Fleetport")
 #define ION_DEVICE_ID_EDGEPORT_2               0x005   // Edgeport/2 RS232
 #define ION_DEVICE_ID_EDGEPORT_4I              0x006   // Edgeport/4 RS422
 #define ION_DEVICE_ID_EDGEPORT_2I              0x007   // Edgeport/2 RS422/RS485
-//     ION_DEVICE_ID_HUBPORT_4                 0x008   // Hubport/4 (Placeholder, not used by software)
+#define        ION_DEVICE_ID_EDGEPORT_8RR              0x008   // Edgeport with RJ45 with Data and RTS/CTS only
 //     ION_DEVICE_ID_EDGEPORT_8_HANDBUILT      0x009   // Hand-built Edgeport/8 (Placeholder, used in middle digit of serial number only!)
 //     ION_DEVICE_ID_MULTIMODEM_4X56           0x00A   // MultiTech version of RP/4 (Placeholder, used in middle digit of serial number only!)
 #define        ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT    0x00B   // Edgeport/(4)21 Parallel port (USS720)
 #define ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU     0x012   // Half of an Edgeport/16 (the kind with 2 EP/8s)
 #define ION_DEVICE_ID_EDGEPORT_COMPATIBLE      0x013   // Edgeport Compatible, for NCR, Axiohm etc. testing
 #define ION_DEVICE_ID_EDGEPORT_8I              0x014   // Edgeport/8 RS422 (single-CPU)
+#define ION_DEVICE_ID_EDGEPORT_1               0x015   // Edgeport/1 RS232
+#define ION_DEVICE_ID_EPOS44                   0x016   // Half of an EPOS/44 (TIUMP BASED)
+#define ION_DEVICE_ID_EDGEPORT_42              0x017   // Edgeport/42
+#define ION_DEVICE_ID_EDGEPORT_412_8           0x018   // Edgeport/412 8 port part
+#define ION_DEVICE_ID_EDGEPORT_412_4           0x019   // Edgeport/412 4 port part
+#define ION_DEVICE_ID_EDGEPORT_22I             0x01A   // Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232
+
+// Compact Form factor TI based devices  2c, 21c, 22c, 221c
+#define ION_DEVICE_ID_EDGEPORT_2C              0x01B   // Edgeport/2c is a TI based Edgeport/2 - Small I2c
+#define ION_DEVICE_ID_EDGEPORT_221C            0x01C   // Edgeport/221c is a TI based Edgeport/2 with lucent chip and
+                                                       // 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_EDGEPORT_22C             0x01D   // Edgeport/22c is a TI based Edgeport/2 with
+                                                       // 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_EDGEPORT_21C             0x01E   // Edgeport/21c is a TI based Edgeport/2 with lucent chip
+                                                       // Small I2C
+
+
+/*
+ *  DANGER DANGER The 0x20 bit was used to indicate a 8251/netchip GEN 2 device.
+ *  Since the MAC, Linux, and Optimal drivers still used the old code
+ *  I suggest that you skip the 0x20 bit when creating new PIDs
+ */
+
+
+// Generation 3 devices -- 3410 based edgport/1 (256 byte I2C)
+#define ION_DEVICE_ID_TI3410_EDGEPORT_1                0x040   // Edgeport/1 RS232
+#define ION_DEVICE_ID_TI3410_EDGEPORT_1I       0x041   // Edgeport/1i- RS422 model
+
+// Ti based software switchable RS232/RS422/RS485 devices
+#define ION_DEVICE_ID_EDGEPORT_4S              0x042   // Edgeport/4s - software switchable model
+#define ION_DEVICE_ID_EDGEPORT_8S              0x043   // Edgeport/8s - software switchable model
+
+// Usb to Ethernet dongle
+#define ION_DEVICE_ID_EDGEPORT_E               0x0E0   // Edgeport/E Usb to Ethernet
+
+// Edgeport TI based devices
+#define ION_DEVICE_ID_TI_EDGEPORT_4            0x0201  // Edgeport/4 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_2            0x0205  // Edgeport/2 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_4I           0x0206  // Edgeport/4i RS422
+#define ION_DEVICE_ID_TI_EDGEPORT_2I           0x0207  // Edgeport/2i RS422/RS485
+#define ION_DEVICE_ID_TI_EDGEPORT_421          0x020C  // Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port)
+#define ION_DEVICE_ID_TI_EDGEPORT_21           0x020D  // Edgeport/21 2 RS232 + Parallel (lucent on a different hub port)
+#define ION_DEVICE_ID_TI_EDGEPORT_8            0x020F  // Edgeport/8 (single-CPU)
+#define ION_DEVICE_ID_TI_EDGEPORT_1            0x0215  // Edgeport/1 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_42           0x0217  // Edgeport/42 4 hub 2 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_22I                  0x021A  // Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_2C           0x021B  // Edgeport/2c RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_221C         0x021C  // Edgeport/221c is a TI based Edgeport/2 with lucent chip and
+                                                       // 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_TI_EDGEPORT_22C          0x021D  // Edgeport/22c is a TI based Edgeport/2 with
+                                                       // 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_TI_EDGEPORT_21C          0x021E  // Edgeport/21c is a TI based Edgeport/2 with lucent chip
+
+// Generation 3 devices -- 3410 based edgport/1 (256 byte I2C) 
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1     0x240   // Edgeport/1 RS232
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I    0x241   // Edgeport/1i- RS422 model
+
+// Ti based software switchable RS232/RS422/RS485 devices
+#define ION_DEVICE_ID_TI_EDGEPORT_4S           0x242   // Edgeport/4s - software switchable model
+#define ION_DEVICE_ID_IT_EDGEPORT_8S           0x243   // Edgeport/8s - software switchable model
+
+
+/************************************************************************
+ *
+ *                        Generation 4 devices
+ *
+ ************************************************************************/
+
+// Watchport based on 3410 both 1-wire and binary products (16K I2C)
+#define ION_DEVICE_ID_WP_UNSERIALIZED          0x300   // Watchport based on 3410 both 1-wire and binary products
+#define ION_DEVICE_ID_WP_PROXIMITY             0x301   // Watchport/P Discontinued
+#define ION_DEVICE_ID_WP_MOTION                        0x302   // Watchport/M
+#define ION_DEVICE_ID_WP_MOISTURE              0x303   // Watchport/W
+#define ION_DEVICE_ID_WP_TEMPERATURE           0x304   // Watchport/T
+#define ION_DEVICE_ID_WP_HUMIDITY              0x305   // Watchport/H
+
+#define ION_DEVICE_ID_WP_POWER                 0x306   // Watchport
+#define ION_DEVICE_ID_WP_LIGHT                 0x307   // Watchport
+#define ION_DEVICE_ID_WP_RADIATION             0x308   // Watchport
+#define ION_DEVICE_ID_WP_ACCELERATION          0x309   // Watchport/A
+#define ION_DEVICE_ID_WP_DISTANCE              0x30A   // Watchport/D Discontinued
+#define ION_DEVICE_ID_WP_PROX_DIST             0x30B   // Watchport/D uses distance sensor
+                                                       // Default to /P function
+
+#define ION_DEVICE_ID_PLUS_PWR_HP4CD           0x30C   // 5052 Plus Power HubPort/4CD+ (for Dell)
+#define ION_DEVICE_ID_PLUS_PWR_HP4C            0x30D   // 5052 Plus Power HubPort/4C+ 
+#define ION_DEVICE_ID_PLUS_PWR_PCI             0x30E   // 3410 Plus Power PCI Host Controller 4 port
+
+
+//
+// Definitions for AXIOHM USB product IDs
+//
+#define        USB_VENDOR_ID_AXIOHM                    0x05D9  // Axiohm VID
+
+#define AXIOHM_DEVICE_ID_MASK                  0xffff
+#define AXIOHM_DEVICE_ID_EPIC_A758             0xA758
+#define AXIOHM_DEVICE_ID_EPIC_A794             0xA794
+#define AXIOHM_DEVICE_ID_EPIC_A225             0xA225
+
+
+//
+// Definitions for NCR USB product IDs
+//
+#define        USB_VENDOR_ID_NCR                       0x0404  // NCR VID
+
+#define NCR_DEVICE_ID_MASK                     0xffff
+#define NCR_DEVICE_ID_EPIC_0202                        0x0202
+#define NCR_DEVICE_ID_EPIC_0203                        0x0203
+#define NCR_DEVICE_ID_EPIC_0310                        0x0310
+#define NCR_DEVICE_ID_EPIC_0311                        0x0311
+#define NCR_DEVICE_ID_EPIC_0312                        0x0312
+
+
+//
+// Definitions for SYMBOL USB product IDs
+//
+#define USB_VENDOR_ID_SYMBOL                   0x05E0  // Symbol VID
+#define SYMBOL_DEVICE_ID_MASK                  0xffff
+#define SYMBOL_DEVICE_ID_KEYFOB                        0x0700
+
+
+//
+// Definitions for other product IDs
 #define ION_DEVICE_ID_MT4X56USB                        0x1403  // OEM device
 
-// BlackBox OEM devices
-#define ION_DEVICE_ID_BB_EDGEPORT_4            0x001   // Edgeport/4 RS232
-#define ION_DEVICE_ID_BB_EDGEPORT_4T           0x004   // Edgeport/4 RS232 for Telxon (aka "Fleetport")
-#define ION_DEVICE_ID_BB_EDGEPORT_2            0x005   // Edgeport/2 RS232
-#define ION_DEVICE_ID_BB_EDGEPORT_4I           0x006   // Edgeport/4 RS422
-#define ION_DEVICE_ID_BB_EDGEPORT_2I           0x007   // Edgeport/2 RS422/RS485
-#define        ION_DEVICE_ID_BB_EDGEPORT_421           0x00C   // Edgeport/421 Hub+RS232+Parallel
-#define        ION_DEVICE_ID_BB_EDGEPORT_21            0x00D   // Edgeport/21  RS232+Parallel
-#define ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU   0x00E   // Half of an Edgeport/8 (the kind with 2 EP/4s on 1 PCB)
-#define ION_DEVICE_ID_BB_EDGEPORT_8            0x00F   // Edgeport/8 (single-CPU)
-#define ION_DEVICE_ID_BB_EDGEPORT_2_DIN                0x010   // Edgeport/2 RS232 with Apple DIN connector
-#define ION_DEVICE_ID_BB_EDGEPORT_4_DIN                0x011   // Edgeport/4 RS232 with Apple DIN connector
-#define ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU  0x012   // Half of an Edgeport/16 (the kind with 2 EP/8s)
-#define ION_DEVICE_ID_BB_EDGEPORT_8I           0x014   // Edgeport/8 RS422 (single-CPU)
-
-
-/* Edgeport TI based devices */
-#define ION_DEVICE_ID_TI_EDGEPORT_4            0x0201  /* Edgeport/4 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_2            0x0205  /* Edgeport/2 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_4I           0x0206  /* Edgeport/4i RS422 */
-#define ION_DEVICE_ID_TI_EDGEPORT_2I           0x0207  /* Edgeport/2i RS422/RS485 */
-#define ION_DEVICE_ID_TI_EDGEPORT_421          0x020C  /* Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port) */
-#define ION_DEVICE_ID_TI_EDGEPORT_21           0x020D  /* Edgeport/21 2 RS232 + Parallel (lucent on a different hub port) */
-#define ION_DEVICE_ID_TI_EDGEPORT_1            0x0215  /* Edgeport/1 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_42           0x0217  /* Edgeport/42 4 hub 2 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_22           0x021A  /* Edgeport/22  Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_2C           0x021B  /* Edgeport/2c RS232 */
-
-#define ION_DEVICE_ID_TI_EDGEPORT_421_BOOT     0x0240  /* Edgeport/421 in boot mode */
-#define ION_DEVICE_ID_TI_EDGEPORT_421_DOWN     0x0241  /* Edgeport/421 in download mode first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */
-#define ION_DEVICE_ID_TI_EDGEPORT_21_BOOT      0x0242  /* Edgeport/21 in boot mode */
-#define ION_DEVICE_ID_TI_EDGEPORT_21_DOWN      0x0243  /*Edgeport/42 in download mode: first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */
 
+#define        GENERATION_ID_FROM_USB_PRODUCT_ID( ProductId )                          \
+                       ( (__u16) ((ProductId >> 8) & (ION_GENERATION_MASK)) )
 
 #define        MAKE_USB_PRODUCT_ID( OemId, DeviceId )                                  \
                        ( (__u16) (((OemId) << 10) || (DeviceId)) )
 
 // TxCredits value below which driver won't bother sending (to prevent too many small writes).
 // Send only if above 25%
-#define EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(InitialCredit)   (max(((InitialCredit) / 4), EDGE_FW_BULK_MAX_PACKET_SIZE))
+#define EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(InitialCredit, MaxPacketSize) (max( ((InitialCredit) / 4), (MaxPacketSize) ))
 
 #define        EDGE_FW_BULK_MAX_PACKET_SIZE            64      // Max Packet Size for Bulk In Endpoint (EP1)
 #define EDGE_FW_BULK_READ_BUFFER_SIZE          1024    // Size to use for Bulk reads
 // Definitions of I/O Networks vendor-specific requests
 // for default endpoint
 //
-//     bmRequestType = 00100000        Set vendor-specific, to device
-//     bmRequestType = 10100000        Get vendor-specific, to device
+//     bmRequestType = 01000000        Set vendor-specific, to device
+//     bmRequestType = 11000000        Get vendor-specific, to device
 //
 // These are the definitions for the bRequest field for the
 // above bmRequestTypes.
 #define USB_REQUEST_ION_ENABLE_SUSPEND 9       // Enable/Disable suspend feature
                                                // (wValue != 0: Enable; wValue = 0: Disable)
 
+#define USB_REQUEST_ION_SEND_IOSP      10      // Send an IOSP command to the edgeport over the control pipe   
+#define USB_REQUEST_ION_RECV_IOSP      11      // Receive an IOSP command from the edgeport over the control pipe
+
+
+#define USB_REQUEST_ION_DIS_INT_TIMER  0x80    // Sent to Axiohm to enable/ disable
+                                               // interrupt token timer
+                                               // wValue = 1, enable (default)
+                                               // wValue = 0, disable
 
 //
 // Define parameter values for our vendor-specific commands
 //
 
+//
+// Edgeport Compatiblity Descriptor
+//
+// This descriptor is only returned by Edgeport-compatible devices
+// supporting the EPiC spec. True ION devices do not return this
+// descriptor, but instead return STALL on receipt of the
+// GET_EPIC_DESC command. The driver interprets a STALL to mean that
+// this is a "real" Edgeport.
+//
+
+struct edge_compatibility_bits
+{
+       // This __u32 defines which Vendor-specific commands/functionality
+       // the device supports on the default EP0 pipe.
+
+       __u32   VendEnableSuspend       :  1;   // 0001 Set if device supports ION_ENABLE_SUSPEND
+       __u32   VendUnused              : 31;   // Available for future expansion, must be 0
+
+       // This __u32 defines which IOSP commands are supported over the
+       // bulk pipe EP1.
+
+                                                                                       // xxxx Set if device supports:
+       __u32   IOSPOpen                :  1;   // 0001 OPEN / OPEN_RSP (Currently must be 1)
+       __u32   IOSPClose               :  1;   // 0002 CLOSE
+       __u32   IOSPChase               :  1;   // 0004 CHASE / CHASE_RSP
+       __u32   IOSPSetRxFlow           :  1;   // 0008 SET_RX_FLOW
+       __u32   IOSPSetTxFlow           :  1;   // 0010 SET_TX_FLOW
+       __u32   IOSPSetXChar            :  1;   // 0020 SET_XON_CHAR/SET_XOFF_CHAR
+       __u32   IOSPRxCheck             :  1;   // 0040 RX_CHECK_REQ/RX_CHECK_RSP
+       __u32   IOSPSetClrBreak         :  1;   // 0080 SET_BREAK/CLEAR_BREAK
+       __u32   IOSPWriteMCR            :  1;   // 0100 MCR register writes (set/clr DTR/RTS)
+       __u32   IOSPWriteLCR            :  1;   // 0200 LCR register writes (wordlen/stop/parity)
+       __u32   IOSPSetBaudRate         :  1;   // 0400 setting Baud rate (writes to LCR.80h and DLL/DLM register)
+       __u32   IOSPDisableIntPipe      :  1;   // 0800 Do not use the interrupt pipe for TxCredits or RxButesAvailable
+       __u32   IOSPRxDataAvail         :  1;   // 1000 Return status of RX Fifo (Data available in Fifo)
+       __u32   IOSPTxPurge             :  1;   // 2000 Purge TXBuffer and/or Fifo in Edgeport hardware
+       __u32   IOSPUnused              : 18;   // Available for future expansion, must be 0
+
+       // This __u32 defines which 'general' features are supported
+
+       __u32   TrueEdgeport            :  1;   // 0001 Set if device is a 'real' Edgeport
+                                                                                       // (Used only by driver, NEVER set by an EPiC device)
+       __u32   GenUnused               : 31;   // Available for future expansion, must be 0
+
+};
+
+struct edge_compatibility_descriptor
+{
+       __u8    Length;                         // Descriptor Length (per USB spec)
+       __u8    DescType;                       // Descriptor Type (per USB spec, =DEVICE type)
+       __u8    EpicVer;                        // Version of EPiC spec supported
+                                                                                       // (Currently must be 1)
+       __u8    NumPorts;                       // Number of serial ports supported
+       __u8    iDownloadFile;                  // Index of string containing download code filename
+                                                                                       // 0=no download, FF=download compiled into driver.
+       __u8    Unused[ 3 ];                    // Available for future expansion, must be 0
+                                                                                       // (Currently must be 0).
+       __u8    MajorVersion;                   // Firmware version: xx.
+       __u8    MinorVersion;                   //  yy.
+       __le16  BuildNumber;                    //  zzzz (LE format)
+
+       // The following structure contains __u32s, with each bit
+       // specifying whether the EPiC device supports the given
+       // command or functionality.
+
+       struct edge_compatibility_bits  Supports;
+
+};
 
 // Values for iDownloadFile
 #define        EDGE_DOWNLOAD_FILE_NONE         0       // No download requested
@@ -272,30 +439,30 @@ struct edge_manuf_descriptor {
 
        __u8    NumPorts;                               // F08 Number of ports
        __u8    DescDate[3];                            // F09 MM/DD/YY when descriptor template was compiler,
-                                                       //         so host can track changes to USB-only descriptors.
+                                                       //     so host can track changes to USB-only descriptors.
 
        __u8    SerNumLength;                           // F0C USB string descriptor len
        __u8    SerNumDescType;                         // F0D USB descriptor type (=STRING type)
-       __u16   SerialNumber[MAX_SERIALNUMBER_LEN];     // F0E "01-01-000100" Unicode Serial Number
+       __le16  SerialNumber[MAX_SERIALNUMBER_LEN];     // F0E "01-01-000100" Unicode Serial Number
 
        __u8    AssemblyNumLength;                      // F26 USB string descriptor len
        __u8    AssemblyNumDescType;                    // F27 USB descriptor type (=STRING type)
-       __u16   AssemblyNumber[MAX_ASSEMBLYNUMBER_LEN]; // F28 "350-1000-01-A " assembly number
+       __le16  AssemblyNumber[MAX_ASSEMBLYNUMBER_LEN]; // F28 "350-1000-01-A " assembly number
 
        __u8    OemAssyNumLength;                       // F44 USB string descriptor len
        __u8    OemAssyNumDescType;                     // F45 USB descriptor type (=STRING type)
-       __u16   OemAssyNumber[MAX_ASSEMBLYNUMBER_LEN];  // F46 "xxxxxxxxxxxxxx" OEM assembly number
+       __le16  OemAssyNumber[MAX_ASSEMBLYNUMBER_LEN];  // F46 "xxxxxxxxxxxxxx" OEM assembly number
 
        __u8    ManufDateLength;                        // F62 USB string descriptor len
        __u8    ManufDateDescType;                      // F63 USB descriptor type (=STRING type)
-       __u16   ManufDate[6];                           // F64 "MMDDYY" manufacturing date
+       __le16  ManufDate[6];                           // F64 "MMDDYY" manufacturing date
 
        __u8    Reserved3[0x4D];                        // F70 -- unused, set to 0 --
 
        __u8    UartType;                               // FBD Uart Type
        __u8    IonPid;                                 // FBE Product ID, == LSB of USB DevDesc.PID
-                                                       //     (Note: Edgeport/4s before 11/98 will have
-                                                       //              00 here instead of 01)
+                                                       //      (Note: Edgeport/4s before 11/98 will have
+                                                       //       00 here instead of 01)
        __u8    IonConfig;                              // FBF Config byte for ION manufacturing use
                                                        // FBF end of structure, total len = 3C0h
 
@@ -312,7 +479,7 @@ struct edge_manuf_descriptor {
 // both 00 and 01 values mean '654.
 #define MANUF_UART_EXAR_654_EARLY      0       // Exar 16C654 in Edgeport/4s before 11/98
 #define MANUF_UART_EXAR_654            1       // Exar 16C654
-#define MANUF_UART_EXAR_2852           2       // Exar 16C2852 
+#define MANUF_UART_EXAR_2852           2       // Exar 16C2852
 
 //
 // Note: The CpuRev and BoardRev values do not conform to manufacturing
@@ -334,25 +501,22 @@ struct edge_manuf_descriptor {
 #define MANUF_BOARD_REV_GENERATION_2   0x20    // Second generaiton edgeport
 
 
-
-
 // Values of bottom 5 bits of CpuRev & BoardRev for
 // Implementation 1 (ie, 251+Netchip-based)
 #define        MANUF_CPU_REV_1                 1       // C251TB Rev 1 (Need actual Intel rev here)
 
 #define MANUF_BOARD_REV_A              1       // First rev of 251+Netchip design
 
-
-
 #define        MANUF_SERNUM_LENGTH             sizeof(((struct edge_manuf_descriptor *)0)->SerialNumber)
 #define        MANUF_ASSYNUM_LENGTH            sizeof(((struct edge_manuf_descriptor *)0)->AssemblyNumber)
 #define        MANUF_OEMASSYNUM_LENGTH         sizeof(((struct edge_manuf_descriptor *)0)->OemAssyNumber)
 #define        MANUF_MANUFDATE_LENGTH          sizeof(((struct edge_manuf_descriptor *)0)->ManufDate)
 
-#define        MANUF_ION_CONFIG_MASTER         0x80    // 1=Master mode, 0=Normal
-#define        MANUF_ION_CONFIG_DIAG           0x40    // 1=Run h/w diags, 0=norm
-#define        MANUF_ION_CONFIG_DIAG_NO_LOOP   0x20    // As above but no ext loopback test
-
+#define        MANUF_ION_CONFIG_DIAG_NO_LOOP   0x20    // As below but no ext loopback test
+#define        MANUF_ION_CONFIG_DIAG           0x40    // 930 based device: 1=Run h/w diags, 0=norm
+                                               // TIUMP Device    : 1=IONSERIAL needs to run Final Test
+#define        MANUF_ION_CONFIG_MASTER         0x80    // 930 based device:  1=Master mode, 0=Normal
+                                               // TIUMP Device    :  1=First device on a multi TIUMP Device
 
 //
 // This structure describes parameters for the boot code, and
@@ -368,19 +532,19 @@ struct edge_boot_descriptor {
        __u8            DescVer;                // C2 Desc version/format
        __u8            Reserved1;              // C3 -- unused, set to 0 --
 
-       __u16           BootCodeLength;         // C4 Boot code goes from FF:0000 to FF:(len-1)
+       __le16          BootCodeLength;         // C4 Boot code goes from FF:0000 to FF:(len-1)
                                                //        (LE format)
 
        __u8            MajorVersion;           // C6 Firmware version: xx.
        __u8            MinorVersion;           // C7                   yy.
-       __u16           BuildNumber;            // C8                   zzzz (LE format)
+       __le16          BuildNumber;            // C8                   zzzz (LE format)
        
        __u16           EnumRootDescTable;      // CA Root of ROM-based descriptor table
        __u8            NumDescTypes;           // CC Number of supported descriptor types
 
        __u8            Reserved4;              // CD Fix Compiler Packing
 
-       __u16           Capabilities;           // CE-CF Capabilities flags (LE format)
+       __le16          Capabilities;           // CE-CF Capabilities flags (LE format)
        __u8            Reserved2[0x28];        // D0 -- unused, set to 0 --
        __u8            UConfig0;               // F8 930-defined CPU configuration byte 0
        __u8            UConfig1;               // F9 930-defined CPU configuration byte 1
@@ -398,23 +562,29 @@ struct edge_boot_descriptor {
 #define        BOOT_CAP_RESET_CMD      0x0001  // If set, boot correctly supports ION_RESET_DEVICE
 
 
-
 /************************************************************************
                  T I   U M P   D E F I N I T I O N S
  ***********************************************************************/
 
+// Chip definitions in I2C
+#define UMP5152                        0x52
+#define UMP3410                        0x10
+
+
 //************************************************************************
 //     TI I2C Format Definitions
 //************************************************************************
-#define I2C_DESC_TYPE_INFO_BASIC       1
-#define I2C_DESC_TYPE_FIRMWARE_BASIC   2
-#define I2C_DESC_TYPE_DEVICE           3
-#define I2C_DESC_TYPE_CONFIG           4
-#define I2C_DESC_TYPE_STRING           5
-#define I2C_DESC_TYPE_FIRMWARE_BLANK   0xf2
-
-#define I2C_DESC_TYPE_MAX              5
-// 3410 may define types 6, 7 for other firmware downloads
+#define I2C_DESC_TYPE_INFO_BASIC       0x01
+#define I2C_DESC_TYPE_FIRMWARE_BASIC   0x02
+#define I2C_DESC_TYPE_DEVICE           0x03
+#define I2C_DESC_TYPE_CONFIG           0x04
+#define I2C_DESC_TYPE_STRING           0x05
+#define I2C_DESC_TYPE_FIRMWARE_AUTO    0x07    // for 3410 download
+#define I2C_DESC_TYPE_CONFIG_KLUDGE    0x14    // for 3410
+#define I2C_DESC_TYPE_WATCHPORT_VERSION        0x15    // firmware version number for watchport
+#define I2C_DESC_TYPE_WATCHPORT_CALIBRATION_DATA 0x16  // Watchport Calibration Data
+
+#define I2C_DESC_TYPE_FIRMWARE_BLANK   0xf2
 
 // Special section defined by ION
 #define I2C_DESC_TYPE_ION              0       // Not defined by TI
@@ -428,7 +598,9 @@ struct ti_i2c_desc
        __u8    Data[0];                // Data starts here
 }__attribute__((packed));
 
-struct ti_i2c_firmware_rec 
+// for 5152 devices only (type 2 record)
+// for 3410 the version is stored in the WATCHPORT_FIRMWARE_VERSION descriptor
+struct ti_i2c_firmware_rec
 {
        __u8    Ver_Major;              // Firmware Major version number
        __u8    Ver_Minor;              // Firmware Minor version number
@@ -436,6 +608,14 @@ struct ti_i2c_firmware_rec
 }__attribute__((packed));
 
 
+struct watchport_firmware_version
+{
+// Added 2 bytes for version number
+       __u8    Version_Major;          //  Download Version (for Watchport)
+       __u8    Version_Minor;
+}__attribute__((packed));
+
+
 // Structure of header of download image in fw_down.h
 struct ti_i2c_image_header
 {
@@ -461,6 +641,15 @@ struct ti_basic_descriptor
 } __attribute__((packed));
 
 
+// CPU / Board Rev Definitions
+#define TI_CPU_REV_5052                        2       // 5052 based edgeports
+#define TI_CPU_REV_3410                        3       // 3410 based edgeports
+
+#define TI_BOARD_REV_TI_EP             0       // Basic ti based edgeport
+#define TI_BOARD_REV_COMPACT           1       // Compact board
+#define TI_BOARD_REV_WATCHPORT         2       // Watchport
+
+
 #define TI_GET_CPU_REVISION(x)         (__u8)((((x)>>4)&0x0f))
 #define TI_GET_BOARD_REVISION(x)       (__u8)(((x)&0x0f))
 
@@ -469,20 +658,30 @@ struct ti_basic_descriptor
 
 #define TI_MAX_I2C_SIZE                        ( 16 * 1024 )
 
-/* TI USB 5052 definitions */
+#define TI_MANUF_VERSION_0             0       
+
+// IonConig2 flags
+#define TI_CONFIG2_RS232               0x01
+#define TI_CONFIG2_RS422               0x02
+#define TI_CONFIG2_RS485               0x04
+#define TI_CONFIG2_SWITCHABLE          0x08
+
+#define TI_CONFIG2_WATCHPORT           0x10
+
+
 struct edge_ti_manuf_descriptor
 {
        __u8 IonConfig;         //  Config byte for ION manufacturing use
        __u8 IonConfig2;        //  Expansion
-       __u8 Version;           //  Verqsion
+       __u8 Version;           //  Version
        __u8 CpuRev_BoardRev;   //  CPU revision level (0xF0) and Board Rev Level (0x0F)
        __u8 NumPorts;          //  Number of ports     for this UMP
        __u8 NumVirtualPorts;   //  Number of Virtual ports
        __u8 HubConfig1;        //  Used to configure the Hub
        __u8 HubConfig2;        //  Used to configure the Hub
        __u8 TotalPorts;        //  Total Number of Com Ports for the entire device (All UMPs)
-       __u8 Reserved;
+       __u8 Reserved;          //  Reserved
 }__attribute__((packed));
 
 
-#endif         // if !defined()
+#endif         // if !defined(_USBVEND_H)
index c9343f6..32e3f27 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef _USB_DATAFAB_MDCFE_B_H
 #define _USB_DATAFAB_MDCFE_B_H
 
-extern int datafab_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int datafab_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct datafab_info {
        unsigned long   sectors;        // total sector count
index d4f278c..d764837 100644 (file)
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/cdrom.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "debug.h"
+#include "scsi.h"
+
 
-void usb_stor_show_command(Scsi_Cmnd *srb)
+void usb_stor_show_command(struct scsi_cmnd *srb)
 {
        char *what = NULL;
        int i;
index d5d6b3c..c4f4bcf 100644 (file)
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include "usb.h"
+
+struct scsi_cmnd;
 
 #define USB_STORAGE "usb-storage: "
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
-void usb_stor_show_command(Scsi_Cmnd *srb);
+void usb_stor_show_command(struct scsi_cmnd *srb);
 void usb_stor_show_sense( unsigned char key,
                unsigned char asc, unsigned char ascq );
 #define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x )
index ae135fd..12c15f1 100644 (file)
  */
 
 #include <linux/config.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
@@ -41,7 +45,7 @@
  * Transport for the Microtech DPCM-USB
  *
  */
-int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us)
+int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
   int ret;
 
index e6e5637..81b464c 100644 (file)
@@ -29,6 +29,6 @@
 #ifndef _MICROTECH_DPCM_USB_H
 #define _MICROTECH_DPCM_USB_H
 
-extern int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 #endif
index 4b1ff0a..1dbb630 100644 (file)
  */
 
 #include <linux/config.h>
+#include <linux/hdreg.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "freecom.h"
-#include "linux/hdreg.h"
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
 static void pdump (void *, int);
@@ -55,14 +59,14 @@ struct freecom_cb_wrap {
 struct freecom_xfer_wrap {
        u8    Type;             /* Command type. */
        u8    Timeout;          /* Timeout in seconds. */
-       u32   Count;            /* Number of bytes to transfer. */
+       __le32   Count;         /* Number of bytes to transfer. */
        u8    Pad[58];
 } __attribute__ ((packed));
 
 struct freecom_ide_out {
        u8    Type;             /* Type + IDE register. */
        u8    Pad;
-       u16   Value;            /* Value to write. */
+       __le16   Value;         /* Value to write. */
        u8    Pad2[60];
 };
 
@@ -74,7 +78,7 @@ struct freecom_ide_in {
 struct freecom_status {
        u8    Status;
        u8    Reason;
-       u16   Count;
+       __le16   Count;
        u8    Pad[60];
 };
 
@@ -105,7 +109,7 @@ struct freecom_status {
 #define FCM_STATUS_PACKET_LENGTH       4
 
 static int
-freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
+freecom_readdata (struct scsi_cmnd *srb, struct us_data *us,
                unsigned int ipipe, unsigned int opipe, int count)
 {
        struct freecom_xfer_wrap *fxfr =
@@ -139,7 +143,7 @@ freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
 }
 
 static int
-freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
+freecom_writedata (struct scsi_cmnd *srb, struct us_data *us,
                int unsigned ipipe, unsigned int opipe, int count)
 {
        struct freecom_xfer_wrap *fxfr =
@@ -176,7 +180,7 @@ freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
  * Transport for the Freecom USB/IDE adaptor.
  *
  */
-int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
+int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
        struct freecom_cb_wrap *fcb;
        struct freecom_status  *fst;
@@ -302,7 +306,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
         * move in. */
 
        switch (us->srb->sc_data_direction) {
-       case SCSI_DATA_READ:
+       case DMA_FROM_DEVICE:
                /* catch bogus "read 0 length" case */
                if (!length)
                        break;
@@ -334,7 +338,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
                US_DEBUGP("Transfer happy\n");
                break;
 
-       case SCSI_DATA_WRITE:
+       case DMA_TO_DEVICE:
                /* catch bogus "write 0 length" case */
                if (!length)
                        break;
@@ -364,7 +368,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
                break;
 
 
-       case SCSI_DATA_NONE:
+       case DMA_NONE:
                /* Easy, do nothing. */
                break;
 
index 8c0ada8..1b012d6 100644 (file)
@@ -29,7 +29,7 @@
 #ifndef _FREECOM_USB_H
 #define _FREECOM_USB_H
 
-extern int freecom_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int freecom_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int usb_stor_freecom_reset(struct us_data *us);
 extern int freecom_init (struct us_data *us);
 
index 70ebe1c..0a35f4f 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef _USB_ISD200_H
 #define _USB_ISD200_H
 
-extern void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us);
+extern void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us);
 extern int isd200_Initialization(struct us_data *us);
 
 #endif
index 8147197..19bac9d 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef _USB_JUMPSHOT_H
 #define _USB_JUMPSHOT_H
 
-extern int jumpshot_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct jumpshot_info {
    unsigned long   sectors;     // total sector count
index 1c56f49..99ed4d9 100644 (file)
@@ -45,6 +45,8 @@
  */
 
 #include <linux/highmem.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
@@ -59,7 +61,7 @@
  * Fix-up the return data from an INQUIRY command to show 
  * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us
  */
-static void fix_inquiry_data(Scsi_Cmnd *srb)
+static void fix_inquiry_data(struct scsi_cmnd *srb)
 {
        unsigned char databuf[3];
        unsigned int index, offset;
@@ -91,10 +93,10 @@ static void fix_inquiry_data(Scsi_Cmnd *srb)
  * Fix-up the return data from a READ CAPACITY command. My Feiya reader
  * returns a value that is 1 too large.
  */
-static void fix_read_capacity(Scsi_Cmnd *srb)
+static void fix_read_capacity(struct scsi_cmnd *srb)
 {
        unsigned int index, offset;
-       u32 c;
+       __be32 c;
        unsigned long capacity;
 
        /* verify that it's a READ CAPACITY command */
@@ -120,11 +122,11 @@ static void fix_read_capacity(Scsi_Cmnd *srb)
  * Protocol routines
  ***********************************************************************/
 
-void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_qic157_command(struct scsi_cmnd *srb, struct us_data *us)
 {
        /* Pad the ATAPI command with zeros 
         *
-        * NOTE: This only works because a Scsi_Cmnd struct field contains
+        * NOTE: This only works because a scsi_cmnd struct field contains
         * a unsigned char cmnd[16], so we know we have storage available
         */
        for (; srb->cmd_len<12; srb->cmd_len++)
@@ -141,11 +143,11 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
        }
 }
 
-void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_ATAPI_command(struct scsi_cmnd *srb, struct us_data *us)
 {
        /* Pad the ATAPI command with zeros 
         *
-        * NOTE: This only works because a Scsi_Cmnd struct field contains
+        * NOTE: This only works because a scsi_cmnd struct field contains
         * a unsigned char cmnd[16], so we know we have storage available
         */
 
@@ -166,12 +168,12 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
 }
 
 
-void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us)
 {
        /* fix some commands -- this is a form of mode translation
         * UFI devices only accept 12 byte long commands 
         *
-        * NOTE: This only works because a Scsi_Cmnd struct field contains
+        * NOTE: This only works because a scsi_cmnd struct field contains
         * a unsigned char cmnd[16], so we know we have storage available
         */
 
@@ -213,7 +215,8 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
        }
 }
 
-void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
+                                      struct us_data *us)
 {
        /* send the command to the transport layer */
        usb_stor_invoke_transport(srb, us);
@@ -241,7 +244,7 @@ void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
  * pick up from where this one left off. */
 
 unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
-       unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index,
+       unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
        unsigned int *offset, enum xfer_buf_dir dir)
 {
        unsigned int cnt;
@@ -327,7 +330,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
 /* Store the contents of buffer into srb's transfer buffer and set the
  * SCSI residue. */
 void usb_stor_set_xfer_buf(unsigned char *buffer,
-       unsigned int buflen, Scsi_Cmnd *srb)
+       unsigned int buflen, struct scsi_cmnd *srb)
 {
        unsigned int index = 0, offset = 0;
 
index c1fcb52..7aa460d 100644 (file)
@@ -41,9 +41,8 @@
 #ifndef _PROTOCOL_H_
 #define _PROTOCOL_H_
 
-#include <linux/blkdev.h>
-#include "scsi.h"
-#include "usb.h"
+struct scsi_cmnd;
+struct us_data;
 
 /* Sub Classes */
 
 #define US_SC_DEVICE   0xff            /* Use device's value */
 
 /* Protocol handling routines */
-extern void usb_stor_ATAPI_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_qic157_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_ufi_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_transparent_scsi_command(Scsi_Cmnd*, struct us_data*);
+extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_ufi_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_transparent_scsi_command(struct scsi_cmnd*,
+               struct us_data*);
 
-/* Scsi_Cmnd transfer buffer access utilities */
+/* struct scsi_cmnd transfer buffer access utilities */
 enum xfer_buf_dir      {TO_XFER_BUF, FROM_XFER_BUF};
 
 extern unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
-       unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index,
+       unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
        unsigned int *offset, enum xfer_buf_dir dir);
 
 extern void usb_stor_set_xfer_buf(unsigned char *buffer,
-       unsigned int buflen, Scsi_Cmnd *srb);
+       unsigned int buflen, struct scsi_cmnd *srb);
 #endif
index 6851239..c9d78d6 100644 (file)
@@ -29,7 +29,7 @@
 
 /* Sandisk SDDR-09 stuff */
 
-extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct sddr09_card_info {
        unsigned long   capacity;       /* Size of card in bytes */
index eb96153..10270f4 100644 (file)
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "sddr55.h"
 
-#include <linux/jiffies.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
@@ -74,7 +78,7 @@ static int
 sddr55_bulk_transport(struct us_data *us, int direction,
                      unsigned char *data, unsigned int len) {
        struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
-       unsigned int pipe = (direction == SCSI_DATA_READ) ?
+       unsigned int pipe = (direction == DMA_FROM_DEVICE) ?
                        us->recv_bulk_pipe : us->send_bulk_pipe;
 
        if (!len)
@@ -99,7 +103,7 @@ static int sddr55_status(struct us_data *us)
        command[5] = 0xB0;
        command[7] = 0x80;
        result = sddr55_bulk_transport(us,
-               SCSI_DATA_WRITE, command, 8);
+               DMA_TO_DEVICE, command, 8);
 
        US_DEBUGP("Result for send_command in status %d\n",
                result);
@@ -110,7 +114,7 @@ static int sddr55_status(struct us_data *us)
        }
 
        result = sddr55_bulk_transport(us,
-               SCSI_DATA_READ, status, 4);
+               DMA_FROM_DEVICE, status,        4);
 
        /* expect to get short transfer if no card fitted */
        if (result == USB_STOR_XFER_SHORT || result == USB_STOR_XFER_STALLED) {
@@ -139,7 +143,7 @@ static int sddr55_status(struct us_data *us)
 
        /* now read status */
        result = sddr55_bulk_transport(us,
-               SCSI_DATA_READ, status, 2);
+               DMA_FROM_DEVICE, status,        2);
 
        if (result != USB_STOR_XFER_GOOD) {
                set_sense_info (4, 0, 0);       /* hardware error */
@@ -215,7 +219,7 @@ static int sddr55_read_data(struct us_data *us,
 
                        /* send command */
                        result = sddr55_bulk_transport(us,
-                               SCSI_DATA_WRITE, command, 8);
+                               DMA_TO_DEVICE, command, 8);
 
                        US_DEBUGP("Result for send_command in read_data %d\n",
                                result);
@@ -227,7 +231,7 @@ static int sddr55_read_data(struct us_data *us,
 
                        /* read data */
                        result = sddr55_bulk_transport(us,
-                               SCSI_DATA_READ, buffer, len);
+                               DMA_FROM_DEVICE, buffer, len);
 
                        if (result != USB_STOR_XFER_GOOD) {
                                result = USB_STOR_TRANSPORT_ERROR;
@@ -236,7 +240,7 @@ static int sddr55_read_data(struct us_data *us,
 
                        /* now read status */
                        result = sddr55_bulk_transport(us,
-                               SCSI_DATA_READ, status, 2);
+                               DMA_FROM_DEVICE, status, 2);
 
                        if (result != USB_STOR_XFER_GOOD) {
                                result = USB_STOR_TRANSPORT_ERROR;
@@ -390,7 +394,7 @@ static int sddr55_write_data(struct us_data *us,
 
                /* send command */
                result = sddr55_bulk_transport(us,
-                       SCSI_DATA_WRITE, command, 8);
+                       DMA_TO_DEVICE, command, 8);
 
                if (result != USB_STOR_XFER_GOOD) {
                        US_DEBUGP("Result for send_command in write_data %d\n",
@@ -404,7 +408,7 @@ static int sddr55_write_data(struct us_data *us,
 
                /* send the data */
                result = sddr55_bulk_transport(us,
-                       SCSI_DATA_WRITE, buffer, len);
+                       DMA_TO_DEVICE, buffer, len);
 
                if (result != USB_STOR_XFER_GOOD) {
                        US_DEBUGP("Result for send_data in write_data %d\n",
@@ -417,7 +421,7 @@ static int sddr55_write_data(struct us_data *us,
                }
 
                /* now read status */
-               result = sddr55_bulk_transport(us, SCSI_DATA_READ, status, 6);
+               result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6);
 
                if (result != USB_STOR_XFER_GOOD) {
                        US_DEBUGP("Result for get_status in write_data %d\n",
@@ -483,7 +487,7 @@ static int sddr55_read_deviceID(struct us_data *us,
        memset(command, 0, 8);
        command[5] = 0xB0;
        command[7] = 0x84;
-       result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
+       result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8);
 
        US_DEBUGP("Result of send_control for device ID is %d\n",
                result);
@@ -492,7 +496,7 @@ static int sddr55_read_deviceID(struct us_data *us,
                return USB_STOR_TRANSPORT_ERROR;
 
        result = sddr55_bulk_transport(us,
-               SCSI_DATA_READ, content, 4);
+               DMA_FROM_DEVICE, content, 4);
 
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
@@ -502,7 +506,7 @@ static int sddr55_read_deviceID(struct us_data *us,
 
        if (content[0] != 0xff) {
                result = sddr55_bulk_transport(us,
-                       SCSI_DATA_READ, content, 2);
+                       DMA_FROM_DEVICE, content, 2);
        }
 
        return USB_STOR_TRANSPORT_GOOD;
@@ -624,21 +628,21 @@ static int sddr55_read_map(struct us_data *us) {
        command[6] = numblocks * 2 / 256;
        command[7] = 0x8A;
 
-       result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
+       result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8);
 
        if ( result != USB_STOR_XFER_GOOD) {
                kfree (buffer);
                return -1;
        }
 
-       result = sddr55_bulk_transport(us, SCSI_DATA_READ, buffer, numblocks * 2);
+       result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, buffer, numblocks * 2);
 
        if ( result != USB_STOR_XFER_GOOD) {
                kfree (buffer);
                return -1;
        }
 
-       result = sddr55_bulk_transport(us, SCSI_DATA_READ, command, 2);
+       result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, command, 2);
 
        if ( result != USB_STOR_XFER_GOOD) {
                kfree (buffer);
@@ -734,7 +738,7 @@ static void sddr55_card_info_destructor(void *extra) {
 /*
  * Transport for the Sandisk SDDR-55
  */
-int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us)
+int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
        int result;
        static unsigned char inquiry_response[8] = {
@@ -834,8 +838,8 @@ int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us)
                capacity /= PAGESIZE;
                capacity--;
 
-               ((u32 *) ptr)[0] = cpu_to_be32(capacity);
-               ((u32 *) ptr)[1] = cpu_to_be32(PAGESIZE);
+               ((__be32 *) ptr)[0] = cpu_to_be32(capacity);
+               ((__be32 *) ptr)[1] = cpu_to_be32(PAGESIZE);
                usb_stor_set_xfer_buf(ptr, 8, srb);
 
                sddr55_read_map(us);
index 6dc0da6..d6bd32f 100644 (file)
@@ -28,7 +28,7 @@
 
 /* Sandisk SDDR-55 stuff */
 
-extern int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int sddr55_reset(struct us_data *us);
 
 #endif
index 123b041..153efd6 100644 (file)
@@ -44,7 +44,8 @@
 #include <linux/config.h>
 #include <linux/blkdev.h>
 #include "usb.h"
-#include "scsi.h"
+
+struct scsi_cmnd;
 
 /* Protocols */
 
@@ -82,9 +83,9 @@
 
 /* command block wrapper */
 struct bulk_cb_wrap {
-       __u32   Signature;              /* contains 'USBC' */
+       __le32  Signature;              /* contains 'USBC' */
        __u32   Tag;                    /* unique per command id */
-       __u32   DataTransferLength;     /* size of data */
+       __le32  DataTransferLength;     /* size of data */
        __u8    Flags;                  /* direction in bit 0 */
        __u8    Lun;                    /* LUN normally 0 */
        __u8    Length;                 /* of of the CDB */
@@ -98,9 +99,9 @@ struct bulk_cb_wrap {
 
 /* command status wrapper */
 struct bulk_cs_wrap {
-       __u32   Signature;              /* should = 'USBS' */
+       __le32  Signature;              /* should = 'USBS' */
        __u32   Tag;                    /* same as original command */
-       __u32   Residue;                /* amount not transferred */
+       __le32  Residue;                /* amount not transferred */
        __u8    Status;                 /* see below */
        __u8    Filler[18];
 };
@@ -150,16 +151,16 @@ struct bulk_cs_wrap {
 
 #define US_CBI_ADSC            0
 
-extern int usb_stor_CBI_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_CBI_transport(struct scsi_cmnd *, struct us_data*);
 
-extern int usb_stor_CB_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_CB_transport(struct scsi_cmnd *, struct us_data*);
 extern int usb_stor_CB_reset(struct us_data*);
 
-extern int usb_stor_Bulk_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data*);
 extern int usb_stor_Bulk_max_lun(struct us_data*);
 extern int usb_stor_Bulk_reset(struct us_data*);
 
-extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
+extern void usb_stor_invoke_transport(struct scsi_cmnd *, struct us_data*);
 extern void usb_stor_stop_transport(struct us_data*);
 
 extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
index f893cc0..d3a3fd9 100644 (file)
@@ -1,42 +1,15 @@
 /*
- * USB Skeleton driver - 1.1
+ * USB Skeleton driver - 2.0
  *
- * Copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.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, version 2.
  *
- *
- * This driver is to be used as a skeleton driver to be able to create a
- * USB driver quickly.  The design of it is based on the usb-serial and
- * dc2xx drivers.
- *
- * Thanks to Oliver Neukum, David Brownell, and Alan Stern for their help
- * in debugging this driver.
- *
- *
- * History:
- *
- * 2003-05-06 - 1.1 - changes due to usb core changes with usb_register_dev()
- * 2003-02-25 - 1.0 - fix races involving urb->status, unlink_urb(), and
- *                     disconnect.  Fix transfer amount in read().  Use
- *                     macros instead of magic numbers in probe().  Change
- *                     size variables to size_t.  Show how to eliminate
- *                     DMA bounce buffer.
- * 2002_12_12 - 0.9 - compile fixes and got rid of fixed minor array.
- * 2002_09_26 - 0.8 - changes due to USB core conversion to struct device
- *                     driver.
- * 2002_02_12 - 0.7 - zero out dev in probe function for devices that do
- *                     not have both a bulk in and bulk out endpoint.
- *                     Thanks to Holger Waechtler for the fix.
- * 2001_11_05 - 0.6 - fix minor locking problem in skel_disconnect.
- *                     Thanks to Pete Zaitcev for the fix.
- * 2001_09_04 - 0.5 - fix devfs bug in skel_disconnect. Thanks to wim delvaux
- * 2001_08_21 - 0.4 - more small bug fixes.
- * 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel
- * 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people
- * 2001_05_01 - 0.1 - first version
+ * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c 
+ * but has been rewritten to be easy to read and use, as no locks are now
+ * needed anymore.
  *
  */
 
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
+#include <linux/kref.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 
-#ifdef CONFIG_USB_DEBUG
-       static int debug = 1;
-#else
-       static int debug;
-#endif
-
-/* Use our own dbg macro */
-#undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
-
-
-/* Version Information */
-#define DRIVER_VERSION "v1.0"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
-#define DRIVER_DESC "USB Skeleton Driver"
-
-/* Module parameters */
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
 
 /* Define these values to match your devices */
 #define USB_SKEL_VENDOR_ID     0xfff0
@@ -79,11 +31,8 @@ MODULE_PARM_DESC(debug, "Debug enabled or not");
 /* table of devices that work with this driver */
 static struct usb_device_id skel_table [] = {
        { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
-       /* "Gadget Zero" firmware runs under Linux */
-       { USB_DEVICE(0x0525, 0xa4a0) },
        { }                                     /* Terminating entry */
 };
-
 MODULE_DEVICE_TABLE (usb, skel_table);
 
 
@@ -92,413 +41,195 @@ MODULE_DEVICE_TABLE (usb, skel_table);
 
 /* Structure to hold all of our device specific stuff */
 struct usb_skel {
-       struct usb_device *     udev;                   /* save off the usb device pointer */
+       struct usb_device *     udev;                   /* the usb device for this device */
        struct usb_interface *  interface;              /* the interface for this device */
-       unsigned char           minor;                  /* the starting minor number for this device */
-       unsigned char           num_ports;              /* the number of ports this device has */
-       char                    num_interrupt_in;       /* number of interrupt in endpoints we have */
-       char                    num_bulk_in;            /* number of bulk in endpoints we have */
-       char                    num_bulk_out;           /* number of bulk out endpoints we have */
-
        unsigned char *         bulk_in_buffer;         /* the buffer to receive data */
        size_t                  bulk_in_size;           /* the size of the receive buffer */
        __u8                    bulk_in_endpointAddr;   /* the address of the bulk in endpoint */
-
-       unsigned char *         bulk_out_buffer;        /* the buffer to send data */
-       size_t                  bulk_out_size;          /* the size of the send buffer */
-       struct urb *            write_urb;              /* the urb used to send data */
        __u8                    bulk_out_endpointAddr;  /* the address of the bulk out endpoint */
-       atomic_t                write_busy;             /* true iff write urb is busy */
-       struct completion       write_finished;         /* wait for the write to finish */
-
-       int                     open;                   /* if the port is open or not */
-       int                     present;                /* if the device is not disconnected */
-       struct semaphore        sem;                    /* locks this structure */
-};
-
-
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX (disconnect_sem);
-
-/* local function prototypes */
-static ssize_t skel_read       (struct file *file, char *buffer, size_t count, loff_t *ppos);
-static ssize_t skel_write      (struct file *file, const char *buffer, size_t count, loff_t *ppos);
-static int skel_ioctl          (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-static int skel_open           (struct inode *inode, struct file *file);
-static int skel_release                (struct inode *inode, struct file *file);
-
-static int skel_probe          (struct usb_interface *interface, const struct usb_device_id *id);
-static void skel_disconnect    (struct usb_interface *interface);
-
-static void skel_write_bulk_callback   (struct urb *urb, struct pt_regs *regs);
-
-/*
- * File operations needed when we register this driver.
- * This assumes that this driver NEEDS file operations,
- * of course, which means that the driver is expected
- * to have a node in the /dev directory. If the USB
- * device were for a network interface then the driver
- * would use "struct net_driver" instead, and a serial
- * device would use "struct tty_driver".
- */
-static struct file_operations skel_fops = {
-       /*
-        * The owner field is part of the module-locking
-        * mechanism. The idea is that the kernel knows
-        * which module to increment the use-counter of
-        * BEFORE it calls the device's open() function.
-        * This also means that the kernel can decrement
-        * the use-counter again before calling release()
-        * or should the open() function fail.
-        */
-       .owner =        THIS_MODULE,
-
-       .read =         skel_read,
-       .write =        skel_write,
-       .ioctl =        skel_ioctl,
-       .open =         skel_open,
-       .release =      skel_release,
-};
-
-/* 
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
- */
-static struct usb_class_driver skel_class = {
-       .name =         "usb/skel%d",
-       .fops =         &skel_fops,
-       .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
-       .minor_base =   USB_SKEL_MINOR_BASE,
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver skel_driver = {
-       .owner =        THIS_MODULE,
-       .name =         "skeleton",
-       .probe =        skel_probe,
-       .disconnect =   skel_disconnect,
-       .id_table =     skel_table,
+       struct kref             kref;
 };
+#define to_skel_dev(d) container_of(d, struct usb_skel, kref)
 
+static struct usb_driver skel_driver;
 
-/**
- *     usb_skel_debug_data
- */
-static inline void usb_skel_debug_data (const char *function, int size, const unsigned char *data)
-{
-       int i;
+static void skel_delete(struct kref *kref)
+{      
+       struct usb_skel *dev = to_skel_dev(kref);
 
-       if (!debug)
-               return;
-
-       printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
-               function, size);
-       for (i = 0; i < size; ++i) {
-               printk ("%.2x ", data[i]);
-       }
-       printk ("\n");
-}
-
-
-/**
- *     skel_delete
- */
-static inline void skel_delete (struct usb_skel *dev)
-{
+       usb_put_dev(dev->udev);
        kfree (dev->bulk_in_buffer);
-       usb_buffer_free (dev->udev, dev->bulk_out_size,
-                               dev->bulk_out_buffer,
-                               dev->write_urb->transfer_dma);
-       usb_free_urb (dev->write_urb);
        kfree (dev);
 }
 
-
-/**
- *     skel_open
- */
-static int skel_open (struct inode *inode, struct file *file)
+static int skel_open(struct inode *inode, struct file *file)
 {
-       struct usb_skel *dev = NULL;
+       struct usb_skel *dev;
        struct usb_interface *interface;
        int subminor;
        int retval = 0;
 
-       dbg("%s", __FUNCTION__);
-
        subminor = iminor(inode);
 
-       /* prevent disconnects */
-       down (&disconnect_sem);
-
-       interface = usb_find_interface (&skel_driver, subminor);
+       interface = usb_find_interface(&skel_driver, subminor);
        if (!interface) {
                err ("%s - error, can't find device for minor %d",
                     __FUNCTION__, subminor);
                retval = -ENODEV;
-               goto exit_no_device;
+               goto exit;
        }
 
        dev = usb_get_intfdata(interface);
        if (!dev) {
                retval = -ENODEV;
-               goto exit_no_device;
+               goto exit;
        }
 
-       /* lock this device */
-       down (&dev->sem);
-
-       /* increment our usage count for the driver */
-       ++dev->open;
+       /* increment our usage count for the device */
+       kref_get(&dev->kref);
 
        /* save our object in the file's private structure */
        file->private_data = dev;
 
-       /* unlock this device */
-       up (&dev->sem);
-
-exit_no_device:
-       up (&disconnect_sem);
+exit:
        return retval;
 }
 
-
-/**
- *     skel_release
- */
-static int skel_release (struct inode *inode, struct file *file)
+static int skel_release(struct inode *inode, struct file *file)
 {
        struct usb_skel *dev;
-       int retval = 0;
 
        dev = (struct usb_skel *)file->private_data;
-       if (dev == NULL) {
-               dbg ("%s - object is NULL", __FUNCTION__);
+       if (dev == NULL)
                return -ENODEV;
-       }
 
-       dbg("%s - minor %d", __FUNCTION__, dev->minor);
-
-       /* lock our device */
-       down (&dev->sem);
-
-       if (dev->open <= 0) {
-               dbg ("%s - device not opened", __FUNCTION__);
-               retval = -ENODEV;
-               goto exit_not_opened;
-       }
-
-       /* wait for any bulk writes that might be going on to finish up */
-       if (atomic_read (&dev->write_busy))
-               wait_for_completion (&dev->write_finished);
-
-       --dev->open;
-
-       if (!dev->present && !dev->open) {
-               /* the device was unplugged before the file was released */
-               up (&dev->sem);
-               skel_delete (dev);
-               return 0;
-       }
-
-exit_not_opened:
-       up (&dev->sem);
-
-       return retval;
+       /* decrement the count on our device */
+       kref_put(&dev->kref, skel_delete);
+       return 0;
 }
 
-
-/**
- *     skel_read
- */
-static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t *ppos)
+static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
        struct usb_skel *dev;
        int retval = 0;
 
        dev = (struct usb_skel *)file->private_data;
-
-       dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count);
-
-       /* lock this object */
-       down (&dev->sem);
-
-       /* verify that the device wasn't unplugged */
-       if (!dev->present) {
-               up (&dev->sem);
-               return -ENODEV;
-       }
-
+       
        /* do a blocking bulk read to get data from the device */
-       retval = usb_bulk_msg (dev->udev,
-                              usb_rcvbulkpipe (dev->udev,
-                                               dev->bulk_in_endpointAddr),
-                              dev->bulk_in_buffer,
-                              min (dev->bulk_in_size, count),
-                              &count, HZ*10);
+       retval = usb_bulk_msg(dev->udev,
+                             usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
+                             dev->bulk_in_buffer,
+                             min(dev->bulk_in_size, count),
+                             &count, HZ*10);
 
        /* if the read was successful, copy the data to userspace */
        if (!retval) {
-               if (copy_to_user (buffer, dev->bulk_in_buffer, count))
+               if (copy_to_user(buffer, dev->bulk_in_buffer, count))
                        retval = -EFAULT;
                else
                        retval = count;
        }
 
-       /* unlock the device */
-       up (&dev->sem);
        return retval;
 }
 
-
-/**
- *     skel_write
- *
- *     A device driver has to decide how to report I/O errors back to the
- *     user.  The safest course is to wait for the transfer to finish before
- *     returning so that any errors will be reported reliably.  skel_read()
- *     works like this.  But waiting for I/O is slow, so many drivers only
- *     check for errors during I/O initiation and do not report problems
- *     that occur during the actual transfer.  That's what we will do here.
- *
- *     A driver concerned with maximum I/O throughput would use double-
- *     buffering:  Two urbs would be devoted to write transfers, so that
- *     one urb could always be active while the other was waiting for the
- *     user to send more data.
- */
-static ssize_t skel_write (struct file *file, const char *buffer, size_t count, loff_t *ppos)
+static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
 {
        struct usb_skel *dev;
-       ssize_t bytes_written = 0;
-       int retval = 0;
 
-       dev = (struct usb_skel *)file->private_data;
+       dev = (struct usb_skel *)urb->context;
 
-       dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count);
+       /* sync/async unlink faults aren't errors */
+       if (urb->status && 
+           !(urb->status == -ENOENT || 
+             urb->status == -ECONNRESET ||
+             urb->status == -ESHUTDOWN)) {
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, urb->status);
+       }
 
-       /* lock this object */
-       down (&dev->sem);
+       /* free up our allocated buffer */
+       usb_buffer_free(urb->dev, urb->transfer_buffer_length, 
+                       urb->transfer_buffer, urb->transfer_dma);
+}
 
-       /* verify that the device wasn't unplugged */
-       if (!dev->present) {
-               retval = -ENODEV;
-               goto exit;
-       }
+static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
+{
+       struct usb_skel *dev;
+       int retval = 0;
+       struct urb *urb = NULL;
+       char *buf = NULL;
+
+       dev = (struct usb_skel *)file->private_data;
 
        /* verify that we actually have some data to write */
-       if (count == 0) {
-               dbg("%s - write request of 0 bytes", __FUNCTION__);
+       if (count == 0)
                goto exit;
-       }
 
-       /* wait for a previous write to finish up; we don't use a timeout
-        * and so a nonresponsive device can delay us indefinitely.
-        */
-       if (atomic_read (&dev->write_busy))
-               wait_for_completion (&dev->write_finished);
+       /* create a urb, and a buffer for it, and copy the data to the urb */
+       urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!urb) {
+               retval = -ENOMEM;
+               goto error;
+       }
 
-       /* we can only write as much as our buffer will hold */
-       bytes_written = min (dev->bulk_out_size, count);
+       buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
+       if (!buf) {
+               retval = -ENOMEM;
+               goto error;
+       }
 
-       /* copy the data from userspace into our transfer buffer;
-        * this is the only copy required.
-        */
-       if (copy_from_user(dev->write_urb->transfer_buffer, buffer,
-                          bytes_written)) {
+       if (copy_from_user(buf, user_buffer, count)) {
                retval = -EFAULT;
-               goto exit;
+               goto error;
        }
 
-       usb_skel_debug_data (__FUNCTION__, bytes_written,
-                            dev->write_urb->transfer_buffer);
-
-       /* this urb was already set up, except for this write size */
-       dev->write_urb->transfer_buffer_length = bytes_written;
+       /* initialize the urb properly */
+       usb_fill_bulk_urb(urb, dev->udev,
+                         usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
+                         buf, count, skel_write_bulk_callback, dev);
+       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
        /* send the data out the bulk port */
-       /* a character device write uses GFP_KERNEL,
-        unless a spinlock is held */
-       init_completion (&dev->write_finished);
-       atomic_set (&dev->write_busy, 1);
-       retval = usb_submit_urb(dev->write_urb, GFP_KERNEL);
+       retval = usb_submit_urb(urb, GFP_KERNEL);
        if (retval) {
-               atomic_set (&dev->write_busy, 0);
-               err("%s - failed submitting write urb, error %d",
-                   __FUNCTION__, retval);
-       } else {
-               retval = bytes_written;
+               err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
+               goto error;
        }
 
+       /* release our reference to this urb, the USB core will eventually free it entirely */
+       usb_free_urb(urb);
+
 exit:
-       /* unlock the device */
-       up (&dev->sem);
+       return count;
 
+error:
+       usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
+       usb_free_urb(urb);
        return retval;
 }
 
+static struct file_operations skel_fops = {
+       .owner =        THIS_MODULE,
+       .read =         skel_read,
+       .write =        skel_write,
+       .open =         skel_open,
+       .release =      skel_release,
+};
 
-/**
- *     skel_ioctl
- */
-static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct usb_skel *dev;
-
-       dev = (struct usb_skel *)file->private_data;
-
-       /* lock this object */
-       down (&dev->sem);
-
-       /* verify that the device wasn't unplugged */
-       if (!dev->present) {
-               up (&dev->sem);
-               return -ENODEV;
-       }
-
-       dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __FUNCTION__,
-           dev->minor, cmd, arg);
-
-       /* fill in your device specific stuff here */
-
-       /* unlock the device */
-       up (&dev->sem);
-
-       /* return that we did not understand this ioctl call */
-       return -ENOTTY;
-}
-
-
-/**
- *     skel_write_bulk_callback
+/* 
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
  */
-static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{
-       struct usb_skel *dev = (struct usb_skel *)urb->context;
-
-       dbg("%s - minor %d", __FUNCTION__, dev->minor);
-
-       /* sync/async unlink faults aren't errors */
-       if (urb->status && !(urb->status == -ENOENT ||
-                               urb->status == -ECONNRESET)) {
-               dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, urb->status);
-       }
-
-       /* notify anyone waiting that the write has finished */
-       atomic_set (&dev->write_busy, 0);
-       complete (&dev->write_finished);
-}
-
+static struct usb_class_driver skel_class = {
+       .name =         "usb/skel%d",
+       .fops =         &skel_fops,
+       .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+       .minor_base =   USB_SKEL_MINOR_BASE,
+};
 
-/**
- *     skel_probe
- *
- *     Called by the usb core when a new device is connected that it thinks
- *     this driver might be interested in.
- */
 static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
-       struct usb_device *udev = interface_to_usbdev(interface);
        struct usb_skel *dev = NULL;
        struct usb_host_interface *iface_desc;
        struct usb_endpoint_descriptor *endpoint;
@@ -506,28 +237,21 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
        int i;
        int retval = -ENOMEM;
 
-       /* See if the device offered us matches what we can accept */
-       if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) ||
-           (udev->descriptor.idProduct != USB_SKEL_PRODUCT_ID)) {
-               return -ENODEV;
-       }
-
        /* allocate memory for our device state and initialize it */
-       dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL);
+       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
        if (dev == NULL) {
-               err ("Out of memory");
-               return -ENOMEM;
+               err("Out of memory");
+               goto error;
        }
-       memset (dev, 0x00, sizeof (*dev));
+       memset(dev, 0x00, sizeof(*dev));
+       kref_init(&dev->kref);
 
-       init_MUTEX (&dev->sem);
-       dev->udev = udev;
+       dev->udev = usb_get_dev(interface_to_usbdev(interface));
        dev->interface = interface;
 
        /* set up the endpoint information */
-       /* check out the endpoints */
        /* use only the first bulk-in and bulk-out endpoints */
-       iface_desc = &interface->altsetting[0];
+       iface_desc = interface->cur_altsetting;
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;
 
@@ -539,9 +263,9 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
                        buffer_size = endpoint->wMaxPacketSize;
                        dev->bulk_in_size = buffer_size;
                        dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
-                       dev->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+                       dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
                        if (!dev->bulk_in_buffer) {
-                               err("Couldn't allocate bulk_in_buffer");
+                               err("Could not allocate bulk_in_buffer");
                                goto error;
                        }
                }
@@ -551,153 +275,85 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
                    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
                                        == USB_ENDPOINT_XFER_BULK)) {
                        /* we found a bulk out endpoint */
-                       /* a probe() may sleep and has no restrictions on memory allocations */
-                       dev->write_urb = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!dev->write_urb) {
-                               err("No free urbs available");
-                               goto error;
-                       }
                        dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
-
-                       /* on some platforms using this kind of buffer alloc
-                        * call eliminates a dma "bounce buffer".
-                        *
-                        * NOTE: you'd normally want i/o buffers that hold
-                        * more than one packet, so that i/o delays between
-                        * packets don't hurt throughput.
-                        */
-                       buffer_size = endpoint->wMaxPacketSize;
-                       dev->bulk_out_size = buffer_size;
-                       dev->write_urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP |
-                                       URB_ASYNC_UNLINK);
-                       dev->bulk_out_buffer = usb_buffer_alloc (udev,
-                                       buffer_size, GFP_KERNEL,
-                                       &dev->write_urb->transfer_dma);
-                       if (!dev->bulk_out_buffer) {
-                               err("Couldn't allocate bulk_out_buffer");
-                               goto error;
-                       }
-                       usb_fill_bulk_urb(dev->write_urb, udev,
-                                     usb_sndbulkpipe(udev,
-                                                     endpoint->bEndpointAddress),
-                                     dev->bulk_out_buffer, buffer_size,
-                                     skel_write_bulk_callback, dev);
                }
        }
        if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
-               err("Couldn't find both bulk-in and bulk-out endpoints");
+               err("Could not find both bulk-in and bulk-out endpoints");
                goto error;
        }
 
-       /* allow device read, write and ioctl */
-       dev->present = 1;
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, dev);
 
        /* we can register the device now, as it is ready */
-       usb_set_intfdata (interface, dev);
-       retval = usb_register_dev (interface, &skel_class);
+       retval = usb_register_dev(interface, &skel_class);
        if (retval) {
                /* something prevented us from registering this driver */
-               err ("Not able to get a minor for this device.");
-               usb_set_intfdata (interface, NULL);
+               err("Not able to get a minor for this device.");
+               usb_set_intfdata(interface, NULL);
                goto error;
        }
 
-       dev->minor = interface->minor;
-
        /* let the user know what node this device is now attached to */
-       info ("USB Skeleton device now attached to USBSkel-%d", dev->minor);
+       info("USB Skeleton device now attached to USBSkel-%d", interface->minor);
        return 0;
 
 error:
-       skel_delete (dev);
+       if (dev)
+               kref_put(&dev->kref, skel_delete);
        return retval;
 }
 
-
-/**
- *     skel_disconnect
- *
- *     Called by the usb core when the device is removed from the system.
- *
- *     This routine guarantees that the driver will not submit any more urbs
- *     by clearing dev->udev.  It is also supposed to terminate any currently
- *     active urbs.  Unfortunately, usb_bulk_msg(), used in skel_read(), does
- *     not provide any way to do this.  But at least we can cancel an active
- *     write.
- */
 static void skel_disconnect(struct usb_interface *interface)
 {
        struct usb_skel *dev;
-       int minor;
+       int minor = interface->minor;
 
-       /* prevent races with open() */
-       down (&disconnect_sem);
+       /* prevent skel_open() from racing skel_disconnect() */
+       lock_kernel();
 
-       dev = usb_get_intfdata (interface);
-       usb_set_intfdata (interface, NULL);
-
-       down (&dev->sem);
-
-       minor = dev->minor;
+       dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
 
        /* give back our minor */
-       usb_deregister_dev (interface, &skel_class);
+       usb_deregister_dev(interface, &skel_class);
 
-       /* terminate an ongoing write */
-       if (atomic_read (&dev->write_busy)) {
-               usb_unlink_urb (dev->write_urb);
-               wait_for_completion (&dev->write_finished);
-       }
-
-       /* prevent device read, write and ioctl */
-       dev->present = 0;
-
-       up (&dev->sem);
+       unlock_kernel();
 
-       /* if the device is opened, skel_release will clean this up */
-       if (!dev->open)
-               skel_delete (dev);
-
-       up (&disconnect_sem);
+       /* decrement our usage count */
+       kref_put(&dev->kref, skel_delete);
 
        info("USB Skeleton #%d now disconnected", minor);
 }
 
+static struct usb_driver skel_driver = {
+       .owner =        THIS_MODULE,
+       .name =         "skeleton",
+       .probe =        skel_probe,
+       .disconnect =   skel_disconnect,
+       .id_table =     skel_table,
+};
 
-
-/**
- *     usb_skel_init
- */
 static int __init usb_skel_init(void)
 {
        int result;
 
        /* register this driver with the USB subsystem */
        result = usb_register(&skel_driver);
-       if (result) {
-               err("usb_register failed. Error number %d",
-                   result);
-               return result;
-       }
+       if (result)
+               err("usb_register failed. Error number %d", result);
 
-       info(DRIVER_DESC " " DRIVER_VERSION);
-       return 0;
+       return result;
 }
 
-
-/**
- *     usb_skel_exit
- */
 static void __exit usb_skel_exit(void)
 {
        /* deregister this driver with the USB subsystem */
        usb_deregister(&skel_driver);
 }
 
-
 module_init (usb_skel_init);
 module_exit (usb_skel_exit);
 
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
new file mode 100644 (file)
index 0000000..d6af37b
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ *  linux/drivers/video/amba-clcd.c
+ *
+ * Copyright (C) 2001 ARM Limited, by David A Rusling
+ * Updated to 2.5, Deep Blue Solutions 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.
+ *
+ *  ARM PrimeCell PL110 Color LCD Controller
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/list.h>
+
+#include <asm/hardware/amba.h>
+#include <asm/hardware/clock.h>
+
+#include <asm/hardware/amba_clcd.h>
+
+#define to_clcd(info)  container_of(info, struct clcd_fb, fb)
+
+/* This is limited to 16 characters when displayed by X startup */
+static const char *clcd_name = "CLCD FB";
+
+/*
+ * Unfortunately, the enable/disable functions may be called either from
+ * process or IRQ context, and we _need_ to delay.  This is _not_ good.
+ */
+static inline void clcdfb_sleep(unsigned int ms)
+{
+       if (in_atomic()) {
+               mdelay(ms);
+       } else {
+               msleep(ms);
+       }
+}
+
+static inline void clcdfb_set_start(struct clcd_fb *fb)
+{
+       unsigned long ustart = fb->fb.fix.smem_start;
+       unsigned long lstart;
+
+       ustart += fb->fb.var.yoffset * fb->fb.fix.line_length;
+       lstart = ustart + fb->fb.var.yres * fb->fb.fix.line_length / 2;
+
+       writel(ustart, fb->regs + CLCD_UBAS);
+       writel(lstart, fb->regs + CLCD_LBAS);
+}
+
+static void clcdfb_disable(struct clcd_fb *fb)
+{
+       u32 val;
+
+       if (fb->board->disable)
+               fb->board->disable(fb);
+
+       val = readl(fb->regs + CLCD_CNTL);
+       if (val & CNTL_LCDPWR) {
+               val &= ~CNTL_LCDPWR;
+               writel(val, fb->regs + CLCD_CNTL);
+
+               clcdfb_sleep(20);
+       }
+       if (val & CNTL_LCDEN) {
+               val &= ~CNTL_LCDEN;
+               writel(val, fb->regs + CLCD_CNTL);
+       }
+
+       /*
+        * Disable CLCD clock source.
+        */
+       clk_disable(fb->clk);
+}
+
+static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
+{
+       /*
+        * Enable the CLCD clock source.
+        */
+       clk_enable(fb->clk);
+
+       /*
+        * Bring up by first enabling..
+        */
+       cntl |= CNTL_LCDEN;
+       writel(cntl, fb->regs + CLCD_CNTL);
+
+       clcdfb_sleep(20);
+
+       /*
+        * and now apply power.
+        */
+       cntl |= CNTL_LCDPWR;
+       writel(cntl, fb->regs + CLCD_CNTL);
+
+       /*
+        * finally, enable the interface.
+        */
+       if (fb->board->enable)
+               fb->board->enable(fb);
+}
+
+static int
+clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+       int ret = 0;
+
+       memset(&var->transp, 0, sizeof(var->transp));
+       memset(&var->red, 0, sizeof(var->red));
+       memset(&var->green, 0, sizeof(var->green));
+       memset(&var->blue, 0, sizeof(var->blue));
+
+       switch (var->bits_per_pixel) {
+       case 1:
+       case 2:
+       case 4:
+       case 8:
+               var->red.length         = 8;
+               var->red.offset         = 0;
+               var->green.length       = 8;
+               var->green.offset       = 0;
+               var->blue.length        = 8;
+               var->blue.offset        = 0;
+               break;
+       case 16:
+               var->red.length         = 5;
+               var->green.length       = 5;
+               var->blue.length        = 5;
+               if (fb->panel->cntl & CNTL_BGR) {
+                       var->red.offset         = 10;
+                       var->green.offset       = 5;
+                       var->blue.offset        = 0;
+               } else {
+                       var->red.offset         = 0;
+                       var->green.offset       = 5;
+                       var->blue.offset        = 10;
+               }
+               break;
+       case 24:
+               if (fb->panel->cntl & CNTL_LCDTFT) {
+                       var->red.length         = 8;
+                       var->green.length       = 8;
+                       var->blue.length        = 8;
+
+                       if (fb->panel->cntl & CNTL_BGR) {
+                               var->red.offset         = 16;
+                               var->green.offset       = 8;
+                               var->blue.offset        = 0;
+                       } else {
+                               var->red.offset         = 0;
+                               var->green.offset       = 8;
+                               var->blue.offset        = 16;
+                       }
+                       break;
+               }
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int clcdfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       struct clcd_fb *fb = to_clcd(info);
+       int ret = -EINVAL;
+
+       if (fb->board->check)
+               ret = fb->board->check(fb, var);
+       if (ret == 0)
+               ret = clcdfb_set_bitfields(fb, var);
+
+       return ret;
+}
+
+static int clcdfb_set_par(struct fb_info *info)
+{
+       struct clcd_fb *fb = to_clcd(info);
+       struct clcd_regs regs;
+
+       fb->fb.fix.line_length = fb->fb.var.xres_virtual *
+                                fb->fb.var.bits_per_pixel / 8;
+
+       if (fb->fb.var.bits_per_pixel <= 8)
+               fb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+       else
+               fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+
+       fb->board->decode(fb, &regs);
+
+       clcdfb_disable(fb);
+
+       writel(regs.tim0, fb->regs + CLCD_TIM0);
+       writel(regs.tim1, fb->regs + CLCD_TIM1);
+       writel(regs.tim2, fb->regs + CLCD_TIM2);
+       writel(regs.tim3, fb->regs + CLCD_TIM3);
+
+       clcdfb_set_start(fb);
+
+       clk_set_rate(fb->clk, (1000000000 / regs.pixclock) * 1000);
+
+       fb->clcd_cntl = regs.cntl;
+
+       clcdfb_enable(fb, regs.cntl);
+
+#ifdef DEBUG
+       printk(KERN_INFO "CLCD: Registers set to\n"
+              KERN_INFO "  %08x %08x %08x %08x\n"
+              KERN_INFO "  %08x %08x %08x %08x\n",
+               readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1),
+               readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3),
+               readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS),
+               readl(fb->regs + CLCD_IENB), readl(fb->regs + CLCD_CNTL));
+#endif
+
+       return 0;
+}
+
+static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)
+{
+       unsigned int mask = (1 << bf->length) - 1;
+
+       return (val >> (16 - bf->length) & mask) << bf->offset;
+}
+
+/*
+ *  Set a single color register. The values supplied have a 16 bit
+ *  magnitude.  Return != 0 for invalid regno.
+ */
+static int
+clcdfb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
+                unsigned int blue, unsigned int transp, struct fb_info *info)
+{
+       struct clcd_fb *fb = to_clcd(info);
+
+       if (regno < 16)
+               fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
+                                 convert_bitfield(blue, &fb->fb.var.blue) |
+                                 convert_bitfield(green, &fb->fb.var.green) |
+                                 convert_bitfield(red, &fb->fb.var.red);
+
+       if (fb->fb.var.bits_per_pixel == 8 && regno < 256) {
+               int hw_reg = CLCD_PALETTE + ((regno * 2) & ~3);
+               u32 val, mask, newval;
+
+               newval  = (red >> 11)  & 0x001f;
+               newval |= (green >> 6) & 0x03e0;
+               newval |= (blue >> 1)  & 0x7c00;
+
+               /*
+                * 3.2.11: if we're configured for big endian
+                * byte order, the palette entries are swapped.
+                */
+               if (fb->clcd_cntl & CNTL_BEBO)
+                       regno ^= 1;
+
+               if (regno & 1) {
+                       newval <<= 16;
+                       mask = 0x0000ffff;
+               } else {
+                       mask = 0xffff0000;
+               }
+
+               val = readl(fb->regs + hw_reg) & mask;
+               writel(val | newval, fb->regs + hw_reg);
+       }
+
+       return regno > 255;
+}
+
+/*
+ *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
+ *  then the caller blanks by setting the CLUT (Color Look Up Table) 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
+ *    blank_mode == 3: suspend hsync
+ *    blank_mode == 4: powerdown
+ */
+static int clcdfb_blank(int blank_mode, struct fb_info *info)
+{
+       struct clcd_fb *fb = to_clcd(info);
+
+       if (blank_mode != 0) {
+               clcdfb_disable(fb);
+       } else {
+               clcdfb_enable(fb, fb->clcd_cntl);
+       }
+       return 0;
+}
+
+static struct fb_ops clcdfb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_check_var   = clcdfb_check_var,
+       .fb_set_par     = clcdfb_set_par,
+       .fb_setcolreg   = clcdfb_setcolreg,
+       .fb_blank       = clcdfb_blank,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+       .fb_cursor      = soft_cursor,
+};
+
+static int clcdfb_register(struct clcd_fb *fb)
+{
+       int ret;
+
+       fb->clk = clk_get(&fb->dev->dev, "CLCDCLK");
+       if (IS_ERR(fb->clk)) {
+               ret = PTR_ERR(fb->clk);
+               goto out;
+       }
+
+       ret = clk_use(fb->clk);
+       if (ret)
+               goto free_clk;
+
+       fb->fb.fix.mmio_start   = fb->dev->res.start;
+       fb->fb.fix.mmio_len     = SZ_4K;
+
+       fb->regs = ioremap(fb->fb.fix.mmio_start, fb->fb.fix.mmio_len);
+       if (!fb->regs) {
+               printk(KERN_ERR "CLCD: unable to remap registers\n");
+               ret = -ENOMEM;
+               goto unuse_clk;
+       }
+
+       fb->fb.fbops            = &clcdfb_ops;
+       fb->fb.flags            = FBINFO_FLAG_DEFAULT;
+       fb->fb.pseudo_palette   = fb->cmap;
+
+       strncpy(fb->fb.fix.id, clcd_name, sizeof(fb->fb.fix.id));
+       fb->fb.fix.type         = FB_TYPE_PACKED_PIXELS;
+       fb->fb.fix.type_aux     = 0;
+       fb->fb.fix.xpanstep     = 0;
+       fb->fb.fix.ypanstep     = 0;
+       fb->fb.fix.ywrapstep    = 0;
+       fb->fb.fix.accel        = FB_ACCEL_NONE;
+
+       fb->fb.var.xres         = fb->panel->mode.xres;
+       fb->fb.var.yres         = fb->panel->mode.yres;
+       fb->fb.var.xres_virtual = fb->panel->mode.xres;
+       fb->fb.var.yres_virtual = fb->panel->mode.yres;
+       fb->fb.var.bits_per_pixel = fb->panel->bpp;
+       fb->fb.var.grayscale    = fb->panel->grayscale;
+       fb->fb.var.pixclock     = fb->panel->mode.pixclock;
+       fb->fb.var.left_margin  = fb->panel->mode.left_margin;
+       fb->fb.var.right_margin = fb->panel->mode.right_margin;
+       fb->fb.var.upper_margin = fb->panel->mode.upper_margin;
+       fb->fb.var.lower_margin = fb->panel->mode.lower_margin;
+       fb->fb.var.hsync_len    = fb->panel->mode.hsync_len;
+       fb->fb.var.vsync_len    = fb->panel->mode.vsync_len;
+       fb->fb.var.sync         = fb->panel->mode.sync;
+       fb->fb.var.vmode        = fb->panel->mode.vmode;
+       fb->fb.var.activate     = FB_ACTIVATE_NOW;
+       fb->fb.var.nonstd       = 0;
+       fb->fb.var.height       = fb->panel->height;
+       fb->fb.var.width        = fb->panel->width;
+       fb->fb.var.accel_flags  = 0;
+
+       fb->fb.monspecs.hfmin   = 0;
+       fb->fb.monspecs.hfmax   = 100000;
+       fb->fb.monspecs.vfmin   = 0;
+       fb->fb.monspecs.vfmax   = 400;
+       fb->fb.monspecs.dclkmin = 1000000;
+       fb->fb.monspecs.dclkmax = 100000000;
+
+       /*
+        * Make sure that the bitfields are set appropriately.
+        */
+       clcdfb_set_bitfields(fb, &fb->fb.var);
+
+       /*
+        * Allocate colourmap.
+        */
+       fb_alloc_cmap(&fb->fb.cmap, 256, 0);
+
+       /*
+        * Ensure interrupts are disabled.
+        */
+       writel(0, fb->regs + CLCD_IENB);
+
+       fb_set_var(&fb->fb, &fb->fb.var);
+
+        printk(KERN_INFO "CLCD: %s hardware, %s display\n",
+               fb->board->name, fb->panel->mode.name);
+
+       ret = register_framebuffer(&fb->fb);
+       if (ret == 0)
+               goto out;
+
+       printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret);
+
+       iounmap(fb->regs);
+ unuse_clk:
+       clk_unuse(fb->clk);
+ free_clk:
+       clk_put(fb->clk);
+ out:
+       return ret;
+}
+
+static int clcdfb_probe(struct amba_device *dev, void *id)
+{
+       struct clcd_board *board = dev->dev.platform_data;
+       struct clcd_fb *fb;
+       int ret;
+
+       if (!board)
+               return -EINVAL;
+
+       ret = amba_request_regions(dev, NULL);
+       if (ret) {
+               printk(KERN_ERR "CLCD: unable to reserve regs region\n");
+               goto out;
+       }
+
+       fb = (struct clcd_fb *) kmalloc(sizeof(struct clcd_fb), GFP_KERNEL);
+       if (!fb) {
+               printk(KERN_INFO "CLCD: could not allocate new clcd_fb struct\n");
+               ret = -ENOMEM;
+               goto free_region;
+       }
+       memset(fb, 0, sizeof(struct clcd_fb));
+
+       fb->dev = dev;
+       fb->board = board;
+
+       ret = fb->board->setup(fb);
+       if (ret)
+               goto free_fb;
+
+       ret = clcdfb_register(fb); 
+       if (ret == 0) {
+               amba_set_drvdata(dev, fb);
+               goto out;
+       }
+
+       fb->board->remove(fb);
+ free_fb:
+       kfree(fb);
+ free_region:
+       amba_release_regions(dev);
+ out:
+       return ret;
+}
+
+static int clcdfb_remove(struct amba_device *dev)
+{
+       struct clcd_fb *fb = amba_get_drvdata(dev);
+
+       amba_set_drvdata(dev, NULL);
+
+       clcdfb_disable(fb);
+       unregister_framebuffer(&fb->fb);
+       iounmap(fb->regs);
+       clk_unuse(fb->clk);
+       clk_put(fb->clk);
+
+       fb->board->remove(fb);
+
+       kfree(fb);
+
+       amba_release_regions(dev);
+
+       return 0;
+}
+
+static struct amba_id clcdfb_id_table[] = {
+       {
+               .id     = 0x00041110,
+               .mask   = 0x000fffff,
+       },
+       { 0, 0 },
+};
+
+static struct amba_driver clcd_driver = {
+       .drv            = {
+               .name   = "clcd-pl110",
+       },
+       .probe          = clcdfb_probe,
+       .remove         = clcdfb_remove,
+       .id_table       = clcdfb_id_table,
+};
+
+int __init amba_clcdfb_init(void)
+{
+       if (fb_get_options("ambafb", NULL))
+               return -ENODEV;
+
+       return amba_driver_register(&clcd_driver);
+}
+
+module_init(amba_clcdfb_init);
+
+static void __exit amba_clcdfb_exit(void)
+{
+       amba_driver_unregister(&clcd_driver);
+}
+
+module_exit(amba_clcdfb_exit);
+
+MODULE_DESCRIPTION("ARM PrimeCell PL110 CLCD core driver");
+MODULE_LICENSE("GPL");
index 95ea71c..baa4fa0 100644 (file)
@@ -1307,6 +1307,8 @@ static int amifb_set_par(struct fb_info *info)
                info->fix.ywrapstep = 1;
                info->fix.xpanstep = 0;
                info->fix.ypanstep = 0;
+               info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
+                   FBINFO_READS_FAST; /* override SCROLL_REDRAW */
        } else {
                info->fix.ywrapstep = 0;
                if (par->vmode & FB_VMODE_SMOOTH_XPAN)
@@ -1314,6 +1316,7 @@ static int amifb_set_par(struct fb_info *info)
                else
                        info->fix.xpanstep = 16<<maxfmode;
                info->fix.ypanstep = 1;
+               info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
        }
        return 0;
 }
@@ -2254,6 +2257,13 @@ int __init amifb_init(void)
        u_long chipptr;
        u_int defmode;
 
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("amifb", &option))
+               return -ENODEV;
+       amifb_setup(option);
+#endif
        if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))
                return -ENXIO;
 
@@ -2382,7 +2392,7 @@ default_chipset:
 
        fb_info.fbops = &amifb_ops;
        fb_info.par = &currentpar;
-       fb_info.flags = FBINFO_FLAG_DEFAULT;
+       fb_info.flags = FBINFO_DEFAULT;
 
        if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,
                          NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
@@ -3811,14 +3821,11 @@ static void ami_rebuild_copper(void)
 }
 
 
+module_init(amifb_init);
+
 #ifdef MODULE
 MODULE_LICENSE("GPL");
 
-int init_module(void)
-{
-       return amifb_init();
-}
-
 void cleanup_module(void)
 {
        unregister_framebuffer(&fb_info);
index 1563b0d..bda3ed9 100644 (file)
@@ -524,7 +524,7 @@ static void __init init_asiliant(struct fb_info *p, unsigned long addr)
        p->fix.smem_start       = addr;
        p->var                  = asiliantfb_var;
        p->fbops                = &asiliantfb_ops;
-       p->flags                = FBINFO_FLAG_DEFAULT;
+       p->flags                = FBINFO_DEFAULT;
 
        fb_alloc_cmap(&p->cmap, 256, 0);
 
@@ -609,9 +609,14 @@ static struct pci_driver asiliantfb_driver = {
 
 int __init asiliantfb_init(void)
 {
+       if (fb_get_options("asiliantfb", NULL))
+               return -ENODEV;
+
        return pci_module_init(&asiliantfb_driver);
 }
 
+module_init(asiliantfb_init);
+
 static void __exit asiliantfb_exit(void)
 {
        pci_unregister_driver(&asiliantfb_driver);
index 1c7bcd8..f2d82d0 100644 (file)
@@ -2439,6 +2439,14 @@ static int aty128_pci_resume(struct pci_dev *pdev)
 
 int __init aty128fb_init(void)
 {
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("aty128fb", &option))
+               return -ENODEV;
+       aty128fb_setup(option);
+#endif
+
        return pci_module_init(&aty128fb_driver);
 }
 
@@ -2447,8 +2455,9 @@ static void __exit aty128fb_exit(void)
        pci_unregister_driver(&aty128fb_driver);
 }
 
-#ifdef MODULE
 module_init(aty128fb_init);
+
+#ifdef MODULE
 module_exit(aty128fb_exit);
 
 MODULE_AUTHOR("(c)1999-2003 Brad Douglas <brad@neruo.com>");
index b3ab23b..65b65ad 100644 (file)
@@ -323,7 +323,7 @@ static void bw2_init_one(struct sbus_dev *sdev)
                resp = &res;
                all->info.var.xres = all->info.var.xres_virtual = 1152;
                all->info.var.yres = all->info.var.yres_virtual = 900;
-               all->info.bits_per_pixel = 1;
+               all->info.var.bits_per_pixel = 1;
                linebytes = 1152 / 8;
        } else
 #else
@@ -337,6 +337,10 @@ static void bw2_init_one(struct sbus_dev *sdev)
                                               all->info.var.xres);
        }
 #endif
+       all->info.var.red.length = all->info.var.green.length =
+               all->info.var.blue.length = all->info.var.bits_per_pixel;
+       all->info.var.red.offset = all->info.var.green.offset =
+               all->info.var.blue.offset = 0;
 
        all->par.regs = (struct bw2_regs *)
                sbus_ioremap(resp, BWTWO_REGISTER_OFFSET,
@@ -347,7 +351,7 @@ static void bw2_init_one(struct sbus_dev *sdev)
 
        all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
 
-       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.flags = FBINFO_DEFAULT;
        all->info.fbops = &bw2_ops;
 #if defined(CONFIG_SPARC32)
        if (sdev)
@@ -382,6 +386,9 @@ int __init bw2_init(void)
        struct sbus_bus *sbus;
        struct sbus_dev *sdev;
 
+       if (fb_get_options("bw2fb", &option))
+               return -ENODEV;
+
 #ifdef CONFIG_SUN4
        bw2_init_one(NULL);
 #endif
@@ -412,8 +419,9 @@ bw2_setup(char *arg)
        return 0;
 }
 
-#ifdef MODULE
 module_init(bw2_init);
+
+#ifdef MODULE
 module_exit(bw2_exit);
 #endif
 
index 9c32d2b..b4b286a 100644 (file)
@@ -43,8 +43,9 @@
 #define BYTES_PER_LONG 8
 #endif
 
-static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
-                  int src_idx, unsigned long n)
+static void bitcpy(unsigned long __iomem *dst, int dst_idx,
+                  const unsigned long __iomem *src, int src_idx,
+                  unsigned long n)
 {
        unsigned long first, last;
        int shift = dst_idx-src_idx, left, right;
@@ -185,8 +186,8 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
        }
 }
 
-static void bitcpy_rev(unsigned long *dst, int dst_idx,
-                      const unsigned long *src, int src_idx, unsigned long n)
+static void bitcpy_rev(unsigned long __iomem *dst, int dst_idx,
+                      const unsigned long __iomem *src, int src_idx, unsigned long n)
 {
        unsigned long first, last;
        int shift = dst_idx-src_idx, left, right;
@@ -344,7 +345,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
        int x2, y2, old_dx, old_dy, vxres, vyres;
        unsigned long next_line = p->fix.line_length;
        int dst_idx = 0, src_idx = 0, rev_copy = 0;
-       unsigned long *dst = NULL, *src = NULL;
+       unsigned long __iomem *dst = NULL, *src = NULL;
 
        if (p->state != FBINFO_STATE_RUNNING)
                return;
@@ -394,7 +395,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
                rev_copy = 1;
        }
 
-       dst = src = (unsigned long *)((unsigned long)p->screen_base & 
+       dst = src = (unsigned long __iomem *)((unsigned long)p->screen_base & 
                                      ~(BYTES_PER_LONG-1));
        dst_idx = src_idx = (unsigned long)p->screen_base & (BYTES_PER_LONG-1);
        dst_idx += dy*next_line*8 + dx*p->var.bits_per_pixel;
index 20f3acf..4a94bf8 100644 (file)
@@ -119,7 +119,7 @@ static inline unsigned long pixel_to_pat(const struct fb_info *p,
      *  Unaligned 32-bit pattern fill using 32/64-bit memory accesses
      */
 
-void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
+void bitfill32(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
 {
        unsigned long val = pat;
        unsigned long first, last;
@@ -178,7 +178,7 @@ void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
      *  used for the next 32/64-bit word
      */
 
-void bitfill(unsigned long *dst, int dst_idx, unsigned long pat, int left,
+void bitfill(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left,
             int right, u32 n)
 {
        unsigned long first, last;
@@ -228,7 +228,7 @@ void bitfill(unsigned long *dst, int dst_idx, unsigned long pat, int left,
        }
 }
 
-void bitfill32_rev(unsigned long *dst, int dst_idx, u32 pat, u32 n)
+void bitfill32_rev(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
 {
        unsigned long val = pat, dat;
        unsigned long first, last;
@@ -300,7 +300,7 @@ void bitfill32_rev(unsigned long *dst, int dst_idx, u32 pat, u32 n)
      *  used for the next 32/64-bit word
      */
 
-void bitfill_rev(unsigned long *dst, int dst_idx, unsigned long pat, int left,
+void bitfill_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left,
             int right, u32 n)
 {
        unsigned long first, last, dat;
@@ -364,7 +364,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
        u32 bpp = p->var.bits_per_pixel;
        unsigned long x2, y2, vxres, vyres;
        unsigned long height, width, fg;
-       unsigned long *dst;
+       unsigned long __iomem *dst;
        int dst_idx, left;
 
        if (p->state != FBINFO_STATE_RUNNING)
@@ -397,7 +397,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
        else
                fg = rect->color;
        
-       dst = (unsigned long *)((unsigned long)p->screen_base & 
+       dst = (unsigned long __iomem *)((unsigned long)p->screen_base & 
                                ~(BYTES_PER_LONG-1));
        dst_idx = ((unsigned long)p->screen_base & (BYTES_PER_LONG-1))*8;
        dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
@@ -407,7 +407,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
                p->fbops->fb_sync(p);
        if (!left) {
                u32 pat = pixel_to_pat32(p, fg);
-               void (*fill_op32)(unsigned long *dst, int dst_idx, u32 pat, 
+               void (*fill_op32)(unsigned long __iomem *dst, int dst_idx, u32 pat, 
                                  u32 n) = NULL;
                
                switch (rect->rop) {
@@ -429,7 +429,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
                unsigned long pat = pixel_to_pat(p, fg, (left-dst_idx) % bpp);
                int right = bpp-left;
                int r;
-               void (*fill_op)(unsigned long *dst, int dst_idx, 
+               void (*fill_op)(unsigned long __iomem *dst, int dst_idx, 
                                unsigned long pat, int left, int right, 
                                u32 n) = NULL;
                
index 31da88e..4c123ab 100644 (file)
@@ -87,21 +87,22 @@ static u32 cfb_tab32[] = {
 #endif
 
 static inline void color_imageblit(const struct fb_image *image, 
-                                  struct fb_info *p, u8 *dst1, 
+                                  struct fb_info *p, u8 __iomem *dst1, 
                                   u32 start_index,
                                   u32 pitch_index)
 {
        /* Draw the penguin */
-       u32 *dst, *dst2, color = 0, val, shift;
+       u32 __iomem *dst, *dst2;
+       u32 color = 0, val, shift;
        int i, n, bpp = p->var.bits_per_pixel;
        u32 null_bits = 32 - bpp;
        u32 *palette = (u32 *) p->pseudo_palette;
        const u8 *src = image->data;
 
-       dst2 = (u32 *) dst1;
+       dst2 = (u32 __iomem *) dst1;
        for (i = image->height; i--; ) {
                n = image->width;
-               dst = (u32 *) dst1;
+               dst = (u32 __iomem *) dst1;
                shift = 0;
                val = 0;
                
@@ -136,7 +137,7 @@ static inline void color_imageblit(const struct fb_image *image,
                dst1 += p->fix.line_length;
                if (pitch_index) {
                        dst2 += p->fix.line_length;
-                       dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
+                       dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
 
                        start_index += pitch_index;
                        start_index &= 32 - 1;
@@ -145,25 +146,26 @@ static inline void color_imageblit(const struct fb_image *image,
 }
 
 static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, 
-                                 u8 *dst1, u32 fgcolor,
+                                 u8 __iomem *dst1, u32 fgcolor,
                                  u32 bgcolor, 
                                  u32 start_index,
                                  u32 pitch_index)
 {
        u32 shift, color = 0, bpp = p->var.bits_per_pixel;
-       u32 *dst, *dst2, val, pitch = p->fix.line_length;
+       u32 __iomem *dst, *dst2;
+       u32 val, pitch = p->fix.line_length;
        u32 null_bits = 32 - bpp;
        u32 spitch = (image->width+7)/8;
        const u8 *src = image->data, *s;
        u32 i, j, l;
        
-       dst2 = (u32 *) dst1;
+       dst2 = (u32 __iomem *) dst1;
 
        for (i = image->height; i--; ) {
                shift = val = 0;
                l = 8;
                j = image->width;
-               dst = (u32 *) dst1;
+               dst = (u32 __iomem *) dst1;
                s = src;
 
                /* write leading bits */
@@ -201,7 +203,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
                src += spitch;  
                if (pitch_index) {
                        dst2 += pitch;
-                       dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
+                       dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
                        start_index += pitch_index;
                        start_index &= 32 - 1;
                }
@@ -218,14 +220,14 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
  *           beginning and end of a scanline is dword aligned
  */
 static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p, 
-                                 u8 *dst1, u32 fgcolor, 
+                                 u8 __iomem *dst1, u32 fgcolor, 
                                  u32 bgcolor) 
 {
        u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
        u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
        u32 bit_mask, end_mask, eorx, shift;
        const char *s = image->data, *src;
-       u32 *dst;
+       u32 __iomem *dst;
        u32 *tab = NULL;
        int i, j, k;
                
@@ -253,7 +255,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info *
        k = image->width/ppw;
 
        for (i = image->height; i--; ) {
-               dst = (u32 *) dst1, shift = 8; src = s;
+               dst = (u32 __iomem *) dst1, shift = 8; src = s;
                
                for (j = k; j--; ) {
                        shift -= ppw;
@@ -273,7 +275,7 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
        u32 width = image->width, height = image->height; 
        u32 dx = image->dx, dy = image->dy;
        int x2, y2, vxres, vyres;
-       u8 *dst1;
+       u8 __iomem *dst1;
 
        if (p->state != FBINFO_STATE_RUNNING)
                return;
@@ -325,7 +327,7 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
                else 
                        slow_imageblit(image, p, dst1, fgcolor, bgcolor,
                                        start_index, pitch_index);
-       } else if (image->depth <= bpp) 
+       } else
                color_imageblit(image, p, dst1, start_index, pitch_index);
 }
 
index e0fc4c0..c43322b 100644 (file)
@@ -550,7 +550,7 @@ static void cg14_init_one(struct sbus_dev *sdev, int node, int parent_node)
        all->par.mode = MDI_8_PIX;
        all->par.ramsize = (is_8mb ? 0x800000 : 0x400000);
 
-       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
        all->info.fbops = &cg14_ops;
        all->info.currcon = -1;
        all->info.par = &all->par;
@@ -584,6 +584,9 @@ int __init cg14_init(void)
        struct sbus_bus *sbus;
        struct sbus_dev *sdev;
 
+       if (fb_get_options("cg14fb", NULL))
+               return -ENODEV;
+
 #ifdef CONFIG_SPARC32
        {
                int root, node;
@@ -626,8 +629,9 @@ cg14_setup(char *arg)
        return 0;
 }
 
-#ifdef MODULE
 module_init(cg14_init);
+
+#ifdef MODULE
 module_exit(cg14_exit);
 #endif
 
index dd0163c..0783941 100644 (file)
@@ -398,7 +398,7 @@ static void cg3_init_one(struct sbus_dev *sdev)
                sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET,
                             sizeof(struct cg3_regs), "cg3 regs");
 
-       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.flags = FBINFO_DEFAULT;
        all->info.fbops = &cg3_ops;
 #ifdef CONFIG_SPARC32
        all->info.screen_base = (char *)
@@ -444,6 +444,9 @@ int __init cg3_init(void)
        struct sbus_bus *sbus;
        struct sbus_dev *sdev;
 
+       if (fb_get_options("cg3fb", NULL))
+               return -ENODEV;
+
        for_all_sbusdev(sdev, sbus) {
                if (!strcmp(sdev->prom_name, "cgthree") ||
                    !strcmp(sdev->prom_name, "cgRDI"))
@@ -473,8 +476,9 @@ cg3_setup(char *arg)
        return 0;
 }
 
-#ifdef MODULE
 module_init(cg3_init);
+
+#ifdef MODULE
 module_exit(cg3_exit);
 #endif
 
index 469ac20..be87a66 100644 (file)
@@ -712,7 +712,8 @@ static void cg6_init_one(struct sbus_dev *sdev)
                sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET,
                             sizeof(u32), "cgsix fhc");
 
-       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
+                          FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
        all->info.fbops = &cg6_ops;
 #ifdef CONFIG_SPARC32
        all->info.screen_base = (char *)
@@ -759,6 +760,9 @@ int __init cg6_init(void)
        struct sbus_bus *sbus;
        struct sbus_dev *sdev;
 
+       if (fb_get_options("cg6fb", NULL))
+               return -ENODEV;
+
        for_all_sbusdev(sdev, sbus) {
                if (!strcmp(sdev->prom_name, "cgsix") ||
                    !strcmp(sdev->prom_name, "cgthree+"))
@@ -788,8 +792,9 @@ cg6_setup(char *arg)
        return 0;
 }
 
-#ifdef MODULE
 module_init(cg6_init);
+
+#ifdef MODULE
 module_exit(cg6_exit);
 #endif
 
index c804352..4ee5a25 100644 (file)
@@ -362,7 +362,7 @@ static void __init init_chips(struct fb_info *p, unsigned long addr)
        p->var = chipsfb_var;
 
        p->fbops = &chipsfb_ops;
-       p->flags = FBINFO_FLAG_DEFAULT;
+       p->flags = FBINFO_DEFAULT;
 
        fb_alloc_cmap(&p->cmap, 256, 0);
 
@@ -462,9 +462,14 @@ static struct pci_driver chipsfb_driver = {
 
 int __init chips_init(void)
 {
+       if (fb_get_options("chipsfb", NULL))
+               return -ENODEV;
+
        return pci_module_init(&chipsfb_driver);
 }
 
+module_init(chips_init);
+
 static void __exit chipsfb_exit(void)
 {
        pci_unregister_driver(&chipsfb_driver);
index a982e75..8692e00 100644 (file)
@@ -364,6 +364,9 @@ int __init clps711xfb_init(void)
 {
        int err = -ENOMEM;
 
+       if (fb_get_options("clps711xfb", NULL))
+               return -ENODEV;
+
        cfb = kmalloc(sizeof(*cfb), GFP_KERNEL);
        if (!cfb)
                goto out;
@@ -372,7 +375,7 @@ int __init clps711xfb_init(void)
        strcpy(cfb->fix.id, "clps711x");
 
        cfb->fbops              = &clps7111fb_ops;
-       cfb->flags              = FBINFO_FLAG_DEFAULT;
+       cfb->flags              = FBINFO_DEFAULT;
 
        clps711x_guess_lcd_params(cfb);
 
@@ -432,9 +435,7 @@ static void __exit clps711xfb_exit(void)
        }
 }
 
-#ifdef MODULE
 module_init(clps711xfb_init);
-#endif
 module_exit(clps711xfb_exit);
 
 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
index 8ad33fa..22896d6 100644 (file)
@@ -556,6 +556,11 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
 int __init control_init(void)
 {
        struct device_node *dp;
+       char *option = NULL;
+
+       if (fb_get_options("controlfb", &option))
+               return -ENODEV;
+       control_setup(option);
 
        dp = find_devices("control");
        if (dp != 0 && !control_of_init(dp))
@@ -564,6 +569,7 @@ int __init control_init(void)
        return -ENXIO;
 }
 
+module_init(control_init);
 
 /* Work out which banks of VRAM we have installed. */
 /* danj: I guess the card just ignores writes to nonexistant VRAM... */
@@ -1010,7 +1016,7 @@ static void __init control_init_info(struct fb_info *info, struct fb_info_contro
        info->par = &p->par;
        info->fbops = &controlfb_ops;
        info->pseudo_palette = p->pseudo_palette;
-        info->flags = FBINFO_FLAG_DEFAULT;
+        info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
        info->screen_base = (char *) p->frame_buffer + CTRLFB_OFF;
 
        fb_alloc_cmap(&info->cmap, 256, 0);
index 11ba053..1dbb82d 100644 (file)
@@ -239,6 +239,9 @@ static int __devinit dnfb_probe(struct device *device)
        info->fbops = &dn_fb_ops;
        info->fix = dnfb_fix;
        info->var = dnfb_var;
+       info->var.red.length = 1;
+       info->var.red.offset = 0;
+       info->var.green = info->var.blue = info->var.red;
        info->screen_base = (u_char *) info->fix.smem_start;
 
        err = fb_alloc_cmap(&info->cmap, 2, 0);
@@ -281,6 +284,9 @@ int __init dnfb_init(void)
 {
        int ret;
 
+       if (fb_get_options("dnfb", NULL))
+               return -ENODEV;
+
        ret = driver_register(&dnfb_driver);
 
        if (!ret) {
@@ -291,4 +297,6 @@ int __init dnfb_init(void)
        return ret;
 }
 
+module_init(dnfb_init);
+
 MODULE_LICENSE("GPL");
index a998ee9..6cb54f8 100644 (file)
 /*
- * linux/drivers/video/epson1355fb.c
- *     -- Support for the Epson SED1355 LCD/CRT controller
+ * linux/drivers/video/epson1355fb.c -- Epson S1D13505 frame buffer for 2.5.
  *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Epson Research S1D13505 Embedded RAMDAC LCD/CRT Controller
+ *   (previously known as SED1355)
  *
- * based on linux/drivers/video/skeletonfb.c, which was
+ * Cf. http://www.erd.epson.com/vdc/html/S1D13505.html
+ *
+ *
+ * Copyright (C) Hewlett-Packard Company.  All rights reserved.
+ *
+ * Written by Christopher Hoover <ch@hpl.hp.com>
+ *
+ * Adapted from:
+ *
+ *  linux/drivers/video/skeletonfb.c
+ *  Modified to new api Jan 2001 by James Simmons (jsimmons@infradead.org)
  *  Created 28 Dec 1997 by Geert Uytterhoeven
  *
+ *  linux/drivers/video/epson1355fb.c (2.4 driver)
+ *  Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
  * 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.
- */
-/* TODO (roughly in order of priority):
- * 16 bpp support
- * crt support
- * hw cursor support
- * SwivelView
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ *
+ * Noteworthy Issues
+ * -----------------
+ *
+ * This driver is complicated by the fact that this is a 16-bit chip
+ * and, on at least one platform (ceiva), we can only do 16-bit reads
+ * and writes to the framebuffer.  We hide this from user space
+ * except in the case of mmap().
+ *
+ *
+ * To Do
+ * -----
+ *
+ * - Test 8-bit pseudocolor mode
+ * - Allow setting bpp, virtual resolution
+ * - Implement horizontal panning
+ * - (maybe) Implement hardware cursor
  */
 
-#include <asm/io.h>
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/mm.h>
 #include <linux/tty.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-mfb.h>
-#include <video/fbcon.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
 
-/* Register defines.  The docs don't seem to provide nice mnemonic names
- * so I made them up myself ... */
+#include <video/epson1355.h>
 
-#define E1355_PANEL    0x02
-#define E1355_DISPLAY  0x0D
-#define E1355_MISC     0x1B
-#define E1355_GPIO     0x20
-#define E1355_LUT_INDEX 0x24
-#define E1355_LUT_DATA 0x26
+struct epson1355_par {
+       unsigned long reg_addr;
+};
+
+/* ------------------------------------------------------------------------- */
 
 #ifdef CONFIG_SUPERH
-#define E1355_REG_BASE CONFIG_E1355_REG_BASE
-#define E1355_FB_BASE  CONFIG_E1355_FB_BASE
 
-static inline u8 e1355_read_reg(int index)
+static inline u8 epson1355_read_reg(int index)
 {
-       return ctrl_inb(E1355_REG_BASE + index);
+       return ctrl_inb(par.reg_addr + index);
 }
 
-static inline void e1355_write_reg(u8 data, int index)
+static inline void epson1355_write_reg(u8 data, int index)
 {
-       ctrl_outb(data, E1355_REG_BASE + index);
+       ctrl_outb(data, par.reg_addr + index);
 }
 
-static inline u16 e1355_read_reg16(int index)
+#elif defined(CONFIG_ARM)
+
+# ifdef CONFIG_ARCH_CEIVA
+#  include <asm/arch/hardware.h>
+#  define EPSON1355FB_BASE_PHYS        (CEIVA_PHYS_SED1355)
+# endif
+
+static inline u8 epson1355_read_reg(struct epson1355_par *par, int index)
 {
-       return e1355_read_reg(index) + (e1355_read_reg(index+1) << 8);
+       return __raw_readb(par->reg_addr + index);
 }
 
-static inline void e1355_write_reg16(u16 data, int index)
+static inline void epson1355_write_reg(struct epson1355_par *par, u8 data, int index)
 {
-       e1355_write_reg((data&0xff), index);
-       e1355_write_reg(((data>>8)&0xff), index + 1);
+       __raw_writeb(data, par->reg_addr + index);
 }
+
 #else
-#error unknown architecture
+# error "no architecture-specific epson1355_{read,write}_reg"
 #endif
 
-struct e1355fb_info {
-       struct fb_info_gen gen;
-};
-
-static int current_par_valid = 0;
-static struct display disp;
+#ifndef EPSON1355FB_BASE_PHYS
+# error  "EPSON1355FB_BASE_PHYS is not defined"
+#endif
 
-static struct fb_var_screeninfo default_var;
+#define EPSON1355FB_REGS_OFS   (0)
+#define EPSON1355FB_REGS_PHYS  (EPSON1355FB_BASE_PHYS + EPSON1355FB_REGS_OFS)
+#define EPSON1355FB_REGS_LEN   (64)
 
-int e1355fb_init(void);
-int e1355fb_setup(char*);
-static int e1355_encode_var(struct fb_var_screeninfo *var, const void *par,
-                           struct fb_info_gen *info);
-/* ------------------- chipset specific functions -------------------------- */
+#define EPSON1355FB_FB_OFS     (0x00200000)
+#define EPSON1355FB_FB_PHYS    (EPSON1355FB_BASE_PHYS + EPSON1355FB_FB_OFS)
+#define EPSON1355FB_FB_LEN     (2 * 1024 * 1024)
 
+/* ------------------------------------------------------------------------- */
 
-static void disable_hw_cursor(void)
+static inline u16 epson1355_read_reg16(struct epson1355_par *par, int index)
 {
-       u8 curs;
+       u8 lo = epson1355_read_reg(par, index);
+       u8 hi = epson1355_read_reg(par, index + 1);
 
-       curs = e1355_read_reg(0x27);
-       curs &= ~0xc0;
-       e1355_write_reg(curs, 0x27);
+       return (hi << 8) | lo;
 }
 
-static void e1355_detect(void)
+static inline void epson1355_write_reg16(struct epson1355_par *par, u16 data, int index)
 {
-       u8 rev;
+       u8 lo = data & 0xff;
+       u8 hi = (data >> 8) & 0xff;
 
-       e1355_write_reg(0x00, E1355_MISC);
+       epson1355_write_reg(par, lo, index);
+       epson1355_write_reg(par, hi, index + 1);
+}
 
-       rev = e1355_read_reg(0x00);
+static inline u32 epson1355_read_reg20(struct epson1355_par *par, int index)
+{
+       u8 b0 = epson1355_read_reg(par, index);
+       u8 b1 = epson1355_read_reg(par, index + 1);
+       u8 b2 = epson1355_read_reg(par, index + 2);
 
-       if ((rev & 0xfc) != 0x0c) {
-               printk(KERN_WARNING "Epson 1355 not detected\n");
-       }
+       return (b2 & 0x0f) << 16 | (b1 << 8) | b0;
+}
 
-       /* XXX */
-       disable_hw_cursor();
+static inline void epson1355_write_reg20(struct epson1355_par *par, u32 data, int index)
+{
+       u8 b0 = data & 0xff;
+       u8 b1 = (data >> 8) & 0xff;
+       u8 b2 = (data >> 16) & 0x0f;
 
-       e1355_encode_var(&default_var, NULL, NULL);
+       epson1355_write_reg(par, b0, index);
+       epson1355_write_reg(par, b1, index + 1);
+       epson1355_write_reg(par, b2, index + 2);
 }
 
-struct e1355_par {
-       u32 xres;
-       u32 yres;
+/* ------------------------------------------------------------------------- */
 
-       int bpp;
-       int mem_bpp;
+static void set_lut(struct epson1355_par *par, u8 index, u8 r, u8 g, u8 b)
+{
+       epson1355_write_reg(par, index, REG_LUT_ADDR);
+       epson1355_write_reg(par, r, REG_LUT_DATA);
+       epson1355_write_reg(par, g, REG_LUT_DATA);
+       epson1355_write_reg(par, b, REG_LUT_DATA);
+}
 
-       u32 panel_xres;
-       u32 panel_yres;
-       
-       int panel_width;
-       int panel_ymul;
-};
 
-static int e1355_encode_fix(struct fb_fix_screeninfo *fix,
-                           const void *raw_par,
-                           struct fb_info_gen *info)
+/**
+ *     epson1355fb_setcolreg - sets a color register.
+ *      @regno: Which register in the CLUT we are programming
+ *      @red: The red value which can be up to 16 bits wide
+ *     @green: The green value which can be up to 16 bits wide
+ *     @blue:  The blue value which can be up to 16 bits wide.
+ *     @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ *
+ *     Returns negative errno on error, or zero on success.
+ */
+static int epson1355fb_setcolreg(unsigned regno, unsigned r, unsigned g,
+                                unsigned b, unsigned transp,
+                                struct fb_info *info)
 {
-       const struct e1355_par *par = raw_par;
-       
-       memset(fix, 0, sizeof *fix);
-       
-       fix->type= FB_TYPE_PACKED_PIXELS;
-
-       if (!par)
-               BUG();
+       struct epson1355_par *par = info->par;
 
-       if (par->bpp == 1) {
-               fix->visual = FB_VISUAL_MONO10;
-       } else if (par->bpp <= 8) {
-               fix->visual = FB_VISUAL_PSEUDOCOLOR;
-       } else {
-               fix->visual = FB_VISUAL_TRUECOLOR;
-       }
+       if (info->var.grayscale)
+               r = g = b = (19595 * r + 38470 * g + 7471 * b) >> 16;
 
-       return 0;
-}
+       switch (info->fix.visual) {
+       case FB_VISUAL_TRUECOLOR:
+               if (regno >= 16)
+                       return -EINVAL;
 
-static int e1355_set_bpp(struct e1355_par *par, int bpp)
-{
-       int code;
-       u8 disp;
-       u16 bytes_per_line;
-
-       switch(bpp) {
-       case 1:
-               code = 0; break;
-       case 2:
-               code = 1; break;
-       case 4:
-               code = 2; break;
-       case 8:
-               code = 3; break;
-       case 16:
-               code = 5; break;
-       default:
-               return -EINVAL; break;
-       }
+               ((u32 *) info->pseudo_palette)[regno] =
+                   (r & 0xf800) | (g & 0xfc00) >> 5 | (b & 0xf800) >> 11;
 
-       disp = e1355_read_reg(E1355_DISPLAY);
-       disp &= ~0x1c;
-       disp |= code << 2;
-       e1355_write_reg(disp, E1355_DISPLAY);
-       
-       bytes_per_line = (par->xres * bpp) >> 3;
-       
-       e1355_write_reg16(bytes_per_line, 0x16);
+               break;
+       case FB_VISUAL_PSEUDOCOLOR:
+               if (regno >= 256)
+                       return -EINVAL;
 
-       par->bpp = bpp;
+               set_lut(par, regno, r >> 8, g >> 8, b >> 8);
 
+               break;
+       default:
+               return -ENOSYS;
+       }
        return 0;
 }
-               
-static int e1355_decode_var(const struct fb_var_screeninfo *var,
-                           void *raw_par,
-                           struct fb_info_gen *info)
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ *      epson1355fb_pan_display - Pans the display.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *     Pan (or wrap, depending on the `vmode' field) the display using the
+ *     `xoffset' and `yoffset' fields of the `var' structure.
+ *     If the values don't fit, return -EINVAL.
+ *
+ *      Returns negative errno on error, or zero on success.
+ */
+static int epson1355fb_pan_display(struct fb_var_screeninfo *var,
+                                  struct fb_info *info)
 {
-       struct e1355_par *par = raw_par;
-       int ret;
+       struct epson1355_par *par = info->par;
+       u32 start;
 
-       if (!par)
-               BUG();
+       if (var->xoffset != 0)  /* not yet ... */
+               return -EINVAL;
 
-       /*
-        * Don't allow setting any of these yet: xres and yres don't
-        * make sense for LCD panels; xres_virtual and yres_virtual
-        * should be supported fine by our hardware though.
-        */
-       if (var->xres != par->xres ||
-           var->yres != par->yres ||
-           var->xres != var->xres_virtual ||
-           var->yres != var->yres_virtual ||
-           var->xoffset != 0 ||
-           var->yoffset != 0)
+       if (var->yoffset + info->var.yres > info->var.yres_virtual)
                return -EINVAL;
 
-       if(var->bits_per_pixel != par->bpp) {
-               ret = e1355_set_bpp(par, var->bits_per_pixel);
+       start = (info->fix.line_length >> 1) * var->yoffset;
+
+       epson1355_write_reg20(par, start, REG_SCRN1_DISP_START_ADDR0);
 
-               if (ret)
-                       goto out_err;
-       }
-               
        return 0;
+}
 
- out_err:
-       return ret;
+/* ------------------------------------------------------------------------- */
+
+static void lcd_enable(struct epson1355_par *par, int enable)
+{
+       u8 mode = epson1355_read_reg(par, REG_DISPLAY_MODE);
+
+       if (enable)
+               mode |= 1;
+       else
+               mode &= ~1;
+
+       epson1355_write_reg(par, mode, REG_DISPLAY_MODE);
 }
 
-static void dump_panel_data(void)
+#if defined(CONFIG_ARCH_CEIVA)
+static void backlight_enable(int enable)
+{
+       /* ### this should be protected by a spinlock ... */
+       u8 pddr = clps_readb(PDDR);
+       if (enable)
+               pddr |= (1 << 5);
+       else
+               pddr &= ~(1 << 5);
+       clps_writeb(pddr, PDDR);
+}
+#else
+static void backlight_enable(int enable)
 {
-       u8 panel = e1355_read_reg(E1355_PANEL);
-       int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
-
-       printk("%s %s %s panel, width %d bits\n",
-              panel & 2 ? "dual" : "single",
-              panel & 4 ? "color" : "mono",
-              panel & 1 ? "TFT" : "passive",
-              width[panel&1][(panel>>4)&3]);
-
-       printk("resolution %d x %d\n",
-              (e1355_read_reg(0x04) + 1) * 8,
-              ((e1355_read_reg16(0x08) + 1) * (1 + ((panel & 3) == 2))));
 }
+#endif
+
 
-static int e1355_bpp_to_var(int bpp, struct fb_var_screeninfo *var)
+/**
+ *      epson1355fb_blank - blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *      Blank the screen if blank_mode != 0, else unblank. 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
+ *      blank_mode == 3: suspend hsync
+ *      blank_mode == 4: powerdown
+ *
+ *      Returns negative errno on error, or zero on success.
+ *
+ */
+static int epson1355fb_blank(int blank_mode, struct fb_info *info)
 {
-       switch(bpp) {
-       case 1:
-       case 2:
-       case 4:
-       case 8:
-               var->bits_per_pixel = bpp;
-               var->red.offset = var->green.offset = var->blue.offset = 0;
-               var->red.length = var->green.length = var->blue.length = bpp;
+       struct epson1355_par *par = info->par;
+
+       switch (blank_mode) {
+       case VESA_NO_BLANKING:
+               lcd_enable(par, 1);
+               backlight_enable(1);
                break;
-       case 16:
-               var->bits_per_pixel = 16;
-               var->red.offset = 11;
-               var->red.length = 5;
-               var->green.offset = 5;
-               var->green.length = 6;
-               var->blue.offset = 0;
-               var->blue.length = 5;
+       case VESA_VSYNC_SUSPEND:
+       case VESA_HSYNC_SUSPEND:
+               backlight_enable(0);
+               break;
+       case VESA_POWERDOWN:
+               backlight_enable(0);
+               lcd_enable(par, 0);
                break;
+       default:
+               return -EINVAL;
        }
-
        return 0;
 }
 
-static int e1355_encode_var(struct fb_var_screeninfo *var, const void *raw_par,
-                           struct fb_info_gen *info)
-{
-       u8 panel, display;
-       u32 xres, xres_virtual, yres;
-       static int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
-       static int bpp_tab[8] = { 1, 2, 4, 8, 15, 16 };
-       int bpp, hw_bpp;
-       int is_color, is_dual, is_tft;
-       int lcd_enabled, crt_enabled;
+/* ------------------------------------------------------------------------- */
 
-       panel = e1355_read_reg(E1355_PANEL);
-       display = e1355_read_reg(E1355_DISPLAY);
+/*
+ * We can't use the cfb generic routines, as we have to limit
+ * ourselves to 16-bit or 8-bit loads and stores to this 16-bit
+ * chip.
+ */
 
-       is_color = (panel & 0x04) != 0;
-       is_dual  = (panel & 0x02) != 0;
-       is_tft   = (panel & 0x01) != 0;
+static inline void epson1355fb_fb_writel(unsigned long v, unsigned long *a)
+{
+       u16 *p = (u16 *) a;
+       u16 l = v & 0xffff;
+       u16 h = v >> 16;
 
-       bpp = bpp_tab[(display>>2)&7]; 
-       e1355_bpp_to_var(bpp, var);
+       fb_writew(l, p);
+       fb_writew(h, p + 1);
+}
 
-       crt_enabled = (display & 0x02) != 0;
-       lcd_enabled = (display & 0x02) != 0;
+static inline unsigned long epson1355fb_fb_readl(const unsigned long *a)
+{
+       const u16 *p = (u16 *) a;
+       u16 l = fb_readw(p);
+       u16 h = fb_readw(p + 1);
 
-       hw_bpp = width[is_tft][(panel>>4)&3];
+       return (h << 16) | l;
+}
 
-       xres = e1355_read_reg(0x04) + 1;
-       yres = e1355_read_reg16(0x08) + 1;
-       
-       xres *= 8;
-       /* talk about weird hardware .. */
-       yres *= (is_dual && !crt_enabled) ? 2 : 1;
+#define FB_READL epson1355fb_fb_readl
+#define FB_WRITEL epson1355fb_fb_writel
 
-       xres_virtual = e1355_read_reg16(0x16);
-       /* it's in 2-byte words initially */
-       xres_virtual *= 16;
-       xres_virtual /= var->bits_per_pixel;
+/* ------------------------------------------------------------------------- */
 
-       var->xres = xres;
-       var->yres = yres;
-       var->xres_virtual = xres_virtual;
-       var->yres_virtual = yres;
+static inline unsigned long copy_from_user16(void *to, const void *from,
+                                            unsigned long n)
+{
+       u16 *dst = (u16 *) to;
+       u16 *src = (u16 *) from;
 
-       var->xoffset = var->yoffset = 0;
+       if (!access_ok(VERIFY_READ, from, n))
+               return n;
 
-       var->grayscale = !is_color;
-       
-       return 0;
-}
+       while (n > 1) {
+               u16 v;
+               if (__get_user(v, src))
+                       return n;
 
-#define is_dual(panel) (((panel)&3)==2)
+               fb_writew(v, dst);
 
-static void get_panel_data(struct e1355_par *par)
-{
-       u8 panel;
-       int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
+               src++, dst++;
+               n -= 2;
+       }
 
-       panel = e1355_read_reg(E1355_PANEL);
+       if (n) {
+               u8 v;
 
-       par->panel_width = width[panel&1][(panel>>4)&3];
-       par->panel_xres = (e1355_read_reg(0x04) + 1) * 8;
-       par->panel_ymul = is_dual(panel) ? 2 : 1;
-       par->panel_yres = ((e1355_read_reg16(0x08) + 1)
-                          * par->panel_ymul);
+               if (__get_user(v, ((u8 *) src)))
+                       return n;
+
+               fb_writeb(v, dst);
+       }
+       return 0;
 }
 
-static void e1355_get_par(void *raw_par, struct fb_info_gen *info)
+static inline unsigned long copy_to_user16(void *to, const void *from,
+                                          unsigned long n)
 {
-       struct e1355_par *par = raw_par;
+       u16 *dst = (u16 *) to;
+       u16 *src = (u16 *) from;
 
-       get_panel_data(par);
-}
+       if (!access_ok(VERIFY_WRITE, to, n))
+               return n;
 
-static void e1355_set_par(const void *par, struct fb_info_gen *info)
-{
-}
+       while (n > 1) {
+               u16 v = fb_readw(src);
 
-static int e1355_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-                          unsigned *blue, unsigned *transp,
-                          struct fb_info *info)
-{
-       u8 r, g, b;
+               if (__put_user(v, dst))
+                       return n;
 
-       e1355_write_reg(regno, E1355_LUT_INDEX);
-       r = e1355_read_reg(E1355_LUT_DATA);
-       g = e1355_read_reg(E1355_LUT_DATA);
-       b = e1355_read_reg(E1355_LUT_DATA);
+               src++, dst++;
+               n -= 2;
+       }
 
-       *red = r << 8;
-       *green = g << 8;
-       *blue = b << 8;
+       if (n) {
+               u8 v = fb_readb(src);
 
+               if (__put_user(v, ((u8 *) dst)))
+                       return n;
+       }
        return 0;
 }
 
-static int e1355fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-                            unsigned blue, unsigned transp,
-                            struct fb_info *info)
+
+static ssize_t
+epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos)
 {
-       u8 r = (red >> 8) & 0xf0;
-       u8 g = (green>>8) & 0xf0;
-       u8 b = (blue>> 8) & 0xf0;
-
-       e1355_write_reg(regno, E1355_LUT_INDEX);
-       e1355_write_reg(r, E1355_LUT_DATA);
-       e1355_write_reg(g, E1355_LUT_DATA);
-       e1355_write_reg(b, E1355_LUT_DATA);
-       
-       return 0;
+       struct inode *inode = file->f_dentry->d_inode;
+       int fbidx = iminor(inode);
+       struct fb_info *info = registered_fb[fbidx];
+       unsigned long p = *ppos;
+
+       /* from fbmem.c except for our own copy_*_user */
+       if (!info || !info->screen_base)
+               return -ENODEV;
+
+       if (p >= info->fix.smem_len)
+               return 0;
+       if (count >= info->fix.smem_len)
+               count = info->fix.smem_len;
+       if (count + p > info->fix.smem_len)
+               count = info->fix.smem_len - p;
+
+       if (count) {
+               char *base_addr;
+
+               base_addr = info->screen_base;
+               count -= copy_to_user16(buf, base_addr + p, count);
+               if (!count)
+                       return -EFAULT;
+               *ppos += count;
+       }
+       return count;
 }
 
-static int e1355_pan_display(const struct fb_var_screeninfo *var,
-                            struct fb_info_gen *info)
+static ssize_t
+epson1355fb_write(struct file *file, const char *buf,
+                 size_t count, loff_t * ppos)
 {
-       BUG();
-       
-       return -EINVAL;
-}
+       struct inode *inode = file->f_dentry->d_inode;
+       int fbidx = iminor(inode);
+       struct fb_info *info = registered_fb[fbidx];
+       unsigned long p = *ppos;
+       int err;
+
+       /* from fbmem.c except for our own copy_*_user */
+       if (!info || !info->screen_base)
+               return -ENODEV;
+
+       /* from fbmem.c except for our own copy_*_user */
+       if (p > info->fix.smem_len)
+               return -ENOSPC;
+       if (count >= info->fix.smem_len)
+               count = info->fix.smem_len;
+       err = 0;
+       if (count + p > info->fix.smem_len) {
+               count = info->fix.smem_len - p;
+               err = -ENOSPC;
+       }
 
-/*
- * The AERO_HACKS parts disable/enable the backlight on the Compaq Aero 8000.
- * I'm not sure they aren't dangerous to the hardware, so be warned.
- */
-#undef AERO_HACKS
+       if (count) {
+               char *base_addr;
 
-static int e1355_blank(int blank_mode, struct fb_info_gen *info)
-{
-       u8 disp;
+               base_addr = info->screen_base;
+               count -= copy_from_user16(base_addr + p, buf, count);
+               *ppos += count;
+               err = -EFAULT;
+       }
+       if (count)
+               return count;
+       return err;
+}
 
-       switch (blank_mode) {
-       case VESA_NO_BLANKING:
-               disp = e1355_read_reg(E1355_DISPLAY);
-               disp |= 1;
-               e1355_write_reg(disp, E1355_DISPLAY);
-               
-#ifdef AERO_HACKS
-               e1355_write_reg(0x6, 0x20);
-#endif
-               break;
+/* ------------------------------------------------------------------------- */
+
+static struct fb_ops epson1355fb_fbops = {
+       .owner          = THIS_MODULE,
+       .fb_setcolreg   = epson1355fb_setcolreg,
+       .fb_pan_display = epson1355fb_pan_display,
+       .fb_blank       = epson1355fb_blank,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+       .fb_read        = epson1355fb_read,
+       .fb_write       = epson1355fb_write,
+       .fb_cursor      = soft_cursor,
+};
 
-       case VESA_VSYNC_SUSPEND:
-       case VESA_HSYNC_SUSPEND:
-       case VESA_POWERDOWN:
-               disp = e1355_read_reg(E1355_DISPLAY);
-               disp &= ~1;
-               e1355_write_reg(disp, E1355_DISPLAY);
+/* ------------------------------------------------------------------------- */
 
-#ifdef AERO_HACKS
-               e1355_write_reg(0x0, 0x20);
-#endif
-               break;
+static __init unsigned int get_fb_size(struct fb_info *info)
+{
+       unsigned int size = 2 * 1024 * 1024;
+       char *p = info->screen_base;
 
-       default:
-               return -EINVAL;
-       }
+       /* the 512k framebuffer is aliased at start + 0x80000 * n */
+       fb_writeb(1, p);
+       fb_writeb(0, p + 0x80000);
+       if (!fb_readb(p))
+               size = 512 * 1024;
 
-       return 0;
+       fb_writeb(0, p);
+
+       return size;
 }
 
-static struct display_switch e1355_dispsw;
+static int epson1355_width_tab[2][4] __initdata =
+    { {4, 8, 16, -1}, {9, 12, 16, -1} };
+static int epson1355_bpp_tab[8] __initdata = { 1, 2, 4, 8, 15, 16 };
 
-static void e1355_set_disp(const void *unused, struct display *disp,
-                          struct fb_info_gen *info)
+static void __init fetch_hw_state(struct fb_info *info, struct epson1355_par *par)
 {
-       struct display_switch *d;
+       struct fb_var_screeninfo *var = &info->var;
+       struct fb_fix_screeninfo *fix = &info->fix;
+       u8 panel, display;
+       u16 offset;
+       u32 xres, yres;
+       u32 xres_virtual, yres_virtual;
+       int bpp, lcd_bpp;
+       int is_color, is_dual, is_tft;
+       int lcd_enabled, crt_enabled;
 
-       disp->dispsw = &e1355_dispsw;
-       
-       switch(disp->var.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
-       case 1:
-               d = &fbcon_mfb; break;
-#endif        
-#ifdef FBCON_HAS_CFB8
+       fix->type = FB_TYPE_PACKED_PIXELS;
+
+       display = epson1355_read_reg(par, REG_DISPLAY_MODE);
+       bpp = epson1355_bpp_tab[(display >> 2) & 7];
+
+       switch (bpp) {
        case 8:
-               d = &fbcon_cfb8; break;
-#endif
+               fix->visual = FB_VISUAL_PSEUDOCOLOR;
+               var->bits_per_pixel = 8;
+               var->red.offset = var->green.offset = var->blue.offset = 0;
+               var->red.length = var->green.length = var->blue.length = 8;
+               break;
+       case 16:
+               /* 5-6-5 RGB */
+               fix->visual = FB_VISUAL_TRUECOLOR;
+               var->bits_per_pixel = 16;
+               var->red.offset = 11;
+               var->red.length = 5;
+               var->green.offset = 5;
+               var->green.length = 6;
+               var->blue.offset = 0;
+               var->blue.length = 5;
+               break;
        default:
-               BUG(); break;
+               BUG();
        }
+       fb_alloc_cmap(&(info->cmap), 256, 0);
 
-       memcpy(&e1355_dispsw, d, sizeof *d);
+       panel = epson1355_read_reg(par, REG_PANEL_TYPE);
+       is_color = (panel & 0x04) != 0;
+       is_dual = (panel & 0x02) != 0;
+       is_tft = (panel & 0x01) != 0;
+       crt_enabled = (display & 0x02) != 0;
+       lcd_enabled = (display & 0x01) != 0;
+       lcd_bpp = epson1355_width_tab[is_tft][(panel >> 4) & 3];
 
-       /* reading is terribly slow for us */
-#if 0 /* XXX: need to work out why this doesn't work */
-       e1355_dispsw.bmove = fbcon_redraw_bmove;
-#endif
-}
+       xres = (epson1355_read_reg(par, REG_HORZ_DISP_WIDTH) + 1) * 8;
+       yres = (epson1355_read_reg16(par, REG_VERT_DISP_HEIGHT0) + 1) *
+           ((is_dual && !crt_enabled) ? 2 : 1);
+       offset = epson1355_read_reg16(par, REG_MEM_ADDR_OFFSET0) & 0x7ff;
+       xres_virtual = offset * 16 / bpp;
+       yres_virtual = fix->smem_len / (offset * 2);
 
-/* ------------ Interfaces to hardware functions ------------ */
+       var->xres = xres;
+       var->yres = yres;
+       var->xres_virtual = xres_virtual;
+       var->yres_virtual = yres_virtual;
+       var->xoffset = var->yoffset = 0;
 
+       fix->line_length = offset * 2;
 
-struct fbgen_hwswitch e1355_switch = {
-       .detect =       e1355_detect,
-       .encode_fix =   e1355_encode_fix,
-       .decode_var =   e1355_decode_var,
-       .encode_var =   e1355_encode_var,
-       .get_par =      e1355_get_par,
-       .set_par =      e1355_set_par,
-       .getcolreg =    e1355_getcolreg,
-       .pan_display =  e1355_pan_display,
-       .blank =        e1355_blank,
-       .set_disp =     e1355_set_disp,
-};
+       fix->xpanstep = 0;      /* no pan yet */
+       fix->ypanstep = 1;
+       fix->ywrapstep = 0;
+       fix->accel = FB_ACCEL_NONE;
+
+       var->grayscale = !is_color;
 
+#ifdef DEBUG
+       printk(KERN_INFO
+              "epson1355fb: xres=%d, yres=%d, "
+              "is_color=%d, is_dual=%d, is_tft=%d\n",
+              xres, yres, is_color, is_dual, is_tft);
+       printk(KERN_INFO
+              "epson1355fb: bpp=%d, lcd_bpp=%d, "
+              "crt_enabled=%d, lcd_enabled=%d\n",
+              bpp, lcd_bpp, crt_enabled, lcd_enabled);
+#endif
+}
 
-/* ------------ Hardware Independent Functions ------------ */
 
+static void clearfb16(struct fb_info *info)
+{
+       u16 *dst = (u16 *) info->screen_base;
+       unsigned long n = info->fix.smem_len;
 
-static struct fb_ops e1355fb_ops = {
-       .owner =        THIS_MODULE,
-       .fb_get_fix =   fbgen_get_fix,
-       .fb_get_var =   fbgen_get_var,
-       .fb_set_var =   fbgen_set_var,
-       .fb_get_cmap =  fbgen_get_cmap,
-       .fb_set_cmap =  gen_set_cmap,
-       .fb_setcolreg = e1355fb_setcolreg,
-       .fb_pan_display =fbgen_pan_display,
-       .fb_blank =     fbgen_blank,
-};
+       while (n > 1) {
+               fb_writew(0, dst);
+               dst++, n -= 2;
+       }
 
-static struct e1355fb_info fb_info;
+       if (n)
+               fb_writeb(0, dst);
+}
 
-int __init e1355fb_setup(char *str)
+static void epson1355fb_platform_release(struct device *device)
 {
-       return 0;
 }
 
-int __init e1355fb_init(void)
+static int epson1355fb_remove(struct device *device)
 {
-       fb_info.gen.fbhw = &e1355_switch;
-       fb_info.gen.fbhw->detect();
-       strcpy(fb_info.gen.info.modename, "SED1355");
-       fb_info.gen.info.changevar = NULL;
-       fb_info.gen.info.fbops = &e1355fb_ops;
-       fb_info.gen.info.screen_base = (void *)E1355_FB_BASE;
-       fb_info.gen.currcon = -1;
-       fb_info.gen.info.disp = &disp;
-       fb_info.gen.parsize = sizeof(struct e1355_par);
-       fb_info.gen.info.switch_con = &fbgen_switch;
-       fb_info.gen.info.updatevar = &fbgen_update_var;
-       fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
-       /* This should give a reasonable default video mode */
-       fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
-       fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
-       fbgen_set_disp(-1, &fb_info.gen);
-       if (disp.var.bits_per_pixel > 1) 
-               do_install_cmap(0, &fb_info.gen);
-       if (register_framebuffer(&fb_info.gen.info) < 0)
-               return -EINVAL;
-       printk(KERN_INFO "fb%d: %s frame buffer device\n", fb_info.gen.info.node,
-              fb_info.gen.info.modename);
+       struct fb_info *info = dev_get_drvdata(device);
+       struct epson1355_par *par = info->par;
+
+       backlight_enable(0);
+       if (par) {
+               lcd_enable(par, 0);
+               if (par && par->reg_addr)
+                       iounmap((void *) par->reg_addr);
+       }
 
+       if (info) {
+               fb_dealloc_cmap(&info->cmap);
+               if (info->screen_base)
+                       iounmap(info->screen_base);
+               framebuffer_release(info);
+       }
+       release_mem_region(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN);
+       release_mem_region(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN);
        return 0;
 }
 
+int __init epson1355fb_probe(struct device *device)
+{
+       struct platform_device *dev = to_platform_device(device);
+       struct epson1355_par *default_par;
+       struct fb_info *info;
+       u8 revision;
+       int rc = 0;
+
+       if (!request_mem_region(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN, "S1D13505 registers")) {
+               printk(KERN_ERR "epson1355fb: unable to reserve "
+                      "registers at 0x%0x\n", EPSON1355FB_REGS_PHYS);
+               rc = -EBUSY;
+               goto bail;
+       }
+
+       if (!request_mem_region(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN,
+                               "S1D13505 framebuffer")) {
+               printk(KERN_ERR "epson1355fb: unable to reserve "
+                      "framebuffer at 0x%0x\n", EPSON1355FB_FB_PHYS);
+               rc = -EBUSY;
+               goto bail;
+       }
 
-    /*
-     *  Cleanup
-     */
+       info = framebuffer_alloc(sizeof(struct epson1355_par) + sizeof(u32) * 256, &dev->dev);
+       if (!info)
+               rc = -ENOMEM;
+               goto bail;
+
+       default_par = info->par;
+       default_par->reg_addr = (unsigned long) ioremap(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN);
+       if (!default_par->reg_addr) {
+               printk(KERN_ERR "epson1355fb: unable to map registers\n");
+               rc = -ENOMEM;
+               goto bail;
+       }
+       info->pseudo_palette = (void *)(default_par + 1);
 
-void e1355fb_cleanup(struct fb_info *info)
-{
+       info->screen_base = ioremap(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN);
+       if (!info->screen_base) {
+               printk(KERN_ERR "epson1355fb: unable to map framebuffer\n");
+               rc = -ENOMEM;
+               goto bail;
+       }
+
+       revision = epson1355_read_reg(default_par, REG_REVISION_CODE);
+       if ((revision >> 2) != 3) {
+               printk(KERN_INFO "epson1355fb: epson1355 not found\n");
+               rc = -ENODEV;
+               goto bail;
+       }
+
+       info->fix.mmio_start = EPSON1355FB_REGS_PHYS;
+       info->fix.mmio_len = EPSON1355FB_REGS_LEN;
+       info->fix.smem_start = EPSON1355FB_FB_PHYS;
+       info->fix.smem_len = get_fb_size(info);
+
+       printk(KERN_INFO "epson1355fb: regs mapped at 0x%lx, fb %d KiB mapped at 0x%p\n",
+              default_par->reg_addr, info->fix.smem_len / 1024, info->screen_base);
+
+       strcpy(info->fix.id, "S1D13505");
+       info->par = default_par;
+       info->fbops = &epson1355fb_fbops;
+       info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+       /* we expect the boot loader to have initialized the chip
+          with appropriate parameters from which we can determinte
+          the flavor of lcd panel attached */
+       fetch_hw_state(info, default_par);
+
+       /* turn this puppy on ... */
+       clearfb16(info);
+       backlight_enable(1);
+       lcd_enable(default_par, 1);
+
+       if (register_framebuffer(info) < 0) {
+               rc = -EINVAL;
+               goto bail;
+       }
        /*
-        *  If your driver supports multiple boards, you should unregister and
-        *  clean up all instances.
+        * Our driver data.
         */
+       dev_set_drvdata(&dev->dev, info);
+
+       printk(KERN_INFO "fb%d: %s frame buffer device\n",
+              info->node, info->fix.id);
+
+       return 0;
+
+      bail:
+       epson1355fb_remove(device);
+       return rc;
+}
+
+static struct device_driver epson1355fb_driver = {
+       .name   = "epson1355fb",
+       .bus    = &platform_bus_type,
+       .probe  = epson1355fb_probe,
+       .remove = epson1355fb_remove,
+};
+
+static struct platform_device epson1355fb_device = {
+       .name   = "epson1355fb",
+       .id     = 0,
+       .dev    = {
+               .release = epson1355fb_platform_release,
+       }
+};
+
+int __init epson1355fb_init(void)
+{
+       int ret = 0;
+
+       if (fb_get_options("epson1355fb", NULL))
+               return -ENODEV;
+
+       ret = driver_register(&epson1355fb_driver);
+       if (!ret) {
+               ret = platform_device_register(&epson1355fb_device);
+               if (ret)
+                       driver_unregister(&epson1355fb_driver);
+       }
+       return ret;
+}
+
+module_init(epson1355fb_init);
        
-       unregister_framebuffer(info);
-       /* ... */
+#ifdef MODULE
+static void __exit epson1355fb_exit(void)
+{
+       platform_device_unregister(&epson1355fb_device);
+       driver_unregister(&epson1355fb_driver);
 }
 
+/* ------------------------------------------------------------------------- */
+
+module_exit(epson1355fb_exit);
+#endif
+
+MODULE_AUTHOR("Christopher Hoover <ch@hpl.hp.com>");
+MODULE_DESCRIPTION("Framebuffer driver for Epson S1D13505");
 MODULE_LICENSE("GPL");
index a28a66e..fb2f225 100644 (file)
 #define DPRINTK(fmt, args...)
 #endif
 
+#define FBMON_FIX_HEADER 1
+
+#ifdef CONFIG_FB_MODE_HELPERS
+struct broken_edid {
+       u8  manufacturer[4];
+       u32 model;
+       u32 fix;
+};
+
+static struct broken_edid brokendb[] = {
+       /* DEC FR-PCXAV-YZ */
+       { .manufacturer = "DEC",
+         .model        = 0x073a,
+         .fix          = FBMON_FIX_HEADER,
+       },
+};
 
 const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0x00
@@ -65,30 +81,77 @@ static void copy_string(unsigned char *c, unsigned char *s)
   while (i-- && (*--s == 0x20)) *s = 0;
 }
 
+static void fix_broken_edid(unsigned char *edid)
+{
+       unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
+       u32 model, i;
+
+       manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
+       manufacturer[1] = ((block[0] & 0x03) << 3) +
+               ((block[1] & 0xe0) >> 5) + '@';
+       manufacturer[2] = (block[1] & 0x1f) + '@';
+       manufacturer[3] = 0;
+       model = block[2] + (block[3] << 8);
+
+       for (i = 0; i < ARRAY_SIZE(brokendb); i++) {
+               if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) &&
+                       brokendb[i].model == model) {
+                       switch (brokendb[i].fix) {
+                       case FBMON_FIX_HEADER:
+                               printk("fbmon: The EDID header of "
+                                      "Manufacturer: %s Model: 0x%x is "
+                                      "known to be broken,\n"
+                                      "fbmon: trying a header "
+                                      "reconstruct\n", manufacturer, model);
+                               memcpy(edid, edid_v1_header, 8);
+                               break;
+                       }
+               }
+       }
+}
+
 static int edid_checksum(unsigned char *edid)
 {
-       unsigned char i, csum = 0;
+       unsigned char i, csum = 0, all_null = 0;
 
-       for (i = 0; i < EDID_LENGTH; i++)
+       for (i = 0; i < EDID_LENGTH; i++) {
                csum += edid[i];
+               all_null |= edid[i];
+       }
 
-       if (csum == 0x00) {
+       if (csum == 0x00 && all_null) {
                /* checksum passed, everything's good */
                return 1;
-       } else {
+       }
+
+       fix_broken_edid(edid);
+       csum = all_null = 0;
+       for (i = 0; i < EDID_LENGTH; i++) {
+               csum += edid[i];
+               all_null |= edid[i];
+       }
+       if (csum != 0x00 || !all_null) {
                printk("EDID checksum failed, aborting\n");
                return 0;
        }
+       return 1;
 }
 
 static int edid_check_header(unsigned char *edid)
 {
-       if ((edid[0] != 0x00) || (edid[1] != 0xff) || (edid[2] != 0xff) ||
-           (edid[3] != 0xff) || (edid[4] != 0xff) || (edid[5] != 0xff) ||
-           (edid[6] != 0xff)) {
-               printk
-                   ("EDID header doesn't match EDID v1 header, aborting\n");
-               return 0;
+       int i, fix = 0;
+
+       for (i = 0; i < 8; i++) {
+               if (edid[i] != edid_v1_header[i])
+                       fix = 1;
+       }
+       if (!fix)
+               return 1;
+
+       fix_broken_edid(edid);
+       for (i = 0; i < 8; i++) {
+               if (edid[i] != edid_v1_header[i])
+                       return 0;
        }
        return 1;
 }
@@ -1094,6 +1157,36 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
        
        return 0;
 }
+#else
+int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
+{
+       return 1;
+}
+void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+       specs = NULL;
+}
+char *get_EDID_from_firmware(struct device *dev)
+{
+       return NULL;
+}
+struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
+{
+       return NULL;
+}
+void fb_destroy_modedb(struct fb_videomode *modedb)
+{
+}
+int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
+{
+       return 1;
+}
+int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
+               struct fb_info *info)
+{
+       return -EINVAL;
+}
+#endif /* CONFIG_FB_MODE_HELPERS */
        
 /*
  * fb_validate_mode - validates var against monitor capabilities
index 1f76131..349499e 100644 (file)
@@ -362,61 +362,6 @@ struct ffb_par {
        struct list_head        list;
 };
 
-#undef FFB_DO_DEBUG_LOG
-
-#ifdef FFB_DO_DEBUG_LOG
-#define FFB_DEBUG_LOG_ENTS     32
-static struct ffb_log {
-       int op;
-#define OP_FILLRECT    1
-#define OP_IMAGEBLIT   2
-
-       int depth, x, y, w, h;
-} ffb_debug_log[FFB_DEBUG_LOG_ENTS];
-static int ffb_debug_log_ent;
-
-static void ffb_do_log(unsigned long unused)
-{
-       int i;
-
-       for (i = 0; i < FFB_DEBUG_LOG_ENTS; i++) {
-               struct ffb_log *p = &ffb_debug_log[i];
-
-               printk("FFB_LOG: OP[%s] depth(%d) x(%d) y(%d) w(%d) h(%d)\n",
-                      (p->op == OP_FILLRECT ? "FILLRECT" : "IMAGEBLIT"),
-                      p->depth, p->x, p->y, p->w, p->h);
-       }
-}
-static struct timer_list ffb_log_timer =
-       TIMER_INITIALIZER(ffb_do_log, 0, 0);
-
-static void ffb_log(int op, int depth, int x, int y, int w, int h)
-{
-       if (ffb_debug_log_ent < FFB_DEBUG_LOG_ENTS) {
-               struct ffb_log *p = &ffb_debug_log[ffb_debug_log_ent];
-
-               if (ffb_debug_log_ent != 0 &&
-                   p[-1].op == op && p[-1].depth == depth)
-                       return;
-               p->op = op;
-               p->depth = depth;
-               p->x = x;
-               p->y = y;
-               p->w = w;
-               p->h = h;
-
-               if (++ffb_debug_log_ent == FFB_DEBUG_LOG_ENTS) {
-                       ffb_log_timer.expires = jiffies + 2;
-                       add_timer(&ffb_log_timer);
-               }
-       }
-}
-#else
-#define ffb_log(a,b,c,d,e,f)   do { } while(0)
-#endif
-
-#undef FORCE_WAIT_EVERY_ROP
-
 static void FFBFifo(struct ffb_par *par, int n)
 {
        struct ffb_fbc *fbc;
@@ -479,7 +424,7 @@ static void ffb_switch_from_graph(struct ffb_par *par)
        upa_writel(0x2000707f, &fbc->fbc);
        upa_writel(par->rop_cache, &fbc->rop);
        upa_writel(0xffffffff, &fbc->pmask);
-       upa_writel((0 << 16) | (32 << 0), &fbc->fontinc);
+       upa_writel((1 << 16) | (0 << 0), &fbc->fontinc);
        upa_writel(par->fg_cache, &fbc->fg);
        upa_writel(par->bg_cache, &fbc->bg);
        FFBWait(par);
@@ -526,8 +471,6 @@ static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
        if (rect->rop != ROP_COPY && rect->rop != ROP_XOR)
                BUG();
 
-       ffb_log(OP_FILLRECT, 0, rect->dx, rect->dy, rect->width, rect->height);
-
        fg = ((u32 *)info->pseudo_palette)[rect->color];
 
        spin_lock_irqsave(&par->lock, flags);
@@ -548,9 +491,6 @@ static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
        upa_writel(rect->dx, &fbc->bx);
        upa_writel(rect->height, &fbc->bh);
        upa_writel(rect->width, &fbc->bw);
-#ifdef FORCE_WAIT_EVERY_ROP
-       FFBWait(par);
-#endif
 
        spin_unlock_irqrestore(&par->lock, flags);
 }
@@ -572,7 +512,7 @@ ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
        unsigned long flags;
 
        if (area->dx != area->sx ||
-           area->dy == area->dy) {
+           area->dy == area->sy) {
                cfb_copyarea(info, area);
                return;
        }
@@ -609,10 +549,7 @@ static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
        unsigned long flags;
        u32 fg, bg, xy;
        u64 fgbg;
-       int i, width;
-
-       ffb_log(OP_IMAGEBLIT, image->depth,
-               image->dx, image->dy, image->width, image->height);
+       int i, width, stride;
 
        if (image->depth > 1) {
                cfb_imageblit(info, image);
@@ -623,6 +560,8 @@ static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
        bg = ((u32 *)info->pseudo_palette)[image->bg_color];
        fgbg = ((u64) fg << 32) | (u64) bg;
        xy = (image->dy << 16) | image->dx;
+       width = image->width;
+       stride = ((width + 7) >> 3);
 
        spin_lock_irqsave(&par->lock, flags);
 
@@ -632,55 +571,49 @@ static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
                *(u64 *)&par->fg_cache = fgbg;
        }
 
-       ffb_rop(par, FFB_ROP_NEW);
+       if (width >= 32) {
+               FFBFifo(par, 1);
+               upa_writel(32, &fbc->fontw);
+       }
 
-       for (i = 0; i < image->height; i++) {
-               width = image->width;
+       while (width >= 32) {
+               const u8 *next_data = data + 4;
 
                FFBFifo(par, 1);
                upa_writel(xy, &fbc->fontxy);
-               xy += (1 << 16);
-
-               while (width >= 32) {
-                       u32 val;
-
-                       FFBFifo(par, 2);
-                       upa_writel(32, &fbc->fontw);
-
-                       val = ((u32)data[0] << 24) |
-                             ((u32)data[1] << 16) |
-                             ((u32)data[2] <<  8) |
-                             ((u32)data[3] <<  0);
+               xy += (32 << 0);
+
+               for (i = 0; i < image->height; i++) {
+                       u32 val = (((u32)data[0] << 24) |
+                                  ((u32)data[1] << 16) |
+                                  ((u32)data[2] <<  8) |
+                                  ((u32)data[3] <<  0));
+                       FFBFifo(par, 1);
                        upa_writel(val, &fbc->font);
 
-                       data += 4;
-                       width -= 32;
+                       data += stride;
                }
 
-               if (width) {
-                       u32 val;
-
-                       FFBFifo(par, 2);
-                       upa_writel(width, &fbc->fontw);
-                       if (width <= 8) {
-                               val = (u32) data[0] << 24;
-                               data += 1;
-                       } else if (width <= 16) {
-                               val = ((u32) data[0] << 24) |
-                                     ((u32) data[1] << 16);
-                               data += 2;
-                       } else {
-                               val = ((u32) data[0] << 24) |
-                                     ((u32) data[1] << 16) |
-                                     ((u32) data[2] <<  8);
-                               data += 3;
-                       }
+               data = next_data;
+               width -= 32;
+       }
+
+       if (width) {
+               FFBFifo(par, 2);
+               upa_writel(width, &fbc->fontw);
+               upa_writel(xy, &fbc->fontxy);
+
+               for (i = 0; i < image->height; i++) {
+                       u32 val = (((u32)data[0] << 24) |
+                                  ((u32)data[1] << 16) |
+                                  ((u32)data[2] <<  8) |
+                                  ((u32)data[3] <<  0));
+                       FFBFifo(par, 1);
                        upa_writel(val, &fbc->font);
+
+                       data += stride;
                }
        }
-#ifdef FORCE_WAIT_EVERY_ROP
-       FFBWait(par);
-#endif
 
        spin_unlock_irqrestore(&par->lock, flags);
 }
@@ -1027,7 +960,13 @@ static void ffb_init_one(int node, int parent)
        all->par.prom_node = node;
        all->par.prom_parent_node = parent;
 
-       all->info.flags = FBINFO_FLAG_DEFAULT;
+       /* Don't mention copyarea, so SCROLL_REDRAW is always
+        * used.  It is the fastest on this chip.
+        */
+       all->info.flags = (FBINFO_DEFAULT |
+                          /* FBINFO_HWACCEL_COPYAREA | */
+                          FBINFO_HWACCEL_FILLRECT |
+                          FBINFO_HWACCEL_IMAGEBLIT);
        all->info.fbops = &ffb_ops;
        all->info.screen_base = (char *) all->par.physbase + FFB_DFB24_POFF;
        all->info.currcon = -1;
@@ -1110,6 +1049,9 @@ int __init ffb_init(void)
 {
        int root;
 
+       if (fb_get_options("ffb", NULL))
+               return -ENODEV;
+
        ffb_scan_siblings(prom_root_node);
 
        root = prom_getchild(prom_root_node);
@@ -1140,8 +1082,9 @@ ffb_setup(char *arg)
        return 0;
 }
 
-#ifdef MODULE
 module_init(ffb_init);
+
+#ifdef MODULE
 module_exit(ffb_exit);
 #endif
 
index 9bd2022..3adb65d 100644 (file)
@@ -280,7 +280,7 @@ static int __devinit fm2fb_probe(struct zorro_dev *z,
        info->pseudo_palette = info->par;
        info->par = NULL;
        info->fix = fb_fix;
-       info->flags = FBINFO_FLAG_DEFAULT;
+       info->flags = FBINFO_DEFAULT;
 
        if (register_framebuffer(info) < 0) {
                fb_dealloc_cmap(&info->cmap);
@@ -292,12 +292,18 @@ static int __devinit fm2fb_probe(struct zorro_dev *z,
        return 0;
 }
 
+int __init fm2fb_setup(char *options);
+
 int __init fm2fb_init(void)
 {
+       char *option = NULL;
+
+       if (fb_get_options("fm2fb", &option))
+               return -ENODEV;
+       fm2fb_setup(option);
        return zorro_register_driver(&fm2fb_driver);
 }
 
-int __init fm2fb_setup(char *options)
 {
        char *this_opt;
 
@@ -313,4 +319,5 @@ int __init fm2fb_setup(char *options)
        return 0;
 }
 
+module_init(fm2fb_init);
 MODULE_LICENSE("GPL");
index a869bf1..5eed5bd 100644 (file)
@@ -202,6 +202,9 @@ int __init g364fb_init(void)
            (volatile unsigned int *) CURS_PAL_REG;
        int mem, i, j;
 
+       if (fb_get_options("g364fb", NULL))
+               return -ENODEV;
+
        /* TBD: G364 detection */
 
        /* get the resolution set by ARC console */
@@ -241,7 +244,7 @@ int __init g364fb_init(void)
        fb_info.screen_base = (char *) G364_MEM_BASE;   /* virtual kernel address */
        fb_info.var = fb_var;
        fb_info.fix = fb_fix;
-       fb_info.flags = FBINFO_FLAG_DEFAULT;
+       fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
        fb_alloc_cmap(&fb_info.cmap, 255, 0);
 
@@ -250,4 +253,5 @@ int __init g364fb_init(void)
        return 0;
 }
 
+module_init(g364fb_init);
 MODULE_LICENSE("GPL");
index 2afc414..1dfc1d6 100644 (file)
@@ -1083,6 +1083,14 @@ int __init gbefb_init(void)
 {
        int i, ret = 0;
 
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("gbefb", &option))
+               return -ENODEV;
+       gbefb_setup(options);
+#endif
+
        if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
                printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
                return -EBUSY;
@@ -1135,7 +1143,7 @@ int __init gbefb_init(void)
        fb_info.currcon = -1;
        fb_info.fbops = &gbefb_ops;
        fb_info.pseudo_palette = pseudo_palette;
-       fb_info.flags = FBINFO_FLAG_DEFAULT;
+       fb_info.flags = FBINFO_DEFAULT;
        fb_info.screen_base = gbe_mem;
        fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
@@ -1192,8 +1200,9 @@ void __exit gbefb_exit(void)
        iounmap(gbe);
 }
 
-#ifdef MODULE
 module_init(gbefb_init);
+
+#ifdef MODULE
 module_exit(gbefb_exit);
 #endif
 
index 90439cb..9d2ea3b 100644 (file)
@@ -270,6 +270,9 @@ int __init hitfb_init(void)
        unsigned short lcdclor, ldr3, ldvndr;
        int size;
 
+       if (fb_get_options("hitfb", NULL))
+               return -ENODEV;
+
        hitfb_fix.smem_start = CONFIG_HD64461_IOBASE + 0x02000000;
        hitfb_fix.smem_len = (MACH_HP690) ? 1024 * 1024 : 512 * 1024;
 
@@ -321,7 +324,7 @@ int __init hitfb_init(void)
        fb_info.var = hitfb_var;
        fb_info.fix = hitfb_fix;
        fb_info.pseudo_palette = pseudo_palette;
-       fb_info.flags = FBINFO_FLAG_DEFAULT;
+       fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
        fb_info.screen_base = (void *)hitfb_fix.smem_start;
 
@@ -341,8 +344,9 @@ static void __exit hitfb_exit(void)
        unregister_framebuffer(&fb_info);
 }
 
-#ifdef MODULE
 module_init(hitfb_init);
+
+#ifdef MODULE
 module_exit(hitfb_exit);
 #endif
 
index bfbdbab..9405d71 100644 (file)
@@ -115,6 +115,9 @@ int __init hpfb_init_one(unsigned long base)
 {
        unsigned long fboff;
 
+       if (fb_get_options("hpfb", NULL))
+               return -ENODEV;
+
        fboff = (in_8(base + TOPCAT_FBOMSB) << 8) | in_8(base + TOPCAT_FBOLSB);
 
        hpfb_fix.smem_start = 0xf0000000 | (in_8(base + fboff) << 16);
@@ -151,7 +154,7 @@ int __init hpfb_init_one(unsigned long base)
         *      Let there be consoles..
         */
        fb_info.fbops = &hpfb_ops;
-       fb_info.flags = FBINFO_FLAG_DEFAULT;
+       fb_info.flags = FBINFO_DEFAULT;
        fb_info.var   = hpfb_defined;
        fb_info.fix   = hpfb_fix;
        fb_info.screen_base = (char *)hpfb_fix.smem_start;      // FIXME
@@ -211,4 +214,5 @@ int __init hpfb_init(void)
        return 0;
 }
 
+module_init(hpfb_init);
 MODULE_LICENSE("GPL");
index ffeaef8..27fa703 100644 (file)
@@ -193,19 +193,19 @@ struct mode_registers std_modes[] = {
 
 void round_off_xres(u32 *xres) 
 {
-       if (*xres < 800) 
+       if (*xres <= 640)
                *xres = 640;
-       if (*xres < 1024 && *xres >= 800) 
+       else if (*xres <= 800)
                *xres = 800;
-       if (*xres < 1152 && *xres >= 1024)
+       else if (*xres <= 1024)
                *xres = 1024;
-       if (*xres < 1280 && *xres >= 1152)
+       else if (*xres <= 1152)
                *xres = 1152;
-       if (*xres < 1600 && *xres >= 1280)
+       else if (*xres <= 1280)
                *xres = 1280;
-       if (*xres >= 1600)
+       else
                *xres = 1600;
-}              
+}
 
 inline void round_off_yres(u32 *xres, u32 *yres)
 {
index 2633664..6acde25 100644 (file)
@@ -1353,11 +1353,15 @@ static int i810fb_set_par(struct fb_info *info)
 
        encode_fix(&info->fix, info);
 
-       if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) 
+       if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) {
+               info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+               FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+               FBINFO_HWACCEL_IMAGEBLIT;
                info->pixmap.scan_align = 2;
-       else 
+       } else {
                info->pixmap.scan_align = 1;
-       
+               info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+       }
        return 0;
 }
 
@@ -1388,16 +1392,17 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
        struct i810fb_par *par = (struct i810fb_par *)info->par;
        u8 *mmio = par->mmio_start_virtual;     
-       u8 data[64 * 8];
-       
+
        if (!info->var.accel_flags || par->dev_flags & LOCKUP) 
                return soft_cursor(info, cursor);
 
        if (cursor->image.width > 64 || cursor->image.height > 64)
                return -ENXIO;
 
-       if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical)
+       if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical) {
                i810_init_cursor(par);
+               cursor->set |= FB_CUR_SETALL;
+       }
 
        i810_enable_cursor(mmio, OFF);
 
@@ -1409,50 +1414,56 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 
                info->cursor.image.dx = cursor->image.dx;
                info->cursor.image.dy = cursor->image.dy;
-               
-               tmp = cursor->image.dx - info->var.xoffset;
-               tmp |= (cursor->image.dy - info->var.yoffset) << 16;
-           
+               tmp = (info->cursor.image.dx - info->var.xoffset) & 0xffff;
+               tmp |= (info->cursor.image.dy - info->var.yoffset) << 16;
                i810_writel(CURPOS, mmio, tmp);
        }
 
        if (cursor->set & FB_CUR_SETSIZE) {
+               i810_reset_cursor_image(par);
                info->cursor.image.height = cursor->image.height;
                info->cursor.image.width = cursor->image.width;
-               i810_reset_cursor_image(par);
        }
 
        if (cursor->set & FB_CUR_SETCMAP) {
-               info->cursor.image.fg_color = cursor->image.fg_color;
-               info->cursor.image.bg_color = cursor->image.bg_color;
                i810_load_cursor_colors(cursor->image.fg_color,
                                        cursor->image.bg_color,
                                        info);
+               info->cursor.image.fg_color = cursor->image.fg_color;
+               info->cursor.image.bg_color = cursor->image.bg_color;
+
        }
 
-       if (cursor->set & FB_CUR_SETSHAPE) {
+       if (cursor->set & (FB_CUR_SETSHAPE)) {
                int size = ((info->cursor.image.width + 7) >> 3) * 
-                            info->cursor.image.height;
+                       info->cursor.image.height;
                int i;
+               u8 *data = kmalloc(64 * 8, GFP_KERNEL);
+
+               if (data == NULL)
+                       return -ENOMEM;
+               info->cursor.image.data = cursor->image.data;
 
                switch (info->cursor.rop) {
                case ROP_XOR:
                        for (i = 0; i < size; i++)
-                               data[i] = cursor->image.data[i] ^ info->cursor.mask[i]; 
+                               data[i] = info->cursor.image.data[i] ^ info->cursor.mask[i];
                        break;
                case ROP_COPY:
                default:
                        for (i = 0; i < size; i++)
-                               data[i] = cursor->image.data[i] & info->cursor.mask[i]; 
+                               data[i] = info->cursor.image.data[i] & info->cursor.mask[i];
                        break;
                }
                i810_load_cursor_image(info->cursor.image.width, 
                                       info->cursor.image.height, data,
                                       par);
+               kfree(data);
        }
 
        if (info->cursor.enable)
                i810_enable_cursor(mmio, ON);
+
        return 0;
 }
 
@@ -1641,9 +1652,11 @@ static void __devinit i810_init_monspecs(struct fb_info *info)
                hsync1 = HFMIN;
        if (!hsync2) 
                hsync2 = HFMAX;
-       info->monspecs.hfmax = hsync2;
-       info->monspecs.hfmin = hsync1;
-       if (hsync2 < hsync1) 
+       if (!info->monspecs.hfmax)
+               info->monspecs.hfmax = hsync2;
+       if (!info->monspecs.hfmin)
+               info->monspecs.hfmin = hsync1;
+       if (hsync2 < hsync1)
                info->monspecs.hfmin = hsync2;
 
        if (!vsync1)
@@ -1652,8 +1665,10 @@ static void __devinit i810_init_monspecs(struct fb_info *info)
                vsync2 = VFMAX;
        if (IS_DVT && vsync1 < 60)
                vsync1 = 60;
-       info->monspecs.vfmax = vsync2;
-       info->monspecs.vfmin = vsync1;          
+       if (!info->monspecs.vfmax)
+               info->monspecs.vfmax = vsync2;
+       if (!info->monspecs.vfmin)
+               info->monspecs.vfmin = vsync1;
        if (vsync2 < vsync1) 
                info->monspecs.vfmin = vsync2;
 }
@@ -1724,6 +1739,7 @@ static void __devinit i810_init_device(struct i810fb_par *par)
        pci_read_config_byte(par->dev, 0x50, &reg);
        reg &= FREQ_MASK;
        par->mem_freq = (reg) ? 133 : 100;
+
 }
 
 static int __devinit 
@@ -1836,8 +1852,9 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
 {
        struct fb_info    *info;
        struct i810fb_par *par = NULL;
-       int err, vfreq, hfreq, pixclock;
+       int i, err = -1, vfreq, hfreq, pixclock;
 
+       i = 0;
        if (!(info = kmalloc(sizeof(struct fb_info), GFP_KERNEL))) {
                i810fb_release_resource(info, par);
                return -ENOMEM;
@@ -1879,8 +1896,6 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
        info->screen_base = par->fb.virtual;
        info->fbops = &par->i810fb_ops;
        info->pseudo_palette = par->pseudo_palette;
-       info->flags = FBINFO_FLAG_DEFAULT;
-       
        fb_alloc_cmap(&info->cmap, 256, 0);
 
        if ((err = info->fbops->fb_check_var(&info->var, info))) {
@@ -1957,8 +1972,7 @@ static void i810fb_release_resource(struct fb_info *info,
 
                kfree(par);
        }
-       if (info) 
-               kfree(info);
+       kfree(info);
 }
 
 static void __exit i810fb_remove_pci(struct pci_dev *dev)
@@ -1975,10 +1989,11 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev)
 #ifndef MODULE
 int __init i810fb_init(void)
 {
-       if (agp_intel_init()) {
-               printk("i810fb_init: cannot initialize intel agpgart\n");
+       char *option = NULL;
+
+       if (fb_get_options("i810fb", &option))
                return -ENODEV;
-       }
+       i810fb_setup(option);
 
        if (pci_register_driver(&i810fb_driver) > 0)
                return 0;
@@ -2054,9 +2069,8 @@ static void __exit i810fb_exit(void)
 {
        pci_unregister_driver(&i810fb_driver);
 }
-module_init(i810fb_init);
 module_exit(i810fb_exit);
 
 #endif /* MODULE */
 
-
+module_init(i810fb_init);
index 7e0353a..dd6b16c 100644 (file)
@@ -357,7 +357,7 @@ static int __init iga_init(struct fb_info *info, struct iga_par *par)
                 video_cmap_len = 256;
 
        info->fbops = &igafb_ops;
-       info->flags = FBINFO_FLAG_DEFAULT;
+       info->flags = FBINFO_DEFAULT;
 
        fb_alloc_cmap(&info->cmap, video_cmap_len, 0);
 
@@ -381,6 +381,9 @@ int __init igafb_init(void)
        unsigned long addr;
        int size, iga2000 = 0;
 
+       if (fb_get_options("igafb", NULL))
+               return -ENODEV;
+
         /* Do not attach when we have a serial console. */
         if (!con_is_present())
                 return -ENXIO;
@@ -572,4 +575,5 @@ int __init igafb_setup(char *options)
     return 0;
 }
 
+module_init(igafb_init);
 MODULE_LICENSE("GPL");
index 7547e89..99fb72a 100644 (file)
@@ -588,7 +588,7 @@ static void leo_init_one(struct sbus_dev *sdev)
                sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
                             sizeof(struct leo_cursor), "leolx cursor");
 
-       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
        all->info.fbops = &leo_ops;
        all->info.currcon = -1;
        all->info.par = &all->par;
@@ -626,6 +626,9 @@ int __init leo_init(void)
        struct sbus_bus *sbus;
        struct sbus_dev *sdev;
 
+       if (fb_get_options("leofb", NULL))
+               return -ENODEV;
+
        for_all_sbusdev(sdev, sbus) {
                if (!strcmp(sdev->prom_name, "leo"))
                        leo_init_one(sdev);
@@ -654,8 +657,8 @@ leo_setup(char *arg)
        return 0;
 }
 
-#ifdef MODULE
 module_init(leo_init);
+#ifdef MODULE
 module_exit(leo_exit);
 #endif
 
index 9baa40a..4945a4c 100644 (file)
@@ -614,6 +614,11 @@ void __init macfb_init(void)
 {
        int video_cmap_len, video_is_nubus = 0;
        struct nubus_dev* ndev = NULL;
+       char *option = NULL;
+
+       if (fb_get_options("macfb", &option))
+               return -ENODEV;
+       macfb_setup(option);
 
        if (!MACH_IS_MAC) 
                return;
@@ -660,6 +665,9 @@ void __init macfb_init(void)
        case 1:
                /* XXX: I think this will catch any program that tries
                   to do FBIO_PUTCMAP when the visual is monochrome */
+               macfb_defined.red.length = macfb_defined.bits_per_pixel;
+               macfb_defined.green.length = macfb_defined.bits_per_pixel;
+               macfb_defined.blue.length = macfb_defined.bits_per_pixel;
                video_cmap_len = 0;
                macfb_fix.visual = FB_VISUAL_MONO01;
                break;
@@ -947,7 +955,7 @@ void __init macfb_init(void)
        fb_info.var             = macfb_defined;
        fb_info.fix             = macfb_fix;
        fb_info.pseudo_palette  = pseudo_palette;
-       fb_info.flags           = FBINFO_FLAG_DEFAULT;
+       fb_info.flags           = FBINFO_DEFAULT;
 
        fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
        
@@ -958,4 +966,5 @@ void __init macfb_init(void)
               fb_info.node, fb_info.fix.id);
 }
 
+module_init(macfb_init);
 MODULE_LICENSE("GPL");
index fa14835..9d92dda 100644 (file)
@@ -27,7 +27,7 @@ struct matroxfb_dh_fb_info {
                unsigned int    len;
                              } mmio;
 
-       int                     interlaced:1;
+       unsigned int            interlaced:1;
 
        u_int32_t cmap[17];
 };
index 62f498e..76fd3a5 100644 (file)
@@ -391,7 +391,7 @@ void matroxfb_vgaHWrestore(WPMINFO2) {
        CRITEND
 }
 
-static void get_pins(unsigned char* pins, struct matrox_bios* bd) {
+static void get_pins(unsigned char __iomem* pins, struct matrox_bios* bd) {
        unsigned int b0 = readb(pins);
        
        if (b0 == 0x2E && readb(pins+1) == 0x41) {
@@ -427,7 +427,7 @@ static void get_pins(unsigned char* pins, struct matrox_bios* bd) {
        }
 }
 
-static void get_bios_version(unsigned char* vbios, struct matrox_bios* bd) {
+static void get_bios_version(unsigned char __iomem * vbios, struct matrox_bios* bd) {
        unsigned int pcir_offset;
        
        pcir_offset = readb(vbios + 24) | (readb(vbios + 25) << 8);
@@ -452,7 +452,7 @@ static void get_bios_version(unsigned char* vbios, struct matrox_bios* bd) {
        }
 }
 
-static void get_bios_output(unsigned char* vbios, struct matrox_bios* bd) {
+static void get_bios_output(unsigned char __iomem* vbios, struct matrox_bios* bd) {
        unsigned char b;
        
        b = readb(vbios + 0x7FF1);
@@ -462,7 +462,7 @@ static void get_bios_output(unsigned char* vbios, struct matrox_bios* bd) {
        bd->output.state = b;
 }
 
-static void get_bios_tvout(unsigned char* vbios, struct matrox_bios* bd) {
+static void get_bios_tvout(unsigned char __iomem* vbios, struct matrox_bios* bd) {
        unsigned int i;
        
        /* Check for 'IBM .*(V....TVO' string - it means TVO BIOS */
@@ -489,7 +489,7 @@ static void get_bios_tvout(unsigned char* vbios, struct matrox_bios* bd) {
        }
 }
 
-static void parse_bios(unsigned char* vbios, struct matrox_bios* bd) {
+static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
        unsigned int pins_offset;
        
        if (readb(vbios) != 0x55 || readb(vbios + 1) != 0xAA) {
@@ -738,7 +738,7 @@ void matroxfb_read_pins(WPMINFO2) {
        pci_write_config_dword(pdev, PCI_OPTION_REG, opt);
 #ifdef CONFIG_X86
        if (!ACCESS_FBINFO(bios).bios_valid) {
-               unsigned char* b;
+               unsigned char __iomem* b;
 
                b = ioremap(0x000C0000, 65536);
                if (!b) {
index 572ed22..46264bd 100644 (file)
@@ -126,6 +126,9 @@ int __init maxinefb_init(void)
        unsigned long fb_start;
        int i;
 
+       if (fb_get_options("maxinefb", NULL))
+               return -ENODEV;
+
        /* Validate we're on the proper machine type */
        if (mips_machtype != MACH_DS5000_XX) {
                return -EINVAL;
@@ -159,7 +162,7 @@ int __init maxinefb_init(void)
        fb_info.screen_base = (char *) maxinefb_fix.smem_start;
        fb_info.var = maxinefb_defined;
        fb_info.fix = maxinefb_fix;
-       fb_info.flags = FBINFO_FLAG_DEFAULT;
+       fb_info.flags = FBINFO_DEFAULT;
 
        fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
@@ -175,7 +178,7 @@ static void __exit maxinefb_exit(void)
 
 #ifdef MODULE
 MODULE_LICENSE("GPL");
-module_init(maxinefb_init);
 #endif
+module_init(maxinefb_init);
 module_exit(maxinefb_exit);
 
index 99c2e63..92a41f7 100644 (file)
@@ -28,7 +28,8 @@
 #include <linux/ioport.h>
 #include <asm/io.h>
 #include <asm/prom.h>
-#ifdef CONFIG_BOOTX_TEXT
+
+#ifdef CONFIG_PPC32
 #include <asm/bootx.h>
 #endif
 
@@ -70,7 +71,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                          u_int transp, struct fb_info *info);
 static int offb_blank(int blank, struct fb_info *info);
 
-#ifdef CONFIG_BOOTX_TEXT
+#ifdef CONFIG_PPC32
 extern boot_infos_t *boot_infos;
 #endif
 
@@ -245,18 +246,20 @@ static int offb_blank(int blank, struct fb_info *info)
 
 int __init offb_init(void)
 {
-       struct device_node *dp;
-       unsigned int dpy;
+       struct device_node *dp = NULL, *boot_disp = NULL;
 #if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32)
-       struct device_node *displays = find_type_devices("display");
        struct device_node *macos_display = NULL;
+#endif
+       if (fb_get_options("offb", NULL))
+               return -ENODEV;
 
+#if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32)
        /* If we're booted from BootX... */
-       if (prom_num_displays == 0 && boot_infos != 0) {
+       if (boot_infos != 0) {
                unsigned long addr =
                    (unsigned long) boot_infos->dispDeviceBase;
                /* find the device node corresponding to the macos display */
-               for (dp = displays; dp != NULL; dp = dp->next) {
+               while ((dp = of_find_node_by_type(dp, "display"))) {
                        int i;
                        /*
                         * Grrr...  It looks like the MacOS ATI driver
@@ -325,10 +328,19 @@ int __init offb_init(void)
        }
 #endif /* defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) */
 
-       for (dpy = 0; dpy < prom_num_displays; dpy++) {
-               if ((dp = find_path_device(prom_display_paths[dpy])))
+       for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+               if (get_property(dp, "linux,opened", NULL) &&
+                   get_property(dp, "linux,boot-display", NULL)) {
+                       boot_disp = dp;
                        offb_init_nodriver(dp);
+               }
        }
+       for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+               if (get_property(dp, "linux,opened", NULL) &&
+                   dp != boot_disp)
+                       offb_init_nodriver(dp);
+       }
+
        return 0;
 }
 
@@ -527,7 +539,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
        info->screen_base = ioremap(address, fix->smem_len);
        info->par = par;
        info->pseudo_palette = (void *) (info + 1);
-       info->flags = FBINFO_FLAG_DEFAULT;
+       info->flags = FBINFO_DEFAULT;
 
        fb_alloc_cmap(&info->cmap, 256, 0);
 
@@ -541,4 +553,5 @@ static void __init offb_init_fb(const char *name, const char *full_name,
               info->node, full_name);
 }
 
+module_init(offb_init);
 MODULE_LICENSE("GPL");
index 67b71d5..7fbbef4 100644 (file)
@@ -297,7 +297,7 @@ static void p9100_init_one(struct sbus_dev *sdev)
                sbus_ioremap(&sdev->resource[0], 0,
                             sizeof(struct p9100_regs), "p9100 regs");
 
-       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.flags = FBINFO_DEFAULT;
        all->info.fbops = &p9100_ops;
 #ifdef CONFIG_SPARC32
        all->info.screen_base = (char *)
@@ -340,6 +340,9 @@ int __init p9100_init(void)
        struct sbus_bus *sbus;
        struct sbus_dev *sdev;
 
+       if (fb_get_options("p9100fb", NULL))
+               return -ENODEV;
+
        for_all_sbusdev(sdev, sbus) {
                if (!strcmp(sdev->prom_name, "p9100"))
                        p9100_init_one(sdev);
@@ -368,8 +371,9 @@ p9100_setup(char *arg)
        return 0;
 }
 
-#ifdef MODULE
 module_init(p9100_init);
+
+#ifdef MODULE
 module_exit(p9100_exit);
 #endif
 
index feba14a..5ad8308 100644 (file)
@@ -311,7 +311,7 @@ static void __devinit platinum_init_info(struct fb_info *info, struct fb_info_pl
        /* Fill fb_info */
        info->fbops = &platinumfb_ops;
        info->pseudo_palette = pinfo->pseudo_palette;
-        info->flags = FBINFO_FLAG_DEFAULT;
+        info->flags = FBINFO_DEFAULT;
        info->screen_base = (char *) pinfo->frame_buffer + 0x20;
 
        fb_alloc_cmap(&info->cmap, 256, 0);
@@ -667,6 +667,13 @@ static struct of_platform_driver platinum_driver =
 
 int __init platinumfb_init(void)
 {
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("platinumfb", &option))
+               return -ENODEV;
+       platinumfb_setup(option);
+#endif
        of_register_driver(&platinum_driver);
 
        return 0;
@@ -679,8 +686,8 @@ void __exit platinumfb_exit(void)
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("framebuffer driver for Apple Platinum video");
+module_init(platinumfb_init);
 
 #ifdef MODULE
-module_init(platinumfb_init);
 module_exit(platinumfb_exit);
 #endif
index 45e3265..0d07707 100644 (file)
@@ -142,7 +142,7 @@ int __init pmagbafb_init_one(int slot)
        info->var = pmagbafb_defined;
        info->fix = pmagbafb_fix; 
        info->screen_base = pmagbafb_fix.smem_start;
-       info->flags = FBINFO_FLAG_DEFAULT;
+       info->flags = FBINFO_DEFAULT;
 
        fb_alloc_cmap(&fb_info.cmap, 256, 0);
        
@@ -160,6 +160,9 @@ int __init pmagbafb_init(void)
        int sid;
        int found = 0;
 
+       if (fb_get_options("pmagbafb", NULL))
+               return -ENODEV;
+
        if (TURBOCHANNEL) {
                while ((sid = search_tc_card("PMAG-BA")) >= 0) {
                        found = 1;
@@ -172,4 +175,5 @@ int __init pmagbafb_init(void)
        }
 }
 
+module_init(pmagbafb_init);
 MODULE_LICENSE("GPL");
index 16847d8..7847bed 100644 (file)
@@ -145,7 +145,7 @@ int __init pmagbbfb_init_one(int slot)
        info->var = pmagbbfb_defined;
        info->fix = pmagbbfb_fix;
        info->screen_base = pmagbbfb_fix.smem_start; 
-       info->flags = FBINFO_FLAG_DEFAULT;
+       info->flags = FBINFO_DEFAULT;
 
        fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
@@ -163,6 +163,9 @@ int __init pmagbbfb_init(void)
        int sid;
        int found = 0;
 
+       if (fb_get_options("pmagbbfb", NULL))
+               return -ENODEV;
+
        if (TURBOCHANNEL) {
                while ((sid = search_tc_card("PMAGB-BA")) >= 0) {
                        found = 1;
@@ -175,4 +178,5 @@ int __init pmagbbfb_init(void)
        }
 }
 
+module_init(pmagbbfb_init);
 MODULE_LICENSE("GPL");
index 5f63f10..a6ecf96 100644 (file)
@@ -795,7 +795,7 @@ static int __init pvr2fb_common_init(void)
        fb_info->fix            = pvr2_fix;
        fb_info->par            = currentpar;
        fb_info->pseudo_palette = (void *)(fb_info->par + 1);
-       fb_info->flags          = FBINFO_FLAG_DEFAULT;
+       fb_info->flags          = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
        if (video_output == VO_VGA)
                defmode = DEFMODE_VGA;
@@ -1057,6 +1057,13 @@ int __init pvr2fb_init(void)
        int i, ret = -ENODEV;
        int size;
 
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("pvr2fb", &option))
+               return -ENODEV;
+       pvr2fb_setup(option);
+#endif
        size = sizeof(struct fb_info) + sizeof(struct pvr2fb_par) + 16 * sizeof(u32);
 
        fb_info = kmalloc(size, GFP_KERNEL);
@@ -1108,9 +1115,7 @@ static void __exit pvr2fb_exit(void)
        kfree(fb_info);
 }
 
-#ifdef MODULE
 module_init(pvr2fb_init);
-#endif
 module_exit(pvr2fb_exit);
 
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
index 0a860dd..3e2bb2d 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/bitfield.h>
 #include <asm/arch/pxafb.h>
 
@@ -1040,7 +1041,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
        fbi->fb.var.vmode       = FB_VMODE_NONINTERLACED;
 
        fbi->fb.fbops           = &pxafb_ops;
-       fbi->fb.flags           = FBINFO_FLAG_DEFAULT;
+       fbi->fb.flags           = FBINFO_DEFAULT;
        fbi->fb.node            = -1;
        fbi->fb.currcon         = -1;
 
@@ -1359,11 +1360,6 @@ static struct device_driver pxafb_driver = {
 #endif
 };
 
-int __devinit pxafb_init(void)
-{
-       return driver_register(&pxafb_driver);
-}
-
 #ifndef MODULE
 int __devinit pxafb_setup(char *options)
 {
@@ -1373,12 +1369,25 @@ int __devinit pxafb_setup(char *options)
        return 0;
 }
 #else
-module_init(pxafb_init);
 # ifdef CONFIG_FB_PXA_PARAMETERS
 module_param_string(options, g_options, sizeof(g_options), 0);
 MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
 # endif
 #endif
 
+int __devinit pxafb_init(void)
+{
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("pxafb", &option))
+               return -ENODEV;
+       pxafb_setup(option);
+#endif
+       return driver_register(&pxafb_driver);
+}
+
+module_init(pxafb_init);
+
 MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
 MODULE_LICENSE("GPL");
index 3caf9f7..983b728 100644 (file)
@@ -205,6 +205,7 @@ unsigned long riva_get_memlen(struct riva_par *par)
                break;
        case NV_ARCH_10:
        case NV_ARCH_20:
+       case NV_ARCH_30:
                if(chipset == NV_CHIP_IGEFORCE2) {
 
                        dev = pci_find_slot(0, 1);
@@ -274,6 +275,7 @@ unsigned long riva_get_maxdclk(struct riva_par *par)
        case NV_ARCH_04:
        case NV_ARCH_10:
        case NV_ARCH_20:
+       case NV_ARCH_30:
                switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003) {
                case 3:
                        dclk = 800000;
index e54b015..707022a 100644 (file)
@@ -89,12 +89,14 @@ typedef unsigned int   U032;
 #define VGA_RD08(p,i)   NV_RD08(p,i)
 
 /*
- * Define supported architectures.
+ * Define different architectures.
  */
 #define NV_ARCH_03  0x03
 #define NV_ARCH_04  0x04
 #define NV_ARCH_10  0x10
 #define NV_ARCH_20  0x20
+#define NV_ARCH_30  0x30
+#define NV_ARCH_40  0x40
 
 /***************************************************************************\
 *                                                                           *
index a8dbc25..4b72002 100644 (file)
@@ -106,6 +106,7 @@ static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name)
        chan->algo.getsda               = riva_gpio_getsda;
        chan->algo.getscl               = riva_gpio_getscl;
        chan->algo.udelay               = 40;
+       chan->algo.mdelay               = 5;
        chan->algo.timeout              = 20;
        chan->algo.data                 = chan;
 
@@ -130,19 +131,34 @@ void riva_create_i2c_busses(struct riva_par *par)
        par->chan[1].par        = par;
        par->chan[2].par        = par;
 
-       switch (par->riva.Architecture) {
-#if 0          /* no support yet for other nVidia chipsets */
+       par->bus = 0;
+
+       switch ((par->pdev->device >> 4) & 0xff) {
+       case 0x17:
+       case 0x18:
+       case 0x25:
+       case 0x28:
+       case 0x30:
+       case 0x31:
+       case 0x32:
+       case 0x33:
+       case 0x34:
                par->chan[2].ddc_base   = 0x50;
-               riva_setup_i2c_bus(&par->chan[2], "BUS2");
-#endif
-       case NV_ARCH_10:
-       case NV_ARCH_20:
-       case NV_ARCH_04:
+               par->bus++;
+               riva_setup_i2c_bus(&par->chan[2], "BUS3");
+       case 0x04:
+       case 0x05:
+       case 0x10:
+       case 0x11:
+       case 0x15:
+       case 0x20:
                par->chan[1].ddc_base   = 0x36;
-               riva_setup_i2c_bus(&par->chan[1], "BUS1");
-       case NV_ARCH_03:
+               par->bus++;
+               riva_setup_i2c_bus(&par->chan[1], "BUS2");
+       case 0x03:
                par->chan[0].ddc_base   = 0x3e;
-               riva_setup_i2c_bus(&par->chan[0], "BUS0");
+               par->bus++;
+               riva_setup_i2c_bus(&par->chan[0], "BUS1");
        }
 }
 
index 136c9d8..4fc5482 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/mtrr.h>
 
 #define INCLUDE_TIMING_TABLE_DATA
-#define DBE_REG_BASE default_par.regs
+#define DBE_REG_BASE par->regs
 #include <video/sgivw.h>
 
 struct sgivw_par {
@@ -44,9 +44,6 @@ struct sgivw_par {
 extern unsigned long sgivwfb_mem_phys;
 extern unsigned long sgivwfb_mem_size;
 
-static struct sgivw_par default_par;
-static u32 pseudo_palette[17];
-static struct fb_info fb_info;
 static int ypan = 0;
 static int ywrap = 0;
 
@@ -162,7 +159,7 @@ static unsigned long get_line_length(int xres_virtual, int bpp)
  *              console.
  */
 
-static void dbe_TurnOffDma(void)
+static void dbe_TurnOffDma(struct sgivw_par *par)
 {
        unsigned int readVal;
        int i;
@@ -367,7 +364,7 @@ static int sgivwfb_check_var(struct fb_var_screeninfo *var,
 /*
  *  Setup flatpanel related registers.
  */
-static void sgivwfb_setup_flatpanel(struct dbe_timing_info *currentTiming)
+static void sgivwfb_setup_flatpanel(struct sgivw_par *par, struct dbe_timing_info *currentTiming)
 {
        int fp_wid, fp_hgt, fp_vbs, fp_vbe;
        u32 outputVal = 0;
@@ -429,7 +426,7 @@ static int sgivwfb_set_par(struct fb_info *info)
        /* Turn on dotclock PLL */
        DBE_SETREG(ctrlstat, 0x20000000);
 
-       dbe_TurnOffDma();
+       dbe_TurnOffDma(par);
 
        /* dbe_CalculateScreenParams(); */
        maxPixelsPerTileX = 512 / bytesPerPixel;
@@ -453,7 +450,7 @@ static int sgivwfb_set_par(struct fb_info *info)
                DBE_SETREG(vt_xy, 0x00000000);
                udelay(1);
        } else
-               dbe_TurnOffDma();
+               dbe_TurnOffDma(par);
 
        /* dbe_Initdbe(); */
        for (i = 0; i < 256; i++) {
@@ -567,7 +564,7 @@ static int sgivwfb_set_par(struct fb_info *info)
        DBE_SETREG(vt_hcmap, outputVal);
 
        if (flatpanel_id != -1)
-               sgivwfb_setup_flatpanel(currentTiming);
+               sgivwfb_setup_flatpanel(par, currentTiming);
 
        outputVal = 0;
        temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;
@@ -752,16 +749,30 @@ int __init sgivwfb_setup(char *options)
 /*
  *  Initialisation
  */
-int __init sgivwfb_init(void)
+static void sgivwfb_release(struct device *device)
+{
+}
+
+static int __init sgivwfb_probe(struct device *device)
 {
+       struct platform_device *dev = to_platform_device(device);
+       struct sgivw_par *par;
+       struct fb_info *info;
        char *monitor;
 
+       info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 256, &dev->dev);
+       if (!info)
+               return -ENOMEM;
+       par = info->par;
+
        if (!request_mem_region(DBE_REG_PHYS, DBE_REG_SIZE, "sgivwfb")) {
                printk(KERN_ERR "sgivwfb: couldn't reserve mmio region\n");
+               framebuffer_release(info);
                return -EBUSY;
        }
-       default_par.regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
-       if (!default_par.regs) {
+
+       par->regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
+       if (!par->regs) {
                printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
                goto fail_ioremap_regs;
        }
@@ -773,66 +784,118 @@ int __init sgivwfb_init(void)
        sgivwfb_fix.ywrapstep = ywrap;
        sgivwfb_fix.ypanstep = ypan;
 
-       fb_info.fix = sgivwfb_fix;
+       info->fix = sgivwfb_fix;
 
        switch (flatpanel_id) {
                case FLATPANEL_SGI_1600SW:
-                       fb_info.var = sgivwfb_var1600sw;
+                       info->var = sgivwfb_var1600sw;
                        monitor = "SGI 1600SW flatpanel";
                        break;
                default:
-                       fb_info.var = sgivwfb_var;
+                       info->var = sgivwfb_var;
                        monitor = "CRT";
        }
 
        printk(KERN_INFO "sgivwfb: %s monitor selected\n", monitor);
 
-       fb_info.fbops = &sgivwfb_ops;
-       fb_info.pseudo_palette = pseudo_palette;
-       fb_info.par = &default_par;
-       fb_info.flags = FBINFO_FLAG_DEFAULT;
+       info->fbops = &sgivwfb_ops;
+       info->pseudo_palette = (void *) (par + 1);
+       info->flags = FBINFO_DEFAULT;
 
-       fb_info.screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
-       if (!fb_info.screen_base) {
+       info->screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
+       if (!info->screen_base) {
                printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n");
                goto fail_ioremap_fbmem;
        }
 
-       fb_alloc_cmap(&fb_info.cmap, 256, 0);
+       if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+               goto fail_color_map;
 
-       if (register_framebuffer(&fb_info) < 0) {
+       if (register_framebuffer(info) < 0) {
                printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
                goto fail_register_framebuffer;
        }
 
+       dev_set_drvdata(&dev->dev, info);
+
        printk(KERN_INFO "fb%d: SGI DBE frame buffer device, using %ldK of video memory at %#lx\n",      
-               fb_info.node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
+               info->node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
        return 0;
 
 fail_register_framebuffer:
-       iounmap((char *) fb_info.screen_base);
+       fb_dealloc_cmap(&info->cmap);
+fail_color_map:
+       iounmap((char *) info->screen_base);
 fail_ioremap_fbmem:
-       iounmap(default_par.regs);
+       iounmap(par->regs);
 fail_ioremap_regs:
        release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+       framebuffer_release(info);
        return -ENXIO;
 }
 
-#ifdef MODULE
-MODULE_LICENSE("GPL");
+static int sgivwfb_remove(struct device *device)
+{
+       struct fb_info *info = dev_get_drvdata(device);
+
+       if (info) {
+               struct sgivw_par *par = info->par;
+
+               unregister_framebuffer(info);
+               dbe_TurnOffDma(par);
+               iounmap(par->regs);
+               iounmap(info->screen_base);
+               release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+       }
+       return 0;
+}
+
+static struct device_driver sgivwfb_driver = {
+       .name   = "sgivwfb",
+       .bus    = &platform_bus_type,
+       .probe  = sgivwfb_probe,
+       .remove = sgivwfb_remove,
+};
 
-int init_module(void)
+static struct platform_device sgivwfb_device = {
+       .name   = "sgivwfb",
+       .id     = 0,
+       .dev    = {
+               .release = sgivwfb_release,
+       }
+};
+
+int __init sgivwfb_init(void)
 {
-       return sgivwfb_init();
+       int ret;
+
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("sgivwfb", &option))
+               return -ENODEV;
+       sgivwfb_setup(option);
+#endif
+       ret = driver_register(&sgivwfb_driver);
+       if (!ret) {
+               ret = platform_device_register(&sgivwfb_device);
+               if (ret)
+                       driver_unregister(&sgivwfb_driver);
+       }
+       return ret;
 }
 
-void cleanup_module(void)
+module_init(sgivwfb_init);
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+static void __exit sgivwfb_exit(void)
 {
-       unregister_framebuffer(&fb_info);
-       dbe_TurnOffDma();
-       iounmap(regs);
-       iounmap(&fb_info.screen_base);
-       release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+       platform_device_unregister(&sgivwfb_device);
+       driver_unregister(&sgivwfb_driver);
 }
 
+module_exit(sgivwfb_exit);
+
 #endif                         /* MODULE */
index 9a15615..4b7e498 100644 (file)
@@ -1298,6 +1298,7 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
            case 1:
                fix->type = FB_TYPE_PLANES;     /* well, sort of */
                fix->visual = FB_VISUAL_MONO10;
+               var->red.length = var->green.length = var->blue.length = 1;
                break;
            case 8:
                fix->type = FB_TYPE_PACKED_PIXELS;
@@ -1324,7 +1325,7 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
        strcpy(fix->id, "stifb");
        info->fbops = &stifb_ops;
        info->screen_base = (void*) REGION_BASE(fb,1);
-       info->flags = FBINFO_FLAG_DEFAULT;
+       info->flags = FBINFO_DEFAULT;
        info->currcon = -1;
 
        /* This has to been done !!! */
@@ -1375,12 +1376,22 @@ out_err0:
 
 static int stifb_disabled __initdata;
 
+int __init
+stifb_setup(char *options);
+
 int __init
 stifb_init(void)
 {
        struct sti_struct *sti;
        int i;
        
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("stifb", &option))
+               return -ENODEV;
+       stifb_setup(option);
+#endif
        if (stifb_disabled) {
                printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n");
                return -ENXIO;
@@ -1451,9 +1462,7 @@ stifb_setup(char *options)
 
 __setup("stifb=", stifb_setup);
 
-#ifdef MODULE
 module_init(stifb_init);
-#endif
 module_exit(stifb_cleanup);
 
 MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
index 543711c..e3e43ca 100644 (file)
@@ -412,7 +412,7 @@ static void tcx_init_one(struct sbus_dev *sdev)
                all->par.mmap_map[i].poff = sdev->reg_addrs[j].phys_addr;
        }
 
-       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.flags = FBINFO_DEFAULT;
        all->info.fbops = &tcx_ops;
 #ifdef CONFIG_SPARC32
        all->info.screen_base = (char *)
@@ -468,6 +468,9 @@ int __init tcx_init(void)
        struct sbus_bus *sbus;
        struct sbus_dev *sdev;
 
+       if (fb_get_options("tcxfb", NULL))
+               return -ENODEV;
+
        for_all_sbusdev(sdev, sbus) {
                if (!strcmp(sdev->prom_name, "tcx"))
                        tcx_init_one(sdev);
@@ -496,8 +499,9 @@ tcx_setup(char *arg)
        return 0;
 }
 
-#ifdef MODULE
 module_init(tcx_init);
+
+#ifdef MODULE
 module_exit(tcx_exit);
 #endif
 
index f060c0a..09a9a34 100644 (file)
@@ -60,6 +60,9 @@ static struct fb_var_screeninfo tx3912fb_var = {
        .blue =         { 0, 2, 0 },
 #else
        .bits_per_pixel =4,
+       .red =          { 0, 4, 0 },    /* ??? */
+       .green =        { 0, 4, 0 },
+       .blue =         { 0, 4, 0 },
 #endif
        .activate =     FB_ACTIVATE_NOW,
        .width =        -1,
@@ -205,6 +208,8 @@ static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green,
        return 0;
 }
 
+int __init tx3912fb_setup(char *options);
+
 /*
  * Initialization of the framebuffer
  */
@@ -212,6 +217,11 @@ int __init tx3912fb_init(void)
 {
        u_long tx3912fb_paddr = 0;
        int size = (info->var.bits_per_pixel == 8) ? 256 : 16;
+       char *option = NULL;
+
+       if (fb_get_options("tx3912fb", &option))
+               return -ENODEV;
+       tx3912fb_setup(option);
 
        /* Disable the video logic */
        outl(inl(TX3912_VIDEO_CTRL1) &
@@ -296,7 +306,7 @@ int __init tx3912fb_init(void)
        fb_info.var = tx3912fb_var;
        fb_info.fix = tx3912fb_fix;
        fb_info.pseudo_palette = pseudo_palette;
-       fb_info.flags = FBINFO_FLAG_DEFAULT;
+       fb_info.flags = FBINFO_DEFAULT;
 
        /* Clear the framebuffer */
        memset((void *) fb_info.fix.smem_start, 0xff, fb_info.fix.smem_len);
@@ -326,4 +336,5 @@ int __init tx3912fb_setup(char *options)
        return 0;
 }
 
+module_init(tx3912fb_init);
 MODULE_LICENSE("GPL");
index fd8eb47..cdb1b14 100644 (file)
@@ -322,6 +322,11 @@ int __init valkyriefb_init(void)
        struct fb_info_valkyrie *p;
        unsigned long frame_buffer_phys, cmap_regs_phys, flags;
        int err;
+       char *option = NULL;
+
+       if (fb_get_options("valkyriefb", &option))
+               return -ENODEV;
+       valkyriefb_setup(option);
 
 #ifdef CONFIG_MAC
        if (!MACH_IS_MAC)
@@ -540,7 +545,7 @@ static void __init valkyrie_init_info(struct fb_info *info, struct fb_info_valky
 {
        info->fbops = &valkyriefb_ops;
        info->screen_base = (char *) p->frame_buffer + 0x1000;
-       info->flags = FBINFO_FLAG_DEFAULT;
+       info->flags = FBINFO_DEFAULT;
        info->pseudo_palette = p->pseudo_palette;
        fb_alloc_cmap(&info->cmap, 256, 0);
        info->par = &p->par;
@@ -579,4 +584,5 @@ int __init valkyriefb_setup(char *options)
        return 0;
 }
 
+module_init(valkyriefb_init);
 MODULE_LICENSE("GPL");
index 1902281..0ea62d8 100644 (file)
@@ -32,21 +32,21 @@ struct regstate {
        __u8 misc;
 };     
 
-static inline unsigned char vga_rcrtcs(caddr_t regbase, unsigned short iobase, 
+static inline unsigned char vga_rcrtcs(void __iomem *regbase, unsigned short iobase, 
                                       unsigned char reg)
 {
        vga_w(regbase, iobase + 0x4, reg);
        return vga_r(regbase, iobase + 0x5);
 }
 
-static inline void vga_wcrtcs(caddr_t regbase, unsigned short iobase, 
+static inline void vga_wcrtcs(void __iomem *regbase, unsigned short iobase, 
                              unsigned char reg, unsigned char val)
 {
        vga_w(regbase, iobase + 0x4, reg);
        vga_w(regbase, iobase + 0x5, val);
 }
 
-static void save_vga_text(struct vgastate *state, caddr_t fbbase)
+static void save_vga_text(struct vgastate *state, void __iomem *fbbase)
 {
        struct regstate *saved = (struct regstate *) state->vidstate;
        int i;
@@ -134,7 +134,7 @@ static void save_vga_text(struct vgastate *state, caddr_t fbbase)
        vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
 }
 
-static void restore_vga_text(struct vgastate *state, caddr_t fbbase)
+static void restore_vga_text(struct vgastate *state, void __iomem *fbbase)
 {
        struct regstate *saved = (struct regstate *) state->vidstate;
        int i;
@@ -403,7 +403,7 @@ int save_vga(struct vgastate *state)
        }
 
        if (state->flags & VGA_SAVE_FONTS) {
-               caddr_t fbbase;
+               void __iomem *fbbase;
 
                /* exit if window is less than 32K */
                if (state->memsize && state->memsize < 4 * 8192) {
@@ -473,7 +473,7 @@ int restore_vga (struct vgastate *state)
                restore_vga_mode(state);
 
        if (state->flags & VGA_SAVE_FONTS) {
-               caddr_t fbbase = ioremap(state->membase, state->memsize);
+               void __iomem *fbbase = ioremap(state->membase, state->memsize);
 
                if (!fbbase) {
                        vga_cleanup(state);
index bdeb028..9849549 100644 (file)
@@ -21,6 +21,25 @@ config W1_MATROX
          This support is also available as a module.  If so, the module 
          will be called matrox_w1.ko.
 
+config W1_DS9490
+       tristate "DS9490R transport layer driver"
+       depends on W1 && USB
+       help
+         Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge.
+
+         This support is also available as a module.  If so, the module 
+         will be called ds9490r.ko.
+
+config W1_DS9490R_BRIDGE
+       tristate "DS9490R USB <-> W1 transport layer for 1-wire"
+       depends on W1_DS9490
+       help
+         Say Y here if you want to communicate with your 1-wire devices
+         using DS9490R USB bridge.
+
+         This support is also available as a module.  If so, the module 
+         will be called ds_w1_bridge.ko.
+
 config W1_THERM
        tristate "Thermal family implementation"
        depends on W1
@@ -28,4 +47,11 @@ config W1_THERM
          Say Y here if you want to connect 1-wire thermal sensors to you
          wire.
 
+config W1_SMEM
+       tristate "Simple 64bit memory family implementation"
+       depends on W1
+       help
+         Say Y here if you want to connect 1-wire 
+         simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
+
 endmenu
index 7d005d9..a389bdc 100644 (file)
@@ -7,3 +7,10 @@ wire-objs              := w1.o w1_int.o w1_family.o w1_netlink.o w1_io.o
 
 obj-$(CONFIG_W1_MATROX)                += matrox_w1.o
 obj-$(CONFIG_W1_THERM)         += w1_therm.o
+obj-$(CONFIG_W1_SMEM)          += w1_smem.o
+
+obj-$(CONFIG_W1_DS9490)                += ds9490r.o 
+ds9490r-objs    := dscore.o
+
+obj-$(CONFIG_W1_DS9490_BRIDGE) += ds_w1_bridge.o
+
diff --git a/drivers/w1/ds_w1_bridge.c b/drivers/w1/ds_w1_bridge.c
new file mode 100644 (file)
index 0000000..0baaeb5
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ *     ds_w1_bridge.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * This program is free software; you can redistribute 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/types.h>
+
+#include "../w1/w1.h"
+#include "../w1/w1_int.h"
+#include "dscore.h"
+       
+static struct ds_device *ds_dev;
+static struct w1_bus_master *ds_bus_master;
+
+static u8 ds9490r_touch_bit(unsigned long data, u8 bit)
+{
+       u8 ret;
+       struct ds_device *dev = (struct ds_device *)data;
+
+       if (ds_touch_bit(dev, bit, &ret))
+               return 0;
+
+       return ret;
+}
+
+static void ds9490r_write_bit(unsigned long data, u8 bit)
+{
+       struct ds_device *dev = (struct ds_device *)data;
+
+       ds_write_bit(dev, bit);
+}
+
+static void ds9490r_write_byte(unsigned long data, u8 byte)
+{
+       struct ds_device *dev = (struct ds_device *)data;
+
+       ds_write_byte(dev, byte);
+}
+
+static u8 ds9490r_read_bit(unsigned long data)
+{
+       struct ds_device *dev = (struct ds_device *)data;
+       int err;
+       u8 bit = 0;
+
+       err = ds_touch_bit(dev, 1, &bit);
+       if (err)
+               return 0;
+       //err = ds_read_bit(dev, &bit);
+       //if (err)
+       //      return 0;
+
+       return bit & 1;
+}
+
+static u8 ds9490r_read_byte(unsigned long data)
+{
+       struct ds_device *dev = (struct ds_device *)data;
+       int err;
+       u8 byte = 0;
+
+       err = ds_read_byte(dev, &byte);
+       if (err)
+               return 0;
+
+       return byte;
+}
+
+static void ds9490r_write_block(unsigned long data, u8 *buf, int len)
+{
+       struct ds_device *dev = (struct ds_device *)data;
+
+       ds_write_block(dev, buf, len);
+}
+
+static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len)
+{
+       struct ds_device *dev = (struct ds_device *)data;
+       int err;
+
+       err = ds_read_block(dev, buf, len);
+       if (err < 0)
+               return 0;
+
+       return len;
+}
+
+static u8 ds9490r_reset(unsigned long data)
+{
+       struct ds_device *dev = (struct ds_device *)data;
+       struct ds_status st;
+       int err;
+
+       memset(&st, 0, sizeof(st));
+
+       err = ds_reset(dev, &st);
+       if (err)
+               return 1;
+
+       return 0;
+}
+
+static int __devinit ds_w1_init(void)
+{
+       int err;
+       
+       ds_bus_master = kmalloc(sizeof(*ds_bus_master), GFP_KERNEL);
+       if (!ds_bus_master) {
+               printk(KERN_ERR "Failed to allocate DS9490R USB<->W1 bus_master structure.\n");
+               return -ENOMEM;
+       }
+
+       ds_dev = ds_get_device();
+       if (!ds_dev) {
+               printk(KERN_ERR "DS9490R is not registered.\n");
+               err =  -ENODEV;
+               goto err_out_free_bus_master;
+       }
+
+       memset(ds_bus_master, 0, sizeof(*ds_bus_master));
+
+       ds_bus_master->data             = (unsigned long)ds_dev;
+       ds_bus_master->touch_bit        = &ds9490r_touch_bit;
+       ds_bus_master->read_bit         = &ds9490r_read_bit;
+       ds_bus_master->write_bit        = &ds9490r_write_bit;
+       ds_bus_master->read_byte        = &ds9490r_read_byte;
+       ds_bus_master->write_byte       = &ds9490r_write_byte;
+       ds_bus_master->read_block       = &ds9490r_read_block;
+       ds_bus_master->write_block      = &ds9490r_write_block;
+       ds_bus_master->reset_bus        = &ds9490r_reset;
+
+       err = w1_add_master_device(ds_bus_master);
+       if (err)
+               goto err_out_put_device;
+
+       return 0;
+
+err_out_put_device:
+       ds_put_device(ds_dev);
+err_out_free_bus_master:
+       kfree(ds_bus_master);
+
+       return err;
+}
+
+static void __devexit ds_w1_fini(void)
+{
+       w1_remove_master_device(ds_bus_master);
+       ds_put_device(ds_dev);
+       kfree(ds_bus_master);
+}
+
+module_init(ds_w1_init);
+module_exit(ds_w1_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
diff --git a/drivers/w1/dscore.c b/drivers/w1/dscore.c
new file mode 100644 (file)
index 0000000..f0f26a4
--- /dev/null
@@ -0,0 +1,783 @@
+/*
+ *     dscore.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * This program is free software; you can redistribute 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/mod_devicetable.h>
+#include <linux/usb.h>
+
+#include "dscore.h"
+
+static struct usb_device_id ds_id_table [] = {
+       { USB_DEVICE(0x04fa, 0x2490) },
+       { },
+};
+MODULE_DEVICE_TABLE(usb, ds_id_table);
+
+int ds_probe(struct usb_interface *, const struct usb_device_id *);
+void ds_disconnect(struct usb_interface *);
+
+inline int ds_touch_bit(struct ds_device *, u8, u8 *);
+inline int ds_read_byte(struct ds_device *, u8 *);
+inline int ds_read_bit(struct ds_device *, u8 *);
+inline int ds_write_byte(struct ds_device *, u8);
+inline int ds_write_bit(struct ds_device *, u8);
+inline int ds_start_pulse(struct ds_device *, int);
+inline int ds_set_speed(struct ds_device *, int);
+inline int ds_reset(struct ds_device *, struct ds_status *);
+inline int ds_detect(struct ds_device *, struct ds_status *);
+inline int ds_stop_pulse(struct ds_device *, int);
+inline int ds_send_data(struct ds_device *, unsigned char *, int);
+inline int ds_recv_data(struct ds_device *, unsigned char *, int);
+inline int ds_recv_status(struct ds_device *, struct ds_status *);
+inline struct ds_device * ds_get_device(void);
+inline void ds_put_device(struct ds_device *);
+
+static inline void ds_dump_status(unsigned char *, unsigned char *, int);
+static inline int ds_send_control(struct ds_device *, u16, u16);
+static inline int ds_send_control_mode(struct ds_device *, u16, u16);
+static inline int ds_send_control_cmd(struct ds_device *, u16, u16);
+
+
+static struct usb_driver ds_driver = {
+       .owner =        THIS_MODULE,
+       .name =         "DS9490R",
+       .probe =        ds_probe,
+       .disconnect =   ds_disconnect,
+       .id_table =     ds_id_table,
+};
+
+static struct ds_device *ds_dev;
+
+struct ds_device * ds_get_device(void)
+{
+       if (ds_dev)
+               atomic_inc(&ds_dev->refcnt);
+       return ds_dev;
+}
+
+void ds_put_device(struct ds_device *dev)
+{
+       atomic_dec(&dev->refcnt);
+}
+
+static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
+{
+       int err;
+       
+       err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 
+                       CONTROL_CMD, 0x40, value, index, NULL, 0, HZ);
+       if (err < 0) {
+               printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n", 
+                               value, index, err);
+               return err;
+       }
+
+       return err;
+}
+
+static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
+{
+       int err;
+       
+       err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 
+                       MODE_CMD, 0x40, value, index, NULL, 0, HZ);
+       if (err < 0) {
+               printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n", 
+                               value, index, err);
+               return err;
+       }
+
+       return err;
+}
+
+static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
+{
+       int err;
+       
+       err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 
+                       COMM_CMD, 0x40, value, index, NULL, 0, HZ);
+       if (err < 0) {
+               printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n", 
+                               value, index, err);
+               return err;
+       }
+
+       return err;
+}
+
+static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
+{
+       printk("%45s: %8x\n", str, buf[off]);
+}
+
+int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, unsigned char *buf, int size)
+{
+       int count, err;
+               
+       memset(st, 0, sizeof(st));
+       
+       count = 0;
+       err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
+       if (err < 0) {
+               printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
+               return err;
+       }
+       
+       if (count >= sizeof(*st))
+               memcpy(st, buf, sizeof(*st));
+
+       return count;
+}
+
+int ds_recv_status(struct ds_device *dev, struct ds_status *st)
+{
+       unsigned char buf[64];
+       int count, err = 0, i;
+       
+       memcpy(st, buf, sizeof(*st));
+               
+       count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+       if (count < 0)
+               return err;
+       
+       printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
+       for (i=0; i<count; ++i)
+               printk("%02x ", buf[i]);
+       printk("\n");
+
+       if (count >= 16) {
+               ds_dump_status(buf, "enable flag", 0);
+               ds_dump_status(buf, "1-wire speed", 1);
+               ds_dump_status(buf, "strong pullup duration", 2);
+               ds_dump_status(buf, "programming pulse duration", 3);
+               ds_dump_status(buf, "pulldown slew rate control", 4);
+               ds_dump_status(buf, "write-1 low time", 5);
+               ds_dump_status(buf, "data sample offset/write-0 recovery time", 6);
+               ds_dump_status(buf, "reserved (test register)", 7);
+               ds_dump_status(buf, "device status flags", 8);
+               ds_dump_status(buf, "communication command byte 1", 9);
+               ds_dump_status(buf, "communication command byte 2", 10);
+               ds_dump_status(buf, "communication command buffer status", 11);
+               ds_dump_status(buf, "1-wire data output buffer status", 12);
+               ds_dump_status(buf, "1-wire data input buffer status", 13);
+               ds_dump_status(buf, "reserved", 14);
+               ds_dump_status(buf, "reserved", 15);
+       }
+
+       memcpy(st, buf, sizeof(*st));
+
+       if (st->status & ST_EPOF) {
+               printk(KERN_INFO "Resetting device after ST_EPOF.\n");
+               err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+               if (err)
+                       return err;
+               count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+               if (count < 0)
+                       return err;
+       }
+#if 0
+       if (st->status & ST_IDLE) {
+               printk(KERN_INFO "Resetting pulse after ST_IDLE.\n");
+               err = ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+               if (err)
+                       return err;
+       }
+#endif
+       
+       return err;
+}
+
+int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
+{
+       int count, err;
+       struct ds_status st;
+       
+       count = 0;
+       err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), 
+                               buf, size, &count, HZ);
+       if (err < 0) {
+               printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
+               usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
+               ds_recv_status(dev, &st);
+               return err;
+       }
+
+#if 0
+       {
+               int i;
+
+               printk("%s: count=%d: ", __func__, count);
+               for (i=0; i<count; ++i)
+                       printk("%02x ", buf[i]);
+               printk("\n");
+       }
+#endif
+       return count;
+}
+
+int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
+{
+       int count, err;
+       
+       count = 0;
+       err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, HZ);
+       if (err < 0) {
+               printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
+               return err;
+       }
+
+       return err;
+}
+
+int ds_stop_pulse(struct ds_device *dev, int limit)
+{
+       struct ds_status st;
+       int count = 0, err = 0;
+       u8 buf[0x20];
+       
+       do {
+               err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
+               if (err)
+                       break;
+               err = ds_send_control(dev, CTL_RESUME_EXE, 0);
+               if (err)
+                       break;
+               err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
+               if (err)
+                       break;
+
+               if ((st.status & ST_SPUA) == 0) {
+                       err = ds_send_control_mode(dev, MOD_PULSE_EN, 0);
+                       if (err)
+                               break;
+               }
+       } while(++count < limit);
+
+       return err;
+}
+
+int ds_detect(struct ds_device *dev, struct ds_status *st)
+{
+       int err;
+       
+       err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+       if (err)
+               return err;
+
+       err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
+       if (err)
+               return err;
+       
+       err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
+       if (err)
+               return err;
+       
+       err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
+       if (err)
+               return err;
+
+       err = ds_recv_status(dev, st);
+
+       return err;
+}
+
+int ds_wait_status(struct ds_device *dev, struct ds_status *st)
+{
+       u8 buf[0x20];
+       int err, count = 0;
+
+       do {
+               err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+#if 0
+               if (err >= 0) { 
+                       int i;
+                       printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
+                       for (i=0; i<err; ++i)
+                               printk("%02x ", buf[i]);
+                       printk("\n");
+               }
+#endif
+       } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);
+
+
+       if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
+               ds_recv_status(dev, st);
+               return -1;
+       }
+       else {
+               return 0;
+       }
+}
+
+int ds_reset(struct ds_device *dev, struct ds_status *st)
+{
+       int err;
+
+       //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE);
+       err = ds_send_control(dev, 0x43, SPEED_NORMAL);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, st);
+#if 0
+       if (st->command_buffer_status) {
+               printk(KERN_INFO "Short circuit.\n");
+               return -EIO;
+       }
+#endif
+       
+       return 0;
+}
+
+int ds_set_speed(struct ds_device *dev, int speed)
+{
+       int err;
+       
+       if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE)
+               return -EINVAL;
+
+       if (speed != SPEED_OVERDRIVE)
+               speed = SPEED_FLEXIBLE;
+
+       speed &= 0xff;
+       
+       err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
+       if (err)
+               return err;
+
+       return err;
+}
+
+int ds_start_pulse(struct ds_device *dev, int delay)
+{
+       int err;
+       u8 del = 1 + (u8)(delay >> 4);
+       struct ds_status st;
+       
+#if 0
+       err = ds_stop_pulse(dev, 10);
+       if (err)
+               return err;
+
+       err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
+       if (err)
+               return err;
+#endif
+       err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
+       if (err)
+               return err;
+
+       err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0);
+       if (err)
+               return err;
+
+       mdelay(delay);
+
+       ds_wait_status(dev, &st);
+       
+       return err;
+}
+
+int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
+{
+       int err, count;
+       struct ds_status st;
+       u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
+       u16 cmd;
+       
+       err = ds_send_control(dev, value, 0);
+       if (err)
+               return err;
+
+       count = 0;
+       do {
+               err = ds_wait_status(dev, &st);
+               if (err)
+                       return err;
+
+               cmd = st.command0 | (st.command1 << 8);
+       } while (cmd != value && ++count < 10);
+
+       if (err < 0 || count >= 10) {
+               printk(KERN_ERR "Failed to obtain status.\n");
+               return -EINVAL;
+       }
+
+       err = ds_recv_data(dev, tbit, sizeof(*tbit));
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+int ds_write_bit(struct ds_device *dev, u8 bit)
+{
+       int err;
+       struct ds_status st;
+       
+       err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       return 0;
+}
+
+int ds_write_byte(struct ds_device *dev, u8 byte)
+{
+       int err;
+       struct ds_status st;
+       u8 rbyte;
+       
+       err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
+       if (err)
+               return err;
+
+       err = ds_wait_status(dev, &st);
+       if (err)
+               return err;
+               
+       err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
+       if (err < 0)
+               return err;
+       
+       ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+
+       return !(byte == rbyte);
+}
+
+int ds_read_bit(struct ds_device *dev, u8 *bit)
+{
+       int err;
+
+       err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
+       if (err)
+               return err;
+       
+       err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0);
+       if (err)
+               return err;
+       
+       err = ds_recv_data(dev, bit, sizeof(*bit));
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+int ds_read_byte(struct ds_device *dev, u8 *byte)
+{
+       int err;
+       struct ds_status st;
+
+       err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+       
+       err = ds_recv_data(dev, byte, sizeof(*byte));
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+inline int ds_read_block(struct ds_device *dev, u8 *buf, int len)
+{
+       struct ds_status st;
+       int err;
+
+       if (len > 64*1024)
+               return -E2BIG;
+
+       memset(buf, 0xFF, len);
+       
+       err = ds_send_data(dev, buf, len);
+       if (err < 0)
+               return err;
+       
+       err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+       
+       memset(buf, 0x00, len);
+       err = ds_recv_data(dev, buf, len);
+
+       return err;
+}
+
+inline int ds_write_block(struct ds_device *dev, u8 *buf, int len)
+{
+       int err;
+       struct ds_status st;
+       
+       err = ds_send_data(dev, buf, len);
+       if (err < 0)
+               return err;
+       
+       ds_wait_status(dev, &st);
+
+       err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       err = ds_recv_data(dev, buf, len);
+       if (err < 0)
+               return err;
+
+       ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+       
+       return !(err == len);
+}
+
+int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
+{
+       int err;
+       u16 value, index;
+       struct ds_status st;
+
+       memset(buf, 0, sizeof(buf));
+       
+       err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
+       if (err)
+               return err;
+       
+       ds_wait_status(ds_dev, &st);
+
+       value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
+       index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
+       err = ds_send_control(ds_dev, value, index);
+       if (err)
+               return err;
+
+       ds_wait_status(ds_dev, &st);
+
+       err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
+       if (err < 0)
+               return err;
+
+       return err/8;
+}
+
+int ds_match_access(struct ds_device *dev, u64 init)
+{
+       int err;
+       struct ds_status st;
+
+       err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
+       if (err)
+               return err;
+       
+       ds_wait_status(dev, &st);
+
+       err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       return 0;
+}
+
+int ds_set_path(struct ds_device *dev, u64 init)
+{
+       int err;
+       struct ds_status st;
+       u8 buf[9];
+
+       memcpy(buf, &init, 8);
+       buf[8] = BRANCH_MAIN;
+       
+       err = ds_send_data(dev, buf, sizeof(buf));
+       if (err)
+               return err;
+       
+       ds_wait_status(dev, &st);
+
+       err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       return 0;
+}
+
+int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct usb_endpoint_descriptor *endpoint;
+       struct usb_host_interface *iface_desc;
+       int i, err;
+
+       ds_dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
+       if (!ds_dev) {
+               printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
+               return -ENOMEM;
+       }
+
+       ds_dev->udev = usb_get_dev(udev);
+       usb_set_intfdata(intf, ds_dev);
+
+       err = usb_set_interface(ds_dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
+       if (err) {
+               printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
+                               intf->altsetting[0].desc.bInterfaceNumber, err);
+               return err;
+       }
+
+       err = usb_reset_configuration(ds_dev->udev);
+       if (err) {
+               printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
+               return err;
+       }
+       
+       iface_desc = &intf->altsetting[0];
+       if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
+               printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
+               return -ENODEV;
+       }
+
+       atomic_set(&ds_dev->refcnt, 0);
+       memset(ds_dev->ep, 0, sizeof(ds_dev->ep));
+       
+       /*
+        * This loop doesn'd show control 0 endpoint, 
+        * so we will fill only 1-3 endpoints entry.
+        */
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+
+               ds_dev->ep[i+1] = endpoint->bEndpointAddress;
+               
+               printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
+                       i, endpoint->bEndpointAddress, endpoint->wMaxPacketSize,
+                       (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
+                       endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+       }
+       
+#if 0
+       {
+               int err, i;
+               u64 buf[3];
+               u64 init=0xb30000002078ee81ull;
+               struct ds_status st;
+               
+               ds_reset(ds_dev, &st);
+               err = ds_search(ds_dev, init, buf, 3, 0);
+               if (err < 0)
+                       return err;
+               for (i=0; i<err; ++i)
+                       printk("%d: %llx\n", i, buf[i]);
+               
+               printk("Resetting...\n");       
+               ds_reset(ds_dev, &st);
+               printk("Setting path for %llx.\n", init);
+               err = ds_set_path(ds_dev, init);
+               if (err)
+                       return err;
+               printk("Calling MATCH_ACCESS.\n");
+               err = ds_match_access(ds_dev, init);
+               if (err)
+                       return err;
+
+               printk("Searching the bus...\n");
+               err = ds_search(ds_dev, init, buf, 3, 0);
+
+               printk("ds_search() returned %d\n", err);
+               
+               if (err < 0)
+                       return err;
+               for (i=0; i<err; ++i)
+                       printk("%d: %llx\n", i, buf[i]);
+               
+               return 0;
+       }
+#endif
+
+       return 0;
+}
+
+void ds_disconnect(struct usb_interface *intf)
+{
+       struct ds_device *dev;
+       
+       dev = usb_get_intfdata (intf);
+       usb_set_intfdata (intf, NULL);
+
+       while(atomic_read(&dev->refcnt))
+               schedule_timeout(HZ);
+
+       usb_put_dev(dev->udev);
+       kfree(dev);
+       ds_dev = NULL;
+}
+
+int ds_init(void)
+{
+       int err;
+
+       err = usb_register(&ds_driver);
+       if (err) {
+               printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+void ds_fini(void)
+{
+       usb_deregister(&ds_driver);
+}
+
+module_init(ds_init);
+module_exit(ds_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+
+EXPORT_SYMBOL(ds_touch_bit);
+EXPORT_SYMBOL(ds_read_byte);
+EXPORT_SYMBOL(ds_read_bit);
+EXPORT_SYMBOL(ds_read_block);
+EXPORT_SYMBOL(ds_write_byte);
+EXPORT_SYMBOL(ds_write_bit);
+EXPORT_SYMBOL(ds_write_block);
+EXPORT_SYMBOL(ds_start_pulse);
+EXPORT_SYMBOL(ds_set_speed);
+EXPORT_SYMBOL(ds_reset);
+EXPORT_SYMBOL(ds_detect);
+EXPORT_SYMBOL(ds_stop_pulse);
+EXPORT_SYMBOL(ds_send_data);
+EXPORT_SYMBOL(ds_recv_data);
+EXPORT_SYMBOL(ds_recv_status);
+EXPORT_SYMBOL(ds_search);
+EXPORT_SYMBOL(ds_get_device);
+EXPORT_SYMBOL(ds_put_device);
+
diff --git a/drivers/w1/dscore.h b/drivers/w1/dscore.h
new file mode 100644 (file)
index 0000000..77c37c6
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ *     dscore.h
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * This program is free software; you can redistribute 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 __DSCORE_H
+#define __DSCORE_H
+
+#include <linux/usb.h>
+#include <asm/atomic.h>
+
+/* COMMAND TYPE CODES */
+#define CONTROL_CMD                    0x00
+#define COMM_CMD                       0x01
+#define MODE_CMD                       0x02
+
+/* CONTROL COMMAND CODES */
+#define CTL_RESET_DEVICE               0x0000
+#define CTL_START_EXE                  0x0001
+#define CTL_RESUME_EXE                 0x0002
+#define CTL_HALT_EXE_IDLE              0x0003
+#define CTL_HALT_EXE_DONE              0x0004
+#define CTL_FLUSH_COMM_CMDS            0x0007
+#define CTL_FLUSH_RCV_BUFFER           0x0008
+#define CTL_FLUSH_XMT_BUFFER           0x0009
+#define CTL_GET_COMM_CMDS              0x000A
+
+/* MODE COMMAND CODES */
+#define MOD_PULSE_EN                   0x0000
+#define MOD_SPEED_CHANGE_EN            0x0001
+#define MOD_1WIRE_SPEED                        0x0002
+#define MOD_STRONG_PU_DURATION         0x0003
+#define MOD_PULLDOWN_SLEWRATE          0x0004
+#define MOD_PROG_PULSE_DURATION                0x0005
+#define MOD_WRITE1_LOWTIME             0x0006
+#define MOD_DSOW0_TREC                 0x0007
+
+/* COMMUNICATION COMMAND CODES */
+#define COMM_ERROR_ESCAPE              0x0601
+#define COMM_SET_DURATION              0x0012
+#define COMM_BIT_IO                    0x0020
+#define COMM_PULSE                     0x0030
+#define COMM_1_WIRE_RESET              0x0042
+#define COMM_BYTE_IO                   0x0052
+#define COMM_MATCH_ACCESS              0x0064
+#define COMM_BLOCK_IO                  0x0074
+#define COMM_READ_STRAIGHT             0x0080
+#define COMM_DO_RELEASE                        0x6092
+#define COMM_SET_PATH                  0x00A2
+#define COMM_WRITE_SRAM_PAGE           0x00B2
+#define COMM_WRITE_EPROM               0x00C4
+#define COMM_READ_CRC_PROT_PAGE                0x00D4
+#define COMM_READ_REDIRECT_PAGE_CRC    0x21E4
+#define COMM_SEARCH_ACCESS             0x00F4
+
+/* Communication command bits */
+#define COMM_TYPE                      0x0008
+#define COMM_SE                                0x0008
+#define COMM_D                         0x0008
+#define COMM_Z                         0x0008
+#define COMM_CH                                0x0008
+#define COMM_SM                                0x0008
+#define COMM_R                         0x0008
+#define COMM_IM                                0x0001
+
+#define COMM_PS                                0x4000
+#define COMM_PST                       0x4000
+#define COMM_CIB                       0x4000
+#define COMM_RTS                       0x4000
+#define COMM_DT                                0x2000
+#define COMM_SPU                       0x1000
+#define COMM_F                         0x0800
+#define COMM_NTP                       0x0400
+#define COMM_ICP                       0x0200
+#define COMM_RST                       0x0100
+
+#define PULSE_PROG                     0x01
+#define PULSE_SPUE                     0x02
+
+#define BRANCH_MAIN                    0xCC
+#define BRANCH_AUX                     0x33
+
+/*
+ * Duration of the strong pull-up pulse in milliseconds.
+ */
+#define PULLUP_PULSE_DURATION          750
+
+/* Status flags */
+#define ST_SPUA                                0x01  /* Strong Pull-up is active */
+#define ST_PRGA                                0x02  /* 12V programming pulse is being generated */
+#define ST_12VP                                0x04  /* external 12V programming voltage is present */
+#define ST_PMOD                                0x08  /* DS2490 powered from USB and external sources */
+#define ST_HALT                                0x10  /* DS2490 is currently halted */
+#define ST_IDLE                                0x20  /* DS2490 is currently idle */
+#define ST_EPOF                                0x80
+
+#define SPEED_NORMAL                   0x00
+#define SPEED_FLEXIBLE                 0x01
+#define SPEED_OVERDRIVE                        0x02
+
+#define NUM_EP                         4
+#define EP_CONTROL                     0
+#define EP_STATUS                      1
+#define EP_DATA_OUT                    2
+#define EP_DATA_IN                     3
+
+struct ds_device
+{
+       struct usb_device       *udev;
+       struct usb_interface    *intf;
+
+       int                     ep[NUM_EP];
+
+       atomic_t                refcnt;
+};
+
+struct ds_status
+{
+       u8                      enable;
+       u8                      speed;
+       u8                      pullup_dur;
+       u8                      ppuls_dur;
+       u8                      pulldown_slew;
+       u8                      write1_time;
+       u8                      write0_time;
+       u8                      reserved0;
+       u8                      status;
+       u8                      command0;
+       u8                      command1;
+       u8                      command_buffer_status;
+       u8                      data_out_buffer_status;
+       u8                      data_in_buffer_status;
+       u8                      reserved1;
+       u8                      reserved2;
+
+};
+
+inline int ds_touch_bit(struct ds_device *, u8, u8 *);
+inline int ds_read_byte(struct ds_device *, u8 *);
+inline int ds_read_bit(struct ds_device *, u8 *);
+inline int ds_write_byte(struct ds_device *, u8);
+inline int ds_write_bit(struct ds_device *, u8);
+inline int ds_start_pulse(struct ds_device *, int);
+inline int ds_set_speed(struct ds_device *, int);
+inline int ds_reset(struct ds_device *, struct ds_status *);
+inline int ds_detect(struct ds_device *, struct ds_status *);
+inline int ds_stop_pulse(struct ds_device *, int);
+inline int ds_send_data(struct ds_device *, unsigned char *, int);
+inline int ds_recv_data(struct ds_device *, unsigned char *, int);
+inline int ds_recv_status(struct ds_device *, struct ds_status *);
+inline struct ds_device * ds_get_device(void);
+inline void ds_put_device(struct ds_device *);
+inline int ds_write_block(struct ds_device *, u8 *, int);
+inline int ds_read_block(struct ds_device *, u8 *, int);
+
+#endif /* __DSCORE_H */
+
index bde1778..44abe37 100644 (file)
@@ -94,7 +94,7 @@ static void matrox_w1_write_ddc_bit(unsigned long, u8);
 /*
  * These functions read and write DDC Data bit.
  *
- * Using tristate pins, since i can't  fin any open-drain pin in whole motherboard.
+ * Using tristate pins, since i can't find any open-drain pin in whole motherboard.
  * Unfortunately we can't connect to Intel's 82801xx IO controller
  * since we don't know motherboard schema, wich has pretty unused(may be not) GPIO.
  *
index 4f52422..278393f 100644 (file)
@@ -45,7 +45,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
 
-static int w1_timeout = 5 * HZ;
+static int w1_timeout = 10;
 int w1_max_slave_count = 10;
 
 module_param_named(timeout, w1_timeout, int, 0);
@@ -137,25 +137,95 @@ static struct device_attribute w1_slave_attribute_val = {
        .show = &w1_default_read_name,
 };
 
-static ssize_t w1_master_attribute_show(struct device *dev, char *buf)
+ssize_t w1_master_attribute_show_name(struct device *dev, char *buf)
+{
+       struct w1_master *md = container_of (dev, struct w1_master, dev);
+       ssize_t count;
+       
+       if (down_interruptible (&md->mutex))
+               return -EBUSY;
+
+       count = sprintf(buf, "%s\n", md->name);
+       
+       up(&md->mutex);
+
+       return count;
+}
+
+ssize_t w1_master_attribute_show_pointer(struct device *dev, char *buf)
+{
+       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       ssize_t count;
+       
+       if (down_interruptible(&md->mutex))
+               return -EBUSY;
+
+       count = sprintf(buf, "0x%p\n", md->bus_master);
+       
+       up(&md->mutex);
+       return count;
+}
+
+ssize_t w1_master_attribute_show_timeout(struct device *dev, char *buf)
+{
+       ssize_t count;
+       count = sprintf(buf, "%d\n", w1_timeout);
+       return count;
+}
+
+ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, char *buf)
+{
+       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       ssize_t count;
+       
+       if (down_interruptible(&md->mutex))
+               return -EBUSY;
+
+       count = sprintf(buf, "%d\n", md->max_slave_count);
+       
+       up(&md->mutex);
+       return count;
+}
+
+ssize_t w1_master_attribute_show_attempts(struct device *dev, char *buf)
+{
+       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       ssize_t count;
+       
+       if (down_interruptible(&md->mutex))
+               return -EBUSY;
+
+       count = sprintf(buf, "%lu\n", md->attempts);
+       
+       up(&md->mutex);
+       return count;
+}
+
+ssize_t w1_master_attribute_show_slave_count(struct device *dev, char *buf)
+{
+       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       ssize_t count;
+       
+       if (down_interruptible(&md->mutex))
+               return -EBUSY;
+
+       count = sprintf(buf, "%d\n", md->slave_count);
+       
+       up(&md->mutex);
+       return count;
+}
+
+ssize_t w1_master_attribute_show_slaves(struct device *dev, char *buf)
+
 {
-       return sprintf(buf, "please fix me\n");
-#if 0
        struct w1_master *md = container_of(dev, struct w1_master, dev);
        int c = PAGE_SIZE;
 
        if (down_interruptible(&md->mutex))
                return -EBUSY;
 
-       c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", md->name);
-       c -= snprintf(buf + PAGE_SIZE - c, c,
-                      "bus_master=0x%p, timeout=%d, max_slave_count=%d, attempts=%lu\n",
-                      md->bus_master, w1_timeout, md->max_slave_count,
-                      md->attempts);
-       c -= snprintf(buf + PAGE_SIZE - c, c, "%d slaves: ",
-                      md->slave_count);
        if (md->slave_count == 0)
-               c -= snprintf(buf + PAGE_SIZE - c, c, "no.\n");
+               c -= snprintf(buf + PAGE_SIZE - c, c, "not found.\n");
        else {
                struct list_head *ent, *n;
                struct w1_slave *sl;
@@ -163,25 +233,70 @@ static ssize_t w1_master_attribute_show(struct device *dev, char *buf)
                list_for_each_safe(ent, n, &md->slist) {
                        sl = list_entry(ent, struct w1_slave, w1_slave_entry);
 
-                       c -= snprintf(buf + PAGE_SIZE - c, c, "%s[%p] ",
-                                      sl->name, sl);
+                       c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
                }
-               c -= snprintf(buf + PAGE_SIZE - c, c, "\n");
        }
 
        up(&md->mutex);
 
        return PAGE_SIZE - c;
-#endif
 }
 
-struct device_attribute w1_master_attribute = {
+static struct device_attribute w1_master_attribute_slaves = {
        .attr = {
-                       .name = "w1_master_stats",
+                       .name = "w1_master_slaves",
                        .mode = S_IRUGO,
                        .owner = THIS_MODULE,
        },
-       .show = &w1_master_attribute_show,
+       .show = &w1_master_attribute_show_slaves,
+};
+static struct device_attribute w1_master_attribute_slave_count = {
+       .attr = {
+                       .name = "w1_master_slave_count",
+                       .mode = S_IRUGO,
+                       .owner = THIS_MODULE
+       },
+       .show = &w1_master_attribute_show_slave_count,
+};
+static struct device_attribute w1_master_attribute_attempts = {
+       .attr = {
+                       .name = "w1_master_attempts",
+                       .mode = S_IRUGO,
+                       .owner = THIS_MODULE
+       },
+       .show = &w1_master_attribute_show_attempts,
+};
+static struct device_attribute w1_master_attribute_max_slave_count = {
+       .attr = {
+                       .name = "w1_master_max_slave_count",
+                       .mode = S_IRUGO,
+                       .owner = THIS_MODULE
+       },
+       .show = &w1_master_attribute_show_max_slave_count,
+};
+static struct device_attribute w1_master_attribute_timeout = {
+       .attr = {
+                       .name = "w1_master_timeout",
+                       .mode = S_IRUGO,
+                       .owner = THIS_MODULE
+       },
+       .show = &w1_master_attribute_show_timeout,
+};
+static struct device_attribute w1_master_attribute_pointer = {
+       .attr = {
+                       .name = "w1_master_pointer",
+                       .mode = S_IRUGO,
+                       .owner = THIS_MODULE
+       },
+       .show = &w1_master_attribute_show_pointer,
+};
+static struct device_attribute w1_master_attribute_name = {
+       .attr = {
+                       .name = "w1_master_name",
+                       .mode = S_IRUGO,
+                       .owner = THIS_MODULE
+       },
+       .show = &w1_master_attribute_show_name,
 };
 
 static struct bin_attribute w1_slave_bin_attribute = {
@@ -204,11 +319,11 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
        sl->dev.release = &w1_slave_release;
 
        snprintf(&sl->dev.bus_id[0], sizeof(sl->dev.bus_id),
-                 "%x-%llx",
+                 "%02x-%012llx",
                  (unsigned int) sl->reg_num.family,
                  (unsigned long long) sl->reg_num.id);
        snprintf (&sl->name[0], sizeof(sl->name),
-                 "%x-%llx",
+                 "%02x-%012llx",
                  (unsigned int) sl->reg_num.family,
                  (unsigned long long) sl->reg_num.id);
 
@@ -223,12 +338,16 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
                return err;
        }
 
-       w1_slave_bin_attribute.read = sl->family->fops->rbin;
-       w1_slave_attribute.show = sl->family->fops->rname;
-       w1_slave_attribute_val.show = sl->family->fops->rval;
-       w1_slave_attribute_val.attr.name = sl->family->fops->rvalname;
+       memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin));
+       memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name));
+       memcpy(&sl->attr_val, &w1_slave_attribute_val, sizeof(sl->attr_val));
+       
+       sl->attr_bin.read = sl->family->fops->rbin;
+       sl->attr_name.show = sl->family->fops->rname;
+       sl->attr_val.show = sl->family->fops->rval;
+       sl->attr_val.attr.name = sl->family->fops->rvalname;
 
-       err = device_create_file(&sl->dev, &w1_slave_attribute);
+       err = device_create_file(&sl->dev, &sl->attr_name);
        if (err < 0) {
                dev_err(&sl->dev,
                         "sysfs file creation for [%s] failed. err=%d\n",
@@ -237,23 +356,23 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
                return err;
        }
 
-       err = device_create_file(&sl->dev, &w1_slave_attribute_val);
+       err = device_create_file(&sl->dev, &sl->attr_val);
        if (err < 0) {
                dev_err(&sl->dev,
                         "sysfs file creation for [%s] failed. err=%d\n",
                         sl->dev.bus_id, err);
-               device_remove_file(&sl->dev, &w1_slave_attribute);
+               device_remove_file(&sl->dev, &sl->attr_name);
                device_unregister(&sl->dev);
                return err;
        }
 
-       err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_bin_attribute);
+       err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
        if (err < 0) {
                dev_err(&sl->dev,
                         "sysfs file creation for [%s] failed. err=%d\n",
                         sl->dev.bus_id, err);
-               device_remove_file(&sl->dev, &w1_slave_attribute);
-               device_remove_file(&sl->dev, &w1_slave_attribute_val);
+               device_remove_file(&sl->dev, &sl->attr_name);
+               device_remove_file(&sl->dev, &sl->attr_val);
                device_unregister(&sl->dev);
                return err;
        }
@@ -268,6 +387,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
        struct w1_slave *sl;
        struct w1_family *f;
        int err;
+       struct w1_netlink_msg msg;
 
        sl = kmalloc(sizeof(struct w1_slave), GFP_KERNEL);
        if (!sl) {
@@ -281,6 +401,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 
        sl->owner = THIS_MODULE;
        sl->master = dev;
+       set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
 
        memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
        atomic_set(&sl->refcnt, 0);
@@ -290,8 +411,8 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
        f = w1_family_registered(rn->family);
        if (!f) {
                spin_unlock(&w1_flock);
-               dev_info(&dev->dev, "Family %x is not registered.\n",
-                         rn->family);
+               dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n",
+                         rn->family, rn->family, rn->id, rn->crc);
                kfree(sl);
                return -ENODEV;
        }
@@ -312,20 +433,31 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 
        dev->slave_count++;
 
+       memcpy(&msg.id.id, rn, sizeof(msg.id.id));
+       msg.type = W1_SLAVE_ADD;
+       w1_netlink_send(dev, &msg);
+
        return 0;
 }
 
 static void w1_slave_detach(struct w1_slave *sl)
 {
+       struct w1_netlink_msg msg;
+       
        dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name);
 
        while (atomic_read(&sl->refcnt))
                schedule_timeout(10);
 
-       sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_bin_attribute);
-       device_remove_file(&sl->dev, &w1_slave_attribute);
+       sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
+       device_remove_file(&sl->dev, &sl->attr_name);
+       device_remove_file(&sl->dev, &sl->attr_val);
        device_unregister(&sl->dev);
        w1_family_put(sl->family);
+
+       memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
+       msg.type = W1_SLAVE_REMOVE;
+       w1_netlink_send(sl->master, &msg);
 }
 
 static void w1_search(struct w1_master *dev)
@@ -337,12 +469,9 @@ static void w1_search(struct w1_master *dev)
        struct list_head *ent;
        struct w1_slave *sl;
        int family_found = 0;
-       struct w1_netlink_msg msg;
 
        dev->attempts++;
 
-       memset(&msg, 0, sizeof(msg));
-
        search_bit = id_bit = comp_bit = 0;
        rn = tmp = last = 0;
        last_device = last_zero = last_family_desc = 0;
@@ -368,8 +497,6 @@ static void w1_search(struct w1_master *dev)
                }
 
 #if 1
-               memset(&msg, 0, sizeof(msg));
-
                w1_write_8(dev, W1_SEARCH);
                for (i = 0; i < 64; ++i) {
                        /*
@@ -413,9 +540,6 @@ static void w1_search(struct w1_master *dev)
 
                }
 #endif
-               msg.id.w1_id = rn;
-               msg.val = w1_calc_crc8((u8 *) & rn, 7);
-               w1_netlink_send(dev, &msg);
 
                if (desc_bit == last_zero)
                        last_device = 1;
@@ -432,8 +556,10 @@ static void w1_search(struct w1_master *dev)
 
                        if (sl->reg_num.family == tmp->family &&
                            sl->reg_num.id == tmp->id &&
-                           sl->reg_num.crc == tmp->crc)
+                           sl->reg_num.crc == tmp->crc) {
+                               set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
                                break;
+                       }
                        else if (sl->reg_num.family == tmp->family) {
                                family_found = 1;
                                break;
@@ -443,12 +569,38 @@ static void w1_search(struct w1_master *dev)
                }
 
                if (slave_count == dev->slave_count &&
-                   msg.val && (*((__u8 *) & msg.val) == msg.id.id.crc)) {
+                   ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
                        w1_attach_slave_device(dev, (struct w1_reg_num *) &rn);
                }
        }
 }
 
+int w1_create_master_attributes(struct w1_master *dev)
+{
+       if (    device_create_file(&dev->dev, &w1_master_attribute_slaves) < 0 ||
+               device_create_file(&dev->dev, &w1_master_attribute_slave_count) < 0 ||
+               device_create_file(&dev->dev, &w1_master_attribute_attempts) < 0 ||
+               device_create_file(&dev->dev, &w1_master_attribute_max_slave_count) < 0 ||
+               device_create_file(&dev->dev, &w1_master_attribute_timeout) < 0||
+               device_create_file(&dev->dev, &w1_master_attribute_pointer) < 0||
+               device_create_file(&dev->dev, &w1_master_attribute_name) < 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+void w1_destroy_master_attributes(struct w1_master *dev)
+{
+       device_remove_file(&dev->dev, &w1_master_attribute_slaves);
+       device_remove_file(&dev->dev, &w1_master_attribute_slave_count);
+       device_remove_file(&dev->dev, &w1_master_attribute_attempts);
+       device_remove_file(&dev->dev, &w1_master_attribute_max_slave_count);
+       device_remove_file(&dev->dev, &w1_master_attribute_timeout);
+       device_remove_file(&dev->dev, &w1_master_attribute_pointer);
+       device_remove_file(&dev->dev, &w1_master_attribute_name);
+}
+
+
 int w1_control(void *data)
 {
        struct w1_slave *sl;
@@ -462,7 +614,7 @@ int w1_control(void *data)
        while (!control_needs_exit || have_to_wait) {
                have_to_wait = 0;
 
-               timeout = w1_timeout;
+               timeout = w1_timeout*HZ;
                do {
                        timeout = interruptible_sleep_on_timeout(&w1_control_wait, timeout);
                        if (current->flags & PF_FREEZE)
@@ -516,7 +668,7 @@ int w1_control(void *data)
                                        kfree(sl);
                                }
                        }
-                       device_remove_file(&dev->dev, &w1_master_attribute);
+                       w1_destroy_master_attributes(dev);
                        atomic_dec(&dev->refcnt);
                }
        }
@@ -528,12 +680,14 @@ int w1_process(void *data)
 {
        struct w1_master *dev = (struct w1_master *) data;
        unsigned long timeout;
+       struct list_head *ent, *n;
+       struct w1_slave *sl;
 
        daemonize("%s", dev->name);
        allow_signal(SIGTERM);
 
        while (!dev->need_exit) {
-               timeout = w1_timeout;
+               timeout = w1_timeout*HZ;
                do {
                        timeout = interruptible_sleep_on_timeout(&dev->kwait, timeout);
                        if (current->flags & PF_FREEZE)
@@ -551,7 +705,28 @@ int w1_process(void *data)
 
                if (down_interruptible(&dev->mutex))
                        continue;
-               w1_search(dev);
+
+               list_for_each_safe(ent, n, &dev->slist) {
+                       sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+
+                       if (sl)
+                               clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
+               }
+               
+               w1_search(dev);
+               
+               list_for_each_safe(ent, n, &dev->slist) {
+                       sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+
+                       if (sl && !test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) {
+                               list_del (&sl->w1_slave_entry);
+
+                               w1_slave_detach (sl);
+                               kfree (sl);
+
+                               dev->slave_count--;
+                       }
+               }
                up(&dev->mutex);
        }
 
@@ -621,3 +796,6 @@ void w1_fini(void)
 
 module_init(w1_init);
 module_exit(w1_fini);
+
+EXPORT_SYMBOL(w1_create_master_attributes);
+EXPORT_SYMBOL(w1_destroy_master_attributes);
index aba042d..54a3437 100644 (file)
@@ -52,6 +52,8 @@ struct w1_reg_num
 #define W1_READ_PSUPPLY                0xB4
 #define W1_MATCH_ROM           0x55
 
+#define W1_SLAVE_ACTIVE                (1<<0)
+
 struct w1_slave
 {
        struct module           *owner;
@@ -60,11 +62,15 @@ struct w1_slave
        struct w1_reg_num       reg_num;
        atomic_t                refcnt;
        u8                      rom[9];
+       u32                     flags;
 
        struct w1_master        *master;
        struct w1_family        *family;
        struct device           dev;
        struct completion       dev_released;
+
+       struct bin_attribute    attr_bin;
+       struct device_attribute attr_name, attr_val;
 };
 
 struct w1_bus_master
@@ -73,6 +79,16 @@ struct w1_bus_master
 
        u8                      (*read_bit)(unsigned long);
        void                    (*write_bit)(unsigned long, u8);
+       
+       u8                      (*read_byte)(unsigned long);
+       void                    (*write_byte)(unsigned long, u8);
+       
+       u8                      (*read_block)(unsigned long, u8 *, int);
+       void                    (*write_block)(unsigned long, u8 *, int);
+       
+       u8                      (*touch_bit)(unsigned long, u8);
+  
+       u8                      (*reset_bus)(unsigned long);
 };
 
 struct w1_master
@@ -107,6 +123,9 @@ struct w1_master
        struct sock             *nls;
 };
 
+int w1_create_master_attributes(struct w1_master *);
+void w1_destroy_master_attributes(struct w1_master *);
+
 #endif /* __KERNEL__ */
 
 #endif /* __W1_H */
index 9b8443c..6a62d2a 100644 (file)
 spinlock_t w1_flock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(w1_families);
 
+static int w1_check_family(struct w1_family *f)
+{
+       if (!f->fops->rname || !f->fops->rbin || !f->fops->rval || !f->fops->rvalname)
+               return -EINVAL;
+
+       return 0;
+}
+
 int w1_register_family(struct w1_family *newf)
 {
        struct list_head *ent, *n;
        struct w1_family *f;
        int ret = 0;
 
+       if (w1_check_family(newf))
+               return -EINVAL;
+
        spin_lock(&w1_flock);
        list_for_each_safe(ent, n, &w1_families) {
                f = list_entry(ent, struct w1_family, family_entry);
index 15f44fe..03a2de7 100644 (file)
@@ -28,7 +28,7 @@
 
 #define W1_FAMILY_DEFAULT      0
 #define W1_FAMILY_THERM                0x10
-#define W1_FAMILY_IBUT         0xff /* ? */
+#define W1_FAMILY_SMEM         0x01
 
 #define MAXNAMELEN             32
 
index c75e9f7..e671d40 100644 (file)
 
 #include "w1.h"
 #include "w1_log.h"
+#include "w1_netlink.h"
 
 static u32 w1_ids = 1;
 
 extern struct device_driver w1_driver;
 extern struct bus_type w1_bus_type;
 extern struct device w1_device;
-extern struct device_attribute w1_master_attribute;
 extern int w1_max_slave_count;
 extern struct list_head w1_masters;
 extern spinlock_t w1_mlock;
@@ -119,6 +119,7 @@ int w1_add_master_device(struct w1_bus_master *master)
 {
        struct w1_master *dev;
        int retval = 0;
+       struct w1_netlink_msg msg;
 
        dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, &w1_driver, &w1_device);
        if (!dev)
@@ -133,7 +134,7 @@ int w1_add_master_device(struct w1_bus_master *master)
                goto err_out_free_dev;
        }
 
-       retval = device_create_file(&dev->dev, &w1_master_attribute);
+       retval =  w1_create_master_attributes(dev);
        if (retval)
                goto err_out_kill_thread;
 
@@ -145,6 +146,11 @@ int w1_add_master_device(struct w1_bus_master *master)
        list_add(&dev->w1_master_entry, &w1_masters);
        spin_unlock(&w1_mlock);
 
+       msg.id.mst.id = dev->id;
+       msg.id.mst.pid = dev->kpid;
+       msg.type = W1_MASTER_ADD;
+       w1_netlink_send(dev, &msg);
+
        return 0;
 
 err_out_kill_thread:
@@ -164,6 +170,7 @@ err_out_free_dev:
 void __w1_remove_master_device(struct w1_master *dev)
 {
        int err;
+       struct w1_netlink_msg msg;
 
        dev->need_exit = 1;
        err = kill_proc(dev->kpid, SIGTERM, 1);
@@ -175,6 +182,11 @@ void __w1_remove_master_device(struct w1_master *dev)
        while (atomic_read(&dev->refcnt))
                schedule_timeout(10);
 
+       msg.id.mst.id = dev->id;
+       msg.id.mst.pid = dev->kpid;
+       msg.type = W1_MASTER_REMOVE;
+       w1_netlink_send(dev, &msg);
+
        w1_free_dev(dev);
 }
 
index 9baacee..765f065 100644 (file)
@@ -55,6 +55,14 @@ void w1_delay(unsigned long tm)
        udelay(tm * w1_delay_parm);
 }
 
+u8 w1_touch_bit(struct w1_master *dev, int bit)
+{
+       if (dev->bus_master->touch_bit)
+               return dev->bus_master->touch_bit(dev->bus_master->data, bit);
+       else
+               return w1_read_bit(dev);
+}
+
 void w1_write_bit(struct w1_master *dev, int bit)
 {
        if (bit) {
@@ -74,8 +82,11 @@ void w1_write_8(struct w1_master *dev, u8 byte)
 {
        int i;
 
-       for (i = 0; i < 8; ++i)
-               w1_write_bit(dev, (byte >> i) & 0x1);
+       if (dev->bus_master->write_byte)
+               dev->bus_master->write_byte(dev->bus_master->data, byte);
+       else
+               for (i = 0; i < 8; ++i)
+                       w1_write_bit(dev, (byte >> i) & 0x1);
 }
 
 u8 w1_read_bit(struct w1_master *dev)
@@ -98,23 +109,57 @@ u8 w1_read_8(struct w1_master * dev)
        int i;
        u8 res = 0;
 
-       for (i = 0; i < 8; ++i)
-               res |= (w1_read_bit(dev) << i);
+       if (dev->bus_master->read_byte)
+               res = dev->bus_master->read_byte(dev->bus_master->data);
+       else
+               for (i = 0; i < 8; ++i)
+                       res |= (w1_read_bit(dev) << i);
 
        return res;
 }
 
+void w1_write_block(struct w1_master *dev, u8 *buf, int len)
+{
+       int i;
+
+       if (dev->bus_master->write_block)
+               dev->bus_master->write_block(dev->bus_master->data, buf, len);
+       else
+               for (i = 0; i < len; ++i)
+                       w1_write_8(dev, buf[i]);
+}
+
+u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
+{
+       int i;
+       u8 ret;
+
+       if (dev->bus_master->read_block)
+               ret = dev->bus_master->read_block(dev->bus_master->data, buf, len);
+       else {
+               for (i = 0; i < len; ++i)
+                       buf[i] = w1_read_8(dev);
+               ret = len;
+       }
+
+       return ret;
+}
+
 int w1_reset_bus(struct w1_master *dev)
 {
-       int result;
+       int result = 0;
 
-       dev->bus_master->write_bit(dev->bus_master->data, 0);
-       w1_delay(480);
-       dev->bus_master->write_bit(dev->bus_master->data, 1);
-       w1_delay(70);
+       if (dev->bus_master->reset_bus)
+               result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
+       else {
+               dev->bus_master->write_bit(dev->bus_master->data, 0);
+               w1_delay(480);
+               dev->bus_master->write_bit(dev->bus_master->data, 1);
+               w1_delay(70);
 
-       result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1;
-       w1_delay(410);
+               result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1;
+               w1_delay(410);
+       }
 
        return result;
 }
@@ -136,3 +181,5 @@ EXPORT_SYMBOL(w1_read_8);
 EXPORT_SYMBOL(w1_reset_bus);
 EXPORT_SYMBOL(w1_calc_crc8);
 EXPORT_SYMBOL(w1_delay);
+EXPORT_SYMBOL(w1_read_block);
+EXPORT_SYMBOL(w1_write_block);
index e493a87..f63c210 100644 (file)
 #include "w1.h"
 
 void w1_delay(unsigned long);
+u8 w1_touch_bit(struct w1_master *, int);
 void w1_write_bit(struct w1_master *, int);
 void w1_write_8(struct w1_master *, u8);
 u8 w1_read_bit(struct w1_master *);
 u8 w1_read_8(struct w1_master *);
 int w1_reset_bus(struct w1_master *);
 u8 w1_calc_crc8(u8 *, int);
+void w1_write_block(struct w1_master *, u8 *, int);
+u8 w1_read_block(struct w1_master *, u8 *, int);
 
 #endif /* __W1_IO_H */
index 7064ded..ea1b530 100644 (file)
 
 #include "w1.h"
 
+enum w1_netlink_message_types {
+       W1_SLAVE_ADD = 0,
+       W1_SLAVE_REMOVE,
+       W1_MASTER_ADD,
+       W1_MASTER_REMOVE,
+};
+
 struct w1_netlink_msg 
 {
+       __u8                            type;
+       __u8                            reserved[3];
        union
        {
                struct w1_reg_num       id;
                __u64                   w1_id;
+               struct
+               {
+                       __u32           id;
+                       __u32           pid;
+               } mst;
        } id;
-       __u64                           val;
 };
 
 #ifdef __KERNEL__
diff --git a/drivers/w1/w1_smem.c b/drivers/w1/w1_smem.c
new file mode 100644 (file)
index 0000000..ab82eb7
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *     w1_smem.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems 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 <asm/types.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/types.h>
+
+#include "w1.h"
+#include "w1_io.h"
+#include "w1_int.h"
+#include "w1_family.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
+
+static ssize_t w1_smem_read_name(struct device *, char *);
+static ssize_t w1_smem_read_val(struct device *, char *);
+static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t);
+
+static struct w1_family_ops w1_smem_fops = {
+       .rname = &w1_smem_read_name,
+       .rbin = &w1_smem_read_bin,
+       .rval = &w1_smem_read_val,
+       .rvalname = "id",
+};
+
+static ssize_t w1_smem_read_name(struct device *dev, char *buf)
+{
+       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+       return sprintf(buf, "%s\n", sl->name);
+}
+
+static ssize_t w1_smem_read_val(struct device *dev, char *buf)
+{
+       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+       int i;
+       ssize_t count = 0;
+       
+       for (i = 0; i < 9; ++i)
+               count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
+       count += sprintf(buf + count, "\n");
+
+       return count;
+}
+
+static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+       struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
+                                               struct w1_slave, dev);
+       int i;
+
+       atomic_inc(&sl->refcnt);
+       if (down_interruptible(&sl->master->mutex)) {
+               count = 0;
+               goto out_dec;
+       }
+
+       if (off > W1_SLAVE_DATA_SIZE) {
+               count = 0;
+               goto out;
+       }
+       if (off + count > W1_SLAVE_DATA_SIZE) {
+               count = 0;
+               goto out;
+       }
+       for (i = 0; i < 9; ++i)
+               count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
+       count += sprintf(buf + count, "\n");
+       
+out:
+       up(&sl->master->mutex);
+out_dec:
+       atomic_dec(&sl->refcnt);
+
+       return count;
+}
+
+static struct w1_family w1_smem_family = {
+       .fid = W1_FAMILY_SMEM,
+       .fops = &w1_smem_fops,
+};
+
+static int __init w1_smem_init(void)
+{
+       return w1_register_family(&w1_smem_family);
+}
+
+static void __exit w1_smem_fini(void)
+{
+       w1_unregister_family(&w1_smem_family);
+}
+
+module_init(w1_smem_init);
+module_exit(w1_smem_fini);
index 3eed829..d986c60 100644 (file)
@@ -36,6 +36,11 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
 
+static u8 bad_roms[][9] = {
+                               {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87}, 
+                               {}
+                       };
+
 static ssize_t w1_therm_read_name(struct device *, char *);
 static ssize_t w1_therm_read_temp(struct device *, char *);
 static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
@@ -69,14 +74,24 @@ static ssize_t w1_therm_read_temp(struct device *dev, char *buf)
        return sprintf(buf, "%d\n", temp * 1000);
 }
 
+static int w1_therm_check_rom(u8 rom[9])
+{
+       int i;
+
+       for (i=0; i<sizeof(bad_roms)/9; ++i)
+               if (!memcmp(bad_roms[i], rom, 9))
+                       return 1;
+
+       return 0;
+}
+
 static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
 {
        struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
                                                struct w1_slave, dev);
        struct w1_master *dev = sl->master;
        u8 rom[9], crc, verdict;
-       size_t icount;
-       int i;
+       int i, max_trying = 10;
        u16 temp;
 
        atomic_inc(&sl->refcnt);
@@ -89,10 +104,10 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
                count = 0;
                goto out;
        }
-       if (off + count > W1_SLAVE_DATA_SIZE)
-               count = W1_SLAVE_DATA_SIZE - off;
-
-       icount = count;
+       if (off + count > W1_SLAVE_DATA_SIZE) {
+               count = 0;
+               goto out;
+       }
 
        memset(buf, 0, count);
        memset(rom, 0, sizeof(rom));
@@ -100,56 +115,54 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
        count = 0;
        verdict = 0;
        crc = 0;
-       if (!w1_reset_bus(dev)) {
-               u64 id = *(u64 *) & sl->reg_num;
-               int count = 0;
 
-               w1_write_8(dev, W1_MATCH_ROM);
-               for (i = 0; i < 8; ++i)
-                       w1_write_8(dev, (id >> i * 8) & 0xff);
+       while (max_trying--) {
+               if (!w1_reset_bus (dev)) {
+                       int count = 0;
+                       u8 match[9] = {W1_MATCH_ROM, };
 
-               w1_write_8(dev, W1_CONVERT_TEMP);
+                       memcpy(&match[1], (u64 *) & sl->reg_num, 8);
+                       
+                       w1_write_block(dev, match, 9);
 
-               while (dev->bus_master->read_bit(dev->bus_master->data) == 0
-                      && count < 10) {
-                       w1_delay(1);
-                       count++;
-               }
+                       w1_write_8(dev, W1_CONVERT_TEMP);
 
-               if (count < 10) {
-                       if (!w1_reset_bus(dev)) {
-                               w1_write_8(dev, W1_MATCH_ROM);
-                               for (i = 0; i < 8; ++i)
-                                       w1_write_8(dev,
-                                                  (id >> i * 8) & 0xff);
+                       if (count < 10) {
+                               if (!w1_reset_bus(dev)) {
+                                       w1_write_block(dev, match, 9);
 
-                               w1_write_8(dev, W1_READ_SCRATCHPAD);
-                               for (i = 0; i < 9; ++i)
-                                       rom[i] = w1_read_8(dev);
+                                       w1_write_8(dev, W1_READ_SCRATCHPAD);
+                                       if ((count = w1_read_block(dev, rom, 9)) != 9) {
+                                               dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
+                                       }
 
-                               crc = w1_calc_crc8(rom, 8);
+                                       crc = w1_calc_crc8(rom, 8);
 
-                               if (rom[8] == crc && rom[0])
-                                       verdict = 1;
+                                       if (rom[8] == crc && rom[0])
+                                               verdict = 1;
+                               }
                        }
+                       else
+                               dev_warn(&dev->dev,
+                                         "18S20 doesn't respond to CONVERT_TEMP.\n");
                }
-               else
-                       dev_warn(&dev->dev,
-                                 "18S20 doesn't respond to CONVERT_TEMP.\n");
+
+               if (!w1_therm_check_rom(rom))
+                       break;
        }
 
        for (i = 0; i < 9; ++i)
-               count += snprintf(buf + count, icount - count, "%02x ", rom[i]);
-       count += snprintf(buf + count, icount - count, ": crc=%02x %s\n",
+               count += sprintf(buf + count, "%02x ", rom[i]);
+       count += sprintf(buf + count, ": crc=%02x %s\n",
                           crc, (verdict) ? "YES" : "NO");
        if (verdict)
                memcpy(sl->rom, rom, sizeof(sl->rom));
        for (i = 0; i < 9; ++i)
-               count += snprintf(buf + count, icount - count, "%02x ", sl->rom[i]);
+               count += sprintf(buf + count, "%02x ", sl->rom[i]);
        temp = 0;
        temp <<= sl->rom[1] / 2;
        temp |= sl->rom[0] / 2;
-       count += snprintf(buf + count, icount - count, "t=%u\n", temp);
+       count += sprintf(buf + count, "t=%u\n", temp);
 out:
        up(&dev->mutex);
 out_dec:
index 32f99d8..f621726 100644 (file)
@@ -5,7 +5,7 @@
 obj-$(CONFIG_ZORRO)    += zorro.o zorro-driver.o zorro-sysfs.o names.o
 obj-$(CONFIG_PROC_FS)  += proc.o
 
-host-progs             := gen-devlist
+hostprogs-y            := gen-devlist
 
 # Files generated that shall be removed upon make clean
 clean-files := devlist.h
index 6aed04e..63f5df9 100644 (file)
@@ -64,15 +64,9 @@ struct adfs_discmap {
        unsigned int            dm_endbit;
 };
 
-/* dir stuff */
-
-
 /* Inode stuff */
-int adfs_get_block(struct inode *inode, sector_t block,
-                  struct buffer_head *bh, int create);
 struct inode *adfs_iget(struct super_block *sb, struct object_info *obj);
-void adfs_read_inode(struct inode *inode);
-void adfs_write_inode(struct inode *inode,int unused);
+int adfs_write_inode(struct inode *inode,int unused);
 int adfs_notify_change(struct dentry *dentry, struct iattr *attr);
 
 /* map.c */
@@ -84,9 +78,6 @@ void __adfs_error(struct super_block *sb, const char *function,
                  const char *fmt, ...);
 #define adfs_error(sb, fmt...) __adfs_error(sb, __FUNCTION__, fmt)
 
-/* namei.c */
-extern struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
-
 /* super.c */
 
 /*
index 1c047fc..d80a2d7 100644 (file)
@@ -268,7 +268,8 @@ struct dentry_operations adfs_dentry_operations = {
        .d_compare      = adfs_compare,
 };
 
-struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *
+adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = NULL;
        struct object_info obj;
index 1c60626..b61648b 100644 (file)
@@ -93,7 +93,7 @@ static inline void adfs_writename(char *to, char *from, int maxlen)
 #define dir_u32(idx)                           \
        ({ int _buf = idx >> blocksize_bits;    \
           int _off = idx - (_buf << blocksize_bits);\
-         *(u32 *)(bh[_buf]->b_data + _off);    \
+         *(__le32 *)(bh[_buf]->b_data + _off); \
        })
 
 #define bufoff(_bh,_idx)                       \
@@ -112,7 +112,7 @@ adfs_dir_checkbyte(const struct adfs_dir *dir)
 {
        struct buffer_head * const *bh = dir->bh;
        const int blocksize_bits = dir->sb->s_blocksize_bits;
-       union { u32 *ptr32; u8 *ptr8; } ptr, end;
+       union { __le32 *ptr32; u8 *ptr8; } ptr, end;
        u32 dircheck = 0;
        int last = 5 - 26;
        int i = 0;
@@ -125,7 +125,7 @@ adfs_dir_checkbyte(const struct adfs_dir *dir)
        do {
                last += 26;
                do {
-                       dircheck = cpu_to_le32(dir_u32(i)) ^ ror13(dircheck);
+                       dircheck = le32_to_cpu(dir_u32(i)) ^ ror13(dircheck);
 
                        i += sizeof(u32);
                } while (i < (last & ~3));
@@ -155,8 +155,8 @@ adfs_dir_checkbyte(const struct adfs_dir *dir)
        end.ptr8 = ptr.ptr8 + 36;
 
        do {
-               unsigned int v = *ptr.ptr32++;
-               dircheck = cpu_to_le32(v) ^ ror13(dircheck);
+               __le32 v = *ptr.ptr32++;
+               dircheck = le32_to_cpu(v) ^ ror13(dircheck);
        } while (ptr.ptr32 < end.ptr32);
 
        return (dircheck ^ (dircheck >> 8) ^ (dircheck >> 16) ^ (dircheck >> 24)) & 0xff;
@@ -165,7 +165,7 @@ adfs_dir_checkbyte(const struct adfs_dir *dir)
 /*
  * Read and check that a directory is valid
  */
-int
+static int
 adfs_dir_read(struct super_block *sb, unsigned long object_id,
              unsigned int size, struct adfs_dir *dir)
 {
@@ -260,7 +260,7 @@ adfs_obj2dir(struct adfs_direntry *de, struct object_info *obj)
  * get a directory entry.  Note that the caller is responsible
  * for holding the relevant locks.
  */
-int
+static int
 __adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj)
 {
        struct super_block *sb = dir->sb;
@@ -290,7 +290,7 @@ __adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj)
        return 0;
 }
 
-int
+static int
 __adfs_dir_put(struct adfs_dir *dir, int pos, struct object_info *obj)
 {
        struct super_block *sb = dir->sb;
index a65f653..b55aa41 100644 (file)
 struct adfs_bigdirheader {
        __u8    startmasseq;
        __u8    bigdirversion[3];
-       __u32   bigdirstartname;
-       __u32   bigdirnamelen;
-       __u32   bigdirsize;
-       __u32   bigdirentries;
-       __u32   bigdirnamesize;
-       __u32   bigdirparent;
+       __le32  bigdirstartname;
+       __le32  bigdirnamelen;
+       __le32  bigdirsize;
+       __le32  bigdirentries;
+       __le32  bigdirnamesize;
+       __le32  bigdirparent;
        char    bigdirname[1];
 };
 
 struct adfs_bigdirentry {
-       __u32   bigdirload;
-       __u32   bigdirexec;
-       __u32   bigdirlen;
-       __u32   bigdirindaddr;
-       __u32   bigdirattr;
-       __u32   bigdirobnamelen;
-       __u32   bigdirobnameptr;
+       __le32  bigdirload;
+       __le32  bigdirexec;
+       __le32  bigdirlen;
+       __le32  bigdirindaddr;
+       __le32  bigdirattr;
+       __le32  bigdirobnamelen;
+       __le32  bigdirobnameptr;
 };
 
 struct adfs_bigdirtail {
-       __u32   bigdirendname;
+       __le32  bigdirendname;
        __u8    bigdirendmasseq;
        __u8    reserved[2];
        __u8    bigdircheckbyte;
index f17ccbc..fee8214 100644 (file)
@@ -24,8 +24,9 @@
  * Lookup/Create a block at offset 'block' into 'inode'.  We currently do
  * not support creation of new blocks, so we return -EIO for this case.
  */
-int
-adfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh, int create)
+static int
+adfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh,
+              int create)
 {
        if (block < 0)
                goto abort_negative;
@@ -372,10 +373,11 @@ out:
  * The adfs-specific inode data has already been updated by
  * adfs_notify_change()
  */
-void adfs_write_inode(struct inode *inode, int unused)
+int adfs_write_inode(struct inode *inode, int unused)
 {
        struct super_block *sb = inode->i_sb;
        struct object_info obj;
+       int ret;
 
        lock_kernel();
        obj.file_id     = inode->i_ino;
@@ -386,7 +388,8 @@ void adfs_write_inode(struct inode *inode, int unused)
        obj.attr        = ADFS_I(inode)->attr;
        obj.size        = inode->i_size;
 
-       adfs_dir_update(sb, &obj);
+       ret = adfs_dir_update(sb, &obj);
        unlock_kernel();
+       return ret;
 }
 MODULE_LICENSE("GPL");
index 7c59ca7..48c7a31 100644 (file)
@@ -92,9 +92,8 @@ lookup_zone(const struct adfs_discmap *dm, const unsigned int idlen,
                 * find end of fragment
                 */
                {
-                       u32 v, *_map = (u32 *)map;
-
-                       v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
+                       __le32 *_map = (__le32 *)map;
+                       u32 v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
                        while (v == 0) {
                                mapptr = (mapptr & ~31) + 32;
                                if (mapptr >= mapsize)
@@ -171,9 +170,8 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm)
                 * find end of fragment
                 */
                {
-                       u32 v, *_map = (u32 *)map;
-
-                       v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
+                       __le32 *_map = (__le32 *)map;
+                       u32 v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
                        while (v == 0) {
                                mapptr = (mapptr & ~31) + 32;
                                if (mapptr >= mapsize)
index e9462e7..87e8694 100644 (file)
@@ -62,7 +62,7 @@ static int adfs_checkdiscrecord(struct adfs_discrecord *dr)
         * are unable to represent sector offsets in
         * 32 bits.  This works out at 2.0 TB.
         */
-       if (dr->disc_size_high >> dr->log2secsize)
+       if (le32_to_cpu(dr->disc_size_high) >> dr->log2secsize)
                return 1;
 
        /* idlen must be no greater than 19 v2 [1.0] */
@@ -241,7 +241,7 @@ static int init_inodecache(void)
 {
        adfs_inode_cachep = kmem_cache_create("adfs_inode_cache",
                                             sizeof(struct adfs_inode_info),
-                                            0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+                                            0, SLAB_RECLAIM_ACCOUNT,
                                             init_once, NULL);
        if (adfs_inode_cachep == NULL)
                return -ENOMEM;
@@ -300,8 +300,8 @@ static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_di
        i = zone - 1;
        dm[0].dm_startblk = 0;
        dm[0].dm_startbit = ADFS_DR_SIZE_BITS;
-       dm[i].dm_endbit   = (dr->disc_size_high << (32 - dr->log2bpmb)) +
-                           (dr->disc_size >> dr->log2bpmb) +
+       dm[i].dm_endbit   = (le32_to_cpu(dr->disc_size_high) << (32 - dr->log2bpmb)) +
+                           (le32_to_cpu(dr->disc_size) >> dr->log2bpmb) +
                            (ADFS_DR_SIZE_BITS - i * zone_size);
 
        if (adfs_checkmap(sb, dm))
@@ -439,7 +439,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
         * get the root_size from the disc record.
         */
        if (asb->s_version) {
-               root_obj.size = dr->root_size;
+               root_obj.size = le32_to_cpu(dr->root_size);
                asb->s_dir     = &adfs_fplus_dir_ops;
                asb->s_namelen = ADFS_FPLUS_NAME_LEN;
        } else {
index f2cbba3..d11f39c 100644 (file)
@@ -37,7 +37,7 @@ struct dentry_operations affs_dentry_operations = {
        .d_compare      = affs_compare_dentry,
 };
 
-struct dentry_operations affs_intl_dentry_operations = {
+static struct dentry_operations affs_intl_dentry_operations = {
        .d_hash         = affs_intl_hash_dentry,
        .d_compare      = affs_intl_compare_dentry,
 };
index fc2c1a9..c476fde 100644 (file)
@@ -93,9 +93,10 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
 
 /*****************************************************************************/
 /*
- * attempt to fetch the status of an inode, coelescing multiple simultaneous fetches
+ * attempt to fetch the status of an inode, coelescing multiple simultaneous
+ * fetches
  */
-int afs_inode_fetch_status(struct inode *inode)
+static int afs_inode_fetch_status(struct inode *inode)
 {
        struct afs_vnode *vnode;
        int ret;
index c567afd..955dbef 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/completion.h>
@@ -47,7 +48,7 @@ MODULE_LICENSE("GPL");
 
 static char *rootcell;
 
-MODULE_PARM(rootcell, "s");
+module_param(rootcell, charp, 0);
 MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
 
 
index 65b0b6e..e3d6011 100644 (file)
@@ -71,9 +71,6 @@ struct afs_vldbentry {
 
 };
 
-/* probe a volume location server to see if it is still alive */
-extern int afs_rxvl_probe(struct afs_server *server, int alloc_flags);
-
 /* look up a volume location database entry by name */
 extern int afs_rxvl_get_entry_by_name(struct afs_server *server,
                                      const char *volname,
index e3e9611..9867fef 100644 (file)
@@ -86,9 +86,9 @@ static void afs_vnode_cb_timed_out(struct afs_timer *timer)
  * - starts callback expiry timer
  * - adds to server's callback list
  */
-void afs_vnode_finalise_status_update(struct afs_vnode *vnode,
-                                     struct afs_server *server,
-                                     int ret)
+static void afs_vnode_finalise_status_update(struct afs_vnode *vnode,
+                                            struct afs_server *server,
+                                            int ret)
 {
        struct afs_server *oldserver = NULL;
 
index bbe4634..1e69188 100644 (file)
@@ -99,7 +99,6 @@ extern int afs_vlocation_lookup(struct afs_cell *cell,
 
 #define afs_get_vlocation(V) do { atomic_inc(&(V)->usage); } while(0)
 
-extern void __afs_put_vlocation(struct afs_vlocation *vlocation);
 extern void afs_put_vlocation(struct afs_vlocation *vlocation);
 extern void afs_vlocation_do_timeout(struct afs_vlocation *vlocation);
 
index 9ef5b31..f01ebd7 100644 (file)
@@ -85,7 +85,7 @@ static void bfs_read_inode(struct inode * inode)
        brelse(bh);
 }
 
-static void bfs_write_inode(struct inode * inode, int unused)
+static int bfs_write_inode(struct inode * inode, int unused)
 {
        unsigned long ino = inode->i_ino;
        struct bfs_inode * di;
@@ -94,7 +94,7 @@ static void bfs_write_inode(struct inode * inode, int unused)
 
        if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) {
                printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino);
-               return;
+               return -EIO;
        }
 
        lock_kernel();
@@ -103,7 +103,7 @@ static void bfs_write_inode(struct inode * inode, int unused)
        if (!bh) {
                printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
                unlock_kernel();
-               return;
+               return -EIO;
        }
 
        off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
@@ -129,6 +129,7 @@ static void bfs_write_inode(struct inode * inode, int unused)
        mark_buffer_dirty(bh);
        brelse(bh);
        unlock_kernel();
+       return 0;
 }
 
 static void bfs_delete_inode(struct inode * inode)
@@ -245,7 +246,7 @@ static int init_inodecache(void)
 {
        bfs_inode_cachep = kmem_cache_create("bfs_inode_cache",
                                             sizeof(struct bfs_inode_info),
-                                            0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+                                            0, SLAB_RECLAIM_ACCOUNT,
                                             init_once, NULL);
        if (bfs_inode_cachep == NULL)
                return -ENOMEM;
index 8fdf3d7..1782310 100755 (executable)
@@ -61,7 +61,7 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
        if((cifs_pdu == NULL) || (ses == NULL))
                return -EINVAL;
 
-       if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0) 
+       if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) 
                return rc;
 
        spin_lock(&GlobalMid_Lock);
@@ -107,13 +107,11 @@ int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
        if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
                cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
 
-       expected_sequence_number = cpu_to_le32(expected_sequence_number);
-
        /* save off the origiginal signature so we can modify the smb and check
                its signature against what the server sent */
        memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
 
-       cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number;
+       cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(expected_sequence_number);
        cifs_pdu->Signature.Sequence.Reserved = 0;
 
        rc = cifs_calculate_signature(cifs_pdu, mac_key,
@@ -153,7 +151,7 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
        wchar_t * unicode_buf;
        unsigned int i,user_name_len,dom_name_len;
 
-       if(ses)
+       if(ses == NULL)
                return -EINVAL;
 
        E_md4hash(ses->password, temp_hash);
@@ -167,7 +165,13 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
                return -EINVAL;
   
        ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
+       if(ucase_buf == NULL)
+               return -ENOMEM;
        unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
+       if(unicode_buf == NULL) {
+               kfree(ucase_buf);
+               return -ENOMEM;
+       }
    
        for(i=0;i<user_name_len;i++)
                ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
index c8d1a56..a78ed0a 100644 (file)
@@ -187,8 +187,8 @@ cifs_inet_pton(int address_family, char *cp,void *dst)
        if (value > addr_class_max[end - bytes])
                return 0;
 
-       address.s_addr = *((int *) bytes) | htonl(value);
-       *((int *)dst) = address.s_addr;
+       address.s_addr = *((__be32 *) bytes) | htonl(value);
+       *((__be32 *)dst) = address.s_addr;
        return 1; /* success */
 }
 
@@ -810,16 +810,13 @@ map_smb_to_linux_error(struct smb_hdr *smb)
 
        if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
                /* translate the newer STATUS codes to old style errors and then to POSIX errors */
-               smb->Status.CifsError = le32_to_cpu(smb->Status.CifsError);
+               __u32 err = le32_to_cpu(smb->Status.CifsError);
                if(cifsFYI)
-                       cifs_print_status(smb->Status.CifsError);
-               ntstatus_to_dos(smb->Status.CifsError, &smberrclass,
-                               &smberrcode);
+                       cifs_print_status(err);
+               ntstatus_to_dos(err, &smberrclass, &smberrcode);
        } else {
                smberrclass = smb->Status.DosError.ErrorClass;
-               smb->Status.DosError.Error =
-                   le16_to_cpu(smb->Status.DosError.Error);
-               smberrcode = smb->Status.DosError.Error;
+               smberrcode = le16_to_cpu(smb->Status.DosError.Error);
        }
 
        /* old style errors */
index f06edcb..5b15cee 100644 (file)
 
 #define NTLMSSP_SIGNATURE "NTLMSSP"
 /* Message Types */
-#define NtLmNegotiate     1
-#define NtLmChallenge     2
-#define NtLmAuthenticate  3
-#define UnknownMessage    8
+#define NtLmNegotiate     cpu_to_le32(1)
+#define NtLmChallenge     cpu_to_le32(2)
+#define NtLmAuthenticate  cpu_to_le32(3)
+#define UnknownMessage    cpu_to_le32(8)
 
 /* Negotiate Flags */
 #define NTLMSSP_NEGOTIATE_UNICODE       0x01   // Text strings are in unicode
 /* appearance */
 
 typedef struct _SECURITY_BUFFER {
-       __u16 Length;
-       __u16 MaximumLength;
-       __u32 Buffer;           /* offset to buffer */
+       __le16 Length;
+       __le16 MaximumLength;
+       __le32 Buffer;          /* offset to buffer */
 } SECURITY_BUFFER;
 
 typedef struct _NEGOTIATE_MESSAGE {
        __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
-       __u32 MessageType;     /* 1 */
-       __u32 NegotiateFlags;
+       __le32 MessageType;     /* 1 */
+       __le32 NegotiateFlags;
        SECURITY_BUFFER DomainName;     /* RFC 1001 style and ASCII */
        SECURITY_BUFFER WorkstationName;        /* RFC 1001 and ASCII */
        char DomainString[0];
@@ -77,9 +77,9 @@ typedef struct _NEGOTIATE_MESSAGE {
 
 typedef struct _CHALLENGE_MESSAGE {
        __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
-       __u32 MessageType;   /* 2 */
+       __le32 MessageType;   /* 2 */
        SECURITY_BUFFER TargetName;
-       __u32 NegotiateFlags;
+       __le32 NegotiateFlags;
        __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
        __u8 Reserved[8];
        SECURITY_BUFFER TargetInfoArray;
@@ -87,14 +87,14 @@ typedef struct _CHALLENGE_MESSAGE {
 
 typedef struct _AUTHENTICATE_MESSAGE {
        __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
-       __u32 MessageType;  /* 3 */
+       __le32 MessageType;  /* 3 */
        SECURITY_BUFFER LmChallengeResponse;
        SECURITY_BUFFER NtChallengeResponse;
        SECURITY_BUFFER DomainName;
        SECURITY_BUFFER UserName;
        SECURITY_BUFFER WorkstationName;
        SECURITY_BUFFER SessionKey;
-       __u32 NegotiateFlags;
+       __le32 NegotiateFlags;
        char UserString[0];
 } AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
 
index 2a1a5cf..5597080 100644 (file)
@@ -28,7 +28,7 @@ int coda_fake_statfs;
 char * coda_f2s(struct CodaFid *f)
 {
        static char s[60];
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
        sprintf(s, "(%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2]);
 #else
        sprintf(s, "(%08x.%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2], f->opaque[3]);
index f0c867c..ba4141a 100644 (file)
@@ -44,6 +44,23 @@ coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *p
        return host_file->f_op->read(host_file, buf, count, ppos);
 }
 
+static ssize_t
+coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
+                  read_actor_t actor, void *target)
+{
+       struct coda_file_info *cfi;
+       struct file *host_file;
+
+       cfi = CODA_FTOC(coda_file);
+       BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
+       host_file = cfi->cfi_container;
+
+       if (!host_file->f_op || !host_file->f_op->sendfile)
+               return -EINVAL;
+
+       return host_file->f_op->sendfile(host_file, ppos, count, actor, target);
+}
+
 static ssize_t
 coda_file_write(struct file *coda_file, const char __user *buf, size_t count, loff_t *ppos)
 {
@@ -278,5 +295,6 @@ struct file_operations coda_file_operations = {
        .flush          = coda_flush,
        .release        = coda_release,
        .fsync          = coda_fsync,
+       .sendfile       = coda_file_sendfile,
 };
 
index 79c8803..569e144 100644 (file)
@@ -55,7 +55,7 @@ static void *alloc_upcall(int opcode, int size)
         inp->ih.opcode = opcode;
        inp->ih.pid = current->pid;
        inp->ih.pgid = process_group(current);
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
        memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
        inp->ih.cred.cr_fsuid = current->fsuid;
 #else
@@ -172,7 +172,7 @@ int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
         union inputArgs *inp;
         union outputArgs *outp;
         int insize, outsize, error;
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
        struct coda_cred cred = { 0, };
        cred.cr_fsuid = uid;
 #endif
@@ -180,7 +180,7 @@ int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
        insize = SIZE(store);
        UPARG(CODA_STORE);
        
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
        memcpy(&(inp->ih.cred), &cred, sizeof(cred));
 #else
        inp->ih.uid = uid;
@@ -219,7 +219,7 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
        union inputArgs *inp;
        union outputArgs *outp;
        int insize, outsize, error;
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
        struct coda_cred cred = { 0, };
        cred.cr_fsuid = uid;
 #endif
@@ -227,7 +227,7 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
        insize = SIZE(release);
        UPARG(CODA_CLOSE);
        
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
        memcpy(&(inp->ih.cred), &cred, sizeof(cred));
 #else
        inp->ih.uid = uid;
index 2265e2a..180607f 100644 (file)
@@ -13,8 +13,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 
-
-extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 static int efs_readpage(struct file *file, struct page *page)
 {
        return block_read_full_page(page,efs_get_block);
@@ -23,7 +21,7 @@ static sector_t _efs_bmap(struct address_space *mapping, sector_t block)
 {
        return generic_block_bmap(mapping,block,efs_get_block);
 }
-struct address_space_operations efs_aops = {
+static struct address_space_operations efs_aops = {
        .readpage = efs_readpage,
        .sync_page = block_sync_page,
        .bmap = _efs_bmap
index d4910e4..467e34b 100644 (file)
@@ -15,6 +15,9 @@
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 
+static int efs_statfs(struct super_block *s, struct kstatfs *buf);
+static int efs_fill_super(struct super_block *s, void *d, int silent);
+
 static struct super_block *efs_get_sb(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data)
 {
@@ -58,7 +61,7 @@ static int init_inodecache(void)
 {
        efs_inode_cachep = kmem_cache_create("efs_inode_cache",
                                sizeof(struct efs_inode_info),
-                               0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+                               0, SLAB_RECLAIM_ACCOUNT,
                                init_once, NULL);
        if (efs_inode_cachep == NULL)
                return -ENOMEM;
@@ -71,7 +74,7 @@ static void destroy_inodecache(void)
                printk(KERN_INFO "efs_inode_cache: not all structures were freed\n");
 }
 
-void efs_put_super(struct super_block *s)
+static void efs_put_super(struct super_block *s)
 {
        kfree(s->s_fs_info);
        s->s_fs_info = NULL;
@@ -118,7 +121,8 @@ module_exit(exit_efs_fs)
 
 static efs_block_t efs_validate_vh(struct volume_header *vh) {
        int             i;
-       unsigned int    cs, csum, *ui;
+       __be32          cs, *ui;
+       int             csum;
        efs_block_t     sblock = 0; /* shuts up gcc */
        struct pt_types *pt_entry;
        int             pt_type, slice = -1;
@@ -132,8 +136,8 @@ static efs_block_t efs_validate_vh(struct volume_header *vh) {
                return 0;
        }
 
-       ui = ((unsigned int *) (vh + 1)) - 1;
-       for(csum = 0; ui >= ((unsigned int *) vh);) {
+       ui = ((__be32 *) (vh + 1)) - 1;
+       for(csum = 0; ui >= ((__be32 *) vh);) {
                cs = *ui--;
                csum += be32_to_cpu(cs);
        }
@@ -213,7 +217,7 @@ static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) {
        return 0;    
 }
 
-int efs_fill_super(struct super_block *s, void *d, int silent)
+static int efs_fill_super(struct super_block *s, void *d, int silent)
 {
        struct efs_sb_info *sb;
        struct buffer_head *bh;
@@ -292,7 +296,7 @@ out_no_fs:
        return -EINVAL;
 }
 
-int efs_statfs(struct super_block *s, struct kstatfs *buf) {
+static int efs_statfs(struct super_block *s, struct kstatfs *buf) {
        struct efs_sb_info *sb = SUPER_INFO(s);
 
        buf->f_type    = EFS_SUPER_MAGIC;       /* efs magic number */
index 01937da..b0a1c4b 100644 (file)
 #define EXT2_ACL_MAX_ENTRIES   32
 
 typedef struct {
-       __u16           e_tag;
-       __u16           e_perm;
-       __u32           e_id;
+       __le16          e_tag;
+       __le16          e_perm;
+       __le32          e_id;
 } ext2_acl_entry;
 
 typedef struct {
-       __u16           e_tag;
-       __u16           e_perm;
+       __le16          e_tag;
+       __le16          e_perm;
 } ext2_acl_entry_short;
 
 typedef struct {
-       __u32           a_version;
+       __le32          a_version;
 } ext2_acl_header;
 
 static inline size_t ext2_acl_size(int count)
index 6af2765..bf30cbf 100644 (file)
@@ -251,7 +251,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
        loff_t pos = filp->f_pos;
        struct inode *inode = filp->f_dentry->d_inode;
        struct super_block *sb = inode->i_sb;
-       unsigned offset = pos & ~PAGE_CACHE_MASK;
+       unsigned int offset = pos & ~PAGE_CACHE_MASK;
        unsigned long n = pos >> PAGE_CACHE_SHIFT;
        unsigned long npages = dir_pages(inode);
        unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
@@ -270,8 +270,13 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
                ext2_dirent *de;
                struct page *page = ext2_get_page(inode, n);
 
-               if (IS_ERR(page))
+               if (IS_ERR(page)) {
+                       ext2_error(sb, __FUNCTION__,
+                                  "bad page in #%lu",
+                                  inode->i_ino);
+                       filp->f_pos += PAGE_CACHE_SIZE - offset;
                        continue;
+               }
                kaddr = page_address(page);
                if (need_revalidate) {
                        offset = ext2_validate_entry(kaddr, offset, chunk_mask);
@@ -303,6 +308,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
                                        goto success;
                                }
                        }
+                       filp->f_pos += le16_to_cpu(de->rec_len);
                }
                ext2_put_page(page);
        }
@@ -310,7 +316,6 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
 success:
        ret = 0;
 done:
-       filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
        filp->f_version = inode->i_version;
        return ret;
 }
index 67f704a..80faa86 100644 (file)
@@ -5,7 +5,7 @@
  * second extended file system inode data in memory
  */
 struct ext2_inode_info {
-       __u32   i_data[15];
+       __le32  i_data[15];
        __u32   i_flags;
        __u32   i_faddr;
        __u8    i_frag_no;
@@ -115,7 +115,7 @@ extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
 
 /* inode.c */
 extern void ext2_read_inode (struct inode *);
-extern void ext2_write_inode (struct inode *, int);
+extern int ext2_write_inode (struct inode *, int);
 extern void ext2_put_inode (struct inode *);
 extern void ext2_delete_inode (struct inode *);
 extern int ext2_sync_inode (struct inode *);
@@ -131,9 +131,6 @@ extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
 /* super.c */
 extern void ext2_error (struct super_block *, const char *, const char *, ...)
        __attribute__ ((format (printf, 3, 4)));
-extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
-                                  const char *, ...)
-       __attribute__ ((NORET_AND format (printf, 3, 4)));
 extern void ext2_warning (struct super_block *, const char *, const char *, ...)
        __attribute__ ((format (printf, 3, 4)));
 extern void ext2_update_dynamic_rev (struct super_block *sb);
index a113ead..6268bcd 100644 (file)
 #define EXT2_XATTR_INDEX_SECURITY              6
 
 struct ext2_xattr_header {
-       __u32   h_magic;        /* magic number for identification */
-       __u32   h_refcount;     /* reference count */
-       __u32   h_blocks;       /* number of disk blocks used */
-       __u32   h_hash;         /* hash value of all attributes */
+       __le32  h_magic;        /* magic number for identification */
+       __le32  h_refcount;     /* reference count */
+       __le32  h_blocks;       /* number of disk blocks used */
+       __le32  h_hash;         /* hash value of all attributes */
        __u32   h_reserved[4];  /* zero right now */
 };
 
 struct ext2_xattr_entry {
        __u8    e_name_len;     /* length of name */
        __u8    e_name_index;   /* attribute name index */
-       __u16   e_value_offs;   /* offset in disk block of value */
-       __u32   e_value_block;  /* disk block attribute is stored on (n/i) */
-       __u32   e_value_size;   /* size of attribute value */
-       __u32   e_hash;         /* hash value of name and value */
+       __le16  e_value_offs;   /* offset in disk block of value */
+       __le32  e_value_block;  /* disk block attribute is stored on (n/i) */
+       __le32  e_value_size;   /* size of attribute value */
+       __le32  e_hash;         /* hash value of name and value */
        char    e_name[0];      /* attribute name */
 };
 
index 9d9d9d2..f83830d 100644 (file)
 #define EXT3_ACL_MAX_ENTRIES   32
 
 typedef struct {
-       __u16           e_tag;
-       __u16           e_perm;
-       __u32           e_id;
+       __le16          e_tag;
+       __le16          e_perm;
+       __le32          e_id;
 } ext3_acl_entry;
 
 typedef struct {
-       __u16           e_tag;
-       __u16           e_perm;
+       __le16          e_tag;
+       __le16          e_perm;
 } ext3_acl_entry_short;
 
 typedef struct {
-       __u32           a_version;
+       __le32          a_version;
 } ext3_acl_header;
 
 static inline size_t ext3_acl_size(int count)
index 0b6a459..49382a2 100644 (file)
@@ -49,10 +49,6 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
 
        J_ASSERT(ext3_journal_current_handle() == 0);
 
-       smp_mb();               /* prepare for lockless i_state read */
-       if (!(inode->i_state & I_DIRTY))
-               goto out;
-
        /*
         * data=writeback:
         *  The caller's filemap_fdatawrite()/wait will sync the data.
index 9c71433..2aabe9f 100644 (file)
 #define EXT3_XATTR_INDEX_SECURITY              6
 
 struct ext3_xattr_header {
-       __u32   h_magic;        /* magic number for identification */
-       __u32   h_refcount;     /* reference count */
-       __u32   h_blocks;       /* number of disk blocks used */
-       __u32   h_hash;         /* hash value of all attributes */
+       __le32  h_magic;        /* magic number for identification */
+       __le32  h_refcount;     /* reference count */
+       __le32  h_blocks;       /* number of disk blocks used */
+       __le32  h_hash;         /* hash value of all attributes */
        __u32   h_reserved[4];  /* zero right now */
 };
 
 struct ext3_xattr_entry {
        __u8    e_name_len;     /* length of name */
        __u8    e_name_index;   /* attribute name index */
-       __u16   e_value_offs;   /* offset in disk block of value */
-       __u32   e_value_block;  /* disk block attribute is stored on (n/i) */
-       __u32   e_value_size;   /* size of attribute value */
-       __u32   e_hash;         /* hash value of name and value */
+       __le16  e_value_offs;   /* offset in disk block of value */
+       __le32  e_value_block;  /* disk block attribute is stored on (n/i) */
+       __le32  e_value_size;   /* size of attribute value */
+       __le32  e_hash;         /* hash value of name and value */
        char    e_name[0];      /* attribute name */
 };
 
index eec0990..ad8ff5f 100644 (file)
@@ -45,13 +45,13 @@ int __fat_access(struct super_block *sb, int nr, int new_value)
        }
        if (sbi->fat_bits == 32) {
                p_first = p_last = NULL; /* GCC needs that stuff */
-               next = CF_LE_L(((__u32 *) bh->b_data)[(first &
+               next = CF_LE_L(((__le32 *) bh->b_data)[(first &
                    (sb->s_blocksize - 1)) >> 2]);
                /* Fscking Microsoft marketing department. Their "32" is 28. */
                next &= 0x0fffffff;
        } else if (sbi->fat_bits == 16) {
                p_first = p_last = NULL; /* GCC needs that stuff */
-               next = CF_LE_W(((__u16 *) bh->b_data)[(first &
+               next = CF_LE_W(((__le16 *) bh->b_data)[(first &
                    (sb->s_blocksize - 1)) >> 1]);
        } else {
                p_first = &((__u8 *)bh->b_data)[first & (sb->s_blocksize - 1)];
@@ -63,10 +63,10 @@ int __fat_access(struct super_block *sb, int nr, int new_value)
        }
        if (new_value != -1) {
                if (sbi->fat_bits == 32) {
-                       ((__u32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]
+                       ((__le32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]
                                = CT_LE_L(new_value);
                } else if (sbi->fat_bits == 16) {
-                       ((__u16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]
+                       ((__le16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]
                                = CT_LE_W(new_value);
                } else {
                        if (nr & 1) {
@@ -146,7 +146,8 @@ void fat_cache_init(struct super_block *sb)
        sbi->cache = sbi->cache_array;
 }
 
-void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu)
+static void
+fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
        struct fat_cache *walk;
index 27ee2ec..993d50c 100644 (file)
@@ -93,14 +93,6 @@ static void dump_de(struct msdos_dir_entry *de)
 }
 #endif
 
-static inline unsigned char
-fat_tolower(struct nls_table *t, unsigned char c)
-{
-       unsigned char nc = t->charset2lower[c];
-
-       return nc ? nc : c;
-}
-
 static inline int
 fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
 {
@@ -140,17 +132,6 @@ fat_short2lower_uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *un
        return charlen;
 }
 
-static int
-fat_strnicmp(struct nls_table *t, const unsigned char *s1,
-                                       const unsigned char *s2, int len)
-{
-       while(len--)
-               if (fat_tolower(t, *s1++) != fat_tolower(t, *s2++))
-                       return 1;
-
-       return 0;
-}
-
 static inline int
 fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size,
                  wchar_t *uni_buf, unsigned short opt, int lower)
@@ -311,7 +292,7 @@ parse_long:
                        :uni16_to_x8(bufname, bufuname, uni_xlate, nls_io);
                if (xlate_len == name_len)
                        if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
-                           (anycase && !fat_strnicmp(nls_io, name, bufname,
+                           (anycase && !nls_strnicmp(nls_io, name, bufname,
                                                                xlate_len)))
                                goto Found;
 
@@ -322,7 +303,7 @@ parse_long:
                        if (xlate_len != name_len)
                                continue;
                        if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
-                           (anycase && !fat_strnicmp(nls_io, name, bufname,
+                           (anycase && !nls_strnicmp(nls_io, name, bufname,
                                                                xlate_len)))
                                goto Found;
                }
@@ -733,7 +714,7 @@ int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat)
 {
        struct buffer_head *bh;
        struct msdos_dir_entry *de;
-       __u16 date, time;
+       __le16 date, time;
 
        bh = fat_extend_dir(dir);
        if (IS_ERR(bh))
@@ -745,12 +726,12 @@ int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat)
        memcpy(de[0].name,MSDOS_DOT,MSDOS_NAME);
        memcpy(de[1].name,MSDOS_DOTDOT,MSDOS_NAME);
        de[0].attr = de[1].attr = ATTR_DIR;
-       de[0].time = de[1].time = CT_LE_W(time);
-       de[0].date = de[1].date = CT_LE_W(date);
+       de[0].time = de[1].time = time;
+       de[0].date = de[1].date = date;
        if (is_vfat) {  /* extra timestamps */
-               de[0].ctime = de[1].ctime = CT_LE_W(time);
+               de[0].ctime = de[1].ctime = time;
                de[0].adate = de[0].cdate =
-                       de[1].adate = de[1].cdate = CT_LE_W(date);
+                       de[1].adate = de[1].cdate = date;
        }
        de[0].start = CT_LE_W(MSDOS_I(dir)->i_logstart);
        de[0].starthi = CT_LE_W(MSDOS_I(dir)->i_logstart>>16);
index 413a414..85a85ec 100644 (file)
@@ -73,9 +73,9 @@ void fat_clusters_flush(struct super_block *sb)
                       sbi->fsinfo_sector);
        } else {
                if (sbi->free_clusters != -1)
-                       fsinfo->free_clusters = CF_LE_L(sbi->free_clusters);
+                       fsinfo->free_clusters = cpu_to_le32(sbi->free_clusters);
                if (sbi->prev_free != -1)
-                       fsinfo->next_cluster = CF_LE_L(sbi->prev_free);
+                       fsinfo->next_cluster = cpu_to_le32(sbi->prev_free);
                mark_buffer_dirty(bh);
        }
        brelse(bh);
@@ -243,8 +243,7 @@ int date_dos2unix(unsigned short time,unsigned short date)
 
 /* Convert linear UNIX date to a MS-DOS time/date pair. */
 
-void fat_date_unix2dos(int unix_date,unsigned short *time,
-    unsigned short *date)
+void fat_date_unix2dos(int unix_date,__le16 *time, __le16 *date)
 {
        int day,year,nl_day,month;
 
@@ -254,8 +253,8 @@ void fat_date_unix2dos(int unix_date,unsigned short *time,
        if (unix_date < 315532800)
                unix_date = 315532800;
 
-       *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
-           (((unix_date/3600) % 24) << 11);
+       *time = cpu_to_le16((unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
+           (((unix_date/3600) % 24) << 11));
        day = unix_date/86400-3652;
        year = day/365;
        if ((year+3)/4+365*year > day) year--;
@@ -269,7 +268,7 @@ void fat_date_unix2dos(int unix_date,unsigned short *time,
                for (month = 0; month < 12; month++)
                        if (day_n[month] > nl_day) break;
        }
-       *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
+       *date = cpu_to_le16(nl_day-day_n[month-1]+1+(month << 5)+(year << 9));
 }
 
 
index 0e4cc9f..d8be917 100644 (file)
@@ -59,7 +59,7 @@ extern void                   vxfs_put_fake_inode(struct inode *);
 extern struct vxfs_inode_info *        vxfs_blkiget(struct super_block *, u_long, ino_t);
 extern struct vxfs_inode_info *        vxfs_stiget(struct super_block *, ino_t);
 extern void                    vxfs_read_inode(struct inode *);
-extern void                    vxfs_put_inode(struct inode *);
+extern void                    vxfs_clear_inode(struct inode *);
 
 /* vxfs_lookup.c */
 extern struct inode_operations vxfs_dir_inode_ops;
index f4b891e..9672d2f 100644 (file)
@@ -337,16 +337,15 @@ vxfs_read_inode(struct inode *ip)
 }
 
 /**
- * vxfs_put_inode - remove inode from main memory
+ * vxfs_clear_inode - remove inode from main memory
  * @ip:                inode to discard.
  *
  * Description:
- *  vxfs_put_inode() is called on each iput.  If we are the last
- *  link in memory, free the fspriv inode area.
+ *  vxfs_clear_inode() is called on the final iput and frees the private
+ *  inode area.
  */
 void
-vxfs_put_inode(struct inode *ip)
+vxfs_clear_inode(struct inode *ip)
 {
-       if (atomic_read(&ip->i_count) == 1)
-               kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
+       kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
 }
index 8fcec56..0ae2c7b 100644 (file)
@@ -60,7 +60,7 @@ static int            vxfs_remount(struct super_block *, int *, char *);
 
 static struct super_operations vxfs_super_ops = {
        .read_inode =           vxfs_read_inode,
-       .put_inode =            vxfs_put_inode,
+       .clear_inode =          vxfs_clear_inode,
        .put_super =            vxfs_put_super,
        .statfs =               vxfs_statfs,
        .remount_fs =           vxfs_remount,
index af78ad6..89450ae 100644 (file)
@@ -85,7 +85,8 @@ int hfs_brec_find(struct hfs_find_data *fd)
 {
        struct hfs_btree *tree;
        struct hfs_bnode *bnode;
-       u32 data, nidx, parent;
+       u32 nidx, parent;
+       __be32 data;
        int height, res;
 
        tree = fd->tree;
index 117fe1e..24e7579 100644 (file)
  *  Accesses memory in 32-bit aligned chunks of 32-bits and thus
  *  may read beyond the 'size'th bit.
  */
-static u32 hfs_find_set_zero_bits(u32 *bitmap, u32 size, u32 offset, u32 *max)
+static u32 hfs_find_set_zero_bits(__be32 *bitmap, u32 size, u32 offset, u32 *max)
 {
-       u32 *curr, *end;
-       u32 val, mask, start, len;
+       __be32 *curr, *end;
+       u32 mask, start, len, n;
+       __be32 val;
        int i;
 
        len = *max;
@@ -42,11 +43,11 @@ static u32 hfs_find_set_zero_bits(u32 *bitmap, u32 size, u32 offset, u32 *max)
        /* scan the first partial u32 for zero bits */
        val = *curr;
        if (~val) {
-               val = be32_to_cpu(val);
+               n = be32_to_cpu(val);
                i = offset % 32;
                mask = (1U << 31) >> i;
                for (; i < 32; mask >>= 1, i++) {
-                       if (!(val & mask))
+                       if (!(n & mask))
                                goto found;
                }
        }
@@ -55,10 +56,10 @@ static u32 hfs_find_set_zero_bits(u32 *bitmap, u32 size, u32 offset, u32 *max)
        while (++curr < end) {
                val = *curr;
                if (~val) {
-                       val = be32_to_cpu(val);
+                       n = be32_to_cpu(val);
                        mask = 1 << 31;
                        for (i = 0; i < 32; mask >>= 1, i++) {
-                               if (!(val & mask))
+                               if (!(n & mask))
                                        goto found;
                        }
                }
@@ -72,38 +73,38 @@ found:
        /* do any partial u32 at the start */
        len = min(size - start, len);
        while (1) {
-               val |= mask;
+               n |= mask;
                if (++i >= 32)
                        break;
                mask >>= 1;
-               if (!--len || val & mask)
+               if (!--len || n & mask)
                        goto done;
        }
        if (!--len)
                goto done;
-       *curr++ = cpu_to_be32(val);
+       *curr++ = cpu_to_be32(n);
        /* do full u32s */
        while (1) {
-               val = be32_to_cpu(*curr);
+               n = be32_to_cpu(*curr);
                if (len < 32)
                        break;
-               if (val) {
+               if (n) {
                        len = 32;
                        break;
                }
-               *curr++ = 0xffffffffU;
+               *curr++ = cpu_to_be32(0xffffffff);
                len -= 32;
        }
        /* do any partial u32 at end */
        mask = 1U << 31;
        for (i = 0; i < len; i++) {
-               if (val & mask)
+               if (n & mask)
                        break;
-               val |= mask;
+               n |= mask;
                mask >>= 1;
        }
 done:
-       *curr = cpu_to_be32(val);
+       *curr = cpu_to_be32(n);
        *max = (curr - bitmap) * 32 + i - start;
        return start;
 }
@@ -191,7 +192,7 @@ out:
  */
 int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count)
 {
-       u32 *curr;
+       __be32 *curr;
        u32 mask;
        int i, len;
 
index d0cf0a6..b47ab42 100644 (file)
@@ -29,7 +29,7 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf,
 
 u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off)
 {
-       u16 data;
+       __be16 data;
        // optimize later...
        hfs_bnode_read(node, &data, off, 2);
        return be16_to_cpu(data);
@@ -72,9 +72,9 @@ void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
 
 void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data)
 {
-       data = cpu_to_be16(data);
+       __be16 v = cpu_to_be16(data);
        // optimize later...
-       hfs_bnode_write(node, &data, off, 2);
+       hfs_bnode_write(node, &v, off, 2);
 }
 
 void hfs_bnode_write_u8(struct hfs_bnode *node, int off, u8 data)
@@ -136,7 +136,7 @@ void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
 void hfs_bnode_dump(struct hfs_bnode *node)
 {
        struct hfs_bnode_desc desc;
-       u32 cnid;
+       __be32 cnid;
        int i, off, key_off;
 
        dprint(DBG_BNODE_MOD, "bnode: %d\n", node->this);
@@ -173,7 +173,7 @@ void hfs_bnode_unlink(struct hfs_bnode *node)
 {
        struct hfs_btree *tree;
        struct hfs_bnode *tmp;
-       u32 cnid;
+       __be32 cnid;
 
        tree = node->tree;
        if (node->prev) {
index 5e54671..10e986c 100644 (file)
@@ -13,7 +13,7 @@
 /* Get the length and offset of the given record in the given node */
 u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off)
 {
-       u16 retval[2];
+       __be16 retval[2];
        u16 dataoff;
 
        dataoff = node->tree->node_size - (rec + 2) * 2;
@@ -55,7 +55,7 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
        int size, key_len, rec;
        int data_off, end_off;
        int idx_rec_off, data_rec_off, end_rec_off;
-       u32 cnid;
+       __be32 cnid;
 
        tree = fd->tree;
        if (!fd->bnode) {
@@ -391,7 +391,7 @@ skip:
        node = parent;
 
        if (new_node) {
-               u32 cnid;
+               __be32 cnid;
 
                fd->bnode = hfs_bnode_find(tree, new_node->parent);
                /* create index key and entry */
@@ -423,7 +423,7 @@ int hfs_btree_inc_height(struct hfs_btree *tree)
        struct hfs_bnode *node, *new_node;
        struct hfs_bnode_desc node_desc;
        int key_size, rec;
-       u32 cnid;
+       __be32 cnid;
 
        node = NULL;
        if (tree->root) {
index 19f10cf..64354de 100644 (file)
@@ -154,7 +154,7 @@ static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx)
        struct hfs_btree *tree = prev->tree;
        struct hfs_bnode *node;
        struct hfs_bnode_desc desc;
-       u32 cnid;
+       __be32 cnid;
 
        node = hfs_bnode_create(tree, idx);
        if (IS_ERR(node))
index 266af5e..87eaa9f 100644 (file)
@@ -125,11 +125,11 @@ extern int hfs_brec_goto(struct hfs_find_data *, int);
 
 
 struct hfs_bnode_desc {
-       u32 next;               /* (V) Number of the next node at this level */
-       u32 prev;               /* (V) Number of the prev node at this level */
+       __be32 next;            /* (V) Number of the next node at this level */
+       __be32 prev;            /* (V) Number of the prev node at this level */
        u8 type;                /* (F) The type of node */
        u8 height;              /* (F) The level of this node (leaves=1) */
-       u16 num_recs;           /* (V) The number of records in this node */
+       __be16 num_recs;        /* (V) The number of records in this node */
        u16 reserved;
 } __packed;
 
@@ -139,20 +139,20 @@ struct hfs_bnode_desc {
 #define HFS_NODE_LEAF  0xFF    /* A leaf (ndNHeight==1) node */
 
 struct hfs_btree_header_rec {
-       u16 depth;              /* (V) The number of levels in this B-tree */
-       u32 root;               /* (V) The node number of the root node */
-       u32 leaf_count;         /* (V) The number of leaf records */
-       u32 leaf_head;          /* (V) The number of the first leaf node */
-       u32 leaf_tail;          /* (V) The number of the last leaf node */
-       u16 node_size;          /* (F) The number of bytes in a node (=512) */
-       u16 max_key_len;        /* (F) The length of a key in an index node */
-       u32 node_count;         /* (V) The total number of nodes */
-       u32 free_nodes;         /* (V) The number of unused nodes */
+       __be16 depth;           /* (V) The number of levels in this B-tree */
+       __be32 root;            /* (V) The node number of the root node */
+       __be32 leaf_count;      /* (V) The number of leaf records */
+       __be32 leaf_head;       /* (V) The number of the first leaf node */
+       __be32 leaf_tail;       /* (V) The number of the last leaf node */
+       __be16 node_size;       /* (F) The number of bytes in a node (=512) */
+       __be16 max_key_len;     /* (F) The length of a key in an index node */
+       __be32 node_count;      /* (V) The total number of nodes */
+       __be32 free_nodes;      /* (V) The number of unused nodes */
        u16 reserved1;
-       u32 clump_size;         /* (F) clump size. not usually used. */
+       __be32 clump_size;      /* (F) clump size. not usually used. */
        u8 btree_type;          /* (F) BTree type */
        u8 reserved2;
-       u32 attributes;         /* (F) attributes */
+       __be32 attributes;      /* (F) attributes */
        u32 reserved3[16];
 } __packed;
 
index a9f4e23..b7ce3f0 100644 (file)
@@ -279,13 +279,13 @@ int hfs_free_fork(struct super_block *sb, struct hfs_cat_file *file, int type)
        int res, i;
 
        if (type == HFS_FK_DATA) {
-               total_blocks = file->PyLen;
+               total_blocks = be32_to_cpu(file->PyLen);
                extent = file->ExtRec;
        } else {
-               total_blocks = file->RPyLen;
+               total_blocks = be32_to_cpu(file->RPyLen);
                extent = file->RExtRec;
        }
-       total_blocks = be32_to_cpu(total_blocks) / HFS_SB(sb)->alloc_blksz;
+       total_blocks /= HFS_SB(sb)->alloc_blksz;
        if (!total_blocks)
                return 0;
 
index 73ac408..df6b33a 100644 (file)
@@ -91,45 +91,45 @@ struct hfs_name {
 } __packed;
 
 struct hfs_point {
-       u16 v;
-       u16 h;
+       __be16 v;
+       __be16 h;
 } __packed;
 
 struct hfs_rect {
-       u16 top;
-       u16 left;
-       u16 bottom;
-       u16 right;
+       __be16 top;
+       __be16 left;
+       __be16 bottom;
+       __be16 right;
 } __packed;
 
 struct hfs_finfo {
-       u32 fdType;
-       u32 fdCreator;
-       u16 fdFlags;
+       __be32 fdType;
+       __be32 fdCreator;
+       __be16 fdFlags;
        struct hfs_point fdLocation;
-       u16 fdFldr;
+       __be16 fdFldr;
 } __packed;
 
 struct hfs_fxinfo {
-       u16 fdIconID;
+       __be16 fdIconID;
        u8 fdUnused[8];
-       u16 fdComment;
-       u32 fdPutAway;
+       __be16 fdComment;
+       __be32 fdPutAway;
 } __packed;
 
 struct hfs_dinfo {
        struct hfs_rect frRect;
-       u16 frFlags;
+       __be16 frFlags;
        struct hfs_point frLocation;
-       u16 frView;
+       __be16 frView;
 } __packed;
 
 struct hfs_dxinfo {
        struct hfs_point frScroll;
-       u32 frOpenChain;
-       u16 frUnused;
-       u16 frComment;
-       u32 frPutAway;
+       __be32 frOpenChain;
+       __be16 frUnused;
+       __be16 frComment;
+       __be32 frPutAway;
 } __packed;
 
 union hfs_finder_info {
@@ -150,7 +150,7 @@ union hfs_finder_info {
 struct hfs_cat_key {
        u8 key_len;             /* number of bytes in the key */
        u8 reserved;            /* padding */
-       u32 ParID;              /* CNID of the parent dir */
+       __be32 ParID;           /* CNID of the parent dir */
        struct hfs_name CName;  /* The filename of the entry */
 } __packed;
 
@@ -158,8 +158,8 @@ struct hfs_cat_key {
 struct hfs_ext_key {
        u8 key_len;             /* number of bytes in the key */
        u8 FkType;              /* HFS_FK_{DATA,RSRC} */
-       u32 FNum;               /* The File ID of the file */
-       u16 FABN;               /* allocation blocks number*/
+       __be32 FNum;            /* The File ID of the file */
+       __be16 FABN;            /* allocation blocks number*/
 } __packed;
 
 typedef union hfs_btree_key {
@@ -171,8 +171,8 @@ typedef union hfs_btree_key {
 typedef union hfs_btree_key btree_key;
 
 struct hfs_extent {
-       u16 block;
-       u16 count;
+       __be16 block;
+       __be16 count;
 };
 typedef struct hfs_extent hfs_extent_rec[3];
 
@@ -183,18 +183,18 @@ struct hfs_cat_file {
        u8 Flags;                       /* Flags such as read-only */
        s8 Typ;                         /* file version number = 0 */
        struct hfs_finfo UsrWds;        /* data used by the Finder */
-       u32 FlNum;                      /* The CNID */
-       u16 StBlk;                      /* obsolete */
-       u32 LgLen;                      /* The logical EOF of the data fork*/
-       u32 PyLen;                      /* The physical EOF of the data fork */
-       u16 RStBlk;                     /* obsolete */
-       u32 RLgLen;                     /* The logical EOF of the rsrc fork */
-       u32 RPyLen;                     /* The physical EOF of the rsrc fork */
-       u32 CrDat;                      /* The creation date */
-       u32 MdDat;                      /* The modified date */
-       u32 BkDat;                      /* The last backup date */
+       __be32 FlNum;                   /* The CNID */
+       __be16 StBlk;                   /* obsolete */
+       __be32 LgLen;                   /* The logical EOF of the data fork*/
+       __be32 PyLen;                   /* The physical EOF of the data fork */
+       __be16 RStBlk;                  /* obsolete */
+       __be32 RLgLen;                  /* The logical EOF of the rsrc fork */
+       __be32 RPyLen;                  /* The physical EOF of the rsrc fork */
+       __be32 CrDat;                   /* The creation date */
+       __be32 MdDat;                   /* The modified date */
+       __be32 BkDat;                   /* The last backup date */
        struct hfs_fxinfo FndrInfo;     /* more data for the Finder */
-       u16 ClpSize;                    /* number of bytes to allocate
+       __be16 ClpSize;                 /* number of bytes to allocate
                                           when extending files */
        hfs_extent_rec ExtRec;          /* first extent record
                                           for the data fork */
@@ -207,13 +207,13 @@ struct hfs_cat_file {
 struct hfs_cat_dir {
        s8 type;                        /* The type of entry */
        u8 reserved;
-       u16 Flags;                      /* flags */
-       u16 Val;                        /* Valence: number of files and
+       __be16 Flags;                   /* flags */
+       __be16 Val;                     /* Valence: number of files and
                                           dirs in the directory */
-       u32 DirID;                      /* The CNID */
-       u32 CrDat;                      /* The creation date */
-       u32 MdDat;                      /* The modification date */
-       u32 BkDat;                      /* The last backup date */
+       __be32 DirID;                   /* The CNID */
+       __be32 CrDat;                   /* The creation date */
+       __be32 MdDat;                   /* The modification date */
+       __be32 BkDat;                   /* The last backup date */
        struct hfs_dinfo UsrInfo;       /* data used by the Finder */
        struct hfs_dxinfo FndrInfo;     /* more data used by Finder */
        u8 Resrv[16];                   /* reserved by Apple */
@@ -223,7 +223,7 @@ struct hfs_cat_dir {
 struct hfs_cat_thread {
        s8 type;                        /* The type of entry */
        u8 reserved[9];                 /* reserved by Apple */
-       u32 ParID;                      /* CNID of parent directory */
+       __be32 ParID;                   /* CNID of parent directory */
        struct hfs_name CName;          /* The name of this entry */
 }  __packed;
 
@@ -236,43 +236,43 @@ typedef union hfs_cat_rec {
 } hfs_cat_rec;
 
 struct hfs_mdb {
-       u16 drSigWord;                  /* Signature word indicating fs type */
-       u32 drCrDate;                   /* fs creation date/time */
-       u32 drLsMod;                    /* fs modification date/time */
-       u16 drAtrb;                     /* fs attributes */
-       u16 drNmFls;                    /* number of files in root directory */
-       u16 drVBMSt;                    /* location (in 512-byte blocks)
+       __be16 drSigWord;               /* Signature word indicating fs type */
+       __be32 drCrDate;                /* fs creation date/time */
+       __be32 drLsMod;                 /* fs modification date/time */
+       __be16 drAtrb;                  /* fs attributes */
+       __be16 drNmFls;                 /* number of files in root directory */
+       __be16 drVBMSt;                 /* location (in 512-byte blocks)
                                           of the volume bitmap */
-       u16 drAllocPtr;                 /* location (in allocation blocks)
+       __be16 drAllocPtr;              /* location (in allocation blocks)
                                           to begin next allocation search */
-       u16 drNmAlBlks;                 /* number of allocation blocks */
-       u32 drAlBlkSiz;                 /* bytes in an allocation block */
-       u32 drClpSiz;                   /* clumpsize, the number of bytes to
+       __be16 drNmAlBlks;              /* number of allocation blocks */
+       __be32 drAlBlkSiz;              /* bytes in an allocation block */
+       __be32 drClpSiz;                /* clumpsize, the number of bytes to
                                           allocate when extending a file */
-       u16 drAlBlSt;                   /* location (in 512-byte blocks)
+       __be16 drAlBlSt;                /* location (in 512-byte blocks)
                                           of the first allocation block */
-       u32 drNxtCNID;                  /* CNID to assign to the next
+       __be32 drNxtCNID;               /* CNID to assign to the next
                                           file or directory created */
-       u16 drFreeBks;                  /* number of free allocation blocks */
+       __be16 drFreeBks;               /* number of free allocation blocks */
        u8 drVN[28];                    /* the volume label */
-       u32 drVolBkUp;                  /* fs backup date/time */
-       u16 drVSeqNum;                  /* backup sequence number */
-       u32 drWrCnt;                    /* fs write count */
-       u32 drXTClpSiz;                 /* clumpsize for the extents B-tree */
-       u32 drCTClpSiz;                 /* clumpsize for the catalog B-tree */
-       u16 drNmRtDirs;                 /* number of directories in
+       __be32 drVolBkUp;               /* fs backup date/time */
+       __be16 drVSeqNum;               /* backup sequence number */
+       __be32 drWrCnt;                 /* fs write count */
+       __be32 drXTClpSiz;              /* clumpsize for the extents B-tree */
+       __be32 drCTClpSiz;              /* clumpsize for the catalog B-tree */
+       __be16 drNmRtDirs;              /* number of directories in
                                           the root directory */
-       u32 drFilCnt;                   /* number of files in the fs */
-       u32 drDirCnt;                   /* number of directories in the fs */
+       __be32 drFilCnt;                /* number of files in the fs */
+       __be32 drDirCnt;                /* number of directories in the fs */
        u8 drFndrInfo[32];              /* data used by the Finder */
-       u16 drEmbedSigWord;             /* embedded volume signature */
-       u32 drEmbedExtent;              /* starting block number (xdrStABN)
+       __be16 drEmbedSigWord;          /* embedded volume signature */
+       __be32 drEmbedExtent;           /* starting block number (xdrStABN)
                                           and number of allocation blocks
                                           (xdrNumABlks) occupied by embedded
                                           volume */
-       u32 drXTFlSize;                 /* bytes in the extents B-tree */
+       __be32 drXTFlSize;              /* bytes in the extents B-tree */
        hfs_extent_rec drXTExtRec;      /* extents B-tree's first 3 extents */
-       u32 drCTFlSize;                 /* bytes in the catalog B-tree */
+       __be32 drCTFlSize;              /* bytes in the catalog B-tree */
        hfs_extent_rec drCTExtRec;      /* catalog B-tree's first 3 extents */
 } __packed;
 
index 33876db..ecf33d8 100644 (file)
@@ -90,7 +90,7 @@ struct hfs_sb_info {
        struct buffer_head *alt_mdb_bh;         /* The hfs_buffer holding
                                                   the alternate superblock */
        struct hfs_mdb *alt_mdb;
-       u32 *bitmap;                            /* The page holding the
+       __be32 *bitmap;                         /* The page holding the
                                                   allocation bitmap */
        struct hfs_btree *ext_tree;                     /* Information about
                                                   the extents b-tree */
@@ -129,8 +129,8 @@ struct hfs_sb_info {
                                                   "allocation block" */
        int s_quiet;                            /* Silent failure when
                                                   changing owner or mode? */
-       u32 s_type;                             /* Type for new files */
-       u32 s_creator;                          /* Creator for new files */
+       __be32 s_type;                          /* Type for new files */
+       __be32 s_creator;                       /* Creator for new files */
        umode_t s_file_umask;                   /* The umask applied to the
                                                   permissions on all files */
        umode_t s_dir_umask;                    /* The umask applied to the
@@ -197,11 +197,11 @@ extern struct address_space_operations hfs_aops;
 extern struct address_space_operations hfs_btree_aops;
 
 extern struct inode *hfs_new_inode(struct inode *, struct qstr *, int);
-extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, u32 *, u32 *);
-extern void hfs_write_inode(struct inode *, int);
+extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *);
+extern int hfs_write_inode(struct inode *, int);
 extern int hfs_inode_setattr(struct dentry *, struct iattr *);
 extern void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
-                               u32 log_size, u32 phys_size, u32 clump_size);
+                       __be32 log_size, __be32 phys_size, u32 clump_size);
 extern struct inode *hfs_iget(struct super_block *, struct hfs_cat_key *, hfs_cat_rec *);
 extern void hfs_clear_inode(struct inode *);
 extern void hfs_delete_inode(struct inode *);
@@ -223,9 +223,6 @@ extern int hfs_strcmp(const unsigned char *, unsigned int,
                      const unsigned char *, unsigned int);
 extern int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
 
-/* super.c */
-extern struct super_block *hfs_read_super(struct super_block *,void *,int);
-
 /* trans.c */
 extern void hfs_triv2mac(struct hfs_name *, struct qstr *);
 extern int hfs_mac2triv(char *, const struct hfs_name *);
index cedb9ab..f90764f 100644 (file)
@@ -71,7 +71,7 @@ int hfs_mdb_get(struct super_block *sb)
        int off2, len, size, sect;
        sector_t part_start, part_size;
        loff_t off;
-       u16 attrib;
+       __be16 attrib;
 
        /* set the device driver to 512-byte blocks */
        size = sb_min_blocksize(sb, HFS_SECTOR_SIZE);
@@ -164,7 +164,7 @@ int hfs_mdb_get(struct super_block *sb)
                hfs_warn("hfs_fs: continuing without an alternate MDB\n");
        }
 
-       HFS_SB(sb)->bitmap = (u32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0);
+       HFS_SB(sb)->bitmap = (__be32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0);
        if (!HFS_SB(sb)->bitmap)
                goto out;
 
index 19c189d..36add53 100644 (file)
  * contiguous starting at block 1.
  */
 struct new_pmap {
-       u16     pmSig;          /* signature */
-       u16     reSigPad;       /* padding */
-       u32     pmMapBlkCnt;    /* partition blocks count */
-       u32     pmPyPartStart;  /* physical block start of partition */
-       u32     pmPartBlkCnt;   /* physical block count of partition */
+       __be16  pmSig;          /* signature */
+       __be16  reSigPad;       /* padding */
+       __be32  pmMapBlkCnt;    /* partition blocks count */
+       __be32  pmPyPartStart;  /* physical block start of partition */
+       __be32  pmPartBlkCnt;   /* physical block count of partition */
        u8      pmPartName[32]; /* (null terminated?) string
                                   giving the name of this
                                   partition */
@@ -41,11 +41,11 @@ struct new_pmap {
  * one of these.
  */
 struct old_pmap {
-       u16             pdSig;  /* Signature bytes */
+       __be16          pdSig;  /* Signature bytes */
        struct  old_pmap_entry {
-               u32     pdStart;
-               u32     pdSize;
-               u32     pdFSID;
+               __be32  pdStart;
+               __be32  pdSize;
+               __be32  pdFSID;
        }       pdEntry[42];
 } __packed;
 
@@ -59,7 +59,7 @@ int hfs_part_find(struct super_block *sb,
                  sector_t *part_start, sector_t *part_size)
 {
        struct buffer_head *bh;
-       u16 *data;
+       __be16 *data;
        int i, size, res;
 
        res = -ENOENT;
index d8305b7..257cdde 100644 (file)
@@ -85,7 +85,8 @@ int hfs_brec_find(struct hfs_find_data *fd)
 {
        struct hfs_btree *tree;
        struct hfs_bnode *bnode;
-       u32 data, nidx, parent;
+       u32 nidx, parent;
+       __be32 data;
        int height, res;
 
        tree = fd->tree;
index 644dcb5..c7d3164 100644 (file)
@@ -19,8 +19,9 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
 {
        struct page *page;
        struct address_space *mapping;
-       u32 *pptr, *curr, *end;
-       u32 val, mask, start, len;
+       __be32 *pptr, *curr, *end;
+       u32 mask, start, len, n;
+       __be32 val;
        int i;
 
        len = *max;
@@ -44,10 +45,10 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
        /* scan the first partial u32 for zero bits */
        val = *curr;
        if (~val) {
-               val = be32_to_cpu(val);
+               n = be32_to_cpu(val);
                mask = (1U << 31) >> i;
                for (; i < 32; mask >>= 1, i++) {
-                       if (!(val & mask))
+                       if (!(n & mask))
                                goto found;
                }
        }
@@ -58,10 +59,10 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
                while (curr < end) {
                        val = *curr;
                        if (~val) {
-                               val = be32_to_cpu(val);
+                               n = be32_to_cpu(val);
                                mask = 1 << 31;
                                for (i = 0; i < 32; mask >>= 1, i++) {
-                                       if (!(val & mask))
+                                       if (!(n & mask))
                                                goto found;
                                }
                        }
@@ -92,27 +93,27 @@ found:
        /* do any partial u32 at the start */
        len = min(size - start, len);
        while (1) {
-               val |= mask;
+               n |= mask;
                if (++i >= 32)
                        break;
                mask >>= 1;
-               if (!--len || val & mask)
+               if (!--len || n & mask)
                        goto done;
        }
        if (!--len)
                goto done;
-       *curr++ = cpu_to_be32(val);
+       *curr++ = cpu_to_be32(n);
        /* do full u32s */
        while (1) {
                while (curr < end) {
-                       val = be32_to_cpu(*curr);
+                       n = be32_to_cpu(*curr);
                        if (len < 32)
                                goto last;
-                       if (val) {
+                       if (n) {
                                len = 32;
                                goto last;
                        }
-                       *curr++ = 0xffffffffU;
+                       *curr++ = cpu_to_be32(0xffffffff);
                        len -= 32;
                }
                set_page_dirty(page);
@@ -128,13 +129,13 @@ last:
        /* do any partial u32 at end */
        mask = 1U << 31;
        for (i = 0; i < len; i++) {
-               if (val & mask)
+               if (n & mask)
                        break;
-               val |= mask;
+               n |= mask;
                mask >>= 1;
        }
 done:
-       *curr = cpu_to_be32(val);
+       *curr = cpu_to_be32(n);
        set_page_dirty(page);
        kunmap(page);
        *max = offset + (curr - pptr) * 32 + i - start;
@@ -150,7 +151,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
 {
        struct page *page;
        struct address_space *mapping;
-       u32 *pptr, *curr, *end;
+       __be32 *pptr, *curr, *end;
        u32 mask, len, pnr;
        int i;
 
index b071364..25119fd 100644 (file)
@@ -142,7 +142,7 @@ static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx)
        struct hfs_btree *tree = prev->tree;
        struct hfs_bnode *node;
        struct hfs_bnode_desc desc;
-       u32 cnid;
+       __be32 cnid;
 
        node = hfs_bnode_create(tree, idx);
        if (IS_ERR(node))
index 3cf2721..51d4b12 100644 (file)
@@ -19,8 +19,8 @@
 /* Compare two extents keys, returns 0 on same, pos/neg for difference */
 int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
 {
-       u32 k1id, k2id;
-       u32 k1s, k2s;
+       __be32 k1id, k2id;
+       __be32 k1s, k2s;
 
        k1id = k1->ext.cnid;
        k2id = k2->ext.cnid;
index 2e172a8..57b6ec7 100644 (file)
@@ -333,7 +333,7 @@ extern struct address_space_operations hfsplus_btree_aops;
 void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *);
 void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *);
 int hfsplus_cat_read_inode(struct inode *, struct hfs_find_data *);
-void hfsplus_cat_write_inode(struct inode *);
+int hfsplus_cat_write_inode(struct inode *);
 struct inode *hfsplus_new_inode(struct super_block *, int);
 void hfsplus_delete_inode(struct inode *);
 
@@ -344,7 +344,6 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 /* options.c */
 int parse_options(char *, struct hfsplus_sb_info *);
 void fill_defaults(struct hfsplus_sb_info *);
-void fill_current(struct hfsplus_sb_info *, struct hfsplus_sb_info *);
 
 /* tables.c */
 extern u16 case_fold_table[];
index 696f06f..5bad37c 100644 (file)
 
 /* Structures used on disk */
 
-typedef u32 hfsplus_cnid;
-typedef u16 hfsplus_unichr;
+typedef __be32 hfsplus_cnid;
+typedef __be16 hfsplus_unichr;
 
 /* A "string" as used in filenames, etc. */
 struct hfsplus_unistr {
-       u16 length;
+       __be16 length;
        hfsplus_unichr unicode[255];
 } __packed;
 
@@ -58,12 +58,12 @@ struct hfsplus_unistr {
 
 /* POSIX permissions */
 struct hfsplus_perm {
-       u32 owner;
-       u32 group;
+       __be32 owner;
+       __be32 group;
        u8  rootflags;
        u8  userflags;
-       u16 mode;
-       u32 dev;
+       __be16 mode;
+       __be32 dev;
 } __packed;
 
 #define HFSPLUS_FLG_NODUMP     0x01
@@ -72,46 +72,46 @@ struct hfsplus_perm {
 
 /* A single contiguous area of a file */
 struct hfsplus_extent {
-       u32 start_block;
-       u32 block_count;
+       __be32 start_block;
+       __be32 block_count;
 } __packed;
 typedef struct hfsplus_extent hfsplus_extent_rec[8];
 
 /* Information for a "Fork" in a file */
 struct hfsplus_fork_raw {
-       u64 total_size;
-       u32 clump_size;
-       u32 total_blocks;
+       __be64 total_size;
+       __be32 clump_size;
+       __be32 total_blocks;
        hfsplus_extent_rec extents;
 } __packed;
 
 /* HFS+ Volume Header */
 struct hfsplus_vh {
-       u16 signature;
-       u16 version;
-       u32 attributes;
-       u32 last_mount_vers;
+       __be16 signature;
+       __be16 version;
+       __be32 attributes;
+       __be32 last_mount_vers;
        u32 reserved;
 
-       u32 create_date;
-       u32 modify_date;
-       u32 backup_date;
-       u32 checked_date;
+       __be32 create_date;
+       __be32 modify_date;
+       __be32 backup_date;
+       __be32 checked_date;
 
-       u32 file_count;
-       u32 folder_count;
+       __be32 file_count;
+       __be32 folder_count;
 
-       u32 blocksize;
-       u32 total_blocks;
-       u32 free_blocks;
+       __be32 blocksize;
+       __be32 total_blocks;
+       __be32 free_blocks;
 
-       u32 next_alloc;
-       u32 rsrc_clump_sz;
-       u32 data_clump_sz;
+       __be32 next_alloc;
+       __be32 rsrc_clump_sz;
+       __be32 data_clump_sz;
        hfsplus_cnid next_cnid;
 
-       u32 write_count;
-       u64 encodings_bmp;
+       __be32 write_count;
+       __be64 encodings_bmp;
 
        u8 finder_info[32];
 
@@ -131,11 +131,11 @@ struct hfsplus_vh {
 
 /* HFS+ BTree node descriptor */
 struct hfs_bnode_desc {
-       u32 next;
-       u32 prev;
+       __be32 next;
+       __be32 prev;
        s8 type;
        u8 height;
-       u16 num_recs;
+       __be16 num_recs;
        u16 reserved;
 } __packed;
 
@@ -147,20 +147,20 @@ struct hfs_bnode_desc {
 
 /* HFS+ BTree header */
 struct hfs_btree_header_rec {
-       u16 depth;
-       u32 root;
-       u32 leaf_count;
-       u32 leaf_head;
-       u32 leaf_tail;
-       u16 node_size;
-       u16 max_key_len;
-       u32 node_count;
-       u32 free_nodes;
+       __be16 depth;
+       __be32 root;
+       __be32 leaf_count;
+       __be32 leaf_head;
+       __be32 leaf_tail;
+       __be16 node_size;
+       __be16 max_key_len;
+       __be32 node_count;
+       __be32 free_nodes;
        u16 reserved1;
-       u32 clump_size;
+       __be32 clump_size;
        u8 btree_type;
        u8 reserved2;
-       u32 attributes;
+       __be32 attributes;
        u32 reserved3[16];
 } __packed;
 
@@ -186,7 +186,7 @@ struct hfs_btree_header_rec {
 
 /* HFS+ catalog entry key */
 struct hfsplus_cat_key {
-       u16 key_len;
+       __be16 key_len;
        hfsplus_cnid parent;
        struct hfsplus_unistr name;
 } __packed;
@@ -194,83 +194,83 @@ struct hfsplus_cat_key {
 
 /* Structs from hfs.h */
 struct hfsp_point {
-       u16 v;
-       u16 h;
+       __be16 v;
+       __be16 h;
 } __packed;
 
 struct hfsp_rect {
-       u16 top;
-       u16 left;
-       u16 bottom;
-       u16 right;
+       __be16 top;
+       __be16 left;
+       __be16 bottom;
+       __be16 right;
 } __packed;
 
 
 /* HFS directory info (stolen from hfs.h */
 struct DInfo {
        struct hfsp_rect frRect;
-       u16 frFlags;
+       __be16 frFlags;
        struct hfsp_point frLocation;
-       u16 frView;
+       __be16 frView;
 } __packed;
 
 struct DXInfo {
        struct hfsp_point frScroll;
-       u32 frOpenChain;
-       u16 frUnused;
-       u16 frComment;
-       u32 frPutAway;
+       __be32 frOpenChain;
+       __be16 frUnused;
+       __be16 frComment;
+       __be32 frPutAway;
 } __packed;
 
 /* HFS+ folder data (part of an hfsplus_cat_entry) */
 struct hfsplus_cat_folder {
-       s16 type;
-       u16 flags;
-       u32 valence;
+       __be16 type;
+       __be16 flags;
+       __be32 valence;
        hfsplus_cnid id;
-       u32 create_date;
-       u32 content_mod_date;
-       u32 attribute_mod_date;
-       u32 access_date;
-       u32 backup_date;
+       __be32 create_date;
+       __be32 content_mod_date;
+       __be32 attribute_mod_date;
+       __be32 access_date;
+       __be32 backup_date;
        struct hfsplus_perm permissions;
        struct DInfo user_info;
        struct DXInfo finder_info;
-       u32 text_encoding;
+       __be32 text_encoding;
        u32 reserved;
 } __packed;
 
 /* HFS file info (stolen from hfs.h) */
 struct FInfo {
-       u32 fdType;
-       u32 fdCreator;
-       u16 fdFlags;
+       __be32 fdType;
+       __be32 fdCreator;
+       __be16 fdFlags;
        struct hfsp_point fdLocation;
-       u16 fdFldr;
+       __be16 fdFldr;
 } __packed;
 
 struct FXInfo {
-       u16 fdIconID;
+       __be16 fdIconID;
        u8 fdUnused[8];
-       u16 fdComment;
-       u32 fdPutAway;
+       __be16 fdComment;
+       __be32 fdPutAway;
 } __packed;
 
 /* HFS+ file data (part of a cat_entry) */
 struct hfsplus_cat_file {
-       s16 type;
-       u16 flags;
+       __be16 type;
+       __be16 flags;
        u32 reserved1;
        hfsplus_cnid id;
-       u32 create_date;
-       u32 content_mod_date;
-       u32 attribute_mod_date;
-       u32 access_date;
-       u32 backup_date;
+       __be32 create_date;
+       __be32 content_mod_date;
+       __be32 attribute_mod_date;
+       __be32 access_date;
+       __be32 backup_date;
        struct hfsplus_perm permissions;
        struct FInfo user_info;
        struct FXInfo finder_info;
-       u32 text_encoding;
+       __be32 text_encoding;
        u32 reserved2;
 
        struct hfsplus_fork_raw data_fork;
@@ -283,7 +283,7 @@ struct hfsplus_cat_file {
 
 /* HFS+ catalog thread (part of a cat_entry) */
 struct hfsplus_cat_thread {
-       s16 type;
+       __be16 type;
        s16 reserved;
        hfsplus_cnid parentID;
        struct hfsplus_unistr nodeName;
@@ -293,7 +293,7 @@ struct hfsplus_cat_thread {
 
 /* A data record in the catalog tree */
 typedef union {
-       s16 type;
+       __be16 type;
        struct hfsplus_cat_folder folder;
        struct hfsplus_cat_file file;
        struct hfsplus_cat_thread thread;
@@ -307,18 +307,18 @@ typedef union {
 
 /* HFS+ extents tree key */
 struct hfsplus_ext_key {
-       u16 key_len;
+       __be16 key_len;
        u8 fork_type;
        u8 pad;
        hfsplus_cnid cnid;
-       u32 start_block;
+       __be32 start_block;
 } __packed;
 
 #define HFSPLUS_EXT_KEYLEN 12
 
 /* HFS+ generic BTree key */
 typedef union {
-       u16 key_len;
+       __be16 key_len;
        struct hfsplus_cat_key cat;
        struct hfsplus_ext_key ext;
 } __packed hfsplus_btree_key;
index 3bc137f..ae78306 100644 (file)
  * contiguous starting at block 1.
  */
 struct new_pmap {
-       u16     pmSig;          /* signature */
-       u16     reSigPad;       /* padding */
-       u32     pmMapBlkCnt;    /* partition blocks count */
-       u32     pmPyPartStart;  /* physical block start of partition */
-       u32     pmPartBlkCnt;   /* physical block count of partition */
+       __be16  pmSig;          /* signature */
+       __be16  reSigPad;       /* padding */
+       __be32  pmMapBlkCnt;    /* partition blocks count */
+       __be32  pmPyPartStart;  /* physical block start of partition */
+       __be32  pmPartBlkCnt;   /* physical block count of partition */
        u8      pmPartName[32]; /* (null terminated?) string
                                   giving the name of this
                                   partition */
@@ -57,11 +57,11 @@ struct new_pmap {
  * one of these.
  */
 struct old_pmap {
-       u16             pdSig;  /* Signature bytes */
+       __be16          pdSig;  /* Signature bytes */
        struct  old_pmap_entry {
-               u32     pdStart;
-               u32     pdSize;
-               u32     pdFSID;
+               __be32  pdStart;
+               __be32  pdSize;
+               __be32  pdFSID;
        }       pdEntry[42];
 } __packed;
 
@@ -75,7 +75,7 @@ int hfs_part_find(struct super_block *sb,
                  sector_t *part_start, sector_t *part_size)
 {
        struct buffer_head *bh;
-       u16 *data;
+       __be16 *data;
        int i, size, res;
 
        res = -ENOENT;
index 16e6dd8..4ff176a 100644 (file)
@@ -94,20 +94,20 @@ static void hfsplus_read_inode(struct inode *inode)
        make_bad_inode(inode);
 }
 
-void hfsplus_write_inode(struct inode *inode, int unused)
+int hfsplus_write_inode(struct inode *inode, int unused)
 {
        struct hfsplus_vh *vhdr;
+       int ret = 0;
 
        dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino);
        hfsplus_ext_write_extent(inode);
        if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) {
-               hfsplus_cat_write_inode(inode);
-               return;
+               return hfsplus_cat_write_inode(inode);
        }
        vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr;
        switch (inode->i_ino) {
        case HFSPLUS_ROOT_CNID:
-               hfsplus_cat_write_inode(inode);
+               ret = hfsplus_cat_write_inode(inode);
                break;
        case HFSPLUS_EXT_CNID:
                if (vhdr->ext_file.total_size != cpu_to_be64(inode->i_size)) {
@@ -148,6 +148,7 @@ void hfsplus_write_inode(struct inode *inode, int unused)
                hfs_btree_write(HFSPLUS_SB(inode->i_sb).attr_tree);
                break;
        }
+       return ret;
 }
 
 static void hfsplus_clear_inode(struct inode *inode)
index 794292e..0f8e01c 100644 (file)
@@ -1,4 +1,4 @@
-# 
+#
 # Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
 # Licensed under the GPL
 #
@@ -12,7 +12,7 @@ STAT64_INO_FIELD := $(shell grep -q __st_ino /usr/include/bits/stat.h && \
 
 hostfs-objs := hostfs_kern.o hostfs_user.o
 
-obj-y = 
+obj-y =
 obj-$(CONFIG_HOSTFS) += hostfs.o
 
 SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
index d1f6c33..416761f 100644 (file)
@@ -3,7 +3,7 @@
 
 #include "os.h"
 
-/* These are exactly the same definitions as in fs.h, but the names are 
+/* These are exactly the same definitions as in fs.h, but the names are
  * changed so that this file can be included in both kernel and user files.
  */
 
@@ -31,16 +31,16 @@ struct hostfs_iattr {
        unsigned int    ia_attr_flags;
 };
 
-extern int stat_file(const char *path, unsigned long long *inode_out, 
+extern int stat_file(const char *path, unsigned long long *inode_out,
                     int *mode_out, int *nlink_out, int *uid_out, int *gid_out,
-                    unsigned long long *size_out, struct timespec *atime_out, 
-                    struct timespec *mtime_out, struct timespec *ctime_out, 
+                    unsigned long long *size_out, struct timespec *atime_out,
+                    struct timespec *mtime_out, struct timespec *ctime_out,
                     int *blksize_out, unsigned long long *blocks_out);
 extern int access_file(char *path, int r, int w, int x);
 extern int open_file(char *path, int r, int w, int append);
-extern int file_type(const char *path, int *rdev);
+extern int file_type(const char *path, int *maj, int *min);
 extern void *open_dir(char *path, int *err_out);
-extern char *read_dir(void *stream, unsigned long long *pos, 
+extern char *read_dir(void *stream, unsigned long long *pos,
                      unsigned long long *ino_out, int *len_out);
 extern void close_file(void *stream);
 extern void close_dir(void *stream);
@@ -48,7 +48,7 @@ extern int read_file(int fd, unsigned long long *offset, char *buf, int len);
 extern int write_file(int fd, unsigned long long *offset, const char *buf,
                      int len);
 extern int lseek_file(int fd, long long offset, int whence);
-extern int file_create(char *name, int ur, int uw, int ux, int gr, 
+extern int file_create(char *name, int ur, int uw, int ux, int gr,
                       int gw, int gx, int or, int ow, int ox);
 extern int set_attr(const char *file, struct hostfs_iattr *attrs);
 extern int make_symlink(const char *from, const char *to);
@@ -59,10 +59,10 @@ extern int do_mknod(const char *file, int mode, int dev);
 extern int link_file(const char *from, const char *to);
 extern int do_readlink(char *file, char *buf, int size);
 extern int rename_file(char *from, char *to);
-extern int do_statfs(char *root, long *bsize_out, long long *blocks_out, 
-                    long long *bfree_out, long long *bavail_out, 
-                    long long *files_out, long long *ffree_out, 
-                    void *fsid_out, int fsid_size, long *namelen_out, 
+extern int do_statfs(char *root, long *bsize_out, long long *blocks_out,
+                    long long *bfree_out, long long *bavail_out,
+                    long long *files_out, long long *ffree_out,
+                    void *fsid_out, int fsid_size, long *namelen_out,
                     long *spare_out);
 
 #endif
index e67f038..a2d5c4d 100644 (file)
@@ -1,11 +1,11 @@
-# 
+#
 # Copyright (C) 2002, 2003 Jeff Dike (jdike@karaya.com)
 # Licensed under the GPL
 #
 
 hppfs-objs := hppfs_kern.o
 
-obj-y = 
+obj-y =
 obj-$(CONFIG_HPPFS) += hppfs.o
 
 clean:
index ebf08cb..f8e0cbd 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -24,7 +24,7 @@ struct hppfs_data {
 };
 
 struct hppfs_private {
-       struct file proc_file;
+       struct file *proc_file;
        int host_fd;
        loff_t len;
        struct hppfs_data *contents;
@@ -75,7 +75,7 @@ static char *dentry_name(struct dentry *dentry, int extra)
                else len += parent->d_name.len + 1;
                parent = parent->d_parent;
        }
-       
+
        root = "proc";
        len += strlen(root);
        name = kmalloc(len + extra + 1, GFP_KERNEL);
@@ -155,7 +155,7 @@ static void hppfs_read_inode(struct inode *ino)
        ino->i_blocks = proc_ino->i_blocks;
 }
 
-static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, 
+static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
                                   struct nameidata *nd)
 {
        struct dentry *proc_dentry, *new, *parent;
@@ -178,7 +178,7 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
                        up(&parent->d_inode->i_sem);
                        goto out;
                }
-               new = (*parent->d_inode->i_op->lookup)(parent->d_inode, 
+               new = (*parent->d_inode->i_op->lookup)(parent->d_inode,
                                                       proc_dentry, NULL);
                if(new){
                        dput(proc_dentry);
@@ -191,13 +191,13 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
                return(proc_dentry);
 
        inode = iget(ino->i_sb, 0);
-       if(inode == NULL) 
+       if(inode == NULL)
                goto out_dput;
 
        err = init_inode(inode, proc_dentry);
-       if(err) 
+       if(err)
                goto out_put;
-       
+
        hppfs_read_inode(inode);
 
        d_add(dentry, inode);
@@ -215,7 +215,7 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
 static struct inode_operations hppfs_file_iops = {
 };
 
-static ssize_t read_proc(struct file *file, char *buf, ssize_t count, 
+static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
                         loff_t *ppos, int is_user)
 {
        ssize_t (*read)(struct file *, char *, size_t, loff_t *);
@@ -225,7 +225,7 @@ static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
 
        if(!is_user)
                set_fs(KERNEL_DS);
-               
+
        n = (*read)(file, buf, count, &file->f_pos);
 
        if(!is_user)
@@ -273,7 +273,7 @@ static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count)
        return(n);
 }
 
-static ssize_t hppfs_read(struct file *file, char *buf, size_t count, 
+static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
                          loff_t *ppos)
 {
        struct hppfs_private *hppfs = file->private_data;
@@ -307,16 +307,16 @@ static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
                if(count > 0)
                        *ppos += count;
        }
-       else count = read_proc(&hppfs->proc_file, buf, count, ppos, 1);
+       else count = read_proc(hppfs->proc_file, buf, count, ppos, 1);
 
        return(count);
 }
 
-static ssize_t hppfs_write(struct file *file, const char *buf, size_t len, 
+static ssize_t hppfs_write(struct file *file, const char *buf, size_t len,
                           loff_t *ppos)
 {
        struct hppfs_private *data = file->private_data;
-       struct file *proc_file = &data->proc_file;
+       struct file *proc_file = data->proc_file;
        ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
        int err;
 
@@ -361,9 +361,9 @@ static void free_contents(struct hppfs_data *head)
        kfree(head);
 }
 
-static struct hppfs_data *hppfs_get_data(int fd, int filter, 
-                                        struct file *proc_file, 
-                                        struct file *hppfs_file, 
+static struct hppfs_data *hppfs_get_data(int fd, int filter,
+                                        struct file *proc_file,
+                                        struct file *hppfs_file,
                                         loff_t *size_out)
 {
        struct hppfs_data *data, *new, *head;
@@ -414,7 +414,7 @@ static struct hppfs_data *hppfs_get_data(int fd, int filter,
                        err = -ENOMEM;
                        goto failed_free;
                }
-       
+
                INIT_LIST_HEAD(&new->list);
                list_add(&new->list, &data->list);
                data = new;
@@ -423,7 +423,7 @@ static struct hppfs_data *hppfs_get_data(int fd, int filter,
 
  failed_free:
        free_contents(head);
- failed:               
+ failed:
        return(ERR_PTR(err));
 }
 
@@ -471,15 +471,16 @@ static int hppfs_open(struct inode *inode, struct file *file)
        proc_dentry = HPPFS_I(inode)->proc_dentry;
 
        /* XXX This isn't closed anywhere */
-       err = open_private_file(&data->proc_file, proc_dentry, 
-                               file_mode(file->f_mode));
-       if(err)
+       data->proc_file = dentry_open(dget(proc_dentry), NULL,
+                                     file_mode(file->f_mode));
+       err = PTR_ERR(data->proc_file);
+       if(IS_ERR(data->proc_file))
                goto out_free1;
 
        type = os_file_type(host_file);
        if(type == OS_TYPE_FILE){
                fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
-               if(fd >= 0) 
+               if(fd >= 0)
                        data->host_fd = fd;
                else printk("hppfs_open : failed to open '%s', errno = %d\n",
                            host_file, -fd);
@@ -489,8 +490,8 @@ static int hppfs_open(struct inode *inode, struct file *file)
        else if(type == OS_TYPE_DIR){
                fd = open_host_sock(host_file, &filter);
                if(fd > 0){
-                       data->contents = hppfs_get_data(fd, filter, 
-                                                       &data->proc_file, 
+                       data->contents = hppfs_get_data(fd, filter,
+                                                       &data->proc_file,
                                                        file, &data->len);
                        if(!IS_ERR(data->contents))
                                data->host_fd = fd;
@@ -524,9 +525,10 @@ static int hppfs_dir_open(struct inode *inode, struct file *file)
                goto out;
 
        proc_dentry = HPPFS_I(inode)->proc_dentry;
-       err = open_private_file(&data->proc_file, proc_dentry, 
-                               file_mode(file->f_mode));
-       if(err)
+       data->proc_file = dentry_open(dget(proc_dentry), NULL,
+                                     file_mode(file->f_mode));
+       err = PTR_ERR(data->proc_file);
+       if(IS_ERR(data->proc_file))
                goto out_free;
 
        file->private_data = data;
@@ -569,7 +571,7 @@ struct hppfs_dirent {
        struct dentry *dentry;
 };
 
-static int hppfs_filldir(void *d, const char *name, int size, 
+static int hppfs_filldir(void *d, const char *name, int size,
                         loff_t offset, ino_t inode, unsigned int type)
 {
        struct hppfs_dirent *dirent = d;
@@ -577,7 +579,7 @@ static int hppfs_filldir(void *d, const char *name, int size,
        if(file_removed(dirent->dentry, name))
                return(0);
 
-       return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset, 
+       return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset,
                                  inode, type));
 }
 
@@ -629,7 +631,7 @@ static struct inode *hppfs_alloc_inode(struct super_block *sb)
        struct hppfs_inode_info *hi;
 
        hi = kmalloc(sizeof(*hi), GFP_KERNEL);
-       if(hi == NULL) 
+       if(hi == NULL)
                return(NULL);
 
        *hi = ((struct hppfs_inode_info) { .proc_dentry = NULL });
@@ -647,7 +649,7 @@ static void hppfs_destroy_inode(struct inode *inode)
        kfree(HPPFS_I(inode));
 }
 
-static struct super_operations hppfs_sbops = { 
+static struct super_operations hppfs_sbops = {
        .alloc_inode    = hppfs_alloc_inode,
        .destroy_inode  = hppfs_destroy_inode,
        .read_inode     = hppfs_read_inode,
@@ -657,41 +659,43 @@ static struct super_operations hppfs_sbops = {
 
 static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen)
 {
-       struct file proc_file;
+       struct file *proc_file;
        struct dentry *proc_dentry;
        int (*readlink)(struct dentry *, char *, int);
        int err, n;
 
        proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
-       err = open_private_file(&proc_file, proc_dentry, O_RDONLY);
-       if(err) 
+       proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY);
+       err = PTR_ERR(proc_dentry);
+       if(IS_ERR(proc_dentry))
                return(err);
 
        readlink = proc_dentry->d_inode->i_op->readlink;
        n = (*readlink)(proc_dentry, buffer, buflen);
 
-       close_private_file(&proc_file);
-       
+       fput(proc_file);
+
        return(n);
 }
 
 static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct file proc_file;
+       struct file *proc_file;
        struct dentry *proc_dentry;
        int (*follow_link)(struct dentry *, struct nameidata *);
        int err, n;
 
        proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
-       err = open_private_file(&proc_file, proc_dentry, O_RDONLY);
-       if(err) 
+       proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY);
+       err = PTR_ERR(proc_dentry);
+       if(IS_ERR(proc_dentry))
                return(err);
 
        follow_link = proc_dentry->d_inode->i_op->follow_link;
        n = (*follow_link)(proc_dentry, nd);
 
-       close_private_file(&proc_file);
-       
+       fput(proc_file);
+
        return(n);
 }
 
@@ -733,7 +737,7 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
 
        err = -ENOENT;
        procfs = get_fs_type("proc");
-       if(procfs == NULL) 
+       if(procfs == NULL)
                goto out;
 
        if(list_empty(&procfs->fs_supers))
@@ -741,7 +745,7 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
 
        proc_sb = list_entry(procfs->fs_supers.next, struct super_block,
                             s_instances);
-       
+
        sb->s_blocksize = 1024;
        sb->s_blocksize_bits = 10;
        sb->s_magic = HPPFS_SUPER_MAGIC;
index 8f19712..4a3d494 100644 (file)
@@ -191,10 +191,10 @@ static int count_tags(struct buffer_head *bh, int size)
 
                nr++;
                tagp += sizeof(journal_block_tag_t);
-               if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
+               if (!(tag->t_flags & cpu_to_be32(JFS_FLAG_SAME_UUID)))
                        tagp += 16;
 
-               if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
+               if (tag->t_flags & cpu_to_be32(JFS_FLAG_LAST_TAG))
                        break;
        }
 
@@ -239,8 +239,8 @@ int journal_recover(journal_t *journal)
 
        if (!sb->s_start) {
                jbd_debug(1, "No recovery required, last transaction %d\n",
-                         ntohl(sb->s_sequence));
-               journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
+                         be32_to_cpu(sb->s_sequence));
+               journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1;
                return 0;
        }
 
@@ -295,7 +295,7 @@ int journal_skip_recovery(journal_t *journal)
                ++journal->j_transaction_sequence;
        } else {
 #ifdef CONFIG_JBD_DEBUG
-               int dropped = info.end_transaction - ntohl(sb->s_sequence);
+               int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence);
 #endif
                jbd_debug(0, 
                          "JBD: ignoring %d transaction%s from the journal.\n",
@@ -331,8 +331,8 @@ static int do_one_pass(journal_t *journal,
         */
 
        sb = journal->j_superblock;
-       next_commit_ID = ntohl(sb->s_sequence);
-       next_log_block = ntohl(sb->s_start);
+       next_commit_ID = be32_to_cpu(sb->s_sequence);
+       next_log_block = be32_to_cpu(sb->s_start);
 
        first_commit_ID = next_commit_ID;
        if (pass == PASS_SCAN)
@@ -385,13 +385,13 @@ static int do_one_pass(journal_t *journal,
 
                tmp = (journal_header_t *)bh->b_data;
 
-               if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
+               if (tmp->h_magic != cpu_to_be32(JFS_MAGIC_NUMBER)) {
                        brelse(bh);
                        break;
                }
 
-               blocktype = ntohl(tmp->h_blocktype);
-               sequence = ntohl(tmp->h_sequence);
+               blocktype = be32_to_cpu(tmp->h_blocktype);
+               sequence = be32_to_cpu(tmp->h_sequence);
                jbd_debug(3, "Found magic %d, sequence %d\n", 
                          blocktype, sequence);
 
@@ -427,7 +427,7 @@ static int do_one_pass(journal_t *journal,
                                unsigned long io_block;
 
                                tag = (journal_block_tag_t *) tagp;
-                               flags = ntohl(tag->t_flags);
+                               flags = be32_to_cpu(tag->t_flags);
 
                                io_block = next_log_block++;
                                wrap(journal, next_log_block);
@@ -444,7 +444,7 @@ static int do_one_pass(journal_t *journal,
                                        unsigned long blocknr;
 
                                        J_ASSERT(obh != NULL);
-                                       blocknr = ntohl(tag->t_blocknr);
+                                       blocknr = be32_to_cpu(tag->t_blocknr);
 
                                        /* If the block has been
                                         * revoked, then we're all done
@@ -476,8 +476,8 @@ static int do_one_pass(journal_t *journal,
                                        memcpy(nbh->b_data, obh->b_data,
                                                        journal->j_blocksize);
                                        if (flags & JFS_FLAG_ESCAPE) {
-                                               *((unsigned int *)bh->b_data) =
-                                                       htonl(JFS_MAGIC_NUMBER);
+                                               *((__be32 *)bh->b_data) =
+                                               cpu_to_be32(JFS_MAGIC_NUMBER);
                                        }
 
                                        BUFFER_TRACE(nbh, "marking dirty");
@@ -572,13 +572,13 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
 
        header = (journal_revoke_header_t *) bh->b_data;
        offset = sizeof(journal_revoke_header_t);
-       max = ntohl(header->r_count);
+       max = be32_to_cpu(header->r_count);
 
        while (offset < max) {
                unsigned long blocknr;
                int err;
 
-               blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
+               blocknr = be32_to_cpu(* ((__be32 *) (bh->b_data+offset)));
                offset += 4;
                err = journal_set_revoke(journal, blocknr, sequence);
                if (err)
index 2b70f81..d94abcc 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
- *   Portions Copyright (c) Christoph Hellwig, 2001-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2004
+ *   Portions Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
 #include <linux/mpage.h>
 #include <linux/buffer_head.h>
 #include <linux/pagemap.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_imap.h"
@@ -105,10 +106,10 @@ int jfs_commit_inode(struct inode *inode, int wait)
        return rc;
 }
 
-void jfs_write_inode(struct inode *inode, int wait)
+int jfs_write_inode(struct inode *inode, int wait)
 {
        if (test_cflag(COMMIT_Nolink, inode))
-               return;
+               return 0;
        /*
         * If COMMIT_DIRTY is not set, the inode isn't really dirty.
         * It has been committed since the last change, but was still
@@ -117,12 +118,14 @@ void jfs_write_inode(struct inode *inode, int wait)
         if (!test_cflag(COMMIT_Dirty, inode)) {
                /* Make sure committed changes hit the disk */
                jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait);
-               return;
+               return 0;
         }
 
        if (jfs_commit_inode(inode, wait)) {
                jfs_err("jfs_write_inode: jfs_commit_inode failed!");
-       }
+               return -EIO;
+       } else
+               return 0;
 }
 
 void jfs_delete_inode(struct inode *inode)
@@ -134,6 +137,13 @@ void jfs_delete_inode(struct inode *inode)
 
        diFree(inode);
 
+       /*
+        * Free the inode from the quota allocation.
+        */
+       DQUOT_INIT(inode);
+       DQUOT_FREE_INODE(inode);
+       DQUOT_DROP(inode);
+
        clear_inode(inode);
 }
 
index 3e8592b..84f2459 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2004
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -17,6 +17,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_imap.h"
@@ -60,6 +61,17 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
        } else
                inode->i_gid = current->fsgid;
 
+       /*
+        * Allocate inode to quota.
+        */
+       if (DQUOT_ALLOC_INODE(inode)) {
+               DQUOT_DROP(inode);
+               inode->i_flags |= S_NOQUOTA;
+               inode->i_nlink = 0;
+               iput(inode);
+               return NULL;
+       }
+
        inode->i_mode = mode;
        if (S_ISDIR(mode))
                jfs_inode->mode2 = IDIRECTORY | mode;
index 71f6753..2eb6869 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines  Corp., 2000-2003
+ *   Copyright (C) International Business Machines  Corp., 2000-2004
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
 
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -390,7 +391,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
        }
        /* update bmap file size */
        ipbmap->i_size += xlen << sbi->l2bsize;
-       ipbmap->i_blocks += LBLK2PBLK(sb, xlen);
+       inode_add_bytes(ipbmap, xlen << sbi->l2bsize);
 
        iplist[0] = ipbmap;
        rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
index 205cfdb..5d3f82b 100644 (file)
@@ -27,14 +27,27 @@ int simple_statfs(struct super_block *sb, struct kstatfs *buf)
 }
 
 /*
- * Lookup the data. This is trivial - if the dentry didn't already
- * exist, we know it is negative.
+ * Retaining negative dentries for an in-memory filesystem just wastes
+ * memory and lookup time: arrange for them to be deleted immediately.
  */
+static int simple_delete_dentry(struct dentry *dentry)
+{
+       return 1;
+}
 
+/*
+ * Lookup the data. This is trivial - if the dentry didn't already
+ * exist, we know it is negative.  Set d_op to delete negative dentries.
+ */
 struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+       static struct dentry_operations simple_dentry_operations = {
+               .d_delete = simple_delete_dentry,
+       };
+
        if (dentry->d_name.len > NAME_MAX)
                return ERR_PTR(-ENAMETOOLONG);
+       dentry->d_op = &simple_dentry_operations;
        d_add(dentry, NULL);
        return NULL;
 }
@@ -456,6 +469,58 @@ ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
        return count;
 }
 
+/*
+ * Transaction based IO.
+ * The file expects a single write which triggers the transaction, and then
+ * possibly a read which collects the result - which is stored in a
+ * file-local buffer.
+ */
+char *simple_transaction_get(struct file *file, const char __user *buf, size_t size)
+{
+       struct simple_transaction_argresp *ar;
+       static spinlock_t simple_transaction_lock = SPIN_LOCK_UNLOCKED;
+
+       if (size > SIMPLE_TRANSACTION_LIMIT - 1)
+               return ERR_PTR(-EFBIG);
+
+       ar = (struct simple_transaction_argresp *)get_zeroed_page(GFP_KERNEL);
+       if (!ar)
+               return ERR_PTR(-ENOMEM);
+
+       spin_lock(&simple_transaction_lock);
+
+       /* only one write allowed per open */
+       if (file->private_data) {
+               spin_unlock(&simple_transaction_lock);
+               free_page((unsigned long)ar);
+               return ERR_PTR(-EBUSY);
+       }
+
+       file->private_data = ar;
+
+       spin_unlock(&simple_transaction_lock);
+
+       if (copy_from_user(ar->data, buf, size))
+               return ERR_PTR(-EFAULT);
+
+       return ar->data;
+}
+
+ssize_t simple_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
+{
+       struct simple_transaction_argresp *ar = file->private_data;
+
+       if (!ar)
+               return 0;
+       return simple_read_from_buffer(buf, size, pos, ar->data, ar->size);
+}
+
+int simple_transaction_release(struct inode *inode, struct file *file)
+{
+       free_page((unsigned long)file->private_data);
+       return 0;
+}
+
 EXPORT_SYMBOL(dcache_dir_close);
 EXPORT_SYMBOL(dcache_dir_lseek);
 EXPORT_SYMBOL(dcache_dir_open);
@@ -479,3 +544,6 @@ EXPORT_SYMBOL(simple_statfs);
 EXPORT_SYMBOL(simple_sync_file);
 EXPORT_SYMBOL(simple_unlink);
 EXPORT_SYMBOL(simple_read_from_buffer);
+EXPORT_SYMBOL(simple_transaction_get);
+EXPORT_SYMBOL(simple_transaction_read);
+EXPORT_SYMBOL(simple_transaction_release);
index 319e28f..caad617 100644 (file)
@@ -27,6 +27,7 @@ static int    nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
 static void    nlmclnt_unlock_callback(struct rpc_task *);
 static void    nlmclnt_cancel_callback(struct rpc_task *);
 static int     nlm_stat_to_errno(u32 stat);
+static void    nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host);
 
 /*
  * Cookie counter for NLM requests
@@ -41,11 +42,83 @@ static inline void nlmclnt_next_cookie(struct nlm_cookie *c)
        nlm_cookie++;
 }
 
+static struct nlm_lockowner *nlm_get_lockowner(struct nlm_lockowner *lockowner)
+{
+       atomic_inc(&lockowner->count);
+       return lockowner;
+}
+
+static void nlm_put_lockowner(struct nlm_lockowner *lockowner)
+{
+       if (!atomic_dec_and_lock(&lockowner->count, &lockowner->host->h_lock))
+               return;
+       list_del(&lockowner->list);
+       spin_unlock(&lockowner->host->h_lock);
+       nlm_release_host(lockowner->host);
+       kfree(lockowner);
+}
+
+static inline int nlm_pidbusy(struct nlm_host *host, uint32_t pid)
+{
+       struct nlm_lockowner *lockowner;
+       list_for_each_entry(lockowner, &host->h_lockowners, list) {
+               if (lockowner->pid == pid)
+                       return -EBUSY;
+       }
+       return 0;
+}
+
+static inline uint32_t __nlm_alloc_pid(struct nlm_host *host)
+{
+       uint32_t res;
+       do {
+               res = host->h_pidcount++;
+       } while (nlm_pidbusy(host, res) < 0);
+       return res;
+}
+
+static struct nlm_lockowner *__nlm_find_lockowner(struct nlm_host *host, fl_owner_t owner)
+{
+       struct nlm_lockowner *lockowner;
+       list_for_each_entry(lockowner, &host->h_lockowners, list) {
+               if (lockowner->owner != owner)
+                       continue;
+               return nlm_get_lockowner(lockowner);
+       }
+       return NULL;
+}
+
+static struct nlm_lockowner *nlm_find_lockowner(struct nlm_host *host, fl_owner_t owner)
+{
+       struct nlm_lockowner *res, *new = NULL;
+
+       spin_lock(&host->h_lock);
+       res = __nlm_find_lockowner(host, owner);
+       if (res == NULL) {
+               spin_unlock(&host->h_lock);
+               new = (struct nlm_lockowner *)kmalloc(sizeof(*new), GFP_KERNEL);
+               spin_lock(&host->h_lock);
+               res = __nlm_find_lockowner(host, owner);
+               if (res == NULL && new != NULL) {
+                       res = new;
+                       atomic_set(&new->count, 1);
+                       new->owner = owner;
+                       new->pid = __nlm_alloc_pid(host);
+                       new->host = nlm_get_host(host);
+                       list_add(&new->list, &host->h_lockowners);
+                       new = NULL;
+               }
+       }
+       spin_unlock(&host->h_lock);
+       if (new != NULL)
+               kfree(new);
+       return res;
+}
+
 /*
  * Initialize arguments for TEST/LOCK/UNLOCK/CANCEL calls
  */
-static inline void
-nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
+static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
 {
        struct nlm_args *argp = &req->a_args;
        struct nlm_lock *lock = &argp->lock;
@@ -60,6 +133,14 @@ nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
        locks_copy_lock(&lock->fl, fl);
 }
 
+static void nlmclnt_release_lockargs(struct nlm_rqst *req)
+{
+       struct file_lock *fl = &req->a_args.lock.fl;
+
+       if (fl->fl_ops && fl->fl_ops->fl_release_private)
+               fl->fl_ops->fl_release_private(fl);
+}
+
 /*
  * Initialize arguments for GRANTED call. The nlm_rqst structure
  * has been cleared already.
@@ -77,8 +158,10 @@ nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
 
        if (lock->oh.len > NLMCLNT_OHSIZE) {
                void *data = kmalloc(lock->oh.len, GFP_KERNEL);
-               if (!data)
+               if (!data) {
+                       nlmclnt_freegrantargs(call);
                        return 0;
+               }
                call->a_args.lock.oh.data = (u8 *) data;
        }
 
@@ -89,12 +172,15 @@ nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
 void
 nlmclnt_freegrantargs(struct nlm_rqst *call)
 {
+       struct file_lock *fl = &call->a_args.lock.fl;
        /*
         * Check whether we allocated memory for the owner.
         */
        if (call->a_args.lock.oh.data != (u8 *) call->a_owner) {
                kfree(call->a_args.lock.oh.data);
        }
+       if (fl->fl_ops && fl->fl_ops->fl_release_private)
+               fl->fl_ops->fl_release_private(fl);
 }
 
 /*
@@ -165,6 +251,8 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
        }
        call->a_host = host;
 
+       nlmclnt_locks_init_private(fl, host);
+
        /* Set up the argument struct */
        nlmclnt_setlockargs(call, fl);
 
@@ -179,9 +267,6 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
        else
                status = -EINVAL;
 
-       if (status < 0 && (call->a_flags & RPC_TASK_ASYNC))
-               kfree(call);
-
  out_restore:
        spin_lock_irqsave(&current->sighand->siglock, flags);
        current->blocked = oldset;
@@ -382,7 +467,9 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
 {
        int     status;
 
-       if ((status = nlmclnt_call(req, NLMPROC_TEST)) < 0)
+       status = nlmclnt_call(req, NLMPROC_TEST);
+       nlmclnt_release_lockargs(req);
+       if (status < 0)
                return status;
 
        status = req->a_res.status;
@@ -391,10 +478,9 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
        } if (status == NLM_LCK_DENIED) {
                /*
                 * Report the conflicting lock back to the application.
-                * FIXME: Is it OK to report the pid back as well?
                 */
                locks_copy_lock(fl, &req->a_res.lock.fl);
-               /* fl->fl_pid = 0; */
+               fl->fl_pid = 0;
        } else {
                return nlm_stat_to_errno(req->a_res.status);
        }
@@ -402,18 +488,30 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
        return 0;
 }
 
-static
-void nlmclnt_insert_lock_callback(struct file_lock *fl)
+static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl)
 {
-       nlm_get_host(fl->fl_u.nfs_fl.host);
+       memcpy(&new->fl_u.nfs_fl, &fl->fl_u.nfs_fl, sizeof(new->fl_u.nfs_fl));
+       nlm_get_lockowner(new->fl_u.nfs_fl.owner);
 }
-static
-void nlmclnt_remove_lock_callback(struct file_lock *fl)
+
+static void nlmclnt_locks_release_private(struct file_lock *fl)
 {
-       if (fl->fl_u.nfs_fl.host) {
-               nlm_release_host(fl->fl_u.nfs_fl.host);
-               fl->fl_u.nfs_fl.host = NULL;
-       }
+       nlm_put_lockowner(fl->fl_u.nfs_fl.owner);
+       fl->fl_ops = NULL;
+}
+
+static struct file_lock_operations nlmclnt_lock_ops = {
+       .fl_copy_lock = nlmclnt_locks_copy_lock,
+       .fl_release_private = nlmclnt_locks_release_private,
+};
+
+static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host)
+{
+       BUG_ON(fl->fl_ops != NULL);
+       fl->fl_u.nfs_fl.state = 0;
+       fl->fl_u.nfs_fl.flags = 0;
+       fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner);
+       fl->fl_ops = &nlmclnt_lock_ops;
 }
 
 /*
@@ -446,7 +544,8 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
        if (!host->h_monitored && nsm_monitor(host) < 0) {
                printk(KERN_NOTICE "lockd: failed to monitor %s\n",
                                        host->h_name);
-               return -ENOLCK;
+               status = -ENOLCK;
+               goto out;
        }
 
        do {
@@ -456,18 +555,21 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
                        status = nlmclnt_block(host, fl, &resp->status);
                }
                if (status < 0)
-                       return status;
+                       goto out;
        } while (resp->status == NLM_LCK_BLOCKED && req->a_args.block);
 
        if (resp->status == NLM_LCK_GRANTED) {
                fl->fl_u.nfs_fl.state = host->h_state;
                fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
-               fl->fl_u.nfs_fl.host = host;
-               fl->fl_insert = nlmclnt_insert_lock_callback;
-               fl->fl_remove = nlmclnt_remove_lock_callback;
+               fl->fl_flags |= FL_SLEEP;
+               if (posix_lock_file_wait(fl->fl_file, fl) < 0)
+                               printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+                                               __FUNCTION__);
        }
-
-       return nlm_stat_to_errno(resp->status);
+       status = nlm_stat_to_errno(resp->status);
+out:
+       nlmclnt_release_lockargs(req);
+       return status;
 }
 
 /*
@@ -527,13 +629,24 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
        fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED;
 
        if (req->a_flags & RPC_TASK_ASYNC) {
-               return nlmclnt_async_call(req, NLMPROC_UNLOCK,
+               status = nlmclnt_async_call(req, NLMPROC_UNLOCK,
                                        nlmclnt_unlock_callback);
+               /* Hrmf... Do the unlock early since locks_remove_posix()
+                * really expects us to free the lock synchronously */
+               posix_lock_file(fl->fl_file, fl);
+               if (status < 0) {
+                       nlmclnt_release_lockargs(req);
+                       kfree(req);
+               }
+               return status;
        }
 
-       if ((status = nlmclnt_call(req, NLMPROC_UNLOCK)) < 0)
+       status = nlmclnt_call(req, NLMPROC_UNLOCK);
+       nlmclnt_release_lockargs(req);
+       if (status < 0)
                return status;
 
+       posix_lock_file(fl->fl_file, fl);
        if (resp->status == NLM_LCK_GRANTED)
                return 0;
 
@@ -564,9 +677,9 @@ nlmclnt_unlock_callback(struct rpc_task *task)
        }
        if (status != NLM_LCK_GRANTED)
                printk(KERN_WARNING "lockd: unexpected unlock status: %d\n", status);
-
 die:
        nlm_release_host(req->a_host);
+       nlmclnt_release_lockargs(req);
        kfree(req);
        return;
  retry_rebind:
@@ -605,8 +718,10 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl)
 
        status = nlmclnt_async_call(req, NLMPROC_CANCEL,
                                        nlmclnt_cancel_callback);
-       if (status < 0)
+       if (status < 0) {
+               nlmclnt_release_lockargs(req);
                kfree(req);
+       }
 
        spin_lock_irqsave(&current->sighand->siglock, flags);
        current->blocked = oldset;
@@ -648,6 +763,7 @@ nlmclnt_cancel_callback(struct rpc_task *task)
 
 die:
        nlm_release_host(req->a_host);
+       nlmclnt_release_lockargs(req);
        kfree(req);
        return;
 
index 47c7713..1bc0676 100644 (file)
@@ -409,13 +409,13 @@ MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
 MODULE_LICENSE("GPL");
 
 module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong,
-                 &nlm_grace_period, 644);
+                 &nlm_grace_period, 0644);
 module_param_call(nlm_timeout, param_set_timeout, param_get_ulong,
-                 &nlm_timeout, 644);
+                 &nlm_timeout, 0644);
 module_param_call(nlm_udpport, param_set_port, param_get_int,
-                 &nlm_udpport, 644);
+                 &nlm_udpport, 0644);
 module_param_call(nlm_tcpport, param_set_port, param_get_int,
-                 &nlm_tcpport, 644);
+                 &nlm_tcpport, 0644);
 
 /*
  * Initialising and terminating the module.
index a3d3b78..3afa265 100644 (file)
@@ -53,8 +53,9 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
                *filp = file;
 
                /* Set up the missing parts of the file_lock structure */
-               lock->fl.fl_file  = &file->f_file;
+               lock->fl.fl_file  = file->f_file;
                lock->fl.fl_owner = (fl_owner_t) host;
+               lock->fl.fl_lmops = &nlmsvc_lock_operations;
        }
 
        return 0;
index b676e8c..3eca6cf 100644 (file)
@@ -82,8 +82,9 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
                *filp = file;
 
                /* Set up the missing parts of the file_lock structure */
-               lock->fl.fl_file  = &file->f_file;
+               lock->fl.fl_file  = file->f_file;
                lock->fl.fl_owner = (fl_owner_t) host;
+               lock->fl.fl_lmops = &nlmsvc_lock_operations;
        }
 
        return 0;
index 0be7f08..de75363 100644 (file)
@@ -67,7 +67,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
        down(&nlm_file_sema);
 
        for (file = nlm_files[hash]; file; file = file->f_next)
-               if (!memcmp(&file->f_handle, f, sizeof(*f)))
+               if (!nfs_compare_fh(&file->f_handle, f))
                        goto found;
 
        dprintk("lockd: creating file for (%08x %08x %08x %08x %08x %08x)\n",
@@ -124,7 +124,7 @@ out_free:
 static inline void
 nlm_delete_file(struct nlm_file *file)
 {
-       struct inode *inode = file->f_file.f_dentry->d_inode;
+       struct inode *inode = file->f_file->f_dentry->d_inode;
        struct nlm_file **fp, *f;
 
        dprintk("lockd: closing file %s/%ld\n",
@@ -133,7 +133,7 @@ nlm_delete_file(struct nlm_file *file)
        while ((f = *fp) != NULL) {
                if (f == file) {
                        *fp = file->f_next;
-                       nlmsvc_ops->fclose(&file->f_file);
+                       nlmsvc_ops->fclose(file->f_file);
                        kfree(file);
                        return;
                }
@@ -176,7 +176,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 (posix_lock_file(file->f_file, &lock) < 0) {
                                printk("lockd: unlock failure in %s:%d\n",
                                                __FILE__, __LINE__);
                                return 1;
@@ -230,7 +230,7 @@ nlm_traverse_files(struct nlm_host *host, int action)
                        if (!file->f_blocks && !file->f_locks
                         && !file->f_shares && !file->f_count) {
                                *fp = file->f_next;
-                               nlmsvc_ops->fclose(&file->f_file);
+                               nlmsvc_ops->fclose(file->f_file);
                                kfree(file);
                        } else {
                                fp = &file->f_next;
index f8e9bd8..5a4b51d 100644 (file)
@@ -358,5 +358,5 @@ static inline unsigned nblocks(loff_t size)
                res += blocks;
                direct = 1;
        }
-       return blocks;
+       return res;
 }
index 845bfe4..6593a5c 100644 (file)
@@ -337,7 +337,7 @@ static void info_server(struct ncp_server *server, unsigned int id, const void *
 {
        if (server->info_sock) {
                struct kvec iov[2];
-               __u32 hdr[2];
+               __be32 hdr[2];
        
                hdr[0] = cpu_to_be32(len + 8);
                hdr[1] = cpu_to_be32(id);
index 15697bc..e935f1b 100644 (file)
@@ -36,8 +36,8 @@
 /* these magic numbers must appear in the symlink file -- this makes it a bit
    more resilient against the magic attributes being set on random files. */
 
-#define NCP_SYMLINK_MAGIC0     le32_to_cpu(0x6c6d7973)     /* "symlnk->" */
-#define NCP_SYMLINK_MAGIC1     le32_to_cpu(0x3e2d6b6e)
+#define NCP_SYMLINK_MAGIC0     cpu_to_le32(0x6c6d7973)     /* "symlnk->" */
+#define NCP_SYMLINK_MAGIC1     cpu_to_le32(0x3e2d6b6e)
 
 /* ----- read a symbolic link ------------------------------------------ */
 
@@ -67,8 +67,8 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
 
        if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) {
                if (length<NCP_MIN_SYMLINK_SIZE || 
-                   ((__u32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
-                   ((__u32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
+                   ((__le32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
+                   ((__le32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
                        goto failEIO;
                link = rawlink + 8;
                length -= 8;
@@ -110,7 +110,8 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
        char *rawlink;
        int length, err, i, outlen;
        int kludge;
-       int mode, attr;
+       int mode;
+       __le32 attr;
        unsigned int hdr;
 
        DPRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
@@ -133,8 +134,8 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
        if (kludge) {
                mode = 0;
                attr = aSHARED | aHIDDEN;
-               ((__u32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0;
-               ((__u32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1;
+               ((__le32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0;
+               ((__le32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1;
                hdr = 8;
        } else {
                mode = S_IFLNK | S_IRWXUGO;
index d85ccd5..b4baa03 100644 (file)
@@ -9,6 +9,7 @@ nfs-y                   := dir.o file.o inode.o nfs2xdr.o pagelist.o \
 nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o      
 nfs-$(CONFIG_NFS_V3)   += nfs3proc.o nfs3xdr.o
 nfs-$(CONFIG_NFS_V4)   += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
-                          idmap.o
+                          delegation.o idmap.o \
+                          callback.o callback_xdr.o callback_proc.o
 nfs-$(CONFIG_NFS_DIRECTIO) += direct.o
 nfs-objs               := $(nfs-y)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
new file mode 100644 (file)
index 0000000..ad7677b
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * linux/fs/nfs/callback.c
+ *
+ * Copyright (C) 2004 Trond Myklebust
+ *
+ * NFSv4 callback handling
+ */
+
+#include <linux/config.h>
+#include <linux/completion.h>
+#include <linux/ip.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/sunrpc/svc.h>
+#include <linux/sunrpc/svcsock.h>
+#include <linux/nfs_fs.h>
+#include "callback.h"
+
+#define NFSDBG_FACILITY NFSDBG_CALLBACK
+
+struct nfs_callback_data {
+       unsigned int users;
+       struct svc_serv *serv;
+       pid_t pid;
+       struct completion started;
+       struct completion stopped;
+};
+
+static struct nfs_callback_data nfs_callback_info;
+static DECLARE_MUTEX(nfs_callback_sema);
+static struct svc_program nfs4_callback_program;
+
+unsigned short nfs_callback_tcpport;
+
+/*
+ * This is the callback kernel thread.
+ */
+static void nfs_callback_svc(struct svc_rqst *rqstp)
+{
+       struct svc_serv *serv = rqstp->rq_server;
+       int err;
+
+       __module_get(THIS_MODULE);
+       lock_kernel();
+
+       nfs_callback_info.pid = current->pid;
+       daemonize("nfsv4-svc");
+       /* Process request with signals blocked, but allow SIGKILL.  */
+       allow_signal(SIGKILL);
+
+       complete(&nfs_callback_info.started);
+
+       while (nfs_callback_info.users != 0 || !signalled()) {
+               /*
+                * Listen for a request on the socket
+                */
+               err = svc_recv(serv, rqstp, MAX_SCHEDULE_TIMEOUT);
+               if (err == -EAGAIN || err == -EINTR)
+                       continue;
+               if (err < 0) {
+                       printk(KERN_WARNING
+                                       "%s: terminating on error %d\n",
+                                       __FUNCTION__, -err);
+                       break;
+               }
+               dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__,
+                               NIPQUAD(rqstp->rq_addr.sin_addr.s_addr));
+               svc_process(serv, rqstp);
+       }
+
+       nfs_callback_info.pid = 0;
+       complete(&nfs_callback_info.stopped);
+       unlock_kernel();
+       module_put_and_exit(0);
+}
+
+/*
+ * Bring up the server process if it is not already up.
+ */
+int nfs_callback_up(void)
+{
+       struct svc_serv *serv;
+       struct svc_sock *svsk;
+       int ret = 0;
+
+       lock_kernel();
+       down(&nfs_callback_sema);
+       if (nfs_callback_info.users++ || nfs_callback_info.pid != 0)
+               goto out;
+       init_completion(&nfs_callback_info.started);
+       init_completion(&nfs_callback_info.stopped);
+       serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE);
+       ret = -ENOMEM;
+       if (!serv)
+               goto out_err;
+       /* FIXME: We don't want to register this socket with the portmapper */
+       ret = svc_makesock(serv, IPPROTO_TCP, 0);
+       if (ret < 0)
+               goto out_destroy;
+       if (!list_empty(&serv->sv_permsocks)) {
+               svsk = list_entry(serv->sv_permsocks.next,
+                               struct svc_sock, sk_list);
+               nfs_callback_tcpport = ntohs(inet_sk(svsk->sk_sk)->sport);
+               dprintk ("Callback port = 0x%x\n", nfs_callback_tcpport);
+       } else
+               BUG();
+       ret = svc_create_thread(nfs_callback_svc, serv);
+       if (ret < 0)
+               goto out_destroy;
+       nfs_callback_info.serv = serv;
+       wait_for_completion(&nfs_callback_info.started);
+out:
+       up(&nfs_callback_sema);
+       unlock_kernel();
+       return ret;
+out_destroy:
+       svc_destroy(serv);
+out_err:
+       nfs_callback_info.users--;
+       goto out;
+}
+
+/*
+ * Kill the server process if it is not already up.
+ */
+int nfs_callback_down(void)
+{
+       int ret = 0;
+
+       lock_kernel();
+       down(&nfs_callback_sema);
+       if (--nfs_callback_info.users || nfs_callback_info.pid == 0)
+               goto out;
+       kill_proc(nfs_callback_info.pid, SIGKILL, 1);
+       wait_for_completion(&nfs_callback_info.stopped);
+out:
+       up(&nfs_callback_sema);
+       unlock_kernel();
+       return ret;
+}
+
+/*
+ * AUTH_NULL authentication
+ */
+static int nfs_callback_null_accept(struct svc_rqst *rqstp, u32 *authp)
+{
+       struct kvec    *argv = &rqstp->rq_arg.head[0];
+       struct kvec    *resv = &rqstp->rq_res.head[0];
+
+       if (argv->iov_len < 3*4)
+               return SVC_GARBAGE;
+
+       if (svc_getu32(argv) != 0) {
+               dprintk("svc: bad null cred\n");
+               *authp = rpc_autherr_badcred;
+               return SVC_DENIED;
+       }
+       if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
+               dprintk("svc: bad null verf\n");
+                *authp = rpc_autherr_badverf;
+                return SVC_DENIED;
+       }
+
+       /* Signal that mapping to nobody uid/gid is required */
+       rqstp->rq_cred.cr_uid = (uid_t) -1;
+       rqstp->rq_cred.cr_gid = (gid_t) -1;
+       rqstp->rq_cred.cr_group_info = groups_alloc(0);
+       if (rqstp->rq_cred.cr_group_info == NULL)
+               return SVC_DROP; /* kmalloc failure - client must retry */
+
+       /* Put NULL verifier */
+       svc_putu32(resv, RPC_AUTH_NULL);
+       svc_putu32(resv, 0);
+       dprintk("%s: success, returning %d!\n", __FUNCTION__, SVC_OK);
+       return SVC_OK;
+}
+
+static int nfs_callback_null_release(struct svc_rqst *rqstp)
+{
+       if (rqstp->rq_cred.cr_group_info)
+               put_group_info(rqstp->rq_cred.cr_group_info);
+       rqstp->rq_cred.cr_group_info = NULL;
+       return 0; /* don't drop */
+}
+
+static struct auth_ops nfs_callback_auth_null = {
+       .name = "null",
+       .flavour = RPC_AUTH_NULL,
+       .accept = nfs_callback_null_accept,
+       .release = nfs_callback_null_release,
+};
+
+/*
+ * AUTH_SYS authentication
+ */
+static int nfs_callback_unix_accept(struct svc_rqst *rqstp, u32 *authp)
+{
+       struct kvec    *argv = &rqstp->rq_arg.head[0];
+       struct kvec    *resv = &rqstp->rq_res.head[0];
+       struct svc_cred *cred = &rqstp->rq_cred;
+       u32 slen, i;
+       int len = argv->iov_len;
+
+       dprintk("%s: start\n", __FUNCTION__);
+       cred->cr_group_info = NULL;
+       rqstp->rq_client = NULL;
+       if ((len -= 3*4) < 0)
+               return SVC_GARBAGE;
+
+       /* Get length, time stamp and machine name */
+       svc_getu32(argv);
+       svc_getu32(argv);
+       slen = XDR_QUADLEN(ntohl(svc_getu32(argv)));
+       if (slen > 64 || (len -= (slen + 3)*4) < 0)
+               goto badcred;
+       argv->iov_base = (void*)((u32*)argv->iov_base + slen);
+       argv->iov_len -= slen*4;
+
+       cred->cr_uid = ntohl(svc_getu32(argv));
+       cred->cr_gid = ntohl(svc_getu32(argv));
+       slen = ntohl(svc_getu32(argv));
+       if (slen > 16 || (len -= (slen + 2)*4) < 0)
+               goto badcred;
+       cred->cr_group_info = groups_alloc(slen);
+       if (cred->cr_group_info == NULL)
+               return SVC_DROP;
+       for (i = 0; i < slen; i++)
+               GROUP_AT(cred->cr_group_info, i) = ntohl(svc_getu32(argv));
+
+       if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
+               *authp = rpc_autherr_badverf;
+               return SVC_DENIED;
+       }
+       /* Put NULL verifier */
+       svc_putu32(resv, RPC_AUTH_NULL);
+       svc_putu32(resv, 0);
+       dprintk("%s: success, returning %d!\n", __FUNCTION__, SVC_OK);
+       return SVC_OK;
+badcred:
+       *authp = rpc_autherr_badcred;
+       return SVC_DENIED;
+}
+
+static int nfs_callback_unix_release(struct svc_rqst *rqstp)
+{
+       if (rqstp->rq_cred.cr_group_info)
+               put_group_info(rqstp->rq_cred.cr_group_info);
+       rqstp->rq_cred.cr_group_info = NULL;
+       return 0;
+}
+
+static struct auth_ops nfs_callback_auth_unix = {
+       .name = "unix",
+       .flavour = RPC_AUTH_UNIX,
+       .accept = nfs_callback_unix_accept,
+       .release = nfs_callback_unix_release,
+};
+
+/*
+ * Hook the authentication protocol
+ */
+static int nfs_callback_auth(struct svc_rqst *rqstp, u32 *authp)
+{
+       struct in_addr *addr = &rqstp->rq_addr.sin_addr;
+       struct nfs4_client *clp;
+       struct kvec *argv = &rqstp->rq_arg.head[0];
+       int flavour;
+       int retval;
+
+       /* Don't talk to strangers */
+       clp = nfs4_find_client(addr);
+       if (clp == NULL)
+               return SVC_DROP;
+       dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr));
+       nfs4_put_client(clp);
+       flavour = ntohl(svc_getu32(argv));
+       switch(flavour) {
+               case RPC_AUTH_NULL:
+                       if (rqstp->rq_proc != CB_NULL) {
+                               *authp = rpc_autherr_tooweak;
+                               retval = SVC_DENIED;
+                               break;
+                       }
+                       rqstp->rq_authop = &nfs_callback_auth_null;
+                       retval = nfs_callback_null_accept(rqstp, authp);
+                       break;
+               case RPC_AUTH_UNIX:
+                       /* Eat the authentication flavour */
+                       rqstp->rq_authop = &nfs_callback_auth_unix;
+                       retval = nfs_callback_unix_accept(rqstp, authp);
+                       break;
+               default:
+                       /* FIXME: need to add RPCSEC_GSS upcalls */
+#if 0
+                       svc_ungetu32(argv);
+                       retval = svc_authenticate(rqstp, authp);
+#else
+                       *authp = rpc_autherr_rejectedcred;
+                       retval = SVC_DENIED;
+#endif
+       }
+       dprintk("%s: flavour %d returning error %d\n", __FUNCTION__, flavour, retval);
+       return retval;
+}
+
+/*
+ * Define NFS4 callback program
+ */
+extern struct svc_version nfs4_callback_version1;
+
+static struct svc_version *nfs4_callback_version[] = {
+       [1] = &nfs4_callback_version1,
+};
+
+static struct svc_stat nfs4_callback_stats;
+
+static struct svc_program nfs4_callback_program = {
+       .pg_prog = NFS4_CALLBACK,                       /* RPC service number */
+       .pg_nvers = ARRAY_SIZE(nfs4_callback_version),  /* Number of entries */
+       .pg_vers = nfs4_callback_version,               /* version table */
+       .pg_name = "NFSv4 callback",                    /* service name */
+       .pg_class = "nfs",                              /* authentication class */
+       .pg_stats = &nfs4_callback_stats,
+       .pg_authenticate = nfs_callback_auth,
+};
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
new file mode 100644 (file)
index 0000000..a0db2d4
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * linux/fs/nfs/callback.h
+ *
+ * Copyright (C) 2004 Trond Myklebust
+ *
+ * NFSv4 callback definitions
+ */
+#ifndef __LINUX_FS_NFS_CALLBACK_H
+#define __LINUX_FS_NFS_CALLBACK_H
+
+#define NFS4_CALLBACK 0x40000000
+#define NFS4_CALLBACK_XDRSIZE 2048
+#define NFS4_CALLBACK_BUFSIZE (1024 + NFS4_CALLBACK_XDRSIZE)
+
+enum nfs4_callback_procnum {
+       CB_NULL = 0,
+       CB_COMPOUND = 1,
+};
+
+enum nfs4_callback_opnum {
+       OP_CB_GETATTR = 3,
+       OP_CB_RECALL  = 4,
+       OP_CB_ILLEGAL = 10044,
+};
+
+struct cb_compound_hdr_arg {
+       int taglen;
+       const char *tag;
+       unsigned int callback_ident;
+       unsigned nops;
+};
+
+struct cb_compound_hdr_res {
+       uint32_t *status;
+       int taglen;
+       const char *tag;
+       uint32_t *nops;
+};
+
+struct cb_getattrargs {
+       struct sockaddr_in *addr;
+       struct nfs_fh fh;
+       uint32_t bitmap[2];
+};
+
+struct cb_getattrres {
+       uint32_t status;
+       uint32_t bitmap[2];
+       uint64_t size;
+       uint64_t change_attr;
+       struct timespec ctime;
+       struct timespec mtime;
+};
+
+struct cb_recallargs {
+       struct sockaddr_in *addr;
+       struct nfs_fh fh;
+       nfs4_stateid stateid;
+       uint32_t truncate;
+};
+
+extern unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res);
+extern unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
+
+extern int nfs_callback_up(void);
+extern int nfs_callback_down(void);
+
+extern unsigned short nfs_callback_tcpport;
+
+#endif /* __LINUX_FS_NFS_CALLBACK_H */
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
new file mode 100644 (file)
index 0000000..ece27e4
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * linux/fs/nfs/callback_proc.c
+ *
+ * Copyright (C) 2004 Trond Myklebust
+ *
+ * NFSv4 callback procedures
+ */
+#include <linux/config.h>
+#include <linux/nfs4.h>
+#include <linux/nfs_fs.h>
+#include "callback.h"
+#include "delegation.h"
+
+#define NFSDBG_FACILITY NFSDBG_CALLBACK
+unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res)
+{
+       struct nfs4_client *clp;
+       struct nfs_delegation *delegation;
+       struct nfs_inode *nfsi;
+       struct inode *inode;
+       
+       res->bitmap[0] = res->bitmap[1] = 0;
+       res->status = htonl(NFS4ERR_BADHANDLE);
+       clp = nfs4_find_client(&args->addr->sin_addr);
+       if (clp == NULL)
+               goto out;
+       inode = nfs_delegation_find_inode(clp, &args->fh);
+       if (inode == NULL)
+               goto out_putclient;
+       nfsi = NFS_I(inode);
+       down_read(&nfsi->rwsem);
+       delegation = nfsi->delegation;
+       if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0)
+               goto out_iput;
+       res->size = i_size_read(inode);
+       res->change_attr = NFS_CHANGE_ATTR(inode);
+       res->ctime = inode->i_ctime;
+       res->mtime = inode->i_mtime;
+       res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) &
+               args->bitmap[0];
+       res->bitmap[1] = (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) &
+               args->bitmap[1];
+       res->status = 0;
+out_iput:
+       up_read(&nfsi->rwsem);
+       iput(inode);
+out_putclient:
+       nfs4_put_client(clp);
+out:
+       dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res->status));
+       return res->status;
+}
+
+unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
+{
+       struct nfs4_client *clp;
+       struct inode *inode;
+       unsigned res;
+       
+       res = htonl(NFS4ERR_BADHANDLE);
+       clp = nfs4_find_client(&args->addr->sin_addr);
+       if (clp == NULL)
+               goto out;
+       inode = nfs_delegation_find_inode(clp, &args->fh);
+       if (inode == NULL)
+               goto out_putclient;
+       /* Set up a helper thread to actually return the delegation */
+       switch(nfs_async_inode_return_delegation(inode, &args->stateid)) {
+               case 0:
+                       res = 0;
+                       break;
+               case -ENOENT:
+                       res = htonl(NFS4ERR_BAD_STATEID);
+                       break;
+               default:
+                       res = htonl(NFS4ERR_RESOURCE);
+       }
+       iput(inode);
+out_putclient:
+       nfs4_put_client(clp);
+out:
+       dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res));
+       return res;
+}
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
new file mode 100644 (file)
index 0000000..d271df9
--- /dev/null
@@ -0,0 +1,481 @@
+/*
+ * linux/fs/nfs/callback_xdr.c
+ *
+ * Copyright (C) 2004 Trond Myklebust
+ *
+ * NFSv4 callback encode/decode procedures
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sunrpc/svc.h>
+#include <linux/nfs4.h>
+#include <linux/nfs_fs.h>
+#include "callback.h"
+
+#define CB_OP_TAGLEN_MAXSZ     (512)
+#define CB_OP_HDR_RES_MAXSZ    (2 + CB_OP_TAGLEN_MAXSZ)
+#define CB_OP_GETATTR_BITMAP_MAXSZ     (4)
+#define CB_OP_GETATTR_RES_MAXSZ        (CB_OP_HDR_RES_MAXSZ + \
+                               CB_OP_GETATTR_BITMAP_MAXSZ + \
+                               2 + 2 + 3 + 3)
+#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
+
+#define NFSDBG_FACILITY NFSDBG_CALLBACK
+
+typedef unsigned (*callback_process_op_t)(void *, void *);
+typedef unsigned (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *);
+typedef unsigned (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *);
+
+
+struct callback_op {
+       callback_process_op_t process_op;
+       callback_decode_arg_t decode_args;
+       callback_encode_res_t encode_res;
+       long res_maxsize;
+};
+
+static struct callback_op callback_ops[];
+
+static int nfs4_callback_null(struct svc_rqst *rqstp, void *argp, void *resp)
+{
+       return htonl(NFS4_OK);
+}
+
+static int nfs4_decode_void(struct svc_rqst *rqstp, uint32_t *p, void *dummy)
+{
+       return xdr_argsize_check(rqstp, p);
+}
+
+static int nfs4_encode_void(struct svc_rqst *rqstp, uint32_t *p, void *dummy)
+{
+       return xdr_ressize_check(rqstp, p);
+}
+
+static uint32_t *read_buf(struct xdr_stream *xdr, int nbytes)
+{
+       uint32_t *p;
+
+       p = xdr_inline_decode(xdr, nbytes);
+       if (unlikely(p == NULL))
+               printk(KERN_WARNING "NFSv4 callback reply buffer overflowed!\n");
+       return p;
+}
+
+static unsigned decode_string(struct xdr_stream *xdr, unsigned int *len, const char **str)
+{
+       uint32_t *p;
+
+       p = read_buf(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       *len = ntohl(*p);
+
+       if (*len != 0) {
+               p = read_buf(xdr, *len);
+               if (unlikely(p == NULL))
+                       return htonl(NFS4ERR_RESOURCE);
+               *str = (const char *)p;
+       } else
+               *str = NULL;
+
+       return 0;
+}
+
+static unsigned decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh)
+{
+       uint32_t *p;
+
+       p = read_buf(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       fh->size = ntohl(*p);
+       if (fh->size > NFS4_FHSIZE)
+               return htonl(NFS4ERR_BADHANDLE);
+       p = read_buf(xdr, fh->size);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       memcpy(&fh->data[0], p, fh->size);
+       memset(&fh->data[fh->size], 0, sizeof(fh->data) - fh->size);
+       return 0;
+}
+
+static unsigned decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
+{
+       uint32_t *p;
+       unsigned int attrlen;
+
+       p = read_buf(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       attrlen = ntohl(*p);
+       p = read_buf(xdr, attrlen << 2);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       if (likely(attrlen > 0))
+               bitmap[0] = ntohl(*p++);
+       if (attrlen > 1)
+               bitmap[1] = ntohl(*p);
+       return 0;
+}
+
+static unsigned decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
+{
+       uint32_t *p;
+
+       p = read_buf(xdr, 16);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       memcpy(stateid->data, p, 16);
+       return 0;
+}
+
+static unsigned decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr)
+{
+       uint32_t *p;
+       unsigned int minor_version;
+       unsigned status;
+
+       status = decode_string(xdr, &hdr->taglen, &hdr->tag);
+       if (unlikely(status != 0))
+               return status;
+       /* We do not like overly long tags! */
+       if (hdr->taglen > CB_OP_TAGLEN_MAXSZ-12 || hdr->taglen < 0) {
+               printk("NFSv4 CALLBACK %s: client sent tag of length %u\n",
+                               __FUNCTION__, hdr->taglen);
+               return htonl(NFS4ERR_RESOURCE);
+       }
+       p = read_buf(xdr, 12);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       minor_version = ntohl(*p++);
+       /* Check minor version is zero. */
+       if (minor_version != 0) {
+               printk(KERN_WARNING "%s: NFSv4 server callback with illegal minor version %u!\n",
+                               __FUNCTION__, minor_version);
+               return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
+       }
+       hdr->callback_ident = ntohl(*p++);
+       hdr->nops = ntohl(*p);
+       return 0;
+}
+
+static unsigned decode_op_hdr(struct xdr_stream *xdr, unsigned int *op)
+{
+       uint32_t *p;
+       p = read_buf(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       *op = ntohl(*p);
+       return 0;
+}
+
+static unsigned decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_getattrargs *args)
+{
+       unsigned status;
+
+       status = decode_fh(xdr, &args->fh);
+       if (unlikely(status != 0))
+               goto out;
+       args->addr = &rqstp->rq_addr;
+       status = decode_bitmap(xdr, args->bitmap);
+out:
+       dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
+       return status;
+}
+
+static unsigned decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_recallargs *args)
+{
+       uint32_t *p;
+       unsigned status;
+
+       args->addr = &rqstp->rq_addr;
+       status = decode_stateid(xdr, &args->stateid);
+       if (unlikely(status != 0))
+               goto out;
+       p = read_buf(xdr, 4);
+       if (unlikely(p == NULL)) {
+               status = htonl(NFS4ERR_RESOURCE);
+               goto out;
+       }
+       args->truncate = ntohl(*p);
+       status = decode_fh(xdr, &args->fh);
+out:
+       dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
+       return 0;
+}
+
+static unsigned encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
+{
+       uint32_t *p;
+
+       p = xdr_reserve_space(xdr, 4 + len);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       xdr_encode_opaque(p, str, len);
+       return 0;
+}
+
+#define CB_SUPPORTED_ATTR0 (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE)
+#define CB_SUPPORTED_ATTR1 (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY)
+static unsigned encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitmap, uint32_t **savep)
+{
+       uint32_t bm[2];
+       uint32_t *p;
+
+       bm[0] = htonl(bitmap[0] & CB_SUPPORTED_ATTR0);
+       bm[1] = htonl(bitmap[1] & CB_SUPPORTED_ATTR1);
+       if (bm[1] != 0) {
+               p = xdr_reserve_space(xdr, 16);
+               if (unlikely(p == NULL))
+                       return htonl(NFS4ERR_RESOURCE);
+               *p++ = htonl(2);
+               *p++ = bm[0];
+               *p++ = bm[1];
+       } else if (bm[0] != 0) {
+               p = xdr_reserve_space(xdr, 12);
+               if (unlikely(p == NULL))
+                       return htonl(NFS4ERR_RESOURCE);
+               *p++ = htonl(1);
+               *p++ = bm[0];
+       } else {
+               p = xdr_reserve_space(xdr, 8);
+               if (unlikely(p == NULL))
+                       return htonl(NFS4ERR_RESOURCE);
+               *p++ = htonl(0);
+       }
+       *savep = p;
+       return 0;
+}
+
+static unsigned encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t change)
+{
+       uint32_t *p;
+
+       if (!(bitmap[0] & FATTR4_WORD0_CHANGE))
+               return 0;
+       p = xdr_reserve_space(xdr, 8);
+       if (unlikely(p == 0))
+               return htonl(NFS4ERR_RESOURCE);
+       p = xdr_encode_hyper(p, change);
+       return 0;
+}
+
+static unsigned encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t size)
+{
+       uint32_t *p;
+
+       if (!(bitmap[0] & FATTR4_WORD0_SIZE))
+               return 0;
+       p = xdr_reserve_space(xdr, 8);
+       if (unlikely(p == 0))
+               return htonl(NFS4ERR_RESOURCE);
+       p = xdr_encode_hyper(p, size);
+       return 0;
+}
+
+static unsigned encode_attr_time(struct xdr_stream *xdr, const struct timespec *time)
+{
+       uint32_t *p;
+
+       p = xdr_reserve_space(xdr, 12);
+       if (unlikely(p == 0))
+               return htonl(NFS4ERR_RESOURCE);
+       p = xdr_encode_hyper(p, time->tv_sec);
+       *p = htonl(time->tv_nsec);
+       return 0;
+}
+
+static unsigned encode_attr_ctime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time)
+{
+       if (!(bitmap[1] & FATTR4_WORD1_TIME_METADATA))
+               return 0;
+       return encode_attr_time(xdr,time);
+}
+
+static unsigned encode_attr_mtime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time)
+{
+       if (!(bitmap[1] & FATTR4_WORD1_TIME_MODIFY))
+               return 0;
+       return encode_attr_time(xdr,time);
+}
+
+static unsigned encode_compound_hdr_res(struct xdr_stream *xdr, struct cb_compound_hdr_res *hdr)
+{
+       unsigned status;
+
+       hdr->status = xdr_reserve_space(xdr, 4);
+       if (unlikely(hdr->status == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       status = encode_string(xdr, hdr->taglen, hdr->tag);
+       if (unlikely(status != 0))
+               return status;
+       hdr->nops = xdr_reserve_space(xdr, 4);
+       if (unlikely(hdr->nops == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       return 0;
+}
+
+static unsigned encode_op_hdr(struct xdr_stream *xdr, uint32_t op, uint32_t res)
+{
+       uint32_t *p;
+       
+       p = xdr_reserve_space(xdr, 8);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       *p++ = htonl(op);
+       *p = res;
+       return 0;
+}
+
+static unsigned encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr, const struct cb_getattrres *res)
+{
+       uint32_t *savep;
+       unsigned status = res->status;
+       
+       if (unlikely(status != 0))
+               goto out;
+       status = encode_attr_bitmap(xdr, res->bitmap, &savep);
+       if (unlikely(status != 0))
+               goto out;
+       status = encode_attr_change(xdr, res->bitmap, res->change_attr);
+       if (unlikely(status != 0))
+               goto out;
+       status = encode_attr_size(xdr, res->bitmap, res->size);
+       if (unlikely(status != 0))
+               goto out;
+       status = encode_attr_ctime(xdr, res->bitmap, &res->ctime);
+       if (unlikely(status != 0))
+               goto out;
+       status = encode_attr_mtime(xdr, res->bitmap, &res->mtime);
+       *savep = htonl((unsigned int)((char *)xdr->p - (char *)(savep+1)));
+out:
+       dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
+       return status;
+}
+
+static unsigned process_op(struct svc_rqst *rqstp,
+               struct xdr_stream *xdr_in, void *argp,
+               struct xdr_stream *xdr_out, void *resp)
+{
+       struct callback_op *op;
+       unsigned int op_nr;
+       unsigned int status = 0;
+       long maxlen;
+       unsigned res;
+
+       dprintk("%s: start\n", __FUNCTION__);
+       status = decode_op_hdr(xdr_in, &op_nr);
+       if (unlikely(status != 0)) {
+               op_nr = OP_CB_ILLEGAL;
+               op = &callback_ops[0];
+       } else if (unlikely(op_nr != OP_CB_GETATTR && op_nr != OP_CB_RECALL)) {
+               op_nr = OP_CB_ILLEGAL;
+               op = &callback_ops[0];
+               status = htonl(NFS4ERR_OP_ILLEGAL);
+       } else
+               op = &callback_ops[op_nr];
+
+       maxlen = xdr_out->end - xdr_out->p;
+       if (maxlen > 0 && maxlen < PAGE_SIZE) {
+               if (likely(status == 0 && op->decode_args != NULL))
+                       status = op->decode_args(rqstp, xdr_in, argp);
+               if (likely(status == 0 && op->process_op != NULL))
+                       status = op->process_op(argp, resp);
+       } else
+               status = htonl(NFS4ERR_RESOURCE);
+
+       res = encode_op_hdr(xdr_out, op_nr, status);
+       if (status == 0)
+               status = res;
+       if (op->encode_res != NULL && status == 0)
+               status = op->encode_res(rqstp, xdr_out, resp);
+       dprintk("%s: done, status = %d\n", __FUNCTION__, status);
+       return status;
+}
+
+/*
+ * Decode, process and encode a COMPOUND
+ */
+static int nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp)
+{
+       struct cb_compound_hdr_arg hdr_arg;
+       struct cb_compound_hdr_res hdr_res;
+       struct xdr_stream xdr_in, xdr_out;
+       uint32_t *p;
+       unsigned int status;
+       unsigned int nops = 1;
+
+       dprintk("%s: start\n", __FUNCTION__);
+
+       xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
+
+       p = (uint32_t*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
+       rqstp->rq_res.head[0].iov_len = PAGE_SIZE;
+       xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
+
+       decode_compound_hdr_arg(&xdr_in, &hdr_arg);
+       hdr_res.taglen = hdr_arg.taglen;
+       hdr_res.tag = hdr_arg.tag;
+       encode_compound_hdr_res(&xdr_out, &hdr_res);
+
+       for (;;) {
+               status = process_op(rqstp, &xdr_in, argp, &xdr_out, resp);
+               if (status != 0)
+                       break;
+               if (nops == hdr_arg.nops)
+                       break;
+               nops++;
+       }
+       *hdr_res.status = status;
+       *hdr_res.nops = htonl(nops);
+       dprintk("%s: done, status = %u\n", __FUNCTION__, status);
+       return rpc_success;
+}
+
+/*
+ * Define NFS4 callback COMPOUND ops.
+ */
+static struct callback_op callback_ops[] = {
+       [0] = {
+               .res_maxsize = CB_OP_HDR_RES_MAXSZ,
+       },
+       [OP_CB_GETATTR] = {
+               .process_op = (callback_process_op_t)nfs4_callback_getattr,
+               .decode_args = (callback_decode_arg_t)decode_getattr_args,
+               .encode_res = (callback_encode_res_t)encode_getattr_res,
+               .res_maxsize = CB_OP_GETATTR_RES_MAXSZ,
+       },
+       [OP_CB_RECALL] = {
+               .process_op = (callback_process_op_t)nfs4_callback_recall,
+               .decode_args = (callback_decode_arg_t)decode_recall_args,
+               .res_maxsize = CB_OP_RECALL_RES_MAXSZ,
+       }
+};
+
+/*
+ * Define NFS4 callback procedures
+ */
+static struct svc_procedure nfs4_callback_procedures1[] = {
+       [CB_NULL] = {
+               .pc_func = nfs4_callback_null,
+               .pc_decode = (kxdrproc_t)nfs4_decode_void,
+               .pc_encode = (kxdrproc_t)nfs4_encode_void,
+               .pc_xdrressize = 1,
+       },
+       [CB_COMPOUND] = {
+               .pc_func = nfs4_callback_compound,
+               .pc_encode = (kxdrproc_t)nfs4_encode_void,
+               .pc_argsize = 256,
+               .pc_ressize = 256,
+               .pc_xdrressize = NFS4_CALLBACK_BUFSIZE,
+       }
+};
+
+struct svc_version nfs4_callback_version1 = {
+       .vs_vers = 1,
+       .vs_nproc = ARRAY_SIZE(nfs4_callback_procedures1),
+       .vs_proc = nfs4_callback_procedures1,
+       .vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
+       .vs_dispatch = NULL,
+};
+
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
new file mode 100644 (file)
index 0000000..5b9c60f
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * linux/fs/nfs/delegation.c
+ *
+ * Copyright (C) 2004 Trond Myklebust
+ *
+ * NFS file delegation management
+ *
+ */
+#include <linux/config.h>
+#include <linux/completion.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#include <linux/nfs4.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_xdr.h>
+
+#include "delegation.h"
+
+static struct nfs_delegation *nfs_alloc_delegation(void)
+{
+       return (struct nfs_delegation *)kmalloc(sizeof(struct nfs_delegation), GFP_KERNEL);
+}
+
+static void nfs_free_delegation(struct nfs_delegation *delegation)
+{
+       if (delegation->cred)
+               put_rpccred(delegation->cred);
+       kfree(delegation);
+}
+
+static void nfs_delegation_claim_opens(struct inode *inode)
+{
+       struct nfs_inode *nfsi = NFS_I(inode);
+       struct nfs_open_context *ctx;
+       struct nfs4_state *state;
+
+again:
+       spin_lock(&inode->i_lock);
+       list_for_each_entry(ctx, &nfsi->open_files, list) {
+               state = ctx->state;
+               if (state == NULL)
+                       continue;
+               if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
+                       continue;
+               get_nfs_open_context(ctx);
+               spin_unlock(&inode->i_lock);
+               if (nfs4_open_delegation_recall(ctx->dentry, state) < 0)
+                       return;
+               put_nfs_open_context(ctx);
+               goto again;
+       }
+       spin_unlock(&inode->i_lock);
+}
+
+/*
+ * Set up a delegation on an inode
+ */
+void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
+{
+       struct nfs_delegation *delegation = NFS_I(inode)->delegation;
+
+       if (delegation == NULL)
+               return;
+       memcpy(delegation->stateid.data, res->delegation.data,
+                       sizeof(delegation->stateid.data));
+       delegation->type = res->delegation_type;
+       delegation->maxsize = res->maxsize;
+       put_rpccred(cred);
+       delegation->cred = get_rpccred(cred);
+       delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM;
+       NFS_I(inode)->delegation_state = delegation->type;
+       smp_wmb();
+}
+
+/*
+ * Set up a delegation on an inode
+ */
+int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
+{
+       struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
+       struct nfs_inode *nfsi = NFS_I(inode);
+       struct nfs_delegation *delegation;
+       int status = 0;
+
+       delegation = nfs_alloc_delegation();
+       if (delegation == NULL)
+               return -ENOMEM;
+       memcpy(delegation->stateid.data, res->delegation.data,
+                       sizeof(delegation->stateid.data));
+       delegation->type = res->delegation_type;
+       delegation->maxsize = res->maxsize;
+       delegation->cred = get_rpccred(cred);
+       delegation->inode = inode;
+
+       spin_lock(&clp->cl_lock);
+       if (nfsi->delegation == NULL) {
+               list_add(&delegation->super_list, &clp->cl_delegations);
+               nfsi->delegation = delegation;
+               nfsi->delegation_state = delegation->type;
+               delegation = NULL;
+       } else {
+               if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
+                                       sizeof(delegation->stateid)) != 0 ||
+                               delegation->type != nfsi->delegation->type) {
+                       printk("%s: server %u.%u.%u.%u, handed out a duplicate delegation!\n",
+                                       __FUNCTION__, NIPQUAD(clp->cl_addr));
+                       status = -EIO;
+               }
+       }
+       spin_unlock(&clp->cl_lock);
+       if (delegation != NULL)
+               kfree(delegation);
+       return status;
+}
+
+static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
+{
+       int res = 0;
+
+       __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+
+       res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid);
+       nfs_free_delegation(delegation);
+       return res;
+}
+
+/* Sync all data to disk upon delegation return */
+static void nfs_msync_inode(struct inode *inode)
+{
+       filemap_fdatawrite(inode->i_mapping);
+       nfs_wb_all(inode);
+       filemap_fdatawait(inode->i_mapping);
+}
+
+/*
+ * Basic procedure for returning a delegation to the server
+ */
+int nfs_inode_return_delegation(struct inode *inode)
+{
+       struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
+       struct nfs_inode *nfsi = NFS_I(inode);
+       struct nfs_delegation *delegation;
+       int res = 0;
+
+       nfs_msync_inode(inode);
+       down_read(&clp->cl_sem);
+       /* Guard against new delegated open calls */
+       down_write(&nfsi->rwsem);
+       spin_lock(&clp->cl_lock);
+       delegation = nfsi->delegation;
+       if (delegation != NULL) {
+               list_del_init(&delegation->super_list);
+               nfsi->delegation = NULL;
+               nfsi->delegation_state = 0;
+       }
+       spin_unlock(&clp->cl_lock);
+       nfs_delegation_claim_opens(inode);
+       up_write(&nfsi->rwsem);
+       up_read(&clp->cl_sem);
+       nfs_msync_inode(inode);
+
+       if (delegation != NULL)
+               res = nfs_do_return_delegation(inode, delegation);
+       return res;
+}
+
+/*
+ * Return all delegations associated to a super block
+ */
+void nfs_return_all_delegations(struct super_block *sb)
+{
+       struct nfs4_client *clp = NFS_SB(sb)->nfs4_state;
+       struct nfs_delegation *delegation;
+       struct inode *inode;
+
+       if (clp == NULL)
+               return;
+restart:
+       spin_lock(&clp->cl_lock);
+       list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+               if (delegation->inode->i_sb != sb)
+                       continue;
+               inode = igrab(delegation->inode);
+               if (inode == NULL)
+                       continue;
+               spin_unlock(&clp->cl_lock);
+               nfs_inode_return_delegation(inode);
+               iput(inode);
+               goto restart;
+       }
+       spin_unlock(&clp->cl_lock);
+}
+
+/*
+ * Return all delegations following an NFS4ERR_CB_PATH_DOWN error.
+ */
+void nfs_handle_cb_pathdown(struct nfs4_client *clp)
+{
+       struct nfs_delegation *delegation;
+       struct inode *inode;
+
+       if (clp == NULL)
+               return;
+restart:
+       spin_lock(&clp->cl_lock);
+       list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+               inode = igrab(delegation->inode);
+               if (inode == NULL)
+                       continue;
+               spin_unlock(&clp->cl_lock);
+               nfs_inode_return_delegation(inode);
+               iput(inode);
+               goto restart;
+       }
+       spin_unlock(&clp->cl_lock);
+}
+
+struct recall_threadargs {
+       struct inode *inode;
+       struct nfs4_client *clp;
+       const nfs4_stateid *stateid;
+
+       struct completion started;
+       int result;
+};
+
+static int recall_thread(void *data)
+{
+       struct recall_threadargs *args = (struct recall_threadargs *)data;
+       struct inode *inode = igrab(args->inode);
+       struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
+       struct nfs_inode *nfsi = NFS_I(inode);
+       struct nfs_delegation *delegation;
+
+       daemonize("nfsv4-delegreturn");
+
+       nfs_msync_inode(inode);
+       down_read(&clp->cl_sem);
+       down_write(&nfsi->rwsem);
+       spin_lock(&clp->cl_lock);
+       delegation = nfsi->delegation;
+       if (delegation != NULL && memcmp(delegation->stateid.data,
+                               args->stateid->data,
+                               sizeof(delegation->stateid.data)) == 0) {
+               list_del_init(&delegation->super_list);
+               nfsi->delegation = NULL;
+               nfsi->delegation_state = 0;
+               args->result = 0;
+       } else {
+               delegation = NULL;
+               args->result = -ENOENT;
+       }
+       spin_unlock(&clp->cl_lock);
+       complete(&args->started);
+       nfs_delegation_claim_opens(inode);
+       up_write(&nfsi->rwsem);
+       up_read(&clp->cl_sem);
+       nfs_msync_inode(inode);
+
+       if (delegation != NULL)
+               nfs_do_return_delegation(inode, delegation);
+       iput(inode);
+       module_put_and_exit(0);
+}
+
+/*
+ * Asynchronous delegation recall!
+ */
+int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid)
+{
+       struct recall_threadargs data = {
+               .inode = inode,
+               .stateid = stateid,
+       };
+       int status;
+
+       init_completion(&data.started);
+       __module_get(THIS_MODULE);
+       status = kernel_thread(recall_thread, &data, CLONE_KERNEL);
+       if (status < 0)
+               goto out_module_put;
+       wait_for_completion(&data.started);
+       return data.result;
+out_module_put:
+       module_put(THIS_MODULE);
+       return status;
+}
+
+/*
+ * Retrieve the inode associated with a delegation
+ */
+struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle)
+{
+       struct nfs_delegation *delegation;
+       struct inode *res = NULL;
+       spin_lock(&clp->cl_lock);
+       list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+               if (nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
+                       res = igrab(delegation->inode);
+                       break;
+               }
+       }
+       spin_unlock(&clp->cl_lock);
+       return res;
+}
+
+/*
+ * Mark all delegations as needing to be reclaimed
+ */
+void nfs_delegation_mark_reclaim(struct nfs4_client *clp)
+{
+       struct nfs_delegation *delegation;
+       spin_lock(&clp->cl_lock);
+       list_for_each_entry(delegation, &clp->cl_delegations, super_list)
+               delegation->flags |= NFS_DELEGATION_NEED_RECLAIM;
+       spin_unlock(&clp->cl_lock);
+}
+
+/*
+ * Reap all unclaimed delegations after reboot recovery is done
+ */
+void nfs_delegation_reap_unclaimed(struct nfs4_client *clp)
+{
+       struct nfs_delegation *delegation, *n;
+       LIST_HEAD(head);
+       spin_lock(&clp->cl_lock);
+       list_for_each_entry_safe(delegation, n, &clp->cl_delegations, super_list) {
+               if ((delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0)
+                       continue;
+               list_move(&delegation->super_list, &head);
+               NFS_I(delegation->inode)->delegation = NULL;
+               NFS_I(delegation->inode)->delegation_state = 0;
+       }
+       spin_unlock(&clp->cl_lock);
+       while(!list_empty(&head)) {
+               delegation = list_entry(head.next, struct nfs_delegation, super_list);
+               list_del(&delegation->super_list);
+               nfs_free_delegation(delegation);
+       }
+}
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
new file mode 100644 (file)
index 0000000..3f6c45a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * linux/fs/nfs/delegation.h
+ *
+ * Copyright (c) Trond Myklebust
+ *
+ * Definitions pertaining to NFS delegated files
+ */
+#ifndef FS_NFS_DELEGATION_H
+#define FS_NFS_DELEGATION_H
+
+#if defined(CONFIG_NFS_V4)
+/*
+ * NFSv4 delegation
+ */
+struct nfs_delegation {
+       struct list_head super_list;
+       struct rpc_cred *cred;
+       struct inode *inode;
+       nfs4_stateid stateid;
+       int type;
+#define NFS_DELEGATION_NEED_RECLAIM 1
+       long flags;
+       loff_t maxsize;
+};
+
+int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
+void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
+int nfs_inode_return_delegation(struct inode *inode);
+int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
+
+struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle);
+void nfs_return_all_delegations(struct super_block *sb);
+void nfs_handle_cb_pathdown(struct nfs4_client *clp);
+
+void nfs_delegation_mark_reclaim(struct nfs4_client *clp);
+void nfs_delegation_reap_unclaimed(struct nfs4_client *clp);
+
+/* NFSv4 delegation-related procedures */
+int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
+int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
+
+static inline int nfs_have_delegation(struct inode *inode, int flags)
+{
+       flags &= FMODE_READ|FMODE_WRITE;
+       smp_rmb();
+       if ((NFS_I(inode)->delegation_state & flags) == flags)
+               return 1;
+       return 0;
+}
+#else
+static inline int nfs_have_delegation(struct inode *inode, int flags)
+{
+       return 0;
+}
+#endif
+
+#endif
index a2ddc6c..857e3ea 100644 (file)
@@ -108,7 +108,6 @@ xdr_decode_fhstatus(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res)
 {
        struct nfs_fh *fh = res->fh;
 
-       memset((void *)fh, 0, sizeof(*fh));
        if ((res->status = ntohl(*p++)) == 0) {
                fh->size = NFS2_FHSIZE;
                memcpy(fh->data, p, NFS2_FHSIZE);
@@ -121,7 +120,6 @@ xdr_decode_fhstatus3(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res)
 {
        struct nfs_fh *fh = res->fh;
 
-       memset((void *)fh, 0, sizeof(*fh));
        if ((res->status = ntohl(*p++)) == 0) {
                int size = ntohl(*p++);
                if (size <= NFS3_FHSIZE) {
index a759f5a..6be08f6 100644 (file)
@@ -68,18 +68,6 @@ nfs3_async_handle_jukebox(struct rpc_task *task)
        return 1;
 }
 
-static struct rpc_cred *
-nfs_cred(struct inode *inode, struct file *filp)
-{
-       struct rpc_cred *cred = NULL;
-
-       if (filp)
-               cred = (struct rpc_cred *)filp->private_data;
-       if (!cred)
-               cred = NFS_I(inode)->mm_cred;
-       return cred;
-}
-
 /*
  * Bare-bones access to getattr: this is for nfs_read_super.
  */
@@ -104,14 +92,15 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  * One function for each procedure in the NFS protocol.
  */
 static int
-nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
+nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+               struct nfs_fattr *fattr)
 {
        int     status;
 
        dprintk("NFS call  getattr\n");
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(inode), NFS3PROC_GETATTR,
-                         NFS_FH(inode), fattr, 0);
+       status = rpc_call(server->client, NFS3PROC_GETATTR,
+                         fhandle, fattr, 0);
        dprintk("NFS reply getattr\n");
        return status;
 }
@@ -164,8 +153,7 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name,
        return status;
 }
 
-static int
-nfs3_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
+static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 {
        struct nfs_fattr        fattr;
        struct nfs3_accessargs  arg = {
@@ -178,9 +166,10 @@ nfs3_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
                .rpc_proc       = &nfs3_procedures[NFS3PROC_ACCESS],
                .rpc_argp       = &arg,
                .rpc_resp       = &res,
-               .rpc_cred       = cred
+               .rpc_cred       = entry->cred
        };
-       int     status;
+       int mode = entry->mask;
+       int status;
 
        dprintk("NFS call  access\n");
        fattr.valid = 0;
@@ -200,20 +189,27 @@ nfs3_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
        }
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
        nfs_refresh_inode(inode, &fattr);
-       dprintk("NFS reply access\n");
-
-       if (status == 0 && (arg.access & res.access) != arg.access)
-               status = -EACCES;
+       if (status == 0) {
+               entry->mask = 0;
+               if (res.access & NFS3_ACCESS_READ)
+                       entry->mask |= MAY_READ;
+               if (res.access & (NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE))
+                       entry->mask |= MAY_WRITE;
+               if (res.access & (NFS3_ACCESS_LOOKUP|NFS3_ACCESS_EXECUTE))
+                       entry->mask |= MAY_EXEC;
+       }
+       dprintk("NFS reply access, status = %d\n", status);
        return status;
 }
 
-static int
-nfs3_proc_readlink(struct inode *inode, struct page *page)
+static int nfs3_proc_readlink(struct inode *inode, struct page *page,
+               unsigned int pgbase, unsigned int pglen)
 {
        struct nfs_fattr        fattr;
        struct nfs3_readlinkargs args = {
                .fh             = NFS_FH(inode),
-               .count          = PAGE_CACHE_SIZE,
+               .pgbase         = pgbase,
+               .pglen          = pglen,
                .pages          = &page
        };
        int                     status;
@@ -227,8 +223,7 @@ nfs3_proc_readlink(struct inode *inode, struct page *page)
        return status;
 }
 
-static int
-nfs3_proc_read(struct nfs_read_data *rdata, struct file *filp)
+static int nfs3_proc_read(struct nfs_read_data *rdata)
 {
        int                     flags = rdata->flags;
        struct inode *          inode = rdata->inode;
@@ -237,13 +232,13 @@ nfs3_proc_read(struct nfs_read_data *rdata, struct file *filp)
                .rpc_proc       = &nfs3_procedures[NFS3PROC_READ],
                .rpc_argp       = &rdata->args,
                .rpc_resp       = &rdata->res,
+               .rpc_cred       = rdata->cred,
        };
        int                     status;
 
        dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
                        (long long) rdata->args.offset);
        fattr->valid = 0;
-       msg.rpc_cred = nfs_cred(inode, filp);
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
        if (status >= 0)
                nfs_refresh_inode(inode, fattr);
@@ -251,8 +246,7 @@ nfs3_proc_read(struct nfs_read_data *rdata, struct file *filp)
        return status;
 }
 
-static int
-nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
+static int nfs3_proc_write(struct nfs_write_data *wdata)
 {
        int                     rpcflags = wdata->flags;
        struct inode *          inode = wdata->inode;
@@ -261,13 +255,13 @@ nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
                .rpc_proc       = &nfs3_procedures[NFS3PROC_WRITE],
                .rpc_argp       = &wdata->args,
                .rpc_resp       = &wdata->res,
+               .rpc_cred       = wdata->cred,
        };
        int                     status;
 
        dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
                        (long long) wdata->args.offset);
        fattr->valid = 0;
-       msg.rpc_cred = nfs_cred(inode, filp);
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
        if (status >= 0)
                nfs_refresh_inode(inode, fattr);
@@ -275,8 +269,7 @@ nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
        return status < 0? status : wdata->res.count;
 }
 
-static int
-nfs3_proc_commit(struct nfs_write_data *cdata, struct file *filp)
+static int nfs3_proc_commit(struct nfs_write_data *cdata)
 {
        struct inode *          inode = cdata->inode;
        struct nfs_fattr *      fattr = cdata->res.fattr;
@@ -284,13 +277,13 @@ nfs3_proc_commit(struct nfs_write_data *cdata, struct file *filp)
                .rpc_proc       = &nfs3_procedures[NFS3PROC_COMMIT],
                .rpc_argp       = &cdata->args,
                .rpc_resp       = &cdata->res,
+               .rpc_cred       = cdata->cred,
        };
        int                     status;
 
        dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
                        (long long) cdata->args.offset);
        fattr->valid = 0;
-       msg.rpc_cred = nfs_cred(inode, filp);
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
        if (status >= 0)
                nfs_refresh_inode(inode, fattr);
@@ -425,20 +418,21 @@ nfs3_proc_remove(struct inode *dir, struct qstr *name)
 static int
 nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name)
 {
-       struct nfs3_diropargs   *arg;
-       struct nfs_fattr        *res;
+       struct unlinkxdr {
+               struct nfs3_diropargs arg;
+               struct nfs_fattr res;
+       } *ptr;
 
-       arg = (struct nfs3_diropargs *)kmalloc(sizeof(*arg)+sizeof(*res), GFP_KERNEL);
-       if (!arg)
+       ptr = (struct unlinkxdr *)kmalloc(sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
                return -ENOMEM;
-       res = (struct nfs_fattr*)(arg + 1);
-       arg->fh = NFS_FH(dir->d_inode);
-       arg->name = name->name;
-       arg->len = name->len;
-       res->valid = 0;
+       ptr->arg.fh = NFS_FH(dir->d_inode);
+       ptr->arg.name = name->name;
+       ptr->arg.len = name->len;
+       ptr->res.valid = 0;
        msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
-       msg->rpc_argp = arg;
-       msg->rpc_resp = res;
+       msg->rpc_argp = &ptr->arg;
+       msg->rpc_resp = &ptr->res;
        return 0;
 }
 
@@ -534,6 +528,8 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
        };
        int                     status;
 
+       if (path->len > NFS3_MAXPATHLEN)
+               return -ENAMETOOLONG;
        dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
        dir_attr.valid = 0;
        fattr->valid = 0;
@@ -832,27 +828,6 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
        rpc_call_setup(task, &msg, 0);
 }
 
-/*
- * Set up the nfspage struct with the right credentials
- */
-void
-nfs3_request_init(struct nfs_page *req, struct file *filp)
-{
-       req->wb_cred = get_rpccred(nfs_cred(req->wb_inode, filp));
-}
-
-static int
-nfs3_request_compatible(struct nfs_page *req, struct file *filp, struct page *page)
-{
-       if (req->wb_file != filp)
-               return 0;
-       if (req->wb_page != page)
-               return 0;
-       if (req->wb_cred != nfs_file_cred(filp))
-               return 0;
-       return 1;
-}
-
 static int
 nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
@@ -892,7 +867,5 @@ struct nfs_rpc_ops  nfs_v3_clientops = {
        .commit_setup   = nfs3_proc_commit_setup,
        .file_open      = nfs_open,
        .file_release   = nfs_release,
-       .request_init   = nfs3_request_init,
-       .request_compatible = nfs3_request_compatible,
        .lock           = nfs3_proc_lock,
 };
index c82fc85..4f1ba72 100644 (file)
 
 #define NFS_PARANOIA 1
 
-/*
- * Spinlock
- */
-spinlock_t nfs_wreq_lock = SPIN_LOCK_UNLOCKED;
-
 static kmem_cache_t *nfs_page_cachep;
 
 static inline struct nfs_page *
@@ -36,7 +31,6 @@ nfs_page_alloc(void)
        if (p) {
                memset(p, 0, sizeof(*p));
                INIT_LIST_HEAD(&p->wb_list);
-               init_waitqueue_head(&p->wb_wait);
        }
        return p;
 }
@@ -62,7 +56,7 @@ nfs_page_free(struct nfs_page *p)
  * User should ensure it is safe to sleep in this function.
  */
 struct nfs_page *
-nfs_create_request(struct file *file, struct inode *inode,
+nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
                   struct page *page,
                   unsigned int offset, unsigned int count)
 {
@@ -94,33 +88,38 @@ nfs_create_request(struct file *file, struct inode *inode,
        req->wb_offset  = offset;
        req->wb_pgbase  = offset;
        req->wb_bytes   = count;
-       req->wb_inode   = inode;
-       req->wb_count   = 1;
-       server->rpc_ops->request_init(req, file);
+       atomic_set(&req->wb_count, 1);
+       req->wb_context = get_nfs_open_context(ctx);
 
        return req;
 }
 
+/**
+ * nfs_unlock_request - Unlock request and wake up sleepers.
+ * @req:
+ */
+void nfs_unlock_request(struct nfs_page *req)
+{
+       if (!NFS_WBACK_BUSY(req)) {
+               printk(KERN_ERR "NFS: Invalid unlock attempted\n");
+               BUG();
+       }
+       smp_mb__before_clear_bit();
+       clear_bit(PG_BUSY, &req->wb_flags);
+       smp_mb__after_clear_bit();
+       wake_up_all(&req->wb_context->waitq);
+       nfs_release_request(req);
+}
+
 /**
  * nfs_clear_request - Free up all resources allocated to the request
  * @req:
  *
- * Release all resources associated with a write request after it
+ * Release page resources associated with a write request after it
  * has completed.
  */
 void nfs_clear_request(struct nfs_page *req)
 {
-       if (req->wb_state)
-               req->wb_state = NULL;
-       /* Release struct file or cached credential */
-       if (req->wb_file) {
-               fput(req->wb_file);
-               req->wb_file = NULL;
-       }
-       if (req->wb_cred) {
-               put_rpccred(req->wb_cred);
-               req->wb_cred = NULL;
-       }
        if (req->wb_page) {
                page_cache_release(req->wb_page);
                req->wb_page = NULL;
@@ -137,12 +136,8 @@ void nfs_clear_request(struct nfs_page *req)
 void
 nfs_release_request(struct nfs_page *req)
 {
-       spin_lock(&nfs_wreq_lock);
-       if (--req->wb_count) {
-               spin_unlock(&nfs_wreq_lock);
+       if (!atomic_dec_and_test(&req->wb_count))
                return;
-       }
-       spin_unlock(&nfs_wreq_lock);
 
 #ifdef NFS_PARANOIA
        BUG_ON (!list_empty(&req->wb_list));
@@ -151,6 +146,7 @@ nfs_release_request(struct nfs_page *req)
 
        /* Release struct file or cached credential */
        nfs_clear_request(req);
+       put_nfs_open_context(req->wb_context);
        nfs_page_free(req);
 }
 
@@ -194,12 +190,12 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head)
 int
 nfs_wait_on_request(struct nfs_page *req)
 {
-       struct inode    *inode = req->wb_inode;
+       struct inode    *inode = req->wb_context->dentry->d_inode;
         struct rpc_clnt        *clnt = NFS_CLIENT(inode);
 
        if (!NFS_WBACK_BUSY(req))
                return 0;
-       return nfs_wait_event(clnt, req->wb_wait, !NFS_WBACK_BUSY(req));
+       return nfs_wait_event(clnt, req->wb_context->waitq, !NFS_WBACK_BUSY(req));
 }
 
 /**
@@ -224,7 +220,11 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
 
                req = nfs_list_entry(head->next);
                if (prev) {
-                       if (req->wb_cred != prev->wb_cred)
+                       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;
@@ -254,7 +254,7 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
  * 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 nfs_wreq_lock when calling this function
+ * You must be holding the inode's req_lock when calling this function
  */
 int
 nfs_scan_list(struct list_head *head, struct list_head *dst,
index 4c47c00..87d4cc2 100644 (file)
@@ -7,5 +7,6 @@ obj-$(CONFIG_NFSD)      += nfsd.o
 nfsd-y                         := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
                           export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o
 nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o
-nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o
+nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
+                          nfs4acl.o
 nfsd-objs              := $(nfsd-y)
index 479835b..3397bec 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/types.h>
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/mount.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
@@ -22,7 +23,7 @@
  * Note: we hold the dentry use count while the file is open.
  */
 static u32
-nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
+nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
 {
        u32             nfserr;
        struct svc_fh   fh;
@@ -35,10 +36,6 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
 
        exp_readlock();
        nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
-       if (!nfserr) {
-               dget(filp->f_dentry);
-               mntget(filp->f_vfsmnt);
-       }
        fh_put(&fh);
        rqstp->rq_client = NULL;
        exp_readunlock();
@@ -60,9 +57,7 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
 static void
 nlm_fclose(struct file *filp)
 {
-       nfsd_close(filp);
-       dput(filp->f_dentry);
-       mntput(filp->f_vfsmnt);
+       fput(filp);
 }
 
 struct nlmsvc_binding          nfsd_nlm_ops = {
index 941ceae..effcd19 100644 (file)
@@ -492,8 +492,16 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
                count += PAGE_SIZE;
        }
        resp->count = count >> 2;
-       if (resp->offset)
-               xdr_encode_hyper(resp->offset, offset);
+       if (resp->offset) {
+               if (unlikely(resp->offset1)) {
+                       /* we ended up with offset on a page boundary */
+                       *resp->offset = htonl(offset >> 32);
+                       *resp->offset1 = htonl(offset & 0xffffffff);
+                       resp->offset1 = NULL;
+               } else {
+                       xdr_encode_hyper(resp->offset, offset);
+               }
+       }
 
        RETURN_STATUS(nfserr);
 }
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
new file mode 100644 (file)
index 0000000..1723939
--- /dev/null
@@ -0,0 +1,974 @@
+/*
+ *  fs/nfs4acl/acl.c
+ *
+ *  Common NFSv4 ACL handling code.
+ *
+ *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Marius Aamodt Eriksen <marius@umich.edu>
+ *  Jeff Sedlak <jsedlak@umich.edu>
+ *  J. Bruce Fields <bfields@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/nfs_fs.h>
+#include <linux/posix_acl.h>
+#include <linux/nfs4.h>
+#include <linux/nfs4_acl.h>
+
+
+/* mode bit translations: */
+#define NFS4_READ_MODE (NFS4_ACE_READ_DATA | NFS4_ACE_READ_NAMED_ATTRS)
+#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_WRITE_NAMED_ATTRS | NFS4_ACE_APPEND_DATA)
+#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
+#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | NFS4_ACE_SYNCHRONIZE)
+#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
+
+/* flags used to simulate posix default ACLs */
+#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
+               | NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE)
+
+#define MASK_EQUAL(mask1, mask2) \
+       ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) )
+
+static u32
+mask_from_posix(unsigned short perm, unsigned int flags)
+{
+       int mask = NFS4_ANYONE_MODE;
+
+       if (flags & NFS4_ACL_OWNER)
+               mask |= NFS4_OWNER_MODE;
+       if (perm & ACL_READ)
+               mask |= NFS4_READ_MODE;
+       if (perm & ACL_WRITE)
+               mask |= NFS4_WRITE_MODE;
+       if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
+               mask |= NFS4_ACE_DELETE_CHILD;
+       if (perm & ACL_EXECUTE)
+               mask |= NFS4_EXECUTE_MODE;
+       return mask;
+}
+
+static u32
+deny_mask(u32 allow_mask, unsigned int flags)
+{
+       u32 ret = ~allow_mask & ~NFS4_ACE_DELETE;
+       if (!(flags & NFS4_ACL_DIR))
+               ret &= ~NFS4_ACE_DELETE_CHILD;
+       return ret;
+}
+
+static int
+mode_from_nfs4(u32 perm, unsigned short *mode, unsigned int flags)
+{
+       u32 ignore = 0;
+
+       if (!(flags & NFS4_ACL_DIR))
+               ignore |= NFS4_ACE_DELETE_CHILD; /* ignore it */
+       perm |= ignore;
+       *mode = 0;
+       if ((perm & NFS4_READ_MODE) == NFS4_READ_MODE)
+               *mode |= ACL_READ;
+       if ((perm & NFS4_WRITE_MODE) == NFS4_WRITE_MODE)
+               *mode |= ACL_WRITE;
+       if ((perm & NFS4_EXECUTE_MODE) == NFS4_EXECUTE_MODE)
+               *mode |= ACL_EXECUTE;
+       if (!MASK_EQUAL(perm, ignore|mask_from_posix(*mode, flags)))
+               return -EINVAL;
+       return 0;
+}
+
+struct ace_container {
+       struct nfs4_ace  *ace;
+       struct list_head  ace_l;
+};
+
+static short ace2type(struct nfs4_ace *);
+static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
+static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
+int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
+int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
+
+struct nfs4_acl *
+nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
+                       unsigned int flags)
+{
+       struct nfs4_acl *acl;
+       int error = -EINVAL;
+
+       if ((pacl != NULL &&
+               (posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) ||
+           (dpacl != NULL &&
+               (posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0)))
+               goto out_err;
+
+       acl = nfs4_acl_new();
+       if (acl == NULL) {
+               error = -ENOMEM;
+               goto out_err;
+       }
+
+       if (pacl != NULL) {
+               error = _posix_to_nfsv4_one(pacl, acl,
+                                               flags & ~NFS4_ACL_TYPE_DEFAULT);
+               if (error < 0)
+                       goto out_acl;
+       }
+
+       if (dpacl != NULL) {
+               error = _posix_to_nfsv4_one(dpacl, acl,
+                                               flags | NFS4_ACL_TYPE_DEFAULT);
+               if (error < 0)
+                       goto out_acl;
+       }
+
+       return acl;
+
+out_acl:
+       nfs4_acl_free(acl);
+out_err:
+       acl = ERR_PTR(error);
+
+       return acl;
+}
+
+static int
+nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype,
+               uid_t owner, unsigned int flags)
+{
+       int error;
+
+       error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+                                eflag, mask, whotype, owner);
+       if (error < 0)
+               return error;
+       error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+                               eflag, deny_mask(mask, flags), whotype, owner);
+       return error;
+}
+
+/* We assume the acl has been verified with posix_acl_valid. */
+static int
+_posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+                                               unsigned int flags)
+{
+       struct posix_acl_entry *pa, *pe, *group_owner_entry;
+       int error = -EINVAL;
+       u32 mask, mask_mask;
+       int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
+                                       NFS4_INHERITANCE_FLAGS : 0);
+
+       BUG_ON(pacl->a_count < 3);
+       pe = pacl->a_entries + pacl->a_count;
+       pa = pe - 2; /* if mask entry exists, it's second from the last. */
+       if (pa->e_tag == ACL_MASK)
+               mask_mask = deny_mask(mask_from_posix(pa->e_perm, flags), flags);
+       else
+               mask_mask = 0;
+
+       pa = pacl->a_entries;
+       BUG_ON(pa->e_tag != ACL_USER_OBJ);
+       mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
+       error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
+       if (error < 0)
+               goto out;
+       pa++;
+
+       while (pa->e_tag == ACL_USER) {
+               mask = mask_from_posix(pa->e_perm, flags);
+               error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+                               eflag,  mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id);
+               if (error < 0)
+                       goto out;
+
+
+               error = nfs4_acl_add_pair(acl, eflag, mask,
+                               NFS4_ACL_WHO_NAMED, pa->e_id, flags);
+               if (error < 0)
+                       goto out;
+               pa++;
+       }
+
+       /* In the case of groups, we apply allow ACEs first, then deny ACEs,
+        * since a user can be in more than one group.  */
+
+       /* allow ACEs */
+
+       if (pacl->a_count > 3) {
+               BUG_ON(pa->e_tag != ACL_GROUP_OBJ);
+               error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+                               NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
+                               NFS4_ACL_WHO_GROUP, 0);
+               if (error < 0)
+                       goto out;
+       }
+       group_owner_entry = pa;
+       mask = mask_from_posix(pa->e_perm, flags);
+       error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+                       NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
+                       NFS4_ACL_WHO_GROUP, 0);
+       if (error < 0)
+               goto out;
+       pa++;
+
+       while (pa->e_tag == ACL_GROUP) {
+               mask = mask_from_posix(pa->e_perm, flags);
+               error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+                               NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
+                               NFS4_ACL_WHO_NAMED, pa->e_id);
+               if (error < 0)
+                       goto out;
+
+               error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+                               NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
+                               NFS4_ACL_WHO_NAMED, pa->e_id);
+               if (error < 0)
+                       goto out;
+               pa++;
+       }
+
+       /* deny ACEs */
+
+       pa = group_owner_entry;
+       mask = mask_from_posix(pa->e_perm, flags);
+       error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+                       NFS4_ACE_IDENTIFIER_GROUP | eflag,
+                       deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0);
+       if (error < 0)
+               goto out;
+       pa++;
+       while (pa->e_tag == ACL_GROUP) {
+               mask = mask_from_posix(pa->e_perm, flags);
+               error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+                               NFS4_ACE_IDENTIFIER_GROUP | eflag,
+                               deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id);
+               if (error < 0)
+                       goto out;
+               pa++;
+       }
+
+       if (pa->e_tag == ACL_MASK)
+               pa++;
+       BUG_ON(pa->e_tag != ACL_OTHER);
+       mask = mask_from_posix(pa->e_perm, flags);
+       error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
+
+out:
+       return error;
+}
+
+static void
+sort_pacl_range(struct posix_acl *pacl, int start, int end) {
+       int sorted = 0, i;
+       struct posix_acl_entry tmp;
+
+       /* We just do a bubble sort; easy to do in place, and we're not
+        * expecting acl's to be long enough to justify anything more. */
+       while (!sorted) {
+               sorted = 1;
+               for (i = start; i < end; i++) {
+                       if (pacl->a_entries[i].e_id
+                                       > pacl->a_entries[i+1].e_id) {
+                               sorted = 0;
+                               tmp = pacl->a_entries[i];
+                               pacl->a_entries[i] = pacl->a_entries[i+1];
+                               pacl->a_entries[i+1] = tmp;
+                       }
+               }
+       }
+}
+
+static void
+sort_pacl(struct posix_acl *pacl)
+{
+       /* posix_acl_valid requires that users and groups be in order
+        * by uid/gid. */
+       int i, j;
+
+       if (pacl->a_count <= 4)
+               return; /* no users or groups */
+       i = 1;
+       while (pacl->a_entries[i].e_tag == ACL_USER)
+               i++;
+       sort_pacl_range(pacl, 1, i-1);
+
+       BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
+       j = i++;
+       while (pacl->a_entries[j].e_tag == ACL_GROUP)
+               j++;
+       sort_pacl_range(pacl, i, j-1);
+       return;
+}
+
+static int
+write_pace(struct nfs4_ace *ace, struct posix_acl *pacl,
+               struct posix_acl_entry **pace, short tag, unsigned int flags)
+{
+       struct posix_acl_entry *this = *pace;
+
+       if (*pace == pacl->a_entries + pacl->a_count)
+               return -EINVAL; /* fell off the end */
+       (*pace)++;
+       this->e_tag = tag;
+       if (tag == ACL_USER_OBJ)
+               flags |= NFS4_ACL_OWNER;
+       if (mode_from_nfs4(ace->access_mask, &this->e_perm, flags))
+               return -EINVAL;
+       this->e_id = (tag == ACL_USER || tag == ACL_GROUP ?
+                       ace->who : ACL_UNDEFINED_ID);
+       return 0;
+}
+
+static struct nfs4_ace *
+get_next_v4_ace(struct list_head **p, struct list_head *head)
+{
+       struct nfs4_ace *ace;
+
+       *p = (*p)->next;
+       if (*p == head)
+               return NULL;
+       ace = list_entry(*p, struct nfs4_ace, l_ace);
+
+       return ace;
+}
+
+int
+nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
+               struct posix_acl **dpacl, unsigned int flags)
+{
+       struct nfs4_acl *dacl;
+       int error = -ENOMEM;
+
+       *pacl = NULL;
+       *dpacl = NULL;
+
+       dacl = nfs4_acl_new();
+       if (dacl == NULL)
+               goto out;
+
+       error = nfs4_acl_split(acl, dacl);
+       if (error < 0)
+               goto out_acl;
+
+       if (pacl != NULL) {
+               if (acl->naces == 0) {
+                       error = -ENODATA;
+                       goto try_dpacl;
+               }
+
+               *pacl = _nfsv4_to_posix_one(acl, flags);
+               if (IS_ERR(*pacl)) {
+                       error = PTR_ERR(*pacl);
+                       *pacl = NULL;
+                       goto out_acl;
+               }
+       }
+
+try_dpacl:
+       if (dpacl != NULL) {
+               if (dacl->naces == 0) {
+                       if (pacl == NULL || *pacl == NULL)
+                               error = -ENODATA;
+                       goto out_acl;
+               }
+
+               error = 0;
+               *dpacl = _nfsv4_to_posix_one(dacl, flags);
+               if (IS_ERR(*dpacl)) {
+                       error = PTR_ERR(*dpacl);
+                       *dpacl = NULL;
+                       goto out_acl;
+               }
+       }
+
+out_acl:
+       if (error && pacl) {
+               posix_acl_release(*pacl);
+               *pacl = NULL;
+       }
+       nfs4_acl_free(dacl);
+out:
+       return error;
+}
+
+static int
+same_who(struct nfs4_ace *a, struct nfs4_ace *b)
+{
+       return a->whotype == b->whotype &&
+               (a->whotype != NFS4_ACL_WHO_NAMED || a->who == b->who);
+}
+
+static int
+complementary_ace_pair(struct nfs4_ace *allow, struct nfs4_ace *deny,
+               unsigned int flags)
+{
+       int ignore = 0;
+       if (!(flags & NFS4_ACL_DIR))
+               ignore |= NFS4_ACE_DELETE_CHILD;
+       return MASK_EQUAL(ignore|deny_mask(allow->access_mask, flags),
+                         ignore|deny->access_mask) &&
+               allow->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
+               deny->type == NFS4_ACE_ACCESS_DENIED_ACE_TYPE &&
+               allow->flag == deny->flag &&
+               same_who(allow, deny);
+}
+
+static inline int
+user_obj_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
+               struct posix_acl *pacl, struct posix_acl_entry **pace,
+               unsigned int flags)
+{
+       int error = -EINVAL;
+       struct nfs4_ace *ace, *ace2;
+
+       ace = get_next_v4_ace(p, &n4acl->ace_head);
+       if (ace == NULL)
+               goto out;
+       if (ace2type(ace) != ACL_USER_OBJ)
+               goto out;
+       error = write_pace(ace, pacl, pace, ACL_USER_OBJ, flags);
+       if (error < 0)
+               goto out;
+       error = -EINVAL;
+       ace2 = get_next_v4_ace(p, &n4acl->ace_head);
+       if (ace2 == NULL)
+               goto out;
+       if (!complementary_ace_pair(ace, ace2, flags))
+               goto out;
+       error = 0;
+out:
+       return error;
+}
+
+static inline int
+users_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
+               struct nfs4_ace **mask_ace,
+               struct posix_acl *pacl, struct posix_acl_entry **pace,
+               unsigned int flags)
+{
+       int error = -EINVAL;
+       struct nfs4_ace *ace, *ace2;
+
+       ace = get_next_v4_ace(p, &n4acl->ace_head);
+       if (ace == NULL)
+               goto out;
+       while (ace2type(ace) == ACL_USER) {
+               if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
+                       goto out;
+               if (*mask_ace &&
+                       !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
+                       goto out;
+               *mask_ace = ace;
+               ace = get_next_v4_ace(p, &n4acl->ace_head);
+               if (ace == NULL)
+                       goto out;
+               if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
+                       goto out;
+               error = write_pace(ace, pacl, pace, ACL_USER, flags);
+               if (error < 0)
+                       goto out;
+               error = -EINVAL;
+               ace2 = get_next_v4_ace(p, &n4acl->ace_head);
+               if (ace2 == NULL)
+                       goto out;
+               if (!complementary_ace_pair(ace, ace2, flags))
+                       goto out;
+               if ((*mask_ace)->flag != ace2->flag ||
+                               !same_who(*mask_ace, ace2))
+                       goto out;
+               ace = get_next_v4_ace(p, &n4acl->ace_head);
+               if (ace == NULL)
+                       goto out;
+       }
+       error = 0;
+out:
+       return error;
+}
+
+static inline int
+group_obj_and_groups_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
+               struct nfs4_ace **mask_ace,
+               struct posix_acl *pacl, struct posix_acl_entry **pace,
+               unsigned int flags)
+{
+       int error = -EINVAL;
+       struct nfs4_ace *ace, *ace2;
+       struct ace_container *ac;
+       struct list_head group_l;
+
+       INIT_LIST_HEAD(&group_l);
+       ace = list_entry(*p, struct nfs4_ace, l_ace);
+
+       /* group owner (mask and allow aces) */
+
+       if (pacl->a_count != 3) {
+               /* then the group owner should be preceded by mask */
+               if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
+                       goto out;
+               if (*mask_ace &&
+                       !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
+                       goto out;
+               *mask_ace = ace;
+               ace = get_next_v4_ace(p, &n4acl->ace_head);
+               if (ace == NULL)
+                       goto out;
+
+               if ((*mask_ace)->flag != ace->flag || !same_who(*mask_ace, ace))
+                       goto out;
+       }
+
+       if (ace2type(ace) != ACL_GROUP_OBJ)
+               goto out;
+
+       ac = kmalloc(sizeof(*ac), GFP_KERNEL);
+       error = -ENOMEM;
+       if (ac == NULL)
+               goto out;
+       ac->ace = ace;
+       list_add_tail(&ac->ace_l, &group_l);
+
+       error = -EINVAL;
+       if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
+               goto out;
+
+       error = write_pace(ace, pacl, pace, ACL_GROUP_OBJ, flags);
+       if (error < 0)
+               goto out;
+
+       error = -EINVAL;
+       ace = get_next_v4_ace(p, &n4acl->ace_head);
+       if (ace == NULL)
+               goto out;
+
+       /* groups (mask and allow aces) */
+
+       while (ace2type(ace) == ACL_GROUP) {
+               if (*mask_ace == NULL)
+                       goto out;
+
+               if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE ||
+                       !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
+                       goto out;
+               *mask_ace = ace;
+
+               ace = get_next_v4_ace(p, &n4acl->ace_head);
+               if (ace == NULL)
+                       goto out;
+               ac = kmalloc(sizeof(*ac), GFP_KERNEL);
+               error = -ENOMEM;
+               if (ac == NULL)
+                       goto out;
+               error = -EINVAL;
+               if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE ||
+                               !same_who(ace, *mask_ace))
+                       goto out;
+
+               ac->ace = ace;
+               list_add_tail(&ac->ace_l, &group_l);
+
+               error = write_pace(ace, pacl, pace, ACL_GROUP, flags);
+               if (error < 0)
+                       goto out;
+               error = -EINVAL;
+               ace = get_next_v4_ace(p, &n4acl->ace_head);
+               if (ace == NULL)
+                       goto out;
+       }
+
+       /* group owner (deny ace) */
+
+       if (ace2type(ace) != ACL_GROUP_OBJ)
+               goto out;
+       ac = list_entry(group_l.next, struct ace_container, ace_l);
+       ace2 = ac->ace;
+       if (!complementary_ace_pair(ace2, ace, flags))
+               goto out;
+       list_del(group_l.next);
+       kfree(ac);
+
+       /* groups (deny aces) */
+
+       while (!list_empty(&group_l)) {
+               ace = get_next_v4_ace(p, &n4acl->ace_head);
+               if (ace == NULL)
+                       goto out;
+               if (ace2type(ace) != ACL_GROUP)
+                       goto out;
+               ac = list_entry(group_l.next, struct ace_container, ace_l);
+               ace2 = ac->ace;
+               if (!complementary_ace_pair(ace2, ace, flags))
+                       goto out;
+               list_del(group_l.next);
+               kfree(ac);
+       }
+
+       ace = get_next_v4_ace(p, &n4acl->ace_head);
+       if (ace == NULL)
+               goto out;
+       if (ace2type(ace) != ACL_OTHER)
+               goto out;
+       error = 0;
+out:
+       while (!list_empty(&group_l)) {
+               ac = list_entry(group_l.next, struct ace_container, ace_l);
+               list_del(group_l.next);
+               kfree(ac);
+       }
+       return error;
+}
+
+static inline int
+mask_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
+               struct nfs4_ace **mask_ace,
+               struct posix_acl *pacl, struct posix_acl_entry **pace,
+               unsigned int flags)
+{
+       int error = -EINVAL;
+       struct nfs4_ace *ace;
+
+       ace = list_entry(*p, struct nfs4_ace, l_ace);
+       if (pacl->a_count != 3) {
+               if (*mask_ace == NULL)
+                       goto out;
+               (*mask_ace)->access_mask = deny_mask((*mask_ace)->access_mask, flags);
+               write_pace(*mask_ace, pacl, pace, ACL_MASK, flags);
+       }
+       error = 0;
+out:
+       return error;
+}
+
+static inline int
+other_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
+               struct posix_acl *pacl, struct posix_acl_entry **pace,
+               unsigned int flags)
+{
+       int error = -EINVAL;
+       struct nfs4_ace *ace, *ace2;
+
+       ace = list_entry(*p, struct nfs4_ace, l_ace);
+       if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
+               goto out;
+       error = write_pace(ace, pacl, pace, ACL_OTHER, flags);
+       if (error < 0)
+               goto out;
+       error = -EINVAL;
+       ace2 = get_next_v4_ace(p, &n4acl->ace_head);
+       if (ace2 == NULL)
+               goto out;
+       if (!complementary_ace_pair(ace, ace2, flags))
+               goto out;
+       error = 0;
+out:
+       return error;
+}
+
+static int
+calculate_posix_ace_count(struct nfs4_acl *n4acl)
+{
+       if (n4acl->naces == 6) /* owner, owner group, and other only */
+               return 3;
+       else { /* Otherwise there must be a mask entry. */
+               /* Also, the remaining entries are for named users and
+                * groups, and come in threes (mask, allow, deny): */
+               if (n4acl->naces < 7)
+                       return -1;
+               if ((n4acl->naces - 7) % 3)
+                       return -1;
+               return 4 + (n4acl->naces - 7)/3;
+       }
+}
+
+
+static struct posix_acl *
+_nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags)
+{
+       struct posix_acl *pacl;
+       int error = -EINVAL, nace = 0;
+       struct list_head *p;
+       struct nfs4_ace *mask_ace = NULL;
+       struct posix_acl_entry *pace;
+
+       nace = calculate_posix_ace_count(n4acl);
+       if (nace < 0)
+               goto out_err;
+
+       pacl = posix_acl_alloc(nace, GFP_KERNEL);
+       error = -ENOMEM;
+       if (pacl == NULL)
+               goto out_err;
+
+       pace = &pacl->a_entries[0];
+       p = &n4acl->ace_head;
+
+       error = user_obj_from_v4(n4acl, &p, pacl, &pace, flags);
+       if (error)
+               goto out_acl;
+
+       error = users_from_v4(n4acl, &p, &mask_ace, pacl, &pace, flags);
+       if (error)
+               goto out_acl;
+
+       error = group_obj_and_groups_from_v4(n4acl, &p, &mask_ace, pacl, &pace,
+                                               flags);
+       if (error)
+               goto out_acl;
+
+       error = mask_from_v4(n4acl, &p, &mask_ace, pacl, &pace, flags);
+       if (error)
+               goto out_acl;
+       error = other_from_v4(n4acl, &p, pacl, &pace, flags);
+       if (error)
+               goto out_acl;
+
+       error = -EINVAL;
+       if (p->next != &n4acl->ace_head)
+               goto out_acl;
+       if (pace != pacl->a_entries + pacl->a_count)
+               goto out_acl;
+
+       sort_pacl(pacl);
+
+       return pacl;
+out_acl:
+       posix_acl_release(pacl);
+out_err:
+       pacl = ERR_PTR(error);
+       return pacl;
+}
+
+int
+nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
+{
+       struct list_head *h, *n;
+       struct nfs4_ace *ace;
+       int error = 0;
+
+       list_for_each_safe(h, n, &acl->ace_head) {
+               ace = list_entry(h, struct nfs4_ace, l_ace);
+
+               if ((ace->flag & NFS4_INHERITANCE_FLAGS)
+                               != NFS4_INHERITANCE_FLAGS)
+                       continue;
+
+               error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
+                               ace->access_mask, ace->whotype, ace->who) == -1;
+               if (error < 0)
+                       goto out;
+
+               list_del(h);
+               kfree(ace);
+               acl->naces--;
+       }
+
+out:
+       return error;
+}
+
+static short
+ace2type(struct nfs4_ace *ace)
+{
+       switch (ace->whotype) {
+               case NFS4_ACL_WHO_NAMED:
+                       return (ace->flag & NFS4_ACE_IDENTIFIER_GROUP ?
+                                       ACL_GROUP : ACL_USER);
+               case NFS4_ACL_WHO_OWNER:
+                       return ACL_USER_OBJ;
+               case NFS4_ACL_WHO_GROUP:
+                       return ACL_GROUP_OBJ;
+               case NFS4_ACL_WHO_EVERYONE:
+                       return ACL_OTHER;
+       }
+       BUG();
+       return -1;
+}
+
+EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
+EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
+
+struct nfs4_acl *
+nfs4_acl_new(void)
+{
+       struct nfs4_acl *acl;
+
+       if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL)
+               return NULL;
+
+       acl->naces = 0;
+       INIT_LIST_HEAD(&acl->ace_head);
+
+       return acl;
+}
+
+void
+nfs4_acl_free(struct nfs4_acl *acl)
+{
+       struct list_head *h;
+       struct nfs4_ace *ace;
+
+       if (!acl)
+               return;
+
+       while (!list_empty(&acl->ace_head)) {
+               h = acl->ace_head.next;
+               list_del(h);
+               ace = list_entry(h, struct nfs4_ace, l_ace);
+               kfree(ace);
+       }
+
+       kfree(acl);
+
+       return;
+}
+
+int
+nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
+               int whotype, uid_t who)
+{
+       struct nfs4_ace *ace;
+
+       if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
+               return -1;
+
+       ace->type = type;
+       ace->flag = flag;
+       ace->access_mask = access_mask;
+       ace->whotype = whotype;
+       ace->who = who;
+
+       list_add_tail(&ace->l_ace, &acl->ace_head);
+       acl->naces++;
+
+       return 0;
+}
+
+static struct {
+       char *string;
+       int   stringlen;
+       int type;
+} s2t_map[] = {
+       {
+               .string    = "OWNER@",
+               .stringlen = sizeof("OWNER@") - 1,
+               .type      = NFS4_ACL_WHO_OWNER,
+       },
+       {
+               .string    = "GROUP@",
+               .stringlen = sizeof("GROUP@") - 1,
+               .type      = NFS4_ACL_WHO_GROUP,
+       },
+       {
+               .string    = "EVERYONE@",
+               .stringlen = sizeof("EVERYONE@") - 1,
+               .type      = NFS4_ACL_WHO_EVERYONE,
+       },
+};
+
+int
+nfs4_acl_get_whotype(char *p, u32 len)
+{
+       int i;
+
+       for (i=0; i < sizeof(s2t_map) / sizeof(*s2t_map); i++) {
+               if (s2t_map[i].stringlen == len &&
+                               0 == memcmp(s2t_map[i].string, p, len))
+                       return s2t_map[i].type;
+       }
+       return NFS4_ACL_WHO_NAMED;
+}
+
+int
+nfs4_acl_write_who(int who, char *p)
+{
+       int i;
+
+       for (i=0; i < sizeof(s2t_map) / sizeof(*s2t_map); i++) {
+               if (s2t_map[i].type == who) {
+                       memcpy(p, s2t_map[i].string, s2t_map[i].stringlen);
+                       return s2t_map[i].stringlen;
+               }
+       }
+       BUG();
+       return -1;
+}
+
+static inline int
+match_who(struct nfs4_ace *ace, uid_t owner, gid_t group, uid_t who)
+{
+       switch (ace->whotype) {
+               case NFS4_ACL_WHO_NAMED:
+                       return who == ace->who;
+               case NFS4_ACL_WHO_OWNER:
+                       return who == owner;
+               case NFS4_ACL_WHO_GROUP:
+                       return who == group;
+               case NFS4_ACL_WHO_EVERYONE:
+                       return 1;
+               default:
+                       return 0;
+       }
+}
+
+/* 0 = granted, -EACCES = denied; mask is an nfsv4 mask, not mode bits */
+int
+nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
+                       uid_t who, u32 mask)
+{
+       struct nfs4_ace *ace;
+       u32 allowed = 0;
+
+       list_for_each_entry(ace, &acl->ace_head, l_ace) {
+               if (!match_who(ace, group, owner, who))
+                       continue;
+               switch (ace->type) {
+                       case NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE:
+                               allowed |= ace->access_mask;
+                               if ((allowed & mask) == mask)
+                                       return 0;
+                               break;
+                       case NFS4_ACE_ACCESS_DENIED_ACE_TYPE:
+                               if (ace->access_mask & mask)
+                                       return -EACCES;
+                               break;
+               }
+       }
+       return -EACCES;
+}
+
+EXPORT_SYMBOL(nfs4_acl_new);
+EXPORT_SYMBOL(nfs4_acl_free);
+EXPORT_SYMBOL(nfs4_acl_add_ace);
+EXPORT_SYMBOL(nfs4_acl_get_whotype);
+EXPORT_SYMBOL(nfs4_acl_write_who);
+EXPORT_SYMBOL(nfs4_acl_permission);
index b783620..8a06919 100644 (file)
@@ -328,6 +328,8 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
 
        /* Now call the procedure handler, and encode NFS status. */
        nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
+       if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2)
+               nfserr = nfserr_dropit;
        if (nfserr == nfserr_dropit) {
                dprintk("nfsd: Dropping request due to malloc failure!\n");
                nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
index af796a7..e5d1016 100644 (file)
@@ -1619,6 +1619,33 @@ static wchar_t *page_charset2uni[256] = {
        NULL,   NULL,   c2u_FA, c2u_FB, c2u_FC, NULL,   NULL,   NULL,   
 };
 
+static unsigned char u2c_00hi[256 - 0xA0][2] = {
+       {0x00, 0x00}, {0x00, 0x00}, {0x81, 0x91}, {0x81, 0x92},/* 0xA0-0xA3 */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x81, 0x98},/* 0xA4-0xA7 */
+       {0x81, 0x4E}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xA8-0xAB */
+       {0x81, 0xCA}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xAC-0xAF */
+       {0x81, 0x8B}, {0x81, 0x7D}, {0x00, 0x00}, {0x00, 0x00},/* 0xB0-0xB3 */
+       {0x81, 0x4C}, {0x00, 0x00}, {0x81, 0xF7}, {0x00, 0x00},/* 0xB4-0xB7 */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xB8-0xBB */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xBC-0xBF */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xC0-0xC3 */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xC4-0xC7 */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xC8-0xCB */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xCC-0xCF */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xD0-0xD3 */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x81, 0x7E},/* 0xD4-0xD7 */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xD8-0xDB */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xDC-0xDF */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xE0-0xE3 */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xE4-0xE7 */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xE8-0xEB */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xEC-0xEF */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xF0-0xF3 */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x81, 0x80},/* 0xF4-0xF7 */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xF8-0xFB */
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xFC-0xFF */
+};
+
 static unsigned char u2c_03[512] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
@@ -7708,7 +7735,7 @@ static unsigned char u2c_FF[512] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD4-0xD7 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD8-0xDB */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xDC-0xDF */
-       0x81, 0x91, 0x81, 0x92, 0xEE, 0xF9, 0x81, 0x50, /* 0xE0-0xE3 */
+       0x81, 0x91, 0x81, 0x92, 0x81, 0xCA, 0x81, 0x50, /* 0xE0-0xE3 */
        0xEE, 0xFA, 0x81, 0x8F, 0x00, 0x00, 0x00, 0x00, /* 0xE4-0xE7 */
 };
 
@@ -7842,9 +7869,17 @@ static int uni2char(const wchar_t uni,
                if (out[0] == 0x00 && out[1] == 0x00)
                        return -EINVAL;
                return 2;
-       } else if ((ch == 0) && (cl <= 0x7F)) {
-               out[0] = cl;
-               return 1;
+       } else if (ch == 0) {
+               if (cl <= 0x7F) {
+                       out[0] = cl;
+                       return 1;
+               } else if (0xA0 <= cl) {
+                       out[0] = u2c_00hi[cl - 0xA0][0];
+                       out[1] = u2c_00hi[cl - 0xA0][1];
+                       if (out[0] && out[1])
+                               return 2;
+               }
+               return -EINVAL;
        }
        else
                return -EINVAL;
diff --git a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c
new file mode 100644 (file)
index 0000000..b8f0611
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * bitmap.c - NTFS kernel bitmap handling.  Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file is free software; you can redistribute 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/include file 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 (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef NTFS_RW
+
+#include <linux/pagemap.h>
+
+#include "bitmap.h"
+#include "debug.h"
+#include "ntfs.h"
+
+/**
+ * __ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value
+ * @vi:                        vfs inode describing the bitmap
+ * @start_bit:         first bit to set
+ * @count:             number of bits to set
+ * @value:             value to set the bits to (i.e. 0 or 1)
+ * @is_rollback:       if TRUE this is a rollback operation
+ *
+ * Set @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi to @value, where @value is either 0 or 1.
+ *
+ * @is_rollback should always be FALSE, it is for internal use to rollback
+ * errors.  You probably want to use ntfs_bitmap_set_bits_in_run() instead.
+ *
+ * Return 0 on success and -errno on error.
+ */
+int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
+               const s64 count, const u8 value, const BOOL is_rollback)
+{
+       s64 cnt = count;
+       pgoff_t index, end_index;
+       struct address_space *mapping;
+       struct page *page;
+       u8 *kaddr;
+       int pos, len;
+       u8 bit;
+
+       BUG_ON(!vi);
+       ntfs_debug("Entering for i_ino 0x%lx, start_bit 0x%llx, count 0x%llx, "
+                       "value %u.%s", vi->i_ino, (unsigned long long)start_bit,
+                       (unsigned long long)cnt, (unsigned int)value,
+                       is_rollback ? " (rollback)" : "");
+       BUG_ON(start_bit < 0);
+       BUG_ON(cnt < 0);
+       BUG_ON(value > 1);
+       /*
+        * Calculate the indices for the pages containing the first and last
+        * bits, i.e. @start_bit and @start_bit + @cnt - 1, respectively.
+        */
+       index = start_bit >> (3 + PAGE_CACHE_SHIFT);
+       end_index = (start_bit + cnt - 1) >> (3 + PAGE_CACHE_SHIFT);
+
+       /* Get the page containing the first bit (@start_bit). */
+       mapping = vi->i_mapping;
+       page = ntfs_map_page(mapping, index);
+       if (IS_ERR(page)) {
+               if (!is_rollback)
+                       ntfs_error(vi->i_sb, "Failed to map first page (error "
+                                       "%li), aborting.", PTR_ERR(page));
+               return PTR_ERR(page);
+       }
+       kaddr = page_address(page);
+
+       /* Set @pos to the position of the byte containing @start_bit. */
+       pos = (start_bit >> 3) & ~PAGE_CACHE_MASK;
+
+       /* Calculate the position of @start_bit in the first byte. */
+       bit = start_bit & 7;
+
+       /* If the first byte is partial, modify the appropriate bits in it. */
+       if (bit) {
+               u8 *byte = kaddr + pos;
+               while ((bit & 7) && cnt--) {
+                       if (value)
+                               *byte |= 1 << bit++;
+                       else
+                               *byte &= ~(1 << bit++);
+               }
+               /* If we are done, unmap the page and return success. */
+               if (!cnt)
+                       goto done;
+
+               /* Update @pos to the new position. */
+               pos++;
+       }
+       /*
+        * Depending on @value, modify all remaining whole bytes in the page up
+        * to @cnt.
+        */
+       len = min_t(s64, cnt >> 3, PAGE_CACHE_SIZE - pos);
+       memset(kaddr + pos, value ? 0xff : 0, len);
+       cnt -= len << 3;
+
+       /* Update @len to point to the first not-done byte in the page. */
+       if (cnt < 8)
+               len += pos;
+
+       /* If we are not in the last page, deal with all subsequent pages. */
+       while (index < end_index) {
+               BUG_ON(cnt <= 0);
+
+               /* Update @index and get the next page. */
+               flush_dcache_page(page);
+               set_page_dirty(page);
+               ntfs_unmap_page(page);
+               page = ntfs_map_page(mapping, ++index);
+               if (IS_ERR(page))
+                       goto rollback;
+               kaddr = page_address(page);
+               /*
+                * Depending on @value, modify all remaining whole bytes in the
+                * page up to @cnt.
+                */
+               len = min_t(s64, cnt >> 3, PAGE_CACHE_SIZE);
+               memset(kaddr, value ? 0xff : 0, len);
+               cnt -= len << 3;
+       }
+       /*
+        * The currently mapped page is the last one.  If the last byte is
+        * partial, modify the appropriate bits in it.  Note, @len is the
+        * position of the last byte inside the page.
+        */
+       if (cnt) {
+               u8 *byte;
+
+               BUG_ON(cnt > 7);
+
+               bit = cnt;
+               byte = kaddr + len;
+               while (bit--) {
+                       if (value)
+                               *byte |= 1 << bit;
+                       else
+                               *byte &= ~(1 << bit);
+               }
+       }
+done:
+       /* We are done.  Unmap the page and return success. */
+       flush_dcache_page(page);
+       set_page_dirty(page);
+       ntfs_unmap_page(page);
+       ntfs_debug("Done.");
+       return 0;
+rollback:
+       /*
+        * Current state:
+        *      - no pages are mapped
+        *      - @count - @cnt is the number of bits that have been modified
+        */
+       if (is_rollback)
+               return PTR_ERR(page);
+       if (count != cnt)
+               pos = __ntfs_bitmap_set_bits_in_run(vi, start_bit, count - cnt,
+                               value ? 0 : 1, TRUE);
+       else
+               pos = 0;
+       if (!pos) {
+               /* Rollback was successful. */
+               ntfs_error(vi->i_sb, "Failed to map subsequent page (error "
+                               "%li), aborting.", PTR_ERR(page));
+       } else {
+               /* Rollback failed. */
+               ntfs_error(vi->i_sb, "Failed to map subsequent page (error "
+                               "%li) and rollback failed (error %i).  "
+                               "Aborting and leaving inconsistent metadata.  "
+                               "Unmount and run chkdsk.", PTR_ERR(page), pos);
+               NVolSetErrors(NTFS_SB(vi->i_sb));
+       }
+       return PTR_ERR(page);
+}
+
+#endif /* NTFS_RW */
diff --git a/fs/ntfs/bitmap.h b/fs/ntfs/bitmap.h
new file mode 100644 (file)
index 0000000..bb50d6b
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * bitmap.h - Defines for NTFS kernel bitmap handling.  Part of the Linux-NTFS
+ *           project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file is free software; you can redistribute 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/include file 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 (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LINUX_NTFS_BITMAP_H
+#define _LINUX_NTFS_BITMAP_H
+
+#ifdef NTFS_RW
+
+#include <linux/fs.h>
+
+#include "types.h"
+
+extern int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
+               const s64 count, const u8 value, const BOOL is_rollback);
+
+/**
+ * ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value
+ * @vi:                        vfs inode describing the bitmap
+ * @start_bit:         first bit to set
+ * @count:             number of bits to set
+ * @value:             value to set the bits to (i.e. 0 or 1)
+ *
+ * Set @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi to @value, where @value is either 0 or 1.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_set_bits_in_run(struct inode *vi,
+               const s64 start_bit, const s64 count, const u8 value)
+{
+       return __ntfs_bitmap_set_bits_in_run(vi, start_bit, count, value,
+                       FALSE);
+}
+
+/**
+ * ntfs_bitmap_set_run - set a run of bits in a bitmap
+ * @vi:                vfs inode describing the bitmap
+ * @start_bit: first bit to set
+ * @count:     number of bits to set
+ *
+ * Set @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_set_run(struct inode *vi, const s64 start_bit,
+               const s64 count)
+{
+       return ntfs_bitmap_set_bits_in_run(vi, start_bit, count, 1);
+}
+
+/**
+ * ntfs_bitmap_clear_run - clear a run of bits in a bitmap
+ * @vi:                vfs inode describing the bitmap
+ * @start_bit: first bit to clear
+ * @count:     number of bits to clear
+ *
+ * Clear @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_clear_run(struct inode *vi, const s64 start_bit,
+               const s64 count)
+{
+       return ntfs_bitmap_set_bits_in_run(vi, start_bit, count, 0);
+}
+
+/**
+ * ntfs_bitmap_set_bit - set a bit in a bitmap
+ * @vi:                vfs inode describing the bitmap
+ * @bit:       bit to set
+ *
+ * Set bit @bit in the bitmap described by the vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_set_bit(struct inode *vi, const s64 bit)
+{
+       return ntfs_bitmap_set_run(vi, bit, 1);
+}
+
+/**
+ * ntfs_bitmap_clear_bit - clear a bit in a bitmap
+ * @vi:                vfs inode describing the bitmap
+ * @bit:       bit to clear
+ *
+ * Clear bit @bit in the bitmap described by the vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_clear_bit(struct inode *vi, const s64 bit)
+{
+       return ntfs_bitmap_clear_run(vi, bit, 1);
+}
+
+#endif /* NTFS_RW */
+
+#endif /* defined _LINUX_NTFS_BITMAP_H */
index 14a67a6..e027f36 100644 (file)
@@ -26,7 +26,9 @@
 #include "types.h"
 #include "volume.h"
 
-static inline BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr) {
+static inline BOOL ntfs_is_collation_rule_supported(COLLATION_RULE cr) {
+       int i;
+
        /*
         * FIXME:  At the moment we only support COLLATION_BINARY and
         * COLLATION_NTOFS_ULONG, so we return false for everything else for
@@ -34,14 +36,14 @@ static inline BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr) {
         */
        if (unlikely(cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG))
                return FALSE;
-       cr = le32_to_cpu(cr);
-       if (likely(((cr >= 0) && (cr <= 0x02)) ||
-                       ((cr >= 0x10) && (cr <= 0x13))))
+       i = le32_to_cpu(cr);
+       if (likely(((i >= 0) && (i <= 0x02)) ||
+                       ((i >= 0x10) && (i <= 0x13))))
                return TRUE;
        return FALSE;
 }
 
-extern int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr,
+extern int ntfs_collate(ntfs_volume *vol, COLLATION_RULE cr,
                const void *data1, const int data1_len,
                const void *data2, const int data2_len);
 
index f4396a0..b19a488 100644 (file)
@@ -65,7 +65,7 @@ void ntfs_index_ctx_put(ntfs_index_context *ictx)
        if (ictx->entry) {
                if (ictx->is_in_root) {
                        if (ictx->actx)
-                               put_attr_search_ctx(ictx->actx);
+                               ntfs_attr_put_search_ctx(ictx->actx);
                        if (ictx->base_ni)
                                unmap_mft_record(ictx->base_ni);
                } else {
@@ -125,6 +125,7 @@ void ntfs_index_ctx_put(ntfs_index_context *ictx)
 int ntfs_index_lookup(const void *key, const int key_len,
                ntfs_index_context *ictx)
 {
+       VCN vcn, old_vcn;
        ntfs_inode *idx_ni = ictx->idx_ni;
        ntfs_volume *vol = idx_ni->vol;
        struct super_block *sb = vol->sb;
@@ -133,13 +134,11 @@ int ntfs_index_lookup(const void *key, const int key_len,
        INDEX_ROOT *ir;
        INDEX_ENTRY *ie;
        INDEX_ALLOCATION *ia;
-       u8 *index_end;
-       attr_search_context *actx;
-       int rc, err = 0;
-       VCN vcn, old_vcn;
+       u8 *index_end, *kaddr;
+       ntfs_attr_search_ctx *actx;
        struct address_space *ia_mapping;
        struct page *page;
-       u8 *kaddr;
+       int rc, err = 0;
 
        ntfs_debug("Entering.");
        BUG_ON(!NInoAttr(idx_ni));
@@ -157,22 +156,25 @@ int ntfs_index_lookup(const void *key, const int key_len,
        }
        /* Get hold of the mft record for the index inode. */
        m = map_mft_record(base_ni);
-       if (unlikely(IS_ERR(m))) {
+       if (IS_ERR(m)) {
                ntfs_error(sb, "map_mft_record() failed with error code %ld.",
                                -PTR_ERR(m));
                return PTR_ERR(m);
        }
-       actx = get_attr_search_ctx(base_ni, m);
+       actx = ntfs_attr_get_search_ctx(base_ni, m);
        if (unlikely(!actx)) {
                err = -ENOMEM;
                goto err_out;
        }
        /* Find the index root attribute in the mft record. */
-       if (!lookup_attr(AT_INDEX_ROOT, idx_ni->name, idx_ni->name_len,
-                       CASE_SENSITIVE, 0, NULL, 0, actx)) {
-               ntfs_error(sb, "Index root attribute missing in inode 0x%lx.",
-                               idx_ni->mft_no);
-               err = -EIO;
+       err = ntfs_attr_lookup(AT_INDEX_ROOT, idx_ni->name, idx_ni->name_len,
+                       CASE_SENSITIVE, 0, NULL, 0, actx);
+       if (unlikely(err)) {
+               if (err == -ENOENT) {
+                       ntfs_error(sb, "Index root attribute missing in inode "
+                                       "0x%lx.", idx_ni->mft_no);
+                       err = -EIO;
+               }
                goto err_out;
        }
        /* Get to the index root value (it has been verified in read_inode). */
@@ -263,13 +265,13 @@ done:
                goto err_out;
        }
        /* Get the starting vcn of the index_block holding the child node. */
-       vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+       vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8));
        ia_mapping = VFS_I(idx_ni)->i_mapping;
        /*
         * We are done with the index root and the mft record.  Release them,
         * otherwise we deadlock with ntfs_map_page().
         */
-       put_attr_search_ctx(actx);
+       ntfs_attr_put_search_ctx(actx);
        unmap_mft_record(base_ni);
        m = NULL;
        actx = NULL;
@@ -425,7 +427,7 @@ ia_done:
        }
        /* Child node present, descend into it. */
        old_vcn = vcn;
-       vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+       vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8));
        if (vcn >= 0) {
                /*
                 * If vcn is in the same page cache page as old_vcn we recycle
@@ -448,7 +450,7 @@ unm_err_out:
        ntfs_unmap_page(page);
 err_out:
        if (actx)
-               put_attr_search_ctx(actx);
+               ntfs_attr_put_search_ctx(actx);
        if (m)
                unmap_mft_record(base_ni);
        return err;
index 8ed9436..159442d 100644 (file)
@@ -78,7 +78,7 @@ typedef struct {
        u16 data_len;
        BOOL is_in_root;
        INDEX_ROOT *ir;
-       attr_search_context *actx;
+       ntfs_attr_search_ctx *actx;
        ntfs_inode *base_ni;
        INDEX_ALLOCATION *ia;
        struct page *page;
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
new file mode 100644 (file)
index 0000000..748ed0d
--- /dev/null
@@ -0,0 +1,1001 @@
+/*
+ * lcnalloc.c - Cluster (de)allocation code.  Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file is free software; you can redistribute 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/include file 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 (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef NTFS_RW
+
+#include <linux/pagemap.h>
+
+#include "lcnalloc.h"
+#include "debug.h"
+#include "bitmap.h"
+#include "inode.h"
+#include "volume.h"
+#include "attrib.h"
+#include "malloc.h"
+#include "ntfs.h"
+
+/**
+ * ntfs_cluster_free_from_rl_nolock - free clusters from runlist
+ * @vol:       mounted ntfs volume on which to free the clusters
+ * @rl:                runlist describing the clusters to free
+ *
+ * Free all the clusters described by the runlist @rl on the volume @vol.  In
+ * the case of an error being returned, at least some of the clusters were not
+ * freed.
+ *
+ * Return 0 on success and -errno on error.
+ *
+ * Locking: - The volume lcn bitmap must be locked for writing on entry and is
+ *           left locked on return.
+ */
+static int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
+               const runlist_element *rl)
+{
+       struct inode *lcnbmp_vi = vol->lcnbmp_ino;
+       int ret = 0;
+
+       ntfs_debug("Entering.");
+       for (; rl->length; rl++) {
+               int err;
+
+               if (rl->lcn < 0)
+                       continue;
+               err = ntfs_bitmap_clear_run(lcnbmp_vi, rl->lcn, rl->length);
+               if (unlikely(err && (!ret || ret == ENOMEM) && ret != err))
+                       ret = err;
+       }
+       ntfs_debug("Done.");
+       return ret;
+}
+
+/**
+ * ntfs_cluster_alloc - allocate clusters on an ntfs volume
+ * @vol:       mounted ntfs volume on which to allocate the clusters
+ * @start_vcn: vcn to use for the first allocated cluster
+ * @count:     number of clusters to allocate
+ * @start_lcn: starting lcn at which to allocate the clusters (or -1 if none)
+ * @zone:      zone from which to allocate the clusters
+ *
+ * Allocate @count clusters preferably starting at cluster @start_lcn or at the
+ * current allocator position if @start_lcn is -1, on the mounted ntfs volume
+ * @vol. @zone is either DATA_ZONE for allocation of normal clusters or
+ * MFT_ZONE for allocation of clusters for the master file table, i.e. the
+ * $MFT/$DATA attribute.
+ *
+ * @start_vcn specifies the vcn of the first allocated cluster.  This makes
+ * merging the resulting runlist with the old runlist easier.
+ *
+ * You need to check the return value with IS_ERR().  If this is false, the
+ * function was successful and the return value is a runlist describing the
+ * allocated cluster(s).  If IS_ERR() is true, the function failed and
+ * PTR_ERR() gives you the error code.
+ *
+ * Notes on the allocation algorithm
+ * =================================
+ *
+ * There are two data zones.  First is the area between the end of the mft zone
+ * and the end of the volume, and second is the area between the start of the
+ * volume and the start of the mft zone.  On unmodified/standard NTFS 1.x
+ * volumes, the second data zone does not exist due to the mft zone being
+ * expanded to cover the start of the volume in order to reserve space for the
+ * mft bitmap attribute.
+ *
+ * This is not the prettiest function but the complexity stems from the need of
+ * implementing the mft vs data zoned approach and from the fact that we have
+ * access to the lcn bitmap in portions of up to 8192 bytes at a time, so we
+ * need to cope with crossing over boundaries of two buffers.  Further, the
+ * fact that the allocator allows for caller supplied hints as to the location
+ * of where allocation should begin and the fact that the allocator keeps track
+ * of where in the data zones the next natural allocation should occur,
+ * contribute to the complexity of the function.  But it should all be
+ * worthwhile, because this allocator should: 1) be a full implementation of
+ * the MFT zone approach used by Windows NT, 2) cause reduction in
+ * fragmentation, and 3) be speedy in allocations (the code is not optimized
+ * for speed, but the algorithm is, so further speed improvements are probably
+ * possible).
+ *
+ * FIXME: We should be monitoring cluster allocation and increment the MFT zone
+ * size dynamically but this is something for the future.  We will just cause
+ * heavier fragmentation by not doing it and I am not even sure Windows would
+ * grow the MFT zone dynamically, so it might even be correct not to do this.
+ * The overhead in doing dynamic MFT zone expansion would be very large and
+ * unlikely worth the effort. (AIA)
+ *
+ * TODO: I have added in double the required zone position pointer wrap around
+ * logic which can be optimized to having only one of the two logic sets.
+ * However, having the double logic will work fine, but if we have only one of
+ * the sets and we get it wrong somewhere, then we get into trouble, so
+ * removing the duplicate logic requires _very_ careful consideration of _all_
+ * possible code paths.  So at least for now, I am leaving the double logic -
+ * better safe than sorry... (AIA)
+ *
+ * Locking: - The volume lcn bitmap must be unlocked on entry and is unlocked
+ *           on return.
+ *         - This function takes the volume lcn bitmap lock for writing and
+ *           modifies the bitmap contents.
+ */
+runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
+               const s64 count, const LCN start_lcn,
+               const NTFS_CLUSTER_ALLOCATION_ZONES zone)
+{
+       LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn;
+       LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size;
+       s64 clusters;
+       struct inode *lcnbmp_vi;
+       runlist_element *rl = NULL;
+       struct address_space *mapping;
+       struct page *page = NULL;
+       u8 *buf, *byte;
+       int err = 0, rlpos, rlsize, buf_size;
+       u8 pass, done_zones, search_zone, need_writeback = 0, bit;
+
+       ntfs_debug("Entering for start_vcn 0x%llx, count 0x%llx, start_lcn "
+                       "0x%llx, zone %s_ZONE.", (unsigned long long)start_vcn,
+                       (unsigned long long)count,
+                       (unsigned long long)start_lcn,
+                       zone == MFT_ZONE ? "MFT" : "DATA");
+       BUG_ON(!vol);
+       lcnbmp_vi = vol->lcnbmp_ino;
+       BUG_ON(!lcnbmp_vi);
+       BUG_ON(start_vcn < 0);
+       BUG_ON(count < 0);
+       BUG_ON(start_lcn < -1);
+       BUG_ON(zone < FIRST_ZONE);
+       BUG_ON(zone > LAST_ZONE);
+
+       /* Return empty runlist if @count == 0 */
+       // FIXME: Do we want to just return NULL instead? (AIA)
+       if (!count) {
+               rl = ntfs_malloc_nofs(PAGE_SIZE);
+               if (!rl)
+                       return ERR_PTR(-ENOMEM);
+               rl[0].vcn = start_vcn;
+               rl[0].lcn = LCN_RL_NOT_MAPPED;
+               rl[0].length = 0;
+               return rl;
+       }
+       /* Take the lcnbmp lock for writing. */
+       down_write(&vol->lcnbmp_lock);
+       /*
+        * If no specific @start_lcn was requested, use the current data zone
+        * position, otherwise use the requested @start_lcn but make sure it
+        * lies outside the mft zone.  Also set done_zones to 0 (no zones done)
+        * and pass depending on whether we are starting inside a zone (1) or
+        * at the beginning of a zone (2).  If requesting from the MFT_ZONE,
+        * we either start at the current position within the mft zone or at
+        * the specified position.  If the latter is out of bounds then we start
+        * at the beginning of the MFT_ZONE.
+        */
+       done_zones = 0;
+       pass = 1;
+       /*
+        * zone_start and zone_end are the current search range.  search_zone
+        * is 1 for mft zone, 2 for data zone 1 (end of mft zone till end of
+        * volume) and 4 for data zone 2 (start of volume till start of mft
+        * zone).
+        */
+       zone_start = start_lcn;
+       if (zone_start < 0) {
+               if (zone == DATA_ZONE)
+                       zone_start = vol->data1_zone_pos;
+               else
+                       zone_start = vol->mft_zone_pos;
+               if (!zone_start) {
+                       /*
+                        * Zone starts at beginning of volume which means a
+                        * single pass is sufficient.
+                        */
+                       pass = 2;
+               }
+       } else if (zone == DATA_ZONE && zone_start >= vol->mft_zone_start &&
+                       zone_start < vol->mft_zone_end) {
+               zone_start = vol->mft_zone_end;
+               /*
+                * Starting at beginning of data1_zone which means a single
+                * pass in this zone is sufficient.
+                */
+               pass = 2;
+       } else if (zone == MFT_ZONE && (zone_start < vol->mft_zone_start ||
+                       zone_start >= vol->mft_zone_end)) {
+               zone_start = vol->mft_lcn;
+               if (!vol->mft_zone_end)
+                       zone_start = 0;
+               /*
+                * Starting at beginning of volume which means a single pass
+                * is sufficient.
+                */
+               pass = 2;
+       }
+       if (zone == MFT_ZONE) {
+               zone_end = vol->mft_zone_end;
+               search_zone = 1;
+       } else /* if (zone == DATA_ZONE) */ {
+               /* Skip searching the mft zone. */
+               done_zones |= 1;
+               if (zone_start >= vol->mft_zone_end) {
+                       zone_end = vol->nr_clusters;
+                       search_zone = 2;
+               } else {
+                       zone_end = vol->mft_zone_start;
+                       search_zone = 4;
+               }
+       }
+       /*
+        * bmp_pos is the current bit position inside the bitmap.  We use
+        * bmp_initial_pos to determine whether or not to do a zone switch.
+        */
+       bmp_pos = bmp_initial_pos = zone_start;
+
+       /* Loop until all clusters are allocated, i.e. clusters == 0. */
+       clusters = count;
+       rlpos = rlsize = 0;
+       mapping = lcnbmp_vi->i_mapping;
+       while (1) {
+               ntfs_debug("Start of outer while loop: done_zones 0x%x, "
+                               "search_zone %i, pass %i, zone_start 0x%llx, "
+                               "zone_end 0x%llx, bmp_initial_pos 0x%llx, "
+                               "bmp_pos 0x%llx, rlpos %i, rlsize %i.",
+                               done_zones, search_zone, pass,
+                               (unsigned long long)zone_start,
+                               (unsigned long long)zone_end,
+                               (unsigned long long)bmp_initial_pos,
+                               (unsigned long long)bmp_pos, rlpos, rlsize);
+               /* Loop until we run out of free clusters. */
+               last_read_pos = bmp_pos >> 3;
+               ntfs_debug("last_read_pos 0x%llx.",
+                               (unsigned long long)last_read_pos);
+               if (last_read_pos > lcnbmp_vi->i_size) {
+                       ntfs_debug("End of attribute reached.  "
+                                       "Skipping to zone_pass_done.");
+                       goto zone_pass_done;
+               }
+               if (likely(page)) {
+                       if (need_writeback) {
+                               ntfs_debug("Marking page dirty.");
+                               flush_dcache_page(page);
+                               set_page_dirty(page);
+                               need_writeback = 0;
+                       }
+                       ntfs_unmap_page(page);
+               }
+               page = ntfs_map_page(mapping, last_read_pos >>
+                               PAGE_CACHE_SHIFT);
+               if (IS_ERR(page)) {
+                       err = PTR_ERR(page);
+                       ntfs_error(vol->sb, "Failed to map page.");
+                       goto out;
+               }
+               buf_size = last_read_pos & ~PAGE_CACHE_MASK;
+               buf = page_address(page) + buf_size;
+               buf_size = PAGE_CACHE_SIZE - buf_size;
+               if (unlikely(last_read_pos + buf_size > lcnbmp_vi->i_size))
+                       buf_size = lcnbmp_vi->i_size - last_read_pos;
+               buf_size <<= 3;
+               lcn = bmp_pos & 7;
+               bmp_pos &= ~7;
+               ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, "
+                               "bmp_pos 0x%llx, need_writeback %i.", buf_size,
+                               (unsigned long long)lcn,
+                               (unsigned long long)bmp_pos, need_writeback);
+               while (lcn < buf_size && lcn + bmp_pos < zone_end) {
+                       byte = buf + (lcn >> 3);
+                       ntfs_debug("In inner while loop: buf_size %i, "
+                                       "lcn 0x%llx, bmp_pos 0x%llx, "
+                                       "need_writeback %i, byte ofs 0x%x, "
+                                       "*byte 0x%x.", buf_size,
+                                       (unsigned long long)lcn,
+                                       (unsigned long long)bmp_pos,
+                                       need_writeback,
+                                       (unsigned int)(lcn >> 3),
+                                       (unsigned int)*byte);
+                       /* Skip full bytes. */
+                       if (*byte == 0xff) {
+                               lcn = (lcn + 8) & ~7;
+                               ntfs_debug("Continuing while loop 1.");
+                               continue;
+                       }
+                       bit = 1 << (lcn & 7);
+                       ntfs_debug("bit %i.", bit);
+                       /* If the bit is already set, go onto the next one. */
+                       if (*byte & bit) {
+                               lcn++;
+                               ntfs_debug("Continuing while loop 2.");
+                               continue;
+                       }
+                       /*
+                        * Allocate more memory if needed, including space for
+                        * the terminator element.
+                        * ntfs_malloc_nofs() operates on whole pages only.
+                        */
+                       if ((rlpos + 2) * sizeof(*rl) > rlsize) {
+                               runlist_element *rl2;
+
+                               ntfs_debug("Reallocating memory.");
+                               if (!rl)
+                                       ntfs_debug("First free bit is at LCN "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       (lcn + bmp_pos));
+                               rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE);
+                               if (unlikely(!rl2)) {
+                                       err = -ENOMEM;
+                                       ntfs_error(vol->sb, "Failed to "
+                                                       "allocate memory.");
+                                       goto out;
+                               }
+                               memcpy(rl2, rl, rlsize);
+                               ntfs_free(rl);
+                               rl = rl2;
+                               rlsize += PAGE_SIZE;
+                               ntfs_debug("Reallocated memory, rlsize 0x%x.",
+                                               rlsize);
+                       }
+                       /* Allocate the bitmap bit. */
+                       *byte |= bit;
+                       /* We need to write this bitmap page to disk. */
+                       need_writeback = 1;
+                       ntfs_debug("*byte 0x%x, need_writeback is set.",
+                                       (unsigned int)*byte);
+                       /*
+                        * Coalesce with previous run if adjacent LCNs.
+                        * Otherwise, append a new run.
+                        */
+                       ntfs_debug("Adding run (lcn 0x%llx, len 0x%llx), "
+                                       "prev_lcn 0x%llx, lcn 0x%llx, "
+                                       "bmp_pos 0x%llx, prev_run_len 0x%llx, "
+                                       "rlpos %i.",
+                                       (unsigned long long)(lcn + bmp_pos),
+                                       1ULL, (unsigned long long)prev_lcn,
+                                       (unsigned long long)lcn,
+                                       (unsigned long long)bmp_pos,
+                                       (unsigned long long)prev_run_len,
+                                       rlpos);
+                       if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) {
+                               ntfs_debug("Coalescing to run (lcn 0x%llx, "
+                                               "len 0x%llx).",
+                                               (unsigned long long)
+                                               rl[rlpos - 1].lcn,
+                                               (unsigned long long)
+                                               rl[rlpos - 1].length);
+                               rl[rlpos - 1].length = ++prev_run_len;
+                               ntfs_debug("Run now (lcn 0x%llx, len 0x%llx), "
+                                               "prev_run_len 0x%llx.",
+                                               (unsigned long long)
+                                               rl[rlpos - 1].lcn,
+                                               (unsigned long long)
+                                               rl[rlpos - 1].length,
+                                               (unsigned long long)
+                                               prev_run_len);
+                       } else {
+                               if (likely(rlpos)) {
+                                       ntfs_debug("Adding new run, (previous "
+                                                       "run lcn 0x%llx, "
+                                                       "len 0x%llx).",
+                                                       (unsigned long long)
+                                                       rl[rlpos - 1].lcn,
+                                                       (unsigned long long)
+                                                       rl[rlpos - 1].length);
+                                       rl[rlpos].vcn = rl[rlpos - 1].vcn +
+                                                       prev_run_len;
+                               } else {
+                                       ntfs_debug("Adding new run, is first "
+                                                       "run.");
+                                       rl[rlpos].vcn = start_vcn;
+                               }
+                               rl[rlpos].lcn = prev_lcn = lcn + bmp_pos;
+                               rl[rlpos].length = prev_run_len = 1;
+                               rlpos++;
+                       }
+                       /* Done? */
+                       if (!--clusters) {
+                               LCN tc;
+                               /*
+                                * Update the current zone position.  Positions
+                                * of already scanned zones have been updated
+                                * during the respective zone switches.
+                                */
+                               tc = lcn + bmp_pos + 1;
+                               ntfs_debug("Done. Updating current zone "
+                                               "position, tc 0x%llx, "
+                                               "search_zone %i.",
+                                               (unsigned long long)tc,
+                                               search_zone);
+                               switch (search_zone) {
+                               case 1:
+                                       ntfs_debug("Before checks, "
+                                                       "vol->mft_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->mft_zone_pos);
+                                       if (tc >= vol->mft_zone_end) {
+                                               vol->mft_zone_pos =
+                                                               vol->mft_lcn;
+                                               if (!vol->mft_zone_end)
+                                                       vol->mft_zone_pos = 0;
+                                       } else if ((bmp_initial_pos >=
+                                                       vol->mft_zone_pos ||
+                                                       tc > vol->mft_zone_pos)
+                                                       && tc >= vol->mft_lcn)
+                                               vol->mft_zone_pos = tc;
+                                       ntfs_debug("After checks, "
+                                                       "vol->mft_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->mft_zone_pos);
+                                       break;
+                               case 2:
+                                       ntfs_debug("Before checks, "
+                                                       "vol->data1_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->data1_zone_pos);
+                                       if (tc >= vol->nr_clusters)
+                                               vol->data1_zone_pos =
+                                                            vol->mft_zone_end;
+                                       else if ((bmp_initial_pos >=
+                                                   vol->data1_zone_pos ||
+                                                   tc > vol->data1_zone_pos)
+                                                   && tc >= vol->mft_zone_end)
+                                               vol->data1_zone_pos = tc;
+                                       ntfs_debug("After checks, "
+                                                       "vol->data1_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->data1_zone_pos);
+                                       break;
+                               case 4:
+                                       ntfs_debug("Before checks, "
+                                                       "vol->data2_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->data2_zone_pos);
+                                       if (tc >= vol->mft_zone_start)
+                                               vol->data2_zone_pos = 0;
+                                       else if (bmp_initial_pos >=
+                                                     vol->data2_zone_pos ||
+                                                     tc > vol->data2_zone_pos)
+                                               vol->data2_zone_pos = tc;
+                                       ntfs_debug("After checks, "
+                                                       "vol->data2_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->data2_zone_pos);
+                                       break;
+                               default:
+                                       BUG();
+                               }
+                               ntfs_debug("Finished.  Going to out.");
+                               goto out;
+                       }
+                       lcn++;
+               }
+               bmp_pos += buf_size;
+               ntfs_debug("After inner while loop: buf_size 0x%x, lcn "
+                               "0x%llx, bmp_pos 0x%llx, need_writeback %i.",
+                               buf_size, (unsigned long long)lcn,
+                               (unsigned long long)bmp_pos, need_writeback);
+               if (bmp_pos < zone_end) {
+                       ntfs_debug("Continuing outer while loop, "
+                                       "bmp_pos 0x%llx, zone_end 0x%llx.",
+                                       (unsigned long long)bmp_pos,
+                                       (unsigned long long)zone_end);
+                       continue;
+               }
+zone_pass_done:        /* Finished with the current zone pass. */
+               ntfs_debug("At zone_pass_done, pass %i.", pass);
+               if (pass == 1) {
+                       /*
+                        * Now do pass 2, scanning the first part of the zone
+                        * we omitted in pass 1.
+                        */
+                       pass = 2;
+                       zone_end = zone_start;
+                       switch (search_zone) {
+                       case 1: /* mft_zone */
+                               zone_start = vol->mft_zone_start;
+                               break;
+                       case 2: /* data1_zone */
+                               zone_start = vol->mft_zone_end;
+                               break;
+                       case 4: /* data2_zone */
+                               zone_start = 0;
+                               break;
+                       default:
+                               BUG();
+                       }
+                       /* Sanity check. */
+                       if (zone_end < zone_start)
+                               zone_end = zone_start;
+                       bmp_pos = zone_start;
+                       ntfs_debug("Continuing outer while loop, pass 2, "
+                                       "zone_start 0x%llx, zone_end 0x%llx, "
+                                       "bmp_pos 0x%llx.",
+                                       (unsigned long long)zone_start,
+                                       (unsigned long long)zone_end,
+                                       (unsigned long long)bmp_pos);
+                       continue;
+               } /* pass == 2 */
+done_zones_check:
+               ntfs_debug("At done_zones_check, search_zone %i, done_zones "
+                               "before 0x%x, done_zones after 0x%x.",
+                               search_zone, done_zones,
+                               done_zones | search_zone);
+               done_zones |= search_zone;
+               if (done_zones < 7) {
+                       ntfs_debug("Switching zone.");
+                       /* Now switch to the next zone we haven't done yet. */
+                       pass = 1;
+                       switch (search_zone) {
+                       case 1:
+                               ntfs_debug("Switching from mft zone to data1 "
+                                               "zone.");
+                               /* Update mft zone position. */
+                               if (rlpos) {
+                                       LCN tc;
+
+                                       ntfs_debug("Before checks, "
+                                                       "vol->mft_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->mft_zone_pos);
+                                       tc = rl[rlpos - 1].lcn +
+                                                       rl[rlpos - 1].length;
+                                       if (tc >= vol->mft_zone_end) {
+                                               vol->mft_zone_pos =
+                                                               vol->mft_lcn;
+                                               if (!vol->mft_zone_end)
+                                                       vol->mft_zone_pos = 0;
+                                       } else if ((bmp_initial_pos >=
+                                                       vol->mft_zone_pos ||
+                                                       tc > vol->mft_zone_pos)
+                                                       && tc >= vol->mft_lcn)
+                                               vol->mft_zone_pos = tc;
+                                       ntfs_debug("After checks, "
+                                                       "vol->mft_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->mft_zone_pos);
+                               }
+                               /* Switch from mft zone to data1 zone. */
+switch_to_data1_zone:          search_zone = 2;
+                               zone_start = bmp_initial_pos =
+                                               vol->data1_zone_pos;
+                               zone_end = vol->nr_clusters;
+                               if (zone_start == vol->mft_zone_end)
+                                       pass = 2;
+                               if (zone_start >= zone_end) {
+                                       vol->data1_zone_pos = zone_start =
+                                                       vol->mft_zone_end;
+                                       pass = 2;
+                               }
+                               break;
+                       case 2:
+                               ntfs_debug("Switching from data1 zone to "
+                                               "data2 zone.");
+                               /* Update data1 zone position. */
+                               if (rlpos) {
+                                       LCN tc;
+
+                                       ntfs_debug("Before checks, "
+                                                       "vol->data1_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->data1_zone_pos);
+                                       tc = rl[rlpos - 1].lcn +
+                                                       rl[rlpos - 1].length;
+                                       if (tc >= vol->nr_clusters)
+                                               vol->data1_zone_pos =
+                                                            vol->mft_zone_end;
+                                       else if ((bmp_initial_pos >=
+                                                   vol->data1_zone_pos ||
+                                                   tc > vol->data1_zone_pos)
+                                                   && tc >= vol->mft_zone_end)
+                                               vol->data1_zone_pos = tc;
+                                       ntfs_debug("After checks, "
+                                                       "vol->data1_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->data1_zone_pos);
+                               }
+                               /* Switch from data1 zone to data2 zone. */
+                               search_zone = 4;
+                               zone_start = bmp_initial_pos =
+                                               vol->data2_zone_pos;
+                               zone_end = vol->mft_zone_start;
+                               if (!zone_start)
+                                       pass = 2;
+                               if (zone_start >= zone_end) {
+                                       vol->data2_zone_pos = zone_start =
+                                                       bmp_initial_pos = 0;
+                                       pass = 2;
+                               }
+                               break;
+                       case 4:
+                               ntfs_debug("Switching from data2 zone to "
+                                               "data1 zone.");
+                               /* Update data2 zone position. */
+                               if (rlpos) {
+                                       LCN tc;
+
+                                       ntfs_debug("Before checks, "
+                                                       "vol->data2_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->data2_zone_pos);
+                                       tc = rl[rlpos - 1].lcn +
+                                                       rl[rlpos - 1].length;
+                                       if (tc >= vol->mft_zone_start)
+                                               vol->data2_zone_pos = 0;
+                                       else if (bmp_initial_pos >=
+                                                     vol->data2_zone_pos ||
+                                                     tc > vol->data2_zone_pos)
+                                               vol->data2_zone_pos = tc;
+                                       ntfs_debug("After checks, "
+                                                       "vol->data2_zone_pos "
+                                                       "0x%llx.",
+                                                       (unsigned long long)
+                                                       vol->data2_zone_pos);
+                               }
+                               /* Switch from data2 zone to data1 zone. */
+                               goto switch_to_data1_zone;
+                       default:
+                               BUG();
+                       }
+                       ntfs_debug("After zone switch, search_zone %i, "
+                                       "pass %i, bmp_initial_pos 0x%llx, "
+                                       "zone_start 0x%llx, zone_end 0x%llx.",
+                                       search_zone, pass,
+                                       (unsigned long long)bmp_initial_pos,
+                                       (unsigned long long)zone_start,
+                                       (unsigned long long)zone_end);
+                       bmp_pos = zone_start;
+                       if (zone_start == zone_end) {
+                               ntfs_debug("Empty zone, going to "
+                                               "done_zones_check.");
+                               /* Empty zone. Don't bother searching it. */
+                               goto done_zones_check;
+                       }
+                       ntfs_debug("Continuing outer while loop.");
+                       continue;
+               } /* done_zones == 7 */
+               ntfs_debug("All zones are finished.");
+               /*
+                * All zones are finished!  If DATA_ZONE, shrink mft zone.  If
+                * MFT_ZONE, we have really run out of space.
+                */
+               mft_zone_size = vol->mft_zone_end - vol->mft_zone_start;
+               ntfs_debug("vol->mft_zone_start 0x%llx, vol->mft_zone_end "
+                               "0x%llx, mft_zone_size 0x%llx.",
+                               (unsigned long long)vol->mft_zone_start,
+                               (unsigned long long)vol->mft_zone_end,
+                               (unsigned long long)mft_zone_size);
+               if (zone == MFT_ZONE || mft_zone_size <= 0) {
+                       ntfs_debug("No free clusters left, going to out.");
+                       /* Really no more space left on device. */
+                       err = ENOSPC;
+                       goto out;
+               } /* zone == DATA_ZONE && mft_zone_size > 0 */
+               ntfs_debug("Shrinking mft zone.");
+               zone_end = vol->mft_zone_end;
+               mft_zone_size >>= 1;
+               if (mft_zone_size > 0)
+                       vol->mft_zone_end = vol->mft_zone_start + mft_zone_size;
+               else /* mft zone and data2 zone no longer exist. */
+                       vol->data2_zone_pos = vol->mft_zone_start =
+                                       vol->mft_zone_end = 0;
+               if (vol->mft_zone_pos >= vol->mft_zone_end) {
+                       vol->mft_zone_pos = vol->mft_lcn;
+                       if (!vol->mft_zone_end)
+                               vol->mft_zone_pos = 0;
+               }
+               bmp_pos = zone_start = bmp_initial_pos =
+                               vol->data1_zone_pos = vol->mft_zone_end;
+               search_zone = 2;
+               pass = 2;
+               done_zones &= ~2;
+               ntfs_debug("After shrinking mft zone, mft_zone_size 0x%llx, "
+                               "vol->mft_zone_start 0x%llx, "
+                               "vol->mft_zone_end 0x%llx, "
+                               "vol->mft_zone_pos 0x%llx, search_zone 2, "
+                               "pass 2, dones_zones 0x%x, zone_start 0x%llx, "
+                               "zone_end 0x%llx, vol->data1_zone_pos 0x%llx, "
+                               "continuing outer while loop.",
+                               (unsigned long long)mft_zone_size,
+                               (unsigned long long)vol->mft_zone_start,
+                               (unsigned long long)vol->mft_zone_end,
+                               (unsigned long long)vol->mft_zone_pos,
+                               done_zones, (unsigned long long)zone_start,
+                               (unsigned long long)zone_end,
+                               (unsigned long long)vol->data1_zone_pos);
+       }
+       ntfs_debug("After outer while loop.");
+out:
+       ntfs_debug("At out.");
+       /* Add runlist terminator element. */
+       if (likely(rl)) {
+               rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
+               rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
+               rl[rlpos].length = 0;
+       }
+       if (likely(page && !IS_ERR(page))) {
+               if (need_writeback) {
+                       ntfs_debug("Marking page dirty.");
+                       flush_dcache_page(page);
+                       set_page_dirty(page);
+                       need_writeback = 0;
+               }
+               ntfs_unmap_page(page);
+       }
+       if (likely(!err)) {
+               up_write(&vol->lcnbmp_lock);
+               ntfs_debug("Done.");
+               return rl;
+       }
+       ntfs_error(vol->sb, "Failed to allocate clusters, aborting "
+                       "(error %i).", err);
+       if (rl) {
+               int err2;
+
+               if (err == ENOSPC)
+                       ntfs_debug("Not enough space to complete allocation, "
+                                       "err ENOSPC, first free lcn 0x%llx, "
+                                       "could allocate up to 0x%llx "
+                                       "clusters.",
+                                       (unsigned long long)rl[0].lcn,
+                                       (unsigned long long)count - clusters);
+               /* Deallocate all allocated clusters. */
+               ntfs_debug("Attempting rollback...");
+               err2 = ntfs_cluster_free_from_rl_nolock(vol, rl);
+               if (err2) {
+                       ntfs_error(vol->sb, "Failed to rollback (error %i).  "
+                                       "Leaving inconsistent metadata!  "
+                                       "Unmount and run chkdsk.", err2);
+                       NVolSetErrors(vol);
+               }
+               /* Free the runlist. */
+               ntfs_free(rl);
+       } else if (err == ENOSPC)
+               ntfs_debug("No space left at all, err = ENOSPC, "
+                               "first free lcn = 0x%llx.",
+                               (unsigned long long)vol->data1_zone_pos);
+       up_write(&vol->lcnbmp_lock);
+       return ERR_PTR(err);
+}
+
+/**
+ * __ntfs_cluster_free - free clusters on an ntfs volume
+ * @vi:                vfs inode whose runlist describes the clusters to free
+ * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters
+ * @count:     number of clusters to free or -1 for all clusters
+ * @is_rollback:       if TRUE this is a rollback operation
+ *
+ * Free @count clusters starting at the cluster @start_vcn in the runlist
+ * described by the vfs inode @vi.
+ *
+ * If @count is -1, all clusters from @start_vcn to the end of the runlist are
+ * deallocated.  Thus, to completely free all clusters in a runlist, use
+ * @start_vcn = 0 and @count = -1.
+ *
+ * @is_rollback should always be FALSE, it is for internal use to rollback
+ * errors.  You probably want to use ntfs_cluster_free() instead.
+ *
+ * Note, ntfs_cluster_free() does not modify the runlist at all, so the caller
+ * has to deal with it later.
+ *
+ * Return the number of deallocated clusters (not counting sparse ones) on
+ * success and -errno on error.
+ *
+ * Locking: - The runlist described by @vi must be unlocked on entry and is
+ *           unlocked on return.
+ *         - This function takes the runlist lock of @vi for reading and
+ *           sometimes for writing and sometimes modifies the runlist.
+ *         - The volume lcn bitmap must be unlocked on entry and is unlocked
+ *           on return.
+ *         - This function takes the volume lcn bitmap lock for writing and
+ *           modifies the bitmap contents.
+ */
+s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
+               const BOOL is_rollback)
+{
+       s64 delta, to_free, total_freed, real_freed;
+       ntfs_inode *ni;
+       ntfs_volume *vol;
+       struct inode *lcnbmp_vi;
+       runlist_element *rl;
+       int err;
+
+       BUG_ON(!vi);
+       ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count "
+                       "0x%llx.%s", vi->i_ino, (unsigned long long)start_vcn,
+                       (unsigned long long)count,
+                       is_rollback ? " (rollback)" : "");
+       ni = NTFS_I(vi);
+       vol = ni->vol;
+       lcnbmp_vi = vol->lcnbmp_ino;
+       BUG_ON(!lcnbmp_vi);
+       BUG_ON(start_vcn < 0);
+       BUG_ON(count < -1);
+       /*
+        * Lock the lcn bitmap for writing but only if not rolling back.  We
+        * must hold the lock all the way including through rollback otherwise
+        * rollback is not possible because once we have cleared a bit and
+        * dropped the lock, anyone could have set the bit again, thus
+        * allocating the cluster for another use.
+        */
+       if (likely(!is_rollback))
+               down_write(&vol->lcnbmp_lock);
+
+       total_freed = real_freed = 0;
+
+       /* This returns with ni->runlist locked for reading on success. */
+       rl = ntfs_find_vcn(ni, start_vcn, FALSE);
+       if (IS_ERR(rl)) {
+               if (!is_rollback)
+                       ntfs_error(vol->sb, "Failed to find first runlist "
+                                       "element (error %li), aborting.",
+                                       PTR_ERR(rl));
+               err = PTR_ERR(rl);
+               goto err_out;
+       }
+       if (unlikely(rl->lcn < (LCN)LCN_HOLE)) {
+               if (!is_rollback)
+                       ntfs_error(vol->sb, "First runlist element has "
+                                       "invalid lcn, aborting.");
+               err = -EIO;
+               goto unl_err_out;
+       }
+       /* Find the starting cluster inside the run that needs freeing. */
+       delta = start_vcn - rl->vcn;
+
+       /* The number of clusters in this run that need freeing. */
+       to_free = rl->length - delta;
+       if (count >= 0 && to_free > count)
+               to_free = count;
+
+       if (likely(rl->lcn >= 0)) {
+               /* Do the actual freeing of the clusters in this run. */
+               err = ntfs_bitmap_set_bits_in_run(lcnbmp_vi, rl->lcn + delta,
+                               to_free, likely(!is_rollback) ? 0 : 1);
+               if (unlikely(err)) {
+                       if (!is_rollback)
+                               ntfs_error(vol->sb, "Failed to clear first run "
+                                               "(error %i), aborting.", err);
+                       goto unl_err_out;
+               }
+               /* We have freed @to_free real clusters. */
+               real_freed = to_free;
+       };
+       /* Go to the next run and adjust the number of clusters left to free. */
+       ++rl;
+       if (count >= 0)
+               count -= to_free;
+
+       /* Keep track of the total "freed" clusters, including sparse ones. */
+       total_freed = to_free;
+       /*
+        * Loop over the remaining runs, using @count as a capping value, and
+        * free them.
+        */
+       for (; rl->length && count != 0; ++rl) {
+               if (unlikely(rl->lcn < (LCN)LCN_HOLE)) {
+                       VCN vcn;
+
+                       /*
+                        * Attempt to map runlist, dropping runlist lock for
+                        * the duration.
+                        */
+                       up_read(&ni->runlist.lock);
+                       vcn = rl->vcn;
+                       err = ntfs_map_runlist(ni, vcn);
+                       if (err) {
+                               if (!is_rollback)
+                                       ntfs_error(vol->sb, "Failed to map "
+                                                       "runlist fragment.");
+                               if (err == -EINVAL || err == -ENOENT)
+                                       err = -EIO;
+                               goto err_out;
+                       }
+                       /*
+                        * This returns with ni->runlist locked for reading on
+                        * success.
+                        */
+                       rl = ntfs_find_vcn(ni, vcn, FALSE);
+                       if (IS_ERR(rl)) {
+                               err = PTR_ERR(rl);
+                               if (!is_rollback)
+                                       ntfs_error(vol->sb, "Failed to find "
+                                                       "subsequent runlist "
+                                                       "element.");
+                               goto err_out;
+                       }
+                       if (unlikely(rl->lcn < (LCN)LCN_HOLE)) {
+                               if (!is_rollback)
+                                       ntfs_error(vol->sb, "Runlist element "
+                                                       "has invalid lcn "
+                                                       "(0x%llx).",
+                                                       (unsigned long long)
+                                                       rl->lcn);
+                               err = -EIO;
+                               goto unl_err_out;
+                       }
+               }
+               /* The number of clusters in this run that need freeing. */
+               to_free = rl->length;
+               if (count >= 0 && to_free > count)
+                       to_free = count;
+
+               if (likely(rl->lcn >= 0)) {
+                       /* Do the actual freeing of the clusters in the run. */
+                       err = ntfs_bitmap_set_bits_in_run(lcnbmp_vi, rl->lcn,
+                                       to_free, likely(!is_rollback) ? 0 : 1);
+                       if (unlikely(err)) {
+                               if (!is_rollback)
+                                       ntfs_error(vol->sb, "Failed to clear "
+                                                       "subsequent run.");
+                               goto unl_err_out;
+                       }
+                       /* We have freed @to_free real clusters. */
+                       real_freed += to_free;
+               }
+               /* Adjust the number of clusters left to free. */
+               if (count >= 0)
+                       count -= to_free;
+       
+               /* Update the total done clusters. */
+               total_freed += to_free;
+       }
+       up_read(&ni->runlist.lock);
+       if (likely(!is_rollback))
+               up_write(&vol->lcnbmp_lock);
+
+       BUG_ON(count > 0);
+
+       /* We are done.  Return the number of actually freed clusters. */
+       ntfs_debug("Done.");
+       return real_freed;
+unl_err_out:
+       up_read(&ni->runlist.lock);
+err_out:
+       if (is_rollback)
+               return err;
+       /* If no real clusters were freed, no need to rollback. */
+       if (!real_freed) {
+               up_write(&vol->lcnbmp_lock);
+               return err;
+       }
+       /*
+        * Attempt to rollback and if that succeeds just return the error code.
+        * If rollback fails, set the volume errors flag, emit an error
+        * message, and return the error code.
+        */
+       delta = __ntfs_cluster_free(vi, start_vcn, total_freed, TRUE);
+       if (delta < 0) {
+               ntfs_error(vol->sb, "Failed to rollback (error %i).  Leaving "
+                               "inconsistent metadata!  Unmount and run "
+                               "chkdsk.", (int)delta);
+               NVolSetErrors(vol);
+       }
+       up_write(&vol->lcnbmp_lock);
+       ntfs_error(vol->sb, "Aborting (error %i).", err);
+       return err;
+}
+
+#endif /* NTFS_RW */
diff --git a/fs/ntfs/lcnalloc.h b/fs/ntfs/lcnalloc.h
new file mode 100644 (file)
index 0000000..f9292e8
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * lcnalloc.h - Exports for NTFS kernel cluster (de)allocation.  Part of the
+ *             Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file is free software; you can redistribute 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/include file 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 (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LINUX_NTFS_LCNALLOC_H
+#define _LINUX_NTFS_LCNALLOC_H
+
+#ifdef NTFS_RW
+
+#include <linux/fs.h>
+
+#include "types.h"
+#include "volume.h"
+
+typedef enum {
+       FIRST_ZONE      = 0,    /* For sanity checking. */
+       MFT_ZONE        = 0,    /* Allocate from $MFT zone. */
+       DATA_ZONE       = 1,    /* Allocate from $DATA zone. */
+       LAST_ZONE       = 1,    /* For sanity checking. */
+} NTFS_CLUSTER_ALLOCATION_ZONES;
+
+extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol,
+               const VCN start_vcn, const s64 count, const LCN start_lcn,
+               const NTFS_CLUSTER_ALLOCATION_ZONES zone);
+
+extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
+               s64 count, const BOOL is_rollback);
+
+/**
+ * ntfs_cluster_free - free clusters on an ntfs volume
+ * @vi:                vfs inode whose runlist describes the clusters to free
+ * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters
+ * @count:     number of clusters to free or -1 for all clusters
+ *
+ * Free @count clusters starting at the cluster @start_vcn in the runlist
+ * described by the vfs inode @vi.
+ *
+ * If @count is -1, all clusters from @start_vcn to the end of the runlist are
+ * deallocated.  Thus, to completely free all clusters in a runlist, use
+ * @start_vcn = 0 and @count = -1.
+ *
+ * Note, ntfs_cluster_free() does not modify the runlist at all, so the caller
+ * has to deal with it later.
+ *
+ * Return the number of deallocated clusters (not counting sparse ones) on
+ * success and -errno on error.
+ *
+ * Locking: - The runlist described by @vi must be unlocked on entry and is
+ *           unlocked on return.
+ *         - This function takes the runlist lock of @vi for reading and
+ *           sometimes for writing and sometimes modifies the runlist.
+ *         - The volume lcn bitmap must be unlocked on entry and is unlocked
+ *           on return.
+ *         - This function takes the volume lcn bitmap lock for writing and
+ *           modifies the bitmap contents.
+ */
+static inline s64 ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
+               s64 count)
+{
+       return __ntfs_cluster_free(vi, start_vcn, count, FALSE);
+}
+
+#endif /* NTFS_RW */
+
+#endif /* defined _LINUX_NTFS_LCNALLOC_H */
index d66ca9e..b72a85d 100644 (file)
@@ -37,7 +37,7 @@ BOOL ntfs_mark_quotas_out_of_date(ntfs_volume *vol)
 {
        ntfs_index_context *ictx;
        QUOTA_CONTROL_ENTRY *qce;
-       const u32 qid = QUOTA_DEFAULTS_ID;
+       const le32 qid = QUOTA_DEFAULTS_ID;
        int err;
 
        ntfs_debug("Entering.");
index d6d65be..5910d6b 100644 (file)
@@ -79,7 +79,7 @@ static ssize_t nodenum_read(struct file *file, char __user *buf,
                count = 9 - file->f_pos;
        if (copy_to_user(buf, buffer + file->f_pos, count))
                return -EFAULT;
-       file->f_pos += count;
+       *ppos += count;
        return count;
 }
 
@@ -94,7 +94,7 @@ static ssize_t property_read(struct file *filp, char __user *buf,
        openprom_property *op;
        char buffer[64];
        
-       if (filp->f_pos >= 0xffffff || count >= 0xffffff)
+       if (*ppos >= 0xffffff || count >= 0xffffff)
                return -EINVAL;
        if (!filp->private_data) {
                node = nodes[(u16)((long)inode->u.generic_ip)].node;
@@ -180,7 +180,7 @@ static ssize_t property_read(struct file *filp, char __user *buf,
        } else {
                i = (op->len << 1) + 1;
        }
-       k = filp->f_pos;
+       k = *ppos;
        if (k >= i) return 0;
        if (count > i - k) count = i - k;
        if (op->flag & OPP_STRING) {
@@ -197,7 +197,7 @@ static ssize_t property_read(struct file *filp, char __user *buf,
                        j = count;
 
                if (j >= 0) {
-                       if (copy_to_user(buf + k - filp->f_pos,
+                       if (copy_to_user(buf + k - *ppos,
                                         op->value + k - 1, j))
                                return -EFAULT;
                        count -= j;
@@ -205,11 +205,11 @@ static ssize_t property_read(struct file *filp, char __user *buf,
                }
 
                if (count) {
-                       if (put_user('\'', &buf [k++ - filp->f_pos]))
+                       if (put_user('\'', &buf [k++ - *ppos]))
                                return -EFAULT;
                }
                if (count > 1) {
-                       if (put_user('\n', &buf [k++ - filp->f_pos]))
+                       if (put_user('\n', &buf [k++ - *ppos]))
                                return -EFAULT;
                }
        } else if (op->flag & OPP_STRINGLIST) {
@@ -287,7 +287,7 @@ static ssize_t property_read(struct file *filp, char __user *buf,
                if ((k < i - 1) && (k & 1)) {
                        sprintf (buffer, "%02x",
                                 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-                       if (put_user(buffer[1], &buf[k++ - filp->f_pos]))
+                       if (put_user(buffer[1], &buf[k++ - *ppos]))
                                return -EFAULT;
                        count--;
                }
@@ -295,7 +295,7 @@ static ssize_t property_read(struct file *filp, char __user *buf,
                for (; (count > 1) && (k < i - 1); k += 2) {
                        sprintf (buffer, "%02x",
                                 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-                       if (copy_to_user(buf + k - filp->f_pos, buffer, 2))
+                       if (copy_to_user(buf + k - *ppos, buffer, 2))
                                return -EFAULT;
                        count -= 2;
                }
@@ -303,18 +303,18 @@ static ssize_t property_read(struct file *filp, char __user *buf,
                if (count && (k < i - 1)) {
                        sprintf (buffer, "%02x",
                                 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-                       if (put_user(buffer[0], &buf[k++ - filp->f_pos]))
+                       if (put_user(buffer[0], &buf[k++ - *ppos]))
                                return -EFAULT;
                        count--;
                }
 
                if (count) {
-                       if (put_user('\n', &buf [k++ - filp->f_pos]))
+                       if (put_user('\n', &buf [k++ - *ppos]))
                                return -EFAULT;
                }
        }
-       count = k - filp->f_pos;
-       filp->f_pos = k;
+       count = k - *ppos;
+       *ppos = k;
        return count;
 }
 
@@ -327,14 +327,14 @@ static ssize_t property_write(struct file *filp, const char __user *buf,
        void *b;
        openprom_property *op;
        
-       if (filp->f_pos >= 0xffffff || count >= 0xffffff)
+       if (*ppos >= 0xffffff || count >= 0xffffff)
                return -EINVAL;
        if (!filp->private_data) {
                i = property_read (filp, NULL, 0, NULL);
                if (i)
                        return i;
        }
-       k = filp->f_pos;
+       k = *ppos;
        op = (openprom_property *)filp->private_data;
        if (!(op->flag & OPP_STRING)) {
                u32 *first, *last;
@@ -462,7 +462,7 @@ static ssize_t property_write(struct file *filp, const char __user *buf,
                                op->len = i;
                } else
                        op->len = i;
-               filp->f_pos += count;
+               *ppos += count;
        }
 write_try_string:
        if (!(op->flag & OPP_BINARY)) {
@@ -480,7 +480,7 @@ write_try_string:
                                op->flag |= OPP_QUOTED;
                                buf++;
                                count--;
-                               filp->f_pos++;
+                               (*ppos)++;
                                if (!count) {
                                        op->flag |= OPP_STRING;
                                        return 1;
@@ -489,9 +489,9 @@ write_try_string:
                                op->flag |= OPP_NOTQUOTED;
                }
                op->flag |= OPP_STRING;
-               if (op->alloclen <= count + filp->f_pos) {
+               if (op->alloclen <= count + *ppos) {
                        b = kmalloc (sizeof (openprom_property)
-                                    + 2 * (count + filp->f_pos), GFP_KERNEL);
+                                    + 2 * (count + *ppos), GFP_KERNEL);
                        if (!b)
                                return -ENOMEM;
                        memcpy (b, filp->private_data,
@@ -499,14 +499,14 @@ write_try_string:
                                + strlen (op->name) + op->alloclen);
                        memset (((char *)b) + sizeof (openprom_property)
                                + strlen (op->name) + op->alloclen, 
-                               0, 2*(count - filp->f_pos) - op->alloclen);
+                               0, 2*(count - *ppos) - op->alloclen);
                        op = (openprom_property *)b;
-                       op->alloclen = 2*(count + filp->f_pos);
+                       op->alloclen = 2*(count + *ppos);
                        b = filp->private_data;
                        filp->private_data = (void *)op;
                        kfree (b);
                }
-               p = op->value + filp->f_pos - ((op->flag & OPP_QUOTED) ? 1 : 0);
+               p = op->value + *ppos - ((op->flag & OPP_QUOTED) ? 1 : 0);
                if (copy_from_user(p, buf, count))
                        return -EFAULT;
                op->flag |= OPP_DIRTY;
@@ -517,17 +517,17 @@ write_try_string:
                        }
                if (i < count) {
                        op->len = p - op->value;
-                       filp->f_pos += i + 1;
+                       *ppos += i + 1;
                        if ((p > op->value) && (op->flag & OPP_QUOTED)
                            && (*(p - 1) == '\''))
                                op->len--;
                } else {
                        if (p - op->value > op->len)
                                op->len = p - op->value;
-                       filp->f_pos += count;
+                       *ppos += count;
                }
        }
-       return filp->f_pos - k;
+       return *ppos - k;
 }
 
 int property_release (struct inode *inode, struct file *filp)
index 6b494ab..c050857 100644 (file)
@@ -53,16 +53,16 @@ adfs_partition(struct parsed_partitions *state, char *name, char *data,
 #ifdef CONFIG_ACORN_PARTITION_RISCIX
 
 struct riscix_part {
-       __u32   start;
-       __u32   length;
-       __u32   one;
+       __le32  start;
+       __le32  length;
+       __le32  one;
        char    name[16];
 };
 
 struct riscix_record {
-       __u32   magic;
-#define RISCIX_MAGIC   (0x4a657320)
-       __u32   date;
+       __le32  magic;
+#define RISCIX_MAGIC   cpu_to_le32(0x4a657320)
+       __le32  date;
        struct riscix_part part[8];
 };
 
@@ -111,9 +111,9 @@ riscix_partition(struct parsed_partitions *state, struct block_device *bdev,
 #define LINUX_SWAP_MAGIC   0xdeafab1e
 
 struct linux_part {
-       __u32 magic;
-       __u32 start_sect;
-       __u32 nr_sects;
+       __le32 magic;
+       __le32 start_sect;
+       __le32 nr_sects;
 };
 
 static int
@@ -306,8 +306,8 @@ adfspart_check_ADFS(struct parsed_partitions *state, struct block_device *bdev)
 #ifdef CONFIG_ACORN_PARTITION_ICS
 
 struct ics_part {
-       __u32 start;
-       __s32 size;
+       __le32 start;
+       __le32 size;
 };
 
 static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long block)
@@ -336,7 +336,7 @@ static inline int valid_ics_sector(const unsigned char *data)
        for (i = 0, sum = 0x50617274; i < 508; i++)
                sum += data[i];
 
-       sum -= le32_to_cpu(*(__u32 *)(&data[508]));
+       sum -= le32_to_cpu(*(__le32 *)(&data[508]));
 
        return sum == 0;
 }
@@ -412,11 +412,11 @@ adfspart_check_ICS(struct parsed_partitions *state, struct block_device *bdev)
 
 #ifdef CONFIG_ACORN_PARTITION_POWERTEC
 struct ptec_part {
-       __u32 unused1;
-       __u32 unused2;
-       __u32 start;
-       __u32 size;
-       __u32 unused5;
+       __le32 unused1;
+       __le32 unused2;
+       __le32 start;
+       __le32 size;
+       __le32 unused5;
        char type[8];
 };
 
@@ -486,10 +486,10 @@ adfspart_check_POWERTEC(struct parsed_partitions *state, struct block_device *bd
 struct eesox_part {
        char    magic[6];
        char    name[10];
-       u32     start;
-       u32     unused6;
-       u32     unused7;
-       u32     unused8;
+       __le32  start;
+       __le32  unused6;
+       __le32  unused7;
+       __le32  unused8;
 };
 
 /*
index dfc1329..3068528 100644 (file)
@@ -14,7 +14,7 @@
 #include "amiga.h"
 
 static __inline__ u32
-checksum_block(u32 *m, int size)
+checksum_block(__be32 *m, int size)
 {
        u32 sum = 0;
 
@@ -31,6 +31,7 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
        struct RigidDiskBlock *rdb;
        struct PartitionBlock *pb;
        int start_sect, nr_sects, blk, part, res = 0;
+       int blksize = 1;        /* Multiplier for disk block size */
        int slot = 1;
        char b[BDEVNAME_SIZE];
 
@@ -44,17 +45,17 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
                                       bdevname(bdev, b), blk);
                        goto rdb_done;
                }
-               if (*(u32 *)data != cpu_to_be32(IDNAME_RIGIDDISK))
+               if (*(__be32 *)data != cpu_to_be32(IDNAME_RIGIDDISK))
                        continue;
 
                rdb = (struct RigidDiskBlock *)data;
-               if (checksum_block((u32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F) == 0)
+               if (checksum_block((__be32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F) == 0)
                        break;
                /* Try again with 0xdc..0xdf zeroed, Windows might have
                 * trashed it.
                 */
-               *(u32 *)(data+0xdc) = 0;
-               if (checksum_block((u32 *)data,
+               *(__be32 *)(data+0xdc) = 0;
+               if (checksum_block((__be32 *)data,
                                be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
                        printk("Warning: Trashed word at 0xd0 in block %d "
                                "ignored in checksum calculation\n",blk);
@@ -65,10 +66,14 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
                               bdevname(bdev, b), blk);
        }
 
-       printk(" RDSK");
+       /* blksize is blocks per 512 byte standard block */
+       blksize = be32_to_cpu( rdb->rdb_BlockBytes ) / 512;
+
+       printk(" RDSK (%d)", blksize * 512);    /* Be more informative */
        blk = be32_to_cpu(rdb->rdb_PartitionList);
        put_dev_sector(sect);
        for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) {
+               blk *= blksize; /* Read in terms partition table understands */
                data = read_dev_sector(bdev, blk, &sect);
                if (!data) {
                        if (warn_no_part)
@@ -80,7 +85,7 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
                blk = be32_to_cpu(pb->pb_Next);
                if (pb->pb_ID != cpu_to_be32(IDNAME_PARTITION))
                        continue;
-               if (checksum_block((u32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
+               if (checksum_block((__be32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
                        continue;
 
                /* Tell Kernel about it */
@@ -88,13 +93,32 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
                nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
                            be32_to_cpu(pb->pb_Environment[9])) *
                           be32_to_cpu(pb->pb_Environment[3]) *
-                          be32_to_cpu(pb->pb_Environment[5]);
+                          be32_to_cpu(pb->pb_Environment[5]) *
+                          blksize;
                if (!nr_sects)
                        continue;
                start_sect = be32_to_cpu(pb->pb_Environment[9]) *
                             be32_to_cpu(pb->pb_Environment[3]) *
-                            be32_to_cpu(pb->pb_Environment[5]);
+                            be32_to_cpu(pb->pb_Environment[5]) *
+                            blksize;
                put_partition(state,slot++,start_sect,nr_sects);
+               {
+                       /* Be even more informative to aid mounting */
+                       char dostype[4];
+                       __be32 *dt = (__be32 *)dostype;
+                       *dt = pb->pb_Environment[16];
+                       if (dostype[3] < ' ')
+                               printk(" (%c%c%c^%c)",
+                                       dostype[0], dostype[1],
+                                       dostype[2], dostype[3] + '@' );
+                       else
+                               printk(" (%c%c%c%c)",
+                                       dostype[0], dostype[1],
+                                       dostype[2], dostype[3]);
+                       printk("(res %d spb %d)",
+                               be32_to_cpu(pb->pb_Environment[6]),
+                               be32_to_cpu(pb->pb_Environment[4]));
+               }
                res = 1;
        }
        printk("\n");
index 314d4db..63186b0 100644 (file)
@@ -15,8 +15,8 @@ struct partition_info
 {
   u8 flg;                      /* bit 0: active; bit 7: bootable */
   char id[3];                  /* "GEM", "BGM", "XGM", or other */
-  u32 st;                      /* start of partition */
-  u32 siz;                     /* length of partition */
+  __be32 st;                   /* start of partition */
+  __be32 siz;                  /* length of partition */
 };
 
 struct rootsector
index 9b2670e..c44fb05 100644 (file)
               0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
 
 typedef struct _gpt_header {
-       u64 signature;
-       u32 revision;
-       u32 header_size;
-       u32 header_crc32;
-       u32 reserved1;
-       u64 my_lba;
-       u64 alternate_lba;
-       u64 first_usable_lba;
-       u64 last_usable_lba;
+       __le64 signature;
+       __le32 revision;
+       __le32 header_size;
+       __le32 header_crc32;
+       __le32 reserved1;
+       __le64 my_lba;
+       __le64 alternate_lba;
+       __le64 first_usable_lba;
+       __le64 last_usable_lba;
        efi_guid_t disk_guid;
-       u64 partition_entry_lba;
-       u32 num_partition_entries;
-       u32 sizeof_partition_entry;
-       u32 partition_entry_array_crc32;
+       __le64 partition_entry_lba;
+       __le32 num_partition_entries;
+       __le32 sizeof_partition_entry;
+       __le32 partition_entry_array_crc32;
        u8 reserved2[GPT_BLOCK_SIZE - 92];
 } __attribute__ ((packed)) gpt_header;
 
@@ -92,18 +92,18 @@ typedef struct _gpt_entry_attributes {
 typedef struct _gpt_entry {
        efi_guid_t partition_type_guid;
        efi_guid_t unique_partition_guid;
-       u64 starting_lba;
-       u64 ending_lba;
+       __le64 starting_lba;
+       __le64 ending_lba;
        gpt_entry_attributes attributes;
        efi_char16_t partition_name[72 / sizeof (efi_char16_t)];
 } __attribute__ ((packed)) gpt_entry;
 
 typedef struct _legacy_mbr {
        u8 boot_code[440];
-       u32 unique_mbr_signature;
-       u16 unknown;
+       __le32 unique_mbr_signature;
+       __le16 unknown;
        struct partition partition_record[4];
-       u16 signature;
+       __le16 signature;
 } __attribute__ ((packed)) legacy_mbr;
 
 /* Functions */
index 4d51456..7ab1c11 100644 (file)
@@ -2,7 +2,7 @@
  * ldm - Support for Windows Logical Disk Manager (Dynamic Disks)
  *
  * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
- * Copyright (C) 2001      Anton Altaparmakov <aia21@cantab.net>
+ * Copyright (c) 2001-2004 Anton Altaparmakov
  * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
  *
  * Documentation is available at http://linux-ntfs.sf.net/ldm
@@ -517,9 +517,15 @@ static BOOL ldm_validate_vmdb (struct block_device *bdev, unsigned long base,
        if (vm->vblk_offset != 512)
                ldm_info ("VBLKs start at offset 0x%04x.", vm->vblk_offset);
 
-       /* FIXME: How should we handle this situation? */
-       if ((vm->vblk_size * vm->last_vblk_seq) != (toc->bitmap1_size << 9))
-               ldm_info ("VMDB and TOCBLOCK don't agree on the database size.");
+       /*
+        * The last_vblkd_seq can be before the end of the vmdb, just make sure
+        * it is not out of bounds.
+        */
+       if ((vm->vblk_size * vm->last_vblk_seq) > (toc->bitmap1_size << 9)) {
+               ldm_crit ("VMDB exceeds allowed size specified by TOCBLOCK.  "
+                               "Database is corrupt.  Aborting.");
+               goto out;
+       }
 
        result = TRUE;
 out:
@@ -560,7 +566,7 @@ static BOOL ldm_validate_partition_table (struct block_device *bdev)
                return FALSE;
        }
 
-       if (*(u16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC))
+       if (*(__le16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC))
                goto out;
 
        p = (struct partition*)(data + 0x01BE);
index 14abedb..6e8d795 100644 (file)
@@ -99,9 +99,9 @@ struct parsed_partitions;
 #define TOC_BITMAP2            "log"           /* bitmaps in the TOCBLOCK. */
 
 /* Most numbers we deal with are big-endian and won't be aligned. */
-#define BE16(x)                        ((u16)be16_to_cpu(get_unaligned((u16*)(x))))
-#define BE32(x)                        ((u32)be32_to_cpu(get_unaligned((u32*)(x))))
-#define BE64(x)                        ((u64)be64_to_cpu(get_unaligned((u64*)(x))))
+#define BE16(x)                        ((u16)be16_to_cpu(get_unaligned((__be16*)(x))))
+#define BE32(x)                        ((u32)be32_to_cpu(get_unaligned((__be32*)(x))))
+#define BE64(x)                        ((u64)be64_to_cpu(get_unaligned((__be64*)(x))))
 
 /* Borrowed from msdos.c */
 #define SYS_IND(p)             (get_unaligned(&(p)->sys_ind))
index 9b0a0d2..bbf26e1 100644 (file)
@@ -8,23 +8,23 @@
 #define APPLE_AUX_TYPE "Apple_UNIX_SVR2"
 
 struct mac_partition {
-       __u16   signature;      /* expected to be MAC_PARTITION_MAGIC */
-       __u16   res1;
-       __u32   map_count;      /* # blocks in partition map */
-       __u32   start_block;    /* absolute starting block # of partition */
-       __u32   block_count;    /* number of blocks in partition */
+       __be16  signature;      /* expected to be MAC_PARTITION_MAGIC */
+       __be16  res1;
+       __be32  map_count;      /* # blocks in partition map */
+       __be32  start_block;    /* absolute starting block # of partition */
+       __be32  block_count;    /* number of blocks in partition */
        char    name[32];       /* partition name */
        char    type[32];       /* string type description */
-       __u32   data_start;     /* rel block # of first data block */
-       __u32   data_count;     /* number of data blocks */
-       __u32   status;         /* partition status bits */
-       __u32   boot_start;
-       __u32   boot_size;
-       __u32   boot_load;
-       __u32   boot_load2;
-       __u32   boot_entry;
-       __u32   boot_entry2;
-       __u32   boot_cksum;
+       __be32  data_start;     /* rel block # of first data block */
+       __be32  data_count;     /* number of data blocks */
+       __be32  status;         /* partition status bits */
+       __be32  boot_start;
+       __be32  boot_size;
+       __be32  boot_load;
+       __be32  boot_load2;
+       __be32  boot_entry;
+       __be32  boot_entry2;
+       __be32  boot_cksum;
        char    processor[16];  /* identifies ISA of boot */
        /* there is more stuff after this that we don't need */
 };
@@ -35,9 +35,9 @@ struct mac_partition {
 
 /* Driver descriptor structure, in block 0 */
 struct mac_driver_desc {
-       __u16   signature;      /* expected to be MAC_DRIVER_MAGIC */
-       __u16   block_size;
-       __u32   block_count;
+       __be16  signature;      /* expected to be MAC_DRIVER_MAGIC */
+       __be16  block_size;
+       __be32  block_count;
     /* ... more stuff */
 };
 
index e9af780..c05c17b 100644 (file)
@@ -17,34 +17,34 @@ int osf_partition(struct parsed_partitions *state, struct block_device *bdev)
        Sector sect;
        unsigned char *data;
        struct disklabel {
-               u32 d_magic;
-               u16 d_type,d_subtype;
+               __le32 d_magic;
+               __le16 d_type,d_subtype;
                u8 d_typename[16];
                u8 d_packname[16];
-               u32 d_secsize;
-               u32 d_nsectors;
-               u32 d_ntracks;
-               u32 d_ncylinders;
-               u32 d_secpercyl;
-               u32 d_secprtunit;
-               u16 d_sparespertrack;
-               u16 d_sparespercyl;
-               u32 d_acylinders;
-               u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
-               u32 d_headswitch, d_trkseek, d_flags;
-               u32 d_drivedata[5];
-               u32 d_spare[5];
-               u32 d_magic2;
-               u16 d_checksum;
-               u16 d_npartitions;
-               u32 d_bbsize, d_sbsize;
+               __le32 d_secsize;
+               __le32 d_nsectors;
+               __le32 d_ntracks;
+               __le32 d_ncylinders;
+               __le32 d_secpercyl;
+               __le32 d_secprtunit;
+               __le16 d_sparespertrack;
+               __le16 d_sparespercyl;
+               __le32 d_acylinders;
+               __le16 d_rpm, d_interleave, d_trackskew, d_cylskew;
+               __le32 d_headswitch, d_trkseek, d_flags;
+               __le32 d_drivedata[5];
+               __le32 d_spare[5];
+               __le32 d_magic2;
+               __le16 d_checksum;
+               __le16 d_npartitions;
+               __le32 d_bbsize, d_sbsize;
                struct d_partition {
-                       u32 p_size;
-                       u32 p_offset;
-                       u32 p_fsize;
+                       __le32 p_size;
+                       __le32 p_offset;
+                       __le32 p_fsize;
                        u8  p_fstype;
                        u8  p_frag;
-                       u16 p_cpg;
+                       __le16 p_cpg;
                } d_partitions[8];
        } * label;
        struct d_partition * partition;
index f1ad8bc..bace1ce 100644 (file)
@@ -8,30 +8,32 @@
 #include "sgi.h"
 
 struct sgi_disklabel {
-       s32 magic_mushroom;             /* Big fat spliff... */
-       s16 root_part_num;              /* Root partition number */
-       s16 swap_part_num;              /* Swap partition number */
+       __be32 magic_mushroom;          /* Big fat spliff... */
+       __be16 root_part_num;           /* Root partition number */
+       __be16 swap_part_num;           /* Swap partition number */
        s8 boot_file[16];               /* Name of boot file for ARCS */
        u8 _unused0[48];                /* Device parameter useless crapola.. */
        struct sgi_volume {
                s8 name[8];             /* Name of volume */
-               s32 block_num;          /* Logical block number */
-               s32 num_bytes;          /* How big, in bytes */
+               __be32 block_num;               /* Logical block number */
+               __be32 num_bytes;               /* How big, in bytes */
        } volume[15];
        struct sgi_partition {
-               u32 num_blocks;         /* Size in logical blocks */
-               u32 first_block;        /* First logical block */
-               s32 type;               /* Type of this partition */
+               __be32 num_blocks;              /* Size in logical blocks */
+               __be32 first_block;     /* First logical block */
+               __be32 type;            /* Type of this partition */
        } partitions[16];
-       s32 csum;                       /* Disk label checksum */
-       s32 _unused1;                   /* Padding */
+       __be32 csum;                    /* Disk label checksum */
+       __be32 _unused1;                        /* Padding */
 };
 
 int sgi_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
-       int i, csum, magic;
+       int i, csum;
+       __be32 magic;
        int slot = 1;
-       unsigned int *ui, start, blocks, cs;
+       unsigned int start, blocks;
+       __be32 *ui, cs;
        Sector sect;
        struct sgi_disklabel *label;
        struct sgi_partition *p;
@@ -44,12 +46,12 @@ int sgi_partition(struct parsed_partitions *state, struct block_device *bdev)
        magic = label->magic_mushroom;
        if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
                /*printk("Dev %s SGI disklabel: bad magic %08x\n",
-                      bdevname(bdev, b), magic);*/
+                      bdevname(bdev, b), be32_to_cpu(magic));*/
                put_dev_sector(sect);
                return 0;
        }
-       ui = ((unsigned int *) (label + 1)) - 1;
-       for(csum = 0; ui >= ((unsigned int *) label);) {
+       ui = ((__be32 *) (label + 1)) - 1;
+       for(csum = 0; ui >= ((__be32 *) label);) {
                cs = *ui--;
                csum += be32_to_cpu(cs);
        }
index 204826e..abe91ca 100644 (file)
 
 int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
-       int i, csum;
+       int i;
+       __be16 csum;
        int slot = 1;
-       unsigned short *ush;
+       __be16 *ush;
        Sector sect;
        struct sun_disklabel {
                unsigned char info[128];   /* Informative text string */
@@ -26,22 +27,22 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
                        unsigned char flags;
                } infos[8];
                unsigned char spare[246];  /* Boot information etc. */
-               unsigned short rspeed;     /* Disk rotational speed */
-               unsigned short pcylcount;  /* Physical cylinder count */
-               unsigned short sparecyl;   /* extra sects per cylinder */
+               __be16 rspeed;     /* Disk rotational speed */
+               __be16 pcylcount;  /* Physical cylinder count */
+               __be16 sparecyl;   /* extra sects per cylinder */
                unsigned char spare2[4];   /* More magic... */
-               unsigned short ilfact;     /* Interleave factor */
-               unsigned short ncyl;       /* Data cylinder count */
-               unsigned short nacyl;      /* Alt. cylinder count */
-               unsigned short ntrks;      /* Tracks per cylinder */
-               unsigned short nsect;      /* Sectors per track */
+               __be16 ilfact;     /* Interleave factor */
+               __be16 ncyl;       /* Data cylinder count */
+               __be16 nacyl;      /* Alt. cylinder count */
+               __be16 ntrks;      /* Tracks per cylinder */
+               __be16 nsect;      /* Sectors per track */
                unsigned char spare3[4];   /* Even more magic... */
                struct sun_partition {
-                       __u32 start_cylinder;
-                       __u32 num_sectors;
+                       __be32 start_cylinder;
+                       __be32 num_sectors;
                } partitions[8];
-               unsigned short magic;      /* Magic number */
-               unsigned short csum;       /* Label xor'd checksum */
+               __be16 magic;      /* Magic number */
+               __be16 csum;       /* Label xor'd checksum */
        } * label;              
        struct sun_partition *p;
        unsigned long spc;
@@ -59,8 +60,8 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
                return 0;
        }
        /* Look at the checksum */
-       ush = ((unsigned short *) (label+1)) - 1;
-       for (csum = 0; ush >= ((unsigned short *) label);)
+       ush = ((__be16 *) (label+1)) - 1;
+       for (csum = 0; ush >= ((__be16 *) label);)
                csum ^= *ush--;
        if (csum) {
                printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
index 126db97..275dedc 100644 (file)
@@ -68,11 +68,12 @@ unsigned long task_vsize(struct mm_struct *mm)
        struct mm_tblock_struct *tbp;
        unsigned long vsize = 0;
 
+       down_read(&mm->mmap_sem);
        for (tbp = &mm->context.tblock; tbp; tbp = tbp->next) {
                if (tbp->rblock)
                        vsize += kobjsize(tbp->rblock->kblock);
        }
-
+       up_read(&mm->mmap_sem);
        return vsize;
 }
 
@@ -81,7 +82,8 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
 {
        struct mm_tblock_struct *tbp;
        int size = kobjsize(mm);
-       
+
+       down_read(&mm->mmap_sem);
        for (tbp = &mm->context.tblock; tbp; tbp = tbp->next) {
                if (tbp->next)
                        size += kobjsize(tbp->next);
@@ -93,7 +95,7 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
 
        size += (*text = mm->end_code - mm->start_code);
        size += (*data = mm->start_stack - mm->start_data);
-
+       up_read(&mm->mmap_sem);
        *resident = size;
        return size;
 }
index 7c7de91..a6cffda 100644 (file)
@@ -115,8 +115,8 @@ out:
 
 /* Header of new quota format */
 struct v2_disk_dqheader {
-       __u32 dqh_magic;        /* Magic number identifying file */
-       __u32 dqh_version;      /* File version */
+       __le32 dqh_magic;        /* Magic number identifying file */
+       __le32 dqh_version;      /* File version */
 };
 
 static int v1_check_quota_file(struct super_block *sb, int type)
index 623139f..b600930 100644 (file)
@@ -289,8 +289,14 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
             error = reiserfs_xattr_set(inode, name, value, size, 0);
        } else {
             error = reiserfs_xattr_del (inode, name);
-            if (error == -ENODATA)
+            if (error == -ENODATA) {
+                /* This may seem odd here, but it means that the ACL was set
+                 * with a value representable with mode bits. If there was
+                 * an ACL before, reiserfs_xattr_del already dirtied the inode.
+                 */
+                mark_inode_dirty (inode);
                 error = 0;
+            }
         }
 
        if (value)
@@ -502,11 +508,11 @@ posix_acl_access_list (struct inode *inode, const char *name, int namelen, char
 }
 
 struct reiserfs_xattr_handler posix_acl_access_handler = {
-    prefix: XATTR_NAME_ACL_ACCESS,
-    get: posix_acl_access_get,
-    set: posix_acl_access_set,
-    del: posix_acl_access_del,
-    list: posix_acl_access_list,
+       .prefix = XATTR_NAME_ACL_ACCESS,
+       .get = posix_acl_access_get,
+       .set = posix_acl_access_set,
+       .del = posix_acl_access_del,
+       .list = posix_acl_access_list,
 };
 
 static int
@@ -555,9 +561,9 @@ posix_acl_default_list (struct inode *inode, const char *name, int namelen, char
 }
 
 struct reiserfs_xattr_handler posix_acl_default_handler = {
-    prefix: XATTR_NAME_ACL_DEFAULT,
-    get: posix_acl_default_get,
-    set: posix_acl_default_set,
-    del: posix_acl_default_del,
-    list: posix_acl_default_list,
+       .prefix = XATTR_NAME_ACL_DEFAULT,
+       .get = posix_acl_default_get,
+       .set = posix_acl_default_set,
+       .del = posix_acl_default_del,
+       .list = posix_acl_default_list,
 };
index 28c863a..3076d56 100644 (file)
@@ -95,15 +95,16 @@ static inline struct romfs_inode_info *ROMFS_I(struct inode *inode)
        return list_entry(inode, struct romfs_inode_info, vfs_inode);
 }
 
-static __s32
+static __u32
 romfs_checksum(void *data, int size)
 {
-       __s32 sum, *ptr;
+       __u32 sum;
+       __be32 *ptr;
 
        sum = 0; ptr = data;
        size>>=2;
        while (size>0) {
-               sum += ntohl(*ptr++);
+               sum += be32_to_cpu(*ptr++);
                size--;
        }
        return sum;
@@ -131,7 +132,7 @@ static int romfs_fill_super(struct super_block *s, void *data, int silent)
        }
 
        rsb = (struct romfs_super_block *)bh->b_data;
-       sz = ntohl(rsb->size);
+       sz = be32_to_cpu(rsb->size);
        if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1
           || sz < ROMFH_SIZE) {
                if (!silent)
@@ -292,7 +293,7 @@ romfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                offset = i->i_ino & ROMFH_MASK;
                if (romfs_copyfrom(i, &ri, offset, ROMFH_SIZE) <= 0)
                        goto out;
-               offset = ntohl(ri.spec) & ROMFH_MASK;
+               offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
        }
 
        /* Not really failsafe, but we are read-only... */
@@ -316,9 +317,9 @@ romfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                romfs_copyfrom(i, fsname, offset+ROMFH_SIZE, j);
 
                ino = offset;
-               nextfh = ntohl(ri.next);
+               nextfh = be32_to_cpu(ri.next);
                if ((nextfh & ROMFH_TYPE) == ROMFH_HRD)
-                       ino = ntohl(ri.spec);
+                       ino = be32_to_cpu(ri.spec);
                if (filldir(dirent, fsname, j, offset, ino,
                            romfs_dtype_table[nextfh & ROMFH_TYPE]) < 0) {
                        goto out;
@@ -349,7 +350,7 @@ romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
                goto out;
 
        maxoff = romfs_maxsize(dir->i_sb);
-       offset = ntohl(ri.spec) & ROMFH_MASK;
+       offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
 
        /* OK, now find the file whose name is in "dentry" in the
         * directory specified by "dir".  */
@@ -382,12 +383,12 @@ romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
                        }
                }
                /* next entry */
-               offset = ntohl(ri.next) & ROMFH_MASK;
+               offset = be32_to_cpu(ri.next) & ROMFH_MASK;
        }
 
        /* Hard link handling */
-       if ((ntohl(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
-               offset = ntohl(ri.spec) & ROMFH_MASK;
+       if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
+               offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
 
        if ((inode = iget(dir->i_sb, offset)))
                goto outi;
@@ -495,15 +496,15 @@ romfs_read_inode(struct inode *i)
                }
                /* XXX: do romfs_checksum here too (with name) */
 
-               nextfh = ntohl(ri.next);
+               nextfh = be32_to_cpu(ri.next);
                if ((nextfh & ROMFH_TYPE) != ROMFH_HRD)
                        break;
 
-               ino = ntohl(ri.spec) & ROMFH_MASK;
+               ino = be32_to_cpu(ri.spec) & ROMFH_MASK;
        }
 
        i->i_nlink = 1;         /* Hard to decide.. */
-       i->i_size = ntohl(ri.size);
+       i->i_size = be32_to_cpu(ri.size);
        i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0;
        i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0;
        i->i_uid = i->i_gid = 0;
@@ -544,7 +545,7 @@ romfs_read_inode(struct inode *i)
                        break;
                default:
                        /* depending on MBZ for sock/fifos */
-                       nextfh = ntohl(ri.spec);
+                       nextfh = be32_to_cpu(ri.spec);
                        init_special_inode(i, ino,
                                        MKDEV(nextfh>>16,nextfh&0xffff));
        }
@@ -579,7 +580,7 @@ static int init_inodecache(void)
 {
        romfs_inode_cachep = kmem_cache_create("romfs_inode_cache",
                                             sizeof(struct romfs_inode_info),
-                                            0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+                                            0, SLAB_RECLAIM_ACCOUNT,
                                             init_once, NULL);
        if (romfs_inode_cachep == NULL)
                return -ENOMEM;
index 8184570..9a6ad96 100644 (file)
    sb->sv_sbd2->s_tfree = *sb->sv_free_blocks
    but we nevertheless keep it up to date. */
 
-static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh)
+static inline sysv_zone_t *get_chunk(struct super_block *sb, struct buffer_head *bh)
 {
        char *bh_data = bh->b_data;
 
        if (SYSV_SB(sb)->s_type == FSTYPE_SYSV4)
-               return (u32*)(bh_data+4);
+               return (sysv_zone_t*)(bh_data+4);
        else
-               return (u32*)(bh_data+2);
+               return (sysv_zone_t*)(bh_data+2);
 }
 
 /* NOTE NOTE NOTE: nr is a block number _as_ _stored_ _on_ _disk_ */
 
-void sysv_free_block(struct super_block * sb, u32 nr)
+void sysv_free_block(struct super_block * sb, sysv_zone_t nr)
 {
        struct sysv_sb_info * sbi = SYSV_SB(sb);
        struct buffer_head * bh;
-       u32 *blocks = sbi->s_bcache;
+       sysv_zone_t *blocks = sbi->s_bcache;
        unsigned count;
        unsigned block = fs32_to_cpu(sbi, nr);
 
@@ -81,7 +81,7 @@ void sysv_free_block(struct super_block * sb, u32 nr)
                        return;
                }
                memset(bh->b_data, 0, sb->s_blocksize);
-               *(u16*)bh->b_data = cpu_to_fs16(sbi, count);
+               *(__fs16*)bh->b_data = cpu_to_fs16(sbi, count);
                memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t));
                mark_buffer_dirty(bh);
                set_buffer_uptodate(bh);
@@ -96,11 +96,11 @@ void sysv_free_block(struct super_block * sb, u32 nr)
        unlock_super(sb);
 }
 
-u32 sysv_new_block(struct super_block * sb)
+sysv_zone_t sysv_new_block(struct super_block * sb)
 {
        struct sysv_sb_info *sbi = SYSV_SB(sb);
        unsigned int block;
-       u32 nr;
+       sysv_zone_t nr;
        struct buffer_head * bh;
        unsigned count;
 
@@ -133,7 +133,7 @@ u32 sysv_new_block(struct super_block * sb)
                        *sbi->s_bcache_count = cpu_to_fs16(sbi, 1);
                        goto Enospc;
                }
-               count = fs16_to_cpu(sbi, *(u16*)bh->b_data);
+               count = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
                if (count > sbi->s_flc_size) {
                        printk("sysv_new_block: free-list block with >flc_size entries\n");
                        brelse(bh);
@@ -161,7 +161,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
        int sb_count;
        int count;
        struct buffer_head * bh = NULL;
-       u32 *blocks;
+       sysv_zone_t *blocks;
        unsigned block;
        int n;
 
@@ -184,15 +184,16 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
        n = fs16_to_cpu(sbi, *sbi->s_bcache_count);
        blocks = sbi->s_bcache;
        while (1) {
+               sysv_zone_t zone;
                if (n > sbi->s_flc_size)
                        goto E2big;
-               block = 0;
-               while (n && (block = blocks[--n]) != 0)
+               zone = 0;
+               while (n && (zone = blocks[--n]) != 0)
                        count++;
-               if (block == 0)
+               if (zone == 0)
                        break;
 
-               block = fs32_to_cpu(sbi, block);
+               block = fs32_to_cpu(sbi, zone);
                if (bh)
                        brelse(bh);
 
@@ -202,7 +203,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
                bh = sb_bread(sb, block);
                if (!bh)
                        goto Eio;
-               n = fs16_to_cpu(sbi, *(u16*)bh->b_data);
+               n = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
                blocks = get_chunk(sb, bh);
        }
        if (bh)
index d63b580..5b1295c 100644 (file)
@@ -137,7 +137,7 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
        struct super_block *sb = dir->i_sb;
        struct sysv_sb_info *sbi = SYSV_SB(sb);
        struct inode *inode;
-       u16 ino;
+       sysv_ino_t ino;
        unsigned count;
 
        inode = new_inode(sb);
index f0e99fc..59e76b5 100644 (file)
@@ -178,16 +178,22 @@ static void detected_v7(struct sysv_sb_info *sbi)
 static int detect_xenix(struct sysv_sb_info *sbi, struct buffer_head *bh)
 {
        struct xenix_super_block *sbd = (struct xenix_super_block *)bh->b_data;
-       if (sbd->s_magic == cpu_to_le32(0x2b5544))
+       if (*(__le32 *)&sbd->s_magic == cpu_to_le32(0x2b5544))
                sbi->s_bytesex = BYTESEX_LE;
-       else if (sbd->s_magic == cpu_to_be32(0x2b5544))
+       else if (*(__be32 *)&sbd->s_magic == cpu_to_be32(0x2b5544))
                sbi->s_bytesex = BYTESEX_BE;
        else
                return 0;
-       if (sbd->s_type > 2 || sbd->s_type < 1)
+       switch (fs32_to_cpu(sbi, sbd->s_type)) {
+       case 1:
+               sbi->s_type = FSTYPE_XENIX;
+               return 1;
+       case 2:
+               sbi->s_type = FSTYPE_XENIX;
+               return 2;
+       default:
                return 0;
-       sbi->s_type = FSTYPE_XENIX;
-       return sbd->s_type;
+       }
 }
 
 static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
@@ -195,14 +201,17 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
        struct super_block *sb = sbi->s_sb;
        /* All relevant fields are at the same offsets in R2 and R4 */
        struct sysv4_super_block * sbd;
+       u32 type;
 
        sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2);
-       if (sbd->s_magic == cpu_to_le32(0xfd187e20))
+       if (*(__le32 *)&sbd->s_magic == cpu_to_le32(0xfd187e20))
                sbi->s_bytesex = BYTESEX_LE;
-       else if (sbd->s_magic == cpu_to_be32(0xfd187e20))
+       else if (*(__be32 *)&sbd->s_magic == cpu_to_be32(0xfd187e20))
                sbi->s_bytesex = BYTESEX_BE;
        else
                return 0;
+
+       type = fs32_to_cpu(sbi, sbd->s_type);
  
        if (fs16_to_cpu(sbi, sbd->s_nfree) == 0xffff) {
                sbi->s_type = FSTYPE_AFS;
@@ -212,18 +221,17 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
                                "forcing read-only mode.\n", 
                                sb->s_id);
                }
-               return sbd->s_type;
+               return type;
        }
  
        if (fs32_to_cpu(sbi, sbd->s_time) < JAN_1_1980) {
                /* this is likely to happen on SystemV2 FS */
-               if (sbd->s_type > 3 || sbd->s_type < 1)
+               if (type > 3 || type < 1)
                        return 0;
                sbi->s_type = FSTYPE_SYSV2;
-               return sbd->s_type;
+               return type;
        }
-       if ((sbd->s_type > 3 || sbd->s_type < 1) &&
-           (sbd->s_type > 0x30 || sbd->s_type < 0x10))
+       if ((type > 3 || type < 1) && (type > 0x30 || type < 0x10))
                return 0;
 
        /* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10,
@@ -231,14 +239,14 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
           filename limit is gone. Due to lack of information about this
            feature read-only mode seems to be a reasonable approach... -KGB */
 
-       if (sbd->s_type >= 0x10) {
+       if (type >= 0x10) {
                printk("SysV FS: can't handle long file names on %s, "
                       "forcing read-only mode.\n", sb->s_id);
                sbi->s_forced_ro = 1;
        }
 
        sbi->s_type = FSTYPE_SYSV4;
-       return sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type;
+       return type >= 0x10 ? type >> 4 : type;
 }
 
 static int detect_coherent(struct sysv_sb_info *sbi, struct buffer_head *bh)
index 493b0a6..b7f9b4a 100644 (file)
@@ -2,6 +2,10 @@
 #define _SYSV_H
 
 #include <linux/buffer_head.h>
+
+typedef __u16 __bitwise __fs16;
+typedef __u32 __bitwise __fs32;
+
 #include <linux/sysv_fs.h>
 
 /*
@@ -38,14 +42,14 @@ struct sysv_sb_info {
           different superblock layout. */
        char *         s_sbd1;          /* entire superblock data, for part 1 */
        char *         s_sbd2;          /* entire superblock data, for part 2 */
-       u16            *s_sb_fic_count; /* pointer to s_sbd->s_ninode */
-        u16            *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
-       u16            *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
-       u16            *s_bcache_count; /* pointer to s_sbd->s_nfree */
-       u32            *s_bcache;       /* pointer to s_sbd->s_free */
-       u32            *s_free_blocks;  /* pointer to s_sbd->s_tfree */
-       u32            *s_sb_time;      /* pointer to s_sbd->s_time */
-       u32            *s_sb_state;     /* pointer to s_sbd->s_state, only FSTYPE_SYSV */
+       __fs16         *s_sb_fic_count; /* pointer to s_sbd->s_ninode */
+        sysv_ino_t     *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
+       __fs16         *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
+       __fs16         *s_bcache_count; /* pointer to s_sbd->s_nfree */
+       sysv_zone_t    *s_bcache;       /* pointer to s_sbd->s_free */
+       __fs32         *s_free_blocks;  /* pointer to s_sbd->s_tfree */
+       __fs32         *s_sb_time;      /* pointer to s_sbd->s_time */
+       __fs32         *s_sb_state;     /* pointer to s_sbd->s_state, only FSTYPE_SYSV */
        /* We keep those superblock entities that don't change here;
           this saves us an indirection and perhaps a conversion. */
        u32            s_firstinodezone; /* index of first inode zone */
@@ -61,7 +65,7 @@ struct sysv_sb_info {
  * SystemV/V7/Coherent FS inode data in memory
  */
 struct sysv_inode_info {
-       u32             i_data[13];
+       __fs32          i_data[13];
        u32             i_dir_start_lookup;
        struct inode    vfs_inode;
 };
@@ -126,15 +130,15 @@ extern void sysv_free_inode(struct inode *);
 extern unsigned long sysv_count_free_inodes(struct super_block *);
 
 /* balloc.c */
-extern u32 sysv_new_block(struct super_block *);
-extern void sysv_free_block(struct super_block *, u32);
+extern sysv_zone_t sysv_new_block(struct super_block *);
+extern void sysv_free_block(struct super_block *, sysv_zone_t);
 extern unsigned long sysv_count_free_blocks(struct super_block *);
 
 /* itree.c */
 extern void sysv_truncate(struct inode *);
 
 /* inode.c */
-extern void sysv_write_inode(struct inode *, int);
+extern int sysv_write_inode(struct inode *, int);
 extern int sysv_sync_inode(struct inode *);
 extern int sysv_sync_file(struct file *, struct dentry *, int);
 extern void sysv_set_inode(struct inode *, dev_t);
@@ -181,58 +185,60 @@ static inline u32 PDP_swab(u32 x)
 #endif
 }
 
-static inline u32 fs32_to_cpu(struct sysv_sb_info *sbi, u32 n)
+static inline __u32 fs32_to_cpu(struct sysv_sb_info *sbi, __fs32 n)
 {
        if (sbi->s_bytesex == BYTESEX_PDP)
-               return PDP_swab(n);
+               return PDP_swab((__force __u32)n);
        else if (sbi->s_bytesex == BYTESEX_LE)
-               return le32_to_cpu(n);
+               return le32_to_cpu((__force __le32)n);
        else
-               return be32_to_cpu(n);
+               return be32_to_cpu((__force __be32)n);
 }
 
-static inline u32 cpu_to_fs32(struct sysv_sb_info *sbi, u32 n)
+static inline __fs32 cpu_to_fs32(struct sysv_sb_info *sbi, __u32 n)
 {
        if (sbi->s_bytesex == BYTESEX_PDP)
-               return PDP_swab(n);
+               return (__force __fs32)PDP_swab(n);
        else if (sbi->s_bytesex == BYTESEX_LE)
-               return cpu_to_le32(n);
+               return (__force __fs32)cpu_to_le32(n);
        else
-               return cpu_to_be32(n);
+               return (__force __fs32)cpu_to_be32(n);
 }
 
-static inline u32 fs32_add(struct sysv_sb_info *sbi, u32 *n, int d)
+static inline __fs32 fs32_add(struct sysv_sb_info *sbi, __fs32 *n, int d)
 {
        if (sbi->s_bytesex == BYTESEX_PDP)
-               return *n = PDP_swab(PDP_swab(*n)+d);
+               *(__u32*)n = PDP_swab(PDP_swab(*(__u32*)n)+d);
        else if (sbi->s_bytesex == BYTESEX_LE)
-               return *n = cpu_to_le32(le32_to_cpu(*n)+d);
+               *(__le32*)n = cpu_to_le32(le32_to_cpu(*(__le32*)n)+d);
        else
-               return *n = cpu_to_be32(be32_to_cpu(*n)+d);
+               *(__be32*)n = cpu_to_be32(be32_to_cpu(*(__be32*)n)+d);
+       return *n;
 }
 
-static inline u16 fs16_to_cpu(struct sysv_sb_info *sbi, u16 n)
+static inline __u16 fs16_to_cpu(struct sysv_sb_info *sbi, __fs16 n)
 {
        if (sbi->s_bytesex != BYTESEX_BE)
-               return le16_to_cpu(n);
+               return le16_to_cpu((__force __le16)n);
        else
-               return be16_to_cpu(n);
+               return be16_to_cpu((__force __be16)n);
 }
 
-static inline u16 cpu_to_fs16(struct sysv_sb_info *sbi, u16 n)
+static inline __fs16 cpu_to_fs16(struct sysv_sb_info *sbi, __u16 n)
 {
        if (sbi->s_bytesex != BYTESEX_BE)
-               return cpu_to_le16(n);
+               return (__force __fs16)cpu_to_le16(n);
        else
-               return cpu_to_be16(n);
+               return (__force __fs16)cpu_to_be16(n);
 }
 
-static inline u16 fs16_add(struct sysv_sb_info *sbi, u16 *n, int d)
+static inline __fs16 fs16_add(struct sysv_sb_info *sbi, __fs16 *n, int d)
 {
        if (sbi->s_bytesex != BYTESEX_BE)
-               return *n = cpu_to_le16(le16_to_cpu(*n)+d);
+               *(__le16*)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d);
        else
-               return *n = cpu_to_be16(be16_to_cpu(*n)+d);
+               *(__be16*)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d);
+       return *n;
 }
 
 #endif /* _SYSV_H */
index 8f7d9ef..235418f 100644 (file)
 #define xleNUM_to_cpup(x,y) (le ## x ## _to_cpup(y))
 #define uintBPL_t uint(BITS_PER_LONG)
 #define uint(x) xuint(x)
-#define xuint(x) uint ## x ## _t
+#define xuint(x) __le ## x
 
 extern inline int find_next_one_bit (void * addr, int size, int offset)
 {
        uintBPL_t * p = ((uintBPL_t *) addr) + (offset / BITS_PER_LONG);
-       uintBPL_t result = offset & ~(BITS_PER_LONG-1);
-       uintBPL_t tmp;
+       int result = offset & ~(BITS_PER_LONG-1);
+       unsigned long tmp;
 
        if (offset >= size)
                return size;
@@ -91,7 +91,7 @@ static int read_block_bitmap(struct super_block * sb,
 {
        struct buffer_head *bh = NULL;
        int retval = 0;
-       lb_addr loc;
+       kernel_lb_addr loc;
 
        loc.logicalBlockNum = bitmap->s_extPosition;
        loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
@@ -145,7 +145,8 @@ static inline int load_block_bitmap(struct super_block * sb,
 
 static void udf_bitmap_free_blocks(struct super_block * sb,
        struct inode * inode,
-       struct udf_bitmap *bitmap, lb_addr bloc, uint32_t offset, uint32_t count)
+       struct udf_bitmap *bitmap,
+       kernel_lb_addr bloc, uint32_t offset, uint32_t count)
 {
        struct buffer_head * bh = NULL;
        unsigned long block;
@@ -424,11 +425,12 @@ error_return:
 
 static void udf_table_free_blocks(struct super_block * sb,
        struct inode * inode,
-       struct inode * table, lb_addr bloc, uint32_t offset, uint32_t count)
+       struct inode * table,
+       kernel_lb_addr bloc, uint32_t offset, uint32_t count)
 {
        uint32_t start, end;
        uint32_t nextoffset, oextoffset, elen;
-       lb_addr nbloc, obloc, eloc;
+       kernel_lb_addr nbloc, obloc, eloc;
        struct buffer_head *obh, *nbh;
        int8_t etype;
        int i;
@@ -678,7 +680,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
 {
        int alloc_count = 0;
        uint32_t extoffset, elen, adsize;
-       lb_addr bloc, eloc;
+       kernel_lb_addr bloc, eloc;
        struct buffer_head *bh;
        int8_t etype = -1;
 
@@ -748,7 +750,7 @@ static int udf_table_new_block(struct super_block * sb,
        uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
        uint32_t newblock = 0, adsize;
        uint32_t extoffset, goal_extoffset, elen, goal_elen = 0;
-       lb_addr bloc, goal_bloc, eloc, goal_eloc;
+       kernel_lb_addr bloc, goal_bloc, eloc, goal_eloc;
        struct buffer_head *bh, *goal_bh;
        int8_t etype;
 
@@ -854,7 +856,7 @@ static int udf_table_new_block(struct super_block * sb,
 
 inline void udf_free_blocks(struct super_block * sb,
        struct inode * inode,
-       lb_addr bloc, uint32_t offset, uint32_t count)
+       kernel_lb_addr bloc, uint32_t offset, uint32_t count)
 {
        uint16_t partition = bloc.partitionReferenceNum;
 
index 0038465..9a61ecc 100644 (file)
 #include <linux/string.h>
 #include <linux/buffer_head.h>
 
-uint8_t * udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
-       lb_addr fe_loc, int *pos, int *offset, struct buffer_head **bh, int *error)
+#if 0
+static uint8_t *
+udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
+               kernel_lb_addr fe_loc, int *pos, int *offset,
+               struct buffer_head **bh, int *error)
 {
        int loffset = *offset;
        int block;
@@ -71,13 +74,14 @@ uint8_t * udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
        }
        return ad;
 }
+#endif
 
 struct fileIdentDesc *
 udf_fileident_read(struct inode *dir, loff_t *nf_pos,
        struct udf_fileident_bh *fibh,
        struct fileIdentDesc *cfi,
-       lb_addr *bloc, uint32_t *extoffset, 
-       lb_addr *eloc, uint32_t *elen,
+       kernel_lb_addr *bloc, uint32_t *extoffset, 
+       kernel_lb_addr *eloc, uint32_t *elen,
        uint32_t *offset, struct buffer_head **bh)
 {
        struct fileIdentDesc *fi;
@@ -259,7 +263,8 @@ udf_get_fileident(void * buffer, int bufsize, int * offset)
        return fi;
 }
 
-extent_ad *
+#if 0
+static extent_ad *
 udf_get_fileextent(void * buffer, int bufsize, int * offset)
 {
        extent_ad * ext;
@@ -293,6 +298,7 @@ udf_get_fileextent(void * buffer, int bufsize, int * offset)
        *offset = *offset + sizeof(extent_ad);
        return ext;
 }
+#endif
 
 short_ad *
 udf_get_fileshortad(uint8_t *ptr, int maxoffset, int *offset, int inc)
index 9132ff5..f81f2eb 100644 (file)
@@ -58,6 +58,20 @@ typedef struct
 typedef uint8_t                dstring;
 
 /* Timestamp (ECMA 167r3 1/7.3) */
+typedef struct
+{
+       __le16          typeAndTimezone;
+       __le16          year;
+       uint8_t         month;
+       uint8_t         day;
+       uint8_t         hour;
+       uint8_t         minute;
+       uint8_t         second;
+       uint8_t         centiseconds;
+       uint8_t         hundredsOfMicroseconds;
+       uint8_t         microseconds;
+} __attribute__ ((packed)) timestamp;
+
 typedef struct
 {
        uint16_t        typeAndTimezone;
@@ -70,7 +84,7 @@ typedef struct
        uint8_t         centiseconds;
        uint8_t         hundredsOfMicroseconds;
        uint8_t         microseconds;
-} __attribute__ ((packed)) timestamp;
+} __attribute__ ((packed)) kernel_timestamp;
 
 /* Type and Time Zone (ECMA 167r3 1/7.3.1) */
 #define TIMESTAMP_TYPE_MASK            0xF000
@@ -139,12 +153,12 @@ struct bootDesc
        uint8_t         reserved1;
        regid           archType;
        regid           bootIdent;
-       uint32_t        bootExtLocation;
-       uint32_t        bootExtLength;
-       uint64_t        loadAddress;
-       uint64_t        startAddress;
+       __le32          bootExtLocation;
+       __le32          bootExtLength;
+       __le64          loadAddress;
+       __le64          startAddress;
        timestamp       descCreationDateAndTime;
-       uint16_t        flags;
+       __le16          flags;
        uint8_t         reserved2[32];
        uint8_t         bootUse[1906];
 } __attribute__ ((packed));
@@ -153,23 +167,29 @@ struct bootDesc
 #define BOOT_FLAGS_ERASE               0x01
 
 /* Extent Descriptor (ECMA 167r3 3/7.1) */
+typedef struct
+{
+       __le32          extLength;
+       __le32          extLocation;
+} __attribute__ ((packed)) extent_ad;
+
 typedef struct
 {
        uint32_t        extLength;
        uint32_t        extLocation;
-} __attribute__ ((packed)) extent_ad;
+} kernel_extent_ad;
 
 /* Descriptor Tag (ECMA 167r3 3/7.2) */
 typedef struct
 {
-       uint16_t        tagIdent;
-       uint16_t        descVersion;
+       __le16          tagIdent;
+       __le16          descVersion;
        uint8_t         tagChecksum;
        uint8_t         reserved;
-       uint16_t        tagSerialNum;
-       uint16_t        descCRC;
-       uint16_t        descCRCLength;
-       uint32_t        tagLocation;
+       __le16          tagSerialNum;
+       __le16          descCRC;
+       __le16          descCRCLength;
+       __le32          tagLocation;
 } __attribute__ ((packed)) tag;
 
 /* Tag Identifier (ECMA 167r3 3/7.2.1) */
@@ -197,15 +217,15 @@ struct NSRDesc
 struct primaryVolDesc
 {
        tag             descTag;
-       uint32_t        volDescSeqNum;
-       uint32_t        primaryVolDescNum;
+       __le32          volDescSeqNum;
+       __le32          primaryVolDescNum;
        dstring         volIdent[32];
-       uint16_t        volSeqNum;
-       uint16_t        maxVolSeqNum;
-       uint16_t        interchangeLvl;
-       uint16_t        maxInterchangeLvl;
-       uint32_t        charSetList;
-       uint32_t        maxCharSetList;
+       __le16          volSeqNum;
+       __le16          maxVolSeqNum;
+       __le16          interchangeLvl;
+       __le16          maxInterchangeLvl;
+       __le32          charSetList;
+       __le32          maxCharSetList;
        dstring         volSetIdent[128];
        charspec        descCharSet;
        charspec        explanatoryCharSet;
@@ -215,8 +235,8 @@ struct primaryVolDesc
        timestamp       recordingDateAndTime;
        regid           impIdent;
        uint8_t         impUse[64];
-       uint32_t        predecessorVolDescSeqLocation;
-       uint16_t        flags;
+       __le32          predecessorVolDescSeqLocation;
+       __le16          flags;
        uint8_t         reserved[22];
 } __attribute__ ((packed));
 
@@ -236,7 +256,7 @@ struct anchorVolDescPtr
 struct volDescPtr
 {
        tag             descTag;
-       uint32_t        volDescSeqNum;
+       __le32          volDescSeqNum;
        extent_ad       nextVolDescSeqExt;
        uint8_t         reserved[484];
 } __attribute__ ((packed));
@@ -245,7 +265,7 @@ struct volDescPtr
 struct impUseVolDesc
 {
        tag             descTag;
-       uint32_t        volDescSeqNum;
+       __le32          volDescSeqNum;
        regid           impIdent;
        uint8_t         impUse[460];
 } __attribute__ ((packed));
@@ -254,14 +274,14 @@ struct impUseVolDesc
 struct partitionDesc
 {
        tag             descTag;
-       uint32_t        volDescSeqNum;
-       uint16_t        partitionFlags;
-       uint16_t        partitionNumber;
+       __le32          volDescSeqNum;
+       __le16          partitionFlags;
+       __le16          partitionNumber;
        regid           partitionContents;
        uint8_t         partitionContentsUse[128];
-       uint32_t        accessType;
-       uint32_t        partitionStartingLocation;
-       uint32_t        partitionLength;
+       __le32          accessType;
+       __le32          partitionStartingLocation;
+       __le32          partitionLength;
        regid           impIdent;
        uint8_t         impUse[128];
        uint8_t         reserved[156];
@@ -290,14 +310,14 @@ struct partitionDesc
 struct logicalVolDesc
 {
        tag             descTag;
-       uint32_t        volDescSeqNum;
+       __le32          volDescSeqNum;
        charspec        descCharSet;
        dstring         logicalVolIdent[128];
-       uint32_t        logicalBlockSize;
+       __le32          logicalBlockSize;
        regid           domainIdent;
        uint8_t         logicalVolContentsUse[16];
-       uint32_t        mapTableLength;
-       uint32_t        numPartitionMaps;
+       __le32          mapTableLength;
+       __le32          numPartitionMaps;
        regid           impIdent;
        uint8_t         impUse[128];
        extent_ad       integritySeqExt;
@@ -322,8 +342,8 @@ struct genericPartitionMap1
 {
        uint8_t         partitionMapType;
        uint8_t         partitionMapLength;
-       uint16_t        volSeqNum;
-       uint16_t        partitionNum;
+       __le16          volSeqNum;
+       __le16          partitionNum;
 } __attribute__ ((packed));
 
 /* Type 2 Partition Map (ECMA 167r3 3/10.7.3) */
@@ -338,8 +358,8 @@ struct genericPartitionMap2
 struct unallocSpaceDesc
 {
        tag             descTag;
-       uint32_t        volDescSeqNum;
-       uint32_t        numAllocDescs;
+       __le32          volDescSeqNum;
+       __le32          numAllocDescs;
        extent_ad       allocDescs[0];
 } __attribute__ ((packed));
 
@@ -355,13 +375,13 @@ struct logicalVolIntegrityDesc
 {
        tag             descTag;
        timestamp       recordingDateAndTime;
-       uint32_t        integrityType;
+       __le32          integrityType;
        extent_ad       nextIntegrityExt;
        uint8_t         logicalVolContentsUse[32];
-       uint32_t        numOfPartitions;
-       uint32_t        lengthOfImpUse;
-       uint32_t        freeSpaceTable[0];
-       uint32_t        sizeTable[0];
+       __le32          numOfPartitions;
+       __le32          lengthOfImpUse;
+       __le32          freeSpaceTable[0];
+       __le32          sizeTable[0];
        uint8_t         impUse[0];
 } __attribute__ ((packed));
 
@@ -372,33 +392,55 @@ struct logicalVolIntegrityDesc
 /* Recorded Address (ECMA 167r3 4/7.1) */
 typedef struct 
 {
-       uint32_t        logicalBlockNum;
-       uint16_t        partitionReferenceNum;
+       __le32          logicalBlockNum;
+       __le16          partitionReferenceNum;
 } __attribute__ ((packed)) lb_addr;
 
+/* ... and its in-core analog */
+typedef struct 
+{
+       uint32_t                logicalBlockNum;
+       uint16_t                partitionReferenceNum;
+} kernel_lb_addr;
+
 /* Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */
 typedef struct
 {
-        uint32_t       extLength;
-        uint32_t       extPosition;
+        __le32         extLength;
+        __le32         extPosition;
 } __attribute__ ((packed)) short_ad;
 
 /* Long Allocation Descriptor (ECMA 167r3 4/14.14.2) */
 typedef struct
 {
-       uint32_t        extLength;
+       __le32          extLength;
        lb_addr         extLocation;
        uint8_t         impUse[6];
 } __attribute__ ((packed)) long_ad;
 
+typedef struct
+{
+       uint32_t        extLength;
+       kernel_lb_addr  extLocation;
+       uint8_t         impUse[6];
+} kernel_long_ad;
+
 /* Extended Allocation Descriptor (ECMA 167r3 4/14.14.3) */
+typedef struct
+{
+       __le32          extLength;
+       __le32          recordedLength;
+       __le32          informationLength;
+       lb_addr         extLocation;
+} __attribute__ ((packed)) ext_ad;
+
 typedef struct
 {
        uint32_t        extLength;
        uint32_t        recordedLength;
        uint32_t        informationLength;
-       lb_addr         extLocation;
-} __attribute__ ((packed)) ext_ad;
+       kernel_lb_addr  extLocation;
+} kernel_ext_ad;
 
 /* Descriptor Tag (ECMA 167r3 4/7.2 - See 3/7.2) */
 
@@ -420,12 +462,12 @@ struct fileSetDesc
 {
        tag             descTag;
        timestamp       recordingDateAndTime;
-       uint16_t        interchangeLvl;
-       uint16_t        maxInterchangeLvl;
-       uint32_t        charSetList;
-       uint32_t        maxCharSetList;
-       uint32_t        fileSetNum;
-       uint32_t        fileSetDescNum;
+       __le16          interchangeLvl;
+       __le16          maxInterchangeLvl;
+       __le32          charSetList;
+       __le32          maxCharSetList;
+       __le32          fileSetNum;
+       __le32          fileSetDescNum;
        charspec        logicalVolIdentCharSet;
        dstring         logicalVolIdent[128];
        charspec        fileSetCharSet;
@@ -454,11 +496,11 @@ struct partitionHeaderDesc
 struct fileIdentDesc
 {
        tag             descTag;
-       uint16_t        fileVersionNum;
+       __le16          fileVersionNum;
        uint8_t         fileCharacteristics;
        uint8_t         lengthFileIdent;
        long_ad         icb;
-       uint16_t        lengthOfImpUse;
+       __le16          lengthOfImpUse;
        uint8_t         impUse[0];
        uint8_t         fileIdent[0];
        uint8_t         padding[0];
@@ -475,21 +517,21 @@ struct fileIdentDesc
 struct allocExtDesc
 {
        tag             descTag;
-       uint32_t        previousAllocExtLocation;
-       uint32_t        lengthAllocDescs;
+       __le32          previousAllocExtLocation;
+       __le32          lengthAllocDescs;
 } __attribute__ ((packed));
 
 /* ICB Tag (ECMA 167r3 4/14.6) */
 typedef struct
 {
-       uint32_t        priorRecordedNumDirectEntries;
-       uint16_t        strategyType;
-       uint16_t        strategyParameter;
-       uint16_t        numEntries;
+       __le32          priorRecordedNumDirectEntries;
+       __le16          strategyType;
+       __le16          strategyParameter;
+       __le16          numEntries;
        uint8_t         reserved;
        uint8_t         fileType;
        lb_addr         parentICBLocation;
-       uint16_t        flags;
+       __le16          flags;
 } __attribute__ ((packed)) icbtag;
 
 /* Strategy Type (ECMA 167r3 4/14.6.2) */
@@ -553,24 +595,24 @@ struct fileEntry
 {
        tag             descTag;
        icbtag          icbTag;
-       uint32_t        uid;
-       uint32_t        gid;
-       uint32_t        permissions;
-       uint16_t        fileLinkCount;
+       __le32          uid;
+       __le32          gid;
+       __le32          permissions;
+       __le16          fileLinkCount;
        uint8_t         recordFormat;
        uint8_t         recordDisplayAttr;
-       uint32_t        recordLength;
-       uint64_t        informationLength;
-       uint64_t        logicalBlocksRecorded;
+       __le32          recordLength;
+       __le64          informationLength;
+       __le64          logicalBlocksRecorded;
        timestamp       accessTime;
        timestamp       modificationTime;
        timestamp       attrTime;
-       uint32_t        checkpoint;
+       __le32          checkpoint;
        long_ad         extendedAttrICB;
        regid           impIdent;
-       uint64_t        uniqueID;
-       uint32_t        lengthExtendedAttr;
-       uint32_t        lengthAllocDescs;
+       __le64          uniqueID;
+       __le32          lengthExtendedAttr;
+       __le32          lengthAllocDescs;
        uint8_t         extendedAttr[0];
        uint8_t         allocDescs[0];
 } __attribute__ ((packed));
@@ -616,28 +658,28 @@ struct fileEntry
 struct extendedAttrHeaderDesc
 {
        tag             descTag;
-       uint32_t        impAttrLocation;
-       uint32_t        appAttrLocation;
+       __le32          impAttrLocation;
+       __le32          appAttrLocation;
 } __attribute__ ((packed));
 
 /* Generic Format (ECMA 167r3 4/14.10.2) */
 struct genericFormat
 {
-       uint32_t        attrType;
+       __le32          attrType;
        uint8_t         attrSubtype;
        uint8_t         reserved[3];
-       uint32_t        attrLength;
+       __le32          attrLength;
        uint8_t         attrData[0];
 } __attribute__ ((packed));
 
 /* Character Set Information (ECMA 167r3 4/14.10.3) */
 struct charSetInfo
 {
-       uint32_t        attrType;
+       __le32          attrType;
        uint8_t         attrSubtype;
        uint8_t         reserved[3];
-       uint32_t        attrLength;
-       uint32_t        escapeSeqLength;
+       __le32          attrLength;
+       __le32          escapeSeqLength;
        uint8_t         charSetType;
        uint8_t         escapeSeq[0];
 } __attribute__ ((packed));
@@ -645,24 +687,24 @@ struct charSetInfo
 /* Alternate Permissions (ECMA 167r3 4/14.10.4) */
 struct altPerms
 {
-       uint32_t        attrType;
+       __le32          attrType;
        uint8_t         attrSubtype;
        uint8_t         reserved[3];
-       uint32_t        attrLength;
-       uint16_t        ownerIdent;
-       uint16_t        groupIdent;
-       uint16_t        permission;
+       __le32          attrLength;
+       __le16          ownerIdent;
+       __le16          groupIdent;
+       __le16          permission;
 } __attribute__ ((packed));
 
 /* File Times Extended Attribute (ECMA 167r3 4/14.10.5) */
 struct fileTimesExtAttr
 {
-       uint32_t        attrType;
+       __le32          attrType;
        uint8_t         attrSubtype;
        uint8_t         reserved[3];
-       uint32_t        attrLength;
-       uint32_t        dataLength;
-       uint32_t        fileTimeExistence;
+       __le32          attrLength;
+       __le32          dataLength;
+       __le32          fileTimeExistence;
        uint8_t         fileTimes;
 } __attribute__ ((packed));
 
@@ -675,36 +717,36 @@ struct fileTimesExtAttr
 /* Information Times Extended Attribute (ECMA 167r3 4/14.10.6) */
 struct infoTimesExtAttr
 {
-       uint32_t        attrType;
+       __le32          attrType;
        uint8_t         attrSubtype;
        uint8_t         reserved[3];
-       uint32_t        attrLength;
-       uint32_t        dataLength;
-       uint32_t        infoTimeExistence;
+       __le32          attrLength;
+       __le32          dataLength;
+       __le32          infoTimeExistence;
        uint8_t         infoTimes[0];
 } __attribute__ ((packed));
 
 /* Device Specification (ECMA 167r3 4/14.10.7) */
 struct deviceSpec
 {
-       uint32_t        attrType;
+       __le32          attrType;
        uint8_t         attrSubtype;
        uint8_t         reserved[3];
-       uint32_t        attrLength;
-       uint32_t        impUseLength;
-       uint32_t        majorDeviceIdent;
-       uint32_t        minorDeviceIdent;
+       __le32          attrLength;
+       __le32          impUseLength;
+       __le32          majorDeviceIdent;
+       __le32          minorDeviceIdent;
        uint8_t         impUse[0];
 } __attribute__ ((packed));
 
 /* Implementation Use Extended Attr (ECMA 167r3 4/14.10.8) */
 struct impUseExtAttr
 {
-       uint32_t        attrType;
+       __le32          attrType;
        uint8_t         attrSubtype;
        uint8_t         reserved[3];
-       uint32_t        attrLength;
-       uint32_t        impUseLength;
+       __le32          attrLength;
+       __le32          impUseLength;
        regid           impIdent;
        uint8_t         impUse[0];
 } __attribute__ ((packed));
@@ -712,11 +754,11 @@ struct impUseExtAttr
 /* Application Use Extended Attribute (ECMA 167r3 4/14.10.9) */
 struct appUseExtAttr
 {
-       uint32_t        attrType;
+       __le32          attrType;
        uint8_t         attrSubtype;
        uint8_t         reserved[3];
-       uint32_t        attrLength;
-       uint32_t        appUseLength;
+       __le32          attrLength;
+       __le32          appUseLength;
        regid           appIdent;
        uint8_t         appUse[0];
 } __attribute__ ((packed));
@@ -735,7 +777,7 @@ struct unallocSpaceEntry
 {
        tag             descTag;
        icbtag          icbTag;
-       uint32_t        lengthAllocDescs;
+       __le32          lengthAllocDescs;
        uint8_t         allocDescs[0];
 } __attribute__ ((packed));
 
@@ -743,8 +785,8 @@ struct unallocSpaceEntry
 struct spaceBitmapDesc
 {
        tag             descTag;
-       uint32_t        numOfBits;
-       uint32_t        numOfBytes;
+       __le32          numOfBits;
+       __le32          numOfBytes;
        uint8_t         bitmap[0];
 } __attribute__ ((packed));
 
@@ -775,7 +817,7 @@ struct partitionIntegrityEntry
 /* Logical Volume Header Descriptor (ECMA 167r3 4/14.15) */
 struct logicalVolHeaderDesc
 {
-       uint64_t        uniqueID;
+       __le64          uniqueID;
        uint8_t         reserved[24];
 } __attribute__ ((packed));
 
@@ -784,7 +826,7 @@ struct pathComponent
 {
        uint8_t         componentType;
        uint8_t         lengthComponentIdent;
-       uint16_t        componentFileVersionNum;
+       __le16          componentFileVersionNum;
        dstring         componentIdent[0];
 } __attribute__ ((packed));
 
@@ -793,28 +835,28 @@ struct extendedFileEntry
 {
        tag             descTag;
        icbtag          icbTag;
-       uint32_t        uid;
-       uint32_t        gid;
-       uint32_t        permissions;
-       uint16_t        fileLinkCount;
+       __le32          uid;
+       __le32          gid;
+       __le32          permissions;
+       __le16          fileLinkCount;
        uint8_t         recordFormat;
        uint8_t         recordDisplayAttr;
-       uint32_t        recordLength;
-       uint64_t        informationLength;
-       uint64_t        objectSize;
-       uint64_t        logicalBlocksRecorded;
+       __le32          recordLength;
+       __le64          informationLength;
+       __le64          objectSize;
+       __le64          logicalBlocksRecorded;
        timestamp       accessTime;
        timestamp       modificationTime;
        timestamp       createTime;
        timestamp       attrTime;
-       uint32_t        checkpoint;
-       uint32_t        reserved;
+       __le32          checkpoint;
+       __le32          reserved;
        long_ad         extendedAttrICB;
        long_ad         streamDirectoryICB;
        regid           impIdent;
-       uint64_t        uniqueID;
-       uint32_t        lengthExtendedAttr;
-       uint32_t        lengthAllocDescs;
+       __le64          uniqueID;
+       __le32          lengthExtendedAttr;
+       __le32          lengthAllocDescs;
        uint8_t         extendedAttr[0];
        uint8_t         allocDescs[0];
 } __attribute__ ((packed));
index e81448d..2dde6b8 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/fs.h>
 #include <linux/smp_lock.h>
 
+static int udf_fsync_inode(struct inode *, int);
+
 /*
  *     File may be NULL when we are called. Perhaps we shouldn't
  *     even pass file to fsync ?
@@ -39,7 +41,7 @@ int udf_fsync_file(struct file * file, struct dentry *dentry, int datasync)
        return udf_fsync_inode(inode, datasync);
 }
 
-int udf_fsync_inode(struct inode *inode, int datasync)
+static int udf_fsync_inode(struct inode *inode, int datasync)
 {
        int err;
 
index f472445..68245ca 100644 (file)
@@ -54,16 +54,19 @@ MODULE_LICENSE("GPL");
 static mode_t udf_convert_permissions(struct fileEntry *);
 static int udf_update_inode(struct inode *, int);
 static void udf_fill_inode(struct inode *, struct buffer_head *);
-static struct buffer_head *inode_getblk(struct inode *, long, int *, long *, int *);
+static struct buffer_head *inode_getblk(struct inode *, long, int *,
+       long *, int *);
+static int8_t udf_insert_aext(struct inode *, kernel_lb_addr, int,
+       kernel_lb_addr, uint32_t, struct buffer_head *);
 static void udf_split_extents(struct inode *, int *, int, int,
-       long_ad [EXTENT_MERGE_SIZE], int *);
+       kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_prealloc_extents(struct inode *, int, int,
-        long_ad [EXTENT_MERGE_SIZE], int *);
+        kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_merge_extents(struct inode *,
-        long_ad [EXTENT_MERGE_SIZE], int *);
+        kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_update_extents(struct inode *,
-       long_ad [EXTENT_MERGE_SIZE], int, int,
-       lb_addr, uint32_t, struct buffer_head **);
+       kernel_long_ad [EXTENT_MERGE_SIZE], int, int,
+       kernel_lb_addr, uint32_t, struct buffer_head **);
 static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 /*
@@ -213,7 +216,7 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
 {
        int newblock;
        struct buffer_head *sbh = NULL, *dbh = NULL;
-       lb_addr bloc, eloc;
+       kernel_lb_addr bloc, eloc;
        uint32_t elen, extoffset;
        uint8_t alloctype;
 
@@ -268,12 +271,12 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
                        return NULL;
                }
                UDF_I_ALLOCTYPE(inode) = alloctype;
-               sfi->descTag.tagLocation = *block;
+               sfi->descTag.tagLocation = cpu_to_le32(*block);
                dfibh.soffset = dfibh.eoffset;
                dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
                dfi = (struct fileIdentDesc *)(dbh->b_data + dfibh.soffset);
                if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
-                       sfi->fileIdent + sfi->lengthOfImpUse))
+                       sfi->fileIdent + le16_to_cpu(sfi->lengthOfImpUse)))
                {
                        UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
                        udf_release_data(dbh);
@@ -349,8 +352,8 @@ abort_negative:
        goto abort;
 }
 
-struct buffer_head * udf_getblk(struct inode * inode, long block,
-       int create, int * err)
+static struct buffer_head *
+udf_getblk(struct inode *inode, long block, int create, int *err)
 {
        struct buffer_head dummy;
 
@@ -378,11 +381,11 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
        int *err, long *phys, int *new)
 {
        struct buffer_head *pbh = NULL, *cbh = NULL, *nbh = NULL, *result = NULL;
-       long_ad laarr[EXTENT_MERGE_SIZE];
+       kernel_long_ad laarr[EXTENT_MERGE_SIZE];
        uint32_t pextoffset = 0, cextoffset = 0, nextoffset = 0;
        int count = 0, startnum = 0, endnum = 0;
        uint32_t elen = 0;
-       lb_addr eloc, pbloc, cbloc, nbloc;
+       kernel_lb_addr eloc, pbloc, cbloc, nbloc;
        int c = 1;
        uint64_t lbcount = 0, b_off = 0;
        uint32_t newblocknum, newblock, offset = 0;
@@ -476,7 +479,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
                c = !c;
                laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
                        ((offset + 1) << inode->i_sb->s_blocksize_bits);
-               memset(&laarr[c].extLocation, 0x00, sizeof(lb_addr));
+               memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr));
                count ++;
                endnum ++;
                lastblock = 1;
@@ -575,7 +578,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
 }
 
 static void udf_split_extents(struct inode *inode, int *c, int offset, int newblocknum,
-       long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
+       kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
 {
        if ((laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30) ||
                (laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
@@ -637,7 +640,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
 }
 
 static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
-        long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
+        kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
 {
        int start, length = 0, currlength = 0, i;
 
@@ -729,7 +732,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
 }
 
 static void udf_merge_extents(struct inode *inode,
-        long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
+        kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
 {
        int i;
 
@@ -814,11 +817,11 @@ static void udf_merge_extents(struct inode *inode,
 }
 
 static void udf_update_extents(struct inode *inode,
-       long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
-       lb_addr pbloc, uint32_t pextoffset, struct buffer_head **pbh)
+       kernel_long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
+       kernel_lb_addr pbloc, uint32_t pextoffset, struct buffer_head **pbh)
 {
        int start = 0, i;
-       lb_addr tmploc;
+       kernel_lb_addr tmploc;
        uint32_t tmplen;
 
        if (startnum > endnum)
@@ -938,10 +941,10 @@ void udf_truncate(struct inode * inode)
 void
 udf_read_inode(struct inode *inode)
 {
-       memset(&UDF_I_LOCATION(inode), 0xFF, sizeof(lb_addr));
+       memset(&UDF_I_LOCATION(inode), 0xFF, sizeof(kernel_lb_addr));
 }
 
-void
+static void
 __udf_read_inode(struct inode *inode)
 {
        struct buffer_head *bh = NULL;
@@ -994,7 +997,7 @@ __udf_read_inode(struct inode *inode)
                {
                        if (ibh)
                        {
-                               lb_addr loc;
+                               kernel_lb_addr loc;
                                ie = (struct indirectEntry *)ibh->b_data;
        
                                loc = lelb_to_cpu(ie->indirectICB.extLocation);
@@ -1005,7 +1008,7 @@ __udf_read_inode(struct inode *inode)
                                        if (ident == TAG_IDENT_FE ||
                                                ident == TAG_IDENT_EFE)
                                        {
-                                               memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(lb_addr));
+                                               memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(kernel_lb_addr));
                                                udf_release_data(bh);
                                                udf_release_data(ibh);
                                                udf_release_data(nbh);
@@ -1313,11 +1316,13 @@ udf_convert_permissions(struct fileEntry *fe)
  *     Written, tested, and released.
  */
 
-void udf_write_inode(struct inode * inode, int sync)
+int udf_write_inode(struct inode * inode, int sync)
 {
+       int ret;
        lock_kernel();
-       udf_update_inode(inode, sync);
+       ret = udf_update_inode(inode, sync);
        unlock_kernel();
+       return ret;
 }
 
 int udf_sync_inode(struct inode * inode)
@@ -1335,7 +1340,7 @@ udf_update_inode(struct inode *inode, int do_sync)
        uint16_t icbflags;
        uint16_t crclen;
        int i;
-       timestamp cpu_time;
+       kernel_timestamp cpu_time;
        int err = 0;
 
        bh = udf_tread(inode->i_sb,
@@ -1411,11 +1416,11 @@ udf_update_inode(struct inode *inode, int do_sync)
                                udf_add_extendedattr(inode,
                                        sizeof(struct deviceSpec) +
                                        sizeof(regid), 12, 0x3);
-                       dsea->attrType = 12;
+                       dsea->attrType = cpu_to_le32(12);
                        dsea->attrSubtype = 1;
-                       dsea->attrLength = sizeof(struct deviceSpec) +
-                               sizeof(regid);
-                       dsea->impUseLength = sizeof(regid);
+                       dsea->attrLength = cpu_to_le32(sizeof(struct deviceSpec) +
+                               sizeof(regid));
+                       dsea->impUseLength = cpu_to_le32(sizeof(regid));
                }
                eid = (regid *)dsea->impUse;
                memset(eid, 0, sizeof(regid));
@@ -1446,7 +1451,7 @@ udf_update_inode(struct inode *inode, int do_sync)
                fe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
                fe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
                fe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
-               fe->descTag.tagIdent = le16_to_cpu(TAG_IDENT_FE);
+               fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE);
                crclen = sizeof(struct fileEntry);
        }
        else
@@ -1492,7 +1497,7 @@ udf_update_inode(struct inode *inode, int do_sync)
                efe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
                efe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
                efe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
-               efe->descTag.tagIdent = le16_to_cpu(TAG_IDENT_EFE);
+               efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE);
                crclen = sizeof(struct extendedFileEntry);
        }
        if (UDF_I_STRAT4096(inode))
@@ -1578,7 +1583,7 @@ udf_update_inode(struct inode *inode, int do_sync)
  * 12/19/98 dgb  Added semaphore and changed to be a wrapper of iget
  */
 struct inode *
-udf_iget(struct super_block *sb, lb_addr ino)
+udf_iget(struct super_block *sb, kernel_lb_addr ino)
 {
        struct inode *inode;
        unsigned long block;
@@ -1603,7 +1608,7 @@ udf_iget(struct super_block *sb, lb_addr ino)
        else if (UDF_I_LOCATION(inode).logicalBlockNum == 0xFFFFFFFF &&
                UDF_I_LOCATION(inode).partitionReferenceNum == 0xFFFF)
        {
-               memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(lb_addr));
+               memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(kernel_lb_addr));
                __udf_read_inode(inode);
                if (is_bad_inode(inode))
                {
@@ -1624,8 +1629,8 @@ udf_iget(struct super_block *sb, lb_addr ino)
        return inode;
 }
 
-int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
-       lb_addr eloc, uint32_t elen, struct buffer_head **bh, int inc)
+int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
+       kernel_lb_addr eloc, uint32_t elen, struct buffer_head **bh, int inc)
 {
        int adsize;
        short_ad *sad = NULL;
@@ -1651,7 +1656,7 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
                char *sptr, *dptr;
                struct buffer_head *nbh;
                int err, loffset;
-               lb_addr obloc = *bloc;
+               kernel_lb_addr obloc = *bloc;
 
                if (!(bloc->logicalBlockNum = udf_new_block(inode->i_sb, NULL,
                        obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
@@ -1764,8 +1769,8 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
        return etype;
 }
 
-int8_t udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
-    lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
+int8_t udf_write_aext(struct inode *inode, kernel_lb_addr bloc, int *extoffset,
+    kernel_lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
 {
        int adsize;
        uint8_t *ptr;
@@ -1820,8 +1825,8 @@ int8_t udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
        return (elen >> 30);
 }
 
-int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
-       lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
+int8_t udf_next_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
+       kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
 {
        int8_t etype;
 
@@ -1842,8 +1847,8 @@ int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
        return etype;
 }
 
-int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
-       lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
+int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
+       kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
 {
        int alen;
        int8_t etype;
@@ -1901,10 +1906,11 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
        return etype;
 }
 
-int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
-       lb_addr neloc, uint32_t nelen, struct buffer_head *bh)
+static int8_t
+udf_insert_aext(struct inode *inode, kernel_lb_addr bloc, int extoffset,
+               kernel_lb_addr neloc, uint32_t nelen, struct buffer_head *bh)
 {
-       lb_addr oeloc;
+       kernel_lb_addr oeloc;
        uint32_t oelen;
        int8_t etype;
 
@@ -1923,11 +1929,11 @@ int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
        return (nelen >> 30);
 }
 
-int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
-       lb_addr eloc, uint32_t elen, struct buffer_head *nbh)
+int8_t udf_delete_aext(struct inode *inode, kernel_lb_addr nbloc, int nextoffset,
+       kernel_lb_addr eloc, uint32_t elen, struct buffer_head *nbh)
 {
        struct buffer_head *obh;
-       lb_addr obloc;
+       kernel_lb_addr obloc;
        int oextoffset, adsize;
        int8_t etype;
        struct allocExtDesc *aed;
@@ -1964,7 +1970,7 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
                        oextoffset = nextoffset - adsize;
                }
        }
-       memset(&eloc, 0x00, sizeof(lb_addr));
+       memset(&eloc, 0x00, sizeof(kernel_lb_addr));
        elen = 0;
 
        if (nbh != obh)
@@ -2015,8 +2021,8 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
        return (elen >> 30);
 }
 
-int8_t inode_bmap(struct inode *inode, int block, lb_addr *bloc, uint32_t *extoffset,
-       lb_addr *eloc, uint32_t *elen, uint32_t *offset, struct buffer_head **bh)
+int8_t inode_bmap(struct inode *inode, int block, kernel_lb_addr *bloc, uint32_t *extoffset,
+       kernel_lb_addr *eloc, uint32_t *elen, uint32_t *offset, struct buffer_head **bh)
 {
        uint64_t lbcount = 0, bcount = (uint64_t)block << inode->i_sb->s_blocksize_bits;
        int8_t etype;
@@ -2054,7 +2060,7 @@ int8_t inode_bmap(struct inode *inode, int block, lb_addr *bloc, uint32_t *extof
 
 long udf_block_map(struct inode *inode, long block)
 {
-       lb_addr eloc, bloc;
+       kernel_lb_addr eloc, bloc;
        uint32_t offset, extoffset, elen;
        struct buffer_head *bh = NULL;
        int ret;
index 037d0b7..e82aae6 100644 (file)
@@ -67,7 +67,7 @@
 
 struct UDFIdentSuffix
 {
-       uint16_t        UDFRevision;
+       __le16          UDFRevision;
        uint8_t         OSClass;
        uint8_t         OSIdentifier;
        uint8_t         reserved[4];
@@ -90,11 +90,11 @@ struct appIdentSuffix
 struct logicalVolIntegrityDescImpUse
 {
        regid           impIdent;
-       uint32_t        numFiles;
-       uint32_t        numDirs;
-       uint16_t        minUDFReadRev;
-       uint16_t        minUDFWriteRev;
-       uint16_t        maxUDFWriteRev;
+       __le32          numFiles;
+       __le32          numDirs;
+       __le16          minUDFReadRev;
+       __le16          minUDFWriteRev;
+       __le16          maxUDFWriteRev;
        uint8_t         impUse[0];
 } __attribute__ ((packed));
 
@@ -117,8 +117,8 @@ struct udfPartitionMap2
        uint8_t         partitionMapLength;
        uint8_t         reserved1[2];
        regid           partIdent;
-       uint16_t        volSeqNum;
-       uint16_t        partitionNum;
+       __le16          volSeqNum;
+       __le16          partitionNum;
 } __attribute__ ((packed));
 
 /* Virtual Partition Map (UDF 2.50 2.2.8) */
@@ -128,8 +128,8 @@ struct virtualPartitionMap
        uint8_t         partitionMapLength;
        uint8_t         reserved1[2];
        regid           partIdent;
-       uint16_t        volSeqNum;
-       uint16_t        partitionNum;
+       __le16          volSeqNum;
+       __le16          partitionNum;
        uint8_t         reserved2[24];
 } __attribute__ ((packed));
 
@@ -140,13 +140,13 @@ struct sparablePartitionMap
        uint8_t         partitionMapLength;
        uint8_t         reserved1[2];
        regid           partIdent;
-       uint16_t        volSeqNum;
-       uint16_t        partitionNum;
-       uint16_t        packetLength;
+       __le16          volSeqNum;
+       __le16          partitionNum;
+       __le16          packetLength;
        uint8_t         numSparingTables;
        uint8_t         reserved2[1];
-       uint32_t        sizeSparingTable;
-       uint32_t        locSparingTable[4];
+       __le32          sizeSparingTable;
+       __le32          locSparingTable[4];
 } __attribute__ ((packed));
 
 /* Metadata Partition Map (UDF 2.4.0 2.2.10) */
@@ -156,13 +156,13 @@ struct metadataPartitionMap
        uint8_t         partitionMapLength;
        uint8_t         reserved1[2];
        regid           partIdent;
-       uint16_t        volSeqNum;
-       uint16_t        partitionNum;
-       uint32_t        metadataFileLoc;
-       uint32_t        metadataMirrorFileLoc;
-       uint32_t        metadataBitmapFileLoc;
-       uint32_t        allocUnitSize;
-       uint16_t        alignUnitSize;
+       __le16          volSeqNum;
+       __le16          partitionNum;
+       __le32          metadataFileLoc;
+       __le32          metadataMirrorFileLoc;
+       __le32          metadataBitmapFileLoc;
+       __le32          allocUnitSize;
+       __le16          alignUnitSize;
        uint8_t         flags;
        uint8_t         reserved2[5];
 } __attribute__ ((packed));
@@ -170,9 +170,9 @@ struct metadataPartitionMap
 /* Virtual Allocation Table (UDF 1.5 2.2.10) */
 struct virtualAllocationTable15
 {
-       uint32_t        VirtualSector[0];
+       __le32          VirtualSector[0];
        regid           vatIdent;
-       uint32_t        previousVATICBLoc;
+       __le32          previousVATICBLoc;
 } __attribute__ ((packed));  
 
 #define ICBTAG_FILE_TYPE_VAT15         0x00U
@@ -180,18 +180,18 @@ struct virtualAllocationTable15
 /* Virtual Allocation Table (UDF 2.50 2.2.11) */
 struct virtualAllocationTable20
 {
-       uint16_t        lengthHeader;
-       uint16_t        lengthImpUse;
+       __le16          lengthHeader;
+       __le16          lengthImpUse;
        dstring         logicalVolIdent[128];
-       uint32_t        previousVATICBLoc;
-       uint32_t        numFiles;
-       uint32_t        numDirs;
-       uint16_t        minReadRevision;
-       uint16_t        minWriteRevision;
-       uint16_t        maxWriteRevision;
-       uint16_t        reserved;
+       __le32          previousVATICBLoc;
+       __le32          numFiles;
+       __le32          numDirs;
+       __le16          minReadRevision;
+       __le16          minWriteRevision;
+       __le16          maxWriteRevision;
+       __le16          reserved;
        uint8_t         impUse[0];
-       uint32_t        vatEntry[0];
+       __le32          vatEntry[0];
 } __attribute__ ((packed));
 
 #define ICBTAG_FILE_TYPE_VAT20         0xF8U
@@ -199,17 +199,17 @@ struct virtualAllocationTable20
 /* Sparing Table (UDF 2.50 2.2.12) */
 struct sparingEntry
 {
-       uint32_t        origLocation;
-       uint32_t        mappedLocation;
+       __le32          origLocation;
+       __le32          mappedLocation;
 } __attribute__ ((packed));
 
 struct sparingTable
 {
        tag             descTag;
        regid           sparingIdent;
-       uint16_t        reallocationTableLen;
-       uint16_t        reserved;
-       uint32_t        sequenceNum;
+       __le16          reallocationTableLen;
+       __le16          reserved;
+       __le32          sequenceNum;
        struct sparingEntry
                        mapEntry[0];
 } __attribute__ ((packed));
@@ -222,7 +222,7 @@ struct sparingTable
 /* struct long_ad ICB - ADImpUse (UDF 2.50 2.2.4.3) */
 struct allocDescImpUse
 {
-       uint16_t        flags;
+       __le16          flags;
        uint8_t         impUse[4];
 } __attribute__ ((packed));
 
@@ -235,14 +235,14 @@ struct allocDescImpUse
 /* FreeEASpace (UDF 2.50 3.3.4.5.1.1) */
 struct freeEaSpace
 {
-       uint16_t        headerChecksum;
+       __le16          headerChecksum;
        uint8_t         freeEASpace[0];
 } __attribute__ ((packed));
 
 /* DVD Copyright Management Information (UDF 2.50 3.3.4.5.1.2) */
 struct DVDCopyrightImpUse 
 {
-       uint16_t        headerChecksum;
+       __le16          headerChecksum;
        uint8_t         CGMSInfo;
        uint8_t         dataType;
        uint8_t         protectionSystemInfo[4];
@@ -252,7 +252,7 @@ struct DVDCopyrightImpUse
 /* FreeAppEASpace (UDF 2.50 3.3.4.6.1) */
 struct freeAppEASpace
 {
-       uint16_t        headerChecksum;
+       __le16          headerChecksum;
        uint8_t         freeEASpace[0];
 } __attribute__ ((packed));
 
index e182fb8..4d36f26 100644 (file)
@@ -84,7 +84,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, uint16_t
                return 0xFFFFFFFF;
        }
 
-       loc = le32_to_cpu(((uint32_t *)bh->b_data)[index]);
+       loc = le32_to_cpu(((__le32 *)bh->b_data)[index]);
 
        udf_release_data(bh);
 
@@ -119,7 +119,7 @@ uint32_t udf_get_pblock_spar15(struct super_block *sb, uint32_t block, uint16_t
 
        if (st)
        {
-               for (i=0; i<st->reallocationTableLen; i++)
+               for (i=0; i<le16_to_cpu(st->reallocationTableLen); i++)
                {
                        if (le32_to_cpu(st->mapEntry[i].origLocation) >= 0xFFFFFFF0)
                                break;
@@ -163,7 +163,7 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
                        if (!st)
                                return 1;
 
-                       for (k=0; k<st->reallocationTableLen; k++)
+                       for (k=0; k<le16_to_cpu(st->reallocationTableLen); k++)
                        {
                                if (le32_to_cpu(st->mapEntry[k].origLocation) == 0xFFFFFFFF)
                                {
@@ -173,7 +173,7 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
                                                {
                                                        st = (struct sparingTable *)sdata->s_spar_map[j]->b_data;
                                                        st->mapEntry[k].origLocation = cpu_to_le32(packet);
-                                                       udf_update_tag((char *)st, sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry));
+                                                       udf_update_tag((char *)st, sizeof(struct sparingTable) + le16_to_cpu(st->reallocationTableLen) * sizeof(struct sparingEntry));
                                                        mark_buffer_dirty(sdata->s_spar_map[j]);
                                                }
                                        }
@@ -190,7 +190,7 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
                                else if (le32_to_cpu(st->mapEntry[k].origLocation) > packet)
                                        break;
                        }
-                       for (l=k; l<st->reallocationTableLen; l++)
+                       for (l=k; l<le16_to_cpu(st->reallocationTableLen); l++)
                        {
                                if (le32_to_cpu(st->mapEntry[l].origLocation) == 0xFFFFFFFF)
                                {
@@ -203,7 +203,7 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
                                                        mapEntry.origLocation = cpu_to_le32(packet);
                                                        memmove(&st->mapEntry[k+1], &st->mapEntry[k], (l-k)*sizeof(struct sparingEntry));
                                                        st->mapEntry[k] = mapEntry;
-                                                       udf_update_tag((char *)st, sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry));
+                                                       udf_update_tag((char *)st, sizeof(struct sparingTable) + le16_to_cpu(st->reallocationTableLen) * sizeof(struct sparingEntry));
                                                        mark_buffer_dirty(sdata->s_spar_map[j]);
                                                }
                                        }
index b51ea9c..7dc8a55 100644 (file)
 #include "udf_i.h"
 #include "udf_sb.h"
 
-static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset,
-       lb_addr eloc, int8_t etype, uint32_t elen, struct buffer_head *bh, uint32_t nelen)
+static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffset,
+       kernel_lb_addr eloc, int8_t etype, uint32_t elen, struct buffer_head *bh, uint32_t nelen)
 {
-       lb_addr neloc = { 0, 0 };
+       kernel_lb_addr neloc = { 0, 0 };
        int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
        int first_block = (nelen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
 
@@ -68,7 +68,7 @@ static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset,
 
 void udf_discard_prealloc(struct inode * inode)
 {
-       lb_addr bloc, eloc;
+       kernel_lb_addr bloc, eloc;
        uint32_t extoffset = 0, elen, nelen;
        uint64_t lbcount = 0;
        int8_t etype = -1, netype;
@@ -129,7 +129,7 @@ void udf_discard_prealloc(struct inode * inode)
 
 void udf_truncate_extents(struct inode * inode)
 {
-       lb_addr bloc, eloc, neloc = { 0, 0 };
+       kernel_lb_addr bloc, eloc, neloc = { 0, 0 };
        uint32_t extoffset, elen, offset, nelen = 0, lelen = 0, lenalloc;
        int8_t etype;
        int first_block = inode->i_size >> inode->i_sb->s_blocksize_bits;
@@ -254,7 +254,7 @@ void udf_truncate_extents(struct inode * inode)
                        }
                        else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
                        {
-                               lb_addr neloc = { 0, 0 };
+                               kernel_lb_addr neloc = { 0, 0 };
                                extoffset -= adsize;
                                nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
                                        ((elen + offset + inode->i_sb->s_blocksize - 1) &
@@ -272,7 +272,7 @@ void udf_truncate_extents(struct inode * inode)
                                                ~(inode->i_sb->s_blocksize - 1));
                                        udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
                                }
-                               memset(&eloc, 0x00, sizeof(lb_addr));
+                               memset(&eloc, 0x00, sizeof(kernel_lb_addr));
                                elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
                                udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
                        }
index ecff2e1..87a9331 100644 (file)
@@ -68,7 +68,7 @@ struct udf_vds_record
 struct generic_desc
 {
        tag             descTag;
-       uint32_t        volDescSeqNum;
+       __le32          volDescSeqNum;
 };
 
 struct ustr
@@ -89,35 +89,32 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *, struct file
 extern int udf_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 
 /* inode.c */
-extern struct inode *udf_iget(struct super_block *, lb_addr);
+extern struct inode *udf_iget(struct super_block *, kernel_lb_addr);
 extern int udf_sync_inode(struct inode *);
 extern void udf_expand_file_adinicb(struct inode *, int, int *);
 extern struct buffer_head * udf_expand_dir_adinicb(struct inode *, int *, int *);
-extern struct buffer_head * udf_getblk(struct inode *, long, int, int *);
 extern struct buffer_head * udf_bread(struct inode *, int, int, int *);
 extern void udf_truncate(struct inode *);
 extern void udf_read_inode(struct inode *);
 extern void udf_put_inode(struct inode *);
 extern void udf_delete_inode(struct inode *);
 extern void udf_clear_inode(struct inode *);
-extern void udf_write_inode(struct inode *, int);
+extern int udf_write_inode(struct inode *, int);
 extern long udf_block_map(struct inode *, long);
-extern int8_t inode_bmap(struct inode *, int, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
-extern int8_t udf_add_aext(struct inode *, lb_addr *, int *, lb_addr, uint32_t, struct buffer_head **, int);
-extern int8_t udf_write_aext(struct inode *, lb_addr, int *, lb_addr, uint32_t, struct buffer_head *, int);
-extern int8_t udf_insert_aext(struct inode *, lb_addr, int, lb_addr, uint32_t, struct buffer_head *);
-extern int8_t udf_delete_aext(struct inode *, lb_addr, int, lb_addr, uint32_t, struct buffer_head *);
-extern int8_t udf_next_aext(struct inode *, lb_addr *, int *, lb_addr *, uint32_t *, struct buffer_head **, int);
-extern int8_t udf_current_aext(struct inode *, lb_addr *, int *, lb_addr *, uint32_t *, struct buffer_head **, int);
+extern int8_t inode_bmap(struct inode *, int, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
+extern int8_t udf_add_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr, uint32_t, struct buffer_head **, int);
+extern int8_t udf_write_aext(struct inode *, kernel_lb_addr, int *, kernel_lb_addr, uint32_t, struct buffer_head *, int);
+extern int8_t udf_delete_aext(struct inode *, kernel_lb_addr, int, kernel_lb_addr, uint32_t, struct buffer_head *);
+extern int8_t udf_next_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
+extern int8_t udf_current_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
 
 /* misc.c */
-extern int udf_read_tagged_data(char *, int size, int fd, int block, int partref);
 extern struct buffer_head *udf_tgetblk(struct super_block *, int);
 extern struct buffer_head *udf_tread(struct super_block *, int);
 extern struct genericFormat *udf_add_extendedattr(struct inode *, uint32_t, uint32_t, uint8_t);
 extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint8_t);
 extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, uint32_t, uint16_t *);
-extern struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, uint32_t, uint16_t *);
+extern struct buffer_head *udf_read_ptagged(struct super_block *, kernel_lb_addr, uint32_t, uint16_t *);
 extern void udf_release_data(struct buffer_head *);
 extern void udf_update_tag(char *, int);
 extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
@@ -148,28 +145,24 @@ extern void udf_discard_prealloc(struct inode *);
 extern void udf_truncate_extents(struct inode *);
 
 /* balloc.c */
-extern void udf_free_blocks(struct super_block *, struct inode *, lb_addr, uint32_t, uint32_t);
+extern void udf_free_blocks(struct super_block *, struct inode *, kernel_lb_addr, uint32_t, uint32_t);
 extern int udf_prealloc_blocks(struct super_block *, struct inode *, uint16_t, uint32_t, uint32_t);
 extern int udf_new_block(struct super_block *, struct inode *, uint16_t, uint32_t, int *);
 
 /* fsync.c */
 extern int udf_fsync_file(struct file *, struct dentry *, int);
-extern int udf_fsync_inode(struct inode *, int);
 
 /* directory.c */
-extern uint8_t * udf_filead_read(struct inode *, uint8_t *, uint8_t, lb_addr, int *, int *, struct buffer_head **, int *);
-extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
+extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
 extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
-extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
 extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
 extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);
-extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
 
 /* crc.c */
 extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
 
 /* udftime.c */
-extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
-extern timestamp *udf_time_to_stamp(timestamp *, struct timespec);
+extern time_t *udf_stamp_to_time(time_t *, long *, kernel_timestamp);
+extern kernel_timestamp *udf_time_to_stamp(kernel_timestamp *, struct timespec);
 
 #endif /* __UDF_DECL_H */
index 6313daa..17d3788 100644 (file)
@@ -4,15 +4,15 @@
 #include <asm/byteorder.h>
 #include <linux/string.h>
 
-static inline lb_addr lelb_to_cpu(lb_addr in)
+static inline kernel_lb_addr lelb_to_cpu(lb_addr in)
 {
-       lb_addr out;
+       kernel_lb_addr out;
        out.logicalBlockNum = le32_to_cpu(in.logicalBlockNum);
        out.partitionReferenceNum = le16_to_cpu(in.partitionReferenceNum);
        return out;
 }
 
-static inline lb_addr cpu_to_lelb(lb_addr in)
+static inline lb_addr cpu_to_lelb(kernel_lb_addr in)
 {
        lb_addr out;
        out.logicalBlockNum = cpu_to_le32(in.logicalBlockNum);
@@ -20,9 +20,9 @@ static inline lb_addr cpu_to_lelb(lb_addr in)
        return out;
 }
 
-static inline timestamp lets_to_cpu(timestamp in)
+static inline kernel_timestamp lets_to_cpu(timestamp in)
 {
-       timestamp out;
+       kernel_timestamp out;
        memcpy(&out, &in, sizeof(timestamp));
        out.typeAndTimezone = le16_to_cpu(in.typeAndTimezone);
        out.year = le16_to_cpu(in.year);
@@ -45,15 +45,15 @@ static inline short_ad cpu_to_lesa(short_ad in)
        return out;
 }
 
-static inline long_ad lela_to_cpu(long_ad in)
+static inline kernel_long_ad lela_to_cpu(long_ad in)
 {
-       long_ad out;
+       kernel_long_ad out;
        out.extLength = le32_to_cpu(in.extLength);
        out.extLocation = lelb_to_cpu(in.extLocation);
        return out;
 }
 
-static inline long_ad cpu_to_lela(long_ad in)
+static inline long_ad cpu_to_lela(kernel_long_ad in)
 {
        long_ad out;
        out.extLength = cpu_to_le32(in.extLength);
@@ -61,15 +61,15 @@ static inline long_ad cpu_to_lela(long_ad in)
        return out;
 }
 
-static inline extent_ad leea_to_cpu(extent_ad in)
+static inline kernel_extent_ad leea_to_cpu(extent_ad in)
 {
-       extent_ad out;
+       kernel_extent_ad out;
        out.extLength = le32_to_cpu(in.extLength);
        out.extLocation = le32_to_cpu(in.extLocation);
        return out;
 }
 
-static inline timestamp cpu_to_lets(timestamp in)
+static inline timestamp cpu_to_lets(kernel_timestamp in)
 {
        timestamp out;
        memcpy(&out, &in, sizeof(timestamp));
index 3722d7d..c2634bd 100644 (file)
@@ -58,7 +58,7 @@ const unsigned short int __mon_yday[2][13] =
 #define SPD 0x15180 /*3600*24*/
 #define SPY(y,l,s) (SPD * (365*y+l)+s)
 
-time_t year_seconds[MAX_YEAR_SECONDS]= {
+static time_t year_seconds[MAX_YEAR_SECONDS]= {
 /*1970*/ SPY( 0, 0,0), SPY( 1, 0,0), SPY( 2, 0,0), SPY( 3, 1,0), 
 /*1974*/ SPY( 4, 1,0), SPY( 5, 1,0), SPY( 6, 1,0), SPY( 7, 2,0), 
 /*1978*/ SPY( 8, 2,0), SPY( 9, 2,0), SPY(10, 2,0), SPY(11, 3,0), 
@@ -85,7 +85,7 @@ extern struct timezone sys_tz;
 #define SECS_PER_DAY   (SECS_PER_HOUR * 24)
 
 time_t *
-udf_stamp_to_time(time_t *dest, long *dest_usec, timestamp src)
+udf_stamp_to_time(time_t *dest, long *dest_usec, kernel_timestamp src)
 {
        int yday;
        uint8_t type = src.typeAndTimezone >> 12;
@@ -120,8 +120,8 @@ udf_stamp_to_time(time_t *dest, long *dest_usec, timestamp src)
 }
 
 
-timestamp *
-udf_time_to_stamp(timestamp *dest, struct timespec ts)
+kernel_timestamp *
+udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
 {
        long int days, rem, y;
        const unsigned short int *ip;
index da9d316..3d6a263 100644 (file)
@@ -31,6 +31,9 @@
 #define UFSD(x)
 #endif
 
+static int
+ufs_check_dir_entry (const char *, struct inode *, struct ufs_dir_entry *,
+                    struct buffer_head *, unsigned long);
 
 
 /*
@@ -292,9 +295,10 @@ failed:
        return NULL;
 }
 
-int ufs_check_dir_entry (const char * function,        struct inode * dir,
-       struct ufs_dir_entry * de, struct buffer_head * bh, 
-       unsigned long offset)
+static int
+ufs_check_dir_entry (const char *function, struct inode *dir,
+                    struct ufs_dir_entry *de, struct buffer_head *bh,
+                    unsigned long offset)
 {
        struct super_block *sb = dir->i_sb;
        const char *error_msg = NULL;
index 06415ae..2e8d466 100644 (file)
@@ -99,8 +99,8 @@ u64  ufs_frag_map(struct inode *inode, sector_t frag)
        sector_t offsets[4], *p;
        int depth = ufs_block_to_path(inode, frag >> uspi->s_fpbshift, offsets);
        u64  ret = 0L;
-       u32 block;
-       u64 u2_block = 0L;
+       __fs32 block;
+       __fs64 u2_block = 0L;
        unsigned flags = UFS_SB(sb)->s_flags;
        u64 temp = 0L;
 
@@ -126,7 +126,7 @@ u64  ufs_frag_map(struct inode *inode, sector_t frag)
                bh = sb_bread(sb, uspi->s_sbbase + fs32_to_cpu(sb, block)+(n>>shift));
                if (!bh)
                        goto out;
-               block = ((u32*) bh->b_data)[n & mask];
+               block = ((__fs32 *) bh->b_data)[n & mask];
                brelse (bh);
                if (!block)
                        goto out;
@@ -148,7 +148,7 @@ ufs2:
                bh = sb_bread(sb, temp +(u64) (n>>shift));
                if (!bh)
                        goto out;
-               u2_block = ((u64*)bh->b_data)[n & mask];
+               u2_block = ((__fs64 *)bh->b_data)[n & mask];
                brelse(bh);
                if (!u2_block)
                        goto out;
@@ -171,7 +171,7 @@ static struct buffer_head * ufs_inode_getfrag (struct inode *inode,
        struct buffer_head * result;
        unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
        unsigned tmp, goal;
-       u32 * p, * p2;
+       __fs32 * p, * p2;
        unsigned flags = 0;
 
        UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
@@ -303,7 +303,7 @@ static struct buffer_head * ufs_block_getfrag (struct inode *inode,
        struct ufs_sb_private_info * uspi;
        struct buffer_head * result;
        unsigned tmp, goal, block, blockoff;
-       u32 * p;
+       __fs32 * p;
 
        sb = inode->i_sb;
        uspi = UFS_SB(sb)->s_uspi;
@@ -322,7 +322,7 @@ static struct buffer_head * ufs_block_getfrag (struct inode *inode,
                        goto out;
        }
 
-       p = (u32 *) bh->b_data + block;
+       p = (__fs32 *) bh->b_data + block;
 repeat:
        tmp = fs32_to_cpu(sb, *p);
        if (tmp) {
@@ -338,7 +338,7 @@ repeat:
                }
        }
 
-       if (block && (tmp = fs32_to_cpu(sb, ((u32*)bh->b_data)[block-1]) + uspi->s_fpb))
+       if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1]) + uspi->s_fpb))
                goal = tmp + uspi->s_fpb;
        else
                goal = bh->b_blocknr + uspi->s_fpb;
@@ -788,11 +788,13 @@ static int ufs_update_inode(struct inode * inode, int do_sync)
        return 0;
 }
 
-void ufs_write_inode (struct inode * inode, int wait)
+int ufs_write_inode (struct inode * inode, int wait)
 {
+       int ret;
        lock_kernel();
-       ufs_update_inode (inode, wait);
+       ret = ufs_update_inode (inode, wait);
        unlock_kernel();
+       return ret;
 }
 
 int ufs_sync_inode (struct inode *inode)
index 4347518..4ff38a0 100644 (file)
@@ -388,7 +388,7 @@ static int ufs_parse_options (char * options, unsigned * mount_options)
 /*
  * Read on-disk structures associated with cylinder groups
  */
-int ufs_read_cylinder_structures (struct super_block * sb) {
+static int ufs_read_cylinder_structures (struct super_block *sb) {
        struct ufs_sb_info * sbi = UFS_SB(sb);
        struct ufs_sb_private_info * uspi;
        struct ufs_super_block *usb;
@@ -488,7 +488,7 @@ failed:
  * Put on-disk structures associated with cylinder groups and 
  * write them back to disk
  */
-void ufs_put_cylinder_structures (struct super_block * sb) {
+static void ufs_put_cylinder_structures (struct super_block *sb) {
        struct ufs_sb_info * sbi = UFS_SB(sb);
        struct ufs_sb_private_info * uspi;
        struct ufs_buffer_head * ubh;
@@ -743,22 +743,22 @@ again:
        /*
         * Check ufs magic number
         */
-       switch ((uspi->fs_magic = __constant_le32_to_cpu(usb3->fs_magic))) {
+       sbi->s_bytesex = BYTESEX_LE;
+       switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) {
                case UFS_MAGIC:
                case UFS2_MAGIC:
                case UFS_MAGIC_LFN:
                case UFS_MAGIC_FEA:
                case UFS_MAGIC_4GB:
-                       sbi->s_bytesex = BYTESEX_LE;
                        goto magic_found;
        }
-       switch ((uspi->fs_magic = __constant_be32_to_cpu(usb3->fs_magic))) {
+       sbi->s_bytesex = BYTESEX_BE;
+       switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) {
                case UFS_MAGIC:
                case UFS2_MAGIC:
                case UFS_MAGIC_LFN:
                case UFS_MAGIC_FEA:
                case UFS_MAGIC_4GB:
-                       sbi->s_bytesex = BYTESEX_BE;
                        goto magic_found;
        }
 
@@ -993,7 +993,7 @@ failed_nomem:
        return -ENOMEM;
 }
 
-void ufs_write_super (struct super_block * sb) {
+static void ufs_write_super (struct super_block *sb) {
        struct ufs_sb_private_info * uspi;
        struct ufs_super_block_first * usb1;
        struct ufs_super_block_third * usb3;
@@ -1020,7 +1020,7 @@ void ufs_write_super (struct super_block * sb) {
        unlock_kernel();
 }
 
-void ufs_put_super (struct super_block * sb)
+static void ufs_put_super (struct super_block *sb)
 {
        struct ufs_sb_info * sbi = UFS_SB(sb);
                
@@ -1037,7 +1037,7 @@ void ufs_put_super (struct super_block * sb)
 }
 
 
-int ufs_remount (struct super_block * sb, int * mount_flags, char * data)
+static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 {
        struct ufs_sb_private_info * uspi;
        struct ufs_super_block_first * usb1;
@@ -1112,7 +1112,7 @@ int ufs_remount (struct super_block * sb, int * mount_flags, char * data)
        return 0;
 }
 
-int ufs_statfs (struct super_block * sb, struct kstatfs * buf)
+static int ufs_statfs (struct super_block *sb, struct kstatfs *buf)
 {
        struct ufs_sb_private_info * uspi;
        struct ufs_super_block_first * usb1;
@@ -1129,7 +1129,7 @@ int ufs_statfs (struct super_block * sb, struct kstatfs * buf)
        flags = UFS_SB(sb)->s_flags;
        if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
                buf->f_type = UFS2_MAGIC;
-               buf->f_blocks = usb->fs_u11.fs_u2.fs_dsize;
+               buf->f_blocks = fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_dsize);
                buf->f_bfree = ufs_blkstofrags(fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nbfree)) +
                        fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nffree);
                buf->f_ffree = fs64_to_cpu(sb,
@@ -1183,7 +1183,7 @@ static int init_inodecache(void)
 {
        ufs_inode_cachep = kmem_cache_create("ufs_inode_cache",
                                             sizeof(struct ufs_inode_info),
-                                            0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+                                            0, SLAB_RECLAIM_ACCOUNT,
                                             init_once, NULL);
        if (ufs_inode_cachep == NULL)
                return -ENOMEM;
index a19000f..1683d2b 100644 (file)
@@ -22,22 +22,22 @@ enum {
        BYTESEX_BE
 };
 
-static __inline u64
-fs64_to_cpu(struct super_block *sbp, u64 n)
+static inline u64
+fs64_to_cpu(struct super_block *sbp, __fs64 n)
 {
        if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-               return le64_to_cpu(n);
+               return le64_to_cpu((__force __le64)n);
        else
-               return be64_to_cpu(n);
+               return be64_to_cpu((__force __be64)n);
 }
 
-static __inline u64
+static inline __fs64
 cpu_to_fs64(struct super_block *sbp, u64 n)
 {
        if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-               return cpu_to_le64(n);
+               return (__force __fs64)cpu_to_le64(n);
        else
-               return cpu_to_be64(n);
+               return (__force __fs64)cpu_to_be64(n);
 }
 
 static __inline u32
@@ -59,75 +59,75 @@ fs64_sub(struct super_block *sbp, u32 *n, int d)
 }
 
 static __inline u32
-fs32_to_cpu(struct super_block *sbp, u32 n)
+fs32_to_cpu(struct super_block *sbp, __fs32 n)
 {
        if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-               return le32_to_cpu(n);
+               return le32_to_cpu((__force __le32)n);
        else
-               return be32_to_cpu(n);
+               return be32_to_cpu((__force __be32)n);
 }
 
-static __inline u32
+static inline __fs32
 cpu_to_fs32(struct super_block *sbp, u32 n)
 {
        if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-               return cpu_to_le32(n);
+               return (__force __fs32)cpu_to_le32(n);
        else
-               return cpu_to_be32(n);
+               return (__force __fs32)cpu_to_be32(n);
 }
 
-static __inline u32
-fs32_add(struct super_block *sbp, u32 *n, int d)
+static inline void
+fs32_add(struct super_block *sbp, __fs32 *n, int d)
 {
        if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-               return *n = cpu_to_le32(le32_to_cpu(*n)+d);
+               *(__le32 *)n = cpu_to_le32(le32_to_cpu(*(__le32 *)n)+d);
        else
-               return *n = cpu_to_be32(be32_to_cpu(*n)+d);
+               *(__be32 *)n = cpu_to_be32(be32_to_cpu(*(__be32 *)n)+d);
 }
 
-static __inline u32
-fs32_sub(struct super_block *sbp, u32 *n, int d)
+static inline void
+fs32_sub(struct super_block *sbp, __fs32 *n, int d)
 {
        if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-               return *n = cpu_to_le32(le32_to_cpu(*n)-d);
+               *(__le32 *)n = cpu_to_le32(le32_to_cpu(*(__le32 *)n)-d);
        else
-               return *n = cpu_to_be32(be32_to_cpu(*n)-d);
+               *(__be32 *)n = cpu_to_be32(be32_to_cpu(*(__be32 *)n)-d);
 }
 
-static __inline u16
-fs16_to_cpu(struct super_block *sbp, u16 n)
+static inline u16
+fs16_to_cpu(struct super_block *sbp, __fs16 n)
 {
        if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-               return le16_to_cpu(n);
+               return le16_to_cpu((__force __le16)n);
        else
-               return be16_to_cpu(n);
+               return be16_to_cpu((__force __be16)n);
 }
 
-static __inline u16
+static inline __fs16
 cpu_to_fs16(struct super_block *sbp, u16 n)
 {
        if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-               return cpu_to_le16(n);
+               return (__force __fs16)cpu_to_le16(n);
        else
-               return cpu_to_be16(n);
+               return (__force __fs16)cpu_to_be16(n);
 }
 
-static __inline u16
-fs16_add(struct super_block *sbp, u16 *n, int d)
+static inline void
+fs16_add(struct super_block *sbp, __fs16 *n, int d)
 {
        if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-               return *n = cpu_to_le16(le16_to_cpu(*n)+d);
+               *(__le16 *)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d);
        else
-               return *n = cpu_to_be16(be16_to_cpu(*n)+d);
+               *(__be16 *)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d);
 }
 
-static __inline u16
-fs16_sub(struct super_block *sbp, u16 *n, int d)
+static inline void
+fs16_sub(struct super_block *sbp, __fs16 *n, int d)
 {
        if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-               return *n = cpu_to_le16(le16_to_cpu(*n)-d);
+               *(__le16 *)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)-d);
        else
-               return *n = cpu_to_be16(be16_to_cpu(*n)-d);
+               *(__be16 *)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)-d);
 }
 
 #endif /* _UFS_SWAB_H */
index b22169e..2a2987c 100644 (file)
@@ -74,7 +74,7 @@ static int ufs_trunc_direct (struct inode * inode)
        struct super_block * sb;
        struct ufs_sb_private_info * uspi;
        struct buffer_head * bh;
-       u32 * p;
+       __fs32 * p;
        unsigned frag1, frag2, frag3, frag4, block1, block2;
        unsigned frag_to_free, free_count;
        unsigned i, j, tmp;
@@ -199,13 +199,13 @@ next2:;
 }
 
 
-static int ufs_trunc_indirect (struct inode * inode, unsigned offset, u32 * p)
+static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
 {
        struct super_block * sb;
        struct ufs_sb_private_info * uspi;
        struct ufs_buffer_head * ind_ubh;
        struct buffer_head * bh;
-       u32 * ind;
+       __fs32 * ind;
        unsigned indirect_block, i, j, tmp;
        unsigned frag_to_free, free_count;
        int retry;
@@ -296,13 +296,13 @@ next:;
        return retry;
 }
 
-static int ufs_trunc_dindirect (struct inode * inode, unsigned offset, u32 * p)
+static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
 {
        struct super_block * sb;
        struct ufs_sb_private_info * uspi;
        struct ufs_buffer_head * dind_bh;
        unsigned i, tmp, dindirect_block;
-       u32 * dind;
+       __fs32 * dind;
        int retry = 0;
        
        UFSD(("ENTER\n"))
@@ -371,7 +371,7 @@ static int ufs_trunc_tindirect (struct inode * inode)
        struct ufs_sb_private_info * uspi;
        struct ufs_buffer_head * tind_bh;
        unsigned tindirect_block, tmp, i;
-       u32 * tind, * p;
+       __fs32 * tind, * p;
        int retry;
        
        UFSD(("ENTER\n"))
@@ -449,9 +449,9 @@ void ufs_truncate (struct inode * inode)
        while (1) {
                retry = ufs_trunc_direct(inode);
                retry |= ufs_trunc_indirect (inode, UFS_IND_BLOCK,
-                       (u32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]);
+                       (__fs32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]);
                retry |= ufs_trunc_dindirect (inode, UFS_IND_BLOCK + uspi->s_apb,
-                       (u32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]);
+                       (__fs32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]);
                retry |= ufs_trunc_tindirect (inode);
                if (!retry)
                        break;
index ad72b7f..58770d2 100644 (file)
@@ -72,20 +72,20 @@ ufs_get_fs_npsect(struct super_block *sb, struct ufs_super_block_first *usb1,
 static inline u64
 ufs_get_fs_qbmask(struct super_block *sb, struct ufs_super_block_third *usb3)
 {
-       u64 tmp;
+       __fs64 tmp;
 
        switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
        case UFS_ST_SUN:
-               ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qbmask[0];
-               ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qbmask[1];
+               ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qbmask[0];
+               ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qbmask[1];
                break;
        case UFS_ST_SUNx86:
-               ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qbmask[0];
-               ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qbmask[1];
+               ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qbmask[0];
+               ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qbmask[1];
                break;
        case UFS_ST_44BSD:
-               ((u32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qbmask[0];
-               ((u32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qbmask[1];
+               ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qbmask[0];
+               ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qbmask[1];
                break;
        }
 
@@ -95,20 +95,20 @@ ufs_get_fs_qbmask(struct super_block *sb, struct ufs_super_block_third *usb3)
 static inline u64
 ufs_get_fs_qfmask(struct super_block *sb, struct ufs_super_block_third *usb3)
 {
-       u64 tmp;
+       __fs64 tmp;
 
        switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
        case UFS_ST_SUN:
-               ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qfmask[0];
-               ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qfmask[1];
+               ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qfmask[0];
+               ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qfmask[1];
                break;
        case UFS_ST_SUNx86:
-               ((u32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qfmask[0];
-               ((u32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qfmask[1];
+               ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qfmask[0];
+               ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qfmask[1];
                break;
        case UFS_ST_44BSD:
-               ((u32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qfmask[0];
-               ((u32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qfmask[1];
+               ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qfmask[0];
+               ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qfmask[1];
                break;
        }
 
@@ -273,11 +273,11 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head
        ((begin) & ~uspi->s_fmask))
 
 #define ubh_get_addr16(ubh,begin) \
-       (((u16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + \
+       (((__fs16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + \
        ((begin) & (uspi->fsize>>1) - 1)))
 
 #define ubh_get_addr32(ubh,begin) \
-       (((u32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
+       (((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
        ((begin) & ((uspi->s_fsize>>2) - 1)))
 
 #define ubh_get_addr ubh_get_addr8
@@ -315,10 +315,10 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head
  * Macros to access cylinder group array structures
  */
 #define ubh_cg_blktot(ucpi,cylno) \
-       (*((__u32*)ubh_get_addr(UCPI_UBH, (ucpi)->c_btotoff + ((cylno) << 2))))
+       (*((__fs32*)ubh_get_addr(UCPI_UBH, (ucpi)->c_btotoff + ((cylno) << 2))))
 
 #define ubh_cg_blks(ucpi,cylno,rpos) \
-       (*((__u16*)ubh_get_addr(UCPI_UBH, \
+       (*((__fs16*)ubh_get_addr(UCPI_UBH, \
        (ucpi)->c_boff + (((cylno) * uspi->s_nrpos + (rpos)) << 1 ))))
 
 /*
@@ -476,7 +476,7 @@ static inline void _ubh_setblock_(struct ufs_sb_private_info * uspi,
 }
 
 static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap,
-       unsigned * fraglist, int cnt)
+       __fs32 * fraglist, int cnt)
 {
        struct ufs_sb_private_info * uspi;
        unsigned fragsize, pos;
index 061c9bc..778feed 100644 (file)
@@ -312,11 +312,12 @@ out:
 /*
  * Update the disk with the inode content
  */
-void UMSDOS_write_inode (struct inode *inode, int wait)
+int UMSDOS_write_inode (struct inode *inode, int wait)
 {
        struct iattr newattrs;
+       int ret;
 
-       fat_write_inode (inode, wait);
+       ret = fat_write_inode (inode, wait);
        newattrs.ia_mtime = inode->i_mtime;
        newattrs.ia_atime = inode->i_atime;
        newattrs.ia_ctime = inode->i_ctime;
@@ -330,6 +331,7 @@ void UMSDOS_write_inode (struct inode *inode, int wait)
  * UMSDOS_notify_change (inode, &newattrs);
 
  * inode->i_state &= ~I_DIRTY; / * FIXME: this doesn't work.  We need to remove ourselves from list on dirty inodes. /mn/ */
+       return ret;
 }
 
 
index 85f78ea..eea6d3f 100644 (file)
@@ -73,33 +73,6 @@ static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
        return ret;
 }
 
-static inline unsigned char
-vfat_tolower(struct nls_table *t, unsigned char c)
-{
-       unsigned char nc = t->charset2lower[c];
-
-       return nc ? nc : c;
-}
-
-static inline unsigned char
-vfat_toupper(struct nls_table *t, unsigned char c)
-{
-       unsigned char nc = t->charset2upper[c];
-
-       return nc ? nc : c;
-}
-
-static inline int
-vfat_strnicmp(struct nls_table *t, const unsigned char *s1,
-                                       const unsigned char *s2, int len)
-{
-       while(len--)
-               if (vfat_tolower(t, *s1++) != vfat_tolower(t, *s2++))
-                       return 1;
-
-       return 0;
-}
-
 /* returns the length of a struct qstr, ignoring trailing dots */
 static unsigned int vfat_striptail_len(struct qstr *qstr)
 {
@@ -142,7 +115,7 @@ static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
 
        hash = init_name_hash();
        while (len--)
-               hash = partial_name_hash(vfat_tolower(t, *name++), hash);
+               hash = partial_name_hash(nls_tolower(t, *name++), hash);
        qstr->hash = end_name_hash(hash);
 
        return 0;
@@ -160,7 +133,7 @@ static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
        alen = vfat_striptail_len(a);
        blen = vfat_striptail_len(b);
        if (alen == blen) {
-               if (vfat_strnicmp(t, a->name, b->name, alen) == 0)
+               if (nls_strnicmp(t, a->name, b->name, alen) == 0)
                        return 0;
        }
        return 1;
@@ -341,7 +314,7 @@ static inline int to_shortname_char(struct nls_table *nls,
                        info->upper = 0;
                }
 
-               buf[0] = vfat_toupper(nls, buf[0]);
+               buf[0] = nls_toupper(nls, buf[0]);
                if (isalpha(buf[0])) {
                        if (buf[0] == prev)
                                info->lower = 0;
@@ -704,7 +677,8 @@ shortname:
        de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
        de->lcase = lcase;
        de->adate = de->cdate = de->date = 0;
-       de->ctime_ms = de->ctime = de->time = 0;
+       de->ctime = de->time = 0;
+       de->ctime_ms = 0;
        de->start = 0;
        de->starthi = 0;
        de->size = 0;
@@ -1073,8 +1047,8 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        if (is_dir) {
                int start = MSDOS_I(new_dir)->i_logstart;
-               dotdot_de->start = CT_LE_W(start);
-               dotdot_de->starthi = CT_LE_W(start>>16);
+               dotdot_de->start = cpu_to_le16(start);
+               dotdot_de->starthi = cpu_to_le16(start>>16);
                mark_buffer_dirty(dotdot_bh);
                old_dir->i_nlink--;
                if (new_inode) {
index 7122efd..29fc5b3 100644 (file)
@@ -234,6 +234,7 @@ xfs_map_at_offset(
        sector_shift = block_bits - BBSHIFT;
        bn = iomapp->iomap_bn >> sector_shift;
        bn += delta;
+       BUG_ON(!bn && !(iomapp->iomap_flags & IOMAP_REALTIME));
        ASSERT((bn << sector_shift) >= iomapp->iomap_bn);
 
        lock_buffer(bh);
@@ -264,7 +265,7 @@ xfs_probe_unwritten_page(
 
        page = find_trylock_page(mapping, index);
        if (!page)
-               return 0;
+               return NULL;
        if (PageWriteback(page))
                goto out;
 
@@ -549,19 +550,23 @@ enough:
 STATIC void
 xfs_submit_page(
        struct page             *page,
+       struct writeback_control *wbc,
        struct buffer_head      *bh_arr[],
-       int                     cnt)
+       int                     bh_count,
+       int                     probed_page,
+       int                     clear_dirty)
 {
        struct buffer_head      *bh;
        int                     i;
 
        BUG_ON(PageWriteback(page));
        set_page_writeback(page);
-       clear_page_dirty(page);
+       if (clear_dirty)
+               clear_page_dirty(page);
        unlock_page(page);
 
-       if (cnt) {
-               for (i = 0; i < cnt; i++) {
+       if (bh_count) {
+               for (i = 0; i < bh_count; i++) {
                        bh = bh_arr[i];
                        mark_buffer_async_write(bh);
                        if (buffer_unwritten(bh))
@@ -570,10 +575,15 @@ xfs_submit_page(
                        clear_buffer_dirty(bh);
                }
 
-               for (i = 0; i < cnt; i++)
+               for (i = 0; i < bh_count; i++)
                        submit_bh(WRITE, bh_arr[i]);
-       } else
+
+               if (probed_page && clear_dirty)
+                       wbc->nr_to_write--;     /* Wrote an "extra" page */
+       } else {
                end_page_writeback(page);
+               wbc->pages_skipped++;   /* We didn't write this page */
+       }
 }
 
 /*
@@ -608,11 +618,13 @@ xfs_convert_page(
        bh = head = page_buffers(page);
        do {
                offset = i << bbits;
+               if (offset >= end)
+                       break;
                if (!(PageUptodate(page) || buffer_uptodate(bh)))
                        continue;
                if (buffer_mapped(bh) && all_bh &&
-                   !buffer_unwritten(bh) && !buffer_delay(bh)) {
-                       if (startio && (offset < end)) {
+                   !(buffer_unwritten(bh) || buffer_delay(bh))) {
+                       if (startio) {
                                lock_buffer(bh);
                                bh_arr[index++] = bh;
                        }
@@ -640,7 +652,7 @@ xfs_convert_page(
                                ASSERT(private);
                        }
                }
-               if (startio && (offset < end)) {
+               if (startio) {
                        bh_arr[index++] = bh;
                } else {
                        set_buffer_dirty(bh);
@@ -650,8 +662,7 @@ xfs_convert_page(
        } while (i++, (bh = bh->b_this_page) != head);
 
        if (startio) {
-               wbc->nr_to_write--;
-               xfs_submit_page(page, bh_arr, index);
+               xfs_submit_page(page, wbc, bh_arr, index, 1, index == i);
        } else {
                unlock_page(page);
        }
@@ -863,7 +874,7 @@ xfs_page_state_convert(
                SetPageUptodate(page);
 
        if (startio)
-               xfs_submit_page(page, bh_arr, cnt);
+               xfs_submit_page(page, wbc, bh_arr, cnt, 0, 1);
 
        if (iomp) {
                tlast = (iomp->iomap_offset + iomp->iomap_bsize - 1) >>
@@ -938,9 +949,8 @@ linvfs_get_block_core(
 
                        bn = iomap.iomap_bn >> (inode->i_blkbits - BBSHIFT);
                        bn += delta;
-
+                       BUG_ON(!bn && !(iomap.iomap_flags & IOMAP_REALTIME));
                        bh_result->b_blocknr = bn;
-                       bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
                        set_buffer_mapped(bh_result);
                }
                if (create && (iomap.iomap_flags & IOMAP_UNWRITTEN)) {
@@ -965,21 +975,18 @@ linvfs_get_block_core(
        }
 
        if (iomap.iomap_flags & IOMAP_DELAY) {
-               if (unlikely(direct))
-                       BUG();
+               BUG_ON(direct);
                if (create) {
                        set_buffer_mapped(bh_result);
                        set_buffer_uptodate(bh_result);
                }
-               bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
                set_buffer_delay(bh_result);
        }
 
        if (blocks) {
-               loff_t iosize;
-               iosize = (iomap.iomap_bsize - iomap.iomap_delta);
-               bh_result->b_size =
-                   (ssize_t)min(iosize, (loff_t)(blocks << inode->i_blkbits));
+               bh_result->b_size = (ssize_t)min(
+                       (loff_t)(iomap.iomap_bsize - iomap.iomap_delta),
+                       (loff_t)(blocks << inode->i_blkbits));
        }
 
        return 0;
@@ -996,17 +1003,6 @@ linvfs_get_block(
                                        create, 0, BMAPI_WRITE);
 }
 
-STATIC int
-linvfs_get_block_sync(
-       struct inode            *inode,
-       sector_t                iblock,
-       struct buffer_head      *bh_result,
-       int                     create)
-{
-       return linvfs_get_block_core(inode, iblock, 0, bh_result,
-                                       create, 0, BMAPI_SYNC|BMAPI_WRITE);
-}
-
 STATIC int
 linvfs_get_blocks_direct(
        struct inode            *inode,
@@ -1038,7 +1034,7 @@ linvfs_direct_IO(
        if (error)
                return -error;
 
-       return blockdev_direct_IO_no_locking(rw, iocb, inode,
+       return blockdev_direct_IO_own_locking(rw, iocb, inode,
                iomap.iomap_target->pbr_bdev,
                iov, offset, nr_segs,
                linvfs_get_blocks_direct,
@@ -1185,7 +1181,7 @@ linvfs_writepage(
        return 0;
 
 out_fail:
-       set_page_dirty(page);
+       redirty_page_for_writepage(wbc, page);
        unlock_page(page);
        return 0;
 out_unlock:
@@ -1261,13 +1257,7 @@ linvfs_prepare_write(
        unsigned int            from,
        unsigned int            to)
 {
-       if (file && (file->f_flags & O_SYNC)) {
-               return block_prepare_write(page, from, to,
-                                               linvfs_get_block_sync);
-       } else {
-               return block_prepare_write(page, from, to,
-                                               linvfs_get_block);
-       }
+       return block_prepare_write(page, from, to, linvfs_get_block);
 }
 
 struct address_space_operations linvfs_aops = {
index ed8abf2..4c0a72c 100644 (file)
@@ -626,11 +626,8 @@ pagebuf_get(                               /* allocate a buffer            */
        pb = _pagebuf_find(target, ioff, isize, flags, new_pb);
        if (pb == new_pb) {
                error = _pagebuf_lookup_pages(pb, flags);
-               if (unlikely(error)) {
-                       printk(KERN_WARNING
-                              "pagebuf_get: failed to lookup pages\n");
+               if (error)
                        goto no_buffer;
-               }
        } else {
                pagebuf_deallocate(new_pb);
                if (unlikely(pb == NULL))
@@ -1484,6 +1481,7 @@ xfs_free_buftarg(
        xfs_flush_buftarg(btp, 1);
        if (external)
                xfs_blkdev_put(btp->pbr_bdev);
+       iput(btp->pbr_mapping->host);
        kmem_free(btp, sizeof(*btp));
 }
 
@@ -1497,7 +1495,7 @@ xfs_incore_relse(
        truncate_inode_pages(btp->pbr_mapping, 0LL);
 }
 
-void
+int
 xfs_setsize_buftarg(
        xfs_buftarg_t           *btp,
        unsigned int            blocksize,
@@ -1511,7 +1509,42 @@ xfs_setsize_buftarg(
                printk(KERN_WARNING
                        "XFS: Cannot set_blocksize to %u on device %s\n",
                        sectorsize, XFS_BUFTARG_NAME(btp));
+               return EINVAL;
        }
+       return 0;
+}
+
+STATIC int
+xfs_mapping_buftarg(
+       xfs_buftarg_t           *btp,
+       struct block_device     *bdev)
+{
+       struct backing_dev_info *bdi;
+       struct inode            *inode;
+       struct address_space    *mapping;
+       static struct address_space_operations mapping_aops = {
+               .sync_page = block_sync_page,
+       };
+
+       inode = new_inode(bdev->bd_inode->i_sb);
+       if (!inode) {
+               printk(KERN_WARNING
+                       "XFS: Cannot allocate mapping inode for device %s\n",
+                       XFS_BUFTARG_NAME(btp));
+               return ENOMEM;
+       }
+       inode->i_mode = S_IFBLK;
+       inode->i_bdev = bdev;
+       inode->i_rdev = bdev->bd_dev;
+       bdi = blk_get_backing_dev_info(bdev);
+       if (!bdi)
+               bdi = &default_backing_dev_info;
+       mapping = &inode->i_data;
+       mapping->a_ops = &mapping_aops;
+       mapping->backing_dev_info = bdi;
+       mapping_set_gfp_mask(mapping, GFP_KERNEL);
+       btp->pbr_mapping = mapping;
+       return 0;
 }
 
 xfs_buftarg_t *
@@ -1524,10 +1557,15 @@ xfs_alloc_buftarg(
 
        btp->pbr_dev =  bdev->bd_dev;
        btp->pbr_bdev = bdev;
-       btp->pbr_mapping = bdev->bd_inode->i_mapping;
-       xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, bdev_hardsect_size(bdev));
-
+       if (xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, bdev_hardsect_size(bdev)))
+               goto error;
+       if (xfs_mapping_buftarg(btp, bdev))
+               goto error;
        return btp;
+
+error:
+       kmem_free(btp, sizeof(*btp));
+       return NULL;
 }
 
 
index 7bebfd6..242ba07 100644 (file)
@@ -566,7 +566,7 @@ static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp)
 
 extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *);
 extern void xfs_free_buftarg(xfs_buftarg_t *, int);
-extern void xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
+extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
 extern void xfs_incore_relse(xfs_buftarg_t *, int, int);
 extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
 
index e8e02f5..910d5bc 100644 (file)
@@ -61,7 +61,7 @@ static struct vm_operations_struct linvfs_file_vm_ops;
 STATIC inline ssize_t
 __linvfs_read(
        struct kiocb            *iocb,
-       char __user             *buf,
+       char                    __user *buf,
        int                     ioflags,
        size_t                  count,
        loff_t                  pos)
@@ -83,7 +83,7 @@ __linvfs_read(
 STATIC ssize_t
 linvfs_read(
        struct kiocb            *iocb,
-       char __user             *buf,
+       char                    __user *buf,
        size_t                  count,
        loff_t                  pos)
 {
@@ -93,7 +93,7 @@ linvfs_read(
 STATIC ssize_t
 linvfs_read_invis(
        struct kiocb            *iocb,
-       char __user             *buf,
+       char                    __user *buf,
        size_t                  count,
        loff_t                  pos)
 {
@@ -104,29 +104,22 @@ linvfs_read_invis(
 STATIC inline ssize_t
 __linvfs_write(
        struct kiocb    *iocb,
-       const char      *buf,
+       const char      __user *buf,
        int             ioflags,
        size_t          count,
        loff_t          pos)
 {
-       struct iovec    iov = {(void *)buf, count};
+       struct iovec    iov = {(void __user *)buf, count};
        struct file     *file = iocb->ki_filp;
        struct inode    *inode = file->f_mapping->host;
        vnode_t         *vp = LINVFS_GET_VP(inode);
        ssize_t         rval;
 
        BUG_ON(iocb->ki_pos != pos);
-       if (unlikely(file->f_flags & O_DIRECT)) {
+       if (unlikely(file->f_flags & O_DIRECT))
                ioflags |= IO_ISDIRECT;
-               VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos,
-                               ioflags, NULL, rval);
-       } else {
-               down(&inode->i_sem);
-               VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos,
-                               ioflags, NULL, rval);
-               up(&inode->i_sem);
-       }
 
+       VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
        return rval;
 }
 
@@ -134,7 +127,7 @@ __linvfs_write(
 STATIC ssize_t
 linvfs_write(
        struct kiocb            *iocb,
-       const char __user       *buf,
+       const char              __user *buf,
        size_t                  count,
        loff_t                  pos)
 {
@@ -144,7 +137,7 @@ linvfs_write(
 STATIC ssize_t
 linvfs_write_invis(
        struct kiocb            *iocb,
-       const char __user       *buf,
+       const char              __user *buf,
        size_t                  count,
        loff_t                  pos)
 {
@@ -171,8 +164,6 @@ __linvfs_readv(
        if (unlikely(file->f_flags & O_DIRECT))
                ioflags |= IO_ISDIRECT;
        VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
-       if (rval == -EIOCBQUEUED)
-               rval = wait_on_sync_kiocb(&kiocb);
 
        *ppos = kiocb.ki_pos;
        return rval;
@@ -214,19 +205,10 @@ __linvfs_writev(
 
        init_sync_kiocb(&kiocb, file);
        kiocb.ki_pos = *ppos;
-       if (unlikely(file->f_flags & O_DIRECT)) {
+       if (unlikely(file->f_flags & O_DIRECT))
                ioflags |= IO_ISDIRECT;
-               VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos,
-                               ioflags, NULL, rval);
-       } else {
-               down(&inode->i_sem);
-               VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos,
-                               ioflags, NULL, rval);
-               up(&inode->i_sem);
-       }
 
-       if (rval == -EIOCBQUEUED)
-               rval = wait_on_sync_kiocb(&kiocb);
+       VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
 
        *ppos = kiocb.ki_pos;
        return rval;
@@ -427,6 +409,8 @@ linvfs_file_mmap(
        vma->vm_ops = &linvfs_file_vm_ops;
 
        VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
+       if (!error)
+               vn_revalidate(vp);      /* update Linux inode flags */
        return 0;
 }
 
@@ -442,7 +426,7 @@ linvfs_ioctl(
        vnode_t         *vp = LINVFS_GET_VP(inode);
 
        unlock_kernel();
-       VOP_IOCTL(vp, inode, filp, 0, cmd, arg, error);
+       VOP_IOCTL(vp, inode, filp, 0, cmd, (void __user *)arg, error);
        VMODIFY(vp);
        lock_kernel();
 
@@ -467,7 +451,7 @@ linvfs_ioctl_invis(
 
        unlock_kernel();
        ASSERT(vp);
-       VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, arg, error);
+       VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
        VMODIFY(vp);
        lock_kernel();
 
index cbcdec4..b9c4bbf 100644 (file)
@@ -63,6 +63,7 @@ xfs_param_t xfs_params = {
        .inherit_noatim = {     0,              1,              1       },
        .xfs_buf_timer  = {     100/2,          1*100,          30*100  },
        .xfs_buf_age    = {     1*100,          15*100,         7200*100},
+       .inherit_nosym  = {     0,              0,              1       },
 };
 
 /*
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
new file mode 100644 (file)
index 0000000..f375331
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2004 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <linux/config.h>
+#include <linux/compat.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/ioctl32.h>
+#include <linux/syscalls.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+
+#include "xfs_types.h"
+#include "xfs_fs.h"
+#include "xfs_dfrag.h"
+
+#if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
+#define BROKEN_X86_ALIGNMENT
+#else
+
+typedef struct xfs_fsop_bulkreq32 {
+       compat_uptr_t   lastip;         /* last inode # pointer         */
+       __s32           icount;         /* count of entries in buffer   */
+       compat_uptr_t   ubuffer;        /* user buffer for inode desc.  */
+       __s32           ocount;         /* output count pointer         */
+} xfs_fsop_bulkreq32_t;
+
+static int
+xfs_ioctl32_bulkstat(
+       unsigned int            fd,
+       unsigned int            cmd,
+       unsigned long           arg,
+       struct file *           file)
+{
+       xfs_fsop_bulkreq32_t    __user *p32 = (void __user *)arg;
+       xfs_fsop_bulkreq_t      __user *p = compat_alloc_user_space(sizeof(*p));
+       u32                     addr;
+
+       if (get_user(addr, &p32->lastip) ||
+           put_user(compat_ptr(addr), &p->lastip) ||
+           copy_in_user(&p->icount, &p32->icount, sizeof(s32)) ||
+           get_user(addr, &p32->ubuffer) ||
+           put_user(compat_ptr(addr), &p->ubuffer) ||
+           get_user(addr, &p32->ocount) ||
+           put_user(compat_ptr(addr), &p->ocount))
+               return -EFAULT;
+
+       return sys_ioctl(fd, cmd, (unsigned long)p);
+}
+#endif
+
+struct ioctl_trans xfs_ioctl32_trans[] = {
+       { XFS_IOC_DIOINFO, },
+       { XFS_IOC_FSGEOMETRY_V1, },
+       { XFS_IOC_FSGEOMETRY, },
+       { XFS_IOC_GETVERSION, },
+       { XFS_IOC_GETXFLAGS, },
+       { XFS_IOC_SETXFLAGS, },
+       { XFS_IOC_FSGETXATTR, },
+       { XFS_IOC_FSSETXATTR, },
+       { XFS_IOC_FSGETXATTRA, },
+       { XFS_IOC_FSSETDM, },
+       { XFS_IOC_GETBMAP, },
+       { XFS_IOC_GETBMAPA, },
+       { XFS_IOC_GETBMAPX, },
+/* not handled
+       { XFS_IOC_FD_TO_HANDLE, },
+       { XFS_IOC_PATH_TO_HANDLE, },
+       { XFS_IOC_PATH_TO_HANDLE, },
+       { XFS_IOC_PATH_TO_FSHANDLE, },
+       { XFS_IOC_OPEN_BY_HANDLE, },
+       { XFS_IOC_FSSETDM_BY_HANDLE, },
+       { XFS_IOC_READLINK_BY_HANDLE, },
+       { XFS_IOC_ATTRLIST_BY_HANDLE, },
+       { XFS_IOC_ATTRMULTI_BY_HANDLE, },
+*/
+       { XFS_IOC_FSCOUNTS, NULL, },
+       { XFS_IOC_SET_RESBLKS, NULL, },
+       { XFS_IOC_GET_RESBLKS, NULL, },
+       { XFS_IOC_FSGROWFSDATA, NULL, },
+       { XFS_IOC_FSGROWFSLOG, NULL, },
+       { XFS_IOC_FSGROWFSRT, NULL, },
+       { XFS_IOC_FREEZE, NULL, },
+       { XFS_IOC_THAW, NULL, },
+       { XFS_IOC_GOINGDOWN, NULL, },
+       { XFS_IOC_ERROR_INJECTION, NULL, },
+       { XFS_IOC_ERROR_CLEARALL, NULL, },
+#ifndef BROKEN_X86_ALIGNMENT
+       /* xfs_flock_t and xfs_bstat_t have wrong u32 vs u64 alignment */
+       { XFS_IOC_ALLOCSP, },
+       { XFS_IOC_FREESP, },
+       { XFS_IOC_RESVSP, },
+       { XFS_IOC_UNRESVSP, },
+       { XFS_IOC_ALLOCSP64, },
+       { XFS_IOC_FREESP64, },
+       { XFS_IOC_RESVSP64, },
+       { XFS_IOC_UNRESVSP64, },
+       { XFS_IOC_SWAPEXT, },
+       { XFS_IOC_FSBULKSTAT_SINGLE, xfs_ioctl32_bulkstat },
+       { XFS_IOC_FSBULKSTAT, xfs_ioctl32_bulkstat},
+       { XFS_IOC_FSINUMBERS, xfs_ioctl32_bulkstat},
+#endif
+       { 0, },
+};
+
+int __init
+xfs_ioctl32_init(void)
+{
+       int error, i;
+
+       for (i = 0; xfs_ioctl32_trans[i].cmd != 0; i++) {
+               error = register_ioctl32_conversion(xfs_ioctl32_trans[i].cmd,
+                               xfs_ioctl32_trans[i].handler);
+               if (error)
+                       goto fail;
+       }
+
+       return 0;
+
+ fail:
+       while (--i)
+               unregister_ioctl32_conversion(xfs_ioctl32_trans[i].cmd);
+       return error;
+}
+
+void
+xfs_ioctl32_exit(void)
+{
+       int i;
+
+       for (i = 0; xfs_ioctl32_trans[i].cmd != 0; i++)
+               unregister_ioctl32_conversion(xfs_ioctl32_trans[i].cmd);
+}
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h
new file mode 100644 (file)
index 0000000..0e24f08
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2004 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_COMPAT
+extern int xfs_ioctl32_init(void);
+extern void xfs_ioctl32_exit(void);
+#else
+static inline int xfs_ioctl32_init(void) { return 0; }
+static inline void xfs_ioctl32_exit(void) { }
+#endif
index f0f5c87..6a69a62 100644 (file)
@@ -46,6 +46,6 @@ extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int)
 extern void linvfs_unwritten_done(struct buffer_head *, int);
 
 extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
-                        int, unsigned int, unsigned long);
+                        int, unsigned int, void __user *);
 
 #endif /* __XFS_IOPS_H__ */
index ecaa3c0..bbf4ef4 100644 (file)
@@ -85,6 +85,7 @@
 #include <linux/vfs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <linux/proc_fs.h>
 #include <linux/version.h>
 
@@ -140,6 +141,7 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
 #define xfs_inherit_noatime    xfs_params.inherit_noatim.val
 #define xfs_buf_timer_centisecs        xfs_params.xfs_buf_timer.val
 #define xfs_buf_age_centisecs  xfs_params.xfs_buf_age.val
+#define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val
 
 #define current_cpu()          smp_processor_id()
 #define current_pid()          (current->pid)
index c45e963..903e60e 100644 (file)
@@ -74,6 +74,7 @@
 #include "xfs_iomap.h"
 
 #include <linux/capability.h>
+#include <linux/writeback.h>
 
 
 #if defined(XFS_RW_TRACE)
@@ -81,7 +82,7 @@ void
 xfs_rw_enter_trace(
        int                     tag,
        xfs_iocore_t            *io,
-       const struct iovec      *iovp,
+       void                    *data,
        size_t                  segs,
        loff_t                  offset,
        int                     ioflags)
@@ -95,7 +96,7 @@ xfs_rw_enter_trace(
                (void *)ip,
                (void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
                (void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
-               (void *)(__psint_t)iovp,
+               (void *)data,
                (void *)((unsigned long)segs),
                (void *)((unsigned long)((offset >> 32) & 0xffffffff)),
                (void *)((unsigned long)(offset & 0xffffffff)),
@@ -225,40 +226,11 @@ xfs_inval_cached_pages(
        int             write,
        int             relock)
 {
-       xfs_mount_t     *mp;
-
-       if (!VN_CACHED(vp)) {
-               return;
-       }
-
-       mp = io->io_mount;
-
-       /*
-        * We need to get the I/O lock exclusively in order
-        * to safely invalidate pages and mappings.
-        */
-       if (relock) {
-               XFS_IUNLOCK(mp, io, XFS_IOLOCK_SHARED);
-               XFS_ILOCK(mp, io, XFS_IOLOCK_EXCL);
-       }
-
-       /* Writing beyond EOF creates a hole that must be zeroed */
-       if (write && (offset > XFS_SIZE(mp, io))) {
-               xfs_fsize_t     isize;
-
-               XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
-               isize = XFS_SIZE(mp, io);
-               if (offset > isize) {
-                       xfs_zero_eof(vp, io, offset, isize, offset);
-               }
-               XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+       if (VN_CACHED(vp)) {
+               xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
+               VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
        }
 
-       xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
-       VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
-       if (relock) {
-               XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL);
-       }
 }
 
 ssize_t                        /* bytes read, or (-)  error */
@@ -324,11 +296,6 @@ xfs_read(
                return -EIO;
        }
 
-       /* OK so we are holding the I/O lock for the duration
-        * of the submission, then what happens if the I/O
-        * does not really happen here, but is scheduled 
-        * later?
-        */
        xfs_ilock(ip, XFS_IOLOCK_SHARED);
 
        if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
@@ -345,8 +312,11 @@ xfs_read(
        }
 
        xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
-                               iovp, segs, *offset, ioflags);
+                               (void *)iovp, segs, *offset, ioflags);
        ret = __generic_file_aio_read(iocb, iovp, segs, offset);
+       if (ret == -EIOCBQUEUED)
+               ret = wait_on_sync_kiocb(iocb);
+
        xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 
        if (ret > 0)
@@ -406,12 +376,17 @@ xfs_sendfile(
                }
        }
        xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
-                               target, count, *offset, ioflags);
+                  (void *)(unsigned long)target, count, *offset, ioflags);
        ret = generic_file_sendfile(filp, offset, count, actor, target);
+
        xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 
-       XFS_STATS_ADD(xs_read_bytes, ret);
-       xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
+       if (ret > 0)
+               XFS_STATS_ADD(xs_read_bytes, ret);
+
+       if (likely(!(ioflags & IO_INVIS)))
+               xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
+
        return ret;
 }
 
@@ -637,32 +612,34 @@ xfs_write(
        bhv_desc_t              *bdp,
        struct kiocb            *iocb,
        const struct iovec      *iovp,
-       unsigned int            segs,
+       unsigned int            nsegs,
        loff_t                  *offset,
        int                     ioflags,
        cred_t                  *credp)
 {
        struct file             *file = iocb->ki_filp;
-       size_t                  size = 0;
+       struct address_space    *mapping = file->f_mapping;
+       struct inode            *inode = mapping->host;
+       unsigned long           segs = nsegs;
        xfs_inode_t             *xip;
        xfs_mount_t             *mp;
-       ssize_t                 ret;
-       int                     error = 0;
+       ssize_t                 ret = 0, error = 0;
        xfs_fsize_t             isize, new_size;
-       xfs_fsize_t             n, limit;
        xfs_iocore_t            *io;
        vnode_t                 *vp;
        unsigned long           seg;
        int                     iolock;
        int                     eventsent = 0;
        vrwlock_t               locktype;
+       size_t                  ocount = 0, count;
+       loff_t                  pos;
+       int                     need_isem = 1, need_flush = 0;
 
        XFS_STATS_INC(xs_write_calls);
 
        vp = BHV_TO_VNODE(bdp);
        xip = XFS_BHVTOI(bdp);
 
-       /* START copy & waste from filemap.c */
        for (seg = 0; seg < segs; seg++) {
                const struct iovec *iv = &iovp[seg];
 
@@ -670,73 +647,90 @@ xfs_write(
                 * If any segment has a negative length, or the cumulative
                 * length ever wraps negative then return -EINVAL.
                 */
-               size += iv->iov_len;
-               if (unlikely((ssize_t)(size|iv->iov_len) < 0))
-                       return XFS_ERROR(-EINVAL);
+               ocount += iv->iov_len;
+               if (unlikely((ssize_t)(ocount|iv->iov_len) < 0))
+                       return -EINVAL;
+               if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
+                       continue;
+               if (seg == 0)
+                       return -EFAULT;
+               segs = seg;
+               ocount -= iv->iov_len;  /* This segment is no good */
+               break;
        }
-       /* END copy & waste from filemap.c */
 
-       if (size == 0)
+       count = ocount;
+       pos = *offset;
+
+       if (count == 0)
                return 0;
 
        io = &xip->i_iocore;
        mp = io->io_mount;
 
-       if (XFS_FORCED_SHUTDOWN(mp)) {
+       if (XFS_FORCED_SHUTDOWN(mp))
                return -EIO;
-       }
 
        if (ioflags & IO_ISDIRECT) {
                xfs_buftarg_t   *target =
                        (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
                                mp->m_rtdev_targp : mp->m_ddev_targp;
 
-               if ((*offset & target->pbr_smask) ||
-                   (size & target->pbr_smask)) {
+               if ((pos & target->pbr_smask) || (count & target->pbr_smask))
                        return XFS_ERROR(-EINVAL);
-               }
-               iolock = XFS_IOLOCK_SHARED;
-               locktype = VRWLOCK_WRITE_DIRECT;
-       } else {
+
+               if (!VN_CACHED(vp) && pos < i_size_read(inode))
+                       need_isem = 0;
+
+               if (VN_CACHED(vp))
+                       need_flush = 1;
+       }
+
+relock:
+       if (need_isem) {
                iolock = XFS_IOLOCK_EXCL;
                locktype = VRWLOCK_WRITE;
+
+               down(&inode->i_sem);
+       } else {
+               iolock = XFS_IOLOCK_SHARED;
+               locktype = VRWLOCK_WRITE_DIRECT;
        }
 
        xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
 
-       isize = xip->i_d.di_size;
-       limit = XFS_MAXIOFFSET(mp);
+       isize = i_size_read(inode);
 
        if (file->f_flags & O_APPEND)
                *offset = isize;
 
 start:
-       n = limit - *offset;
-       if (n <= 0) {
+       error = -generic_write_checks(file, &pos, &count,
+                                       S_ISBLK(inode->i_mode));
+       if (error) {
                xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
-               return -EFBIG;
+               goto out_unlock_isem;
        }
 
-       if (n < size)
-               size = n;
-
-       new_size = *offset + size;
-       if (new_size > isize) {
+       new_size = pos + count;
+       if (new_size > isize)
                io->io_new_size = new_size;
-       }
 
        if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
            !(ioflags & IO_INVIS) && !eventsent)) {
-               loff_t          savedsize = *offset;
-               int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
+               loff_t          savedsize = pos;
+               int             dmflags = FILP_DELAY_FLAG(file);
+
+               if (need_isem)
+                       dmflags |= DM_FLAGS_ISEM;
 
                xfs_iunlock(xip, XFS_ILOCK_EXCL);
                error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
-                                     *offset, size,
+                                     pos, count,
                                      dmflags, &locktype);
                if (error) {
                        xfs_iunlock(xip, iolock);
-                       return -error;
+                       goto out_unlock_isem;
                }
                xfs_ilock(xip, XFS_ILOCK_EXCL);
                eventsent = 1;
@@ -748,9 +742,8 @@ start:
                 * event prevents another call to XFS_SEND_DATA, which is
                 * what allows the size to change in the first place.
                 */
-               if ((file->f_flags & O_APPEND) &&
-                   savedsize != xip->i_d.di_size) {
-                       *offset = isize = xip->i_d.di_size;
+               if ((file->f_flags & O_APPEND) && savedsize != isize) {
+                       pos = isize = xip->i_d.di_size;
                        goto start;
                }
        }
@@ -761,8 +754,10 @@ start:
         *
         * We must update xfs' times since revalidate will overcopy xfs.
         */
-       if (size && !(ioflags & IO_INVIS))
+       if (!(ioflags & IO_INVIS)) {
                xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+               inode_update_time(inode, 1);
+       }
 
        /*
         * If the offset is beyond the size of the file, we have a couple
@@ -773,12 +768,12 @@ start:
         * to zero it out up to the new size.
         */
 
-       if (!(ioflags & IO_ISDIRECT) && (*offset > isize && isize)) {
-               error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, *offset,
-                       isize, *offset + size);
+       if (pos > isize) {
+               error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos,
+                                       isize, pos + count);
                if (error) {
                        xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
-                       return(-error);
+                       goto out_unlock_isem;
                }
        }
        xfs_iunlock(xip, XFS_ILOCK_EXCL);
@@ -795,22 +790,67 @@ start:
                (S_ISGID | S_IXGRP))) &&
             !capable(CAP_FSETID)) {
                error = xfs_write_clear_setuid(xip);
-               if (error) {
+               if (likely(!error))
+                       error = -remove_suid(file->f_dentry);
+               if (unlikely(error)) {
                        xfs_iunlock(xip, iolock);
-                       return -error;
+                       goto out_unlock_isem;
                }
        }
 
 retry:
-       if (ioflags & IO_ISDIRECT) {
-               xfs_inval_cached_pages(vp, io, *offset, 1, 1);
-               xfs_rw_enter_trace(XFS_DIOWR_ENTER,
-                               io, iovp, segs, *offset, ioflags);
+       /* We can write back this queue in page reclaim */
+       current->backing_dev_info = mapping->backing_dev_info;
+
+       if ((ioflags & IO_ISDIRECT)) {
+               if (need_flush) {
+                       xfs_inval_cached_trace(io, pos, -1,
+                                       ctooff(offtoct(pos)), -1);
+                       VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(pos)),
+                                       -1, FI_REMAPF_LOCKED);
+               }
+
+               if (need_isem) {
+                       /* demote the lock now the cached pages are gone */
+                       XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL);
+                       up(&inode->i_sem);
+
+                       iolock = XFS_IOLOCK_SHARED;
+                       locktype = VRWLOCK_WRITE_DIRECT;
+                       need_isem = 0;
+               }
+
+               xfs_rw_enter_trace(XFS_DIOWR_ENTER, io, (void *)iovp, segs,
+                               *offset, ioflags);
+               ret = generic_file_direct_write(iocb, iovp,
+                               &segs, pos, offset, count, ocount);
+
+               /*
+                * direct-io write to a hole: fall through to buffered I/O
+                * for completing the rest of the request.
+                */
+               if (ret >= 0 && ret != count) {
+                       XFS_STATS_ADD(xs_write_bytes, ret);
+
+                       pos += ret;
+                       count -= ret;
+
+                       need_isem = 1;
+                       ioflags &= ~IO_ISDIRECT;
+                       xfs_iunlock(xip, iolock);
+                       goto relock;
+               }
        } else {
-               xfs_rw_enter_trace(XFS_WRITE_ENTER,
-                               io, iovp, segs, *offset, ioflags);
+               xfs_rw_enter_trace(XFS_WRITE_ENTER, io, (void *)iovp, segs,
+                               *offset, ioflags);
+               ret = generic_file_buffered_write(iocb, iovp, segs,
+                               pos, offset, count, ret);
        }
-       ret = generic_file_aio_write_nolock(iocb, iovp, segs, offset);
+
+       current->backing_dev_info = NULL;
+
+       if (ret == -EIOCBQUEUED)
+               ret = wait_on_sync_kiocb(iocb);
 
        if ((ret == -ENOSPC) &&
            DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) &&
@@ -821,17 +861,15 @@ retry:
                                DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
                                0, 0, 0); /* Delay flag intentionally  unused */
                if (error)
-                       return -error;
+                       goto out_unlock_isem;
                xfs_rwlock(bdp, locktype);
-               *offset = xip->i_d.di_size;
+               pos = xip->i_d.di_size;
                goto retry;
        }
 
        if (*offset > xip->i_d.di_size) {
                xfs_ilock(xip, XFS_ILOCK_EXCL);
                if (*offset > xip->i_d.di_size) {
-                       struct inode    *inode = LINVFS_GET_IP(vp);
-
                        xip->i_d.di_size = *offset;
                        i_size_write(inode, *offset);
                        xip->i_update_core = 1;
@@ -840,23 +878,22 @@ retry:
                xfs_iunlock(xip, XFS_ILOCK_EXCL);
        }
 
-       if (ret <= 0) {
-               xfs_rwunlock(bdp, locktype);
-               return ret;
-       }
+       error = -ret;
+       if (ret <= 0)
+               goto out_unlock_internal;
 
        XFS_STATS_ADD(xs_write_bytes, ret);
 
        /* Handle various SYNC-type writes */
-       if ((file->f_flags & O_SYNC) || IS_SYNC(file->f_dentry->d_inode)) {
-
+       if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
                /*
                 * If we're treating this as O_DSYNC and we have not updated the
                 * size, force the log.
                 */
+               if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) &&
+                   !(xip->i_update_size)) {
+                       xfs_inode_log_item_t    *iip = xip->i_itemp;
 
-               if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC)
-                       && !(xip->i_update_size)) {
                        /*
                         * If an allocation transaction occurred
                         * without extending the size, then we have to force
@@ -876,14 +913,8 @@ retry:
                         * all changes affecting the inode are permanent
                         * when we return.
                         */
-
-                       xfs_inode_log_item_t *iip;
-                       xfs_lsn_t lsn;
-
-                       iip = xip->i_itemp;
                        if (iip && iip->ili_last_lsn) {
-                               lsn = iip->ili_last_lsn;
-                               xfs_log_force(mp, lsn,
+                               xfs_log_force(mp, iip->ili_last_lsn,
                                                XFS_LOG_FORCE | XFS_LOG_SYNC);
                        } else if (xfs_ipincount(xip) > 0) {
                                xfs_log_force(mp, (xfs_lsn_t)0,
@@ -924,12 +955,27 @@ retry:
                                xfs_trans_set_sync(tp);
                                error = xfs_trans_commit(tp, 0, NULL);
                                xfs_iunlock(xip, XFS_ILOCK_EXCL);
+                               if (error)
+                                       goto out_unlock_internal;
                        }
                }
-       } /* (ioflags & O_SYNC) */
+       
+               xfs_rwunlock(bdp, locktype);
+               if (need_isem)
+                       up(&inode->i_sem);
+
+               error = sync_page_range(inode, mapping, pos, ret);
+               if (!error)
+                       error = ret;
+               return error;
+       }
 
+ out_unlock_internal:
        xfs_rwunlock(bdp, locktype);
-       return(ret);
+ out_unlock_isem:
+       if (need_isem)
+               up(&inode->i_sem);
+       return -error;
 }
 
 /*
index faf0afc..d723e35 100644 (file)
@@ -74,11 +74,11 @@ struct xfs_iomap;
 #define        XFS_IOMAP_ALLOC_MAP     25
 #define        XFS_IOMAP_UNWRITTEN     26
 extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
-                       const struct iovec *, size_t, loff_t, int);
+                               void *, size_t, loff_t, int);
 extern void xfs_inval_cached_trace(struct xfs_iocore *,
-                       xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);
+                               xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);
 #else
-#define xfs_rw_enter_trace(tag, io, iovec, segs, offset, ioflags)
+#define xfs_rw_enter_trace(tag, io, data, size, offset, ioflags)
 #define xfs_inval_cached_trace(io, offset, len, first, last)
 #endif
 
index 86b633e..aaf5ddb 100644 (file)
@@ -119,9 +119,9 @@ xfs_read_xfsstats(
 void
 xfs_init_procfs(void)
 {
-       if (!proc_mkdir("fs/xfs", 0))
+       if (!proc_mkdir("fs/xfs", NULL))
                return;
-       create_proc_read_entry("fs/xfs/stat", 0, 0, xfs_read_xfsstats, NULL);
+       create_proc_read_entry("fs/xfs/stat", 0, NULL, xfs_read_xfsstats, NULL);
 }
 
 void
index 4a173d3..c245296 100644 (file)
@@ -45,7 +45,7 @@ xfs_stats_clear_proc_handler(
        ctl_table       *ctl,
        int             write,
        struct file     *filp,
-       void            *buffer,
+       void            __user *buffer,
        size_t          *lenp,
        loff_t          *ppos)
 {
@@ -129,6 +129,11 @@ STATIC ctl_table xfs_table[] = {
        &sysctl_intvec, NULL,
        &xfs_params.xfs_buf_age.min, &xfs_params.xfs_buf_age.max},
 
+       {XFS_INHERIT_NOSYM, "inherit_nosymlinks", &xfs_params.inherit_nosym.val,
+       sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+       &sysctl_intvec, NULL,
+       &xfs_params.inherit_nosym.min, &xfs_params.inherit_nosym.max},
+
        /* please keep this the last entry */
 #ifdef CONFIG_PROC_FS
        {XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val,
index 872014b..5ff61bb 100644 (file)
@@ -59,6 +59,7 @@ typedef struct xfs_param {
        xfs_sysctl_val_t inherit_noatim;/* Inherit the "noatime" inode flag. */
        xfs_sysctl_val_t xfs_buf_timer; /* Interval between xfsbufd wakeups. */
        xfs_sysctl_val_t xfs_buf_age;   /* Metadata buffer age before flush. */
+       xfs_sysctl_val_t inherit_nosym; /* Inherit the "nosymlinks" flag. */
 } xfs_param_t;
 
 /*
@@ -95,6 +96,7 @@ enum {
        XFS_BUF_TIMER = 16,
        XFS_BUF_AGE = 17,
        /* XFS_IO_BYPASS = 18 */
+       XFS_INHERIT_NOSYM = 19,
 };
 
 extern xfs_param_t     xfs_params;
index 897b9dc..855e914 100644 (file)
@@ -249,6 +249,8 @@ vfs_allocate( void )
 
        vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP);
        bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
+       INIT_LIST_HEAD(&vfsp->vfs_sync_list);
+       vfsp->vfs_sync_lock = SPIN_LOCK_UNLOCKED;
        init_waitqueue_head(&vfsp->vfs_wait_sync_task);
        init_waitqueue_head(&vfsp->vfs_wait_single_sync_task);
        return vfsp;
index 3c7ca84..aab7013 100644 (file)
@@ -36,6 +36,7 @@
 #include "xfs_fs.h"
 
 struct fid;
+struct vfs;
 struct cred;
 struct vnode;
 struct kstatfs;
@@ -45,14 +46,24 @@ struct xfs_mount_args;
 
 typedef struct kstatfs xfs_statfs_t;
 
+typedef struct vfs_sync_work {
+       struct list_head        w_list;
+       struct vfs              *w_vfs;
+       void                    *w_data;        /* syncer routine argument */
+       void                    (*w_syncer)(struct vfs *, void *);
+} vfs_sync_work_t;
+
 typedef struct vfs {
        u_int                   vfs_flag;       /* flags */
        xfs_fsid_t              vfs_fsid;       /* file system ID */
        xfs_fsid_t              *vfs_altfsid;   /* An ID fixed for life of FS */
        bhv_head_t              vfs_bh;         /* head of vfs behavior chain */
-       struct super_block      *vfs_super;     /* Linux superblock structure */
-       struct task_struct      *vfs_sync_task; /* xfssyncd process */
-       int                     vfs_sync_seq;   /* xfssyncd generation number */
+       struct super_block      *vfs_super;     /* generic superblock pointer */
+       struct task_struct      *vfs_sync_task; /* generalised sync thread */
+       vfs_sync_work_t         vfs_sync_work;  /* work item for VFS_SYNC */
+       struct list_head        vfs_sync_list;  /* sync thread work item list */
+       spinlock_t              vfs_sync_lock;  /* work item list lock */
+       int                     vfs_sync_seq;   /* sync thread generation no. */
        wait_queue_head_t       vfs_wait_single_sync_task;
        wait_queue_head_t       vfs_wait_sync_task;
 } vfs_t;
@@ -205,4 +216,8 @@ extern void bhv_insert_all_vfsops(struct vfs *);
 extern void bhv_remove_all_vfsops(struct vfs *, int);
 extern void bhv_remove_vfsops(struct vfs *, int);
 
+#define fs_frozen(vfsp)                ((vfsp)->vfs_super->s_frozen)
+#define fs_check_frozen(vfsp, level) \
+       vfs_check_frozen(vfsp->vfs_super, level);
+
 #endif /* __XFS_VFS_H__ */
index af0b65f..3466465 100644 (file)
@@ -194,7 +194,7 @@ typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
                                loff_t *, int, size_t, read_actor_t,
                                void *, struct cred *);
 typedef int    (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
-                               int, unsigned int, unsigned long);
+                               int, unsigned int, void __user *);
 typedef int    (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int,
                                struct cred *);
 typedef int    (*vop_setattr_t)(bhv_desc_t *, struct vattr *, int,
@@ -532,6 +532,7 @@ typedef struct vnode_map {
 extern void    vn_purge(struct vnode *, vmap_t *);
 extern vnode_t *vn_get(struct vnode *, vmap_t *);
 extern int     vn_revalidate(struct vnode *);
+extern void    vn_revalidate_core(struct vnode *, vattr_t *);
 extern void    vn_remove(struct vnode *);
 
 static inline int vn_count(struct vnode *vp)
@@ -593,6 +594,19 @@ static __inline__ void vn_flagclr(struct vnode *vp, uint flag)
 #define VN_ATIMESET(vp, tvp)   (LINVFS_GET_IP(vp)->i_atime = *(tvp))
 #define VN_CTIMESET(vp, tvp)   (LINVFS_GET_IP(vp)->i_ctime = *(tvp))
 
+/*
+ * Dealing with bad inodes
+ */
+static inline void vn_mark_bad(struct vnode *vp)
+{
+       make_bad_inode(LINVFS_GET_IP(vp));
+}
+
+static inline int VN_BAD(struct vnode *vp)
+{
+       return is_bad_inode(LINVFS_GET_IP(vp));
+}
+
 /*
  * Some useful predicates.
  */
index d1368c9..fbfb24c 100644 (file)
@@ -145,7 +145,7 @@ xfs_qm_dqinit(
                 dqp->q_res_icount = 0;
                 dqp->q_res_rtbcount = 0;
                 dqp->q_pincount = 0;
-                dqp->q_hash = 0;
+                dqp->q_hash = NULL;
                 ASSERT(dqp->dq_flnext == dqp->dq_flprev);
 
 #ifdef XFS_DQUOT_TRACE
@@ -187,9 +187,9 @@ xfs_qm_dqdestroy(
  */
 STATIC void
 xfs_qm_dqinit_core(
-       xfs_dqid_t       id,
-       uint             type,
-       xfs_dqblk_t      *d)
+       xfs_dqid_t      id,
+       uint            type,
+       xfs_dqblk_t     *d)
 {
        /*
         * Caller has zero'd the entire dquot 'chunk' already.
@@ -249,6 +249,36 @@ __xfs_dqtrace_entry(
 #endif
 
 
+/*
+ * If default limits are in force, push them into the dquot now.
+ * We overwrite the dquot limits only if they are zero and this
+ * is not the root dquot.
+ */
+void
+xfs_qm_adjust_dqlimits(
+       xfs_mount_t             *mp,
+       xfs_disk_dquot_t        *d)
+{
+       xfs_quotainfo_t         *q = mp->m_quotainfo;
+
+       ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
+
+       if (q->qi_bsoftlimit && INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT))
+               INT_SET(d->d_blk_softlimit, ARCH_CONVERT, q->qi_bsoftlimit);
+       if (q->qi_bhardlimit && INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT))
+               INT_SET(d->d_blk_hardlimit, ARCH_CONVERT, q->qi_bhardlimit);
+       if (q->qi_isoftlimit && INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT))
+               INT_SET(d->d_ino_softlimit, ARCH_CONVERT, q->qi_isoftlimit);
+       if (q->qi_ihardlimit && INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT))
+               INT_SET(d->d_ino_hardlimit, ARCH_CONVERT, q->qi_ihardlimit);
+       if (q->qi_rtbsoftlimit &&
+           INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT))
+               INT_SET(d->d_rtb_softlimit, ARCH_CONVERT, q->qi_rtbsoftlimit);
+       if (q->qi_rtbhardlimit &&
+           INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT))
+               INT_SET(d->d_rtb_hardlimit, ARCH_CONVERT, q->qi_rtbhardlimit);
+}
+
 /*
  * Check the limits and timers of a dquot and start or reset timers
  * if necessary.
@@ -265,53 +295,81 @@ xfs_qm_adjust_dqtimers(
        xfs_mount_t             *mp,
        xfs_disk_dquot_t        *d)
 {
-       /*
-        * The dquot had better be locked. We are modifying it here.
-        */
-
-       /*
-        * root's limits are not real limits.
-        */
-       if (INT_ISZERO(d->d_id, ARCH_CONVERT))
-               return;
+       ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
 
 #ifdef QUOTADEBUG
        if (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT))
-               ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT));
+               ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <=
+                       INT_GET(d->d_blk_hardlimit, ARCH_CONVERT));
        if (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT))
-               ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT));
+               ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <=
+                       INT_GET(d->d_ino_hardlimit, ARCH_CONVERT));
+       if (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT))
+               ASSERT(INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) <=
+                       INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT));
 #endif
        if (INT_ISZERO(d->d_btimer, ARCH_CONVERT)) {
                if ((INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
-                   (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
+                   (INT_GET(d->d_bcount, ARCH_CONVERT) >=
+                               INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
                    (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT) &&
-                   (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
-                       INT_SET(d->d_btimer, ARCH_CONVERT, get_seconds() + XFS_QI_BTIMELIMIT(mp));
+                   (INT_GET(d->d_bcount, ARCH_CONVERT) >=
+                               INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
+                       INT_SET(d->d_btimer, ARCH_CONVERT,
+                               get_seconds() + XFS_QI_BTIMELIMIT(mp));
                }
        } else {
                if ((INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
-                   (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
+                   (INT_GET(d->d_bcount, ARCH_CONVERT) <
+                               INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
                    (INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT) ||
-                   (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
+                   (INT_GET(d->d_bcount, ARCH_CONVERT) <
+                               INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
                        INT_ZERO(d->d_btimer, ARCH_CONVERT);
                }
        }
 
        if (INT_ISZERO(d->d_itimer, ARCH_CONVERT)) {
                if ((INT_GET(d->d_ino_softlimit, ARCH_CONVERT) &&
-                   (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
+                   (INT_GET(d->d_icount, ARCH_CONVERT) >=
+                               INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
                    (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT) &&
-                   (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
-                       INT_SET(d->d_itimer, ARCH_CONVERT, get_seconds() + XFS_QI_ITIMELIMIT(mp));
+                   (INT_GET(d->d_icount, ARCH_CONVERT) >=
+                               INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
+                       INT_SET(d->d_itimer, ARCH_CONVERT,
+                               get_seconds() + XFS_QI_ITIMELIMIT(mp));
                }
        } else {
                if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT) ||
-                   (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_softlimit, ARCH_CONVERT)))  &&
+                   (INT_GET(d->d_icount, ARCH_CONVERT) <
+                               INT_GET(d->d_ino_softlimit, ARCH_CONVERT)))  &&
                    (INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT) ||
-                   (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
+                   (INT_GET(d->d_icount, ARCH_CONVERT) <
+                               INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
                        INT_ZERO(d->d_itimer, ARCH_CONVERT);
                }
        }
+
+       if (INT_ISZERO(d->d_rtbtimer, ARCH_CONVERT)) {
+               if ((INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) &&
+                   (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
+                               INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) ||
+                   (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT) &&
+                   (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
+                               INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
+                       INT_SET(d->d_rtbtimer, ARCH_CONVERT,
+                               get_seconds() + XFS_QI_RTBTIMELIMIT(mp));
+               }
+       } else {
+               if ((INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT) ||
+                   (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
+                               INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) &&
+                   (INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT) ||
+                   (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
+                               INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
+                       INT_ZERO(d->d_rtbtimer, ARCH_CONVERT);
+               }
+       }
 }
 
 /*
index 9964605..0c3fe31 100644 (file)
@@ -209,6 +209,8 @@ extern int          xfs_qm_dqflock_nowait(xfs_dquot_t *);
 extern void            xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp);
 extern void            xfs_qm_adjust_dqtimers(xfs_mount_t *,
                                        xfs_disk_dquot_t *);
+extern void            xfs_qm_adjust_dqlimits(xfs_mount_t *,
+                                       xfs_disk_dquot_t *);
 extern int             xfs_qm_dqwarn(xfs_disk_dquot_t *, uint);
 extern int             xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
                                        xfs_dqid_t, uint, uint, xfs_dquot_t **);
index 4924a11..f539e92 100644 (file)
@@ -136,9 +136,14 @@ typedef struct xfs_quotainfo {
        xfs_qwarncnt_t   qi_bwarnlimit;  /* limit for num warnings */
        xfs_qwarncnt_t   qi_iwarnlimit;  /* limit for num warnings */
        mutex_t          qi_quotaofflock;/* to serialize quotaoff */
-       /* Some useful precalculated constants */
        xfs_filblks_t    qi_dqchunklen;  /* # BBs in a chunk of dqs */
        uint             qi_dqperchunk;  /* # ondisk dqs in above chunk */
+       xfs_qcnt_t       qi_bhardlimit;  /* default data blk hard limit */
+       xfs_qcnt_t       qi_bsoftlimit;  /* default data blk soft limit */
+       xfs_qcnt_t       qi_ihardlimit;  /* default inode count hard limit */
+       xfs_qcnt_t       qi_isoftlimit;  /* default inode count soft limit */
+       xfs_qcnt_t       qi_rtbhardlimit;/* default realtime blk hard limit */
+       xfs_qcnt_t       qi_rtbsoftlimit;/* default realtime blk soft limit */
 } xfs_quotainfo_t;
 
 
@@ -187,7 +192,6 @@ extern int          xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
 extern int             xfs_qm_sync(xfs_mount_t *, short);
 
 /* dquot stuff */
-extern void            xfs_qm_dqunlink(xfs_dquot_t *);
 extern boolean_t       xfs_qm_dqalloc_incore(xfs_dquot_t **);
 extern int             xfs_qm_dqattach(xfs_inode_t *, uint);
 extern void            xfs_qm_dqdetach(xfs_inode_t *);
index d3553ea..29978e0 100644 (file)
@@ -137,8 +137,8 @@ xfs_qm_read_stats(
 void
 xfs_qm_init_procfs(void)
 {
-       create_proc_read_entry("fs/xfs/xqmstat", 0, 0, xfs_qm_read_stats, NULL);
-       create_proc_read_entry("fs/xfs/xqm", 0, 0, xfs_qm_read_xfsquota, NULL);
+       create_proc_read_entry("fs/xfs/xqmstat", 0, NULL, xfs_qm_read_stats, NULL);
+       create_proc_read_entry("fs/xfs/xqm", 0, NULL, xfs_qm_read_xfsquota, NULL);
 }
 
 void
index 416cc95..25079b5 100644 (file)
@@ -452,9 +452,13 @@ xfs_trans_apply_dquot_deltas(
                                INT_MOD(d->d_rtbcount, ARCH_CONVERT, (xfs_qcnt_t)totalrtbdelta);
 
                        /*
+                        * Get any default limits in use.
                         * Start/reset the timer(s) if needed.
                         */
-                       xfs_qm_adjust_dqtimers(tp->t_mountp, d);
+                       if (!INT_ISZERO(d->d_id, ARCH_CONVERT)) {
+                               xfs_qm_adjust_dqlimits(tp->t_mountp, d);
+                               xfs_qm_adjust_dqtimers(tp->t_mountp, d);
+                       }
 
                        dqp->dq_flags |= XFS_DQ_DIRTY;
                        /*
@@ -625,6 +629,7 @@ xfs_trans_unreserve_and_mod_dquots(
 STATIC int
 xfs_trans_dqresv(
        xfs_trans_t     *tp,
+       xfs_mount_t     *mp,
        xfs_dquot_t     *dqp,
        long            nblks,
        long            ninos,
@@ -635,6 +640,7 @@ xfs_trans_dqresv(
        xfs_qcnt_t      softlimit;
        time_t          btimer;
        xfs_qcnt_t      *resbcountp;
+       xfs_quotainfo_t *q = mp->m_quotainfo;
 
        if (! (flags & XFS_QMOPT_DQLOCK)) {
                xfs_dqlock(dqp);
@@ -642,13 +648,21 @@ xfs_trans_dqresv(
        ASSERT(XFS_DQ_IS_LOCKED(dqp));
        if (flags & XFS_TRANS_DQ_RES_BLKS) {
                hardlimit = INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT);
+               if (!hardlimit)
+                       hardlimit = q->qi_bhardlimit;
                softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT);
+               if (!softlimit)
+                       softlimit = q->qi_bsoftlimit;
                btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
                resbcountp = &dqp->q_res_bcount;
        } else {
                ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
                hardlimit = INT_GET(dqp->q_core.d_rtb_hardlimit, ARCH_CONVERT);
+               if (!hardlimit)
+                       hardlimit = q->qi_rtbhardlimit;
                softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT);
+               if (!softlimit)
+                       softlimit = q->qi_rtbsoftlimit;
                btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
                resbcountp = &dqp->q_res_rtbcount;
        }
@@ -689,14 +703,18 @@ xfs_trans_dqresv(
                        }
                }
                if (ninos > 0) {
-                       if (INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT) > 0ULL &&
-                           INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
-                           INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT)) {
+                       hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT);
+                       if (!hardlimit)
+                               hardlimit = q->qi_ihardlimit;
+                       softlimit = INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT);
+                       if (!softlimit)
+                               softlimit = q->qi_isoftlimit;
+                       if (hardlimit > 0ULL &&
+                           INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= hardlimit) {
                                error = EDQUOT;
                                goto error_return;
-                       } else if (INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) > 0ULL &&
-                                  INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
-                                  INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) {
+                       } else if (softlimit > 0ULL &&
+                                  INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= softlimit) {
                                /*
                                 * If timer or warnings has expired,
                                 * return EDQUOT
@@ -786,19 +804,20 @@ xfs_trans_reserve_quota_bydquots(
        resvd = 0;
 
        if (udqp) {
-               if (xfs_trans_dqresv(tp, udqp, nblks, ninos, flags))
+               if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))
                        return (EDQUOT);
                resvd = 1;
        }
 
        if (gdqp) {
-               if (xfs_trans_dqresv(tp, gdqp, nblks, ninos, flags)) {
+               if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {
                        /*
                         * can't do it, so backout previous reservation
                         */
                        if (resvd) {
-                               xfs_trans_dqresv(tp, udqp,  -nblks, -ninos,
-                                                flags);
+                               flags |= XFS_QMOPT_FORCE_RES;
+                               xfs_trans_dqresv(tp, mp, udqp,
+                                                -nblks, -ninos, flags);
                        }
                        return (EDQUOT);
                }
index 852a92d..3dae14c 100644 (file)
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
-#include <linux/types.h>
-#include <linux/slab.h>
-
-#include <xfs_types.h>
-#include "kmem.h"
-#include "spin.h"
-#include "debug.h"
-#include "ktrace.h"
+#include <xfs.h>
 
 static kmem_zone_t *ktrace_hdr_zone;
 static kmem_zone_t *ktrace_ent_zone;
index 9f3d2eb..15b5194 100644 (file)
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <asm/uaccess.h>
-
-#include <xfs_types.h>
-#include "debug.h"
-#include "move.h"
+#include <xfs.h>
 
 /* Read from kernel buffer at src to user/kernel buffer defined
  * by the uio structure. Advance the pointer in the uio struct
index 74cad98..02337c2 100644 (file)
@@ -665,7 +665,7 @@ xfs_alloc_ag_vextent_exact(
         * Allocate/initialize a cursor for the by-number freespace btree.
         */
        bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-               args->agno, XFS_BTNUM_BNO, 0, 0);
+               args->agno, XFS_BTNUM_BNO, NULL, 0);
        /*
         * Lookup bno and minlen in the btree (minlen is irrelevant, really).
         * Look for the closest free block <= bno, it must contain bno
@@ -721,7 +721,7 @@ xfs_alloc_ag_vextent_exact(
         * Allocate/initialize a cursor for the by-size btree.
         */
        cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-               args->agno, XFS_BTNUM_CNT, 0, 0);
+               args->agno, XFS_BTNUM_CNT, NULL, 0);
        ASSERT(args->agbno + args->len <=
                INT_GET(XFS_BUF_TO_AGF(args->agbp)->agf_length,
                        ARCH_CONVERT));
@@ -788,7 +788,7 @@ xfs_alloc_ag_vextent_near(
         * Get a cursor for the by-size btree.
         */
        cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-               args->agno, XFS_BTNUM_CNT, 0, 0);
+               args->agno, XFS_BTNUM_CNT, NULL, 0);
        ltlen = 0;
        bno_cur_lt = bno_cur_gt = NULL;
        /*
@@ -916,7 +916,7 @@ xfs_alloc_ag_vextent_near(
                 * Set up a cursor for the by-bno tree.
                 */
                bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp,
-                       args->agbp, args->agno, XFS_BTNUM_BNO, 0, 0);
+                       args->agbp, args->agno, XFS_BTNUM_BNO, NULL, 0);
                /*
                 * Fix up the btree entries.
                 */
@@ -944,7 +944,7 @@ xfs_alloc_ag_vextent_near(
         * Allocate and initialize the cursor for the leftward search.
         */
        bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-               args->agno, XFS_BTNUM_BNO, 0, 0);
+               args->agno, XFS_BTNUM_BNO, NULL, 0);
        /*
         * Lookup <= bno to find the leftward search's starting point.
         */
@@ -956,7 +956,7 @@ xfs_alloc_ag_vextent_near(
                 * search.
                 */
                bno_cur_gt = bno_cur_lt;
-               bno_cur_lt = 0;
+               bno_cur_lt = NULL;
        }
        /*
         * Found something.  Duplicate the cursor for the rightward search.
@@ -1301,7 +1301,7 @@ xfs_alloc_ag_vextent_size(
         * Allocate and initialize a cursor for the by-size btree.
         */
        cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-               args->agno, XFS_BTNUM_CNT, 0, 0);
+               args->agno, XFS_BTNUM_CNT, NULL, 0);
        bno_cur = NULL;
        /*
         * Look for an entry >= maxlen+alignment-1 blocks.
@@ -1406,7 +1406,7 @@ xfs_alloc_ag_vextent_size(
         * Allocate and initialize a cursor for the by-block tree.
         */
        bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-               args->agno, XFS_BTNUM_BNO, 0, 0);
+               args->agno, XFS_BTNUM_BNO, NULL, 0);
        if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
                        rbno, rlen, XFSA_FIXUP_CNT_OK)))
                goto error0;
@@ -1553,7 +1553,7 @@ xfs_free_ag_extent(
        /*
         * Allocate and initialize a cursor for the by-block btree.
         */
-       bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, 0,
+       bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, NULL,
                0);
        cnt_cur = NULL;
        /*
@@ -1613,7 +1613,7 @@ xfs_free_ag_extent(
        /*
         * Now allocate and initialize a cursor for the by-size tree.
         */
-       cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, 0,
+       cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, NULL,
                0);
        /*
         * Have both left and right contiguous neighbors.
index 55c405c..6b5de3a 100644 (file)
@@ -263,7 +263,7 @@ xfs_alloc_delrec(
                        /*
                         * Update the cursor so there's one fewer level.
                         */
-                       xfs_btree_setbuf(cur, level, 0);
+                       xfs_btree_setbuf(cur, level, NULL);
                        cur->bc_nlevels--;
                } else if (level > 0 &&
                           (error = xfs_alloc_decrement(cur, level, &i)))
index 97bac75..b1480e0 100644 (file)
@@ -246,7 +246,6 @@ int xfs_attr_shortform_getvalue(struct xfs_da_args *args);
 int    xfs_attr_shortform_to_leaf(struct xfs_da_args *args);
 int    xfs_attr_shortform_remove(struct xfs_da_args *remove);
 int    xfs_attr_shortform_list(struct xfs_attr_list_context *context);
-int    xfs_attr_shortform_replace(struct xfs_da_args *args);
 int    xfs_attr_shortform_allfit(struct xfs_dabuf *bp, struct xfs_inode *dp);
 
 /*
index f3bc48f..08d551a 100644 (file)
@@ -65,7 +65,7 @@
  */
 int
 xfs_swapext(
-       xfs_swapext_t   *sxp)
+       xfs_swapext_t   __user *sxp)
 {
        xfs_swapext_t   sx;
        xfs_inode_t     *ip=NULL, *tip=NULL, *ips[2];
index 0e1c26f..9048605 100644 (file)
@@ -60,7 +60,7 @@ typedef struct xfs_swapext
 /*
  * Syscall interface for xfs_swapext
  */
-int    xfs_swapext(struct xfs_swapext *sx);
+int    xfs_swapext(struct xfs_swapext __user *sx);
 
 #endif /* __KERNEL__ */
 
index c674716..9d64173 100644 (file)
@@ -211,7 +211,7 @@ xfs_dir2_trace_args_s(
                (void *)((unsigned long)(args->inumber >> 32)),
                (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
                (void *)args->dp, (void *)args->trans,
-               (void *)(unsigned long)args->justcheck, (void *)(long)s, 0);
+               (void *)(unsigned long)args->justcheck, (void *)(long)s, NULL);
 }
 
 void
index d3a53b6..07641fc 100644 (file)
@@ -457,7 +457,7 @@ inode_allocate:
                        error = xfs_iget_core(vp, mp, tp, ino,
                                                lock_flags, ipp, bno);
                        if (error) {
-                               make_bad_inode(inode);
+                               vn_mark_bad(vp);
                                if (inode->i_state & I_NEW)
                                        unlock_new_inode(inode);
                                iput(inode);
@@ -576,11 +576,8 @@ xfs_iput_new(xfs_inode_t   *ip,
 
        vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
 
-       /* We shouldn't get here without this being true, but just in case */
-       if (inode->i_state & I_NEW) {
-               make_bad_inode(inode);
+       if (inode->i_state & I_NEW)
                unlock_new_inode(inode);
-       }
        if (lock_flags)
                xfs_iunlock(ip, lock_flags);
        VN_RELE(vp);
index 673410c..31c9108 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2003,2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -42,6 +42,7 @@ typedef enum {                                /* iomap_flags values */
        IOMAP_EOF =             0x01,   /* mapping contains EOF   */
        IOMAP_HOLE =            0x02,   /* mapping covers a hole  */
        IOMAP_DELAY =           0x04,   /* mapping covers delalloc region  */
+       IOMAP_REALTIME =        0x10,   /* mapping on the realtime device  */
        IOMAP_UNWRITTEN =       0x20,   /* mapping covers allocated */
                                        /* but uninitialized file data  */
        IOMAP_NEW =             0x40    /* just allocate */
@@ -57,7 +58,7 @@ typedef enum {
        BMAPI_IGNSTATE = (1 << 4),      /* ignore unwritten state on read */
        BMAPI_DIRECT = (1 << 5),                /* direct instead of buffered write */
        BMAPI_MMAP = (1 << 6),          /* allocate for mmap write */
-       BMAPI_SYNC = (1 << 7),          /* sync write */
+       BMAPI_SYNC = (1 << 7),          /* sync write to flush delalloc space */
        BMAPI_TRYLOCK = (1 << 8),       /* non-blocking request */
        BMAPI_DEVICE = (1 << 9),        /* we only want to know the device */
 } bmapi_flags_t;
index 052de38..7d91f70 100644 (file)
@@ -543,7 +543,6 @@ extern int   xlog_find_tail(xlog_t  *log,
                                xfs_daddr_t *head_blk,
                                xfs_daddr_t *tail_blk,
                                int readonly);
-extern int      xlog_print_find_oldest(xlog_t *log, xfs_daddr_t *last_blk);
 extern int      xlog_recover(xlog_t *log, int readonly);
 extern int      xlog_recover_finish(xlog_t *log, int mfsi_flags);
 extern void     xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog);
index 8cddc16..703ec4e 100644 (file)
@@ -309,23 +309,27 @@ typedef struct xfs_dqtrxops {
 } xfs_dqtrxops_t;
 
 #define XFS_DQTRXOP(mp, tp, op, args...) \
-                       ((mp)->m_qm_ops.xfs_dqtrxops ? \
-                       ((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0)
+               ((mp)->m_qm_ops.xfs_dqtrxops ? \
+               ((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0)
+
+#define XFS_DQTRXOP_VOID(mp, tp, op, args...) \
+               ((mp)->m_qm_ops.xfs_dqtrxops ? \
+               ((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : (void)0)
 
 #define XFS_TRANS_DUP_DQINFO(mp, otp, ntp) \
-       XFS_DQTRXOP(mp, otp, qo_dup_dqinfo, ntp)
+       XFS_DQTRXOP_VOID(mp, otp, qo_dup_dqinfo, ntp)
 #define XFS_TRANS_FREE_DQINFO(mp, tp) \
-       XFS_DQTRXOP(mp, tp, qo_free_dqinfo)
+       XFS_DQTRXOP_VOID(mp, tp, qo_free_dqinfo)
 #define XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, field, delta) \
-       XFS_DQTRXOP(mp, tp, qo_mod_dquot_byino, ip, field, delta)
+       XFS_DQTRXOP_VOID(mp, tp, qo_mod_dquot_byino, ip, field, delta)
 #define XFS_TRANS_APPLY_DQUOT_DELTAS(mp, tp) \
-       XFS_DQTRXOP(mp, tp, qo_apply_dquot_deltas)
+       XFS_DQTRXOP_VOID(mp, tp, qo_apply_dquot_deltas)
 #define XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, fl) \
        XFS_DQTRXOP(mp, tp, qo_reserve_quota_nblks, mp, ip, nblks, ninos, fl)
 #define XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, fl) \
        XFS_DQTRXOP(mp, tp, qo_reserve_quota_bydquots, mp, ud, gd, nb, ni, fl)
 #define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \
-       XFS_DQTRXOP(mp, tp, qo_unreserve_and_mod_dquots)
+       XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots)
 
 #define XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, nblks) \
        XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
index 9e0adf4..ad090a8 100644 (file)
@@ -250,9 +250,9 @@ int xfs_sb_good_version(xfs_sb_t *sbp);
        ((((sbp)->sb_versionnum >= XFS_SB_VERSION_1) && \
          ((sbp)->sb_versionnum <= XFS_SB_VERSION_3)) || \
           ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
-           !(((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) && \
-             ((sbp)->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \
-             ((sbp)->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS))
+           !(((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) || \
+             (((sbp)->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \
+              ((sbp)->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS)))
 
 #ifdef __KERNEL__
 #define        XFS_SB_GOOD_VERSION(sbp)        \
index 8d6aac7..04609d2 100644 (file)
@@ -58,7 +58,7 @@ typedef enum { B_FALSE,B_TRUE }       boolean_t;
 typedef __int64_t              prid_t;         /* project ID */
 typedef __uint32_t             inst_t;         /* an instruction */
 
-typedef __u64                  xfs_off_t;
+typedef __s64                  xfs_off_t;      /* <file offset> type */
 typedef __u64                  xfs_ino_t;      /* <inode> type */
 typedef __s64                  xfs_daddr_t;    /* <disk address> type */
 typedef char *                 xfs_caddr_t;    /* <core address> type */
index fa0c9b5..e4a0f1e 100644 (file)
 
 /* Version string */
 
-#define ACPI_CA_VERSION                 0x20040326
+#define ACPI_CA_VERSION                 0x20040816
+
+/*
+ * OS name, used for the _OS object.  The _OS object is essentially obsolete,
+ * but there is a large base of ASL/AML code in existing machines that check
+ * for the string below.  The use of this string usually guarantees that
+ * the ASL will execute down the most tested code path.  Also, there is some
+ * code that will not execute the _OSI method unless _OS matches the string
+ * below.  Therefore, change this string at your own risk.
+ */
+#define ACPI_OS_NAME                    "Microsoft Windows NT"
 
 /* Maximum objects in the various object caches */
 
-#define ACPI_MAX_STATE_CACHE_DEPTH      64          /* State objects for stacks */
+#define ACPI_MAX_STATE_CACHE_DEPTH      64          /* State objects */
 #define ACPI_MAX_PARSE_CACHE_DEPTH      96          /* Parse tree objects */
 #define ACPI_MAX_EXTPARSE_CACHE_DEPTH   64          /* Parse tree objects */
 #define ACPI_MAX_OBJECT_CACHE_DEPTH     64          /* Interpreter operand objects */
 
 /* Constants used in searching for the RSDP in low memory */
 
-#define ACPI_LO_RSDP_WINDOW_BASE        0           /* Physical Address */
-#define ACPI_HI_RSDP_WINDOW_BASE        0xE0000     /* Physical Address */
-#define ACPI_LO_RSDP_WINDOW_SIZE        0x400
-#define ACPI_HI_RSDP_WINDOW_SIZE        0x20000
+#define ACPI_EBDA_PTR_LOCATION          0x0000040E     /* Physical Address */
+#define ACPI_EBDA_PTR_LENGTH            2
+#define ACPI_EBDA_WINDOW_SIZE           1024
+#define ACPI_HI_RSDP_WINDOW_BASE        0x000E0000     /* Physical Address */
+#define ACPI_HI_RSDP_WINDOW_SIZE        0x00020000
 #define ACPI_RSDP_SCAN_STEP             16
 
 /* Operation regions */
 
 /* Number of strings associated with the _OSI reserved method */
 
-#define ACPI_NUM_OSI_STRINGS            4
+#define ACPI_NUM_OSI_STRINGS            9
 
 
 /******************************************************************************
index bb8411e..658c5f5 100644 (file)
@@ -106,6 +106,10 @@ acpi_db_method_end (
  * dbcmds - debug commands and output routines
  */
 
+acpi_status
+acpi_db_disassemble_method (
+       char                            *name);
+
 void
 acpi_db_display_table_info (
        char                            *table_arg);
@@ -164,6 +168,10 @@ void
 acpi_db_set_scope (
        char                            *name);
 
+acpi_status
+acpi_db_sleep (
+       char                            *object_arg);
+
 void
 acpi_db_find_references (
        char                            *object_arg);
index 220bd1b..67f6c5c 100644 (file)
 #define BLOCK_BRACE             2
 #define BLOCK_COMMA_LIST        4
 
+struct acpi_external_list
+{
+       char                                *path;
+       struct acpi_external_list           *next;
+};
+
+extern struct acpi_external_list        *acpi_gbl_external_list;
 extern const char                       *acpi_gbl_io_decode[2];
 extern const char                       *acpi_gbl_word_decode[4];
 extern const char                       *acpi_gbl_consume_decode[2];
@@ -399,4 +406,12 @@ acpi_dm_vendor_small_descriptor (
        u32                             level);
 
 
+/*
+ * dmutils
+ */
+
+void
+acpi_dm_add_to_external_list (
+       char                            *path);
+
 #endif  /* __ACDISASM_H__ */
index 2a09e92..e003a4f 100644 (file)
@@ -437,8 +437,7 @@ acpi_ds_init_aml_walk (
        struct acpi_namespace_node      *method_node,
        u8                              *aml_start,
        u32                             aml_length,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_obj_desc,
+       struct acpi_parameter_info      *info,
        u32                             pass_number);
 
 acpi_status
index 4ab99b2..124c392 100644 (file)
 
 
 acpi_status
-acpi_ev_initialize (
+acpi_ev_initialize_events (
        void);
 
 acpi_status
-acpi_ev_handler_initialize (
+acpi_ev_install_xrupt_handlers (
        void);
 
 
@@ -111,12 +111,27 @@ acpi_ev_notify_dispatch (
 
 acpi_status
 acpi_ev_walk_gpe_list (
-       ACPI_GPE_CALLBACK       gpe_walk_callback);
+       ACPI_GPE_CALLBACK       gpe_walk_callback,
+       u32                             flags);
 
 u8
 acpi_ev_valid_gpe_event (
        struct acpi_gpe_event_info      *gpe_event_info);
 
+acpi_status
+acpi_ev_update_gpe_enable_masks (
+       struct acpi_gpe_event_info      *gpe_event_info,
+       u8                              type);
+
+acpi_status
+acpi_ev_enable_gpe (
+       struct acpi_gpe_event_info      *gpe_event_info,
+       u8                              write_to_hardware);
+
+acpi_status
+acpi_ev_disable_gpe (
+       struct acpi_gpe_event_info      *gpe_event_info);
+
 struct acpi_gpe_event_info *
 acpi_ev_get_gpe_event_info (
        acpi_handle                     gpe_device,
@@ -139,6 +154,11 @@ acpi_status
 acpi_ev_delete_gpe_block (
        struct acpi_gpe_block_info      *gpe_block);
 
+acpi_status
+acpi_ev_delete_gpe_handlers (
+       struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+       struct acpi_gpe_block_info      *gpe_block);
+
 u32
 acpi_ev_gpe_dispatch (
        struct acpi_gpe_event_info      *gpe_event_info,
@@ -148,12 +168,25 @@ u32
 acpi_ev_gpe_detect (
        struct acpi_gpe_xrupt_info      *gpe_xrupt_list);
 
+acpi_status
+acpi_ev_set_gpe_type (
+       struct acpi_gpe_event_info      *gpe_event_info,
+       u8                              type);
+
+acpi_status
+acpi_ev_check_for_wake_only_gpe (
+       struct acpi_gpe_event_info      *gpe_event_info);
+
 /*
  * Evregion - Address Space handling
  */
 
 acpi_status
-acpi_ev_init_address_spaces (
+acpi_ev_install_region_handlers (
+       void);
+
+acpi_status
+acpi_ev_initialize_op_regions (
        void);
 
 acpi_status
@@ -182,6 +215,19 @@ acpi_ev_detach_region (
        union acpi_operand_object      *region_obj,
        u8                              acpi_ns_is_locked);
 
+acpi_status
+acpi_ev_install_space_handler (
+       struct acpi_namespace_node      *node,
+       acpi_adr_space_type             space_id,
+       acpi_adr_space_handler          handler,
+       acpi_adr_space_setup            setup,
+       void                            *context);
+
+acpi_status
+acpi_ev_execute_reg_methods (
+       struct acpi_namespace_node      *node,
+       acpi_adr_space_type             space_id);
+
 acpi_status
 acpi_ev_execute_reg_method (
        union acpi_operand_object      *region_obj,
index 9441f5c..1022cc2 100644 (file)
@@ -95,8 +95,9 @@
 #define AE_LOGICAL_ADDRESS              (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL)
 #define AE_ABORT_METHOD                 (acpi_status) (0x001C | AE_CODE_ENVIRONMENTAL)
 #define AE_SAME_HANDLER                 (acpi_status) (0x001D | AE_CODE_ENVIRONMENTAL)
+#define AE_WAKE_ONLY_GPE                (acpi_status) (0x001E | AE_CODE_ENVIRONMENTAL)
 
-#define AE_CODE_ENV_MAX                 0x001D
+#define AE_CODE_ENV_MAX                 0x001E
 
 /*
  * Programmer exceptions
 #define AE_AML_CIRCULAR_REFERENCE       (acpi_status) (0x0020 | AE_CODE_AML)
 #define AE_AML_BAD_RESOURCE_LENGTH      (acpi_status) (0x0021 | AE_CODE_AML)
 
-#define AE_CODE_AML_MAX                 0x0020
+#define AE_CODE_AML_MAX                 0x0021
 
 /*
  * Internal exceptions used for control
@@ -222,7 +223,8 @@ char const   *acpi_gbl_exception_names_env[] =
        "AE_NO_GLOBAL_LOCK",
        "AE_LOGICAL_ADDRESS",
        "AE_ABORT_METHOD",
-       "AE_SAME_HANDLER"
+       "AE_SAME_HANDLER",
+       "AE_WAKE_ONLY_GPE"
 };
 
 char const   *acpi_gbl_exception_names_pgm[] =
index a19c6fc..eb16ee2 100644 (file)
 
 
 /*
- * Ensure that the globals are actually defined only once.
+ * Ensure that the globals are actually defined and initialized only once.
  *
- * The use of these defines allows a single list of globals (here) in order
+ * The use of these macros allows a single list of globals (here) in order
  * to simplify maintenance of the code.
  */
 #ifdef DEFINE_ACPI_GLOBALS
 #define ACPI_EXTERN
+#define ACPI_INIT_GLOBAL(a,b) a=b
 #else
 #define ACPI_EXTERN extern
+#define ACPI_INIT_GLOBAL(a,b) a
 #endif
 
 /*
@@ -64,6 +66,7 @@
 ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1a_enable;
 ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1b_enable;
 
+
 /*****************************************************************************
  *
  * Debug support
@@ -79,15 +82,42 @@ extern      u32                                 acpi_dbg_layer;
 
 extern      u32                                 acpi_gbl_nesting_level;
 
+
 /*****************************************************************************
  *
- * Runtime configuration
+ * Runtime configuration (static defaults that can be overriden at runtime)
  *
  ****************************************************************************/
 
-ACPI_EXTERN u8                                  acpi_gbl_create_osi_method;
-ACPI_EXTERN u8                                  acpi_gbl_all_methods_serialized;
-ACPI_EXTERN u8                                  acpi_gbl_leave_wake_gpes_disabled;
+/*
+ * Enable "slack" in the AML interpreter?  Default is FALSE, and the
+ * interpreter strictly follows the ACPI specification.  Setting to TRUE
+ * allows the interpreter to forgive certain bad AML constructs.
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_enable_interpreter_slack, FALSE);
+
+/*
+ * Automatically serialize ALL control methods? Default is FALSE, meaning
+ * to use the Serialized/not_serialized method flags on a per method basis.
+ * Only change this if the ASL code is poorly written and cannot handle
+ * reentrancy even though methods are marked "not_serialized".
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_all_methods_serialized, FALSE);
+
+/*
+ * Create the predefined _OSI method in the namespace? Default is TRUE
+ * because ACPI CA is fully compatible with other ACPI implementations.
+ * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior.
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_create_osi_method, TRUE);
+
+/*
+ * Disable wakeup GPEs during runtime? Default is TRUE because WAKE and
+ * RUNTIME GPEs should never be shared, and WAKE GPEs should typically only
+ * be enabled just before going to sleep.
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_leave_wake_gpes_disabled, TRUE);
+
 
 /*****************************************************************************
  *
@@ -102,7 +132,6 @@ ACPI_EXTERN u8                                  acpi_gbl_leave_wake_gpes_disable
  *
  * These tables are single-table only; meaning that there can be at most one
  * of each in the system.  Each global points to the actual table.
- *
  */
 ACPI_EXTERN u32                                 acpi_gbl_table_flags;
 ACPI_EXTERN u32                                 acpi_gbl_rsdt_table_count;
@@ -170,6 +199,7 @@ ACPI_EXTERN u8                                  acpi_gbl_step_to_next_call;
 ACPI_EXTERN u8                                  acpi_gbl_acpi_hardware_present;
 ACPI_EXTERN u8                                  acpi_gbl_global_lock_present;
 ACPI_EXTERN u8                                  acpi_gbl_events_initialized;
+ACPI_EXTERN u8                                  acpi_gbl_system_awake_and_running;
 
 extern u8                                       acpi_gbl_shutdown;
 extern u32                                      acpi_gbl_startup_flags;
index 2281f27..cf55493 100644 (file)
@@ -114,15 +114,7 @@ acpi_hw_clear_acpi_status (
 /* GPE support */
 
 acpi_status
-acpi_hw_enable_gpe (
-       struct acpi_gpe_event_info      *gpe_event_info);
-
-void
-acpi_hw_enable_gpe_for_wakeup (
-       struct acpi_gpe_event_info      *gpe_event_info);
-
-acpi_status
-acpi_hw_disable_gpe (
+acpi_hw_write_gpe_enable_reg (
        struct acpi_gpe_event_info      *gpe_event_info);
 
 acpi_status
@@ -130,10 +122,6 @@ acpi_hw_disable_gpe_block (
        struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
        struct acpi_gpe_block_info      *gpe_block);
 
-void
-acpi_hw_disable_gpe_for_wakeup (
-       struct acpi_gpe_event_info      *gpe_event_info);
-
 acpi_status
 acpi_hw_clear_gpe (
        struct acpi_gpe_event_info      *gpe_event_info);
@@ -149,12 +137,26 @@ acpi_hw_get_gpe_status (
        acpi_event_status               *event_status);
 
 acpi_status
-acpi_hw_prepare_gpes_for_sleep (
-       void);
+acpi_hw_disable_all_gpes (
+       u32                             flags);
 
 acpi_status
-acpi_hw_restore_gpes_on_wake (
-       void);
+acpi_hw_enable_all_runtime_gpes (
+       u32                             flags);
+
+acpi_status
+acpi_hw_enable_all_wakeup_gpes (
+       u32                             flags);
+
+acpi_status
+acpi_hw_enable_runtime_gpe_block (
+       struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+       struct acpi_gpe_block_info      *gpe_block);
+
+acpi_status
+acpi_hw_enable_wakeup_gpe_block (
+       struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+       struct acpi_gpe_block_info      *gpe_block);
 
 
 /* ACPI Timer prototypes */
index 0bcb194..a43e91f 100644 (file)
@@ -117,6 +117,12 @@ acpi_ex_convert_to_ascii (
  * exfield - ACPI AML (p-code) execution - field manipulation
  */
 
+acpi_status
+acpi_ex_common_buffer_setup (
+       union acpi_operand_object       *obj_desc,
+       u32                             buffer_length,
+       u32                             *datum_count);
+
 acpi_status
 acpi_ex_extract_from_field (
        union acpi_operand_object       *obj_desc,
@@ -240,8 +246,8 @@ acpi_ex_do_concatenate (
 u8
 acpi_ex_do_logical_op (
        u16                             opcode,
-       acpi_integer                    operand0,
-       acpi_integer                    operand1);
+       union acpi_operand_object       *obj_desc,
+       union acpi_operand_object       *obj_desc2);
 
 acpi_integer
 acpi_ex_do_math_op (
@@ -563,8 +569,11 @@ acpi_status
 acpi_ex_store_object_to_node (
        union acpi_operand_object       *source_desc,
        struct acpi_namespace_node      *node,
-       struct acpi_walk_state          *walk_state);
+       struct acpi_walk_state          *walk_state,
+       u8                              implicit_conversion);
 
+#define ACPI_IMPLICIT_CONVERSION        TRUE
+#define ACPI_NO_IMPLICIT_CONVERSION     FALSE
 
 /*
  * exstoren
index eb1b957..2afff11 100644 (file)
@@ -189,8 +189,6 @@ struct acpi_namespace_node
        u8                                  type;           /* Type associated with this name */
        u16                                 owner_id;
        union acpi_name_union               name;           /* ACPI Name, always 4 chars per ACPI spec */
-
-
        union acpi_operand_object           *object;        /* Pointer to attached ACPI object (optional) */
        struct acpi_namespace_node          *child;         /* First child */
        struct acpi_namespace_node          *peer;          /* Next peer*/
@@ -211,10 +209,8 @@ struct acpi_namespace_node
 #define ANOBJ_METHOD_LOCAL              0x10
 #define ANOBJ_METHOD_NO_RETVAL          0x20
 #define ANOBJ_METHOD_SOME_NO_RETVAL     0x40
-
 #define ANOBJ_IS_BIT_OFFSET             0x80
 
-
 /*
  * ACPI Table Descriptor.  One per ACPI table
  */
@@ -309,16 +305,31 @@ struct acpi_create_field_info
  *
  ****************************************************************************/
 
-/* Information about a GPE, one per each GPE in an array */
+/* Dispatch info for each GPE -- either a method or handler, cannot be both */
 
-struct acpi_gpe_event_info
+struct acpi_handler_info
 {
-       struct acpi_namespace_node              *method_node;   /* Method node for this GPE level */
-       acpi_gpe_handler                        handler;        /* Address of handler, if any */
+       acpi_event_handler                      address;        /* Address of handler, if any */
        void                                    *context;       /* Context to be passed to handler */
+       struct acpi_namespace_node              *method_node;   /* Method node for this GPE level (saved) */
+};
+
+union acpi_gpe_dispatch_info
+{
+       struct acpi_namespace_node              *method_node;   /* Method node for this GPE level */
+       struct acpi_handler_info                *handler;
+};
+
+/*
+ * Information about a GPE, one per each GPE in an array.
+ * NOTE: Important to keep this struct as small as possible.
+ */
+struct acpi_gpe_event_info
+{
+       union acpi_gpe_dispatch_info    dispatch;       /* Either Method or Handler */
        struct acpi_gpe_register_info           *register_info; /* Backpointer to register info */
-       u8                                      flags;          /* Level or Edge */
-       u8                                      bit_mask;       /* This GPE within the register */
+       u8                                      flags;          /* Misc info about this GPE */
+       u8                                      register_bit;   /* This GPE bit within the register */
 };
 
 /* Information about a GPE register pair, one per each status/enable pair in an array */
@@ -327,9 +338,8 @@ struct acpi_gpe_register_info
 {
        struct acpi_generic_address             status_address; /* Address of status reg */
        struct acpi_generic_address             enable_address; /* Address of enable reg */
-       u8                                      status;         /* Current value of status reg */
-       u8                                      enable;         /* Current value of enable reg */
-       u8                                      wake_enable;    /* Mask of bits to keep enabled when sleeping */
+       u8                                      enable_for_wake; /* GPEs to keep enabled when sleeping */
+       u8                                      enable_for_run; /* GPEs to keep enabled when running */
        u8                                      base_gpe_number; /* Base GPE number for this register */
 };
 
@@ -339,6 +349,7 @@ struct acpi_gpe_register_info
  */
 struct acpi_gpe_block_info
 {
+       struct acpi_namespace_node              *node;
        struct acpi_gpe_block_info              *previous;
        struct acpi_gpe_block_info              *next;
        struct acpi_gpe_xrupt_info              *xrupt_block;   /* Backpointer to interrupt block */
@@ -502,7 +513,7 @@ struct acpi_thread_state
        struct acpi_walk_state              *walk_state_list;       /* Head of list of walk_states for this thread */
        union acpi_operand_object           *acquired_mutex_list;   /* List of all currently acquired mutexes */
        u32                                 thread_id;              /* Running thread ID */
-       u16                                 current_sync_level;     /* Mutex Sync (nested acquire) level */
+       u                                 current_sync_level;     /* Mutex Sync (nested acquire) level */
 };
 
 
index 245bc0b..43c474a 100644 (file)
@@ -53,6 +53,9 @@
 #define ACPI_LOBYTE(l)                  ((u8)(u16)(l))
 #define ACPI_HIBYTE(l)                  ((u8)((((u16)(l)) >> 8) & 0xFF))
 
+#define ACPI_SET_BIT(target,bit)        ((target) |= (bit))
+#define ACPI_CLEAR_BIT(target,bit)      ((target) &= ~(bit))
+
 
 #if ACPI_MACHINE_WIDTH == 16
 
  * printf() format helpers
  */
 
-/* Split 64-bit integer into two 32-bit values. use with %8,8_x%8.8X */
+/* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */
 
 #define ACPI_FORMAT_UINT64(i)           ACPI_HIDWORD(i),ACPI_LODWORD(i)
 
 
 #define ACPI_IS_OCTAL_DIGIT(d)               (((char)(d) >= '0') && ((char)(d) <= '7'))
 
-/* Macros for GAS addressing */
-
-#if ACPI_MACHINE_WIDTH != 16
-
-#define ACPI_PCI_DEVICE(a)              (u16) ((ACPI_HIDWORD ((a))) & 0x0000FFFF)
-#define ACPI_PCI_FUNCTION(a)            (u16) ((ACPI_LODWORD ((a))) >> 16)
-#define ACPI_PCI_REGISTER(a)            (u16) ((ACPI_LODWORD ((a))) & 0x0000FFFF)
-
-#else
-
-/* No support for GAS and PCI IDs in 16-bit mode  */
-
-#define ACPI_PCI_FUNCTION(a)            (u16) ((a) & 0xFFFF0000)
-#define ACPI_PCI_DEVICE(a)              (u16) ((a) & 0x0000FFFF)
-#define ACPI_PCI_REGISTER(a)            (u16) ((a) & 0x0000FFFF)
-
-#endif
-
 
 /* Bitfields within ACPI registers */
 
index de54ba7..8cfd1af 100644 (file)
@@ -278,33 +278,25 @@ acpi_ns_dump_objects (
 
 acpi_status
 acpi_ns_evaluate_by_handle (
-       struct acpi_namespace_node      *prefix_node,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_object);
+       struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_evaluate_by_name (
        char                            *pathname,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_object);
+       struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_evaluate_relative (
-       struct acpi_namespace_node      *prefix_node,
        char                            *pathname,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_object);
+       struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_execute_control_method (
-       struct acpi_namespace_node      *method_node,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_obj_desc);
+       struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_get_object_value (
-       struct acpi_namespace_node      *object_node,
-       union acpi_operand_object       **return_obj_desc);
+       struct acpi_parameter_info      *info);
 
 
 /*
index 51abdda..0d47972 100644 (file)
@@ -204,13 +204,14 @@ struct acpi_object_method
 struct acpi_object_mutex
 {
        ACPI_OBJECT_COMMON_HEADER
-       u16                                     sync_level;
-       u16                                     acquisition_depth;
-       struct acpi_thread_state                *owner_thread;
-       void                                    *semaphore;
+       u8                                      sync_level;         /* 0-15, specified in Mutex() call */
+       u16                                     acquisition_depth;  /* Allow multiple Acquires, same thread */
+       struct acpi_thread_state                *owner_thread;      /* Current owner of the mutex */
+       void                                    *semaphore;         /* Actual OS synchronization object */
        union acpi_operand_object               *prev;              /* Link for list of acquired mutexes */
        union acpi_operand_object               *next;              /* Link for list of acquired mutexes */
-       struct acpi_namespace_node              *node;              /* containing object */
+       struct acpi_namespace_node              *node;              /* Containing namespace node */
+       u8                                      original_sync_level; /* Owner's original sync level (0-15) */
 };
 
 
@@ -220,7 +221,7 @@ struct acpi_object_region
 
        u8                                      space_id;
        union acpi_operand_object               *handler;           /* Handler for region access */
-       struct acpi_namespace_node              *node;              /* containing object */
+       struct acpi_namespace_node              *node;              /* Containing namespace node */
        union acpi_operand_object               *next;
        u32                                     length;
        acpi_physical_address                   address;
index 562e660..42cc5b4 100644 (file)
@@ -73,9 +73,7 @@ acpi_psx_load_table (
 
 acpi_status
 acpi_psx_execute (
-       struct acpi_namespace_node      *method_node,
-       union acpi_operand_object       **params,
-       union acpi_operand_object       **return_obj_desc);
+       struct acpi_parameter_info      *info);
 
 
 /******************************************************************************
index af33ae5..86513a0 100644 (file)
@@ -157,7 +157,8 @@ struct acpi_device_flags {
        u32                     suprise_removal_ok:1;
        u32                     power_manageable:1;
        u32                     performance_manageable:1;
-       u32                     reserved:21;
+       u32                     wake_capable:1; /* Wakeup(_PRW) supported? */
+       u32                     reserved:20;
 };
 
 
@@ -203,10 +204,8 @@ struct acpi_device_power_flags {
        u32                     explicit_get:1;              /* _PSC present? */
        u32                     power_resources:1;         /* Power resources */
        u32                     inrush_current:1;         /* Serialize Dx->D0 */
-       u32                     wake_capable:1;          /* Wakeup supported? */
-       u32                     wake_enabled:1;         /* Enabled for wakeup */
        u32                     power_removed:1;           /* Optimize Dx->D0 */
-       u32                     reserved:26;
+       u32                     reserved:28;
 };
 
 struct acpi_device_power_state {
@@ -250,6 +249,25 @@ struct acpi_device_perf {
        struct acpi_device_perf_state *states;
 };
 
+/* Wakeup Management */
+struct acpi_device_wakeup_flags {
+       u8      valid:1; /* Can successfully enable wakeup? */
+       u8      run_wake:1; /* Run-Wake GPE devices */
+};
+
+struct acpi_device_wakeup_state {
+       u8      enabled:1;
+       u8      active:1;
+};
+
+struct acpi_device_wakeup {
+       acpi_handle             gpe_device;
+       acpi_integer            gpe_number;;
+       acpi_integer            sleep_state;
+       struct acpi_handle_list resources;
+       struct acpi_device_wakeup_state state;
+       struct acpi_device_wakeup_flags flags;
+};
 
 /* Device */
 
@@ -258,11 +276,13 @@ struct acpi_device {
        struct acpi_device      *parent;
        struct list_head        children;
        struct list_head        node;
+       struct list_head        wakeup_list;
        struct list_head        g_list;
        struct acpi_device_status status;
        struct acpi_device_flags flags;
        struct acpi_device_pnp  pnp;
        struct acpi_device_power power;
+       struct acpi_device_wakeup wakeup;
        struct acpi_device_perf performance;
        struct acpi_device_dir  dir;
        struct acpi_device_ops  ops;
index e53a918..54ae84d 100644 (file)
@@ -296,7 +296,7 @@ acpi_install_gpe_handler (
        acpi_handle                     gpe_device,
        u32                             gpe_number,
        u32                             type,
-       acpi_gpe_handler                handler,
+       acpi_event_handler              address,
        void                            *context);
 
 acpi_status
@@ -312,7 +312,7 @@ acpi_status
 acpi_remove_gpe_handler (
        acpi_handle                     gpe_device,
        u32                             gpe_number,
-       acpi_gpe_handler                handler);
+       acpi_event_handler              address);
 
 acpi_status
 acpi_enable_event (
@@ -333,6 +333,12 @@ acpi_get_event_status (
        u32                             event,
        acpi_event_status               *event_status);
 
+acpi_status
+acpi_set_gpe_type (
+       acpi_handle                     gpe_device,
+       u32                             gpe_number,
+       u8                              type);
+
 acpi_status
 acpi_enable_gpe (
        acpi_handle                     gpe_device,
index 56a3782..e9a2b32 100644 (file)
 struct acpi_walk_state
 {
        u8                                  data_type;                          /* To differentiate various internal objs MUST BE FIRST!*/\
+       u8                                  walk_type;
        acpi_owner_id                       owner_id;                           /* Owner of objects created during the walk */
        u8                                  last_predicate;                     /* Result of last predicate */
+       u8                                  reserved;                           /* For alignment */
        u8                                  current_result;                     /* */
        u8                                  next_op_info;                       /* Info about next_op */
        u8                                  num_operands;                       /* Stack pointer for Operands[] array */
        u8                                  return_used;
-       u8                                  walk_type;
        u16                                 opcode;                             /* Current AML opcode */
        u8                                  scope_depth;
        u8                                  reserved1;
@@ -91,7 +92,8 @@ struct acpi_walk_state
        struct acpi_namespace_node          arguments[ACPI_METHOD_NUM_ARGS];    /* Control method arguments */
        union acpi_operand_object           **caller_return_desc;
        union acpi_generic_state            *control_state;                     /* List of control states (nested IFs) */
-       struct acpi_namespace_node          *deferred_node;                      /* Used when executing deferred opcodes */
+       struct acpi_namespace_node          *deferred_node;                     /* Used when executing deferred opcodes */
+       struct acpi_gpe_event_info          *gpe_event_info;                    /* Info for GPE (_Lxx/_Exx methods only */
        struct acpi_namespace_node          local_variables[ACPI_METHOD_NUM_LOCALS];    /* Control method locals */
        struct acpi_namespace_node          *method_call_node;                  /* Called method Node*/
        union acpi_parse_object             *method_call_op;                    /* method_call Op if running a method */
@@ -200,4 +202,21 @@ union acpi_aml_operands
 };
 
 
+/* Internal method parameter list */
+
+struct acpi_parameter_info
+{
+       struct acpi_namespace_node      *node;
+       union acpi_operand_object       **parameters;
+       union acpi_operand_object       *return_object;
+       u8                              parameter_type;
+       u8                              return_object_type;
+};
+
+/* Types for parameter_type above */
+
+#define ACPI_PARAM_ARGS                 0
+#define ACPI_PARAM_GPE                  1
+
+
 #endif
index 55680ad..b380c23 100644 (file)
@@ -288,19 +288,6 @@ struct smart_battery_table
 };
 
 
-/*
- * High performance timer
- */
-struct hpet_table
-{
-       ACPI_TABLE_HEADER_DEF
-       u32                             hardware_id;
-       u32                             base_address [3];
-       u8                              hpet_number;
-       u16                             clock_tick;
-       u8                              attributes;
-};
-
 #pragma pack()
 
 
@@ -344,4 +331,20 @@ struct acpi_table_support
 #include "actbl2.h"   /* Acpi 2.0 table definitions */
 
 
+#pragma pack(1)
+/*
+ * High performance timer
+ */
+struct hpet_table
+{
+       ACPI_TABLE_HEADER_DEF
+       u32                             hardware_id;
+       struct acpi_generic_address     base_address;
+       u8                              hpet_number;
+       u16                             clock_tick;
+       u8                              attributes;
+};
+
+#pragma pack()
+
 #endif /* __ACTBL_H__ */
index e6120c8..8bee457 100644 (file)
@@ -557,34 +557,56 @@ typedef u32                                     acpi_event_status;
 #define ACPI_GPE_MAX                    0xFF
 #define ACPI_NUM_GPE                    256
 
+#define ACPI_GPE_ENABLE                 0
+#define ACPI_GPE_DISABLE                1
+
+
 /*
  * GPE info flags - Per GPE
- * +---------+-+-+-+
- * |Bits 8:3 |2|1|0|
- * +---------+-+-+-+
- *          | | | |
- *          | | | +- Edge or Level Triggered
- *          | | +--- Type: Wake or Runtime
- *          | +----- Enabled for wake?
- *          +--------<Reserved>
+ * +-+-+-+---+---+-+
+ * |7|6|5|4:3|2:1|0|
+ * +-+-+-+---+---+-+
+ *  | | |  |   |  |
+ *  | | |  |   |  +--- Interrupt type: Edge or Level Triggered
+ *  | | |  |   +--- Type: Wake-only, Runtime-only, or wake/runtime
+ *  | | |  +--- Type of dispatch -- to method, handler, or none
+ *  | | +--- Enabled for runtime?
+ *  | +--- Enabled for wake?
+ *  +--- System state when GPE ocurred (running/waking)
  */
-#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 1
-#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 1
-#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0
+#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 0x01
+#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 0x01
+#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0x00
+
+#define ACPI_GPE_TYPE_MASK              (u8) 0x06
+#define ACPI_GPE_TYPE_WAKE_RUN          (u8) 0x06
+#define ACPI_GPE_TYPE_WAKE              (u8) 0x02
+#define ACPI_GPE_TYPE_RUNTIME           (u8) 0x04    /* Default */
+
+#define ACPI_GPE_DISPATCH_MASK          (u8) 0x18
+#define ACPI_GPE_DISPATCH_HANDLER       (u8) 0x08
+#define ACPI_GPE_DISPATCH_METHOD        (u8) 0x10
+#define ACPI_GPE_DISPATCH_NOT_USED      (u8) 0x00    /* Default */
+
+#define ACPI_GPE_RUN_ENABLE_MASK        (u8) 0x20
+#define ACPI_GPE_RUN_ENABLED            (u8) 0x20
+#define ACPI_GPE_RUN_DISABLED           (u8) 0x00    /* Default */
 
-#define ACPI_GPE_TYPE_MASK              (u8) 2
-#define ACPI_GPE_TYPE_WAKE              (u8) 2
-#define ACPI_GPE_TYPE_RUNTIME           (u8) 0       /* Default */
+#define ACPI_GPE_WAKE_ENABLE_MASK       (u8) 0x40
+#define ACPI_GPE_WAKE_ENABLED           (u8) 0x40
+#define ACPI_GPE_WAKE_DISABLED          (u8) 0x00    /* Default */
 
-#define ACPI_GPE_ENABLE_MASK            (u8) 4
-#define ACPI_GPE_ENABLED                (u8) 4
-#define ACPI_GPE_DISABLED               (u8) 0       /* Default */
+#define ACPI_GPE_ENABLE_MASK            (u8) 0x60    /* Both run/wake */
+
+#define ACPI_GPE_SYSTEM_MASK            (u8) 0x80
+#define ACPI_GPE_SYSTEM_RUNNING         (u8) 0x80
+#define ACPI_GPE_SYSTEM_WAKING          (u8) 0x00
 
 /*
  * Flags for GPE and Lock interfaces
  */
-#define ACPI_EVENT_WAKE_ENABLE          0x2
-#define ACPI_EVENT_WAKE_DISABLE         0x2
+#define ACPI_EVENT_WAKE_ENABLE          0x2             /* acpi_gpe_enable */
+#define ACPI_EVENT_WAKE_DISABLE         0x2             /* acpi_gpe_disable */
 
 #define ACPI_NOT_ISR                    0x1
 #define ACPI_ISR                        0x0
@@ -592,9 +614,10 @@ typedef u32                                     acpi_event_status;
 
 /* Notify types */
 
-#define ACPI_SYSTEM_NOTIFY              0
-#define ACPI_DEVICE_NOTIFY              1
-#define ACPI_MAX_NOTIFY_HANDLER_TYPE    1
+#define ACPI_SYSTEM_NOTIFY              0x1
+#define ACPI_DEVICE_NOTIFY              0x2
+#define ACPI_ALL_NOTIFY                 0x3
+#define ACPI_MAX_NOTIFY_HANDLER_TYPE    0x3
 
 #define ACPI_MAX_SYS_NOTIFY             0x7f
 
@@ -775,11 +798,11 @@ struct acpi_system_info
  */
 
 typedef u32
-(ACPI_SYSTEM_XFACE *OSD_HANDLER) (
+(ACPI_SYSTEM_XFACE *acpi_osd_handler) (
        void                            *context);
 
 typedef void
-(ACPI_SYSTEM_XFACE *OSD_EXECUTION_CALLBACK) (
+(ACPI_SYSTEM_XFACE *acpi_osd_exec_callback) (
        void                            *context);
 
 /*
@@ -789,10 +812,6 @@ typedef
 u32 (*acpi_event_handler) (
        void                                *context);
 
-typedef
-void (*acpi_gpe_handler) (
-       void                                *context);
-
 typedef
 void (*acpi_notify_handler) (
        acpi_handle                         device,
@@ -880,6 +899,7 @@ struct acpi_compatible_id_list
 #define ACPI_VALID_HID                  0x0004
 #define ACPI_VALID_UID                  0x0008
 #define ACPI_VALID_CID                  0x0010
+#define ACPI_VALID_SXDS                 0x0020
 
 
 #define ACPI_COMMON_OBJ_INFO \
@@ -899,12 +919,12 @@ struct acpi_device_info
 {
        ACPI_COMMON_OBJ_INFO;
 
-       u8                                  highest_dstates[4]; /* _sx_d values 0xFF indicates not valid */
        u32                                 valid;              /* Indicates which fields below are valid */
        u32                                 current_status;     /* _STA value */
        acpi_integer                        address;            /* _ADR value if any */
        struct acpi_device_id               hardware_id;        /* _HID value if any */
        struct acpi_device_id               unique_id;          /* _UID value if any */
+       u8                                  highest_dstates[4]; /* _sx_d values: 0xFF indicates not valid */
        struct acpi_compatible_id_list      compatibility_id;   /* List of _CIDs if any */
 };
 
index 9a0cd41..7964aaf 100644 (file)
 #define COMPILER_DEPENDENT_INT64   long long
 #define COMPILER_DEPENDENT_UINT64  unsigned long long
 
-
-/* Name of host operating system (returned by the _OS_ namespace object) */
-
-#define ACPI_OS_NAME         "Intel ACPI/CA Core Subsystem"
-
-/* This macro is used to tag functions as "printf-like" because
+/*
+ * This macro is used to tag functions as "printf-like" because
  * some compilers can catch printf format string problems. MSVC
  * doesn't, so this is proprocessed away.
  */
index 709ea3e..d97daf4 100644 (file)
@@ -95,7 +95,7 @@ struct exec
    Worse, we have to notice the start address before swapping to use
    /sbin/loader, which of course is _not_ a TASO application.  */
 #define SET_AOUT_PERSONALITY(BFPM, EX) \
-       set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000 \
+       set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000L \
                           ? ADDR_LIMIT_32BIT : 0) | PER_OSF4))
 
 #define STACK_TOP \
index 61bd72e..ae1e0a5 100644 (file)
@@ -9,15 +9,7 @@
   __asm__ __volatile__("call_pal %0  # bugchk\n\t"".long %1\n\t.8byte %2" \
                       : : "i" (PAL_bugchk), "i"(__LINE__), "i"(__FILE__))
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define PAGE_BUG(page) BUG()
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
index f74d7ec..e69b295 100644 (file)
@@ -20,6 +20,6 @@
 
 #define L1_CACHE_ALIGN(x)  (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 #define SMP_CACHE_BYTES    L1_CACHE_BYTES
-#define L1_CACHE_SHIFT_MAX 6   /* largest L1 which this arch supports */
+#define L1_CACHE_SHIFT_MAX L1_CACHE_SHIFT
 
 #endif
index dcfa94b..399c33b 100644 (file)
@@ -17,9 +17,9 @@
 # define __kernel_extbl(val, shift)    __builtin_alpha_extbl(val, shift)
 # define __kernel_extwl(val, shift)    __builtin_alpha_extwl(val, shift)
 # define __kernel_cmpbge(a, b)         __builtin_alpha_cmpbge(a, b)
-# define __kernel_cttz(x)              __builtin_ctz(x)
-# define __kernel_ctlz(x)              __builtin_clz(x)
-# define __kernel_ctpop(x)             __builtin_popcount(x)
+# define __kernel_cttz(x)              __builtin_ctzl(x)
+# define __kernel_ctlz(x)              __builtin_clzl(x)
+# define __kernel_ctpop(x)             __builtin_popcountl(x)
 #else
 # define __kernel_insbl(val, shift)                                    \
   ({ unsigned long __kir;                                              \
   __asm__("stw %1,%0" : "=m"(mem) : "r"(val))
 #endif
 
+/* Some idiots over in <linux/compiler.h> thought inline should imply
+   always_inline.  This breaks stuff.  We'll include this file whenever
+   we run into such problems.  */
+
+#include <linux/compiler.h>
+#undef inline
+#undef __inline__
+#undef __inline
+
+
 #endif /* __ALPHA_COMPILER_H */
index b32084e..6785ff7 100644 (file)
@@ -370,178 +370,142 @@ struct el_apecs_procdata
  * data to/from the right byte-lanes.
  */
 
-#define vip    volatile int *
-#define vuip   volatile unsigned int *
-#define vulp   volatile unsigned long *
-
-__EXTERN_INLINE u8 apecs_inb(unsigned long addr)
+#define vip    volatile int __force *
+#define vuip   volatile unsigned int __force *
+#define vulp   volatile unsigned long __force *
+
+#define APECS_SET_HAE                                          \
+       do {                                                    \
+               if (addr >= (1UL << 24)) {                      \
+                       unsigned long msb = addr & 0xf8000000;  \
+                       addr -= msb;                            \
+                       set_hae(msb);                           \
+               }                                               \
+       } while (0)
+
+__EXTERN_INLINE unsigned int apecs_ioread8(void __iomem *xaddr)
 {
-       long result = *(vip) ((addr << 5) + APECS_IO + 0x00);
+       unsigned long addr = (unsigned long) xaddr;
+       unsigned long result, base_and_type;
+
+       if (addr >= APECS_DENSE_MEM) {
+               addr -= APECS_DENSE_MEM;
+               APECS_SET_HAE;
+               base_and_type = APECS_SPARSE_MEM + 0x00;
+       } else {
+               addr -= APECS_IO;
+               base_and_type = APECS_IO + 0x00;
+       }
+
+       result = *(vip) ((addr << 5) + base_and_type);
        return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE void apecs_outb(u8 b, unsigned long addr)
+__EXTERN_INLINE void apecs_iowrite8(u8 b, void __iomem *xaddr)
 {
-       unsigned long w;
+       unsigned long addr = (unsigned long) xaddr;
+       unsigned long w, base_and_type;
+
+       if (addr >= APECS_DENSE_MEM) {
+               addr -= APECS_DENSE_MEM;
+               APECS_SET_HAE;
+               base_and_type = APECS_SPARSE_MEM + 0x00;
+       } else {
+               addr -= APECS_IO;
+               base_and_type = APECS_IO + 0x00;
+       }
 
        w = __kernel_insbl(b, addr & 3);
-       *(vuip) ((addr << 5) + APECS_IO + 0x00) = w;
-       mb();
-}
-
-__EXTERN_INLINE u16 apecs_inw(unsigned long addr)
-{
-       long result = *(vip) ((addr << 5) + APECS_IO + 0x08);
-       return __kernel_extwl(result, addr & 3);
+       *(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE void apecs_outw(u16 b, unsigned long addr)
-{
-       unsigned long w;
-
-       w = __kernel_inswl(b, addr & 3);
-       *(vuip) ((addr << 5) + APECS_IO + 0x08) = w;
-       mb();
-}
-
-__EXTERN_INLINE u32 apecs_inl(unsigned long addr)
-{
-       return *(vuip) ((addr << 5) + APECS_IO + 0x18);
-}
-
-__EXTERN_INLINE void apecs_outl(u32 b, unsigned long addr)
-{
-       *(vuip) ((addr << 5) + APECS_IO + 0x18) = b;
-       mb();
-}
-
-
-/*
- * Memory functions.  64-bit and 32-bit accesses are done through
- * dense memory space, everything else through sparse space.
- */
-
-__EXTERN_INLINE u8 apecs_readb(unsigned long addr)
+__EXTERN_INLINE unsigned int apecs_ioread16(void __iomem *xaddr)
 {
-       unsigned long result, msb;
-
-       addr -= APECS_DENSE_MEM;
-       if (addr >= (1UL << 24)) {
-               msb = addr & 0xf8000000;
-               addr -= msb;
-               set_hae(msb);
+       unsigned long addr = (unsigned long) xaddr;
+       unsigned long result, base_and_type;
+
+       if (addr >= APECS_DENSE_MEM) {
+               addr -= APECS_DENSE_MEM;
+               APECS_SET_HAE;
+               base_and_type = APECS_SPARSE_MEM + 0x08;
+       } else {
+               addr -= APECS_IO;
+               base_and_type = APECS_IO + 0x08;
        }
-       result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x00);
-       return __kernel_extbl(result, addr & 3);
-}
 
-__EXTERN_INLINE u16 apecs_readw(unsigned long addr)
-{
-       unsigned long result, msb;
-
-       addr -= APECS_DENSE_MEM;
-       if (addr >= (1UL << 24)) {
-               msb = addr & 0xf8000000;
-               addr -= msb;
-               set_hae(msb);
-       }
-       result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x08);
+       result = *(vip) ((addr << 5) + base_and_type);
        return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE u32 apecs_readl(unsigned long addr)
-{
-       return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 apecs_readq(unsigned long addr)
-{
-       return *(vulp)addr;
-}
-
-__EXTERN_INLINE void apecs_writeb(u8 b, unsigned long addr)
+__EXTERN_INLINE void apecs_iowrite16(u16 b, void __iomem *xaddr)
 {
-       unsigned long msb;
-
-       addr -= APECS_DENSE_MEM;
-       if (addr >= (1UL << 24)) {
-               msb = addr & 0xf8000000;
-               addr -= msb;
-               set_hae(msb);
+       unsigned long addr = (unsigned long) xaddr;
+       unsigned long w, base_and_type;
+
+       if (addr >= APECS_DENSE_MEM) {
+               addr -= APECS_DENSE_MEM;
+               APECS_SET_HAE;
+               base_and_type = APECS_SPARSE_MEM + 0x08;
+       } else {
+               addr -= APECS_IO;
+               base_and_type = APECS_IO + 0x08;
        }
-       *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00) = b * 0x01010101;
+
+       w = __kernel_inswl(b, addr & 3);
+       *(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE void apecs_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE unsigned int apecs_ioread32(void __iomem *xaddr)
 {
-       unsigned long msb;
-
-       addr -= APECS_DENSE_MEM;
-       if (addr >= (1UL << 24)) {
-               msb = addr & 0xf8000000;
-               addr -= msb;
-               set_hae(msb);
-       }
-       *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08) = b * 0x00010001;
+       unsigned long addr = (unsigned long) xaddr;
+       if (addr < APECS_DENSE_MEM)
+               addr = ((addr - APECS_IO) << 5) + APECS_IO + 0x18;
+       return *(vuip)addr;
 }
 
-__EXTERN_INLINE void apecs_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE void apecs_iowrite32(u32 b, void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
+       if (addr < APECS_DENSE_MEM)
+               addr = ((addr - APECS_IO) << 5) + APECS_IO + 0x18;
        *(vuip)addr = b;
 }
 
-__EXTERN_INLINE void apecs_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void __iomem *apecs_ioportmap(unsigned long addr)
 {
-       *(vulp)addr = b;
+       return (void __iomem *)(addr + APECS_IO);
 }
 
-__EXTERN_INLINE unsigned long apecs_ioremap(unsigned long addr,
-                                           unsigned long size
-                                           __attribute__((unused)))
+__EXTERN_INLINE void __iomem *apecs_ioremap(unsigned long addr,
+                                           unsigned long size)
 {
-       return addr + APECS_DENSE_MEM;
+       return (void __iomem *)(addr + APECS_DENSE_MEM);
 }
 
-__EXTERN_INLINE void apecs_iounmap(unsigned long addr)
+__EXTERN_INLINE int apecs_is_ioaddr(unsigned long addr)
 {
-       return;
+       return addr >= IDENT_ADDR + 0x180000000UL;
 }
 
-__EXTERN_INLINE int apecs_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE int apecs_is_mmio(const volatile void __iomem *addr)
 {
-       return addr >= IDENT_ADDR + 0x180000000UL;
+       return (unsigned long)addr >= APECS_DENSE_MEM;
 }
 
+#undef APECS_SET_HAE
+
 #undef vip
 #undef vuip
 #undef vulp
 
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)               apecs_inb((unsigned long)(p))
-#define __inw(p)               apecs_inw((unsigned long)(p))
-#define __inl(p)               apecs_inl((unsigned long)(p))
-#define __outb(x,p)            apecs_outb((x),(unsigned long)(p))
-#define __outw(x,p)            apecs_outw((x),(unsigned long)(p))
-#define __outl(x,p)            apecs_outl((x),(unsigned long)(p))
-#define __readb(a)             apecs_readb((unsigned long)(a))
-#define __readw(a)             apecs_readw((unsigned long)(a))
-#define __readl(a)             apecs_readl((unsigned long)(a))
-#define __readq(a)             apecs_readq((unsigned long)(a))
-#define __writeb(x,a)          apecs_writeb((x),(unsigned long)(a))
-#define __writew(x,a)          apecs_writew((x),(unsigned long)(a))
-#define __writel(x,a)          apecs_writel((x),(unsigned long)(a))
-#define __writeq(x,a)          apecs_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)         apecs_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)           apecs_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)         apecs_is_ioaddr((unsigned long)(a))
-
-#define __raw_readl(a)         __readl(a)
-#define __raw_readq(a)         __readq(a)
-#define __raw_writel(v,a)      __writel((v),(a))
-#define __raw_writeq(v,a)      __writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX            apecs
+#define apecs_trivial_io_bw    0
+#define apecs_trivial_io_lq    0
+#define apecs_trivial_rw_bw    2
+#define apecs_trivial_rw_lq    1
+#define apecs_trivial_iounmap  1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
index e5eca2d..549550f 100644 (file)
@@ -306,90 +306,6 @@ struct el_CIA_sysdata_mcheck {
  * get at PCI memory and I/O.
  */
 
-#define vucp   volatile unsigned char *
-#define vusp   volatile unsigned short *
-#define vip    volatile int *
-#define vuip   volatile unsigned int *
-#define vulp   volatile unsigned long *
-
-__EXTERN_INLINE u8 cia_inb(unsigned long addr)
-{
-       long result;
-       result = *(vip) ((addr << 5) + CIA_IO + 0x00);
-       return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE void cia_outb(u8 b, unsigned long addr)
-{
-       unsigned long w = __kernel_insbl(b, addr & 3);
-       *(vuip) ((addr << 5) + CIA_IO + 0x00) = w;
-       mb();
-}
-
-__EXTERN_INLINE u16 cia_inw(unsigned long addr)
-{
-       long result;
-       result = *(vip) ((addr << 5) + CIA_IO + 0x08);
-       return __kernel_extwl(result, addr & 3);
-}
-
-__EXTERN_INLINE void cia_outw(u16 b, unsigned long addr)
-{
-       unsigned long w = __kernel_inswl(b, addr & 3);
-       *(vuip) ((addr << 5) + CIA_IO + 0x08) = w;
-       mb();
-}
-
-__EXTERN_INLINE u32 cia_inl(unsigned long addr)
-{
-       return *(vuip) ((addr << 5) + CIA_IO + 0x18);
-}
-
-__EXTERN_INLINE void cia_outl(u32 b, unsigned long addr)
-{
-       *(vuip) ((addr << 5) + CIA_IO + 0x18) = b;
-       mb();
-}
-
-__EXTERN_INLINE u8 cia_bwx_inb(unsigned long addr)
-{
-       /* ??? I wish I could get rid of this.  But there's no ioremap
-          equivalent for I/O space.  PCI I/O can be forced into the
-          CIA BWX I/O region, but that doesn't take care of legacy
-          ISA crap.  */
-
-       return __kernel_ldbu(*(vucp)(addr+CIA_BW_IO));
-}
-
-__EXTERN_INLINE void cia_bwx_outb(u8 b, unsigned long addr)
-{
-       __kernel_stb(b, *(vucp)(addr+CIA_BW_IO));
-       mb();
-}
-
-__EXTERN_INLINE u16 cia_bwx_inw(unsigned long addr)
-{
-       return __kernel_ldwu(*(vusp)(addr+CIA_BW_IO));
-}
-
-__EXTERN_INLINE void cia_bwx_outw(u16 b, unsigned long addr)
-{
-       __kernel_stw(b, *(vusp)(addr+CIA_BW_IO));
-       mb();
-}
-
-__EXTERN_INLINE u32 cia_bwx_inl(unsigned long addr)
-{
-       return *(vuip)(addr+CIA_BW_IO);
-}
-
-__EXTERN_INLINE void cia_bwx_outl(u32 b, unsigned long addr)
-{
-       *(vuip)(addr+CIA_BW_IO) = b;
-       mb();
-}
-
-
 /*
  * Memory functions.  64-bit and 32-bit accesses are done through
  * dense memory space, everything else through sparse space.
@@ -422,195 +338,158 @@ __EXTERN_INLINE void cia_bwx_outl(u32 b, unsigned long addr)
  *
  */
 
-__EXTERN_INLINE u8 cia_readb(unsigned long addr)
+#define vip    volatile int __force *
+#define vuip   volatile unsigned int __force *
+#define vulp   volatile unsigned long __force *
+
+__EXTERN_INLINE unsigned int cia_ioread8(void __iomem *xaddr)
 {
-       unsigned long result;
+       unsigned long addr = (unsigned long) xaddr;
+       unsigned long result, base_and_type;
 
+       /* We can use CIA_MEM_R1_MASK for io ports too, since it is large
+          enough to cover all io ports, and smaller than CIA_IO.  */
        addr &= CIA_MEM_R1_MASK;
-       result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x00);
+       if (addr >= CIA_DENSE_MEM)
+               base_and_type = CIA_SPARSE_MEM + 0x00;
+       else
+               base_and_type = CIA_IO + 0x00;
+
+       result = *(vip) ((addr << 5) + base_and_type);
        return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE u16 cia_readw(unsigned long addr)
+__EXTERN_INLINE void cia_iowrite8(u8 b, void __iomem *xaddr)
 {
-       unsigned long result;
+       unsigned long addr = (unsigned long) xaddr;
+       unsigned long w, base_and_type;
 
        addr &= CIA_MEM_R1_MASK;
-       result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x08);
-       return __kernel_extwl(result, addr & 3);
-}
+       if (addr >= CIA_DENSE_MEM)
+               base_and_type = CIA_SPARSE_MEM + 0x00;
+       else
+               base_and_type = CIA_IO + 0x00;
 
-__EXTERN_INLINE void cia_writeb(u8 b, unsigned long addr)
-{
-       unsigned long w;
-
-       addr &= CIA_MEM_R1_MASK;
        w = __kernel_insbl(b, addr & 3);
-       *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) = w;
+       *(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE void cia_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE unsigned int cia_ioread16(void __iomem *xaddr)
 {
-       unsigned long w;
+       unsigned long addr = (unsigned long) xaddr;
+       unsigned long result, base_and_type;
 
        addr &= CIA_MEM_R1_MASK;
-       w = __kernel_inswl(b, addr & 3);
-       *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08) = w;
-}
-
-__EXTERN_INLINE u32 cia_readl(unsigned long addr)
-{
-       return *(vuip)addr;
-}
-
-__EXTERN_INLINE u64 cia_readq(unsigned long addr)
-{
-       return *(vulp)addr;
-}
-
-__EXTERN_INLINE void cia_writel(u32 b, unsigned long addr)
-{
-       *(vuip)addr = b;
-}
+       if (addr >= CIA_DENSE_MEM)
+               base_and_type = CIA_SPARSE_MEM + 0x08;
+       else
+               base_and_type = CIA_IO + 0x08;
 
-__EXTERN_INLINE void cia_writeq(u64 b, unsigned long addr)
-{
-       *(vulp)addr = b;
+       result = *(vip) ((addr << 5) + base_and_type);
+       return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE unsigned long cia_ioremap(unsigned long addr,
-                                         unsigned long size
-                                         __attribute__((unused)))
+__EXTERN_INLINE void cia_iowrite16(u16 b, void __iomem *xaddr)
 {
-       return addr + CIA_DENSE_MEM;
-}
+       unsigned long addr = (unsigned long) xaddr;
+       unsigned long w, base_and_type;
 
-__EXTERN_INLINE void cia_iounmap(unsigned long addr)
-{
-       return;
-}
+       addr &= CIA_MEM_R1_MASK;
+       if (addr >= CIA_DENSE_MEM)
+               base_and_type = CIA_SPARSE_MEM + 0x08;
+       else
+               base_and_type = CIA_IO + 0x08;
 
-__EXTERN_INLINE u8 cia_bwx_readb(unsigned long addr)
-{
-       return __kernel_ldbu(*(vucp)addr);
+       w = __kernel_inswl(b, addr & 3);
+       *(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE u16 cia_bwx_readw(unsigned long addr)
+__EXTERN_INLINE unsigned int cia_ioread32(void __iomem *xaddr)
 {
-       return __kernel_ldwu(*(vusp)addr);
+       unsigned long addr = (unsigned long) xaddr;
+       if (addr < CIA_DENSE_MEM)
+               addr = ((addr - CIA_IO) << 5) + CIA_IO + 0x18;
+       return *(vuip)addr;
 }
 
-__EXTERN_INLINE u32 cia_bwx_readl(unsigned long addr)
+__EXTERN_INLINE void cia_iowrite32(u32 b, void __iomem *xaddr)
 {
-       return *(vuip)addr;
+       unsigned long addr = (unsigned long) xaddr;
+       if (addr < CIA_DENSE_MEM)
+               addr = ((addr - CIA_IO) << 5) + CIA_IO + 0x18;
+       *(vuip)addr = b;
 }
 
-__EXTERN_INLINE u64 cia_bwx_readq(unsigned long addr)
+__EXTERN_INLINE void __iomem *cia_ioportmap(unsigned long addr)
 {
-       return *(vulp)addr;
+       return (void __iomem *)(addr + CIA_IO);
 }
 
-__EXTERN_INLINE void cia_bwx_writeb(u8 b, unsigned long addr)
+__EXTERN_INLINE void __iomem *cia_ioremap(unsigned long addr,
+                                         unsigned long size)
 {
-       __kernel_stb(b, *(vucp)addr);
+       return (void __iomem *)(addr + CIA_DENSE_MEM);
 }
 
-__EXTERN_INLINE void cia_bwx_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE int cia_is_ioaddr(unsigned long addr)
 {
-       __kernel_stw(b, *(vusp)addr);
+       return addr >= IDENT_ADDR + 0x8000000000UL;
 }
 
-__EXTERN_INLINE void cia_bwx_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE int cia_is_mmio(const volatile void __iomem *addr)
 {
-       *(vuip)addr = b;
+       return (unsigned long)addr >= CIA_DENSE_MEM;
 }
 
-__EXTERN_INLINE void cia_bwx_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void __iomem *cia_bwx_ioportmap(unsigned long addr)
 {
-       *(vulp)addr = b;
+       return (void __iomem *)(addr + CIA_BW_IO);
 }
 
-__EXTERN_INLINE unsigned long cia_bwx_ioremap(unsigned long addr,
+__EXTERN_INLINE void __iomem *cia_bwx_ioremap(unsigned long addr,
                                              unsigned long size)
 {
-       return addr + CIA_BW_MEM;
+       return (void __iomem *)(addr + CIA_BW_MEM);
 }
 
-__EXTERN_INLINE void cia_bwx_iounmap(unsigned long addr)
+__EXTERN_INLINE int cia_bwx_is_ioaddr(unsigned long addr)
 {
-       return;
+       return addr >= IDENT_ADDR + 0x8000000000UL;
 }
 
-__EXTERN_INLINE int cia_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE int cia_bwx_is_mmio(const volatile void __iomem *addr)
 {
-       return addr >= IDENT_ADDR + 0x8000000000UL;
+       return (unsigned long)addr < CIA_BW_IO;
 }
 
-#undef vucp
-#undef vusp
 #undef vip
 #undef vuip
 #undef vulp
 
-#ifdef __WANT_IO_DEF
-
+#undef __IO_PREFIX
+#define __IO_PREFIX            cia
+#define cia_trivial_rw_bw      2
+#define cia_trivial_rw_lq      1
+#define cia_trivial_io_bw      0
+#define cia_trivial_io_lq      0
+#define cia_trivial_iounmap    1
+#include <asm/io_trivial.h>
+
+#undef __IO_PREFIX
+#define __IO_PREFIX            cia_bwx
+#define cia_bwx_trivial_rw_bw  1
+#define cia_bwx_trivial_rw_lq  1
+#define cia_bwx_trivial_io_bw  1
+#define cia_bwx_trivial_io_lq  1
+#define cia_bwx_trivial_iounmap        1
+#include <asm/io_trivial.h>
+
+#undef __IO_PREFIX
 #ifdef CONFIG_ALPHA_PYXIS
-# define __inb(p)              cia_bwx_inb((unsigned long)(p))
-# define __inw(p)              cia_bwx_inw((unsigned long)(p))
-# define __inl(p)              cia_bwx_inl((unsigned long)(p))
-# define __outb(x,p)           cia_bwx_outb((x),(unsigned long)(p))
-# define __outw(x,p)           cia_bwx_outw((x),(unsigned long)(p))
-# define __outl(x,p)           cia_bwx_outl((x),(unsigned long)(p))
-# define __readb(a)            cia_bwx_readb((unsigned long)(a))
-# define __readw(a)            cia_bwx_readw((unsigned long)(a))
-# define __readl(a)            cia_bwx_readl((unsigned long)(a))
-# define __readq(a)            cia_bwx_readq((unsigned long)(a))
-# define __writeb(x,a)         cia_bwx_writeb((x),(unsigned long)(a))
-# define __writew(x,a)         cia_bwx_writew((x),(unsigned long)(a))
-# define __writel(x,a)         cia_bwx_writel((x),(unsigned long)(a))
-# define __writeq(x,a)         cia_bwx_writeq((x),(unsigned long)(a))
-# define __ioremap(a,s)                cia_bwx_ioremap((unsigned long)(a),(s))
-# define __iounmap(a)           cia_bwx_iounmap((unsigned long)(a))
-# define inb(p)                        __inb(p)
-# define inw(p)                        __inw(p)
-# define inl(p)                        __inl(p)
-# define outb(x,p)             __outb((x),(p))
-# define outw(x,p)             __outw((x),(p))
-# define outl(x,p)             __outl((x),(p))
-# define __raw_readb(a)                __readb(a)
-# define __raw_readw(a)                __readw(a)
-# define __raw_readl(a)                __readl(a)
-# define __raw_readq(a)                __readq(a)
-# define __raw_writeb(x,a)     __writeb((x),(a))
-# define __raw_writew(x,a)     __writew((x),(a))
-# define __raw_writel(x,a)     __writel((x),(a))
-# define __raw_writeq(x,a)     __writeq((x),(a))
+#define __IO_PREFIX            cia_bwx
 #else
-# define __inb(p)              cia_inb((unsigned long)(p))
-# define __inw(p)              cia_inw((unsigned long)(p))
-# define __inl(p)              cia_inl((unsigned long)(p))
-# define __outb(x,p)           cia_outb((x),(unsigned long)(p))
-# define __outw(x,p)           cia_outw((x),(unsigned long)(p))
-# define __outl(x,p)           cia_outl((x),(unsigned long)(p))
-# define __readb(a)            cia_readb((unsigned long)(a))
-# define __readw(a)            cia_readw((unsigned long)(a))
-# define __readl(a)            cia_readl((unsigned long)(a))
-# define __readq(a)            cia_readq((unsigned long)(a))
-# define __writeb(x,a)         cia_writeb((x),(unsigned long)(a))
-# define __writew(x,a)         cia_writew((x),(unsigned long)(a))
-# define __writel(x,a)         cia_writel((x),(unsigned long)(a))
-# define __writeq(x,a)         cia_writeq((x),(unsigned long)(a))
-# define __ioremap(a,s)                cia_ioremap((unsigned long)(a),(s))
-# define __iounmap(a)           cia_iounmap((unsigned long)(a))
-# define __raw_readl(a)                __readl(a)
-# define __raw_readq(a)                __readq(a)
-# define __raw_writel(v,a)     __writel((v),(a))
-# define __raw_writeq(v,a)     __writeq((v),(a))
-#endif /* PYXIS */
-
-#define __is_ioaddr(a)         cia_is_ioaddr((unsigned long)(a))
-
-#endif /* __WANT_IO_DEF */
+#define __IO_PREFIX            cia
+#endif
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
index 9b9a49f..24b2db5 100644 (file)
@@ -190,137 +190,37 @@ struct el_IRONGATE_sysdata_mcheck {
  * K7 can only use linear accesses to get at PCI memory and I/O spaces.
  */
 
-#define vucp   volatile unsigned char *
-#define vusp   volatile unsigned short *
-#define vuip   volatile unsigned int *
-#define vulp   volatile unsigned long *
-
-__EXTERN_INLINE u8 irongate_inb(unsigned long addr)
-{
-       return __kernel_ldbu(*(vucp)(addr + IRONGATE_IO));
-}
-
-__EXTERN_INLINE void irongate_outb(u8 b, unsigned long addr)
-{
-        __kernel_stb(b, *(vucp)(addr + IRONGATE_IO));
-       mb();
-}
-
-__EXTERN_INLINE u16 irongate_inw(unsigned long addr)
-{
-       return __kernel_ldwu(*(vusp)(addr + IRONGATE_IO));
-}
-
-__EXTERN_INLINE void irongate_outw(u16 b, unsigned long addr)
-{
-        __kernel_stw(b, *(vusp)(addr + IRONGATE_IO));
-       mb();
-}
-
-__EXTERN_INLINE u32 irongate_inl(unsigned long addr)
-{
-       return *(vuip)(addr + IRONGATE_IO);
-}
-
-__EXTERN_INLINE void irongate_outl(u32 b, unsigned long addr)
-{
-        *(vuip)(addr + IRONGATE_IO) = b;
-       mb();
-}
-
 /*
  * Memory functions.  All accesses are done through linear space.
  */
 
-__EXTERN_INLINE u8 irongate_readb(unsigned long addr)
+__EXTERN_INLINE void __iomem *irongate_ioportmap(unsigned long addr)
 {
-       return __kernel_ldbu(*(vucp)addr);
+       return (void __iomem *)(addr + IRONGATE_IO);
 }
 
-__EXTERN_INLINE u16 irongate_readw(unsigned long addr)
-{
-       return __kernel_ldwu(*(vusp)addr);
-}
+extern void __iomem *irongate_ioremap(unsigned long addr, unsigned long size);
+extern void irongate_iounmap(volatile void __iomem *addr);
 
-__EXTERN_INLINE u32 irongate_readl(unsigned long addr)
-{
-       return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 irongate_readq(unsigned long addr)
-{
-       return *(vulp)addr;
-}
-
-__EXTERN_INLINE void irongate_writeb(u8 b, unsigned long addr)
-{
-       __kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void irongate_writew(u16 b, unsigned long addr)
-{
-       __kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void irongate_writel(u32 b, unsigned long addr)
-{
-       *(vuip)addr = b;
-}
-
-__EXTERN_INLINE void irongate_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE int irongate_is_ioaddr(unsigned long addr)
 {
-       *(vulp)addr = b;
+       return addr >= IRONGATE_MEM;
 }
 
-extern unsigned long irongate_ioremap(unsigned long addr, unsigned long size);
-extern void irongate_iounmap(unsigned long addr);
-
-__EXTERN_INLINE int irongate_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE int irongate_is_mmio(const volatile void __iomem *xaddr)
 {
-       return addr >= IRONGATE_MEM;
+       unsigned long addr = (unsigned long)xaddr;
+       return addr < IRONGATE_IO || addr >= IRONGATE_CONF;
 }
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)               irongate_inb((unsigned long)(p))
-#define __inw(p)               irongate_inw((unsigned long)(p))
-#define __inl(p)               irongate_inl((unsigned long)(p))
-#define __outb(x,p)            irongate_outb((x),(unsigned long)(p))
-#define __outw(x,p)            irongate_outw((x),(unsigned long)(p))
-#define __outl(x,p)            irongate_outl((x),(unsigned long)(p))
-#define __readb(a)             irongate_readb((unsigned long)(a))
-#define __readw(a)             irongate_readw((unsigned long)(a))
-#define __readl(a)             irongate_readl((unsigned long)(a))
-#define __readq(a)             irongate_readq((unsigned long)(a))
-#define __writeb(x,a)          irongate_writeb((x),(unsigned long)(a))
-#define __writew(x,a)          irongate_writew((x),(unsigned long)(a))
-#define __writel(x,a)          irongate_writel((x),(unsigned long)(a))
-#define __writeq(x,a)          irongate_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)         irongate_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)           irongate_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)         irongate_is_ioaddr((unsigned long)(a))
-
-#define inb(p)                 __inb(p)
-#define inw(p)                 __inw(p)
-#define inl(p)                 __inl(p)
-#define outb(x,p)              __outb((x),(p))
-#define outw(x,p)              __outw((x),(p))
-#define outl(x,p)              __outl((x),(p))
-#define __raw_readb(a)         __readb(a)
-#define __raw_readw(a)         __readw(a)
-#define __raw_readl(a)         __readl(a)
-#define __raw_readq(a)         __readq(a)
-#define __raw_writeb(v,a)      __writeb((v),(a))
-#define __raw_writew(v,a)      __writew((v),(a))
-#define __raw_writel(v,a)      __writel((v),(a))
-#define __raw_writeq(v,a)      __writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX                    irongate
+#define irongate_trivial_rw_bw         1
+#define irongate_trivial_rw_lq         1
+#define irongate_trivial_io_bw         1
+#define irongate_trivial_io_lq         1
+#define irongate_trivial_iounmap       0
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
index a1f2482..30d55fe 100644 (file)
@@ -325,249 +325,48 @@ struct io7 {
  * I/O functions. All access through linear space.
  */
 
-#define vucp   volatile unsigned char *
-#define vusp   volatile unsigned short *
-#define vuip   volatile unsigned int *
-#define vulp   volatile unsigned long *
-
-#ifdef CONFIG_VGA_HOSE
-extern struct pci_controller *pci_vga_hose;
-
-# define __marvel_is_port_vga(a)       \
-        (((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3))
-# define __marvel_is_mem_vga(a)        (((a) >= 0xa0000) && ((a) <= 0xc0000))
-# define FIXUP_IOADDR_VGA(a) do {                      \
-       if (pci_vga_hose && __marvel_is_port_vga(a))    \
-               a += pci_vga_hose->io_space->start;     \
-    } while(0)
-#else
-# define FIXUP_IOADDR_VGA(a)
-#endif 
-
-#define __marvel_is_port_kbd(a)        (((a) == 0x60) || ((a) == 0x64))
-#define __marvel_is_port_rtc(a)        (((a) == 0x70) || ((a) == 0x71))
-
-#define FIXUP_IOADDR_LEGACY(a)
-
-#define FIXUP_IOADDR(a) do {                           \
-       FIXUP_IOADDR_VGA(a);                            \
-        FIXUP_IOADDR_LEGACY(a);                                \
-    } while(0)
-
-#if 0
-# define IOBUG(x) printk x
-# define IOBUG_FILTER_IOADDR(a, x)     \
-    if (!__marvel_is_port_kbd(a) && !__marvel_is_port_rtc(a)) IOBUG(x)
-#else
-# define IOBUG(x)
-# define IOBUG_FILTER_IOADDR(a, x)
-#endif
-
-extern u8 __marvel_rtc_io(int write, u8 b, unsigned long addr);
-#define __marvel_rtc_inb(a)    __marvel_rtc_io(0, 0, (a))
-#define __marvel_rtc_outb(b, a)        __marvel_rtc_io(1, (b), (a))
-
-__EXTERN_INLINE int marvel_is_ioaddr(unsigned long addr)
-{
-       return (addr & (1UL << 40)) != 0; /*FIXME - hardwire*/
-}
-
-__EXTERN_INLINE u8 marvel_inb(unsigned long addr)
-{
-       FIXUP_IOADDR(addr);
-       if (!marvel_is_ioaddr(addr)) {
-               if (__marvel_is_port_kbd(addr))
-                       return (u8)0;
-               if (__marvel_is_port_rtc(addr))
-                       return __marvel_rtc_inb(addr);
-               IOBUG_FILTER_IOADDR(addr, 
-                                   ("Bad IO addr %lx - reading -1\n", addr));
-               return (u8)-1;
-       }
-       return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void marvel_outb(u8 b, unsigned long addr)
-{
-       FIXUP_IOADDR(addr);
-       if (!marvel_is_ioaddr(addr)) {
-               if (__marvel_is_port_rtc(addr)) 
-                       return (void)__marvel_rtc_outb(b, addr);
-               IOBUG_FILTER_IOADDR(addr, 
-                                   ("Bad IO addr %lx - reading -1\n", addr));
-               return;
-       }
-       __kernel_stb(b, *(vucp)addr);
-       mb();
-}
-
-__EXTERN_INLINE u16 marvel_inw(unsigned long addr)
-{
-       FIXUP_IOADDR(addr);
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG_FILTER_IOADDR(addr, 
-                                   ("Bad IO addr %lx - reading -1\n", addr));
-               return (u16)-1;
-       }
-       return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void marvel_outw(u16 w, unsigned long addr)
-{
-       FIXUP_IOADDR(addr);
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG_FILTER_IOADDR(addr, 
-                                   ("Bad IO addr %lx - reading -1\n", addr));
-               return;
-       }
-       __kernel_stw(w, *(vusp)addr);
-       mb();
-}
-
-__EXTERN_INLINE u32 marvel_inl(unsigned long addr)
-{
-       FIXUP_IOADDR(addr);
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG_FILTER_IOADDR(addr, 
-                                   ("Bad IO addr %lx - reading -1\n", addr));
-               return (u32)-1;
-       }
-       return *(vuip)addr;
-}
-
-__EXTERN_INLINE void marvel_outl(u32 l, unsigned long addr)
-{
-       FIXUP_IOADDR(addr);
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG_FILTER_IOADDR(addr, 
-                                   ("Bad IO addr %lx - reading -1\n", addr));
-               return;
-       }
-       *(vuip)addr = l;
-       mb();
-}
-
 /*
  * Memory functions.  All accesses through linear space.
  */
 
-extern unsigned long marvel_ioremap(unsigned long addr, unsigned long size);
-extern void marvel_iounmap(unsigned long addr);
+#define vucp   volatile unsigned char __force *
+#define vusp   volatile unsigned short __force *
 
-__EXTERN_INLINE u8 marvel_readb(unsigned long addr)
-{
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-               return (u8)-1;
-       }
-       return __kernel_ldbu(*(vucp)addr);
-}
+extern unsigned int marvel_ioread8(void __iomem *);
+extern void marvel_iowrite8(u8 b, void __iomem *);
 
-__EXTERN_INLINE u16 marvel_readw(unsigned long addr)
+__EXTERN_INLINE unsigned int marvel_ioread16(void __iomem *addr)
 {
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-               return (u16)-1;
-       }
        return __kernel_ldwu(*(vusp)addr);
 }
 
-__EXTERN_INLINE u32 marvel_readl(unsigned long addr)
-{
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-               return (u32)-1;
-       }
-       return *(vuip)addr;
-}
-
-__EXTERN_INLINE u64 marvel_readq(unsigned long addr)
+__EXTERN_INLINE void marvel_iowrite16(u16 b, void __iomem *addr)
 {
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-               return (u64)-1;
-       }
-       return *(vulp)addr;
+       __kernel_stw(b, *(vusp)addr);
 }
 
-__EXTERN_INLINE void marvel_writeb(u8 b, unsigned long addr)
-{
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-               return;
-       }
-       __kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void marvel_writew(u16 w, unsigned long addr)
-{
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-               return;
-       }
-       __kernel_stw(w, *(vusp)addr);
-}
+extern void __iomem *marvel_ioremap(unsigned long addr, unsigned long size);
+extern void marvel_iounmap(volatile void __iomem *addr);
+extern void __iomem *marvel_ioportmap (unsigned long addr);
 
-__EXTERN_INLINE void marvel_writel(u32 l, unsigned long addr)
-{
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-               return;
-       }
-       *(vuip)addr = l;
-}
-
-__EXTERN_INLINE void marvel_writeq(u64 q, unsigned long addr)
+__EXTERN_INLINE int marvel_is_ioaddr(unsigned long addr)
 {
-       if (!marvel_is_ioaddr(addr)) {
-               IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-               return;
-       }
-       *(vulp)addr = q;
+       return (addr >> 40) & 1;
 }
 
-#undef FIXUP_IOADDR
-#undef FIXUP_IOADDR_LEGACY
-#undef FIXUP_IOADDR_VGA
+extern int marvel_is_mmio(const volatile void __iomem *);
 
 #undef vucp
 #undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)               marvel_inb((unsigned long)(p))
-#define __inw(p)               marvel_inw((unsigned long)(p))
-#define __inl(p)               marvel_inl((unsigned long)(p))
-#define __outb(x,p)            marvel_outb((x),(unsigned long)(p))
-#define __outw(x,p)            marvel_outw((x),(unsigned long)(p))
-#define __outl(x,p)            marvel_outl((x),(unsigned long)(p))
-#define __readb(a)             marvel_readb((unsigned long)(a))
-#define __readw(a)             marvel_readw((unsigned long)(a))
-#define __readl(a)             marvel_readl((unsigned long)(a))
-#define __readq(a)             marvel_readq((unsigned long)(a))
-#define __writeb(x,a)          marvel_writeb((x),(unsigned long)(a))
-#define __writew(x,a)          marvel_writew((x),(unsigned long)(a))
-#define __writel(x,a)          marvel_writel((x),(unsigned long)(a))
-#define __writeq(x,a)          marvel_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)         marvel_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)           marvel_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)         marvel_is_ioaddr((unsigned long)(a))
-
-/* Disable direct inlining of these calls with the debug checks present.  */
-#if 0
-#define __raw_readb(a)         __readb(a)
-#define __raw_readw(a)         __readw(a)
-#define __raw_readl(a)         __readl(a)
-#define __raw_readq(a)         __readq(a)
-#define __raw_writeb(v,a)      __writeb(v,a)
-#define __raw_writew(v,a)      __writew(v,a)
-#define __raw_writel(v,a)      __writel(v,a)
-#define __raw_writeq(v,a)      __writeq(v,a)
-#endif
 
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX            marvel
+#define marvel_trivial_rw_bw   1
+#define marvel_trivial_rw_lq   1
+#define marvel_trivial_io_bw   0
+#define marvel_trivial_io_lq   1
+#define marvel_trivial_iounmap 0
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 # undef __EXTERN_INLINE
index ce5ae2a..5c1c403 100644 (file)
@@ -199,8 +199,8 @@ struct el_t2_procdata_mcheck {
 
 struct el_t2_logout_header {
        unsigned int    elfl_size;      /* size in bytes of logout area. */
-       int             elfl_sbz1:31;   /* Should be zero. */
-       char            elfl_retry:1;   /* Retry flag. */
+       unsigned int    elfl_sbz1:31;   /* Should be zero. */
+       unsigned int    elfl_retry:1;   /* Retry flag. */
        unsigned int    elfl_procoffset; /* Processor-specific offset. */
        unsigned int    elfl_sysoffset;  /* Offset of system-specific. */
        unsigned int    elfl_error_type;        /* PAL error type code. */
@@ -357,13 +357,13 @@ struct el_t2_frame_corrected {
 #define vip    volatile int *
 #define vuip   volatile unsigned int *
 
-__EXTERN_INLINE u8 t2_inb(unsigned long addr)
+static inline u8 t2_inb(unsigned long addr)
 {
        long result = *(vip) ((addr << 5) + T2_IO + 0x00);
        return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE void t2_outb(u8 b, unsigned long addr)
+static inline void t2_outb(u8 b, unsigned long addr)
 {
        unsigned long w;
 
@@ -372,13 +372,13 @@ __EXTERN_INLINE void t2_outb(u8 b, unsigned long addr)
        mb();
 }
 
-__EXTERN_INLINE u16 t2_inw(unsigned long addr)
+static inline u16 t2_inw(unsigned long addr)
 {
        long result = *(vip) ((addr << 5) + T2_IO + 0x08);
        return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE void t2_outw(u16 b, unsigned long addr)
+static inline void t2_outw(u16 b, unsigned long addr)
 {
        unsigned long w;
 
@@ -387,12 +387,12 @@ __EXTERN_INLINE void t2_outw(u16 b, unsigned long addr)
        mb();
 }
 
-__EXTERN_INLINE u32 t2_inl(unsigned long addr)
+static inline u32 t2_inl(unsigned long addr)
 {
        return *(vuip) ((addr << 5) + T2_IO + 0x18);
 }
 
-__EXTERN_INLINE void t2_outl(u32 b, unsigned long addr)
+static inline void t2_outl(u32 b, unsigned long addr)
 {
        *(vuip) ((addr << 5) + T2_IO + 0x18) = b;
        mb();
@@ -438,8 +438,9 @@ __EXTERN_INLINE void t2_outl(u32 b, unsigned long addr)
 
 static spinlock_t t2_hae_lock = SPIN_LOCK_UNLOCKED;
 
-__EXTERN_INLINE u8 t2_readb(unsigned long addr)
+__EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        unsigned long result, msb;
        unsigned long flags;
        spin_lock_irqsave(&t2_hae_lock, flags);
@@ -451,8 +452,9 @@ __EXTERN_INLINE u8 t2_readb(unsigned long addr)
        return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE u16 t2_readw(unsigned long addr)
+__EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        unsigned long result, msb;
        unsigned long flags;
        spin_lock_irqsave(&t2_hae_lock, flags);
@@ -468,8 +470,9 @@ __EXTERN_INLINE u16 t2_readw(unsigned long addr)
  * On SABLE with T2, we must use SPARSE memory even for 32-bit access,
  * because we cannot access all of DENSE without changing its HAE.
  */
-__EXTERN_INLINE u32 t2_readl(unsigned long addr)
+__EXTERN_INLINE u32 t2_readl(const volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        unsigned long result, msb;
        unsigned long flags;
        spin_lock_irqsave(&t2_hae_lock, flags);
@@ -481,8 +484,9 @@ __EXTERN_INLINE u32 t2_readl(unsigned long addr)
        return result & 0xffffffffUL;
 }
 
-__EXTERN_INLINE u64 t2_readq(unsigned long addr)
+__EXTERN_INLINE u64 t2_readq(const volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        unsigned long r0, r1, work, msb;
        unsigned long flags;
        spin_lock_irqsave(&t2_hae_lock, flags);
@@ -496,8 +500,9 @@ __EXTERN_INLINE u64 t2_readq(unsigned long addr)
        return r1 << 32 | r0;
 }
 
-__EXTERN_INLINE void t2_writeb(u8 b, unsigned long addr)
+__EXTERN_INLINE void t2_writeb(u8 b, volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        unsigned long msb, w;
        unsigned long flags;
        spin_lock_irqsave(&t2_hae_lock, flags);
@@ -509,8 +514,9 @@ __EXTERN_INLINE void t2_writeb(u8 b, unsigned long addr)
        spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
-__EXTERN_INLINE void t2_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        unsigned long msb, w;
        unsigned long flags;
        spin_lock_irqsave(&t2_hae_lock, flags);
@@ -526,8 +532,9 @@ __EXTERN_INLINE void t2_writew(u16 b, unsigned long addr)
  * On SABLE with T2, we must use SPARSE memory even for 32-bit access,
  * because we cannot access all of DENSE without changing its HAE.
  */
-__EXTERN_INLINE void t2_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE void t2_writel(u32 b, volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        unsigned long msb;
        unsigned long flags;
        spin_lock_irqsave(&t2_hae_lock, flags);
@@ -538,8 +545,9 @@ __EXTERN_INLINE void t2_writel(u32 b, unsigned long addr)
        spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
-__EXTERN_INLINE void t2_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void t2_writeq(u64 b, volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        unsigned long msb, work;
        unsigned long flags;
        spin_lock_irqsave(&t2_hae_lock, flags);
@@ -552,16 +560,15 @@ __EXTERN_INLINE void t2_writeq(u64 b, unsigned long addr)
        spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
-__EXTERN_INLINE unsigned long t2_ioremap(unsigned long addr, 
-                                        unsigned long size
-                                        __attribute__((unused)))
+__EXTERN_INLINE void __iomem *t2_ioportmap(unsigned long addr)
 {
-       return addr;
+       return (void __iomem *)(addr + T2_IO);
 }
 
-__EXTERN_INLINE void t2_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *t2_ioremap(unsigned long addr, 
+                                        unsigned long size)
 {
-       return;
+       return (void __iomem *)(addr + T2_DENSE_MEM);
 }
 
 __EXTERN_INLINE int t2_is_ioaddr(unsigned long addr)
@@ -569,30 +576,47 @@ __EXTERN_INLINE int t2_is_ioaddr(unsigned long addr)
        return (long)addr >= 0;
 }
 
+__EXTERN_INLINE int t2_is_mmio(const volatile void __iomem *addr)
+{
+       return (unsigned long)addr >= T2_DENSE_MEM;
+}
+
+/* New-style ioread interface.  The mmio routines are so ugly for T2 that
+   it doesn't make sense to merge the pio and mmio routines.  */
+
+#define IOPORT(OS, NS)                                                 \
+__EXTERN_INLINE unsigned int t2_ioread##NS(void __iomem *xaddr)                \
+{                                                                      \
+       if (t2_is_mmio(xaddr))                                          \
+               return t2_read##OS(xaddr - T2_DENSE_MEM);               \
+       else                                                            \
+               return t2_in##OS((unsigned long)xaddr - T2_IO);         \
+}                                                                      \
+__EXTERN_INLINE void t2_iowrite##NS(u##NS b, void __iomem *xaddr)      \
+{                                                                      \
+       if (t2_is_mmio(xaddr))                                          \
+               t2_write##OS(b, xaddr - T2_DENSE_MEM);                  \
+       else                                                            \
+               t2_out##OS(b, (unsigned long)xaddr - T2_IO);            \
+}
+
+IOPORT(b, 8)
+IOPORT(w, 16)
+IOPORT(l, 32)
+
+#undef IOPORT
+
 #undef vip
 #undef vuip
 
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)               t2_inb((unsigned long)(p))
-#define __inw(p)               t2_inw((unsigned long)(p))
-#define __inl(p)               t2_inl((unsigned long)(p))
-#define __outb(x,p)            t2_outb((x),(unsigned long)(p))
-#define __outw(x,p)            t2_outw((x),(unsigned long)(p))
-#define __outl(x,p)            t2_outl((x),(unsigned long)(p))
-#define __readb(a)             t2_readb((unsigned long)(a))
-#define __readw(a)             t2_readw((unsigned long)(a))
-#define __readl(a)             t2_readl((unsigned long)(a))
-#define __readq(a)             t2_readq((unsigned long)(a))
-#define __writeb(x,a)          t2_writeb((x),(unsigned long)(a))
-#define __writew(x,a)          t2_writew((x),(unsigned long)(a))
-#define __writel(x,a)          t2_writel((x),(unsigned long)(a))
-#define __writeq(x,a)          t2_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)         t2_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)           t2_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)         t2_is_ioaddr((unsigned long)(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX            t2
+#define t2_trivial_rw_bw       0
+#define t2_trivial_rw_lq       0
+#define t2_trivial_io_bw       0
+#define t2_trivial_io_lq       0
+#define t2_trivial_iounmap     1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
index 39959ed..a64ccbf 100644 (file)
@@ -377,149 +377,33 @@ struct el_PRIVATEER_envdata_mcheck {
  * can only use linear accesses to get at PCI/AGP memory and I/O spaces.
  */
 
-#define vucp   volatile unsigned char *
-#define vusp   volatile unsigned short *
-#define vuip   volatile unsigned int *
-#define vulp   volatile unsigned long *
-
-__EXTERN_INLINE u8 titan_inb(unsigned long addr)
-{
-       /* ??? I wish I could get rid of this.  But there's no ioremap
-          equivalent for I/O space.  PCI I/O can be forced into the
-          correct hose's I/O region, but that doesn't take care of
-          legacy ISA crap.  */
-
-       addr += TITAN_IO_BIAS;
-       return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void titan_outb(u8 b, unsigned long addr)
-{
-       addr += TITAN_IO_BIAS;
-       __kernel_stb(b, *(vucp)addr);
-       mb();
-}
-
-__EXTERN_INLINE u16 titan_inw(unsigned long addr)
-{
-       addr += TITAN_IO_BIAS;
-       return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void titan_outw(u16 b, unsigned long addr)
-{
-       addr += TITAN_IO_BIAS;
-       __kernel_stw(b, *(vusp)addr);
-       mb();
-}
-
-__EXTERN_INLINE u32 titan_inl(unsigned long addr)
-{
-       addr += TITAN_IO_BIAS;
-       return *(vuip)addr;
-}
-
-__EXTERN_INLINE void titan_outl(u32 b, unsigned long addr)
-{
-       addr += TITAN_IO_BIAS;
-       *(vuip)addr = b;
-       mb();
-}
-
 /*
  * Memory functions.  all accesses are done through linear space.
  */
 
-extern unsigned long titan_ioremap(unsigned long addr, unsigned long size);
-extern void titan_iounmap(unsigned long addr);
-
-__EXTERN_INLINE int titan_is_ioaddr(unsigned long addr)
-{
-       return addr >= TITAN_BASE;
-}
-
-__EXTERN_INLINE u8 titan_readb(unsigned long addr)
-{
-       return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE u16 titan_readw(unsigned long addr)
-{
-       return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE u32 titan_readl(unsigned long addr)
-{
-       return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 titan_readq(unsigned long addr)
+__EXTERN_INLINE void __iomem *titan_ioportmap(unsigned long addr)
 {
-       return *(vulp)addr;
+       return (void __iomem *)(addr + TITAN_IO_BIAS);
 }
 
-__EXTERN_INLINE void titan_writeb(u8 b, unsigned long addr)
-{
-       __kernel_stb(b, *(vucp)addr);
-}
+extern void __iomem *titan_ioremap(unsigned long addr, unsigned long size);
+extern void titan_iounmap(volatile void __iomem *addr);
 
-__EXTERN_INLINE void titan_writew(u16 b, unsigned long addr)
-{
-       __kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void titan_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE int titan_is_ioaddr(unsigned long addr)
 {
-       *(vuip)addr = b;
+       return addr >= TITAN_BASE;
 }
 
-__EXTERN_INLINE void titan_writeq(u64 b, unsigned long addr)
-{
-       *(vulp)addr = b;
-}
+extern int titan_is_mmio(const volatile void __iomem *addr);
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)               titan_inb((unsigned long)(p))
-#define __inw(p)               titan_inw((unsigned long)(p))
-#define __inl(p)               titan_inl((unsigned long)(p))
-#define __outb(x,p)            titan_outb((x),(unsigned long)(p))
-#define __outw(x,p)            titan_outw((x),(unsigned long)(p))
-#define __outl(x,p)            titan_outl((x),(unsigned long)(p))
-#define __readb(a)             titan_readb((unsigned long)(a))
-#define __readw(a)             titan_readw((unsigned long)(a))
-#define __readl(a)             titan_readl((unsigned long)(a))
-#define __readq(a)             titan_readq((unsigned long)(a))
-#define __writeb(x,a)          titan_writeb((x),(unsigned long)(a))
-#define __writew(x,a)          titan_writew((x),(unsigned long)(a))
-#define __writel(x,a)          titan_writel((x),(unsigned long)(a))
-#define __writeq(x,a)          titan_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)         titan_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)           titan_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)         titan_is_ioaddr((unsigned long)(a))
-
-#define inb(port)              __inb((port))
-#define inw(port)              __inw((port))
-#define inl(port)              __inl((port))
-#define outb(v, port)          __outb((v),(port))
-#define outw(v, port)          __outw((v),(port))
-#define outl(v, port)          __outl((v),(port))
-
-#define __raw_readb(a)         __readb((unsigned long)(a))
-#define __raw_readw(a)         __readw((unsigned long)(a))
-#define __raw_readl(a)         __readl((unsigned long)(a))
-#define __raw_readq(a)         __readq((unsigned long)(a))
-#define __raw_writeb(v,a)      __writeb((v),(unsigned long)(a))
-#define __raw_writew(v,a)      __writew((v),(unsigned long)(a))
-#define __raw_writel(v,a)      __writel((v),(unsigned long)(a))
-#define __raw_writeq(v,a)      __writeq((v),(unsigned long)(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX            titan
+#define titan_trivial_rw_bw    1
+#define titan_trivial_rw_lq    1
+#define titan_trivial_io_bw    1
+#define titan_trivial_io_lq    1
+#define titan_trivial_iounmap  0
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
index 7c815eb..44e635d 100644 (file)
@@ -299,69 +299,19 @@ struct el_TSUNAMI_sysdata_mcheck {
  * can only use linear accesses to get at PCI memory and I/O spaces.
  */
 
-#define vucp   volatile unsigned char *
-#define vusp   volatile unsigned short *
-#define vuip   volatile unsigned int *
-#define vulp   volatile unsigned long *
-
-__EXTERN_INLINE u8 tsunami_inb(unsigned long addr)
-{
-       /* ??? I wish I could get rid of this.  But there's no ioremap
-          equivalent for I/O space.  PCI I/O can be forced into the
-          correct hose's I/O region, but that doesn't take care of
-          legacy ISA crap.  */
-
-       addr += TSUNAMI_IO_BIAS;
-       return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void tsunami_outb(u8 b, unsigned long addr)
-{
-       addr += TSUNAMI_IO_BIAS;
-       __kernel_stb(b, *(vucp)addr);
-       mb();
-}
-
-__EXTERN_INLINE u16 tsunami_inw(unsigned long addr)
-{
-       addr += TSUNAMI_IO_BIAS;
-       return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void tsunami_outw(u16 b, unsigned long addr)
-{
-       addr += TSUNAMI_IO_BIAS;
-       __kernel_stw(b, *(vusp)addr);
-       mb();
-}
-
-__EXTERN_INLINE u32 tsunami_inl(unsigned long addr)
-{
-       addr += TSUNAMI_IO_BIAS;
-       return *(vuip)addr;
-}
-
-__EXTERN_INLINE void tsunami_outl(u32 b, unsigned long addr)
-{
-       addr += TSUNAMI_IO_BIAS;
-       *(vuip)addr = b;
-       mb();
-}
-
 /*
  * Memory functions.  all accesses are done through linear space.
  */
 
-__EXTERN_INLINE unsigned long tsunami_ioremap(unsigned long addr, 
-                                             unsigned long size
-                                             __attribute__((unused)))
+__EXTERN_INLINE void __iomem *tsunami_ioportmap(unsigned long addr)
 {
-       return addr + TSUNAMI_MEM_BIAS;
+       return (void __iomem *)(addr + TSUNAMI_IO_BIAS);
 }
 
-__EXTERN_INLINE void tsunami_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *tsunami_ioremap(unsigned long addr, 
+                                             unsigned long size)
 {
-       return;
+       return (void __iomem *)(addr + TSUNAMI_MEM_BIAS);
 }
 
 __EXTERN_INLINE int tsunami_is_ioaddr(unsigned long addr)
@@ -369,87 +319,20 @@ __EXTERN_INLINE int tsunami_is_ioaddr(unsigned long addr)
        return addr >= TSUNAMI_BASE;
 }
 
-__EXTERN_INLINE u8 tsunami_readb(unsigned long addr)
-{
-       return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE u16 tsunami_readw(unsigned long addr)
-{
-       return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE u32 tsunami_readl(unsigned long addr)
-{
-       return *(vuip)addr;
-}
-
-__EXTERN_INLINE u64 tsunami_readq(unsigned long addr)
-{
-       return *(vulp)addr;
-}
-
-__EXTERN_INLINE void tsunami_writeb(u8 b, unsigned long addr)
-{
-       __kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void tsunami_writew(u16 b, unsigned long addr)
-{
-       __kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void tsunami_writel(u32 b, unsigned long addr)
-{
-       *(vuip)addr = b;
-}
-
-__EXTERN_INLINE void tsunami_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE int tsunami_is_mmio(const volatile void __iomem *xaddr)
 {
-       *(vulp)addr = b;
+       unsigned long addr = (unsigned long) xaddr;
+       return (addr & 0x100000000UL) == 0;
 }
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)               tsunami_inb((unsigned long)(p))
-#define __inw(p)               tsunami_inw((unsigned long)(p))
-#define __inl(p)               tsunami_inl((unsigned long)(p))
-#define __outb(x,p)            tsunami_outb((x),(unsigned long)(p))
-#define __outw(x,p)            tsunami_outw((x),(unsigned long)(p))
-#define __outl(x,p)            tsunami_outl((x),(unsigned long)(p))
-#define __readb(a)             tsunami_readb((unsigned long)(a))
-#define __readw(a)             tsunami_readw((unsigned long)(a))
-#define __readl(a)             tsunami_readl((unsigned long)(a))
-#define __readq(a)             tsunami_readq((unsigned long)(a))
-#define __writeb(x,a)          tsunami_writeb((x),(unsigned long)(a))
-#define __writew(x,a)          tsunami_writew((x),(unsigned long)(a))
-#define __writel(x,a)          tsunami_writel((x),(unsigned long)(a))
-#define __writeq(x,a)          tsunami_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)         tsunami_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)           tsunami_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)         tsunami_is_ioaddr((unsigned long)(a))
-
-#define inb(p)                 __inb(p)
-#define inw(p)                 __inw(p)
-#define inl(p)                 __inl(p)
-#define outb(x,p)              __outb((x),(p))
-#define outw(x,p)              __outw((x),(p))
-#define outl(x,p)              __outl((x),(p))
-#define __raw_readb(a)         __readb(a)
-#define __raw_readw(a)         __readw(a)
-#define __raw_readl(a)         __readl(a)
-#define __raw_readq(a)         __readq(a)
-#define __raw_writeb(v,a)      __writeb((v),(a))
-#define __raw_writew(v,a)      __writew((v),(a))
-#define __raw_writel(v,a)      __writel((v),(a))
-#define __raw_writeq(v,a)      __writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX            tsunami
+#define tsunami_trivial_rw_bw  1
+#define tsunami_trivial_rw_lq  1
+#define tsunami_trivial_io_bw  1
+#define tsunami_trivial_io_lq  1
+#define tsunami_trivial_iounmap        1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
index 7b8bbd1..12af803 100644 (file)
@@ -273,69 +273,19 @@ typedef struct {
 #define __IO_EXTERN_INLINE
 #endif
 
-#define vucp   volatile unsigned char *
-#define vusp   volatile unsigned short *
-#define vuip   volatile unsigned int *
-#define vulp   volatile unsigned long *
-
-__EXTERN_INLINE u8 wildfire_inb(unsigned long addr)
-{
-       /* ??? I wish I could get rid of this.  But there's no ioremap
-          equivalent for I/O space.  PCI I/O can be forced into the
-          correct hose's I/O region, but that doesn't take care of
-          legacy ISA crap.  */
-
-       addr += WILDFIRE_IO_BIAS;
-       return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void wildfire_outb(u8 b, unsigned long addr)
-{
-       addr += WILDFIRE_IO_BIAS;
-       __kernel_stb(b, *(vucp)addr);
-       mb();
-}
-
-__EXTERN_INLINE u16 wildfire_inw(unsigned long addr)
-{
-       addr += WILDFIRE_IO_BIAS;
-       return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void wildfire_outw(u16 b, unsigned long addr)
-{
-       addr += WILDFIRE_IO_BIAS;
-       __kernel_stw(b, *(vusp)addr);
-       mb();
-}
-
-__EXTERN_INLINE u32 wildfire_inl(unsigned long addr)
-{
-       addr += WILDFIRE_IO_BIAS;
-       return *(vuip)addr;
-}
-
-__EXTERN_INLINE void wildfire_outl(u32 b, unsigned long addr)
-{
-       addr += WILDFIRE_IO_BIAS;
-       *(vuip)addr = b;
-       mb();
-}
-
 /*
  * Memory functions.  all accesses are done through linear space.
  */
 
-__EXTERN_INLINE unsigned long wildfire_ioremap(unsigned long addr, 
-                                              unsigned long size
-                                              __attribute__((unused)))
+__EXTERN_INLINE void __iomem *wildfire_ioportmap(unsigned long addr)
 {
-       return addr + WILDFIRE_MEM_BIAS;
+       return (void __iomem *)(addr + WILDFIRE_IO_BIAS);
 }
 
-__EXTERN_INLINE void wildfire_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *wildfire_ioremap(unsigned long addr, 
+                                              unsigned long size)
 {
-       return;
+       return (void __iomem *)(addr + WILDFIRE_MEM_BIAS);
 }
 
 __EXTERN_INLINE int wildfire_is_ioaddr(unsigned long addr)
@@ -343,87 +293,20 @@ __EXTERN_INLINE int wildfire_is_ioaddr(unsigned long addr)
        return addr >= WILDFIRE_BASE;
 }
 
-__EXTERN_INLINE u8 wildfire_readb(unsigned long addr)
-{
-       return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE u16 wildfire_readw(unsigned long addr)
-{
-       return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE u32 wildfire_readl(unsigned long addr)
-{
-       return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 wildfire_readq(unsigned long addr)
-{
-       return *(vulp)addr;
-}
-
-__EXTERN_INLINE void wildfire_writeb(u8 b, unsigned long addr)
-{
-       __kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void wildfire_writew(u16 b, unsigned long addr)
-{
-       __kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void wildfire_writel(u32 b, unsigned long addr)
-{
-       *(vuip)addr = b;
-}
-
-__EXTERN_INLINE void wildfire_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE int wildfire_is_mmio(const volatile void __iomem *xaddr)
 {
-       *(vulp)addr = b;
+       unsigned long addr = (unsigned long)addr;
+       return (addr & 0x100000000UL) == 0;
 }
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)               wildfire_inb((unsigned long)(p))
-#define __inw(p)               wildfire_inw((unsigned long)(p))
-#define __inl(p)               wildfire_inl((unsigned long)(p))
-#define __outb(x,p)            wildfire_outb((x),(unsigned long)(p))
-#define __outw(x,p)            wildfire_outw((x),(unsigned long)(p))
-#define __outl(x,p)            wildfire_outl((x),(unsigned long)(p))
-#define __readb(a)             wildfire_readb((unsigned long)(a))
-#define __readw(a)             wildfire_readw((unsigned long)(a))
-#define __readl(a)             wildfire_readl((unsigned long)(a))
-#define __readq(a)             wildfire_readq((unsigned long)(a))
-#define __writeb(x,a)          wildfire_writeb((x),(unsigned long)(a))
-#define __writew(x,a)          wildfire_writew((x),(unsigned long)(a))
-#define __writel(x,a)          wildfire_writel((x),(unsigned long)(a))
-#define __writeq(x,a)          wildfire_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)         wildfire_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)           wildfire_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)         wildfire_is_ioaddr((unsigned long)(a))
-
-#define inb(p)                 __inb(p)
-#define inw(p)                 __inw(p)
-#define inl(p)                 __inl(p)
-#define outb(x,p)              __outb((x),(p))
-#define outw(x,p)              __outw((x),(p))
-#define outl(x,p)              __outl((x),(p))
-#define __raw_readb(a)         __readb(a)
-#define __raw_readw(a)         __readw(a)
-#define __raw_readl(a)         __readl(a)
-#define __raw_readq(a)         __readq(a)
-#define __raw_writeb(v,a)      __writeb((v),(a))
-#define __raw_writew(v,a)      __writew((v),(a))
-#define __raw_writel(v,a)      __writel((v),(a))
-#define __raw_writeq(v,a)      __writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX                    wildfire
+#define wildfire_trivial_rw_bw         1
+#define wildfire_trivial_rw_lq         1
+#define wildfire_trivial_io_bw         1
+#define wildfire_trivial_io_lq         1
+#define wildfire_trivial_iounmap       1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
index e7e1690..0faad45 100644 (file)
@@ -1 +1,63 @@
-#include <asm-generic/dma-mapping.h>
+#ifndef _ALPHA_DMA_MAPPING_H
+#define _ALPHA_DMA_MAPPING_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_PCI
+
+#include <linux/pci.h>
+
+#define dma_map_single(dev, va, size, dir)             \
+               pci_map_single(alpha_gendev_to_pci(dev), va, size, dir)
+#define dma_unmap_single(dev, addr, size, dir)         \
+               pci_unmap_single(alpha_gendev_to_pci(dev), addr, size, dir)
+#define dma_alloc_coherent(dev, size, addr, gfp)       \
+               pci_alloc_consistent(alpha_gendev_to_pci(dev), size, addr)
+#define dma_free_coherent(dev, size, va, addr)         \
+               pci_free_consistent(alpha_gendev_to_pci(dev), size, va, addr)
+#define dma_map_page(dev, page, off, size, dir)                \
+               pci_map_single(alpha_gendev_to_pci(dev), page, off, size, dir)
+#define dma_unmap_page(dev, addr, size, dir)           \
+               pci_unmap_page(alpha_gendev_to_pci(dev), addr, size, dir)
+#define dma_map_sg(dev, sg, nents, dir)                        \
+               pci_map_sg(alpha_gendev_to_pci(dev), sg, nents, dir)
+#define dma_unmap_sg(dev, sg, nents, dir)              \
+               pci_unmap_sg(alpha_gendev_to_pci(dev), sg, nents, dir)
+#define dma_supported(dev, mask)                       \
+               pci_dma_supported(alpha_gendev_to_pci(dev), mask)
+
+#else  /* no PCI - no IOMMU. */
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+                        dma_addr_t *dma_handle, int gfp);
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+              enum dma_data_direction direction);
+
+#define dma_free_coherent(dev, size, va, addr)         \
+               free_pages((unsigned long)va, get_order(size))
+#define dma_supported(dev, mask)               (mask < 0x00ffffffUL ? 0 : 1)
+#define dma_map_single(dev, va, size, dir)     virt_to_phys(va)
+#define dma_map_page(dev, page, off, size, dir)        (page_to_pa(page) + off)
+
+#define dma_unmap_single(dev, addr, size, dir) do { } while (0)
+#define dma_unmap_page(dev, addr, size, dir)   do { } while (0)
+#define dma_unmap_sg(dev, sg, nents, dir)      do { } while (0)
+
+#endif /* !CONFIG_PCI */
+
+#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)
+#define dma_is_consistent(dev)                 (1)
+
+int dma_set_mask(struct device *dev, u64 mask);
+
+#define dma_sync_single_for_cpu(dev, addr, size, dir)    do { } while (0)
+#define dma_sync_single_for_device(dev, addr, size, dir)  do { } while (0)
+#define dma_sync_single_range(dev, addr, off, size, dir)  do { } while (0)
+#define dma_sync_sg_for_cpu(dev, sg, nents, dir)         do { } while (0)
+#define dma_sync_sg_for_device(dev, sg, nents, dir)      do { } while (0)
+#define dma_cache_sync(va, size, dir)                    do { } while (0)
+
+#define dma_get_cache_alignment()                        L1_CACHE_BYTES
+
+#endif /* _ALPHA_DMA_MAPPING_H */
index e188ed9..10be402 100644 (file)
@@ -39,20 +39,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially nestable IRQ sources in the system
@@ -64,28 +50,7 @@ typedef struct {
 #error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
 #define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
-
-
-#ifdef CONFIG_PREEMPT
-#define in_atomic()    (preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-#define in_atomic()    (preempt_count() != 0)
-#define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-# endif
 #define irq_exit()                                             \
 do {                                                           \
                preempt_count() -= IRQ_EXIT_OFFSET;             \
@@ -95,10 +60,4 @@ do {                                                         \
                preempt_enable_no_resched();                    \
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)  barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* _ALPHA_HARDIRQ_H */
diff --git a/include/asm-alpha/io_trivial.h b/include/asm-alpha/io_trivial.h
new file mode 100644 (file)
index 0000000..cfe1f86
--- /dev/null
@@ -0,0 +1,127 @@
+/* Trivial implementations of basic i/o routines.  Assumes that all
+   of the hard work has been done by ioremap and ioportmap, and that
+   access to i/o space is linear.  */
+
+/* This file may be included multiple times.  */
+
+#if IO_CONCAT(__IO_PREFIX,trivial_io_bw)
+__EXTERN_INLINE unsigned int
+IO_CONCAT(__IO_PREFIX,ioread8)(void __iomem *a)
+{
+       return __kernel_ldbu(*(volatile u8 __force *)a);
+}
+
+__EXTERN_INLINE unsigned int
+IO_CONCAT(__IO_PREFIX,ioread16)(void __iomem *a)
+{
+       return __kernel_ldwu(*(volatile u16 __force *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,iowrite8)(u8 b, void __iomem *a)
+{
+       __kernel_stb(b, *(volatile u8 __force *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,iowrite16)(u16 b, void __iomem *a)
+{
+       __kernel_stb(b, *(volatile u16 __force *)a);
+}
+#endif
+
+#if IO_CONCAT(__IO_PREFIX,trivial_io_lq)
+__EXTERN_INLINE unsigned int
+IO_CONCAT(__IO_PREFIX,ioread32)(void __iomem *a)
+{
+       return *(volatile u32 __force *)a;
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,iowrite32)(u32 b, void __iomem *a)
+{
+       *(volatile u32 __force *)a = b;
+}
+#endif
+
+#if IO_CONCAT(__IO_PREFIX,trivial_rw_bw) == 1
+__EXTERN_INLINE u8
+IO_CONCAT(__IO_PREFIX,readb)(const volatile void __iomem *a)
+{
+       return __kernel_ldbu(*(const volatile u8 __force *)a);
+}
+
+__EXTERN_INLINE u16
+IO_CONCAT(__IO_PREFIX,readw)(const volatile void __iomem *a)
+{
+       return __kernel_ldwu(*(const volatile u16 __force *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writeb)(u8 b, volatile void __iomem *a)
+{
+       __kernel_stb(b, *(volatile u8 __force *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writew)(u16 b, volatile void __iomem *a)
+{
+       __kernel_stb(b, *(volatile u16 __force *)a);
+}
+#elif IO_CONCAT(__IO_PREFIX,trivial_rw_bw) == 2
+__EXTERN_INLINE u8
+IO_CONCAT(__IO_PREFIX,readb)(const volatile void __iomem *a)
+{
+       return IO_CONCAT(__IO_PREFIX,ioread8)((void __iomem *)a);
+}
+
+__EXTERN_INLINE u16
+IO_CONCAT(__IO_PREFIX,readw)(const volatile void __iomem *a)
+{
+       return IO_CONCAT(__IO_PREFIX,ioread16)((void __iomem *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writeb)(u8 b, volatile void __iomem *a)
+{
+       IO_CONCAT(__IO_PREFIX,iowrite8)(b, (void __iomem *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writew)(u16 b, volatile void __iomem *a)
+{
+       IO_CONCAT(__IO_PREFIX,iowrite16)(b, (void __iomem *)a);
+}
+#endif
+
+#if IO_CONCAT(__IO_PREFIX,trivial_rw_lq) == 1
+__EXTERN_INLINE u32
+IO_CONCAT(__IO_PREFIX,readl)(const volatile void __iomem *a)
+{
+       return *(const volatile u32 __force *)a;
+}
+
+__EXTERN_INLINE u64
+IO_CONCAT(__IO_PREFIX,readq)(const volatile void __iomem *a)
+{
+       return *(const volatile u64 __force *)a;
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writel)(u32 b, volatile void __iomem *a)
+{
+       *(volatile u32 __force *)a = b;
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writeq)(u64 b, volatile void __iomem *a)
+{
+       *(volatile u64 __force *)a = b;
+}
+#endif
+
+#if IO_CONCAT(__IO_PREFIX,trivial_iounmap)
+__EXTERN_INLINE void IO_CONCAT(__IO_PREFIX,iounmap)(volatile void __iomem *a)
+{
+}
+#endif
index 7e6c35b..964b06e 100644 (file)
@@ -200,8 +200,9 @@ __EXTERN_INLINE void jensen_outl(u32 b, unsigned long addr)
  * Memory functions.
  */
 
-__EXTERN_INLINE u8 jensen_readb(unsigned long addr)
+__EXTERN_INLINE u8 jensen_readb(const volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        long result;
 
        jensen_set_hae(addr);
@@ -211,8 +212,9 @@ __EXTERN_INLINE u8 jensen_readb(unsigned long addr)
        return 0xffUL & result;
 }
 
-__EXTERN_INLINE u16 jensen_readw(unsigned long addr)
+__EXTERN_INLINE u16 jensen_readw(const volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        long result;
 
        jensen_set_hae(addr);
@@ -222,15 +224,17 @@ __EXTERN_INLINE u16 jensen_readw(unsigned long addr)
        return 0xffffUL & result;
 }
 
-__EXTERN_INLINE u32 jensen_readl(unsigned long addr)
+__EXTERN_INLINE u32 jensen_readl(const volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        jensen_set_hae(addr);
        addr &= JENSEN_HAE_MASK;
        return *(vuip) ((addr << 7) + EISA_MEM + 0x60);
 }
 
-__EXTERN_INLINE u64 jensen_readq(unsigned long addr)
+__EXTERN_INLINE u64 jensen_readq(const volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        unsigned long r0, r1;
 
        jensen_set_hae(addr);
@@ -241,29 +245,33 @@ __EXTERN_INLINE u64 jensen_readq(unsigned long addr)
        return r1 << 32 | r0;
 }
 
-__EXTERN_INLINE void jensen_writeb(u8 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writeb(u8 b, volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        jensen_set_hae(addr);
        addr &= JENSEN_HAE_MASK;
        *(vuip) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101;
 }
 
-__EXTERN_INLINE void jensen_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writew(u16 b, volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        jensen_set_hae(addr);
        addr &= JENSEN_HAE_MASK;
        *(vuip) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001;
 }
 
-__EXTERN_INLINE void jensen_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writel(u32 b, volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        jensen_set_hae(addr);
        addr &= JENSEN_HAE_MASK;
        *(vuip) ((addr << 7) + EISA_MEM + 0x60) = b;
 }
 
-__EXTERN_INLINE void jensen_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writeq(u64 b, volatile void __iomem *xaddr)
 {
+       unsigned long addr = (unsigned long) xaddr;
        jensen_set_hae(addr);
        addr &= JENSEN_HAE_MASK;
        addr = (addr << 7) + EISA_MEM + 0x60;
@@ -271,15 +279,15 @@ __EXTERN_INLINE void jensen_writeq(u64 b, unsigned long addr)
        *(vuip) (addr + (4 << 7)) = b >> 32;
 }
 
-__EXTERN_INLINE unsigned long jensen_ioremap(unsigned long addr, 
-                                            unsigned long size)
+__EXTERN_INLINE void __iomem *jensen_ioportmap(unsigned long addr)
 {
-       return addr;
+       return (void __iomem *)addr;
 }
 
-__EXTERN_INLINE void jensen_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *jensen_ioremap(unsigned long addr,
+                                            unsigned long size)
 {
-       return;
+       return (void __iomem *)(addr + 0x100000000ul);
 }
 
 __EXTERN_INLINE int jensen_is_ioaddr(unsigned long addr)
@@ -287,39 +295,46 @@ __EXTERN_INLINE int jensen_is_ioaddr(unsigned long addr)
        return (long)addr >= 0;
 }
 
-#undef vuip
+__EXTERN_INLINE int jensen_is_mmio(const volatile void __iomem *addr)
+{
+       return (unsigned long)addr >= 0x100000000ul;
+}
 
-#ifdef __WANT_IO_DEF
-
-#define __inb          jensen_inb
-#define __inw          jensen_inw
-#define __inl          jensen_inl
-#define __outb         jensen_outb
-#define __outw         jensen_outw
-#define __outl         jensen_outl
-#define __readb                jensen_readb
-#define __readw                jensen_readw
-#define __writeb       jensen_writeb
-#define __writew       jensen_writew
-#define __readl                jensen_readl
-#define __readq                jensen_readq
-#define __writel       jensen_writel
-#define __writeq       jensen_writeq
-#define __ioremap      jensen_ioremap
-#define __iounmap(a)   jensen_iounmap((unsigned long)a)
-#define __is_ioaddr    jensen_is_ioaddr
+/* New-style ioread interface.  All the routines are so ugly for Jensen
+   that it doesn't make sense to merge them.  */
+
+#define IOPORT(OS, NS)                                                 \
+__EXTERN_INLINE unsigned int jensen_ioread##NS(void __iomem *xaddr)    \
+{                                                                      \
+       if (jensen_is_mmio(xaddr))                                      \
+               return jensen_read##OS(xaddr - 0x100000000ul);          \
+       else                                                            \
+               return jensen_in##OS((unsigned long)xaddr);             \
+}                                                                      \
+__EXTERN_INLINE void jensen_iowrite##NS(u##NS b, void __iomem *xaddr)  \
+{                                                                      \
+       if (jensen_is_mmio(xaddr))                                      \
+               jensen_write##OS(b, xaddr - 0x100000000ul);             \
+       else                                                            \
+               jensen_out##OS(b, (unsigned long)xaddr);                \
+}
 
-/*
- * The above have so much overhead that it probably doesn't make
- * sense to have them inlined (better icache behaviour).
- */
-#define inb(port) \
-(__builtin_constant_p((port))?__inb(port):_inb(port))
+IOPORT(b, 8)
+IOPORT(w, 16)
+IOPORT(l, 32)
 
-#define outb(x, port) \
-(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
+#undef IOPORT
+
+#undef vuip
 
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX            jensen
+#define jensen_trivial_rw_bw   0
+#define jensen_trivial_rw_lq   0
+#define jensen_trivial_io_bw   0
+#define jensen_trivial_io_lq   0
+#define jensen_trivial_iounmap 1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
index f09f719..ece166a 100644 (file)
@@ -45,27 +45,29 @@ struct alpha_machine_vector
        void (*mv_pci_tbi)(struct pci_controller *hose,
                           dma_addr_t start, dma_addr_t end);
 
-       u8 (*mv_inb)(unsigned long);
-       u16 (*mv_inw)(unsigned long);
-       u32 (*mv_inl)(unsigned long);
-
-       void (*mv_outb)(u8, unsigned long);
-       void (*mv_outw)(u16, unsigned long);
-       void (*mv_outl)(u32, unsigned long);
-       
-       u8 (*mv_readb)(unsigned long);
-       u16 (*mv_readw)(unsigned long);
-       u32 (*mv_readl)(unsigned long);
-       u64 (*mv_readq)(unsigned long);
-
-       void (*mv_writeb)(u8, unsigned long);
-       void (*mv_writew)(u16, unsigned long);
-       void (*mv_writel)(u32, unsigned long);
-       void (*mv_writeq)(u64, unsigned long);
-
-       unsigned long (*mv_ioremap)(unsigned long, unsigned long);
-       void (*mv_iounmap)(unsigned long);
+       unsigned int (*mv_ioread8)(void __iomem *);
+       unsigned int (*mv_ioread16)(void __iomem *);
+       unsigned int (*mv_ioread32)(void __iomem *);
+
+       void (*mv_iowrite8)(u8, void __iomem *);
+       void (*mv_iowrite16)(u16, void __iomem *);
+       void (*mv_iowrite32)(u32, void __iomem *);
+
+       u8 (*mv_readb)(const volatile void __iomem *);
+       u16 (*mv_readw)(const volatile void __iomem *);
+       u32 (*mv_readl)(const volatile void __iomem *);
+       u64 (*mv_readq)(const volatile void __iomem *);
+
+       void (*mv_writeb)(u8, volatile void __iomem *);
+       void (*mv_writew)(u16, volatile void __iomem *);
+       void (*mv_writel)(u32, volatile void __iomem *);
+       void (*mv_writeq)(u64, volatile void __iomem *);
+
+       void __iomem *(*mv_ioportmap)(unsigned long);
+       void __iomem *(*mv_ioremap)(unsigned long, unsigned long);
+       void (*mv_iounmap)(volatile void __iomem *);
        int (*mv_is_ioaddr)(unsigned long);
+       int (*mv_is_mmio)(const volatile void __iomem *);
 
        void (*mv_switch_mm)(struct mm_struct *, struct mm_struct *,
                             struct task_struct *);
index 3ae6408..a714d0c 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/config.h>
 #include <asm/system.h>
 #include <asm/machvec.h>
+#include <asm/compiler.h>
 
 /*
  * Force a context reload. This is needed when we change the page
index 5cd3779..bbefe12 100644 (file)
@@ -169,7 +169,7 @@ pci_dma_sync_single_for_cpu(struct pci_dev *dev, dma_addr_t dma_addr,
 
 static inline void
 pci_dma_sync_single_for_device(struct pci_dev *dev, dma_addr_t dma_addr,
-                              long size, int direction)
+                              size_t size, int direction)
 {
        /* Nothing to do.  */
 }
@@ -246,6 +246,8 @@ pcibios_add_platform_entries(struct pci_dev *dev)
 {
 }
 
+struct pci_dev *alpha_gendev_to_pci(struct device *dev);
+
 #endif /* __KERNEL__ */
 
 /* Values for the `which' argument to sys_pciconfig_iobase.  */
index e77230f..d462c5e 100644 (file)
@@ -69,6 +69,7 @@ struct switch_stack {
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->ps & 8) != 0)
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 
 #define alpha_task_regs(task) \
index 88912c4..d00259d 100644 (file)
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       20
 #define SO_SECURITY_ENCRYPTION_NETWORK         21
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
index 1c65a02..086aba2 100644 (file)
@@ -18,6 +18,7 @@
 #define SSI_IEEE_FP_CONTROL            14
 #define SSI_IEEE_STATE_AT_SIGNAL       15
 #define SSI_IEEE_IGNORE_STATE_AT_SIGNAL        16
+#define SSI_IEEE_RAISE_EXCEPTION       1001    /* linux specific */
 
 #define SSIN_UACPROC                   6
 
index 1f19c2a..c433512 100644 (file)
@@ -19,7 +19,7 @@ struct thread_info {
 
        struct exec_domain      *exec_domain;   /* execution domain */
        mm_segment_t            addr_limit;     /* thread address space */
-       long                    cpu;            /* current CPU */
+       unsigned                cpu;            /* current CPU */
        int                     preempt_count; /* 0 => preemptable, <0 => BUG */
 
        int bpt_nsaved;
index 736a4f6..9d484c1 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
+#include <asm/compiler.h>
 
 #ifndef __EXTERN_INLINE
 #define __EXTERN_INLINE extern inline
@@ -86,7 +87,7 @@ flush_tlb(void)
 static inline void
 flush_tlb_other(struct mm_struct *mm)
 {
-       long *mmc = &mm->context[smp_processor_id()];
+       unsigned long *mmc = &mm->context[smp_processor_id()];
        /* Check it's not zero first to avoid cacheline ping pong
           when possible.  */
        if (*mmc) *mmc = 0;
index 0f3d10e..8ca4f6b 100644 (file)
 
 extern inline void scr_writew(u16 val, volatile u16 *addr)
 {
-       if (__is_ioaddr((unsigned long) addr))
-               __raw_writew(val, (unsigned long) addr);
+       if (__is_ioaddr(addr))
+               __raw_writew(val, (volatile u16 __iomem *) addr);
        else
                *addr = val;
 }
 
 extern inline u16 scr_readw(volatile const u16 *addr)
 {
-       if (__is_ioaddr((unsigned long) addr))
-               return __raw_readw((unsigned long) addr);
+       if (__is_ioaddr(addr))
+               return __raw_readw((volatile const u16 __iomem *) addr);
        else
                return *addr;
 }
 
 extern inline void scr_memsetw(u16 *s, u16 c, unsigned int count)
 {
-       if (__is_ioaddr((unsigned long) s))
-               memsetw_io(s, c, count);
+       if (__is_ioaddr(s))
+               memsetw_io((u16 __iomem *) s, c, count);
        else
                memsetw(s, c, count);
 }
@@ -43,9 +43,9 @@ extern void scr_memcpyw(u16 *d, const u16 *s, unsigned int count);
 /* ??? These are currently only used for downloading character sets.  As
    such, they don't need memory barriers.  Is this all they are intended
    to be used for?  */
-#define vga_readb      readb
-#define vga_writeb     writeb
+#define vga_readb(a)   readb((u8 __iomem *)(a))
+#define vga_writeb(v,a)        writeb(v, (u8 __iomem *)(a))
 
-#define VGA_MAP_MEM(x) ((unsigned long) ioremap((x), 0))
+#define VGA_MAP_MEM(x) ((unsigned long) ioremap(x, 0))
 
 #endif
index 4d9f874..3a50eb7 100644 (file)
 #define ARM_ASM_SA1100_APM_H
 
 #include <linux/config.h>
-
-#ifdef CONFIG_APM
-
-
-#define APM_AC_OFFLINE 0
-#define APM_AC_ONLINE 1
-#define APM_AC_BACKUP 2
-#define APM_AC_UNKNOWN 0xFF
-
-#define APM_BATTERY_STATUS_HIGH 0
-#define APM_BATTERY_STATUS_LOW  1
-#define APM_BATTERY_STATUS_CRITICAL 2
-#define APM_BATTERY_STATUS_CHARGING 3
-#define APM_BATTERY_STATUS_UNKNOWN 0xFF
-
-#define APM_BATTERY_LIFE_UNKNOWN 0xFFFF
-#define APM_BATTERY_LIFE_MINUTES 0x8000
-#define APM_BATTERY_LIFE_VALUE_MASK 0x7FFF
+#include <linux/apm_bios.h>
 
 /*
  * This structure gets filled in by the machine specific 'get_power_status'
  */
 struct apm_power_info {
        unsigned char   ac_line_status;
+#define APM_AC_OFFLINE                 0
+#define APM_AC_ONLINE                  1
+#define APM_AC_BACKUP                  2
+#define APM_AC_UNKNOWN                 0xff
+
        unsigned char   battery_status;
+#define APM_BATTERY_STATUS_HIGH                0
+#define APM_BATTERY_STATUS_LOW         1
+#define APM_BATTERY_STATUS_CRITICAL    2
+#define APM_BATTERY_STATUS_CHARGING    3
+#define APM_BATTERY_STATUS_NOT_PRESENT 4
+#define APM_BATTERY_STATUS_UNKNOWN     0xff
+
        unsigned char   battery_flag;
-       unsigned char   battery_life;
+#define APM_BATTERY_FLAG_HIGH          (1 << 0)
+#define APM_BATTERY_FLAG_LOW           (1 << 1)
+#define APM_BATTERY_FLAG_CRITICAL      (1 << 2)
+#define APM_BATTERY_FLAG_CHARGING      (1 << 3)
+#define APM_BATTERY_FLAG_NOT_PRESENT   (1 << 7)
+#define APM_BATTERY_FLAG_UNKNOWN       0xff
+
+       int             battery_life;
        int             time;
        int             units;
+#define APM_UNITS_MINS                 0
+#define APM_UNITS_SECS                 1
+#define APM_UNITS_UNKNOWN              -1
+
 };
 
 /*
  * This allows machines to provide their own "apm get power status" function.
  */
 extern void (*apm_get_power_status)(struct apm_power_info *);
-#endif
 
+/*
+ * Queue an event (APM_SYS_SUSPEND or APM_CRITICAL_SUSPEND)
+ */
+void apm_queue_event(apm_event_t event);
 
 #endif
index fffaabd..68601b3 100644 (file)
@@ -16,7 +16,7 @@ static __inline__ void putc(char c)
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
        while (*s) {
                putc(*s);
index 152fef0..7d0ab79 100644 (file)
@@ -40,7 +40,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
        char c;
 
index 13a9fc1..be19b08 100644 (file)
@@ -1,4 +1,4 @@
 /*
  *  linux/include/asm-arm/arch-ebsa110/param.h
  */
-#define __KERNEL_HZ    200
+#define HZ     200
index 351cc7b..c2fd84e 100644 (file)
@@ -29,7 +29,7 @@ static __inline__ void putc(char c)
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
        while (*s) {
                putc(*s);
index f30a31f..d33ad6a 100644 (file)
@@ -26,7 +26,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
        while (*s) {
                while ((*UART_TSR(EXC_UART00_BASE) &
diff --git a/include/asm-arm/arch-h720x/boards.h b/include/asm-arm/arch-h720x/boards.h
new file mode 100644 (file)
index 0000000..8021f81
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * linux/include/asm-arm/arch-h720x/boards.h
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *
+ * This file contains the board specific defines for various devices
+ *
+ * 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_HARDWARE_INCMACH_H
+#error Do not include this file directly. Include asm/hardware.h instead !
+#endif
+
+/* Hynix H7202 developer board specific device defines */
+#ifdef CONFIG_ARCH_H7202
+
+/* FLASH */
+#define FLASH_VIRT             0xd0000000
+#define FLASH_PHYS             0x00000000
+#define FLASH_SIZE             0x02000000
+
+/* onboard LAN controller */
+# define ETH0_PHYS             0x08000000
+
+/* Touch screen defines */
+/* GPIO Port */
+#define PEN_GPIO               GPIO_B_VIRT
+/* Bitmask for pen down interrupt */
+#define PEN_INT_BIT            (1<<7)
+/* Bitmask for pen up interrupt */
+#define PEN_ENA_BIT            (1<<6)
+/* pen up interrupt */
+#define IRQ_PEN                        IRQ_MUX_GPIOB(7)
+
+#endif
+
+/* Hynix H7201 developer board specific device defines */
+#if defined (CONFIG_ARCH_H7201)
+/* ROM DISK SPACE */
+#define ROM_DISK_BASE           0xc1800000
+#define ROM_DISK_START          0x41800000
+#define ROM_DISK_SIZE           0x00700000
+
+/* SRAM DISK SPACE */
+#define SRAM_DISK_BASE          0xf1000000
+#define SRAM_DISK_START         0x04000000
+#define SRAM_DISK_SIZE          0x00400000
+#endif
+
diff --git a/include/asm-arm/arch-h720x/dma.h b/include/asm-arm/arch-h720x/dma.h
new file mode 100644 (file)
index 0000000..bfc6636
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * linux/include/asm-arm/arch-h720x/dma.h
+ *
+ * Architecture DMA routes
+ *
+ * Copyright (C) 1997.1998 Russell King
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+/*
+ * This is the maximum DMA address that can be DMAd to.
+ * There should not be more than (0xd0000000 - 0xc0000000)
+ * bytes of RAM.
+ */
+#define MAX_DMA_ADDRESS                0xd0000000
+
+#if defined (CONFIG_CPU_H7201)
+#define MAX_DMA_CHANNELS       3
+#elif defined (CONFIG_CPU_H7202)
+#define MAX_DMA_CHANNELS       4
+#else
+#error processor definition missmatch
+#endif
+
+#endif /* __ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-h720x/h7201-regs.h b/include/asm-arm/arch-h720x/h7201-regs.h
new file mode 100644 (file)
index 0000000..49d4f6b
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * linux/include/asm-arm/arch-h720x/h7201-regs.h
+ *
+ * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor Inc.
+ *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *           (C) 2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * This file contains the hardware definitions of the h720x processors
+ *
+ * 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.
+ *
+ * Do not add implementations specific defines here. This files contains
+ * only defines of the onchip peripherals. Add those defines to boards.h,
+ * which is included by this file.
+ */
+
+#define SERIAL2_VIRT           (IO_VIRT + 0x50100)
+#define SERIAL3_VIRT           (IO_VIRT + 0x50200)
+
+/*
+ * PCMCIA
+ */
+#define PCMCIA0_ATT_BASE        0xe5000000
+#define PCMCIA0_ATT_SIZE        0x00200000
+#define PCMCIA0_ATT_START       0x20000000
+#define PCMCIA0_MEM_BASE        0xe5200000
+#define PCMCIA0_MEM_SIZE        0x00200000
+#define PCMCIA0_MEM_START       0x24000000
+#define PCMCIA0_IO_BASE         0xe5400000
+#define PCMCIA0_IO_SIZE         0x00200000
+#define PCMCIA0_IO_START        0x28000000
+
+#define PCMCIA1_ATT_BASE        0xe5600000
+#define PCMCIA1_ATT_SIZE        0x00200000
+#define PCMCIA1_ATT_START       0x30000000
+#define PCMCIA1_MEM_BASE        0xe5800000
+#define PCMCIA1_MEM_SIZE        0x00200000
+#define PCMCIA1_MEM_START       0x34000000
+#define PCMCIA1_IO_BASE         0xe5a00000
+#define PCMCIA1_IO_SIZE         0x00200000
+#define PCMCIA1_IO_START        0x38000000
+
+#define PRIME3C_BASE            0xf0050000
+#define PRIME3C_SIZE            0x00001000
+#define PRIME3C_START           0x10000000
+
+/* VGA Controller */
+#define VGA_RAMBASE            0x50
+#define VGA_TIMING0            0x60
+#define VGA_TIMING1            0x64
+#define VGA_TIMING2            0x68
+#define VGA_TIMING3            0x6c
+
+#define LCD_CTRL_VGA_ENABLE    0x00000100
+#define LCD_CTRL_VGA_BPP_MASK  0x00000600
+#define LCD_CTRL_VGA_4BPP      0x00000000
+#define LCD_CTRL_VGA_8BPP      0x00000200
+#define LCD_CTRL_VGA_16BPP     0x00000300
+#define LCD_CTRL_SHARE_DMA     0x00000800
+#define LCD_CTRL_VDE           0x00100000
+#define LCD_CTRL_LPE           0x00400000      /* LCD Power enable */
+#define LCD_CTRL_BLE           0x00800000      /* LCD backlight enable */
+
+#define VGA_PALETTE_BASE       (IO_VIRT + 0x10800)
diff --git a/include/asm-arm/arch-h720x/h7202-regs.h b/include/asm-arm/arch-h720x/h7202-regs.h
new file mode 100644 (file)
index 0000000..d5c8671
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * linux/include/asm-arm/arch-h720x/h7202-regs.h
+ *
+ * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor Inc.
+ *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *           (C) 2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * This file contains the hardware definitions of the h720x processors
+ *
+ * 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.
+ *
+ * Do not add implementations specific defines here. This files contains
+ * only defines of the onchip peripherals. Add those defines to boards.h,
+ * which is included by this file.
+ */
+
+#define SERIAL2_VIRT           (IO_VIRT + 0x2d000)
+#define SERIAL3_VIRT           (IO_VIRT + 0x2e000)
+
+/* Matrix Keyboard Controller */
+#define KBD_VIRT               (IO_VIRT + 0x22000)
+#define KBD_KBCR               0x00
+#define KBD_KBSC               0x04
+#define KBD_KBTR               0x08
+#define KBD_KBVR0              0x0C
+#define KBD_KBVR1              0x10
+#define KBD_KBSR               0x18
+
+#define KBD_KBCR_SCANENABLE    (1 << 7)
+#define KBD_KBCR_NPOWERDOWN    (1 << 2)
+#define KBD_KBCR_CLKSEL_MASK   (3)
+#define KBD_KBCR_CLKSEL_PCLK2  0x0
+#define KBD_KBCR_CLKSEL_PCLK128        0x1
+#define KBD_KBCR_CLKSEL_PCLK256        0x2
+#define KBD_KBCR_CLKSEL_PCLK512        0x3
+
+#define KBD_KBSR_INTR          (1 << 0)
+#define KBD_KBSR_WAKEUP                (1 << 1)
+
+/* USB device controller */
+
+#define USBD_BASE              (IO_VIRT + 0x12000)
+#define USBD_LENGTH            0x3C
+
+#define USBD_GCTRL             0x00
+#define USBD_EPCTRL            0x04
+#define USBD_INTMASK           0x08
+#define USBD_INTSTAT           0x0C
+#define USBD_PWR               0x10
+#define USBD_DMARXTX           0x14
+#define USBD_DEVID             0x18
+#define USBD_DEVCLASS          0x1C
+#define USBD_INTCLASS          0x20
+#define USBD_SETUP0            0x24
+#define USBD_SETUP1            0x28
+#define USBD_ENDP0RD           0x2C
+#define USBD_ENDP0WT           0x30
+#define USBD_ENDP1RD           0x34
+#define USBD_ENDP2WT           0x38
+
+/* PS/2 port */
+#define PSDATA 0x00
+#define PSSTAT 0x04
+#define PSSTAT_TXEMPTY (1<<0)
+#define PSSTAT_TXBUSY (1<<1)
+#define PSSTAT_RXFULL (1<<2)
+#define PSSTAT_RXBUSY (1<<3)
+#define PSSTAT_CLKIN (1<<4)
+#define PSSTAT_DATAIN (1<<5)
+#define PSSTAT_PARITY (1<<6)
+
+#define PSCONF 0x08
+#define PSCONF_ENABLE (1<<0)
+#define PSCONF_TXINTEN (1<<2)
+#define PSCONF_RXINTEN (1<<3)
+#define PSCONF_FORCECLKLOW (1<<4)
+#define PSCONF_FORCEDATLOW (1<<5)
+#define PSCONF_LCE (1<<6)
+
+#define PSINTR 0x0C
+#define PSINTR_TXINT (1<<0)
+#define PSINTR_RXINT (1<<1)
+#define PSINTR_PAR (1<<2)
+#define PSINTR_RXTO (1<<3)
+#define PSINTR_TXTO (1<<4)
+
+#define PSTDLO 0x10 /* clk low before start transmission */
+#define PSTPRI 0x14 /* PRI clock */
+#define PSTXMT 0x18 /* maximum transmission time */
+#define PSTREC 0x20 /* maximum receive time */
+#define PSPWDN 0x3c
+
+/* ADC converter */
+#define ADC_BASE               (IO_VIRT + 0x29000)
+#define ADC_CR                         0x00
+#define ADC_TSCTRL             0x04
+#define ADC_BT_CTRL            0x08
+#define ADC_MC_CTRL            0x0C
+#define ADC_STATUS             0x10
+
+/* ADC control register bits */
+#define ADC_CR_PW_CTRL                 0x80
+#define ADC_CR_DIRECTC         0x04
+#define ADC_CR_CONTIME_NO      0x00
+#define ADC_CR_CONTIME_2       0x04
+#define ADC_CR_CONTIME_4       0x08
+#define ADC_CR_CONTIME_ADE     0x0c
+#define ADC_CR_LONGCALTIME     0x01
+
+/* ADC touch panel register bits */
+#define ADC_TSCTRL_ENABLE      0x80
+#define ADC_TSCTRL_INTR        0x40
+#define        ADC_TSCTRL_SWBYPSS      0x20
+#define ADC_TSCTRL_SWINVT      0x10
+#define ADC_TSCTRL_S400        0x03
+#define ADC_TSCTRL_S200        0x02
+#define ADC_TSCTRL_S100        0x01
+#define ADC_TSCTRL_S50         0x00
+
+/* ADC Interrupt Status Register bits */
+#define ADC_STATUS_TS_BIT      0x80
+#define ADC_STATUS_MBT_BIT     0x40
+#define ADC_STATUS_BBT_BIT     0x20
+#define ADC_STATUS_MIC_BIT     0x10
+
+/* Touch data registers */
+#define ADC_TS_X0X1            0x30
+#define ADC_TS_X2X3            0x34
+#define ADC_TS_Y0Y1            0x38
+#define ADC_TS_Y2Y3            0x3c
+#define ADC_TS_X4X5            0x40
+#define ADC_TS_X6X7            0x44
+#define ADC_TS_Y4Y5            0x48
+#define ADC_TS_Y6Y7            0x50
+
+/* battery data */
+#define ADC_MB_DATA            0x54
+#define ADC_BB_DATA            0x58
+
+/* Sound data register */
+#define ADC_SD_DAT0            0x60
+#define ADC_SD_DAT1            0x64
+#define ADC_SD_DAT2            0x68
+#define ADC_SD_DAT3            0x6c
+#define ADC_SD_DAT4            0x70
+#define ADC_SD_DAT5            0x74
+#define ADC_SD_DAT6            0x78
+#define ADC_SD_DAT7            0x7c
diff --git a/include/asm-arm/arch-h720x/hardware.h b/include/asm-arm/arch-h720x/hardware.h
new file mode 100644 (file)
index 0000000..864dc1f
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * linux/include/asm-arm/arch-h720x/hardware.h
+ *
+ * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor Inc.
+ *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *
+ * This file contains the hardware definitions of the h720x processors
+ *
+ * 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.
+ *
+ * Do not add implementations specific defines here. This files contains
+ * only defines of the onchip peripherals. Add those defines to boards.h,
+ * which is included by this file.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#define IOCLK (3686400L)
+
+/* Onchip peripherals */
+
+#define IO_VIRT                        0xf0000000      /* IO peripherals */
+#define IO_PHYS                        0x80000000
+#define IO_SIZE                        0x00050000
+
+#ifdef CONFIG_CPU_H7202
+#include "h7202-regs.h"
+#elif defined CONFIG_CPU_H7201
+#include "h7201-regs.h"
+#else
+#error machine definition mismatch
+#endif
+
+/* Macro to access the CPU IO */
+#define CPU_IO(x) (*(volatile u32*)(x))
+
+/* Macro to access general purpose regs (base, offset) */
+#define CPU_REG(x,y) CPU_IO(x+y)
+
+/* Macro to access irq related regs */
+#define IRQ_REG(x) CPU_REG(IRQC_VIRT,x)
+
+/* CPU registers */
+/* general purpose I/O */
+#define GPIO_VIRT(x)           (IO_VIRT + 0x23000 + ((x)<<5))
+#define GPIO_A_VIRT            (GPIO_VIRT(0))
+#define GPIO_B_VIRT            (GPIO_VIRT(1))
+#define GPIO_C_VIRT            (GPIO_VIRT(2))
+#define GPIO_D_VIRT            (GPIO_VIRT(3))
+#define GPIO_E_VIRT            (GPIO_VIRT(4))
+#define GPIO_AMULSEL           (GPIO_VIRT + 0xA4)
+/* Register offsets general purpose I/O */
+#define GPIO_DATA              0x00
+#define GPIO_DIR               0x04
+#define GPIO_MASK              0x08
+#define GPIO_STAT              0x0C
+#define GPIO_EDGE              0x10
+#define GPIO_CLR               0x14
+#define GPIO_POL               0x18
+#define GPIO_EN                        0x1C
+
+/*interrupt controller */
+#define IRQC_VIRT              (IO_VIRT + 0x24000)
+/* register offset interrupt controller */
+#define IRQC_IER               0x00
+#define IRQC_ISR               0x04
+
+/* timer unit */
+#define TIMER_VIRT             (IO_VIRT + 0x25000)
+/* Register offsets timer unit */
+#define TM0_PERIOD             0x00
+#define TM0_COUNT              0x08
+#define TM0_CTRL               0x10
+#define TM1_PERIOD             0x20
+#define TM1_COUNT              0x28
+#define TM1_CTRL               0x30
+#define TM2_PERIOD             0x40
+#define TM2_COUNT              0x48
+#define TM2_CTRL               0x50
+#define TIMER_TOPCTRL          0x60
+#define TIMER_TOPSTAT          0x64
+#define T64_COUNTL             0x80
+#define T64_COUNTH             0x84
+#define T64_CTRL               0x88
+#define T64_BASEL              0x94
+#define T64_BASEH              0x98
+/* Bitmaks timer unit TOPSTAT reg */
+#define TSTAT_T0INT            0x1
+#define TSTAT_T1INT            0x2
+#define TSTAT_T2INT            0x4
+#define TSTAT_T3INT            0x8
+/* Bit description of TMx_CTRL register */
+#define TM_START               0x1
+#define TM_REPEAT              0x2
+#define TM_RESET               0x4
+/* Bit description of TIMER_CTRL register */
+#define ENABLE_TM0_INTR        0x1
+#define ENABLE_TM1_INTR        0x2
+#define ENABLE_TM2_INTR        0x4
+#define TIMER_ENABLE_BIT       0x8
+#define ENABLE_TIMER64         0x10
+#define ENABLE_TIMER64_INT     0x20
+
+/* PMU & PLL */
+#define PMU_BASE               (IO_VIRT + 0x1000)
+#define PMU_MODE               0x00
+#define PMU_STAT               0x20
+#define PMU_PLL_CTRL           0x28
+
+/* PMU Mode bits */
+#define PMU_MODE_SLOW          0x00
+#define PMU_MODE_RUN           0x01
+#define PMU_MODE_IDLE          0x02
+#define PMU_MODE_SLEEP         0x03
+#define PMU_MODE_INIT          0x04
+#define PMU_MODE_DEEPSLEEP     0x07
+#define PMU_MODE_WAKEUP                0x08
+
+/* PMU ... */
+#define PLL_2_EN               0x8000
+#define PLL_1_EN               0x4000
+#define PLL_3_MUTE             0x0080
+
+/* Control bits for PMU/ PLL */
+#define PMU_WARMRESET          0x00010000
+#define PLL_CTRL_MASK23                0x000080ff
+
+/* LCD Controller */
+#define LCD_BASE               (IO_VIRT + 0x10000)
+#define LCD_CTRL               0x00
+#define LCD_STATUS             0x04
+#define LCD_STATUS_M           0x08
+#define LCD_INTERRUPT          0x0C
+#define LCD_DBAR               0x10
+#define LCD_DCAR               0x14
+#define LCD_TIMING0            0x20
+#define LCD_TIMING1            0x24
+#define LCD_TIMING2            0x28
+#define LCD_TEST               0x40
+
+/* LCD Control Bits */
+#define LCD_CTRL_LCD_ENABLE    0x00000001
+/* Bits per pixel */
+#define LCD_CTRL_LCD_BPP_MASK  0x00000006
+#define LCD_CTRL_LCD_4BPP      0x00000000
+#define LCD_CTRL_LCD_8BPP      0x00000002
+#define LCD_CTRL_LCD_16BPP     0x00000004
+#define LCD_CTRL_LCD_BW                0x00000008
+#define LCD_CTRL_LCD_TFT       0x00000010
+#define LCD_CTRL_BGR           0x00001000
+#define LCD_CTRL_LCD_VCOMP     0x00080000
+#define LCD_CTRL_LCD_MONO8     0x00200000
+#define LCD_CTRL_LCD_PWR       0x00400000
+#define LCD_CTRL_LCD_BLE       0x00800000
+#define LCD_CTRL_LDBUSEN       0x01000000
+
+/* Palette */
+#define LCD_PALETTE_BASE       (IO_VIRT + 0x10400)
+
+/* Serial ports */
+#define SERIAL0_VIRT           (IO_VIRT + 0x20000)
+#define SERIAL1_VIRT           (IO_VIRT + 0x21000)
+
+#define SERIAL0_BASE           SERIAL0_VIRT
+#define SERIAL1_BASE           SERIAL1_VIRT
+#define SERIAL2_BASE           SERIAL2_VIRT
+#define SERIAL3_BASE           SERIAL3_VIRT
+
+
+/* General defines to pacify gcc */
+#define PCIO_BASE              (0)     /* for inb, outb and friends */
+#define PCIO_VIRT              PCIO_BASE
+
+#define __ASM_ARCH_HARDWARE_INCMACH_H
+#include "boards.h"
+#undef __ASM_ARCH_HARDWARE_INCMACH_H
+
+#endif                         /* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-h720x/io.h b/include/asm-arm/arch-h720x/io.h
new file mode 100644 (file)
index 0000000..c5b737a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-h720x/io.h
+ *
+ * Copyright (C) 2000 Steve Hill (sjhill@cotw.com)
+ *
+ * Changelog:
+ *
+ *  09-19-2001 JJKIM
+ *             Created from linux/include/asm-arm/arch-l7200/io.h
+ *
+ *  03-27-2003  Robert Schwebel <r.schwebel@pengutronix.de>:
+ *             re-unified header files for h720x
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#include <asm/arch/hardware.h>
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) (a)
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/include/asm-arm/arch-h720x/irq.h b/include/asm-arm/arch-h720x/irq.h
new file mode 100644 (file)
index 0000000..b3821e9
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * include/asm-arm/arch-h720x/irq.h
+ *
+ * Copyright (C) 2000-2002 Jungjun Kim
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ */
+
+#ifndef __ASM_ARCH_IRQ_H
+#define __ASM_ARCH_IRQ_H
+
+extern void __init h720x_init_irq (void);
+
+#endif /* __ASM_ARCH_IRQ_H */
diff --git a/include/asm-arm/arch-h720x/irqs.h b/include/asm-arm/arch-h720x/irqs.h
new file mode 100644 (file)
index 0000000..8244413
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * linux/include/asm-arm/arch-h720x/irqs.h
+ *
+ * Copyright (C) 2000 Jungjun Kim
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#if defined (CONFIG_CPU_H7201)
+
+#define IRQ_PMU                0               /* 0x000001 */
+#define IRQ_DMA                1               /* 0x000002 */
+#define IRQ_LCD                2               /* 0x000004 */
+#define IRQ_VGA                3               /* 0x000008 */
+#define IRQ_PCMCIA1    4               /* 0x000010 */
+#define IRQ_PCMCIA2    5               /* 0x000020 */
+#define IRQ_AFE                6               /* 0x000040 */
+#define IRQ_AIC                7               /* 0x000080 */
+#define IRQ_KEYBOARD   8               /* 0x000100 */
+#define IRQ_TIMER0     9               /* 0x000200 */
+#define IRQ_RTC                10              /* 0x000400 */
+#define IRQ_SOUND      11              /* 0x000800 */
+#define IRQ_USB                12              /* 0x001000 */
+#define IRQ_IrDA       13              /* 0x002000 */
+#define IRQ_UART0      14              /* 0x004000 */
+#define IRQ_UART1      15              /* 0x008000 */
+#define IRQ_SPI                16              /* 0x010000 */
+#define IRQ_GPIOA      17              /* 0x020000 */
+#define IRQ_GPIOB      18              /* 0x040000 */
+#define IRQ_GPIOC      19              /* 0x080000 */
+#define IRQ_GPIOD      20              /* 0x100000 */
+#define IRQ_CommRX     21              /* 0x200000 */
+#define IRQ_CommTX     22              /* 0x400000 */
+#define IRQ_Soft       23              /* 0x800000 */
+
+#define NR_GLBL_IRQS   24
+
+#define IRQ_CHAINED_GPIOA(x)  (NR_GLBL_IRQS + x)
+#define IRQ_CHAINED_GPIOB(x)  (IRQ_CHAINED_GPIOA(32) + x)
+#define IRQ_CHAINED_GPIOC(x)  (IRQ_CHAINED_GPIOB(32) + x)
+#define IRQ_CHAINED_GPIOD(x)  (IRQ_CHAINED_GPIOC(32) + x)
+#define NR_IRQS               IRQ_CHAINED_GPIOD(32)
+
+/* Enable mask for multiplexed interrupts */
+#define IRQ_ENA_MUX    (1<<IRQ_GPIOA) | (1<<IRQ_GPIOB) \
+                       | (1<<IRQ_GPIOC) | (1<<IRQ_GPIOD)
+
+
+#elif defined (CONFIG_CPU_H7202)
+
+#define IRQ_PMU                0               /* 0x00000001 */
+#define IRQ_DMA                1               /* 0x00000002 */
+#define IRQ_LCD                2               /* 0x00000004 */
+#define IRQ_SOUND      3               /* 0x00000008 */
+#define IRQ_I2S                4               /* 0x00000010 */
+#define IRQ_USB        5               /* 0x00000020 */
+#define IRQ_MMC        6               /* 0x00000040 */
+#define IRQ_RTC        7               /* 0x00000080 */
+#define IRQ_UART0      8               /* 0x00000100 */
+#define IRQ_UART1      9               /* 0x00000200 */
+#define IRQ_UART2      10              /* 0x00000400 */
+#define IRQ_UART3      11              /* 0x00000800 */
+#define IRQ_KBD        12              /* 0x00001000 */
+#define IRQ_PS2        13              /* 0x00002000 */
+#define IRQ_AIC        14              /* 0x00004000 */
+#define IRQ_TIMER0     15              /* 0x00008000 */
+#define IRQ_TIMERX     16              /* 0x00010000 */
+#define IRQ_WDT        17              /* 0x00020000 */
+#define IRQ_CAN0       18              /* 0x00040000 */
+#define IRQ_CAN1       19              /* 0x00080000 */
+#define IRQ_EXT0       20              /* 0x00100000 */
+#define IRQ_EXT1       21              /* 0x00200000 */
+#define IRQ_GPIOA      22              /* 0x00400000 */
+#define IRQ_GPIOB      23              /* 0x00800000 */
+#define IRQ_GPIOC      24              /* 0x01000000 */
+#define IRQ_GPIOD      25              /* 0x02000000 */
+#define IRQ_GPIOE      26              /* 0x04000000 */
+#define IRQ_COMMRX     27              /* 0x08000000 */
+#define IRQ_COMMTX     28              /* 0x10000000 */
+#define IRQ_SMC        29              /* 0x20000000 */
+#define IRQ_Soft       30              /* 0x40000000 */
+#define IRQ_RESERVED1  31              /* 0x80000000 */
+#define NR_GLBL_IRQS   32
+
+#define NR_TIMERX_IRQS 3
+
+#define IRQ_CHAINED_GPIOA(x)  (NR_GLBL_IRQS + x)
+#define IRQ_CHAINED_GPIOB(x)  (IRQ_CHAINED_GPIOA(32) + x)
+#define IRQ_CHAINED_GPIOC(x)  (IRQ_CHAINED_GPIOB(32) + x)
+#define IRQ_CHAINED_GPIOD(x)  (IRQ_CHAINED_GPIOC(32) + x)
+#define IRQ_CHAINED_GPIOE(x)  (IRQ_CHAINED_GPIOD(32) + x)
+#define IRQ_CHAINED_TIMERX(x) (IRQ_CHAINED_GPIOE(32) + x)
+#define IRQ_TIMER1            (IRQ_CHAINED_TIMERX(0))
+#define IRQ_TIMER2            (IRQ_CHAINED_TIMERX(1))
+#define IRQ_TIMER64B          (IRQ_CHAINED_TIMERX(2))
+
+#define NR_IRQS                (IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS))
+
+/* Enable mask for multiplexed interrupts */
+#define IRQ_ENA_MUX    (1<<IRQ_TIMERX) | (1<<IRQ_GPIOA) | (1<<IRQ_GPIOB) | \
+                       (1<<IRQ_GPIOC)  | (1<<IRQ_GPIOD) | (1<<IRQ_GPIOE) | \
+                       (1<<IRQ_TIMERX)
+
+#else
+#error cpu definition mismatch
+#endif
+
+/* decode irq number to register number */
+#define IRQ_TO_REGNO(irq) ((irq - NR_GLBL_IRQS) >> 5)
+#define IRQ_TO_BIT(irq) (1 << ((irq - NR_GLBL_IRQS) % 32))
+
+#endif
diff --git a/include/asm-arm/arch-h720x/memory.h b/include/asm-arm/arch-h720x/memory.h
new file mode 100644 (file)
index 0000000..5633447
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * linux/include/asm-arm/arch-h720x/memory.h
+ *
+ * Copyright (c) 2000 Jungjun Kim
+ *
+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Page offset:
+ *    ( 0xc0000000UL )
+ */
+#define PHYS_OFFSET    (0x40000000UL)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *              address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *              to an address that the kernel can use.
+ *
+ * There is something to do here later !, Mar 2000, Jungjun Kim
+ */
+
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x)       __virt_to_phys(x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x)       __phys_to_virt(x)
+
+#endif
diff --git a/include/asm-arm/arch-h720x/param.h b/include/asm-arm/arch-h720x/param.h
new file mode 100644 (file)
index 0000000..2b80235
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * linux/include/asm-arm/arch-h720x/param.h
+ *
+ * Copyright (C) 2000 Jungjun Kim
+ */
+
+#ifndef __ASM_ARCH_PARAM_H
+#define __ASM_ARCH_PARAM_H
+
+#endif
diff --git a/include/asm-arm/arch-h720x/serial.h b/include/asm-arm/arch-h720x/serial.h
new file mode 100644 (file)
index 0000000..c91c9f0
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * linux/include/asm-arm/arch-h72x/serial.h
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *
+ * Serial port setup for Hynix boards
+ *
+ * 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_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+#include <asm/arch/irqs.h>
+
+/*
+ * Standard COM flags
+ */
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define RS_TABLE_SIZE
+
+/* Base clock is 3.6864 MHz */
+#define BASE_BAUD       (115200*2)
+#define EXTRA_SERIAL_PORT_DEFNS
+
+/*
+ * Board dependend defines
+ */
+#if defined (CONFIG_CPU_H7201)
+#define BASE_BAUD_P3C  (115200)
+
+#define STD_SERIAL_PORT_DEFNS \
+       { \
+       .baud_base      = BASE_BAUD, \
+       .port           = SERIAL0_BASE, \
+       .iomem_base     = (u8*)SERIAL0_BASE, \
+       .io_type        = UPIO_MEM, \
+       .irq            = IRQ_UART0, \
+       .flags          = STD_COM_FLAGS, \
+       .iomem_reg_shift = 2,\
+       }, \
+       { \
+       .baud_base      = BASE_BAUD, \
+       .port           = SERIAL1_BASE, \
+       .iomem_base     = (u8*)SERIAL1_BASE, \
+       .io_type        = UPIO_MEM, \
+       .irq            = IRQ_UART1, \
+       .flags          = STD_COM_FLAGS, \
+       .iomem_reg_shift = 2,\
+       }
+
+#elif defined (CONFIG_CPU_H7202)
+
+#define STD_SERIAL_PORT_DEFNS \
+       { \
+       .baud_base      = BASE_BAUD, \
+       .port           = SERIAL0_BASE, \
+       .iomem_base     = (u8*)SERIAL0_BASE, \
+       .io_type        = UPIO_MEM, \
+       .irq            = IRQ_UART0, \
+       .flags          = STD_COM_FLAGS, \
+       .iomem_reg_shift = 2,\
+       }, \
+       { \
+       .baud_base      = BASE_BAUD, \
+       .port           = SERIAL1_BASE, \
+       .iomem_base     = (u8*)SERIAL1_BASE, \
+       .io_type        = UPIO_MEM, \
+       .irq            = IRQ_UART1, \
+       .flags          = STD_COM_FLAGS, \
+       .iomem_reg_shift = 2,\
+       }, \
+       { \
+       .baud_base      = BASE_BAUD, \
+       .port           = SERIAL2_BASE, \
+       .iomem_base     = (u8*)SERIAL2_BASE, \
+       .io_type        = UPIO_MEM, \
+       .irq            = IRQ_UART2, \
+       .flags          = STD_COM_FLAGS, \
+       .iomem_reg_shift = 2,\
+       }, \
+       { \
+       .baud_base      = BASE_BAUD, \
+       .port           = SERIAL3_BASE, \
+       .iomem_base     = (u8*)SERIAL3_BASE, \
+       .io_type        = UPIO_MEM, \
+       .irq            = IRQ_UART3, \
+       .flags          = STD_COM_FLAGS, \
+       .iomem_reg_shift = 2,\
+       }
+
+#else
+#error machine definition mismatch
+#endif
+
+/* __ASM_ARCH_SERIAL_H */
+#endif
diff --git a/include/asm-arm/arch-h720x/system.h b/include/asm-arm/arch-h720x/system.h
new file mode 100644 (file)
index 0000000..0b025e2
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/arm/mach-h720x/system.h
+ *
+ * Copyright (C) 2001-2002 Jungjun Kim, Hynix Semiconductor 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.
+ * linux/include/asm-arm/arch-h720x/system.h
+ *
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+#include <asm/hardware.h>
+
+static void arch_idle(void)
+{
+       CPU_REG (PMU_BASE, PMU_MODE) = PMU_MODE_IDLE;
+       __asm__ __volatile__(
+       "mov    r0, r0\n\t"
+       "mov    r0, r0");
+}
+
+
+static __inline__ void arch_reset(char mode)
+{
+       CPU_REG (PMU_BASE, PMU_STAT) |= PMU_WARMRESET;
+}
+
+#endif
diff --git a/include/asm-arm/arch-h720x/timex.h b/include/asm-arm/arch-h720x/timex.h
new file mode 100644 (file)
index 0000000..48a391c
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-arm/arch-h720x/timex.h
+ * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor 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_TIMEX
+#define __ASM_ARCH_TIMEX
+
+#define CLOCK_TICK_RATE                3686400
+
+#endif
diff --git a/include/asm-arm/arch-h720x/uncompress.h b/include/asm-arm/arch-h720x/uncompress.h
new file mode 100644 (file)
index 0000000..2fffacf
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * linux/include/asm-arm/arch-h720x/uncompress.h
+ *
+ * Copyright (C) 2001-2002 Jungjun Kim
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <asm/arch/hardware.h>
+
+#define LSR    0x14
+#define TEMPTY         0x40
+
+static void putstr(const char *s)
+{
+       char c;
+       volatile unsigned char *p = (volatile unsigned char *)(IO_PHYS+0x20000);
+
+       while ( (c = *s++) != '\0') {
+               /* wait until transmit buffer is empty */
+               while((p[LSR] & TEMPTY) == 0x0);
+               /* write next character */
+               *p = c;
+
+               if(c == '\n') {
+                       while((p[LSR] & TEMPTY) == 0x0);
+                       *p = '\r';
+               }
+       }
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif
diff --git a/include/asm-arm/arch-h720x/vmalloc.h b/include/asm-arm/arch-h720x/vmalloc.h
new file mode 100644 (file)
index 0000000..4af523a
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * linux/include/asm-arm/arch-h720x/vmalloc.h
+ */
+
+#ifndef __ARCH_ARM_VMALLOC_H
+#define __ARCH_ARM_VMALLOC_H
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET   (8*1024*1024)
+#define VMALLOC_START    (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+
+#endif
diff --git a/include/asm-arm/arch-imx/dma.h b/include/asm-arm/arch-imx/dma.h
new file mode 100644 (file)
index 0000000..dbdc017
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  linux/include/asm-arm/imxads/dma.h
+ *
+ *  Copyright (C) 1997,1998 Russell King
+ *
+ * This program is free software; you can redistribute 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_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS                0xffffffff
+
+#define MAX_DMA_CHANNELS       0
+
+/*
+ * DMA registration
+ */
+
+typedef enum {
+       DMA_PRIO_HIGH = 0,
+       DMA_PRIO_MEDIUM = 3,
+       DMA_PRIO_LOW = 6
+} imx_dma_prio;
+
+int imx_request_dma(char *name, imx_dma_prio prio,
+                   void (*irq_handler) (int, void *, struct pt_regs *),
+                   void (*err_handler) (int, void *, struct pt_regs *),
+                   void *data);
+
+void imx_free_dma(int dma_ch);
+
+
+#define DMA_REQ_UART3_T        2
+#define DMA_REQ_UART3_R        3
+#define DMA_REQ_SSI2_T         4
+#define DMA_REQ_SSI2_R         5
+#define DMA_REQ_CSI_STAT       6
+#define DMA_REQ_CSI_R          7
+#define DMA_REQ_MSHC           8
+#define DMA_REQ_DSPA_DCT_DOUT  9
+#define DMA_REQ_DSPA_DCT_DIN  10
+#define DMA_REQ_DSPA_MAC      11
+#define DMA_REQ_EXT           12
+#define DMA_REQ_SDHC          13
+#define DMA_REQ_SPI1_R        14
+#define DMA_REQ_SPI1_T        15
+#define DMA_REQ_SSI_T         16
+#define DMA_REQ_SSI_R         17
+#define DMA_REQ_ASP_DAC       18
+#define DMA_REQ_ASP_ADC       19
+#define DMA_REQ_USP_EP(x)    (20+(x))
+#define DMA_REQ_SPI2_R        26
+#define DMA_REQ_SPI2_T        27
+#define DMA_REQ_UART2_T       28
+#define DMA_REQ_UART2_R       29
+#define DMA_REQ_UART1_T       30
+#define DMA_REQ_UART1_R       31
+
+#endif                         /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-imx/hardware.h b/include/asm-arm/arch-imx/hardware.h
new file mode 100644 (file)
index 0000000..c5d559f
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *  linux/include/asm-arm/arch-imx/hardware.h
+ *
+ *  Copyright (C) 1999 ARM Limited.
+ *
+ * This program is free software; you can redistribute 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_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+#include "imx-regs.h"
+
+#ifndef __ASSEMBLY__
+# define __REG(x)      (*((volatile u32 *)IO_ADDRESS(x)))
+
+# define __REG2(x,y)   \
+       ( __builtin_constant_p(y) ? (__REG((x) + (y))) \
+                         : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
+#endif
+
+/*
+ * Memory map
+ */
+
+#define IMX_IO_PHYS            0x00200000
+#define IMX_IO_SIZE            0x00100000
+#define IMX_IO_BASE            0xe0000000
+
+#define IMX_CS0_PHYS           0x10000000
+#define IMX_CS0_SIZE           0x02000000
+#define IMX_CS0_VIRT           0xe8000000
+
+#define IMX_CS1_PHYS           0x12000000
+#define IMX_CS1_SIZE           0x01000000
+#define IMX_CS1_VIRT           0xea000000
+
+#define IMX_CS2_PHYS           0x13000000
+#define IMX_CS2_SIZE           0x01000000
+#define IMX_CS2_VIRT           0xeb000000
+
+#define IMX_CS3_PHYS           0x14000000
+#define IMX_CS3_SIZE           0x01000000
+#define IMX_CS3_VIRT           0xec000000
+
+#define IMX_CS4_PHYS           0x15000000
+#define IMX_CS4_SIZE           0x01000000
+#define IMX_CS4_VIRT           0xed000000
+
+#define IMX_CS5_PHYS           0x16000000
+#define IMX_CS5_SIZE           0x01000000
+#define IMX_CS5_VIRT           0xee000000
+
+#define IMX_FB_VIRT            0xF1000000
+#define IMX_FB_SIZE            (256*1024)
+
+/* macro to get at IO space when running virtually */
+#define IO_ADDRESS(x) ((x) | IMX_IO_BASE)
+
+#ifndef __ASSEMBLY__
+/*
+ * Handy routine to set GPIO functions
+ */
+extern void imx_gpio_mode( int gpio_mode );
+
+/* get frequencies in Hz */
+extern unsigned int imx_get_system_clk(void);
+extern unsigned int imx_get_mcu_clk(void);
+extern unsigned int imx_get_perclk1(void); /* UART[12], Timer[12], PWM */
+extern unsigned int imx_get_perclk2(void); /* LCD, SD, SPI[12]         */
+extern unsigned int imx_get_perclk3(void); /* SSI                      */
+extern unsigned int imx_get_hclk(void);    /* SDRAM, CSI, Memory Stick,*/
+                                           /* I2C, DMA                 */
+#endif
+
+#define MAXIRQNUM                       62
+#define MAXFIQNUM                       62
+#define MAXSWINUM                       62
+
+/*
+ * Use SDRAM for memory
+ */
+#define MEM_SIZE               0x01000000
+
+#ifdef CONFIG_ARCH_MX1ADS
+#include "mx1ads.h"
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-imx/imx-regs.h b/include/asm-arm/arch-imx/imx-regs.h
new file mode 100644 (file)
index 0000000..f32c203
--- /dev/null
@@ -0,0 +1,548 @@
+#ifndef _IMX_REGS_H
+#define _IMX_REGS_H
+/* ------------------------------------------------------------------------
+ *  Motorola IMX system registers
+ * ------------------------------------------------------------------------
+ *
+ */
+
+/*
+ *  Register BASEs, based on OFFSETs
+ *
+ */
+#define IMX_AIPI1_BASE             (0x00000 + IMX_IO_BASE)
+#define IMX_WDT_BASE               (0x01000 + IMX_IO_BASE)
+#define IMX_TIM1_BASE              (0x02000 + IMX_IO_BASE)
+#define IMX_TIM2_BASE              (0x03000 + IMX_IO_BASE)
+#define IMX_RTC_BASE               (0x04000 + IMX_IO_BASE)
+#define IMX_LCDC_BASE              (0x05000 + IMX_IO_BASE)
+#define IMX_UART1_BASE             (0x06000 + IMX_IO_BASE)
+#define IMX_UART2_BASE             (0x07000 + IMX_IO_BASE)
+#define IMX_PWM_BASE               (0x08000 + IMX_IO_BASE)
+#define IMX_DMAC_BASE              (0x09000 + IMX_IO_BASE)
+#define IMX_AIPI2_BASE             (0x10000 + IMX_IO_BASE)
+#define IMX_SIM_BASE               (0x11000 + IMX_IO_BASE)
+#define IMX_USBD_BASE              (0x12000 + IMX_IO_BASE)
+#define IMX_SPI1_BASE              (0x13000 + IMX_IO_BASE)
+#define IMX_MMC_BASE               (0x14000 + IMX_IO_BASE)
+#define IMX_ASP_BASE               (0x15000 + IMX_IO_BASE)
+#define IMX_BTA_BASE               (0x16000 + IMX_IO_BASE)
+#define IMX_I2C_BASE               (0x17000 + IMX_IO_BASE)
+#define IMX_SSI_BASE               (0x18000 + IMX_IO_BASE)
+#define IMX_SPI2_BASE              (0x19000 + IMX_IO_BASE)
+#define IMX_MSHC_BASE              (0x1A000 + IMX_IO_BASE)
+#define IMX_PLL_BASE               (0x1B000 + IMX_IO_BASE)
+#define IMX_GPIO_BASE              (0x1C000 + IMX_IO_BASE)
+#define IMX_EIM_BASE               (0x20000 + IMX_IO_BASE)
+#define IMX_SDRAMC_BASE            (0x21000 + IMX_IO_BASE)
+#define IMX_MMA_BASE               (0x22000 + IMX_IO_BASE)
+#define IMX_AITC_BASE              (0x23000 + IMX_IO_BASE)
+#define IMX_CSI_BASE               (0x24000 + IMX_IO_BASE)
+
+/* PLL registers */
+#define CSCR   __REG(IMX_PLL_BASE)        /* Clock Source Control Register */
+#define CSCR_SYSTEM_SEL (1<<16)
+
+#define MPCTL0 __REG(IMX_PLL_BASE + 0x4)  /* MCU PLL Control Register 0 */
+#define MPCTL1 __REG(IMX_PLL_BASE + 0x8)  /* MCU PLL and System Clock Register 1 */
+#define SPCTL0 __REG(IMX_PLL_BASE + 0xc)  /* System PLL Control Register 0 */
+#define SPCTL1 __REG(IMX_PLL_BASE + 0x10) /* System PLL Control Register 1 */
+#define PCDR   __REG(IMX_PLL_BASE + 0x20) /* Peripheral Clock Divider Register */
+
+#define CSCR_MPLL_RESTART (1<<21)
+
+/*
+ *  GPIO Module and I/O Multiplexer
+ *  x = 0..3 for reg_A, reg_B, reg_C, reg_D
+ */
+#define DDIR(x)    __REG2(IMX_GPIO_BASE + 0x00, ((x) & 3) << 8)
+#define OCR1(x)    __REG2(IMX_GPIO_BASE + 0x04, ((x) & 3) << 8)
+#define OCR2(x)    __REG2(IMX_GPIO_BASE + 0x08, ((x) & 3) << 8)
+#define ICONFA1(x) __REG2(IMX_GPIO_BASE + 0x0c, ((x) & 3) << 8)
+#define ICONFA2(x) __REG2(IMX_GPIO_BASE + 0x10, ((x) & 3) << 8)
+#define ICONFB1(x) __REG2(IMX_GPIO_BASE + 0x14, ((x) & 3) << 8)
+#define ICONFB2(x) __REG2(IMX_GPIO_BASE + 0x18, ((x) & 3) << 8)
+#define DR(x)      __REG2(IMX_GPIO_BASE + 0x1c, ((x) & 3) << 8)
+#define GIUS(x)    __REG2(IMX_GPIO_BASE + 0x20, ((x) & 3) << 8)
+#define SSR(x)     __REG2(IMX_GPIO_BASE + 0x24, ((x) & 3) << 8)
+#define ICR1(x)    __REG2(IMX_GPIO_BASE + 0x28, ((x) & 3) << 8)
+#define ICR2(x)    __REG2(IMX_GPIO_BASE + 0x2c, ((x) & 3) << 8)
+#define IMR(x)     __REG2(IMX_GPIO_BASE + 0x30, ((x) & 3) << 8)
+#define ISR(x)     __REG2(IMX_GPIO_BASE + 0x34, ((x) & 3) << 8)
+#define GPR(x)     __REG2(IMX_GPIO_BASE + 0x38, ((x) & 3) << 8)
+#define SWR(x)     __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 3) << 8)
+#define PUEN(x)    __REG2(IMX_GPIO_BASE + 0x40, ((x) & 3) << 8)
+
+#define GPIO_PIN_MASK 0x1f
+#define GPIO_PORT_MASK (0x3 << 5)
+
+#define GPIO_PORTA (0<<5)
+#define GPIO_PORTB (1<<5)
+#define GPIO_PORTC (2<<5)
+#define GPIO_PORTD (3<<5)
+
+#define GPIO_OUT   (1<<7)
+#define GPIO_IN    (0<<7)
+#define GPIO_PUEN  (1<<8)
+
+#define GPIO_PF    (0<<9)
+#define GPIO_AF    (1<<9)
+
+#define GPIO_OCR_MASK (3<<10)
+#define GPIO_AIN   (0<<10)
+#define GPIO_BIN   (1<<10)
+#define GPIO_CIN   (2<<10)
+#define GPIO_GPIO  (3<<10)
+
+#define GPIO_AOUT  (1<<12)
+#define GPIO_BOUT  (1<<13)
+
+/* assignements for GPIO alternate/primary functions */
+
+/* FIXME: This list is not completed. The correct directions are
+ * missing on some (many) pins
+ */
+#define PA0_PF_A24           ( GPIO_PORTA | GPIO_PF | 0 )
+#define PA0_AIN_SPI2_CLK     ( GPIO_PORTA | GPIO_OUT | GPIO_AIN | 0 )
+#define PA0_AF_ETMTRACESYNC  ( GPIO_PORTA | GPIO_AF | 0 )
+#define PA1_AOUT_SPI2_RXD    ( GPIO_PORTA | GPIO_IN | GPIO_AOUT | 1 )
+#define PA1_PF_TIN           ( GPIO_PORTA | GPIO_PF | 1 )
+#define PA2_PF_PWM0          ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 2 )
+#define PA3_PF_CSI_MCLK      ( GPIO_PORTA | GPIO_PF | 3 )
+#define PA4_PF_CSI_D0        ( GPIO_PORTA | GPIO_PF | 4 )
+#define PA5_PF_CSI_D1        ( GPIO_PORTA | GPIO_PF | 5 )
+#define PA6_PF_CSI_D2        ( GPIO_PORTA | GPIO_PF | 6 )
+#define PA7_PF_CSI_D3        ( GPIO_PORTA | GPIO_PF | 7 )
+#define PA8_PF_CSI_D4        ( GPIO_PORTA | GPIO_PF | 8 )
+#define PA9_PF_CSI_D5        ( GPIO_PORTA | GPIO_PF | 9 )
+#define PA10_PF_CSI_D6       ( GPIO_PORTA | GPIO_PF | 10 )
+#define PA11_PF_CSI_D7       ( GPIO_PORTA | GPIO_PF | 11 )
+#define PA12_PF_CSI_VSYNC    ( GPIO_PORTA | GPIO_PF | 12 )
+#define PA13_PF_CSI_HSYNC    ( GPIO_PORTA | GPIO_PF | 13 )
+#define PA14_PF_CSI_PIXCLK   ( GPIO_PORTA | GPIO_PF | 14 )
+#define PA15_PF_I2C_SDA      ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 15 )
+#define PA16_PF_I2C_SCL      ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 16 )
+#define PA17_AF_ETMTRACEPKT4 ( GPIO_PORTA | GPIO_AF | 17 )
+#define PA17_AIN_SPI2_SS     ( GPIO_PORTA | GPIO_AIN | 17 )
+#define PA18_AF_ETMTRACEPKT5 ( GPIO_PORTA | GPIO_AF | 18 )
+#define PA19_AF_ETMTRACEPKT6 ( GPIO_PORTA | GPIO_AF | 19 )
+#define PA20_AF_ETMTRACEPKT7 ( GPIO_PORTA | GPIO_AF | 20 )
+#define PA21_PF_A0           ( GPIO_PORTA | GPIO_PF | 21 )
+#define PA22_PF_CS4          ( GPIO_PORTA | GPIO_PF | 22 )
+#define PA23_PF_CS5          ( GPIO_PORTA | GPIO_PF | 23 )
+#define PA24_PF_A16          ( GPIO_PORTA | GPIO_PF | 24 )
+#define PA24_AF_ETMTRACEPKT0 ( GPIO_PORTA | GPIO_AF | 24 )
+#define PA25_PF_A17          ( GPIO_PORTA | GPIO_PF | 25 )
+#define PA25_AF_ETMTRACEPKT1 ( GPIO_PORTA | GPIO_AF | 25 )
+#define PA26_PF_A18          ( GPIO_PORTA | GPIO_PF | 26 )
+#define PA26_AF_ETMTRACEPKT2 ( GPIO_PORTA | GPIO_AF | 26 )
+#define PA27_PF_A19          ( GPIO_PORTA | GPIO_PF | 27 )
+#define PA27_AF_ETMTRACEPKT3 ( GPIO_PORTA | GPIO_AF | 27 )
+#define PA28_PF_A20          ( GPIO_PORTA | GPIO_PF | 28 )
+#define PA28_AF_ETMPIPESTAT0 ( GPIO_PORTA | GPIO_AF | 28 )
+#define PA29_PF_A21          ( GPIO_PORTA | GPIO_PF | 29 )
+#define PA29_AF_ETMPIPESTAT1 ( GPIO_PORTA | GPIO_AF | 29 )
+#define PA30_PF_A22          ( GPIO_PORTA | GPIO_PF | 30 )
+#define PA30_AF_ETMPIPESTAT2 ( GPIO_PORTA | GPIO_AF | 30 )
+#define PA31_PF_A23          ( GPIO_PORTA | GPIO_PF | 31 )
+#define PA31_AF_ETMTRACECLK  ( GPIO_PORTA | GPIO_AF | 31 )
+#define PB8_PF_SD_DAT0       ( GPIO_PORTB | GPIO_PF | GPIO_PUEN | 8 )
+#define PB8_AF_MS_PIO        ( GPIO_PORTB | GPIO_AF | 8 )
+#define PB9_PF_SD_DAT1       ( GPIO_PORTB | GPIO_PF | GPIO_PUEN  | 9 )
+#define PB9_AF_MS_PI1        ( GPIO_PORTB | GPIO_AF | 9 )
+#define PB10_PF_SD_DAT2      ( GPIO_PORTB | GPIO_PF | GPIO_PUEN  | 10 )
+#define PB10_AF_MS_SCLKI     ( GPIO_PORTB | GPIO_AF | 10 )
+#define PB11_PF_SD_DAT3      ( GPIO_PORTB | GPIO_PF | 11 )
+#define PB11_AF_MS_SDIO      ( GPIO_PORTB | GPIO_AF | 11 )
+#define PB12_PF_SD_CLK       ( GPIO_PORTB | GPIO_PF | 12 )
+#define PB12_AF_MS_SCLK0     ( GPIO_PORTB | GPIO_AF | 12 )
+#define PB13_PF_SD_CMD       ( GPIO_PORTB | GPIO_PF | GPIO_PUEN | 13 )
+#define PB13_AF_MS_BS        ( GPIO_PORTB | GPIO_AF | 13 )
+#define PB14_AF_SSI_RXFS     ( GPIO_PORTB | GPIO_AF | 14 )
+#define PB15_AF_SSI_RXCLK    ( GPIO_PORTB | GPIO_AF | 15 )
+#define PB16_AF_SSI_RXDAT    ( GPIO_PORTB | GPIO_IN | GPIO_AF | 16 )
+#define PB17_AF_SSI_TXDAT    ( GPIO_PORTB | GPIO_OUT | GPIO_AF | 17 )
+#define PB18_AF_SSI_TXFS     ( GPIO_PORTB | GPIO_AF | 18 )
+#define PB19_AF_SSI_TXCLK    ( GPIO_PORTB | GPIO_AF | 19 )
+#define PB20_PF_USBD_AFE     ( GPIO_PORTB | GPIO_PF | 20 )
+#define PB21_PF_USBD_OE      ( GPIO_PORTB | GPIO_PF | 21 )
+#define PB22_PFUSBD_RCV      ( GPIO_PORTB | GPIO_PF | 22 )
+#define PB23_PF_USBD_SUSPND  ( GPIO_PORTB | GPIO_PF | 23 )
+#define PB24_PF_USBD_VP      ( GPIO_PORTB | GPIO_PF | 24 )
+#define PB25_PF_USBD_VM      ( GPIO_PORTB | GPIO_PF | 25 )
+#define PB26_PF_USBD_VPO     ( GPIO_PORTB | GPIO_PF | 26 )
+#define PB27_PF_USBD_VMO     ( GPIO_PORTB | GPIO_PF | 27 )
+#define PB28_PF_UART2_CTS    ( GPIO_PORTB | GPIO_OUT | GPIO_PF | 28 )
+#define PB29_PF_UART2_RTS    ( GPIO_PORTB | GPIO_IN | GPIO_PF | 29 )
+#define PB30_PF_UART2_TXD    ( GPIO_PORTB | GPIO_OUT | GPIO_PF | 30 )
+#define PB31_PF_UART2_RXD    ( GPIO_PORTB | GPIO_IN | GPIO_PF | 31 )
+#define PC3_PF_SSI_RXFS      ( GPIO_PORTC | GPIO_PF | 3 )
+#define PC4_PF_SSI_RXCLK     ( GPIO_PORTC | GPIO_PF | 4 )
+#define PC5_PF_SSI_RXDAT     ( GPIO_PORTC | GPIO_IN | GPIO_PF | 5 )
+#define PC6_PF_SSI_TXDAT     ( GPIO_PORTC | GPIO_OUT | GPIO_PF | 6 )
+#define PC7_PF_SSI_TXFS      ( GPIO_PORTC | GPIO_PF | 7 )
+#define PC8_PF_SSI_TXCLK     ( GPIO_PORTC | GPIO_PF | 8 )
+#define PC9_PF_UART1_CTS     ( GPIO_PORTC | GPIO_OUT | GPIO_PF | 9 )
+#define PC10_PF_UART1_RTS    ( GPIO_PORTC | GPIO_IN | GPIO_PF | 10 )
+#define PC11_PF_UART1_TXD    ( GPIO_PORTC | GPIO_OUT | GPIO_PF | 11 )
+#define PC12_PF_UART1_RXD    ( GPIO_PORTC | GPIO_IN | GPIO_PF | 12 )
+#define PC13_PF_SPI1_SPI_RDY ( GPIO_PORTC | GPIO_PF | 13 )
+#define PC14_PF_SPI1_SCLK    ( GPIO_PORTC | GPIO_PF | 14 )
+#define PC15_PF_SPI1_SS      ( GPIO_PORTC | GPIO_PF | 15 )
+#define PC16_PF_SPI1_MISO    ( GPIO_PORTC | GPIO_PF | 16 )
+#define PC17_PF_SPI1_MOSI    ( GPIO_PORTC | GPIO_PF | 17 )
+#define PD6_PF_LSCLK         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 6 )
+#define PD7_PF_REV           ( GPIO_PORTD | GPIO_PF | 7 )
+#define PD7_AF_UART2_DTR     ( GPIO_PORTD | GPIO_IN | GPIO_AF | 7 )
+#define PD7_AIN_SPI2_SCLK    ( GPIO_PORTD | GPIO_AIN | 7 )
+#define PD8_PF_CLS           ( GPIO_PORTD | GPIO_PF | 8 )
+#define PD8_AF_UART2_DCD     ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 8 )
+#define PD8_AIN_SPI2_SS      ( GPIO_PORTD | GPIO_AIN | 8 )
+#define PD9_PF_PS            ( GPIO_PORTD | GPIO_PF | 9 )
+#define PD9_AF_UART2_RI      ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 9 )
+#define PD9_AOUT_SPI2_RXD    ( GPIO_PORTD | GPIO_IN | GPIO_AOUT | 9 )
+#define PD10_PF_SPL_SPR      ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 10 )
+#define PD10_AF_UART2_DSR    ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 10 )
+#define PD10_AIN_SPI2_TXD    ( GPIO_PORTD | GPIO_OUT | GPIO_AIN | 10 )
+#define PD11_PF_CONTRAST     ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 11 )
+#define PD12_PF_ACD_OE       ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 12 )
+#define PD13_PF_LP_HSYNC     ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 13 )
+#define PD14_PF_FLM_VSYNC    ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 14 )
+#define PD15_PF_LD0          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 15 )
+#define PD16_PF_LD1          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 16 )
+#define PD17_PF_LD2          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 17 )
+#define PD18_PF_LD3          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 18 )
+#define PD19_PF_LD4          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 19 )
+#define PD20_PF_LD5          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 20 )
+#define PD21_PF_LD6          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 21 )
+#define PD22_PF_LD7          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 22 )
+#define PD23_PF_LD8          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 23 )
+#define PD24_PF_LD9          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 24 )
+#define PD25_PF_LD10         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 25 )
+#define PD26_PF_LD11         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 26 )
+#define PD27_PF_LD12         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 27 )
+#define PD28_PF_LD13         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 28 )
+#define PD29_PF_LD14         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 29 )
+#define PD30_PF_LD15         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 30 )
+#define PD31_PF_TMR2OUT      ( GPIO_PORTD | GPIO_PF | 31 )
+#define PD31_BIN_SPI2_TXD    ( GPIO_PORTD | GPIO_BIN | 31 )
+
+/*
+ *  DMA Controller
+ */
+#define DCR     __REG(IMX_DMAC_BASE +0x00)     /* DMA Control Register */
+#define DISR    __REG(IMX_DMAC_BASE +0x04)     /* DMA Interrupt status Register */
+#define DIMR    __REG(IMX_DMAC_BASE +0x08)     /* DMA Interrupt mask Register */
+#define DBTOSR  __REG(IMX_DMAC_BASE +0x0c)     /* DMA Burst timeout status Register */
+#define DRTOSR  __REG(IMX_DMAC_BASE +0x10)     /* DMA Request timeout Register */
+#define DSESR   __REG(IMX_DMAC_BASE +0x14)     /* DMA Transfer Error Status Register */
+#define DBOSR   __REG(IMX_DMAC_BASE +0x18)     /* DMA Buffer overflow status Register */
+#define DBTOCR  __REG(IMX_DMAC_BASE +0x1c)     /* DMA Burst timeout control Register */
+#define WSRA    __REG(IMX_DMAC_BASE +0x40)     /* W-Size Register A */
+#define XSRA    __REG(IMX_DMAC_BASE +0x44)     /* X-Size Register A */
+#define YSRA    __REG(IMX_DMAC_BASE +0x48)     /* Y-Size Register A */
+#define WSRB    __REG(IMX_DMAC_BASE +0x4c)     /* W-Size Register B */
+#define XSRB    __REG(IMX_DMAC_BASE +0x50)     /* X-Size Register B */
+#define YSRB    __REG(IMX_DMAC_BASE +0x54)     /* Y-Size Register B */
+#define SAR(x)  __REG2( IMX_DMAC_BASE + 0x80, (x) << 6)        /* Source Address Registers */
+#define DAR(x)  __REG2( IMX_DMAC_BASE + 0x84, (x) << 6)        /* Destination Address Registers */
+#define CNTR(x) __REG2( IMX_DMAC_BASE + 0x88, (x) << 6)        /* Count Registers */
+#define CCR(x)  __REG2( IMX_DMAC_BASE + 0x8c, (x) << 6)        /* Control Registers */
+#define RSSR(x) __REG2( IMX_DMAC_BASE + 0x90, (x) << 6)        /* Request source select Registers */
+#define BLR(x)  __REG2( IMX_DMAC_BASE + 0x94, (x) << 6)        /* Burst length Registers */
+#define RTOR(x) __REG2( IMX_DMAC_BASE + 0x98, (x) << 6)        /* Request timeout Registers */
+#define BUCR(x) __REG2( IMX_DMAC_BASE + 0x98, (x) << 6)        /* Bus Utilization Registers */
+
+#define DCR_DRST           (1<<1)
+#define DCR_DEN            (1<<0)
+#define DBTOCR_EN          (1<<15)
+#define DBTOCR_CNT(x)      ((x) & 0x7fff )
+#define CNTR_CNT(x)        ((x) & 0xffffff )
+#define CCR_DMOD_LINEAR    ( 0x0 << 12 )
+#define CCR_DMOD_2D        ( 0x1 << 12 )
+#define CCR_DMOD_FIFO      ( 0x2 << 12 )
+#define CCR_DMOD_EOBFIFO   ( 0x3 << 12 )
+#define CCR_SMOD_LINEAR    ( 0x0 << 10 )
+#define CCR_SMOD_2D        ( 0x1 << 10 )
+#define CCR_SMOD_FIFO      ( 0x2 << 10 )
+#define CCR_SMOD_EOBFIFO   ( 0x3 << 10 )
+#define CCR_MDIR_DEC       (1<<9)
+#define CCR_MSEL_B         (1<<8)
+#define CCR_DSIZ_32        ( 0x0 << 6 )
+#define CCR_DSIZ_8         ( 0x1 << 6 )
+#define CCR_DSIZ_16        ( 0x2 << 6 )
+#define CCR_SSIZ_32        ( 0x0 << 4 )
+#define CCR_SSIZ_8         ( 0x1 << 4 )
+#define CCR_SSIZ_16        ( 0x2 << 4 )
+#define CCR_REN            (1<<3)
+#define CCR_RPT            (1<<2)
+#define CCR_FRC            (1<<1)
+#define CCR_CEN            (1<<0)
+#define RTOR_EN            (1<<15)
+#define RTOR_CLK           (1<<14)
+#define RTOR_PSC           (1<<13)
+
+/*
+ *  Interrupt controller
+ */
+
+#define IMX_INTCNTL        __REG(IMX_AITC_BASE+0x00)
+#define INTCNTL_FIAD       (1<<19)
+#define INTCNTL_NIAD       (1<<20)
+
+#define IMX_NIMASK         __REG(IMX_AITC_BASE+0x04)
+#define IMX_INTENNUM       __REG(IMX_AITC_BASE+0x08)
+#define IMX_INTDISNUM      __REG(IMX_AITC_BASE+0x0c)
+#define IMX_INTENABLEH     __REG(IMX_AITC_BASE+0x10)
+#define IMX_INTENABLEL     __REG(IMX_AITC_BASE+0x14)
+
+/*
+ *  General purpose timers
+ */
+#define IMX_TCTL(x)        __REG( 0x00 + (x))
+#define TCTL_SWR           (1<<15)
+#define TCTL_FRR           (1<<8)
+#define TCTL_CAP_RIS       (1<<6)
+#define TCTL_CAP_FAL       (2<<6)
+#define TCTL_CAP_RIS_FAL   (3<<6)
+#define TCTL_OM            (1<<5)
+#define TCTL_IRQEN         (1<<4)
+#define TCTL_CLK_PCLK1     (1<<1)
+#define TCTL_CLK_PCLK1_16  (2<<1)
+#define TCTL_CLK_TIN       (3<<1)
+#define TCTL_CLK_32        (4<<1)
+#define TCTL_TEN           (1<<0)
+
+#define IMX_TPRER(x)       __REG( 0x04 + (x))
+#define IMX_TCMP(x)        __REG( 0x08 + (x))
+#define IMX_TCR(x)         __REG( 0x0C + (x))
+#define IMX_TCN(x)         __REG( 0x10 + (x))
+#define IMX_TSTAT(x)       __REG( 0x14 + (x))
+#define TSTAT_CAPT         (1<<1)
+#define TSTAT_COMP         (1<<0)
+
+/*
+ * LCD Controller
+ */
+
+#define LCDC_SSA       __REG(IMX_LCDC_BASE+0x00)
+
+#define LCDC_SIZE      __REG(IMX_LCDC_BASE+0x04)
+#define SIZE_XMAX(x)   ((((x) >> 4) & 0x3f) << 20)
+#define SIZE_YMAX(y)    ( (y) & 0x1ff )
+
+#define LCDC_VPW       __REG(IMX_LCDC_BASE+0x08)
+#define VPW_VPW(x)     ( (x) & 0x3ff )
+
+#define LCDC_CPOS      __REG(IMX_LCDC_BASE+0x0C)
+#define CPOS_CC1        (1<<31)
+#define CPOS_CC0        (1<<30)
+#define CPOS_OP         (1<<28)
+#define CPOS_CXP(x)     (((x) & 3ff) << 16)
+#define CPOS_CYP(y)     ((y) & 0x1ff)
+
+#define LCDC_LCWHB     __REG(IMX_LCDC_BASE+0x10)
+#define LCWHB_BK_EN     (1<<31)
+#define LCWHB_CW(w)     (((w) & 0x1f) << 24)
+#define LCWHB_CH(h)     (((h) & 0x1f) << 16)
+#define LCWHB_BD(x)     ((x) & 0xff)
+
+#define LCDC_LCHCC     __REG(IMX_LCDC_BASE+0x14)
+#define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11)
+#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5)
+#define LCHCC_CUR_COL_B(b) ((b) & 0x1f)
+
+#define LCDC_PCR       __REG(IMX_LCDC_BASE+0x18)
+#define PCR_TFT         (1<<31)
+#define PCR_COLOR       (1<<30)
+#define PCR_PBSIZ_1     (0<<28)
+#define PCR_PBSIZ_2     (1<<28)
+#define PCR_PBSIZ_4     (2<<28)
+#define PCR_PBSIZ_8     (3<<28)
+#define PCR_BPIX_1      (0<<25)
+#define PCR_BPIX_2      (1<<25)
+#define PCR_BPIX_4      (2<<25)
+#define PCR_BPIX_8      (3<<25)
+#define PCR_BPIX_12     (4<<25)
+#define PCR_BPIX_16     (4<<25)
+#define PCR_PIXPOL      (1<<24)
+#define PCR_FLMPOL      (1<<23)
+#define PCR_LPPOL       (1<<22)
+#define PCR_CLKPOL      (1<<21)
+#define PCR_OEPOL       (1<<20)
+#define PCR_SCLKIDLE    (1<<19)
+#define PCR_END_SEL     (1<<18)
+#define PCR_END_BYTE_SWAP (1<<17)
+#define PCR_REV_VS      (1<<16)
+#define PCR_ACD_SEL     (1<<15)
+#define PCR_ACD(x)      (((x) & 0x7f) << 8)
+#define PCR_SCLK_SEL    (1<<7)
+#define PCR_SHARP       (1<<6)
+#define PCR_PCD(x)      ((x) & 0x3f)
+
+#define LCDC_HCR       __REG(IMX_LCDC_BASE+0x1C)
+#define HCR_H_WIDTH(x)  (((x) & 0x3f) << 26)
+#define HCR_H_WAIT_1(x) (((x) & 0xff) << 8)
+#define HCR_H_WAIT_2(x) ((x) & 0xff)
+
+#define LCDC_VCR       __REG(IMX_LCDC_BASE+0x20)
+#define VCR_V_WIDTH(x)  (((x) & 0x3f) << 26)
+#define VCR_V_WAIT_1(x) (((x) & 0xff) << 8)
+#define VCR_V_WAIT_2(x) ((x) & 0xff)
+
+#define LCDC_POS       __REG(IMX_LCDC_BASE+0x24)
+#define POS_POS(x)      ((x) & 1f)
+
+#define LCDC_LSCR1     __REG(IMX_LCDC_BASE+0x28)
+#define LSCR1_PS_RISE_DELAY(x)    (((x) & 0x7f) << 26)
+#define LSCR1_CLS_RISE_DELAY(x)   (((x) & 0x3f) << 16)
+#define LSCR1_REV_TOGGLE_DELAY(x) (((x) & 0xf) << 8)
+#define LSCR1_GRAY2(x)            (((x) & 0xf) << 4)
+#define LSCR1_GRAY1(x)            (((x) & 0xf))
+
+#define LCDC_PWMR      __REG(IMX_LCDC_BASE+0x2C)
+#define PWMR_CLS(x)     (((x) & 0x1ff) << 16)
+#define PWMR_LDMSK      (1<<15)
+#define PWMR_SCR1       (1<<10)
+#define PWMR_SCR0       (1<<9)
+#define PWMR_CC_EN      (1<<8)
+#define PWMR_PW(x)      ((x) & 0xff)
+
+#define LCDC_DMACR     __REG(IMX_LCDC_BASE+0x30)
+#define DMACR_BURST     (1<<31)
+#define DMACR_HM(x)     (((x) & 0xf) << 16)
+#define DMACR_TM(x)     ((x) &0xf)
+
+#define LCDC_RMCR      __REG(IMX_LCDC_BASE+0x34)
+#define RMCR_LCDC_EN           (1<<1)
+#define RMCR_SELF_REF          (1<<0)
+
+#define LCDC_LCDICR    __REG(IMX_LCDC_BASE+0x38)
+#define LCDICR_INT_SYN  (1<<2)
+#define LCDICR_INT_CON  (1)
+
+#define LCDC_LCDISR    __REG(IMX_LCDC_BASE+0x40)
+#define LCDISR_UDR_ERR (1<<3)
+#define LCDISR_ERR_RES (1<<2)
+#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
diff --git a/include/asm-arm/arch-imx/io.h b/include/asm-arm/arch-imx/io.h
new file mode 100644 (file)
index 0000000..6c8789f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  linux/include/asm-arm/arch-imxads/io.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute 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_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a)       (a)
+#define __mem_pci(a)  (a)
+
+#endif
diff --git a/include/asm-arm/arch-imx/irq.h b/include/asm-arm/arch-imx/irq.h
new file mode 100644 (file)
index 0000000..545e065
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ *  linux/include/asm-arm/arch-imxads/irq.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute 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
+ */
+#define fixup_irq(i)   (i)
diff --git a/include/asm-arm/arch-imx/irqs.h b/include/asm-arm/arch-imx/irqs.h
new file mode 100644 (file)
index 0000000..238197c
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  linux/include/asm-arm/arch-imxads/irqs.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute 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 __ARM_IRQS_H__
+#define __ARM_IRQS_H__
+
+/* Use the imx definitions */
+#include <asm/arch/hardware.h>
+
+/*
+ *  IMX Interrupt numbers
+ *
+ */
+#define INT_SOFTINT                 0
+#define CSI_INT                     6
+#define DSPA_MAC_INT                7
+#define DSPA_INT                    8
+#define COMP_INT                    9
+#define MSHC_XINT                   10
+#define GPIO_INT_PORTA              11
+#define GPIO_INT_PORTB              12
+#define GPIO_INT_PORTC              13
+#define LCDC_INT                    14
+#define SIM_INT                     15
+#define SIM_DATA_INT                16
+#define RTC_INT                     17
+#define RTC_SAMINT                  18
+#define UART2_MINT_PFERR            19
+#define UART2_MINT_RTS              20
+#define UART2_MINT_DTR              21
+#define UART2_MINT_UARTC            22
+#define UART2_MINT_TX               23
+#define UART2_MINT_RX               24
+#define UART1_MINT_PFERR            25
+#define UART1_MINT_RTS              26
+#define UART1_MINT_DTR              27
+#define UART1_MINT_UARTC            28
+#define UART1_MINT_TX               29
+#define UART1_MINT_RX               30
+#define VOICE_DAC_INT               31
+#define VOICE_ADC_INT               32
+#define PEN_DATA_INT                33
+#define PWM_INT                     34
+#define SDHC_INT                    35
+#define I2C_INT                     39
+#define CSPI_INT                    41
+#define SSI_TX_INT                  42
+#define SSI_TX_ERR_INT              43
+#define SSI_RX_INT                  44
+#define SSI_RX_ERR_INT              45
+#define TOUCH_INT                   46
+#define USBD_INT0                   47
+#define USBD_INT1                   48
+#define USBD_INT2                   49
+#define USBD_INT3                   50
+#define USBD_INT4                   51
+#define USBD_INT5                   52
+#define USBD_INT6                   53
+#define BTSYS_INT                   55
+#define BTTIM_INT                   56
+#define BTWUI_INT                   57
+#define TIM2_INT                    58
+#define TIM1_INT                    59
+#define DMA_ERR                     60
+#define DMA_INT                     61
+#define GPIO_INT_PORTD              62
+
+#define IMX_IRQS                         (64)
+
+/* note: the IMX has four gpio ports (A-D), but only
+ *       the following pins are connected to the outside
+ *       world:
+ *
+ * PORT A: bits 0-31
+ * PORT B: bits 8-31
+ * PORT C: bits 3-17
+ * PORT D: bits 6-31
+ *
+ * We map these interrupts straight on. As a result we have
+ * several holes in the interrupt mapping. We do this for two
+ * reasons:
+ *   - mapping the interrupts without holes would get
+ *     far more complicated
+ *   - Motorola could well decide to bring some processor
+ *     with more pins connected
+ */
+
+#define IRQ_GPIOA(x)  (IMX_IRQS + x)
+#define IRQ_GPIOB(x)  (IRQ_GPIOA(32) + x)
+#define IRQ_GPIOC(x)  (IRQ_GPIOB(32) + x)
+#define IRQ_GPIOD(x)  (IRQ_GPIOC(32) + x)
+
+/* decode irq number to use with IMR(x), ISR(x) and friends */
+#define IRQ_TO_REG(irq) ((irq - IMX_IRQS) >> 5)
+
+#define NR_IRQS (IRQ_GPIOD(32) + 1)
+#define IRQ_GPIO(x)
+#endif
diff --git a/include/asm-arm/arch-imx/memory.h b/include/asm-arm/arch-imx/memory.h
new file mode 100644 (file)
index 0000000..116a91f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  linux/include/asm-arm/arch-imx/memory.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.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_MMU_H
+#define __ASM_ARCH_MMU_H
+
+#define PHYS_OFFSET    (0x08000000UL)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *              address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *              to an address that the kernel can use.
+ */
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x)       (x - PAGE_OFFSET +  PHYS_OFFSET)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x)       (x -  PHYS_OFFSET + PAGE_OFFSET)
+
+#endif
diff --git a/include/asm-arm/arch-imx/mx1ads.h b/include/asm-arm/arch-imx/mx1ads.h
new file mode 100644 (file)
index 0000000..d90fa4b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * linux/include/asm-arm/arch-imx/mx1ads.h
+ *
+ * Copyright (C) 2004 Robert Schwebel, Pengutronix
+ *
+ * This program is free software; you can redistribute 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_MX1ADS_H
+#define __ASM_ARCH_MX1ADS_H
+
+/* ------------------------------------------------------------------------ */
+/* Memory Map for the M9328MX1ADS (MX1ADS) Board                            */
+/* ------------------------------------------------------------------------ */
+
+#define MX1ADS_FLASH_PHYS              0x10000000
+#define MX1ADS_FLASH_SIZE              (16*1024*1024)
+
+#define IMX_FB_PHYS                    (0x0C000000 - 0x40000)
+
+#define CLK32 32000
+
+#endif /* __ASM_ARCH_MX1ADS_H */
diff --git a/include/asm-arm/arch-imx/param.h b/include/asm-arm/arch-imx/param.h
new file mode 100644 (file)
index 0000000..7c724f0
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  linux/include/asm-arm/arch-imx/param.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute 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
+ */
diff --git a/include/asm-arm/arch-imx/serial.h b/include/asm-arm/arch-imx/serial.h
new file mode 100644 (file)
index 0000000..c885c48
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  linux/include/asm-arm/arch-imx/serial.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute 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_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+#define STD_SERIAL_PORT_DEFNS
+#define EXTRA_SERIAL_PORT_DEFNS
+
+#endif /* __ASM_ARCH_SERIAL_H */
diff --git a/include/asm-arm/arch-imx/system.h b/include/asm-arm/arch-imx/system.h
new file mode 100644 (file)
index 0000000..c645fe9
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  linux/include/asm-arm/arch-imxads/system.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute 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_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static void
+arch_idle(void)
+{
+       /*
+        * This should do all the clock switching
+        * and wait for interrupt tricks
+        */
+       cpu_do_idle();
+}
+
+static inline void
+arch_reset(char mode)
+{
+       cpu_reset(0);
+}
+
+#endif
diff --git a/include/asm-arm/arch-imx/timex.h b/include/asm-arm/arch-imx/timex.h
new file mode 100644 (file)
index 0000000..d65ab3c
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  linux/include/asm-arm/imx/timex.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute 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_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+#include <asm/arch/hardware.h>
+#define CLOCK_TICK_RATE                (CLK32)
+
+#endif
diff --git a/include/asm-arm/arch-imx/uncompress.h b/include/asm-arm/arch-imx/uncompress.h
new file mode 100644 (file)
index 0000000..096077f
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *  linux/include/asm-arm/arch-imxads/uncompress.h
+ *
+ *
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) Shane Nay (shane@minirl.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
+ */
+
+#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
+
+#define UART1_BASE 0x206000
+#define UART2_BASE 0x207000
+#define USR2 0x98
+#define USR2_TXFE (1<<14)
+#define TXR  0x40
+#define UCR1 0x80
+#define UCR1_UARTEN 1
+
+/*
+ * The following code assumes the serial port has already been
+ * initialized by the bootloader.  We search for the first enabled
+ * port in the most probable order.  If you didn't setup a port in
+ * your bootloader then nothing will appear (which might be desired).
+ *
+ * This does not append a newline
+ */
+static void
+putstr(const char *s)
+{
+       unsigned long serial_port;
+
+       do {
+               serial_port = UART1_BASE;
+               if ( UART(UCR1) & UCR1_UARTEN )
+                       break;
+               serial_port = UART2_BASE;
+               if ( UART(UCR1) & UCR1_UARTEN )
+                       break;
+               return;
+       } while(0);
+
+       while (*s) {
+               while ( !(UART(USR2) & USR2_TXFE) )
+                       barrier();
+
+               UART(TXR) = *s;
+
+               if (*s == '\n') {
+                       while ( !(UART(USR2) & USR2_TXFE) )
+                               barrier();
+
+                       UART(TXR) = '\r';
+               }
+               s++;
+       }
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-imx/vmalloc.h b/include/asm-arm/arch-imx/vmalloc.h
new file mode 100644 (file)
index 0000000..252038f
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  linux/include/asm-arm/arch-imx/vmalloc.h
+ *
+ *  Copyright (C) 2000 Russell King.
+ *
+ * This program is free software; you can redistribute 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
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET   (8*1024*1024)
+#define VMALLOC_START    (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
index 284a4ae..3957402 100644 (file)
@@ -28,7 +28,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
        while (*s) {
                while (AMBA_UART_FR & (1 << 5));
index 45e1571..797f9e6 100644 (file)
 /*
- * linux/include/asm-arm/arch-iop80310/dma.h
+ * linux/include/asm-arm/arch-iop3xx/dma.h
  *
- *  Copyright (C) 2001 MontaVista Software, Inc.
+ *  Copyright (C) 2004 Intel Corp.
  *
  * 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 _IOP310_DMA_H_
-#define _IOP310_DMA_H_
-
-/* 2 DMA on primary PCI and 1 on secondary for 80310 */
-#define MAX_IOP310_DMA_CHANNEL   3
-#define MAX_DMA_DESC           64      /*128 */
-
-/*
- * Make the generic DMA bits go away since we don't use it
- */
-#define MAX_DMA_CHANNELS       0
+#ifndef _IOP3XX_DMA_H_P
+#define _IOP3XX_DMA_H_P
 
 #define MAX_DMA_ADDRESS                0xffffffff
 
-#define IOP310_DMA_P0          0
-#define IOP310_DMA_P1          1
-#define IOP310_DMA_S0          2
-
-#define DMA_MOD_READ           0x0001
-#define DMA_MOD_WRITE          0x0002
-#define DMA_MOD_CACHED         0x0004
-#define DMA_MOD_NONCACHED      0x0008
-
-
-#define DMA_DESC_DONE          0x0010
-#define DMA_INCOMPLETE         0x0020
-#define DMA_HOLD               0x0040
-#define DMA_END_CHAIN          0x0080
-#define DMA_COMPLETE           0x0100
-#define DMA_NOTIFY             0x0200
-#define DMA_NEW_HEAD           0x0400
-
-#define DMA_USER_MASK  (DMA_NOTIFY | DMA_INCOMPLETE | \
-                                                DMA_HOLD | DMA_COMPLETE)
-
-#define DMA_DCR_DAC            0x00000020      /* Dual Addr Cycle Enab */
-#define DMA_DCR_IE             0x00000010      /* Interrupt Enable */
-#define DMA_DCR_PCI_IOR                0x00000002      /* I/O Read */
-#define DMA_DCR_PCI_IOW                0x00000003      /* I/O Write */
-#define DMA_DCR_PCI_MR         0x00000006      /* Memory Read */
-#define DMA_DCR_PCI_MW         0x00000007      /* Memory Write */
-#define DMA_DCR_PCI_CR         0x0000000A      /* Configuration Read */
-#define DMA_DCR_PCI_CW         0x0000000B      /* Configuration Write */
-#define DMA_DCR_PCI_MRM                0x0000000C      /* Memory Read Multiple */
-#define DMA_DCR_PCI_MRL                0x0000000E      /* Memory Read Line */
-#define DMA_DCR_PCI_MWI                0x0000000F      /* Mem Write and Inval */
-
-#define DMA_USER_CMD_IE                0x00000001      /* user request int */
-#define DMA_USER_END_CHAIN     0x00000002      /* end of sgl chain flag */
-
-/* ATU defines */
-#define     IOP310_ATUCR_PRIM_OUT_ENAB  /* Configuration   */      0x00000002
-#define     IOP310_ATUCR_DIR_ADDR_ENAB  /* Configuration   */      0x00000080
-
-
-typedef void (*dma_callback_t) (void *buf_context);
-/*
- * DMA Descriptor
- */
-typedef struct _dma_desc
-{
-       u32 NDAR;                                       /* next descriptor address */
-       u32 PDAR;                                       /* PCI address */
-       u32 PUADR;                                      /* upper PCI address */
-       u32 LADR;                                       /* local address */
-       u32 BC;                                         /* byte count */
-       u32 DC;                                         /* descriptor control */
-} dma_desc_t;
-
-typedef struct _dma_sgl
-{
-       dma_desc_t dma_desc;            /* DMA descriptor pointer */
-       u32 status;                                     /* descriptor status */
-       void *data;                                     /* local virt */
-       struct _dma_sgl *next;          /* next descriptor */
-} dma_sgl_t;
-
-/* dma sgl head */
-typedef struct _dma_head
-{
-       u32 total;                                      /* total elements in SGL */
-       u32 status;                                     /* status of sgl */
-       u32 mode;                                       /* read or write mode */
-       dma_sgl_t *list;                        /* pointer to list */
-       dma_callback_t callback;        /* callback function */
-} dma_head_t;
-
-/* function prototypes */
-int dma_request(dmach_t, const char *);
-int dma_queue_buffer(dmach_t, dma_head_t *);
-int dma_suspend(dmach_t);
-int dma_resume(dmach_t);
-int dma_flush_all(dmach_t);
-void dma_free(dmach_t);
-void dma_set_irq_threshold(dmach_t, int);
-dma_sgl_t *dma_get_buffer(dmach_t, int);
-void dma_return_buffer(dmach_t, dma_sgl_t *);
-
-#endif /* _ASM_ARCH_DMA_H */
+#endif /* _ASM_ARCH_DMA_H_P */
index 03338ca..6c15fde 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * linux/include/asm-arm/arch-iop80310/hardware.h
+ * linux/include/asm-arm/arch-iop3xx/hardware.h
  */
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <linux/config.h>
+#include <asm/types.h>
 
 /*
  * Note about PCI IO space mappings
  * The PCI IO space is located at virtual 0xfe000000 from physical
  * 0x90000000.  The PCI BARs must be programmed with physical addresses,
  * but when we read them, we convert them to virtual addresses.  See
- * arch/arm/mach-iop310/iop310-pci.c
+ * arch/arm/mach-iop3xx/iop3xx-pci.c
  */
 
 #define pcibios_assign_all_busses() 1
 
-#ifdef CONFIG_ARCH_IOP310
+
 /*
- * these are the values for the secondary PCI bus on the 80312 chip.  I will
- * have to do some fixup in the bus/dev fixup code
+ * The min PCI I/O and MEM space are dependent on what specific
+ * chipset/platform we are running on, so instead of hardcoding with
+ * #ifdefs, we just fill these in the platform level PCI init code.
  */
-#define PCIBIOS_MIN_IO      0
-#define PCIBIOS_MIN_MEM     0x88000000
-
-// Generic chipset bits
-#include "iop310.h"
+#ifndef __ASSEMBLY__
+extern unsigned long iop3xx_pcibios_min_io;
+extern unsigned long iop3xx_pcibios_min_mem;
 
-// Board specific
-#if defined(CONFIG_ARCH_IQ80310)
-#include "iq80310.h"
+extern unsigned int processor_id;
 #endif
-#endif
-
-#ifdef CONFIG_ARCH_IOP321
 
-#define PCIBIOS_MIN_IO         0x90000000
-#define PCIBIOS_MIN_MEM                0x80000000
+/*
+ * We just set these to zero since they are really bogus anyways
+ */
+#define PCIBIOS_MIN_IO      (iop3xx_pcibios_min_io)
+#define PCIBIOS_MIN_MEM     (iop3xx_pcibios_min_mem)
 
+/*
+ * Generic chipset bits
+ *
+ */
 #include "iop321.h"
+#include "iop331.h"
 
-#ifdef CONFIG_ARCH_IQ80321
+/*
+ * Board specific bits
+ */
 #include "iq80321.h"
-#endif
-#endif
-
-
-
+#include "iq31244.h"
+#include "iq80331.h"
 
 #endif  /* _ASM_ARCH_HARDWARE_H */
index 9d5518d..2fcc165 100644 (file)
@@ -9,8 +9,8 @@
  * published by the Free Software Foundation.
  *
  */
-
-#include <linux/config.h>
+#ifndef _IOP321_IRQS_H_
+#define _IOP321_IRQS_H_
 
 /*
  * IOP80321 chipset interrupts
@@ -62,7 +62,6 @@
 /*
  * Interrupts available on the IQ80321 board
  */
-#ifdef CONFIG_ARCH_IQ80321
 
 /*
  * On board devices
 #define        IRQ_IQ80321_INTC        IRQ_IOP321_XINT2
 #define        IRQ_IQ80321_INTD        IRQ_IOP321_XINT3
 
-#endif // CONFIG_ARCH_IQ80321
+/*
+ * Interrupts on the IQ31244 board
+ */
+
+/*
+ * On board devices
+ */
+#define IRQ_IQ31244_UART       IRQ_IOP321_XINT1
+#define        IRQ_IQ31244_I82546      IRQ_IOP321_XINT0
+#define IRQ_IQ31244_SATA       IRQ_IOP321_XINT2
+#define        IRQ_IQ31244_PCIX_SLOT   IRQ_IOP321_XINT3
 
-#define XSCALE_PMU_IRQ IRQ_IOP321_CORE_PMU
+/*
+ * PCI interrupts
+ */
+#define        IRQ_IQ31244_INTA        IRQ_IOP321_XINT0
+#define        IRQ_IQ31244_INTB        IRQ_IOP321_XINT1
+#define        IRQ_IQ31244_INTC        IRQ_IOP321_XINT2
+#define        IRQ_IQ31244_INTD        IRQ_IOP321_XINT3
 
+#endif // _IOP321_IRQ_H_
index dcf2c7f..98908a0 100644 (file)
  * IOP3xx variants but behave slightly differently on each.
  */
 #ifndef __ASSEMBLY__
-#define iop_is_321() ((processor_id & 0xfffff7e0) == 0x69052420)
+#ifdef CONFIG_ARCH_IOP321
+#define iop_is_321() (((processor_id & 0xfffff5e0) == 0x69052420))
+#else
+#define        iop_is_321()    0
+#endif
 #endif
-
 
 /*
  * IOP321 I/O and Mem space regions for PCI autoconfiguration
  */
+#define IOP321_PCI_LOWER_IO             0x90000000
+#define IOP321_PCI_UPPER_IO             0x9000ffff
+#define IOP321_PCI_LOWER_MEM            0x80000000
+#define IOP321_PCI_UPPER_MEM            0x83ffffff
+
+#define IOP321_PCI_WINDOW_SIZE          64 * 0x100000
 
-#define        IOP321_PCI_IO_BASE              0x90000000
-#define        IOP321_PCI_IO_SIZE              0x00010000
-#define IOP321_PCI_MEM_BASE            0x40000000
-#define IOP321_PCI_MEM_SIZE            0x40000000
 
 /*
  * IOP321 chipset registers
  */
-#define IOP321_VIRT_MEM_BASE 0xfff00000  /* chip virtual mem address*/
+#define IOP321_VIRT_MEM_BASE 0xfeffe000  /* chip virtual mem address*/
+//#define IOP321_VIRT_MEM_BASE 0xfff00000  /* chip virtual mem address*/
 
 #define IOP321_PHY_MEM_BASE  0xffffe000  /* chip physical memory address */
 #define IOP321_REG_ADDR(reg) (IOP321_VIRT_MEM_BASE | (reg))
 #define IOP321_OPHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000378)
 #define IOP321_OPTPR      (volatile u32 *)IOP321_REG_ADDR(0x0000037C)
 #define IOP321_IAR        (volatile u32 *)IOP321_REG_ADDR(0x00000380)
+
+#define IOP321_IIxR_MASK       0x7f /* masks all */
+#define IOP321_IIxR_IRI                0x40 /* RC Index Register Interrupt */
+#define IOP321_IIxR_OFQF       0x20 /* RC Output Free Q Full (ERROR) */
+#define IOP321_IIxR_ipq                0x10 /* RC Inbound Post Q (post) */
+#define IOP321_IIxR_ERRDI      0x08 /* RO Error Doorbell Interrupt */
+#define IOP321_IIxR_IDI                0x04 /* RO Inbound Doorbell Interrupt */
+#define IOP321_IIxR_IM1                0x02 /* RC Inbound Message 1 Interrupt */
+#define IOP321_IIxR_IM0                0x01 /* RC Inbound Message 0 Interrupt */
+
 /* Reserved 0x00000384 through 0x000003FF */
 
 /* DMA Controller 0x00000400 through 0x000004FF */
 
 #define IOP321_PBISR_BOOR_ERR 0x1
 
+/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
+#define IOP321_GTMR    (volatile u32 *)IOP321_REG_ADDR(0x00000700)
+#define IOP321_ESR     (volatile u32 *)IOP321_REG_ADDR(0x00000704)
+#define IOP321_EMISR   (volatile u32 *)IOP321_REG_ADDR(0x00000708)
+/* reserved 0x00000070c */
+#define IOP321_GTSR    (volatile u32 *)IOP321_REG_ADDR(0x00000710)
+/* PERC0 DOESN'T EXIST - index from 1! */
+#define IOP321_PERCR0  (volatile u32 *)IOP321_REG_ADDR(0x00000710)
 
+#define IOP321_GTMR_NGCE       0x04 /* (Not) Global Counter Enable */
 
-/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
 /* Internal arbitration unit 0x00000780 through 0x0007BF */
+#define IOP321_IACR    (volatile u32 *)IOP321_REG_ADDR(0x00000780)
+#define IOP321_MTTR1   (volatile u32 *)IOP321_REG_ADDR(0x00000784)
+#define IOP321_MTTR2   (volatile u32 *)IOP321_REG_ADDR(0x00000788)
 
 /* General Purpose I/O Registers */
 #define IOP321_GPOE       (volatile u32 *)IOP321_REG_ADDR(0x000007C4)
 #define IOP321_TU_TMR0         (volatile u32 *)IOP321_REG_ADDR(0x000007E0)
 #define IOP321_TU_TMR1         (volatile u32 *)IOP321_REG_ADDR(0x000007E4)
 
+#ifdef CONFIG_ARCH_IQ80321
+#define        IOP321_TICK_RATE        200000000       /* 200 MHz clock */
+#elif defined(CONFIG_ARCH_IQ31244)
+#define IOP321_TICK_RATE       198000000       /* 33.000 MHz crystal */
+#endif
+
+#ifdef CONFIG_ARCH_EP80219
+#undef IOP321_TICK_RATE
+#define IOP321_TICK_RATE 200000000 /* 33.333333 Mhz crystal */
+#endif
+
 #define IOP321_TMR_TC          0x01
 #define        IOP321_TMR_EN           0x02
 #define IOP321_TMR_RELOAD      0x04
 #define IOP321_TU_TISR    (volatile u32 *)IOP321_REG_ADDR(0x000007F8)
 #define IOP321_TU_WDTCR   (volatile u32 *)IOP321_REG_ADDR(0x000007FC)
 
-
-
 /* Application accelerator unit 0x00000800 - 0x000008FF */
 #define IOP321_AAU_ACR     (volatile u32 *)IOP321_REG_ADDR(0x00000800)
 #define IOP321_AAU_ASR     (volatile u32 *)IOP321_REG_ADDR(0x00000804)
 #define IOP321_AAU_ADAR    (volatile u32 *)IOP321_REG_ADDR(0x00000808)
 #define IOP321_AAU_ANDAR   (volatile u32 *)IOP321_REG_ADDR(0x0000080C)
 #define IOP321_AAU_SAR1    (volatile u32 *)IOP321_REG_ADDR(0x00000810)
-/* SAR2...SAR32 0x00000814 - 0x000008A4 */
+#define IOP321_AAU_SAR2    (volatile u32 *)IOP321_REG_ADDR(0x00000814)
+#define IOP321_AAU_SAR3    (volatile u32 *)IOP321_REG_ADDR(0x00000818)
+#define IOP321_AAU_SAR4    (volatile u32 *)IOP321_REG_ADDR(0x0000081C)
+#define IOP321_AAU_SAR5    (volatile u32 *)IOP321_REG_ADDR(0x0000082C)
+#define IOP321_AAU_SAR6    (volatile u32 *)IOP321_REG_ADDR(0x00000830)
+#define IOP321_AAU_SAR7    (volatile u32 *)IOP321_REG_ADDR(0x00000834)
+#define IOP321_AAU_SAR8    (volatile u32 *)IOP321_REG_ADDR(0x00000838)
+#define IOP321_AAU_SAR9    (volatile u32 *)IOP321_REG_ADDR(0x00000840)
+#define IOP321_AAU_SAR10   (volatile u32 *)IOP321_REG_ADDR(0x00000844)
+#define IOP321_AAU_SAR11   (volatile u32 *)IOP321_REG_ADDR(0x00000848)
+#define IOP321_AAU_SAR12   (volatile u32 *)IOP321_REG_ADDR(0x0000084C)
+#define IOP321_AAU_SAR13   (volatile u32 *)IOP321_REG_ADDR(0x00000850)
+#define IOP321_AAU_SAR14   (volatile u32 *)IOP321_REG_ADDR(0x00000854)
+#define IOP321_AAU_SAR15   (volatile u32 *)IOP321_REG_ADDR(0x00000858)
+#define IOP321_AAU_SAR16   (volatile u32 *)IOP321_REG_ADDR(0x0000085C)
+#define IOP321_AAU_SAR17   (volatile u32 *)IOP321_REG_ADDR(0x00000864)
+#define IOP321_AAU_SAR18   (volatile u32 *)IOP321_REG_ADDR(0x00000868)
+#define IOP321_AAU_SAR19   (volatile u32 *)IOP321_REG_ADDR(0x0000086C)
+#define IOP321_AAU_SAR20   (volatile u32 *)IOP321_REG_ADDR(0x00000870)
+#define IOP321_AAU_SAR21   (volatile u32 *)IOP321_REG_ADDR(0x00000874)
+#define IOP321_AAU_SAR22   (volatile u32 *)IOP321_REG_ADDR(0x00000878)
+#define IOP321_AAU_SAR23   (volatile u32 *)IOP321_REG_ADDR(0x0000087C)
+#define IOP321_AAU_SAR24   (volatile u32 *)IOP321_REG_ADDR(0x00000880)
+#define IOP321_AAU_SAR25   (volatile u32 *)IOP321_REG_ADDR(0x00000888)
+#define IOP321_AAU_SAR26   (volatile u32 *)IOP321_REG_ADDR(0x0000088C)
+#define IOP321_AAU_SAR27   (volatile u32 *)IOP321_REG_ADDR(0x00000890)
+#define IOP321_AAU_SAR28   (volatile u32 *)IOP321_REG_ADDR(0x00000894)
+#define IOP321_AAU_SAR29   (volatile u32 *)IOP321_REG_ADDR(0x00000898)
+#define IOP321_AAU_SAR30   (volatile u32 *)IOP321_REG_ADDR(0x0000089C)
+#define IOP321_AAU_SAR31   (volatile u32 *)IOP321_REG_ADDR(0x000008A0)
+#define IOP321_AAU_SAR32   (volatile u32 *)IOP321_REG_ADDR(0x000008A4)
 #define IOP321_AAU_DAR     (volatile u32 *)IOP321_REG_ADDR(0x00000820)
 #define IOP321_AAU_ABCR    (volatile u32 *)IOP321_REG_ADDR(0x00000824)
 #define IOP321_AAU_ADCR    (volatile u32 *)IOP321_REG_ADDR(0x00000828)
 
 /* for I2C bit defs see drivers/i2c/i2c-iop3xx.h */
 
+
+#ifndef __ASSEMBLY__
+extern void iop321_map_io(void);
+extern void iop321_init_irq(void);
+extern void iop321_time_init(void);
+#endif
+
 #endif // _IOP321_HW_H_
diff --git a/include/asm-arm/arch-iop3xx/iop331-irqs.h b/include/asm-arm/arch-iop3xx/iop331-irqs.h
new file mode 100644 (file)
index 0000000..37063b4
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * linux/include/asm-arm/arch-iop3xx/irqs.h
+ *
+ * Author:     Dave Jiang (dave.jiang@intel.com)
+ * Copyright:  (C) 2003 Intel Corp.
+ *
+ * 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 _IOP331_IRQS_H_
+#define _IOP331_IRQS_H_
+
+/*
+ * IOP80331 chipset interrupts
+ */
+#define IOP331_IRQ_OFS         0
+#define IOP331_IRQ(x)          (IOP331_IRQ_OFS + (x))
+
+/*
+ * On IRQ or FIQ register
+ */
+#define IRQ_IOP331_DMA0_EOT    IOP331_IRQ(0)
+#define IRQ_IOP331_DMA0_EOC    IOP331_IRQ(1)
+#define IRQ_IOP331_DMA1_EOT    IOP331_IRQ(2)
+#define IRQ_IOP331_DMA1_EOC    IOP331_IRQ(3)
+#define IRQ_IOP331_RSVD_4      IOP331_IRQ(4)
+#define IRQ_IOP331_RSVD_5      IOP331_IRQ(5)
+#define IRQ_IOP331_AA_EOT      IOP331_IRQ(6)
+#define IRQ_IOP331_AA_EOC      IOP331_IRQ(7)
+#define IRQ_IOP331_TIMER0      IOP331_IRQ(8)
+#define IRQ_IOP331_TIMER1      IOP331_IRQ(9)
+#define IRQ_IOP331_I2C_0       IOP331_IRQ(10)
+#define IRQ_IOP331_I2C_1       IOP331_IRQ(11)
+#define IRQ_IOP331_MSG     IOP331_IRQ(12)
+#define IRQ_IOP331_MSGIBQ   IOP331_IRQ(13)
+#define IRQ_IOP331_ATU_BIST    IOP331_IRQ(14)
+#define IRQ_IOP331_PERFMON     IOP331_IRQ(15)
+#define IRQ_IOP331_CORE_PMU    IOP331_IRQ(16)
+#define IRQ_IOP331_RSVD_17     IOP331_IRQ(17)
+#define IRQ_IOP331_RSVD_18     IOP331_IRQ(18)
+#define IRQ_IOP331_RSVD_19     IOP331_IRQ(19)
+#define IRQ_IOP331_RSVD_20     IOP331_IRQ(20)
+#define IRQ_IOP331_RSVD_21     IOP331_IRQ(21)
+#define IRQ_IOP331_RSVD_22     IOP331_IRQ(22)
+#define IRQ_IOP331_RSVD_23     IOP331_IRQ(23)
+#define IRQ_IOP331_XINT0       IOP331_IRQ(24)
+#define IRQ_IOP331_XINT1       IOP331_IRQ(25)
+#define IRQ_IOP331_XINT2       IOP331_IRQ(26)
+#define IRQ_IOP331_XINT3       IOP331_IRQ(27)
+#define IRQ_IOP331_RSVD_28  IOP331_IRQ(28)
+#define IRQ_IOP331_RSVD_29  IOP331_IRQ(29)
+#define IRQ_IOP331_RSVD_30  IOP331_IRQ(30)
+#define IRQ_IOP331_RSVD_31  IOP331_IRQ(31)
+#define IRQ_IOP331_XINT8    IOP331_IRQ(32)  // 0
+#define IRQ_IOP331_XINT9    IOP331_IRQ(33)  // 1
+#define IRQ_IOP331_XINT10   IOP331_IRQ(34)  // 2
+#define IRQ_IOP331_XINT11   IOP331_IRQ(35)  // 3
+#define IRQ_IOP331_XINT12   IOP331_IRQ(36)  // 4
+#define IRQ_IOP331_XINT13   IOP331_IRQ(37)  // 5
+#define IRQ_IOP331_XINT14   IOP331_IRQ(38)  // 6
+#define IRQ_IOP331_XINT15   IOP331_IRQ(39)  // 7
+#define IRQ_IOP331_RSVD_40  IOP331_IRQ(40)  // 8
+#define IRQ_IOP331_RSVD_41  IOP331_IRQ(41)  // 9
+#define IRQ_IOP331_RSVD_42  IOP331_IRQ(42)  // 10
+#define IRQ_IOP331_RSVD_43  IOP331_IRQ(43)  // 11
+#define IRQ_IOP331_RSVD_44  IOP331_IRQ(44)  // 12
+#define IRQ_IOP331_RSVD_45  IOP331_IRQ(45)  // 13
+#define IRQ_IOP331_RSVD_46  IOP331_IRQ(46)  // 14
+#define IRQ_IOP331_RSVD_47  IOP331_IRQ(47)  // 15
+#define IRQ_IOP331_RSVD_48  IOP331_IRQ(48)  // 16
+#define IRQ_IOP331_RSVD_49  IOP331_IRQ(49)  // 17
+#define IRQ_IOP331_RSVD_50  IOP331_IRQ(50)  // 18
+#define IRQ_IOP331_UART0    IOP331_IRQ(51)  // 19
+#define IRQ_IOP331_UART1    IOP331_IRQ(52)  // 20
+#define IRQ_IOP331_PBIE     IOP331_IRQ(53)  // 21
+#define IRQ_IOP331_ATU_CRW  IOP331_IRQ(54)  // 22
+#define IRQ_IOP331_ATU_ERR     IOP331_IRQ(55)  // 23
+#define IRQ_IOP331_MCU_ERR     IOP331_IRQ(56)  // 24
+#define IRQ_IOP331_DMA0_ERR    IOP331_IRQ(57)  // 25
+#define IRQ_IOP331_DMA1_ERR    IOP331_IRQ(58)  // 26
+#define IRQ_IOP331_RSVD_59  IOP331_IRQ(59)  // 27
+#define IRQ_IOP331_AA_ERR      IOP331_IRQ(60)  // 28
+#define IRQ_IOP331_RSVD_61  IOP331_IRQ(61)  // 29
+#define IRQ_IOP331_MSG_ERR     IOP331_IRQ(62)  // 30
+#define IRQ_IOP331_HPI         IOP331_IRQ(63)  // 31
+
+#define NR_IOP331_IRQS         (IOP331_IRQ(63) + 1)
+
+#define NR_IRQS                        NR_IOP331_IRQS
+
+
+/*
+ * Interrupts available on the IQ80331 board
+ */
+
+/*
+ * On board devices
+ */
+#define        IRQ_IQ80331_I82544      IRQ_IOP331_XINT0
+#define IRQ_IQ80331_UART0      IRQ_IOP331_UART0
+#define IRQ_IQ80331_UART1      IRQ_IOP331_UART1
+
+/*
+ * PCI interrupts
+ */
+#define        IRQ_IQ80331_INTA        IRQ_IOP331_XINT0
+#define        IRQ_IQ80331_INTB        IRQ_IOP331_XINT1
+#define        IRQ_IQ80331_INTC        IRQ_IOP331_XINT2
+#define        IRQ_IQ80331_INTD        IRQ_IOP331_XINT3
+
+#endif // _IOP331_IRQ_H_
diff --git a/include/asm-arm/arch-iop3xx/iop331.h b/include/asm-arm/arch-iop3xx/iop331.h
new file mode 100644 (file)
index 0000000..c4854a1
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * linux/include/asm/arch-iop3xx/iop331.h
+ *
+ * Intel IOP331 Chip definitions
+ *
+ * Author: Dave Jiang (dave.jiang@intel.com)
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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 _IOP331_HW_H_
+#define _IOP331_HW_H_
+
+
+/*
+ * This is needed for mixed drivers that need to work on all
+ * IOP3xx variants but behave slightly differently on each.
+ */
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_ARCH_IOP331
+#define        iop_is_331()    ((processor_id & 0xffffffb0) == 0x69054090)
+#else
+#define        iop_is_331()    0
+#endif
+#endif
+
+/*
+ * IOP331 I/O and Mem space regions for PCI autoconfiguration
+ */
+#define IOP331_PCI_LOWER_IO             0x90000000
+#define IOP331_PCI_UPPER_IO             0x900fffff
+#define IOP331_PCI_LOWER_MEM            0x80000000
+#define IOP331_PCI_UPPER_MEM            0x87ffffff
+
+#define IOP331_PCI_WINDOW_SIZE          128 * 0x100000
+
+
+/*
+ * IOP331 chipset registers
+ */
+#define IOP331_VIRT_MEM_BASE 0xfeffe000  /* chip virtual mem address*/
+// #define IOP331_VIRT_MEM_BASE 0xfff00000  /* chip virtual mem address*/
+
+#define IOP331_PHYS_MEM_BASE  0xffffe000  /* chip physical memory address */
+#define IOP331_REG_ADDR(reg) (IOP331_VIRT_MEM_BASE | (reg))
+
+/* Reserved 0x00000000 through 0x000000FF */
+
+/* Address Translation Unit 0x00000100 through 0x000001FF */
+#define IOP331_ATUVID     (volatile u16 *)IOP331_REG_ADDR(0x00000100)
+#define IOP331_ATUDID     (volatile u16 *)IOP331_REG_ADDR(0x00000102)
+#define IOP331_ATUCMD     (volatile u16 *)IOP331_REG_ADDR(0x00000104)
+#define IOP331_ATUSR      (volatile u16 *)IOP331_REG_ADDR(0x00000106)
+#define IOP331_ATURID     (volatile u8  *)IOP331_REG_ADDR(0x00000108)
+#define IOP331_ATUCCR     (volatile u32 *)IOP331_REG_ADDR(0x00000109)
+#define IOP331_ATUCLSR    (volatile u8  *)IOP331_REG_ADDR(0x0000010C)
+#define IOP331_ATULT      (volatile u8  *)IOP331_REG_ADDR(0x0000010D)
+#define IOP331_ATUHTR     (volatile u8  *)IOP331_REG_ADDR(0x0000010E)
+#define IOP331_ATUBIST    (volatile u8  *)IOP331_REG_ADDR(0x0000010F)
+#define IOP331_IABAR0     (volatile u32 *)IOP331_REG_ADDR(0x00000110)
+#define IOP331_IAUBAR0    (volatile u32 *)IOP331_REG_ADDR(0x00000114)
+#define IOP331_IABAR1     (volatile u32 *)IOP331_REG_ADDR(0x00000118)
+#define IOP331_IAUBAR1    (volatile u32 *)IOP331_REG_ADDR(0x0000011C)
+#define IOP331_IABAR2     (volatile u32 *)IOP331_REG_ADDR(0x00000120)
+#define IOP331_IAUBAR2    (volatile u32 *)IOP331_REG_ADDR(0x00000124)
+#define IOP331_ASVIR      (volatile u16 *)IOP331_REG_ADDR(0x0000012C)
+#define IOP331_ASIR       (volatile u16 *)IOP331_REG_ADDR(0x0000012E)
+#define IOP331_ERBAR      (volatile u32 *)IOP331_REG_ADDR(0x00000130)
+#define IOP331_ATU_CAPPTR (volatile u32 *)IOP331_REG_ADDR(0x00000134)
+/* Reserved 0x00000138 through 0x0000013B */
+#define IOP331_ATUILR     (volatile u8  *)IOP331_REG_ADDR(0x0000013C)
+#define IOP331_ATUIPR     (volatile u8  *)IOP331_REG_ADDR(0x0000013D)
+#define IOP331_ATUMGNT    (volatile u8  *)IOP331_REG_ADDR(0x0000013E)
+#define IOP331_ATUMLAT    (volatile u8  *)IOP331_REG_ADDR(0x0000013F)
+#define IOP331_IALR0      (volatile u32 *)IOP331_REG_ADDR(0x00000140)
+#define IOP331_IATVR0     (volatile u32 *)IOP331_REG_ADDR(0x00000144)
+#define IOP331_ERLR       (volatile u32 *)IOP331_REG_ADDR(0x00000148)
+#define IOP331_ERTVR      (volatile u32 *)IOP331_REG_ADDR(0x0000014C)
+#define IOP331_IALR1      (volatile u32 *)IOP331_REG_ADDR(0x00000150)
+#define IOP331_IALR2      (volatile u32 *)IOP331_REG_ADDR(0x00000154)
+#define IOP331_IATVR2     (volatile u32 *)IOP331_REG_ADDR(0x00000158)
+#define IOP331_OIOWTVR    (volatile u32 *)IOP331_REG_ADDR(0x0000015C)
+#define IOP331_OMWTVR0    (volatile u32 *)IOP331_REG_ADDR(0x00000160)
+#define IOP331_OUMWTVR0   (volatile u32 *)IOP331_REG_ADDR(0x00000164)
+#define IOP331_OMWTVR1    (volatile u32 *)IOP331_REG_ADDR(0x00000168)
+#define IOP331_OUMWTVR1   (volatile u32 *)IOP331_REG_ADDR(0x0000016C)
+/* Reserved 0x00000170 through 0x00000177*/
+#define IOP331_OUDWTVR    (volatile u32 *)IOP331_REG_ADDR(0x00000178)
+/* Reserved 0x0000017C through 0x0000017F*/
+#define IOP331_ATUCR      (volatile u32 *)IOP331_REG_ADDR(0x00000180)
+#define IOP331_PCSR       (volatile u32 *)IOP331_REG_ADDR(0x00000184)
+#define IOP331_ATUISR     (volatile u32 *)IOP331_REG_ADDR(0x00000188)
+#define IOP331_ATUIMR     (volatile u32 *)IOP331_REG_ADDR(0x0000018C)
+#define IOP331_IABAR3     (volatile u32 *)IOP331_REG_ADDR(0x00000190)
+#define IOP331_IAUBAR3    (volatile u32 *)IOP331_REG_ADDR(0x00000194)
+#define IOP331_IALR3      (volatile u32 *)IOP331_REG_ADDR(0x00000198)
+#define IOP331_IATVR3     (volatile u32 *)IOP331_REG_ADDR(0x0000019C)
+/* Reserved 0x000001A0 through 0x000001A3*/
+#define IOP331_OCCAR      (volatile u32 *)IOP331_REG_ADDR(0x000001A4)
+/* Reserved 0x000001A8 through 0x000001AB*/
+#define IOP331_OCCDR      (volatile u32 *)IOP331_REG_ADDR(0x000001AC)
+/* Reserved 0x000001B0 through 0x000001BB*/
+#define IOP331_VPDCAPID   (volatile u8 *)IOP331_REG_ADDR(0x000001B8)
+#define IOP331_VPDNXTP    (volatile u8 *)IOP331_REG_ADDR(0x000001B9)
+#define IOP331_VPDAR     (volatile u16 *)IOP331_REG_ADDR(0x000001BA)
+#define IOP331_VPDDR      (volatile u32 *)IOP331_REG_ADDR(0x000001BC)
+#define IOP331_PMCAPID    (volatile u8 *)IOP331_REG_ADDR(0x000001C0)
+#define IOP331_PMNEXT     (volatile u8 *)IOP331_REG_ADDR(0x000001C1)
+#define IOP331_APMCR      (volatile u16 *)IOP331_REG_ADDR(0x000001C2)
+#define IOP331_APMCSR     (volatile u16 *)IOP331_REG_ADDR(0x000001C4)
+/* Reserved 0x000001C6 through 0x000001CF */
+#define IOP331_MSICAPID   (volatile u8 *)IOP331_REG_ADDR(0x000001D0)
+#define IOP331_MSINXTP   (volatile u8 *)IOP331_REG_ADDR(0x000001D1)
+#define IOP331_MSIMCR     (volatile u16 *)IOP331_REG_ADDR(0x000001D2)
+#define IOP331_MSIMAR     (volatile u32 *)IOP331_REG_ADDR(0x000001D4)
+#define IOP331_MSIMUAR   (volatile u32 *)IOP331_REG_ADDR(0x000001D8)
+#define IOP331_MSIMDR    (volatile u32 *)IOP331_REG_ADDR(0x000001DC)
+#define IOP331_PCIXCAPID  (volatile u8 *)IOP331_REG_ADDR(0x000001E0)
+#define IOP331_PCIXNEXT   (volatile u8 *)IOP331_REG_ADDR(0x000001E1)
+#define IOP331_PCIXCMD    (volatile u16 *)IOP331_REG_ADDR(0x000001E2)
+#define IOP331_PCIXSR     (volatile u32 *)IOP331_REG_ADDR(0x000001E4)
+#define IOP331_PCIIRSR    (volatile u32 *)IOP331_REG_ADDR(0x000001EC)
+
+/* Messaging Unit 0x00000300 through 0x000003FF */
+
+/* Reserved 0x00000300 through 0x0000030c */
+#define IOP331_IMR0       (volatile u32 *)IOP331_REG_ADDR(0x00000310)
+#define IOP331_IMR1       (volatile u32 *)IOP331_REG_ADDR(0x00000314)
+#define IOP331_OMR0       (volatile u32 *)IOP331_REG_ADDR(0x00000318)
+#define IOP331_OMR1       (volatile u32 *)IOP331_REG_ADDR(0x0000031C)
+#define IOP331_IDR        (volatile u32 *)IOP331_REG_ADDR(0x00000320)
+#define IOP331_IISR       (volatile u32 *)IOP331_REG_ADDR(0x00000324)
+#define IOP331_IIMR       (volatile u32 *)IOP331_REG_ADDR(0x00000328)
+#define IOP331_ODR        (volatile u32 *)IOP331_REG_ADDR(0x0000032C)
+#define IOP331_OISR       (volatile u32 *)IOP331_REG_ADDR(0x00000330)
+#define IOP331_OIMR       (volatile u32 *)IOP331_REG_ADDR(0x00000334)
+/* Reserved 0x00000338 through 0x0000034F */
+#define IOP331_MUCR       (volatile u32 *)IOP331_REG_ADDR(0x00000350)
+#define IOP331_QBAR       (volatile u32 *)IOP331_REG_ADDR(0x00000354)
+/* Reserved 0x00000358 through 0x0000035C */
+#define IOP331_IFHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000360)
+#define IOP331_IFTPR      (volatile u32 *)IOP331_REG_ADDR(0x00000364)
+#define IOP331_IPHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000368)
+#define IOP331_IPTPR      (volatile u32 *)IOP331_REG_ADDR(0x0000036C)
+#define IOP331_OFHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000370)
+#define IOP331_OFTPR      (volatile u32 *)IOP331_REG_ADDR(0x00000374)
+#define IOP331_OPHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000378)
+#define IOP331_OPTPR      (volatile u32 *)IOP331_REG_ADDR(0x0000037C)
+#define IOP331_IAR        (volatile u32 *)IOP331_REG_ADDR(0x00000380)
+/* Reserved 0x00000384 through 0x000003FF */
+
+/* DMA Controller 0x00000400 through 0x000004FF */
+#define IOP331_DMA0_CCR   (volatile u32 *)IOP331_REG_ADDR(0x00000400)
+#define IOP331_DMA0_CSR   (volatile u32 *)IOP331_REG_ADDR(0x00000404)
+#define IOP331_DMA0_DAR   (volatile u32 *)IOP331_REG_ADDR(0x0000040C)
+#define IOP331_DMA0_NDAR  (volatile u32 *)IOP331_REG_ADDR(0x00000410)
+#define IOP331_DMA0_PADR  (volatile u32 *)IOP331_REG_ADDR(0x00000414)
+#define IOP331_DMA0_PUADR (volatile u32 *)IOP331_REG_ADDR(0x00000418)
+#define IOP331_DMA0_LADR  (volatile u32 *)IOP331_REG_ADDR(0X0000041C)
+#define IOP331_DMA0_BCR   (volatile u32 *)IOP331_REG_ADDR(0x00000420)
+#define IOP331_DMA0_DCR   (volatile u32 *)IOP331_REG_ADDR(0x00000424)
+/* Reserved 0x00000428 through 0x0000043C */
+#define IOP331_DMA1_CCR   (volatile u32 *)IOP331_REG_ADDR(0x00000440)
+#define IOP331_DMA1_CSR   (volatile u32 *)IOP331_REG_ADDR(0x00000444)
+#define IOP331_DMA1_DAR   (volatile u32 *)IOP331_REG_ADDR(0x0000044C)
+#define IOP331_DMA1_NDAR  (volatile u32 *)IOP331_REG_ADDR(0x00000450)
+#define IOP331_DMA1_PADR  (volatile u32 *)IOP331_REG_ADDR(0x00000454)
+#define IOP331_DMA1_PUADR (volatile u32 *)IOP331_REG_ADDR(0x00000458)
+#define IOP331_DMA1_LADR  (volatile u32 *)IOP331_REG_ADDR(0x0000045C)
+#define IOP331_DMA1_BCR   (volatile u32 *)IOP331_REG_ADDR(0x00000460)
+#define IOP331_DMA1_DCR   (volatile u32 *)IOP331_REG_ADDR(0x00000464)
+/* Reserved 0x00000468 through 0x000004FF */
+
+/* Memory controller 0x00000500 through 0x0005FF */
+
+/* Peripheral bus interface unit 0x00000680 through 0x0006FF */
+#define IOP331_PBCR       (volatile u32 *)IOP331_REG_ADDR(0x00000680)
+#define IOP331_PBISR      (volatile u32 *)IOP331_REG_ADDR(0x00000684)
+#define IOP331_PBBAR0     (volatile u32 *)IOP331_REG_ADDR(0x00000688)
+#define IOP331_PBLR0      (volatile u32 *)IOP331_REG_ADDR(0x0000068C)
+#define IOP331_PBBAR1     (volatile u32 *)IOP331_REG_ADDR(0x00000690)
+#define IOP331_PBLR1      (volatile u32 *)IOP331_REG_ADDR(0x00000694)
+#define IOP331_PBBAR2     (volatile u32 *)IOP331_REG_ADDR(0x00000698)
+#define IOP331_PBLR2      (volatile u32 *)IOP331_REG_ADDR(0x0000069C)
+#define IOP331_PBBAR3     (volatile u32 *)IOP331_REG_ADDR(0x000006A0)
+#define IOP331_PBLR3      (volatile u32 *)IOP331_REG_ADDR(0x000006A4)
+#define IOP331_PBBAR4     (volatile u32 *)IOP331_REG_ADDR(0x000006A8)
+#define IOP331_PBLR4      (volatile u32 *)IOP331_REG_ADDR(0x000006AC)
+#define IOP331_PBBAR5     (volatile u32 *)IOP331_REG_ADDR(0x000006B0)
+#define IOP331_PBLR5      (volatile u32 *)IOP331_REG_ADDR(0x000006B4)
+#define IOP331_PBDSCR     (volatile u32 *)IOP331_REG_ADDR(0x000006B8)
+/* Reserved 0x000006BC */
+#define IOP331_PMBR0      (volatile u32 *)IOP331_REG_ADDR(0x000006C0)
+/* Reserved 0x000006C4 through 0x000006DC */
+#define IOP331_PMBR1      (volatile u32 *)IOP331_REG_ADDR(0x000006E0)
+#define IOP331_PMBR2      (volatile u32 *)IOP331_REG_ADDR(0x000006E4)
+
+#define IOP331_PBCR_EN    0x1
+
+#define IOP331_PBISR_BOOR_ERR 0x1
+
+
+
+/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
+/* Internal arbitration unit 0x00000780 through 0x0007BF */
+
+/* Interrupt Controller */
+#define IOP331_INTCTL0    (volatile u32 *)IOP331_REG_ADDR(0x00000790)
+#define IOP331_INTCTL1    (volatile u32 *)IOP331_REG_ADDR(0x00000794)
+#define IOP331_INTSTR0    (volatile u32 *)IOP331_REG_ADDR(0x00000798)
+#define IOP331_INTSTR1    (volatile u32 *)IOP331_REG_ADDR(0x0000079C)
+#define IOP331_IINTSRC0   (volatile u32 *)IOP331_REG_ADDR(0x000007A0)
+#define IOP331_IINTSRC1   (volatile u32 *)IOP331_REG_ADDR(0x000007A4)
+#define IOP331_FINTSRC0   (volatile u32 *)IOP331_REG_ADDR(0x000007A8)
+#define IOP331_FINTSRC1   (volatile u32 *)IOP331_REG_ADDR(0x000007AC)
+#define IOP331_IPR0       (volatile u32 *)IOP331_REG_ADDR(0x000007B0)
+#define IOP331_IPR1       (volatile u32 *)IOP331_REG_ADDR(0x000007B4)
+#define IOP331_IPR2       (volatile u32 *)IOP331_REG_ADDR(0x000007B8)
+#define IOP331_IPR3       (volatile u32 *)IOP331_REG_ADDR(0x000007BC)
+#define IOP331_INTBASE    (volatile u32 *)IOP331_REG_ADDR(0x000007C0)
+#define IOP331_INTSIZE    (volatile u32 *)IOP331_REG_ADDR(0x000007C4)
+#define IOP331_IINTVEC    (volatile u32 *)IOP331_REG_ADDR(0x000007C8)
+#define IOP331_FINTVEC    (volatile u32 *)IOP331_REG_ADDR(0x000007CC)
+
+
+/* Timers */
+
+#define IOP331_TU_TMR0         (volatile u32 *)IOP331_REG_ADDR(0x000007D0)
+#define IOP331_TU_TMR1         (volatile u32 *)IOP331_REG_ADDR(0x000007D4)
+
+#define IOP331_TMR_TC          0x01
+#define        IOP331_TMR_EN           0x02
+#define IOP331_TMR_RELOAD      0x04
+#define        IOP331_TMR_PRIVILEGED   0x09
+
+#define        IOP331_TMR_RATIO_1_1    0x00
+#define        IOP331_TMR_RATIO_4_1    0x10
+#define        IOP331_TMR_RATIO_8_1    0x20
+#define        IOP331_TMR_RATIO_16_1   0x30
+
+#define IOP331_TU_TCR0    (volatile u32 *)IOP331_REG_ADDR(0x000007D8)
+#define IOP331_TU_TCR1    (volatile u32 *)IOP331_REG_ADDR(0x000007DC)
+#define IOP331_TU_TRR0    (volatile u32 *)IOP331_REG_ADDR(0x000007E0)
+#define IOP331_TU_TRR1    (volatile u32 *)IOP331_REG_ADDR(0x000007E4)
+#define IOP331_TU_TISR    (volatile u32 *)IOP331_REG_ADDR(0x000007E8)
+#define IOP331_TU_WDTCR   (volatile u32 *)IOP331_REG_ADDR(0x000007EC)
+
+#define        IOP331_TICK_RATE        266000000       /* 266 MHz clock */
+
+
+/* Application accelerator unit 0x00000800 - 0x000008FF */
+#define IOP331_AAU_ACR     (volatile u32 *)IOP331_REG_ADDR(0x00000800)
+#define IOP331_AAU_ASR     (volatile u32 *)IOP331_REG_ADDR(0x00000804)
+#define IOP331_AAU_ADAR    (volatile u32 *)IOP331_REG_ADDR(0x00000808)
+#define IOP331_AAU_ANDAR   (volatile u32 *)IOP331_REG_ADDR(0x0000080C)
+#define IOP331_AAU_SAR1    (volatile u32 *)IOP331_REG_ADDR(0x00000810)
+#define IOP331_AAU_SAR2    (volatile u32 *)IOP331_REG_ADDR(0x00000814)
+#define IOP331_AAU_SAR3    (volatile u32 *)IOP331_REG_ADDR(0x00000818)
+#define IOP331_AAU_SAR4    (volatile u32 *)IOP331_REG_ADDR(0x0000081C)
+#define IOP331_AAU_SAR5    (volatile u32 *)IOP331_REG_ADDR(0x0000082C)
+#define IOP331_AAU_SAR6    (volatile u32 *)IOP331_REG_ADDR(0x00000830)
+#define IOP331_AAU_SAR7    (volatile u32 *)IOP331_REG_ADDR(0x00000834)
+#define IOP331_AAU_SAR8    (volatile u32 *)IOP331_REG_ADDR(0x00000838)
+#define IOP331_AAU_SAR9    (volatile u32 *)IOP331_REG_ADDR(0x00000840)
+#define IOP331_AAU_SAR10   (volatile u32 *)IOP331_REG_ADDR(0x00000844)
+#define IOP331_AAU_SAR11   (volatile u32 *)IOP331_REG_ADDR(0x00000848)
+#define IOP331_AAU_SAR12   (volatile u32 *)IOP331_REG_ADDR(0x0000084C)
+#define IOP331_AAU_SAR13   (volatile u32 *)IOP331_REG_ADDR(0x00000850)
+#define IOP331_AAU_SAR14   (volatile u32 *)IOP331_REG_ADDR(0x00000854)
+#define IOP331_AAU_SAR15   (volatile u32 *)IOP331_REG_ADDR(0x00000858)
+#define IOP331_AAU_SAR16   (volatile u32 *)IOP331_REG_ADDR(0x0000085C)
+#define IOP331_AAU_SAR17   (volatile u32 *)IOP331_REG_ADDR(0x00000864)
+#define IOP331_AAU_SAR18   (volatile u32 *)IOP331_REG_ADDR(0x00000868)
+#define IOP331_AAU_SAR19   (volatile u32 *)IOP331_REG_ADDR(0x0000086C)
+#define IOP331_AAU_SAR20   (volatile u32 *)IOP331_REG_ADDR(0x00000870)
+#define IOP331_AAU_SAR21   (volatile u32 *)IOP331_REG_ADDR(0x00000874)
+#define IOP331_AAU_SAR22   (volatile u32 *)IOP331_REG_ADDR(0x00000878)
+#define IOP331_AAU_SAR23   (volatile u32 *)IOP331_REG_ADDR(0x0000087C)
+#define IOP331_AAU_SAR24   (volatile u32 *)IOP331_REG_ADDR(0x00000880)
+#define IOP331_AAU_SAR25   (volatile u32 *)IOP331_REG_ADDR(0x00000888)
+#define IOP331_AAU_SAR26   (volatile u32 *)IOP331_REG_ADDR(0x0000088C)
+#define IOP331_AAU_SAR27   (volatile u32 *)IOP331_REG_ADDR(0x00000890)
+#define IOP331_AAU_SAR28   (volatile u32 *)IOP331_REG_ADDR(0x00000894)
+#define IOP331_AAU_SAR29   (volatile u32 *)IOP331_REG_ADDR(0x00000898)
+#define IOP331_AAU_SAR30   (volatile u32 *)IOP331_REG_ADDR(0x0000089C)
+#define IOP331_AAU_SAR31   (volatile u32 *)IOP331_REG_ADDR(0x000008A0)
+#define IOP331_AAU_SAR32   (volatile u32 *)IOP331_REG_ADDR(0x000008A4)
+#define IOP331_AAU_DAR     (volatile u32 *)IOP331_REG_ADDR(0x00000820)
+#define IOP331_AAU_ABCR    (volatile u32 *)IOP331_REG_ADDR(0x00000824)
+#define IOP331_AAU_ADCR    (volatile u32 *)IOP331_REG_ADDR(0x00000828)
+#define IOP331_AAU_EDCR0   (volatile u32 *)IOP331_REG_ADDR(0x0000083c)
+#define IOP331_AAU_EDCR1   (volatile u32 *)IOP331_REG_ADDR(0x00000860)
+#define IOP331_AAU_EDCR2   (volatile u32 *)IOP331_REG_ADDR(0x00000884)
+
+
+#define IOP331_SPDSCR    (volatile u32 *)IOP331_REG_ADDR(0x000015C0)
+#define IOP331_PPDSCR    (volatile u32 *)IOP331_REG_ADDR(0x000015C8)
+/* SSP serial port unit 0x00001600 - 0x0000167F */
+
+/* I2C bus interface unit 0x00001680 - 0x000016FF */
+/* for I2C bit defs see drivers/i2c/i2c-iop3xx.h */
+
+#define IOP331_ICR0       (volatile u32 *)IOP331_REG_ADDR(0x00001680)
+#define IOP331_ISR0       (volatile u32 *)IOP331_REG_ADDR(0x00001684)
+#define IOP331_ISAR0      (volatile u32 *)IOP331_REG_ADDR(0x00001688)
+#define IOP331_IDBR0      (volatile u32 *)IOP331_REG_ADDR(0x0000168C)
+/* Reserved 0x00001690 */
+#define IOP331_IBMR0      (volatile u32 *)IOP331_REG_ADDR(0x00001694)
+/* Reserved 0x00001698 */
+/* Reserved 0x0000169C */
+#define IOP331_ICR1       (volatile u32 *)IOP331_REG_ADDR(0x000016A0)
+#define IOP331_ISR1       (volatile u32 *)IOP331_REG_ADDR(0x000016A4)
+#define IOP331_ISAR1      (volatile u32 *)IOP331_REG_ADDR(0x000016A8)
+#define IOP331_IDBR1      (volatile u32 *)IOP331_REG_ADDR(0x000016AC)
+#define IOP331_IBMR1      (volatile u32 *)IOP331_REG_ADDR(0x000016B4)
+/* Reserved 0x000016B8 through 0x000016FF */
+
+/* 0x00001700 through 0x0000172C  UART 0 */
+
+/* Reserved 0x00001730 through 0x0000173F */
+
+/* 0x00001740 through 0x0000176C UART 1 */
+
+/* Reserved 0x00001770 through 0x0000177F */
+
+/* General Purpose I/O Registers */
+#define IOP331_GPOE       (volatile u32 *)IOP331_REG_ADDR(0x00001780)
+#define IOP331_GPID       (volatile u32 *)IOP331_REG_ADDR(0x00001784)
+#define IOP331_GPOD       (volatile u32 *)IOP331_REG_ADDR(0x00001788)
+
+/* Reserved 0x0000178c through 0x000019ff */
+
+#ifndef __ASSEMBLY__
+extern void iop331_map_io(void);
+extern void iop331_init_irq(void);
+extern void iop331_time_init(void);
+#endif
+
+#endif // _IOP331_HW_H_
diff --git a/include/asm-arm/arch-iop3xx/iq31244.h b/include/asm-arm/arch-iop3xx/iq31244.h
new file mode 100644 (file)
index 0000000..c62c216
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * linux/include/asm/arch-iop3xx/iq31244.h
+ *
+ * Intel IQ31244 evaluation board registers
+ */
+
+#ifndef _IQ31244_H_
+#define _IQ31244_H_
+
+#define IQ31244_RAMBASE                0xa0000000
+
+#define        IQ31244_FLASHBASE       0xf0000000      /* Flash */
+#define        IQ31244_FLASHSIZE       0x00800000
+#define        IQ31244_FLASHWIDTH      2
+
+#define IQ31244_UART           0xfe800000      /* UART #1 */
+#define IQ31244_7SEG_1         0xfe840000      /* 7-Segment MSB */
+#define IQ31244_7SEG_0         0xfe850000      /* 7-Segment LSB (WO) */
+#define IQ31244_ROTARY_SW      0xfe8d0000      /* Rotary Switch */
+#define IQ31244_BATT_STAT      0xfe8f0000      /* Battery Status */
+
+/*
+ * IQ31244 PCI I/O and Mem space regions
+ */
+#define IQ31244_PCI_IO_BASE    0x90000000
+#define IQ31244_PCI_IO_SIZE    0x00010000
+#define IQ31244_PCI_MEM_BASE   0x80000000
+//#define IQ31244_PCI_MEM_SIZE 0x04000000
+#define IQ31244_PCI_MEM_SIZE   0x08000000
+#define        IQ31244_PCI_IO_OFFSET   0x6e000000
+
+#ifndef __ASSEMBLY__
+extern void iq31244_map_io(void);
+#endif
+
+#endif // _IQ31244_H_
index 8a94ce8..e1c5430 100644 (file)
@@ -1,17 +1,35 @@
 /*
  * linux/include/asm/arch-iop3xx/iq80321.h
  *
- * Intel IQ-80321 evaluation board registers
+ * Intel IQ80321 evaluation board registers
  */
 
 #ifndef _IQ80321_H_
 #define _IQ80321_H_
 
-#define IQ80321_RAMBASE      0xa0000000
-#define IQ80321_UART1        0xfe800000    /* UART #1 */
-#define IQ80321_7SEG_1       0xfe840000    /* 7-Segment MSB */
-#define IQ80321_7SEG_0       0xfe850000    /* 7-Segment LSB (WO) */
-#define IQ80321_ROTARY_SW    0xfe8d0000    /* Rotary Switch */
-#define IQ80321_BATT_STAT    0xfe8f0000    /* Battery Status */
+#define IQ80321_RAMBASE                0xa0000000
+
+#define        IQ80321_FLASHBASE       0xf0000000      /* Flash */
+#define        IQ80321_FLASHSIZE       0x00800000
+#define        IQ80321_FLASHWIDTH      1
+
+#define IQ80321_UART           0xfe800000      /* UART #1 */
+#define IQ80321_7SEG_1         0xfe840000      /* 7-Segment MSB */
+#define IQ80321_7SEG_0         0xfe850000      /* 7-Segment LSB (WO) */
+#define IQ80321_ROTARY_SW      0xfe8d0000      /* Rotary Switch */
+#define IQ80321_BATT_STAT      0xfe8f0000      /* Battery Status */
+
+/*
+ * IQ80321 PCI I/O and Mem space regions
+ */
+#define IQ80321_PCI_IO_BASE    0x90000000
+#define IQ80321_PCI_IO_SIZE    0x00010000
+#define IQ80321_PCI_MEM_BASE   0x80000000
+#define IQ80321_PCI_MEM_SIZE   0x04000000
+#define        IQ80321_PCI_IO_OFFSET   0x6e000000
+
+#ifndef __ASSEMBLY__
+extern void iq80321_map_io(void);
+#endif
 
 #endif // _IQ80321_H_
diff --git a/include/asm-arm/arch-iop3xx/iq80331.h b/include/asm-arm/arch-iop3xx/iq80331.h
new file mode 100644 (file)
index 0000000..a076327
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * linux/include/asm/arch-iop3xx/iq80331.h
+ *
+ * Intel IQ80331 evaluation board registers
+ */
+
+#ifndef _IQ80331_H_
+#define _IQ80331_H_
+
+#define IQ80331_RAMBASE                0x00000000
+
+#define        IQ80331_FLASHBASE       0xc0000000      /* Flash */
+#define        IQ80331_FLASHSIZE       0x00800000
+#define        IQ80331_FLASHWIDTH      1
+
+#define IQ80331_UART0_PHYS  (IOP331_PHYS_MEM_BASE | 0x00001700)        /* UART #1 physical */
+#define IQ80331_UART1_PHYS  (IOP331_PHYS_MEM_BASE | 0x00001740)        /* UART #2 physical */
+#define IQ80331_UART0_VIRT  (IOP331_VIRT_MEM_BASE | 0x00001700) /* UART #1 virtual addr */
+#define IQ80331_UART1_VIRT  (IOP331_VIRT_MEM_BASE | 0x00001740) /* UART #2 virtual addr */
+#define IQ80331_7SEG_1         0xce840000      /* 7-Segment MSB */
+#define IQ80331_7SEG_0         0xce850000      /* 7-Segment LSB (WO) */
+#define IQ80331_ROTARY_SW      0xce8d0000      /* Rotary Switch */
+#define IQ80331_BATT_STAT      0xce8f0000      /* Battery Status */
+
+/*
+ * IQ80331 PCI I/O and Mem space regions
+ */
+#define IQ80331_PCI_IO_BASE    0x90000000
+#define IQ80331_PCI_IO_SIZE    0x00010000
+#define IQ80331_PCI_MEM_BASE   0x80000000
+#define IQ80331_PCI_MEM_SIZE   0x08000000
+#define        IQ80331_PCI_IO_OFFSET   0x6e000000
+
+#ifndef __ASSEMBLY__
+extern void iq80331_map_io(void);
+#endif
+
+#endif // _IQ80331_H_
index 1df3302..b2c03f4 100644 (file)
@@ -1,27 +1,21 @@
 /*
  * linux/include/asm-arm/arch-iop3xx/irqs.h
  *
- * Copyright:  (C) 2001 MontaVista Software Inc.
+ * Copyright:  (C) 2001-2003 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.
  *
- *
  */
 
-#include <linux/config.h>
-
 /*
- * Whic iop3xx implementation is this?
+ * Chipset-specific bits
  */
-#ifdef CONFIG_ARCH_IOP310
-
-#include "iop310-irqs.h"
-
-#else
-
+#ifdef CONFIG_ARCH_IOP321
 #include "iop321-irqs.h"
-
 #endif
 
+#ifdef CONFIG_ARCH_IOP331
+#include "iop331-irqs.h"
+#endif
index 56a1672..acf404e 100644 (file)
@@ -1,3 +1,3 @@
 /*
- *  linux/include/asm-arm/arch-iop80310/param.h
+ *  linux/include/asm-arm/arch-iop3xx/param.h
  */
index 8217c12..61192f9 100644 (file)
 /* Standard COM flags */
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 
-#ifdef CONFIG_ARCH_IQ80310
+#ifdef CONFIG_ARCH_IQ80321
+
+#define IRQ_UART1      IRQ_IQ80321_UART
 
-#define IRQ_UART1      IRQ_IQ80310_UART1
-#define IRQ_UART2      IRQ_IQ80310_UART2
+#define RS_TABLE_SIZE 1
 
 #define STD_SERIAL_PORT_DEFNS                  \
        /* UART CLK      PORT        IRQ        FLAGS        */                 \
-       { 0, BASE_BAUD, IQ80310_UART2, IRQ_UART2, STD_COM_FLAGS },  /* ttyS0 */ \
-       { 0, BASE_BAUD, IQ80310_UART1, IRQ_UART1, STD_COM_FLAGS }  /* ttyS1 */
+       { 0, BASE_BAUD, 0xfe800000, IRQ_UART1, STD_COM_FLAGS },  /* ttyS0 */
+#endif // CONFIG_ARCH_IQ80321
 
-#endif // CONFIG_ARCH_IQ80310
+#ifdef CONFIG_ARCH_IQ31244
 
-#ifdef CONFIG_ARCH_IQ80321
+#define IRQ_UART1      IRQ_IQ31244_UART
 
-#define IRQ_UART1      IRQ_IQ80321_UART
+#define RS_TABLE_SIZE 1
 
 #define STD_SERIAL_PORT_DEFNS                  \
        /* UART CLK      PORT        IRQ        FLAGS        */                 \
        { 0, BASE_BAUD, 0xfe800000, IRQ_UART1, STD_COM_FLAGS },  /* ttyS0 */
-#endif // CONFIG_ARCH_IQ80321
+#endif // CONFIG_ARCH_IQ31244
+
+#ifdef CONFIG_ARCH_IQ80331
+
+#undef BASE_BAUD
+
+#define BASE_BAUD ( 33334000 / 16 )
+
+#define IRQ_UART0      IRQ_IQ80331_UART0
+#define IRQ_UART1      IRQ_IQ80331_UART1
+
+#define RS_TABLE_SIZE 2
+
+#define STD_SERIAL_PORT_DEFNS                          \
+       {                                               \
+         /*type: PORT_XSCALE,*/                        \
+         /*xmit_fifo_size: 32,*/                       \
+         baud_base: BASE_BAUD,                         \
+         irq: IRQ_UART0,                               \
+         flags: STD_COM_FLAGS,                         \
+         iomem_base: IQ80331_UART0_VIRT,               \
+         io_type: SERIAL_IO_MEM,                       \
+         iomem_reg_shift: 2                            \
+       }, /* ttyS0 */                                  \
+       {                                               \
+         /*type: PORT_XSCALE,*/                        \
+         /*xmit_fifo_size: 32,*/                       \
+         baud_base: BASE_BAUD,                         \
+         irq: IRQ_UART1,                               \
+         flags: STD_COM_FLAGS,                         \
+         iomem_base: IQ80331_UART1_VIRT,               \
+         io_type: SERIAL_IO_MEM,                       \
+         iomem_reg_shift: 2                            \
+       } /* ttyS1 */
+#endif // CONFIG_ARCH_IQ80331
 
 
 #define EXTRA_SERIAL_PORT_DEFNS
index 54a101b..af6ae8c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-iop80310/system.h
+ * linux/include/asm-arm/arch-iop3xx/system.h
  *
  *  Copyright (C) 2001 MontaVista Software, Inc.
  *
@@ -16,6 +16,14 @@ static inline void arch_idle(void)
 
 static inline void arch_reset(char mode)
 {
+#ifdef CONFIG_ARCH_IOP321
+    *IOP321_PCSR = 0x30;
+#endif
+
+#ifdef CONFIG_ARCH_IOP331
+    *IOP331_PCSR = 0x30;
+#endif
+
        if ( 1 && mode == 's') {
                /* Jump into ROM at address 0 */
                cpu_reset(0);
index 2aec857..d9dbb44 100644 (file)
@@ -1,24 +1,18 @@
 /*
  * linux/include/asm-arm/arch-iop3xx/timex.h
  *
- * IOP310 architecture timex specifications
+ * IOP3xx architecture timex specifications
  */
 #include <linux/config.h>
 
 
-#ifdef CONFIG_ARCH_IQ80310
+#if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244)
 
-#ifndef CONFIG_XSCALE_PMU_TIMER
-/* This is for the on-board timer */
-#define CLOCK_TICK_RATE 33000000 /* Underlying HZ */
-#else
-/* This is for the underlying xs80200 PMU clock. We run the core @ 733MHz */
-#define CLOCK_TICK_RATE        733000000
-#endif // IQ80310
+#define CLOCK_TICK_RATE IOP321_TICK_RATE
 
-#elif defined(CONFIG_ARCH_IQ80321)
+#elif defined(CONFIG_ARCH_IQ80331)
 
-#define CLOCK_TICK_RATE 200000000
+#define CLOCK_TICK_RATE IOP331_TICK_RATE
 
 #else
 
index fd7e72b..673fabc 100644 (file)
@@ -1,26 +1,32 @@
 /*
- *  linux/include/asm-arm/arch-iop80310/uncompress.h
+ *  linux/include/asm-arm/arch-iop3xx/uncompress.h
  */
 #include <linux/config.h>
+#include <asm/types.h>
+#include <asm/mach-types.h>
 #include <linux/serial_reg.h>
 #include <asm/hardware.h>
 
-#ifdef CONFIG_ARCH_IQ80310
-#define UART2_BASE    ((volatile unsigned char *)IQ80310_UART2)
-#elif defined(CONFIG_ARCH_IQ80321)
-#define UART2_BASE    ((volatile unsigned char *)IQ80321_UART1)
+#ifdef CONFIG_ARCH_IOP321
+#define UTYPE unsigned char *
+#else
+#define UTYPE u32 *
 #endif
 
+static volatile UTYPE uart_base;
+
+#define TX_DONE (UART_LSR_TEMT|UART_LSR_THRE)
+
 static __inline__ void putc(char c)
 {
-       while ((UART2_BASE[5] & 0x60) != 0x60);
-       UART2_BASE[0] = c;
+       while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE);
+       *uart_base = c;
 }
 
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
        while (*s) {
                putc(*s);
@@ -30,8 +36,20 @@ static void puts(const char *s)
        }
 }
 
+static __inline__ void __arch_decomp_setup(unsigned long arch_id)
+{
+        if(machine_is_iq80321())
+                       uart_base = (volatile UTYPE)IQ80321_UART;
+               else if(machine_is_iq31244())
+                       uart_base = (volatile UTYPE)IQ31244_UART;
+               else if(machine_is_iq80331())
+                       uart_base = (volatile UTYPE)IQ80331_UART0_PHYS;
+               else
+                       uart_base = (volatile UTYPE)0xfe800000;
+}
+
 /*
  * nothing to do
  */
-#define arch_decomp_setup()
+#define arch_decomp_setup()    __arch_decomp_setup(arch_id)
 #define arch_decomp_wdog()
index e15797d..d59dfed 100644 (file)
@@ -12,4 +12,5 @@
  */
 #define VMALLOC_OFFSET   (8*1024*1024)
 #define VMALLOC_START    (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END       (0xe8000000)
diff --git a/include/asm-arm/arch-ixp2000/dma.h b/include/asm-arm/arch-ixp2000/dma.h
new file mode 100644 (file)
index 0000000..71520c8
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * linux/include/asm-arm/arch-ixdp2400/dma.h
+ *
+ * Copyright (C) 2002 Intel Corp.
+ *
+ * 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_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS                0xffffffff
+
+/* No DMA */
+#define MAX_DMA_CHANNELS       0
+
+#endif /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-ixp2000/enp2611.h b/include/asm-arm/arch-ixp2000/enp2611.h
new file mode 100644 (file)
index 0000000..31ae886
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * include/asm-arm/arch-ixp2000/enp2611.h
+ *
+ * Register and other defines for Radisys ENP-2611
+ *
+ * Created 2004 by Lennert Buytenhek from the ixdp2x01 code.  The
+ * original version carries the following notices:
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef __ENP2611_H
+#define __ENP2611_H
+
+#define ENP2611_GPIO_SCL       0x07
+#define ENP2611_GPIO_SDA       0x06
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp2000/gpio.h b/include/asm-arm/arch-ixp2000/gpio.h
new file mode 100644 (file)
index 0000000..84634af
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * include/asm-arm/arch-ixp2000/ixp2000-gpio.h
+ *
+ * Copyright (C) 2002 Intel 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.
+ */
+
+/*
+ * IXP2000 GPIO in/out, edge/level detection for IRQs:
+ * IRQs are generated on Falling-edge, Rising-Edge, Level-low, Level-High
+ * or both Falling-edge and Rising-edge.  
+ * This must be called *before* the corresponding IRQ is registerd.
+ * Use this instead of directly setting the GPIO registers.
+ * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb)
+ */
+#ifndef _ASM_ARCH_IXP2000_GPIO_H_
+#define _ASM_ARCH_IXP2000_GPIO_H_
+
+#ifndef __ASSEMBLY__
+#define GPIO_OUT                       0x0
+#define GPIO_IN                                0x80
+
+#define IXP2000_GPIO_LOW               0
+#define IXP2000_GPIO_HIGH              1
+
+#define GPIO_NO_EDGES                  0
+#define GPIO_FALLING_EDGE              1
+#define GPIO_RISING_EDGE               2
+#define GPIO_BOTH_EDGES                3
+#define GPIO_LEVEL_LOW                 4
+#define GPIO_LEVEL_HIGH                8
+
+extern void set_GPIO_IRQ_edge(int gpio_nr, int edge);
+extern void set_GPIO_IRQ_level(int gpio_nr, int level);
+extern void gpio_line_config(int line, int style);
+
+static inline int gpio_line_get(int line)
+{
+       return (((*IXP2000_GPIO_PLR) >> line) & 1);
+}
+
+static inline void gpio_line_set(int line, int value)
+{
+       if (value == IXP2000_GPIO_HIGH) {
+               ixp_reg_write(IXP2000_GPIO_POSR, BIT(line));
+       } else if (value == IXP2000_GPIO_LOW)
+               ixp_reg_write(IXP2000_GPIO_POCR, BIT(line));
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
+
diff --git a/include/asm-arm/arch-ixp2000/hardware.h b/include/asm-arm/arch-ixp2000/hardware.h
new file mode 100644 (file)
index 0000000..e7ea781
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/hardware.h
+ *
+ * Hardware definitions for IXP2400/2800 based systems
+ *
+ * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
+ *
+ * Maintainer: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright (C) 2001-2002 Intel Corp.
+ * Copyright (C) 2003-2004 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H__
+#define __ASM_ARCH_HARDWARE_H__
+
+/*
+ * This needs to be platform-specific?
+ */
+#define PCIBIOS_MIN_IO          0x00000000
+#define PCIBIOS_MIN_MEM         0x00000000
+
+#include "ixp2000-regs.h"      /* Chipset Registers */
+
+#define pcibios_assign_all_busses() 0
+
+/*
+ * Platform helper functions
+ */
+#include "platform.h"
+
+/*
+ * Platform-specific bits
+ */
+#include "enp2611.h"           /* ENP-2611 */
+#include "ixdp2x00.h"          /* IXDP2400/2800 */
+#include "ixdp2x01.h"          /* IXDP2401/2801 */
+
+#endif  /* _ASM_ARCH_HARDWARE_H__ */
diff --git a/include/asm-arm/arch-ixp2000/io.h b/include/asm-arm/arch-ixp2000/io.h
new file mode 100644 (file)
index 0000000..7463a32
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * linux/include/asm-arm/arch-ixdp2000/io.h
+ *
+ * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002  Intel Corp.
+ * Copyrgiht (C) 2003-2004 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_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT         0xffffffff
+#define __mem_pci(a)           ((unsigned long)(a))
+
+/*
+ * Pick up VMALLOC_END
+ */
+#define ___io(p)               ((unsigned long)((p)+IXP2000_PCI_IO_VIRT_BASE))
+
+/*
+ * IXP200 does not do proper byte-lane conversion for PCI addresses,
+ * so we need to override standard functions.
+ */
+#define alignb(addr)           ((addr & ~3) + (3 - (addr & 3)))
+#define alignw(addr)           ((addr & ~2) + (2 - (addr & 2)))
+
+#define outb(v,p)              __raw_writeb(v,alignb(___io(p)))
+#define outw(v,p)              __raw_writew((v),alignw(___io(p)))
+#define outl(v,p)              __raw_writel((v),___io(p))
+
+#define inb(p)         ({ unsigned int __v = __raw_readb(alignb(___io(p))); __v; })
+#define inw(p)         \
+       ({ unsigned int __v = (__raw_readw(alignw(___io(p)))); __v; })
+#define inl(p)         \
+       ({ unsigned int __v = (__raw_readl(___io(p))); __v; })
+
+#define outsb(p,d,l)           __raw_writesb(alignb(___io(p)),d,l)
+#define outsw(p,d,l)           __raw_writesw(alignw(___io(p)),d,l)
+#define outsl(p,d,l)           __raw_writesl(___io(p),d,l)
+
+#define insb(p,d,l)            __raw_readsb(alignb(___io(p)),d,l)
+#define insw(p,d,l)            __raw_readsw(alignw(___io(p)),d,l)
+#define insl(p,d,l)            __raw_readsl(___io(p),d,l)
+
+
+#ifdef CONFIG_ARCH_IXDP2X01
+/*
+ * This is an ugly hack but the CS8900 on the 2x01's does not sit in any sort
+ * of "I/O space" and is just direct mapped into a 32-bit-only addressable
+ * bus. The address space for this bus is such that we can't really easilly
+ * make it contigous to the PCI I/O address range, and it also does not
+ * need swapping like PCI addresses do (IXDP2x01 is a BE platform).
+ * B/C of this we can't use the standard in/out functions and need to
+ * runtime check if the incoming address is a PCI address or for
+ * the CS89x0.
+ */
+#undef inw
+#undef outw
+#undef insw
+#undef outsw
+
+#include <asm/mach-types.h>
+
+static inline void insw(u32 ptr, void *buf, int length)
+{
+       register volatile u32 *port = (volatile u32 *)ptr;
+
+       /*
+        * Is this cycle meant for the CS8900?
+        */
+       if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
+               ((port >= IXDP2X01_CS8900_VIRT_BASE) && 
+                (port <= IXDP2X01_CS8900_VIRT_END))) {
+               u8 *buf8 = (u8*)buf;
+               register u32 tmp32;
+
+               do {
+                       tmp32 = *port;
+                       *buf8++ = (u8)tmp32;
+                       *buf8++ = (u8)(tmp32 >> 8);
+               } while(--length);
+
+               return;
+       }
+
+       __raw_readsw(alignw(___io(ptr)),buf,length);
+}
+
+static inline void outsw(u32 ptr, void *buf, int length)
+{
+       register volatile u32 *port = (volatile u32 *)ptr;
+
+       /*
+        * Is this cycle meant for the CS8900?
+        */
+       if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
+               ((port >= IXDP2X01_CS8900_VIRT_BASE) && 
+                (port <= IXDP2X01_CS8900_VIRT_END))) {
+               register u32 tmp32;
+               u8 *buf8 = (u8*)buf;
+               do {
+                       tmp32 = *buf8++;
+                       tmp32 |= (*buf8++) << 8;
+                       *port = tmp32;
+               } while(--length);
+               return;
+       }
+
+       __raw_writesw(alignw(___io(ptr)),buf,length);
+}
+
+
+static inline u16 inw(u32 ptr)
+{
+       register volatile u32 *port = (volatile u32 *)ptr;
+
+       /*
+        * Is this cycle meant for the CS8900?
+        */
+       if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
+               ((port >= IXDP2X01_CS8900_VIRT_BASE) && 
+                (port <= IXDP2X01_CS8900_VIRT_END))) {
+               return (u16)(*port);  
+       }
+
+       return __raw_readw(alignw(___io(ptr)));
+}
+
+static inline void outw(u16 value, u32 ptr)
+{
+       register volatile u32 *port = (volatile u32 *)ptr;
+
+       if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
+               ((port >= IXDP2X01_CS8900_VIRT_BASE) && 
+                (port <= IXDP2X01_CS8900_VIRT_END))) {
+               *port = value;  
+               return;
+       }
+
+       __raw_writew((value),alignw(___io(ptr)));
+}
+#endif /* IXDP2x01 */
+
+#endif
diff --git a/include/asm-arm/arch-ixp2000/irq.h b/include/asm-arm/arch-ixp2000/irq.h
new file mode 100644 (file)
index 0000000..ba00b23
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ *  linux/include/asm-arm/arch-ixp2000/irq.h
+ *
+ *  Copyright (C) 2002 Intel Corp.
+ *
+ * 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 fixup_irq(irq)  (irq)
+
+
diff --git a/include/asm-arm/arch-ixp2000/irqs.h b/include/asm-arm/arch-ixp2000/irqs.h
new file mode 100644 (file)
index 0000000..a6b104f
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/irqs.h
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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 _IRQS_H
+#define _IRQS_H
+
+/*
+ * Do NOT add #ifdef MACHINE_FOO in here.
+ * Simpy add your machine IRQs here and increase NR_IRQS if needed to
+ * hold your machine's IRQ table.
+ */
+
+/*
+ * Some interrupt numbers go unused b/c the IRQ mask/ummask/status
+ * register has those bit reserved. We just mark those interrupts
+ * as invalid and this allows us to do mask/unmask with a single
+ * shift operation instead of having to map the IRQ number to
+ * a HW IRQ number.
+ */
+#define        IRQ_IXP2000_SWI                 0 /* soft interrupt */
+#define        IRQ_IXP2000_ERRSUM              1 /* OR of all bits in ErrorStatus reg*/
+#define        IRQ_IXP2000_UART                2
+#define        IRQ_IXP2000_GPIO                3
+#define        IRQ_IXP2000_TIMER1              4
+#define        IRQ_IXP2000_TIMER2              5
+#define        IRQ_IXP2000_TIMER3              6
+#define        IRQ_IXP2000_TIMER4              7
+#define        IRQ_IXP2000_PMU                 8               
+#define        IRQ_IXP2000_SPF                 9  /* Slow port framer IRQ */
+#define        IRQ_IXP2000_DMA1                10
+#define        IRQ_IXP2000_DMA2                11
+#define        IRQ_IXP2000_DMA3                12
+#define        IRQ_IXP2000_PCI_DOORBELL        13
+#define        IRQ_IXP2000_ME_ATTN             14 
+#define        IRQ_IXP2000_PCI                 15 /* PCI INTA or INTB */
+#define        IRQ_IXP2000_THDA0               16 /* thread 0-31A */
+#define        IRQ_IXP2000_THDA1               17 /* thread 32-63A */
+#define        IRQ_IXP2000_THDA2               18 /* thread 64-95A */
+#define        IRQ_IXP2000_THDA3               19 /* thread 96-127A */
+#define        IRQ_IXP2000_THDB0               24 /* thread 0-31 B */
+#define        IRQ_IXP2000_THDB1               25 /* thread 32-63B */
+/* only 64 threads supported for IXP2400, rest or for IXP2800*/
+#define        IRQ_IXP2000_THDB2               26 /* thread 64-95B */
+#define        IRQ_IXP2000_THDB3               27 /* thread 96-127B */
+
+/* define generic GPIOs */
+#define IRQ_IXP2000_GPIO0              32
+#define IRQ_IXP2000_GPIO1              33
+#define IRQ_IXP2000_GPIO2              34
+#define IRQ_IXP2000_GPIO3              35
+#define IRQ_IXP2000_GPIO4              36
+#define IRQ_IXP2000_GPIO5              37
+#define IRQ_IXP2000_GPIO6              38
+#define IRQ_IXP2000_GPIO7              39
+
+/* split off the 2 PCI sources */
+#define IRQ_IXP2000_PCIA               40
+#define IRQ_IXP2000_PCIB               41
+
+/* Int sources from IRQ_ERROR_STATUS */
+#define IRQ_IXP2000_DRAM0_MIN_ERR      42
+#define IRQ_IXP2000_DRAM0_MAJ_ERR      43
+#define IRQ_IXP2000_DRAM1_MIN_ERR      44
+#define IRQ_IXP2000_DRAM1_MAJ_ERR      45
+#define IRQ_IXP2000_DRAM2_MIN_ERR      46
+#define IRQ_IXP2000_DRAM2_MAJ_ERR      47
+#define IRQ_IXP2000_SRAM0_ERR          48
+#define IRQ_IXP2000_SRAM1_ERR          49
+#define IRQ_IXP2000_SRAM2_ERR           50
+#define IRQ_IXP2000_SRAM3_ERR          51
+#define IRQ_IXP2000_MEDIA_ERR          52
+#define IRQ_IXP2000_PCI_ERR            53
+#define IRQ_IXP2000_SP_INT             54
+
+#define NR_IXP2000_IRQS                 55
+
+#define        IXP2000_BOARD_IRQ(x)            (NR_IXP2000_IRQS + (x))
+
+#define        IXP2000_BOARD_IRQ_MASK(irq)     (1 << (irq - NR_IXP2000_IRQS))  
+
+/*
+ * This allows for all the on-chip sources plus up to 32 CPLD based
+ * IRQs. Should be more than enough.
+ */
+#define        IXP2000_BOARD_IRQS              32
+#define NR_IRQS                                (NR_IXP2000_IRQS + IXP2000_BOARD_IRQS)
+
+
+/* 
+ * IXDP2400 specific IRQs
+ */
+#define        IRQ_IXDP2400_INGRESS_NPU        IXP2000_BOARD_IRQ(0) 
+#define        IRQ_IXDP2400_ENET               IXP2000_BOARD_IRQ(1) 
+#define        IRQ_IXDP2400_MEDIA_PCI          IXP2000_BOARD_IRQ(2) 
+#define        IRQ_IXDP2400_MEDIA_SP           IXP2000_BOARD_IRQ(3) 
+#define        IRQ_IXDP2400_SF_PCI             IXP2000_BOARD_IRQ(4) 
+#define        IRQ_IXDP2400_SF_SP              IXP2000_BOARD_IRQ(5) 
+#define        IRQ_IXDP2400_PMC                IXP2000_BOARD_IRQ(6) 
+#define        IRQ_IXDP2400_TVM                IXP2000_BOARD_IRQ(7) 
+
+#define        NR_IXDP2400_IRQS                ((IRQ_IXDP2400_TVM)+1)  
+#define        IXDP2400_NR_IRQS                NR_IXDP2400_IRQS - NR_IXP2000_IRQS
+
+/* IXDP2800 specific IRQs */
+#define IRQ_IXDP2800_EGRESS_ENET       IXP2000_BOARD_IRQ(0)
+#define IRQ_IXDP2800_INGRESS_NPU       IXP2000_BOARD_IRQ(1)
+#define IRQ_IXDP2800_PMC               IXP2000_BOARD_IRQ(2)
+#define IRQ_IXDP2800_FABRIC_PCI                IXP2000_BOARD_IRQ(3)
+#define IRQ_IXDP2800_FABRIC            IXP2000_BOARD_IRQ(4)
+#define IRQ_IXDP2800_MEDIA             IXP2000_BOARD_IRQ(5)
+
+#define        NR_IXDP2800_IRQS                ((IRQ_IXDP2800_MEDIA)+1)
+#define        IXDP2800_NR_IRQS                NR_IXDP2800_IRQS - NR_IXP2000_IRQS
+
+/* 
+ * IRQs on both IXDP2x01 boards
+ */
+#define IRQ_IXDP2X01_SPCI_DB_0         IXP2000_BOARD_IRQ(2)
+#define IRQ_IXDP2X01_SPCI_DB_1         IXP2000_BOARD_IRQ(3)
+#define IRQ_IXDP2X01_SPCI_PMC_INTA     IXP2000_BOARD_IRQ(4)
+#define IRQ_IXDP2X01_SPCI_PMC_INTB     IXP2000_BOARD_IRQ(5)
+#define IRQ_IXDP2X01_SPCI_PMC_INTC     IXP2000_BOARD_IRQ(6)
+#define IRQ_IXDP2X01_SPCI_PMC_INTD     IXP2000_BOARD_IRQ(7)
+#define IRQ_IXDP2X01_SPCI_FIC_INT      IXP2000_BOARD_IRQ(8)
+#define IRQ_IXDP2X01_IPMI_FROM         IXP2000_BOARD_IRQ(16)
+#define IRQ_IXDP2X01_125US             IXP2000_BOARD_IRQ(17)
+#define IRQ_IXDP2X01_DB_0_ADD          IXP2000_BOARD_IRQ(18)
+#define IRQ_IXDP2X01_DB_1_ADD          IXP2000_BOARD_IRQ(19)
+#define IRQ_IXDP2X01_UART1             IXP2000_BOARD_IRQ(21)
+#define IRQ_IXDP2X01_UART2             IXP2000_BOARD_IRQ(22)
+#define IRQ_IXDP2X01_FIC_ADD_INT       IXP2000_BOARD_IRQ(24)
+#define IRQ_IXDP2X01_CS8900            IXP2000_BOARD_IRQ(25)
+#define IRQ_IXDP2X01_BBSRAM            IXP2000_BOARD_IRQ(26)
+
+#define IXDP2X01_VALID_IRQ_MASK ( \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_DB_0) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_DB_1) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTA) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTB) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTC) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTD) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_FIC_INT) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_IPMI_FROM) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_125US) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_DB_0_ADD) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_DB_1_ADD) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_UART1) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_UART2) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_FIC_ADD_INT) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_CS8900) | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_BBSRAM) )
+
+/* 
+ * IXDP2401 specific IRQs
+ */
+#define IRQ_IXDP2401_INTA_82546                IXP2000_BOARD_IRQ(0)
+#define IRQ_IXDP2401_INTB_82546                IXP2000_BOARD_IRQ(1)
+
+#define        IXDP2401_VALID_IRQ_MASK ( \
+               IXDP2X01_VALID_IRQ_MASK | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2401_INTA_82546) |\
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2401_INTB_82546))
+
+/*
+ * IXDP2801-specific IRQs
+ */
+#define IRQ_IXDP2801_RIV               IXP2000_BOARD_IRQ(0)
+#define IRQ_IXDP2801_CNFG_MEDIA                IXP2000_BOARD_IRQ(27)
+#define IRQ_IXDP2801_CLOCK_REF         IXP2000_BOARD_IRQ(28)
+
+#define        IXDP2801_VALID_IRQ_MASK ( \
+               IXDP2X01_VALID_IRQ_MASK | \
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2801_RIV) |\
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2801_CNFG_MEDIA) |\
+               IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2801_CLOCK_REF))
+
+#define        NR_IXDP2X01_IRQS                ((IRQ_IXDP2801_CLOCK_REF) + 1)
+
+#endif /*_IRQS_H*/
diff --git a/include/asm-arm/arch-ixp2000/ixdp2x00.h b/include/asm-arm/arch-ixp2000/ixdp2x00.h
new file mode 100644 (file)
index 0000000..e017826
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * include/asm-arm/arch-ixp2000/ixdp2x00.h
+ *
+ * Register and other defines for IXDP2[48]00 platforms
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#ifndef _IXDP2X00_H_
+#define _IXDP2X00_H_
+
+/*
+ * On board CPLD memory map
+ */
+#define IXDP2X00_PHYS_CPLD_BASE                0xc7000000
+#define IXDP2X00_VIRT_CPLD_BASE                0xfefdd000
+#define IXDP2X00_CPLD_SIZE             0x00001000
+
+
+#define IXDP2X00_CPLD_REG(x)   \
+       (volatile unsigned long *)(IXDP2X00_VIRT_CPLD_BASE | x)
+
+/*
+ * IXDP2400 CPLD registers
+ */
+#define IXDP2400_CPLD_SYSLED           IXDP2X00_CPLD_REG(0x0)  
+#define IXDP2400_CPLD_DISP_DATA                IXDP2X00_CPLD_REG(0x4)
+#define IXDP2400_CPLD_CLOCK_SPEED      IXDP2X00_CPLD_REG(0x8)
+#define IXDP2400_CPLD_INT_STAT         IXDP2X00_CPLD_REG(0xc)
+#define IXDP2400_CPLD_REV              IXDP2X00_CPLD_REG(0x10)
+#define IXDP2400_CPLD_SYS_CLK_M                IXDP2X00_CPLD_REG(0x14)
+#define IXDP2400_CPLD_SYS_CLK_N                IXDP2X00_CPLD_REG(0x18)
+#define IXDP2400_CPLD_INT_MASK         IXDP2X00_CPLD_REG(0x48)
+
+/*
+ * IXDP2800 CPLD registers
+ */
+#define IXDP2800_CPLD_INT_STAT         IXDP2X00_CPLD_REG(0x0)
+#define IXDP2800_CPLD_INT_MASK         IXDP2X00_CPLD_REG(0x140)
+
+
+#define        IXDP2X00_GPIO_I2C_ENABLE        0x02
+#define        IXDP2X00_GPIO_SCL               0x07
+#define        IXDP2X00_GPIO_SDA               0x06
+
+/*
+ * PCI devfns for on-board devices. We need these to be able to
+ * properly translte IRQs and for device removal.
+ */
+#define        IXDP2400_SLAVE_ENET_DEVFN       0x18    /* Bus 1 */
+#define        IXDP2400_MASTER_ENET_DEVFN      0x20    /* Bus 1 */
+#define        IXDP2400_MEDIA_DEVFN            0x28    /* Bus 1 */
+#define        IXDP2400_SWITCH_FABRIC_DEVFN    0x30    /* Bus 1 */
+
+#define        IXDP2800_SLAVE_ENET_DEVFN       0x20    /* Bus 1 */
+#define        IXDP2800_MASTER_ENET_DEVFN      0x18    /* Bus 1 */
+#define        IXDP2800_SWITCH_FABRIC_DEVFN    0x30    /* Bus 1 */
+
+#define        IXDP2X00_P2P_DEVFN              0x20    /* Bus 0 */
+#define        IXDP2X00_21555_DEVFN            0x30    /* Bus 0 */
+#define IXDP2X00_SLAVE_NPU_DEVFN       0x28    /* Bus 1 */
+#define        IXDP2X00_PMC_DEVFN              0x38    /* Bus 1 */
+#define IXDP2X00_MASTER_NPU_DEVFN      0x38    /* Bus 1 */
+
+#ifndef __ASSEMBLY__
+/*
+ * Master NPU will always have flash and be PCI master.
+ * Slave NPU may or may not have flash but will never be PCI master.
+ */
+static inline unsigned int ixdp2x00_master_npu(void)
+{
+       return ((ixp2000_has_flash()) && (ixp2000_is_pcimaster()));
+}
+
+/*
+ * Helper functions used by ixdp2400 and ixdp2800 specific code
+ */
+void ixdp2x00_init_irq(volatile unsigned long*, volatile unsigned long *, unsigned long);
+void ixdp2x00_slave_pci_postinit(void);
+void ixdp2x00_init_machine(void);
+void ixdp2x00_map_io(void);
+
+#endif
+
+#endif /*_IXDP2X00_H_ */
diff --git a/include/asm-arm/arch-ixp2000/ixdp2x01.h b/include/asm-arm/arch-ixp2000/ixdp2x01.h
new file mode 100644 (file)
index 0000000..626ed6b
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * include/asm/arch/ixdp2x01.h
+ *
+ * Platform definitions for IXDP2X01 && IXDP2801 systems
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (c) MontaVista Software, Inc. 
+ *
+ * Based on original code Copyright (c) 2002-2003 Intel Corporation
+ * 
+ * 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 __IXDP2X01_H__
+#define __IXDP2X01_H__
+
+#define        IXDP2X01_PHYS_CPLD_BASE         0xc6024000
+#define        IXDP2X01_VIRT_CPLD_BASE         0xfefdd000
+#define        IXDP2X01_CPLD_REGION_SIZE       0x1000
+
+#define IXDP2X01_CPLD_VIRT_REG(reg) (volatile u32*)(IXDP2X01_VIRT_CPLD_BASE | reg)
+#define IXDP2X01_CPLD_PHYS_REG(reg) (volatile u32*)(IXDP2X01_PHYS_CPLD_BASE | reg)
+
+#define IXDP2X01_UART1_VIRT_BASE       IXDP2X01_CPLD_VIRT_REG(0x40)
+#define IXDP2X01_UART1_PHYS_BASE       IXDP2X01_CPLD_PHYS_REG(0x40)
+
+#define IXDP2X01_UART2_VIRT_BASE       IXDP2X01_CPLD_VIRT_REG(0x60)
+#define IXDP2X01_UART2_PHYS_BASE       IXDP2X01_CPLD_PHYS_REG(0x60)
+
+#define IXDP2X01_CS8900_VIRT_BASE      IXDP2X01_CPLD_VIRT_REG(0x80)
+#define IXDP2X01_CS8900_VIRT_END       (IXDP2X01_CS8900_VIRT_BASE + 16)
+
+#define IXDP2X01_CPLD_RESET_REG         IXDP2X01_CPLD_VIRT_REG(0x00)
+#define IXDP2X01_INT_MASK_SET_REG      IXDP2X01_CPLD_VIRT_REG(0x08)
+#define IXDP2X01_INT_STAT_REG          IXDP2X01_CPLD_VIRT_REG(0x0C)
+#define IXDP2X01_INT_RAW_REG           IXDP2X01_CPLD_VIRT_REG(0x10) 
+#define IXDP2X01_INT_MASK_CLR_REG      IXDP2X01_INT_RAW_REG
+#define IXDP2X01_INT_SIM_REG           IXDP2X01_CPLD_VIRT_REG(0x14)
+
+#define IXDP2X01_CPLD_FLASH_REG                IXDP2X01_CPLD_VIRT_REG(0x20)
+
+#define IXDP2X01_CPLD_FLASH_INTERN     0x8000
+#define IXDP2X01_CPLD_FLASH_BANK_MASK  0xF
+#define IXDP2X01_FLASH_WINDOW_BITS     25
+#define IXDP2X01_FLASH_WINDOW_SIZE     (1 << IXDP2X01_FLASH_WINDOW_BITS)
+#define IXDP2X01_FLASH_WINDOW_MASK     (IXDP2X01_FLASH_WINDOW_SIZE - 1)
+
+#define        IXDP2X01_UART_CLK               1843200
+
+#endif /* __IXDP2x01_H__ */
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
new file mode 100644 (file)
index 0000000..9c8b21d
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ * include/asm-arm/arch-ixp2000/ixp2000-regs.h
+ *
+ * Chipset register definitions for IXP2400/2800 based systems.
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#ifndef _IXP2000_REGS_H_
+#define _IXP2000_REGS_H_
+
+/* 
+ * Static I/O regions. The manual defines each region as being several
+ * MB in size, but all the registers are within the first 4K, so there's
+ * no purpose in mapping the whole region in.
+ */
+#define        IXP2000_SLOWPORT_CSR_PHYS_BASE  0xc0080000
+#define        IXP2000_SLOWPORT_CSR_VIRT_BASE  0xfefff000
+#define        IXP2000_SLOWPORT_CSR_SIZE       0x1000
+
+#define        IXP2000_GLOBAL_REG_PHYS_BASE    0xc0004000
+#define        IXP2000_GLOBAL_REG_VIRT_BASE    0xfeffe000
+#define        IXP2000_GLOBAL_REG_SIZE         0x1000
+
+#define        IXP2000_UART_PHYS_BASE          0xc0030000
+#define        IXP2000_UART_VIRT_BASE          0xfef30000
+#define IXP2000_UART_SIZE              0x1000
+
+#define        IXP2000_TIMER_PHYS_BASE         0xc0020000
+#define        IXP2000_TIMER_VIRT_BASE         0xfeffc000
+#define        IXP2000_TIMER_SIZE              0x1000
+
+#define        IXP2000_GPIO_PHYS_BASE          0xc0010000
+#define        IXP2000_GPIO_VIRT_BASE          0xfeffb000
+#define        IXP2000_GPIO_SIZE               0x1000
+
+#define IXP2000_INTCTL_PHYS_BASE       0xd6000000
+#define        IXP2000_INTCTL_VIRT_BASE        0xfeffa000
+#define        IXP2000_INTCTL_SIZE             0x01000
+
+#define IXP2000_PCI_CREG_PHYS_BASE     0xde000000
+#define        IXP2000_PCI_CREG_VIRT_BASE      0xfeff0000
+#define        IXP2000_PCI_CREG_SIZE           0x1000
+
+#define IXP2000_PCI_CSR_PHYS_BASE      0xdf000000
+#define        IXP2000_PCI_CSR_VIRT_BASE       0xfefde000
+#define        IXP2000_PCI_CSR_SIZE            0x1000
+
+#define IXP2000_PCI_IO_PHYS_BASE       0xd8000000
+#define        IXP2000_PCI_IO_VIRT_BASE        0xfd000000
+#define IXP2000_PCI_IO_SIZE            0x01000000
+
+#define IXP2000_PCI_CFG0_PHYS_BASE     0xda000000
+#define IXP2000_PCI_CFG0_VIRT_BASE     0xfc000000
+#define IXP2000_PCI_CFG0_SIZE          0x01000000
+
+#define IXP2000_PCI_CFG1_PHYS_BASE     0xdb000000
+#define IXP2000_PCI_CFG1_VIRT_BASE     0xfb000000
+#define IXP2000_PCI_CFG1_SIZE          0x01000000
+
+
+/* 
+ * Timers
+ */
+#define        IXP2000_TIMER_REG(x)            ((volatile unsigned long*)(IXP2000_TIMER_VIRT_BASE | (x)))
+/* Timer control */
+#define        IXP2000_T1_CTL                  IXP2000_TIMER_REG(0x00)
+#define        IXP2000_T2_CTL                  IXP2000_TIMER_REG(0x04)
+#define        IXP2000_T3_CTL                  IXP2000_TIMER_REG(0x08)
+#define        IXP2000_T4_CTL                  IXP2000_TIMER_REG(0x0c)
+/* Store initial value */
+#define        IXP2000_T1_CLD                  IXP2000_TIMER_REG(0x10)
+#define        IXP2000_T2_CLD                  IXP2000_TIMER_REG(0x14)
+#define        IXP2000_T3_CLD                  IXP2000_TIMER_REG(0x18)
+#define        IXP2000_T4_CLD                  IXP2000_TIMER_REG(0x1c)
+/* Read current value */
+#define        IXP2000_T1_CSR                  IXP2000_TIMER_REG(0x20)
+#define        IXP2000_T2_CSR                  IXP2000_TIMER_REG(0x24)
+#define        IXP2000_T3_CSR                  IXP2000_TIMER_REG(0x28)
+#define        IXP2000_T4_CSR                  IXP2000_TIMER_REG(0x2c)
+/* Clear associated timer interrupt */
+#define        IXP2000_T1_CLR                  IXP2000_TIMER_REG(0x30)
+#define        IXP2000_T2_CLR                  IXP2000_TIMER_REG(0x34)
+#define        IXP2000_T3_CLR                  IXP2000_TIMER_REG(0x38)
+#define        IXP2000_T4_CLR                  IXP2000_TIMER_REG(0x3c)
+/* Timer watchdog enable for T4 */
+#define        IXP2000_TWDE                    IXP2000_TIMER_REG(0x40)
+
+#define        WDT_ENABLE                      0x00000001
+#define        TIMER_DIVIDER_256               0x00000008
+#define        TIMER_ENABLE                    0x00000080
+
+/*
+ * Interrupt controller registers
+ */
+#define IXP2000_INTCTL_REG(x)          (volatile unsigned long*)(IXP2000_INTCTL_VIRT_BASE | (x))
+#define IXP2000_IRQ_STATUS             IXP2000_INTCTL_REG(0x08)
+#define IXP2000_IRQ_ENABLE             IXP2000_INTCTL_REG(0x10)
+#define IXP2000_IRQ_ENABLE_SET         IXP2000_INTCTL_REG(0x10)
+#define IXP2000_IRQ_ENABLE_CLR         IXP2000_INTCTL_REG(0x18)
+#define IXP2000_FIQ_ENABLE_CLR         IXP2000_INTCTL_REG(0x14)
+#define IXP2000_IRQ_ERR_STATUS         IXP2000_INTCTL_REG(0x24)
+#define IXP2000_IRQ_ERR_ENABLE_SET     IXP2000_INTCTL_REG(0x2c)
+#define IXP2000_FIQ_ERR_ENABLE_CLR     IXP2000_INTCTL_REG(0x30)
+#define IXP2000_IRQ_ERR_ENABLE_CLR     IXP2000_INTCTL_REG(0x34)
+
+/*
+ * Mask of valid IRQs in the 32-bit IRQ register. We use
+ * this to mark certain IRQs as being in-valid.
+ */
+#define        IXP2000_VALID_IRQ_MASK  0x0f0fffff
+
+/*
+ * PCI config register access from core
+ */
+#define IXP2000_PCI_CREG(x)            (volatile unsigned long*)(IXP2000_PCI_CREG_VIRT_BASE | (x))
+#define IXP2000_PCI_CMDSTAT            IXP2000_PCI_CREG(0x04)
+#define IXP2000_PCI_CSR_BAR            IXP2000_PCI_CREG(0x10)
+#define IXP2000_PCI_SRAM_BAR           IXP2000_PCI_CREG(0x14)
+#define IXP2000_PCI_SDRAM_BAR          IXP2000_PCI_CREG(0x18)
+
+/*
+ * PCI CSRs
+ */
+#define IXP2000_PCI_CSR(x)             (volatile unsigned long*)(IXP2000_PCI_CSR_VIRT_BASE | (x))
+
+/*
+ * PCI outbound interrupts
+ */
+#define IXP2000_PCI_OUT_INT_STATUS     IXP2000_PCI_CSR(0x30)
+#define IXP2000_PCI_OUT_INT_MASK       IXP2000_PCI_CSR(0x34)
+/*
+ * PCI communications
+ */
+#define IXP2000_PCI_MAILBOX0           IXP2000_PCI_CSR(0x50)
+#define IXP2000_PCI_MAILBOX1           IXP2000_PCI_CSR(0x54)
+#define IXP2000_PCI_MAILBOX2           IXP2000_PCI_CSR(0x58)
+#define IXP2000_PCI_MAILBOX3           IXP2000_PCI_CSR(0x5C)
+#define IXP2000_XSCALE_DOORBELL                IXP2000_PCI_CSR(0x60)
+#define IXP2000_XSCALE_DOORBELL_SETUP  IXP2000_PCI_CSR(0x64)
+#define IXP2000_PCI_DOORBELL           IXP2000_PCI_CSR(0x70)
+#define IXP2000_PCI_DOORBELL_SETUP     IXP2000_PCI_CSR(0x74)
+
+/*
+ * DMA engines
+ */
+#define IXP2000_PCI_CH1_BYTE_CNT       IXP2000_PCI_CSR(0x80)
+#define IXP2000_PCI_CH1_ADDR           IXP2000_PCI_CSR(0x84)
+#define IXP2000_PCI_CH1_DRAM_ADDR      IXP2000_PCI_CSR(0x88)
+#define IXP2000_PCI_CH1_DESC_PTR       IXP2000_PCI_CSR(0x8C)
+#define IXP2000_PCI_CH1_CNTRL          IXP2000_PCI_CSR(0x90)
+#define IXP2000_PCI_CH1_ME_PARAM       IXP2000_PCI_CSR(0x94)
+#define IXP2000_PCI_CH2_BYTE_CNT       IXP2000_PCI_CSR(0xA0)
+#define IXP2000_PCI_CH2_ADDR           IXP2000_PCI_CSR(0xA4)
+#define IXP2000_PCI_CH2_DRAM_ADDR      IXP2000_PCI_CSR(0xA8)
+#define IXP2000_PCI_CH2_DESC_PTR       IXP2000_PCI_CSR(0xAC)
+#define IXP2000_PCI_CH2_CNTRL          IXP2000_PCI_CSR(0xB0)
+#define IXP2000_PCI_CH2_ME_PARAM       IXP2000_PCI_CSR(0xB4)
+#define IXP2000_PCI_CH3_BYTE_CNT       IXP2000_PCI_CSR(0xC0)
+#define IXP2000_PCI_CH3_ADDR           IXP2000_PCI_CSR(0xC4)
+#define IXP2000_PCI_CH3_DRAM_ADDR      IXP2000_PCI_CSR(0xC8)
+#define IXP2000_PCI_CH3_DESC_PTR       IXP2000_PCI_CSR(0xCC)
+#define IXP2000_PCI_CH3_CNTRL          IXP2000_PCI_CSR(0xD0)
+#define IXP2000_PCI_CH3_ME_PARAM       IXP2000_PCI_CSR(0xD4)
+#define IXP2000_DMA_INF_MODE           IXP2000_PCI_CSR(0xE0)
+/*
+ * Size masks for BARs
+ */
+#define IXP2000_PCI_SRAM_BASE_ADDR_MASK        IXP2000_PCI_CSR(0xFC)
+#define IXP2000_PCI_DRAM_BASE_ADDR_MASK        IXP2000_PCI_CSR(0x100)
+/*
+ * Control and uEngine related
+ */
+#define IXP2000_PCI_CONTROL            IXP2000_PCI_CSR(0x13C)
+#define IXP2000_PCI_ADDR_EXT           IXP2000_PCI_CSR(0x140)
+#define IXP2000_PCI_ME_PUSH_STATUS     IXP2000_PCI_CSR(0x148)
+#define IXP2000_PCI_ME_PUSH_EN         IXP2000_PCI_CSR(0x14C)
+#define IXP2000_PCI_ERR_STATUS         IXP2000_PCI_CSR(0x150)
+#define IXP2000_PCI_ERR_ENABLE         IXP2000_PCI_CSR(0x154)
+/*
+ * Inbound PCI interrupt control
+ */
+#define IXP2000_PCI_XSCALE_INT_STATUS  IXP2000_PCI_CSR(0x158)
+#define IXP2000_PCI_XSCALE_INT_ENABLE  IXP2000_PCI_CSR(0x15C)
+
+#define IXP2000_PCICNTL_PNR            (1<<17) /* PCI not Reset bit of PCI_CONTROL */
+#define IXP2000_PCICNTL_PCF            (1<<28) /* PCI Centrolfunction bit */
+#define IXP2000_XSCALE_INT             (1<<1)  /* Interrupt from  XScale to PCI */
+
+/* These are from the IRQ register in the PCI ISR register */
+#define PCI_CONTROL_BE_DEO             (1 << 22)       /* Big Endian Data Enable Out */
+#define PCI_CONTROL_BE_DEI             (1 << 21)       /* Big Endian Data Enable In  */
+#define PCI_CONTROL_BE_BEO             (1 << 20)       /* Big Endian Byte Enable Out */
+#define PCI_CONTROL_BE_BEI             (1 << 19)       /* Big Endian Byte Enable In  */
+#define PCI_CONTROL_PNR                        (1 << 17)       /* PCI Not Reset bit */
+
+#define IXP2000_PCI_RST_REL            (1 << 2)
+#define CFG_RST_DIR                    (*IXP2000_PCI_CONTROL & IXP2000_PCICNTL_PCF)
+#define CFG_PCI_BOOT_HOST              (1 << 2)
+#define CFG_BOOT_PROM                  (1 << 1)
+
+/*
+ * SlowPort CSRs
+ *
+ * The slowport is used to access things like flash, SONET framer control
+ * ports, slave microprocessors, CPLDs, and others of chip memory mapped
+ * peripherals.
+ */
+#define        SLOWPORT_CSR(x)         (volatile unsigned long*)(IXP2000_SLOWPORT_CSR_VIRT_BASE | (x))
+
+#define        IXP2000_SLOWPORT_CCR            SLOWPORT_CSR(0x00)
+#define        IXP2000_SLOWPORT_WTC1           SLOWPORT_CSR(0x04)
+#define        IXP2000_SLOWPORT_WTC2           SLOWPORT_CSR(0x08)
+#define        IXP2000_SLOWPORT_RTC1           SLOWPORT_CSR(0x0c)
+#define        IXP2000_SLOWPORT_RTC2           SLOWPORT_CSR(0x10)
+#define        IXP2000_SLOWPORT_FSR            SLOWPORT_CSR(0x14)
+#define        IXP2000_SLOWPORT_PCR            SLOWPORT_CSR(0x18)
+#define        IXP2000_SLOWPORT_ADC            SLOWPORT_CSR(0x1C)
+#define        IXP2000_SLOWPORT_FAC            SLOWPORT_CSR(0x20)
+#define        IXP2000_SLOWPORT_FRM            SLOWPORT_CSR(0x24)
+#define        IXP2000_SLOWPORT_FIN            SLOWPORT_CSR(0x28)
+
+/*
+ * CCR values.  
+ * The CCR configures the clock division for the slowport interface.
+ */
+#define        SLOWPORT_CCR_DIV_1              0x00
+#define        SLOWPORT_CCR_DIV_2              0x01
+#define        SLOWPORT_CCR_DIV_4              0x02
+#define        SLOWPORT_CCR_DIV_6              0x03
+#define        SLOWPORT_CCR_DIV_8              0x04
+#define        SLOWPORT_CCR_DIV_10             0x05
+#define        SLOWPORT_CCR_DIV_12             0x06
+#define        SLOWPORT_CCR_DIV_14             0x07
+#define        SLOWPORT_CCR_DIV_16             0x08
+#define        SLOWPORT_CCR_DIV_18             0x09
+#define        SLOWPORT_CCR_DIV_20             0x0a
+#define        SLOWPORT_CCR_DIV_22             0x0b
+#define        SLOWPORT_CCR_DIV_24             0x0c
+#define        SLOWPORT_CCR_DIV_26             0x0d
+#define        SLOWPORT_CCR_DIV_28             0x0e
+#define        SLOWPORT_CCR_DIV_30             0x0f
+
+/*
+ * PCR values.  PCR configure the mode of the interfac3
+ */
+#define        SLOWPORT_MODE_FLASH             0x00
+#define        SLOWPORT_MODE_LUCENT            0x01
+#define        SLOWPORT_MODE_PMC_SIERRA        0x02
+#define        SLOWPORT_MODE_INTEL_UP          0x03
+#define        SLOWPORT_MODE_MOTOROLA_UP       0x04
+
+/*
+ * ADC values.  Defines data and address bus widths
+ */
+#define        SLOWPORT_ADDR_WIDTH_8           0x00
+#define        SLOWPORT_ADDR_WIDTH_16          0x01
+#define        SLOWPORT_ADDR_WIDTH_24          0x02
+#define        SLOWPORT_ADDR_WIDTH_32          0x03
+#define        SLOWPORT_DATA_WIDTH_8           0x00
+#define        SLOWPORT_DATA_WIDTH_16          0x10
+#define        SLOWPORT_DATA_WIDTH_24          0x20
+#define        SLOWPORT_DATA_WIDTH_32          0x30
+
+/*
+ * Masks and shifts for various fields in the WTC and RTC registers
+ */
+#define        SLOWPORT_WRTC_MASK_HD           0x0003
+#define        SLOWPORT_WRTC_MASK_SU           0x003c
+#define        SLOWPORT_WRTC_MASK_PW           0x03c0
+
+#define        SLOWPORT_WRTC_SHIFT_HD          0x00
+#define        SLOWPORT_WRTC_SHIFT_SU          0x02
+#define        SLOWPORT_WRTC_SHFIT_PW          0x06
+
+
+/*
+ * GPIO registers & GPIO interface
+ */
+#define IXP2000_GPIO_REG(x)            ((volatile unsigned long*)(IXP2000_GPIO_VIRT_BASE+(x)))
+#define IXP2000_GPIO_PLR               IXP2000_GPIO_REG(0x00)
+#define IXP2000_GPIO_PDPR              IXP2000_GPIO_REG(0x04)
+#define IXP2000_GPIO_PDSR              IXP2000_GPIO_REG(0x08)
+#define IXP2000_GPIO_PDCR              IXP2000_GPIO_REG(0x0c)
+#define IXP2000_GPIO_POPR              IXP2000_GPIO_REG(0x10)
+#define IXP2000_GPIO_POSR              IXP2000_GPIO_REG(0x14)
+#define IXP2000_GPIO_POCR              IXP2000_GPIO_REG(0x18)
+#define IXP2000_GPIO_REDR              IXP2000_GPIO_REG(0x1c)
+#define IXP2000_GPIO_FEDR              IXP2000_GPIO_REG(0x20)
+#define IXP2000_GPIO_EDSR              IXP2000_GPIO_REG(0x24)
+#define IXP2000_GPIO_LSHR              IXP2000_GPIO_REG(0x28)
+#define IXP2000_GPIO_LSLR              IXP2000_GPIO_REG(0x2c)
+#define IXP2000_GPIO_LDSR              IXP2000_GPIO_REG(0x30)
+#define IXP2000_GPIO_INER              IXP2000_GPIO_REG(0x34)
+#define IXP2000_GPIO_INSR              IXP2000_GPIO_REG(0x38)
+#define IXP2000_GPIO_INCR              IXP2000_GPIO_REG(0x3c)
+#define IXP2000_GPIO_INST              IXP2000_GPIO_REG(0x40)
+
+/*
+ * "Global" registers...whatever that's supposed to mean.
+ */
+#define GLOBAL_REG_BASE                        (IXP2000_GLOBAL_REG_VIRT_BASE + 0x0a00)
+#define GLOBAL_REG(x)                  (volatile unsigned long*)(GLOBAL_REG_BASE | (x))
+
+#define IXP2000_PROD_ID                        GLOBAL_REG(0x00)
+
+#define IXP2000_MAJ_PROD_TYPE_MASK     0x001F0000
+#define IXP2000_MAJ_PROD_TYPE_IXP2000  0x00000000
+#define IXP2000_MIN_PROD_TYPE_MASK     0x0000FF00
+#define IXP2000_MIN_PROD_TYPE_IXP2400  0x00000200
+#define IXP2000_MIN_PROD_TYPE_IXP2850  0x00000100
+#define IXP2000_MIN_PROD_TYPE_IXP2800  0x00000000
+#define IXP2000_MAJ_REV_MASK           0x000000F0
+#define IXP2000_MIN_REV_MASK           0x0000000F
+#define IXP2000_PROD_ID_MASK           0xFFFFFFFF
+
+#define IXP2000_MISC_CONTROL           GLOBAL_REG(0x04)
+#define IXP2000_MSF_CLK_CNTRL                  GLOBAL_REG(0x08)
+#define IXP2000_RESET0                 GLOBAL_REG(0x0c)
+#define IXP2000_RESET1                 GLOBAL_REG(0x10)
+#define IXP2000_CCR                            GLOBAL_REG(0x14)
+#define        IXP2000_STRAP_OPTIONS           GLOBAL_REG(0x18)
+
+#define        RSTALL                          (1 << 16)
+#define        WDT_RESET_ENABLE                0x01000000
+
+
+#endif                         /* _IXP2000_H_ */
diff --git a/include/asm-arm/arch-ixp2000/memory.h b/include/asm-arm/arch-ixp2000/memory.h
new file mode 100644 (file)
index 0000000..d0f415c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/memory.h
+ *
+ * Copyright (c) 2002 Intel Corp.
+ * Copyright (c) 2003-2004 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#define PHYS_OFFSET    (0x00000000UL)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *             address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *             to an address that the kernel can use.
+ */
+#include <asm/arch/ixp2000-regs.h>
+
+#define __virt_to_bus(v) \
+       (((__virt_to_phys(v) - 0x0) + (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)))
+
+#define __bus_to_virt(b) \
+       __phys_to_virt((((b - (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)) + 0x0)))
+
+#endif
+
diff --git a/include/asm-arm/arch-ixp2000/param.h b/include/asm-arm/arch-ixp2000/param.h
new file mode 100644 (file)
index 0000000..2646d9e
--- /dev/null
@@ -0,0 +1,3 @@
+/*
+ *  linux/include/asm-arm/arch-ixp2000/param.h
+ */
diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h
new file mode 100644 (file)
index 0000000..9f4e315
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * include/asm-arh/arch-ixp2000/platform.h
+ *
+ * Various bits of code used by platform-level code.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * 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 __ASSEMBLY__
+
+/*
+ * The IXP2400 B0 silicon contains an errata that causes writes to 
+ * on-chip I/O register to not complete fully. What this means is
+ * that if you have a write to on-chip I/O followed by a back-to-back
+ * read or write, the first write will happend twice. OR...if it's
+ * not a back-to-back trasaction, the read or write will generate 
+ * incorrect data.
+ *
+ * The official work around for this is to set the on-chip I/O regions
+ * as XCB=101 and then force a read-back from the register.
+ *
+ */
+#if defined(CONFIG_ARCH_ENP2611) || defined(CONFIG_ARCH_IXDP2400) || defined(CONFIG_ARCH_IXDP2401)
+
+#include <asm/system.h>                /* Pickup local_irq_ functions */
+
+static inline void ixp2000_reg_write(volatile unsigned long *reg, unsigned long val)
+{
+       volatile unsigned long dummy;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       *reg = val;
+       barrier();
+       dummy = *reg;
+       local_irq_restore(flags);
+}
+#else
+#define        ixp2000_reg_write(reg, val) (*reg = val)
+#endif /* IXDP2400 || IXDP2401 */
+
+/*
+ * Boards may multiplex different devices on the 2nd channel of 
+ * the slowport interface that each need different configuration 
+ * settings.  For example, the IXDP2400 uses channel 2 on the interface 
+ * to access the CPLD, the switch fabric card, and te media card.  Each 
+ * one needs a different mode so drivers must save/restore the mode 
+ * before and after each operation.  
+ *
+ * acquire_slowport(&your_config);
+ * ...
+ * do slowport operations
+ * ...
+ * release_slowport();
+ *
+ * Note that while you have the slowport, you are holding a spinlock,
+ * so your code should be written as if you explicitly acquired a lock.
+ *
+ * The configuration only affects device 2 on the slowport, so the
+ * MTD map driver does not acquire/release the slowport.  
+ */
+struct slowport_cfg {
+       unsigned long CCR;      /* Clock divide */
+       unsigned long WTC;      /* Write Timing Control */
+       unsigned long RTC;      /* Read Timing Control */
+       unsigned long PCR;      /* Protocol Control Register */
+       unsigned long ADC;      /* Address/Data Width Control */
+};
+
+
+void ixp2000_acquire_slowport(struct slowport_cfg *, struct slowport_cfg *);
+void ixp2000_release_slowport(struct slowport_cfg *);
+
+/*
+ * IXP2400 A0/A1 and  IXP2800 A0/A1/A2 have broken slowport that requires
+ * tweaking of addresses in the MTD driver.
+ */
+static inline unsigned ixp2000_has_broken_slowport(void)
+{
+       unsigned long id = *IXP2000_PROD_ID;
+       unsigned long id_prod = id & (IXP2000_MAJ_PROD_TYPE_MASK |
+                                     IXP2000_MIN_PROD_TYPE_MASK);
+       return (((id_prod ==
+                 /* fixed in IXP2400-B0 */
+                 (IXP2000_MAJ_PROD_TYPE_IXP2000 |
+                  IXP2000_MIN_PROD_TYPE_IXP2400)) &&
+                ((id & IXP2000_MAJ_REV_MASK) == 0)) ||
+               ((id_prod ==
+                 /* fixed in IXP2800-B0 */
+                 (IXP2000_MAJ_PROD_TYPE_IXP2000 |
+                  IXP2000_MIN_PROD_TYPE_IXP2800)) &&
+                ((id & IXP2000_MAJ_REV_MASK) == 0)) ||
+               ((id_prod ==
+                 /* fixed in IXP2850-B0 */
+                 (IXP2000_MAJ_PROD_TYPE_IXP2000 |
+                  IXP2000_MIN_PROD_TYPE_IXP2850)) &&
+                ((id & IXP2000_MAJ_REV_MASK) == 0)));
+}
+
+static inline unsigned int ixp2000_has_flash(void)
+{
+       return ((*IXP2000_STRAP_OPTIONS) & (CFG_BOOT_PROM));
+}
+
+static inline unsigned int ixp2000_is_pcimaster(void)
+{
+       return ((*IXP2000_STRAP_OPTIONS) & (CFG_PCI_BOOT_HOST));
+}
+
+void ixp2000_map_io(void);
+void ixp2000_init_irq(void);
+void ixp2000_init_time(unsigned long);
+
+struct pci_sys_data;
+
+void ixp2000_pci_preinit(void);
+int ixp2000_pci_setup(int, struct pci_sys_data*);
+struct pci_bus* ixp2000_pci_scan_bus(int, struct pci_sys_data*);
+int ixp2000_pci_read_config(struct pci_bus*, unsigned int, int, int, u32 *);
+int ixp2000_pci_write_config(struct pci_bus*, unsigned int, int, int, u32);
+
+/*
+ * Several of the IXP2000 systems have banked flash so we need to extend the
+ * flash_platform_data structure with some private pointers
+ */
+struct ixp2000_flash_data {
+       struct flash_platform_data *platform_data;
+       int nr_banks;
+       unsigned long (*bank_setup)(unsigned long);
+};
+
+/*
+ * GPIO helper functions
+ */
+#define        GPIO_IN         0
+#define        GPIO_OUT        1
+
+extern void gpio_line_config(int line, int style);
+
+static inline int gpio_line_get(int line)
+{
+       return (((*IXP2000_GPIO_PLR) >> line) & 1);
+}
+
+static inline void gpio_line_set(int line, int value)
+{
+       if (value) 
+               ixp2000_reg_write(IXP2000_GPIO_POSR, (1 << line));
+       else 
+               ixp2000_reg_write(IXP2000_GPIO_POCR, (1 << line));
+}
+
+struct ixp2000_i2c_pins {
+       unsigned long sda_pin;
+       unsigned long scl_pin;
+};
+
+#endif /*  !__ASSEMBLY__ */
diff --git a/include/asm-arm/arch-ixp2000/serial.h b/include/asm-arm/arch-ixp2000/serial.h
new file mode 100644 (file)
index 0000000..98eebf1
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * include/asm-arm/arch-ixp2000/serial.h
+ *
+ * Serial port defn for ixp2000 based systems.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (c) 2002-2004 MontaVista Software, Inc.
+ *
+ * We do not register serial ports staticly b/c there is no easy way
+ * to autodetect an XScale port. Instead we register them at runtime
+ * via early_serial_init().
+ */
+
+#ifndef _ARCH_SERIAL_H_
+#define _ARCH_SERIAL_H_
+
+#define BASE_BAUD (50000000/ 16)
+
+/*
+ * Currently no IXP2000 systems with > 3 serial ports.
+ * If you add a system that does, just up this.
+ */
+#define        STD_SERIAL_PORT_DEFNS
+#define        EXTRA_SERIAL_PORT_DEFNS
+
+#endif  // __ARCH_SERIAL_H_
diff --git a/include/asm-arm/arch-ixp2000/system.h b/include/asm-arm/arch-ixp2000/system.h
new file mode 100644 (file)
index 0000000..ec72ba4
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * linux/include/asm-arm/arch-ixp2400/system.h
+ *
+ * Copyright (C) 2002 Intel Corp.
+ *
+ * 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/hardware.h>
+#include <asm/mach-types.h>
+
+static inline void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+       cli();
+
+       if (machine_is_ixdp2401() || machine_is_ixdp2801()) {
+               *IXDP2X01_CPLD_FLASH_REG = ((0 >> IXDP2X01_FLASH_WINDOW_BITS) | IXDP2X01_CPLD_FLASH_INTERN);
+               *IXDP2X01_CPLD_RESET_REG = 0xffffffff;
+       }
+
+       /*
+        * We do a reset all if we are PCI master. We could be a slave and we
+        * don't want to do anything funky on the PCI bus.
+        */
+       if (*IXP2000_STRAP_OPTIONS & CFG_PCI_BOOT_HOST) {
+               *(IXP2000_RESET0) |= (RSTALL);
+       }
+}
diff --git a/include/asm-arm/arch-ixp2000/timex.h b/include/asm-arm/arch-ixp2000/timex.h
new file mode 100644 (file)
index 0000000..b78a183
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/timex.h
+ *
+ * IXP2000 architecture timex specifications
+ */
+
+
+/*
+ * Default clock is 50MHz APB, but platform code can override this
+ */
+#define CLOCK_TICK_RATE        50000000
+
+
diff --git a/include/asm-arm/arch-ixp2000/uncompress.h b/include/asm-arm/arch-ixp2000/uncompress.h
new file mode 100644 (file)
index 0000000..3d3d5b2
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/uncompress.h
+ *
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2002 Intel Corp.
+ *
+ *  This program is free software; you can redistribute  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/serial_reg.h>
+
+#define UART_BASE      0xc0030000
+
+#define PHYS(x)          ((volatile unsigned long *)(UART_BASE + x))
+
+#define UARTDR          PHYS(0x00)      /* Transmit reg dlab=0 */
+#define UARTDLL         PHYS(0x00)      /* Divisor Latch reg dlab=1*/
+#define UARTDLM         PHYS(0x04)      /* Divisor Latch reg dlab=1*/
+#define UARTIER         PHYS(0x04)      /* Interrupt enable reg */
+#define UARTFCR         PHYS(0x08)      /* FIFO control reg dlab =0*/
+#define UARTLCR         PHYS(0x0c)      /* Control reg */
+#define UARTSR          PHYS(0x14)      /* Status reg */
+
+
+static __inline__ void putc(char c)
+{
+       int j = 0x1000;
+
+       while (--j && !(*UARTSR & UART_LSR_THRE)); 
+       *UARTDR = c;
+}
+
+static void putstr(const char *s)
+{
+       while (*s)
+       {
+               putc(*s);
+               if (*s == '\n')
+                       putc('\r');
+               s++;
+       }
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-ixp2000/vmalloc.h b/include/asm-arm/arch-ixp2000/vmalloc.h
new file mode 100644 (file)
index 0000000..f2705a8
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/vmalloc.h
+ *
+ * Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ *
+ * Copyright 2002 Intel Corp.
+ *
+ *  This program is free software; you can redistribute  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.
+ *
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET     (8*1024*1024)
+#define VMALLOC_START      (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x)   ((unsigned long)(x))
+#define VMALLOC_END        0xfb000000
index 91d25c2..5400ab0 100644 (file)
@@ -73,7 +73,7 @@ __ixp4xx_iounmap(void *addr)
 {
        extern void __iounmap(void *addr);
 
-       if ((u32)addr > VMALLOC_START)
+       if ((u32)addr >= VMALLOC_START)
                __iounmap(addr);
 }
 
@@ -101,7 +101,7 @@ __ixp4xx_writeb(u8 value, u32 addr)
 {
        u32 n, byte_enables, data;
 
-       if (addr > VMALLOC_START) {
+       if (addr >= VMALLOC_START) {
                __raw_writeb(value, addr);
                return;
        }
@@ -124,7 +124,7 @@ __ixp4xx_writew(u16 value, u32 addr)
 {
        u32 n, byte_enables, data;
 
-       if (addr > VMALLOC_START) {
+       if (addr >= VMALLOC_START) {
                __raw_writew(value, addr);
                return;
        }
@@ -145,7 +145,7 @@ __ixp4xx_writesw(u32 bus_addr, u16 *vaddr, int count)
 static inline void 
 __ixp4xx_writel(u32 value, u32 addr)
 {
-       if (addr > VMALLOC_START) {
+       if (addr >= VMALLOC_START) {
                __raw_writel(value, addr);
                return;
        }
@@ -165,7 +165,7 @@ __ixp4xx_readb(u32 addr)
 {
        u32 n, byte_enables, data;
 
-       if (addr > VMALLOC_START)
+       if (addr >= VMALLOC_START)
                return __raw_readb(addr);
 
        n = addr % 4;
@@ -188,7 +188,7 @@ __ixp4xx_readw(u32 addr)
 {
        u32 n, byte_enables, data;
 
-       if (addr > VMALLOC_START)
+       if (addr >= VMALLOC_START)
                return __raw_readw(addr);
 
        n = addr % 4;
@@ -211,7 +211,7 @@ __ixp4xx_readl(u32 addr)
 {
        u32 data;
 
-       if (addr > VMALLOC_START)
+       if (addr >= VMALLOC_START)
                return __raw_readl(addr);
 
        if (ixp4xx_pci_read(addr, NP_CMD_MEMREAD, &data))
index 29692ec..0535098 100644 (file)
@@ -32,7 +32,7 @@ static __inline__ void putc(char c)
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
        while (*s)
        {
index 98786ad..9962a12 100644 (file)
@@ -16,4 +16,4 @@
 /*
  * See 'time.h' for how the RTC HZ rate is set
  */
-#define __KERNEL_HZ 128
+#define HZ 128
index d7ac5f6..1caa2b5 100644 (file)
@@ -23,7 +23,7 @@ static __inline__ void putc(char c)
        __raw_writeb(c, IO_UART + 0x00);
 }
 
-static void puts(const char *s)
+static void putstr(const char *s)
 {
        while (*s) {
                if (*s == 10) {                 /* If a LF, add CR */
index c31796f..ec8ab67 100644 (file)
@@ -29,7 +29,7 @@ static __inline__ void putc (char ch)
        UART_DATA = ch;
 }
 
-static void puts (const char* sz)
+static void putstr (const char* sz)
 {
        for (; *sz; ++sz) {
                putc (*sz);
index fe2c06d..e51f248 100644 (file)
 
 /* Placeholder for H2 specific defines */
 
+/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
+#define OMAP1610_ETHR_BASE             0xE8000000
+#define OMAP1610_ETHR_SIZE             SZ_4K
+#define OMAP1610_ETHR_START            0x04000000
+
+/* Intel STRATA NOR flash at CS3 */
+#define OMAP1610_NOR_FLASH_BASE                0xD8000000
+#define OMAP1610_NOR_FLASH_SIZE                SZ_32M
+#define OMAP1610_NOR_FLASH_START       0x0C000000
+
 #endif /*  __ASM_ARCH_OMAP_H2_H */
 
index f08276f..80c37bf 100644 (file)
@@ -1,9 +1,8 @@
 /*
  * linux/include/asm-arm/arch-omap/board-h3.h
  *
- * Hardware definitions for TI OMAP1610 H3 board.
- *
- * Initial creation by Dirk Behme <dirk.behme@de.bosch.com>
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Copyright (C) 2004 Texas Instruments, 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
  * with this program; if not, write  to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
 #ifndef __ASM_ARCH_OMAP_H3_H
 #define __ASM_ARCH_OMAP_H3_H
 
-/* Placeholder for H3 specific defines */
+/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
+#define OMAP1710_ETHR_BASE             0xE8000000
+#define OMAP1710_ETHR_SIZE             SZ_4K
+#define OMAP1710_ETHR_START            0x04000000
 
-#endif /*  __ASM_ARCH_OMAP_H3_H */
+/* Intel STRATA NOR flash at CS3 */
+#define OMAP_NOR_FLASH_BASE            0xD8000000
+#define OMAP_NOR_FLASH_SIZE            SZ_32M
+#define OMAP_NOR_FLASH_START           0x00000000
+
+#define MAXIRQNUM                      (IH_BOARD_BASE)
+#define MAXFIQNUM                      MAXIRQNUM
+#define MAXSWINUM                      MAXIRQNUM
 
+#define NR_IRQS                                (MAXIRQNUM + 1)
+
+#define OMAP_MCBSP1_BASE               OMAP1610_MCBSP1_BASE
+#define AUDIO_DRR2  (OMAP_MCBSP1_BASE + 0x00)
+#define AUDIO_DRR1  (OMAP_MCBSP1_BASE + 0x02)
+#define AUDIO_DXR2  (OMAP_MCBSP1_BASE + 0x04)
+#define AUDIO_DXR1  (OMAP_MCBSP1_BASE + 0x06)
+#define AUDIO_SPCR2 (OMAP_MCBSP1_BASE + 0x08)
+#define AUDIO_SPCR1 (OMAP_MCBSP1_BASE + 0x0a)
+#define AUDIO_RCR2  (OMAP_MCBSP1_BASE + 0x0c)
+#define AUDIO_RCR1  (OMAP_MCBSP1_BASE + 0x0e)
+#define AUDIO_XCR2  (OMAP_MCBSP1_BASE + 0x10)
+#define AUDIO_XCR1  (OMAP_MCBSP1_BASE + 0x12)
+#define AUDIO_SRGR2 (OMAP_MCBSP1_BASE + 0x14)
+#define AUDIO_SRGR1 (OMAP_MCBSP1_BASE + 0x16)
+#define AUDIO_MCR2  (OMAP_MCBSP1_BASE + 0x18)
+#define AUDIO_MCR1  (OMAP_MCBSP1_BASE + 0x1a)
+#define AUDIO_RCERA (OMAP_MCBSP1_BASE + 0x1c)
+#define AUDIO_RCERB (OMAP_MCBSP1_BASE + 0x1e)
+#define AUDIO_XCERA (OMAP_MCBSP1_BASE + 0x20)
+#define AUDIO_XCERB (OMAP_MCBSP1_BASE + 0x22)
+#define AUDIO_PCR0  (OMAP_MCBSP1_BASE + 0x24)
+
+/* UART3 Registers Maping through MPU bus */
+#define OMAP_MPU_UART3_BASE     0xFFFB9800      /* UART3 through MPU bus */
+#define UART3_RHR               (OMAP_MPU_UART3_BASE + 0)
+#define UART3_THR               (OMAP_MPU_UART3_BASE + 0)
+#define UART3_DLL               (OMAP_MPU_UART3_BASE + 0)
+#define UART3_IER               (OMAP_MPU_UART3_BASE + 4)
+#define UART3_DLH               (OMAP_MPU_UART3_BASE + 4)
+#define UART3_IIR               (OMAP_MPU_UART3_BASE + 8)
+#define UART3_FCR               (OMAP_MPU_UART3_BASE + 8)
+#define UART3_EFR               (OMAP_MPU_UART3_BASE + 8)
+#define UART3_LCR               (OMAP_MPU_UART3_BASE + 0x0C)
+#define UART3_MCR               (OMAP_MPU_UART3_BASE + 0x10)
+#define UART3_XON1_ADDR1        (OMAP_MPU_UART3_BASE + 0x10)
+#define UART3_XON2_ADDR2        (OMAP_MPU_UART3_BASE + 0x14)
+#define UART3_LSR               (OMAP_MPU_UART3_BASE + 0x14)
+#define UART3_TCR               (OMAP_MPU_UART3_BASE + 0x18)
+#define UART3_MSR               (OMAP_MPU_UART3_BASE + 0x18)
+#define UART3_XOFF1             (OMAP_MPU_UART3_BASE + 0x18)
+#define UART3_XOFF2             (OMAP_MPU_UART3_BASE + 0x1C)
+#define UART3_SPR               (OMAP_MPU_UART3_BASE + 0x1C)
+#define UART3_TLR               (OMAP_MPU_UART3_BASE + 0x1C)
+#define UART3_MDR1              (OMAP_MPU_UART3_BASE + 0x20)
+#define UART3_MDR2              (OMAP_MPU_UART3_BASE + 0x24)
+#define UART3_SFLSR             (OMAP_MPU_UART3_BASE + 0x28)
+#define UART3_TXFLL             (OMAP_MPU_UART3_BASE + 0x28)
+#define UART3_RESUME            (OMAP_MPU_UART3_BASE + 0x2C)
+#define UART3_TXFLH             (OMAP_MPU_UART3_BASE + 0x2C)
+#define UART3_SFREGL            (OMAP_MPU_UART3_BASE + 0x30)
+#define UART3_RXFLL             (OMAP_MPU_UART3_BASE + 0x30)
+#define UART3_SFREGH            (OMAP_MPU_UART3_BASE + 0x34)
+#define UART3_RXFLH             (OMAP_MPU_UART3_BASE + 0x34)
+#define UART3_BLR               (OMAP_MPU_UART3_BASE + 0x38)
+#define UART3_ACREG             (OMAP_MPU_UART3_BASE + 0x3C)
+#define UART3_DIV16             (OMAP_MPU_UART3_BASE + 0x3C)
+#define UART3_SCR               (OMAP_MPU_UART3_BASE + 0x40)
+#define UART3_SSR               (OMAP_MPU_UART3_BASE + 0x44)
+#define UART3_EBLR              (OMAP_MPU_UART3_BASE + 0x48)
+#define UART3_OSC_12M_SEL       (OMAP_MPU_UART3_BASE + 0x4C)
+#define UART3_MVR               (OMAP_MPU_UART3_BASE + 0x50)
+
+#endif /*  __ASM_ARCH_OMAP_H3_H */
index 50671ba..87e45d9 100644 (file)
 
 #if defined (CONFIG_ARCH_OMAP1510)
 
-/*
- * ---------------------------------------------------------------------------
- *  OMAP-1510 FPGA
- * ---------------------------------------------------------------------------
- */
-#define OMAP1510_FPGA_BASE                     0xE8000000      /* Virtual */
-#define OMAP1510_FPGA_SIZE                     SZ_4K
-#define OMAP1510_FPGA_START                    0x08000000      /* Physical */
-
-/* Revision */
-#define OMAP1510_FPGA_REV_LOW                  (OMAP1510_FPGA_BASE + 0x0)
-#define OMAP1510_FPGA_REV_HIGH                 (OMAP1510_FPGA_BASE + 0x1)
-
-#define OMAP1510_FPGA_LCD_PANEL_CONTROL                (OMAP1510_FPGA_BASE + 0x2)
-#define OMAP1510_FPGA_LED_DIGIT                        (OMAP1510_FPGA_BASE + 0x3)
-#define INNOVATOR_FPGA_HID_SPI                 (OMAP1510_FPGA_BASE + 0x4)
-#define OMAP1510_FPGA_POWER                    (OMAP1510_FPGA_BASE + 0x5)
-
-/* Interrupt status */
-#define OMAP1510_FPGA_ISR_LO                   (OMAP1510_FPGA_BASE + 0x6)
-#define OMAP1510_FPGA_ISR_HI                   (OMAP1510_FPGA_BASE + 0x7)
-
-/* Interrupt mask */
-#define OMAP1510_FPGA_IMR_LO                   (OMAP1510_FPGA_BASE + 0x8)
-#define OMAP1510_FPGA_IMR_HI                   (OMAP1510_FPGA_BASE + 0x9)
-
-/* Reset registers */
-#define OMAP1510_FPGA_HOST_RESET               (OMAP1510_FPGA_BASE + 0xa)
-#define OMAP1510_FPGA_RST                      (OMAP1510_FPGA_BASE + 0xb)
-
-#define OMAP1510_FPGA_AUDIO                    (OMAP1510_FPGA_BASE + 0xc)
-#define OMAP1510_FPGA_DIP                      (OMAP1510_FPGA_BASE + 0xe)
-#define OMAP1510_FPGA_FPGA_IO                  (OMAP1510_FPGA_BASE + 0xf)
-#define OMAP1510_FPGA_UART1                    (OMAP1510_FPGA_BASE + 0x14)
-#define OMAP1510_FPGA_UART2                    (OMAP1510_FPGA_BASE + 0x15)
-#define OMAP1510_FPGA_OMAP1510_STATUS          (OMAP1510_FPGA_BASE + 0x16)
-#define OMAP1510_FPGA_BOARD_REV                        (OMAP1510_FPGA_BASE + 0x18)
-#define OMAP1510P1_PPT_DATA                    (OMAP1510_FPGA_BASE + 0x100)
-#define OMAP1510P1_PPT_STATUS                  (OMAP1510_FPGA_BASE + 0x101)
-#define OMAP1510P1_PPT_CONTROL                 (OMAP1510_FPGA_BASE + 0x102)
-
-#define OMAP1510_FPGA_TOUCHSCREEN              (OMAP1510_FPGA_BASE + 0x204)
-
-#define INNOVATOR_FPGA_INFO                    (OMAP1510_FPGA_BASE + 0x205)
-#define INNOVATOR_FPGA_LCD_BRIGHT_LO           (OMAP1510_FPGA_BASE + 0x206)
-#define INNOVATOR_FPGA_LCD_BRIGHT_HI           (OMAP1510_FPGA_BASE + 0x207)
-#define INNOVATOR_FPGA_LED_GRN_LO              (OMAP1510_FPGA_BASE + 0x208)
-#define INNOVATOR_FPGA_LED_GRN_HI              (OMAP1510_FPGA_BASE + 0x209)
-#define INNOVATOR_FPGA_LED_RED_LO              (OMAP1510_FPGA_BASE + 0x20a)
-#define INNOVATOR_FPGA_LED_RED_HI              (OMAP1510_FPGA_BASE + 0x20b)
-#define INNOVATOR_FPGA_CAM_USB_CONTROL         (OMAP1510_FPGA_BASE + 0x20c)
-#define INNOVATOR_FPGA_EXP_CONTROL             (OMAP1510_FPGA_BASE + 0x20d)
-#define INNOVATOR_FPGA_ISR2                    (OMAP1510_FPGA_BASE + 0x20e)
-#define INNOVATOR_FPGA_IMR2                    (OMAP1510_FPGA_BASE + 0x210)
-
-#define OMAP1510_FPGA_ETHR_START               (OMAP1510_FPGA_START + 0x300)
-#define OMAP1510_FPGA_ETHR_BASE                        (OMAP1510_FPGA_BASE + 0x300)
-
-/*
- * Power up Giga UART driver, turn on HID clock.
- * Turn off BT power, since we're not using it and it
- * draws power.
- */
-#define OMAP1510_FPGA_RESET_VALUE              0x42
-
-#define OMAP1510_FPGA_PCR_IF_PD0               (1 << 7)
-#define OMAP1510_FPGA_PCR_COM2_EN              (1 << 6)
-#define OMAP1510_FPGA_PCR_COM1_EN              (1 << 5)
-#define OMAP1510_FPGA_PCR_EXP_PD0              (1 << 4)
-#define OMAP1510_FPGA_PCR_EXP_PD1              (1 << 3)
-#define OMAP1510_FPGA_PCR_48MHZ_CLK            (1 << 2)
-#define OMAP1510_FPGA_PCR_4MHZ_CLK             (1 << 1)
-#define OMAP1510_FPGA_PCR_RSRVD_BIT0           (1 << 0)
-
-/*
- * Innovator/OMAP1510 FPGA HID register bit definitions
- */
-#define FPGA_HID_SCLK  (1<<0)  /* output */
-#define FPGA_HID_MOSI  (1<<1)  /* output */
-#define FPGA_HID_nSS   (1<<2)  /* output 0/1 chip idle/select */
-#define FPGA_HID_nHSUS (1<<3)  /* output 0/1 host active/suspended */
-#define FPGA_HID_MISO  (1<<4)  /* input */
-#define FPGA_HID_ATN   (1<<5)  /* input  0/1 chip idle/ATN */
-#define FPGA_HID_rsrvd (1<<6)
-#define FPGA_HID_RESETn (1<<7) /* output - 0/1 USAR reset/run */
-
 #ifndef OMAP_SDRAM_DEVICE
 #define OMAP_SDRAM_DEVICE                      D256M_1X16_4B
 #endif
 #define OMAP_FLASH_1_START     0x01000000
 #define OMAP_FLASH_1_SIZE      SZ_16M
 
-/* The FPGA IRQ is cascaded through GPIO_13 */
-#define INT_FPGA               (IH_GPIO_BASE + 13)
-
-/* IRQ Numbers for interrupts muxed through the FPGA */
-#define IH_FPGA_BASE           IH_BOARD_BASE
-#define INT_FPGA_ATN           (IH_FPGA_BASE + 0)
-#define INT_FPGA_ACK           (IH_FPGA_BASE + 1)
-#define INT_FPGA2              (IH_FPGA_BASE + 2)
-#define INT_FPGA3              (IH_FPGA_BASE + 3)
-#define INT_FPGA4              (IH_FPGA_BASE + 4)
-#define INT_FPGA5              (IH_FPGA_BASE + 5)
-#define INT_FPGA6              (IH_FPGA_BASE + 6)
-#define INT_FPGA7              (IH_FPGA_BASE + 7)
-#define INT_FPGA8              (IH_FPGA_BASE + 8)
-#define INT_FPGA9              (IH_FPGA_BASE + 9)
-#define INT_FPGA10             (IH_FPGA_BASE + 10)
-#define INT_FPGA11             (IH_FPGA_BASE + 11)
-#define INT_FPGA12             (IH_FPGA_BASE + 12)
-#define INT_ETHER              (IH_FPGA_BASE + 13)
-#define INT_FPGAUART1          (IH_FPGA_BASE + 14)
-#define INT_FPGAUART2          (IH_FPGA_BASE + 15)
-#define INT_FPGA_TS            (IH_FPGA_BASE + 16)
-#define INT_FPGA17             (IH_FPGA_BASE + 17)
-#define INT_FPGA_CAM           (IH_FPGA_BASE + 18)
-#define INT_FPGA_RTC_A         (IH_FPGA_BASE + 19)
-#define INT_FPGA_RTC_B         (IH_FPGA_BASE + 20)
-#define INT_FPGA_CD            (IH_FPGA_BASE + 21)
-#define INT_FPGA22             (IH_FPGA_BASE + 22)
-#define INT_FPGA23             (IH_FPGA_BASE + 23)
-
-#define NR_FPGA_IRQS            24
+#define NR_FPGA_IRQS           24
+#define NR_IRQS                 IH_BOARD_BASE + NR_FPGA_IRQS
 
 #ifndef __ASSEMBLY__
 void fpga_write(unsigned char val, int reg);
index 4839c44..0c224cc 100644 (file)
@@ -2,8 +2,7 @@
  *  linux/include/asm-arm/arch-omap/board-perseus2.h
  *
  *  Copyright 2003 by Texas Instruments Incorporated
- *    OMAP730 / P2-sample additions
- *    Author: Jean Pihet
+ *    OMAP730 / Perseus2 support by Jean Pihet
  *
  * Copyright (C) 2001 RidgeRun, Inc. (http://www.ridgerun.com)
  * Author: RidgeRun, Inc.
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#ifndef __ASM_ARCH_OMAP_P2SAMPLE_H
-#define __ASM_ARCH_OMAP_P2SAMPLE_H
+#ifndef __ASM_ARCH_OMAP_PERSEUS2_H
+#define __ASM_ARCH_OMAP_PERSEUS2_H
 
-#if defined(CONFIG_ARCH_OMAP730) && defined (CONFIG_MACH_OMAP_PERSEUS2)
-
-/*
- * NOTE:  ALL DEFINITIONS IN THIS FILE NEED TO BE PREFIXED BY IDENTIFIER
- *       P2SAMPLE_ since they are specific to the EVM and not the chip.
- */
-
-/* ---------------------------------------------------------------------------
- *  OMAP730 Debug Board FPGA
- * ---------------------------------------------------------------------------
- */
-
-/* maps in the FPGA registers and the ETHR registers */
-#define OMAP730_FPGA_BASE              0xE8000000      /* VA */
-#define OMAP730_FPGA_SIZE              SZ_4K           /* SIZE */
-#define OMAP730_FPGA_START             0x04000000      /* PA */
-
-#define OMAP730_FPGA_ETHR_START                OMAP730_FPGA_START
-#define OMAP730_FPGA_ETHR_BASE         OMAP730_FPGA_BASE
-#define OMAP730_FPGA_FPGA_REV          (OMAP730_FPGA_BASE + 0x10)      /* FPGA Revision */
-#define OMAP730_FPGA_BOARD_REV         (OMAP730_FPGA_BASE + 0x12)      /* Board Revision */
-#define OMAP730_FPGA_GPIO              (OMAP730_FPGA_BASE + 0x14)      /* GPIO outputs */
-#define OMAP730_FPGA_LEDS              (OMAP730_FPGA_BASE + 0x16)      /* LEDs outputs */
-#define OMAP730_FPGA_MISC_INPUTS       (OMAP730_FPGA_BASE + 0x18)      /* Misc inputs */
-#define OMAP730_FPGA_LAN_STATUS                (OMAP730_FPGA_BASE + 0x1A)      /* LAN Status line */
-#define OMAP730_FPGA_LAN_RESET         (OMAP730_FPGA_BASE + 0x1C)      /* LAN Reset line */
-
-// LEDs definition on debug board (16 LEDs)
-#define OMAP730_FPGA_LED_CLAIMRELEASE  (1 << 15)
-#define OMAP730_FPGA_LED_STARTSTOP     (1 << 14)
-#define OMAP730_FPGA_LED_HALTED                (1 << 13)
-#define OMAP730_FPGA_LED_IDLE          (1 << 12)
-#define OMAP730_FPGA_LED_TIMER         (1 << 11)
-// cpu0 load-meter LEDs
-#define OMAP730_FPGA_LOAD_METER                (1 << 0)        // A bit of fun on our board ...
-#define OMAP730_FPGA_LOAD_METER_SIZE   11
-#define OMAP730_FPGA_LOAD_METER_MASK   ((1 << OMAP730_FPGA_LOAD_METER_SIZE) - 1)
+#include <asm/arch/fpga.h>
 
 #ifndef OMAP_SDRAM_DEVICE
 #define OMAP_SDRAM_DEVICE              D256M_1X16_4B
 #define OMAP_FLASH_0_START     0x00000000      /* PA */
 #define OMAP_FLASH_0_SIZE      SZ_32M
 
-/* The Ethernet Controller IRQ is cascaded to MPU_EXT_nIRQ througb the FPGA */
-#define INT_ETHER              INT_730_MPU_EXT_NIRQ
-
 #define MAXIRQNUM              IH_BOARD_BASE
 #define MAXFIQNUM              MAXIRQNUM
 #define MAXSWINUM              MAXIRQNUM
 
 #define NR_IRQS                        (MAXIRQNUM + 1)
 
-#ifndef __ASSEMBLY__
-void fpga_write(unsigned char val, int reg);
-unsigned char fpga_read(int reg);
-#endif
-
-#else
-#error "Only OMAP730 Perseus2 supported!"
-#endif
-
 #endif
index fe21fc8..a241935 100644 (file)
 #define OMAP_TAG_CLOCK         0x4f01
 #define OMAP_TAG_MMC           0x4f02
 #define OMAP_TAG_UART          0x4f03
+#define OMAP_TAG_USB            0x4f04
 
-struct omap_clock_info {
+struct omap_clock_config {
        /* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
        u8 system_clock_type;
 };
 
-struct omap_mmc_info {
+struct omap_mmc_config {
        u8 mmc_blocks;
        s8 mmc1_power_pin, mmc2_power_pin;
        s8 mmc1_switch_pin, mmc2_switch_pin;
 };
 
-struct omap_uart_info {
+struct omap_uart_config {
        u8 console_uart;
        u32 console_speed;
 };
 
-struct omap_board_info_entry {
+struct omap_usb_config {
+       /* Configure drivers according to the connectors on your board:
+        *  - "A" connector (rectagular)
+        *      ... for host/OHCI use, set "register_host".
+        *  - "B" connector (squarish) or "Mini-B"
+        *      ... for device/gadget use, set "register_dev".
+        *  - "Mini-AB" connector (very similar to Mini-B)
+        *      ... for OTG use as device OR host, initialize "otg"
+        */
+       unsigned        register_host:1;
+       unsigned        register_dev:1;
+       u8              otg;    /* port number, 1-based:  usb1 == 2 */
+
+       u8              hmc_mode;
+
+       /* implicitly true if otg:  host supports remote wakeup? */
+       u8              rwc;
+
+       /* signaling pins used to talk to transceiver on usbN:
+        *  0 == usbN unused
+        *  2 == usb0-only, using internal transceiver
+        *  3 == 3 wire bidirectional
+        *  4 == 4 wire bidirectional
+        *  6 == 6 wire unidirectional (or TLL)
+        */
+       u8              pins[3];
+};
+
+struct omap_board_config_entry {
        u16 tag;
        u16 len;
        u8  data[0];
 };
 
-extern const void *__omap_get_per_info(u16 tag, size_t len);
+struct omap_board_config_kernel {
+       u16 tag;
+       const void *data;
+};
+
+extern const void *__omap_get_config(u16 tag, size_t len);
+
+#define omap_get_config(tag, type) \
+       ((const type *) __omap_get_config((tag), sizeof(type)))
 
-#define omap_get_per_info(tag, type) \
-       ((const type *) __omap_get_per_info((tag), sizeof(type)))
+extern struct omap_board_config_kernel *omap_board_config;
+extern int omap_board_config_size;
 
 #endif
index 565a87f..dc9f61a 100644 (file)
 #ifndef __ASM_ARCH_OMAP_FPGA_H
 #define __ASM_ARCH_OMAP_FPGA_H
 
-extern void fpga_init_irq(void);
-extern unsigned char fpga_read(int reg);
-extern void fpga_write(unsigned char val, int reg);
+#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP1510)
+extern void omap1510_fpga_init_irq(void);
+#else
+#define omap1510_fpga_init_irq()       (0)
+#endif
+
+#define fpga_read(reg)                 __raw_readb(reg)
+#define fpga_write(val, reg)           __raw_writeb(val, reg)
+
+/*
+ * ---------------------------------------------------------------------------
+ *  H2/P2 Debug board FPGA
+ * ---------------------------------------------------------------------------
+ */
+/* maps in the FPGA registers and the ETHR registers */
+#define H2P2_DBG_FPGA_BASE             0xE8000000      /* VA */
+#define H2P2_DBG_FPGA_SIZE             SZ_4K           /* SIZE */
+#define H2P2_DBG_FPGA_START            0x04000000      /* PA */
+
+#define H2P2_DBG_FPGA_ETHR_START       H2P2_DBG_FPGA_START
+#define H2P2_DBG_FPGA_ETHR_BASE                H2P2_DBG_FPGA_BASE
+#define H2P2_DBG_FPGA_FPGA_REV         (H2P2_DBG_FPGA_BASE + 0x10)     /* FPGA Revision */
+#define H2P2_DBG_FPGA_BOARD_REV                (H2P2_DBG_FPGA_BASE + 0x12)     /* Board Revision */
+#define H2P2_DBG_FPGA_GPIO             (H2P2_DBG_FPGA_BASE + 0x14)     /* GPIO outputs */
+#define H2P2_DBG_FPGA_LEDS             (H2P2_DBG_FPGA_BASE + 0x16)     /* LEDs outputs */
+#define H2P2_DBG_FPGA_MISC_INPUTS      (H2P2_DBG_FPGA_BASE + 0x18)     /* Misc inputs */
+#define H2P2_DBG_FPGA_LAN_STATUS       (H2P2_DBG_FPGA_BASE + 0x1A)     /* LAN Status line */
+#define H2P2_DBG_FPGA_LAN_RESET                (H2P2_DBG_FPGA_BASE + 0x1C)     /* LAN Reset line */
+
+/* LEDs definition on debug board (16 LEDs) */
+#define H2P2_DBG_FPGA_LED_CLAIMRELEASE (1 << 15)
+#define H2P2_DBG_FPGA_LED_STARTSTOP    (1 << 14)
+#define H2P2_DBG_FPGA_LED_HALTED       (1 << 13)
+#define H2P2_DBG_FPGA_LED_IDLE         (1 << 12)
+#define H2P2_DBG_FPGA_LED_TIMER                (1 << 11)
+/*  cpu0 load-meter LEDs */
+#define H2P2_DBG_FPGA_LOAD_METER       (1 << 0)        // A bit of fun on our board ...
+#define H2P2_DBG_FPGA_LOAD_METER_SIZE  11
+#define H2P2_DBG_FPGA_LOAD_METER_MASK  ((1 << H2P2_DBG_FPGA_LOAD_METER_SIZE) - 1)
+
+
+/*
+ * ---------------------------------------------------------------------------
+ *  OMAP-1510 FPGA
+ * ---------------------------------------------------------------------------
+ */
+#define OMAP1510_FPGA_BASE                     0xE8000000      /* Virtual */
+#define OMAP1510_FPGA_SIZE                     SZ_4K
+#define OMAP1510_FPGA_START                    0x08000000      /* Physical */
+
+/* Revision */
+#define OMAP1510_FPGA_REV_LOW                  (OMAP1510_FPGA_BASE + 0x0)
+#define OMAP1510_FPGA_REV_HIGH                 (OMAP1510_FPGA_BASE + 0x1)
+
+#define OMAP1510_FPGA_LCD_PANEL_CONTROL                (OMAP1510_FPGA_BASE + 0x2)
+#define OMAP1510_FPGA_LED_DIGIT                        (OMAP1510_FPGA_BASE + 0x3)
+#define INNOVATOR_FPGA_HID_SPI                 (OMAP1510_FPGA_BASE + 0x4)
+#define OMAP1510_FPGA_POWER                    (OMAP1510_FPGA_BASE + 0x5)
+
+/* Interrupt status */
+#define OMAP1510_FPGA_ISR_LO                   (OMAP1510_FPGA_BASE + 0x6)
+#define OMAP1510_FPGA_ISR_HI                   (OMAP1510_FPGA_BASE + 0x7)
+
+/* Interrupt mask */
+#define OMAP1510_FPGA_IMR_LO                   (OMAP1510_FPGA_BASE + 0x8)
+#define OMAP1510_FPGA_IMR_HI                   (OMAP1510_FPGA_BASE + 0x9)
+
+/* Reset registers */
+#define OMAP1510_FPGA_HOST_RESET               (OMAP1510_FPGA_BASE + 0xa)
+#define OMAP1510_FPGA_RST                      (OMAP1510_FPGA_BASE + 0xb)
+
+#define OMAP1510_FPGA_AUDIO                    (OMAP1510_FPGA_BASE + 0xc)
+#define OMAP1510_FPGA_DIP                      (OMAP1510_FPGA_BASE + 0xe)
+#define OMAP1510_FPGA_FPGA_IO                  (OMAP1510_FPGA_BASE + 0xf)
+#define OMAP1510_FPGA_UART1                    (OMAP1510_FPGA_BASE + 0x14)
+#define OMAP1510_FPGA_UART2                    (OMAP1510_FPGA_BASE + 0x15)
+#define OMAP1510_FPGA_OMAP1510_STATUS          (OMAP1510_FPGA_BASE + 0x16)
+#define OMAP1510_FPGA_BOARD_REV                        (OMAP1510_FPGA_BASE + 0x18)
+#define OMAP1510P1_PPT_DATA                    (OMAP1510_FPGA_BASE + 0x100)
+#define OMAP1510P1_PPT_STATUS                  (OMAP1510_FPGA_BASE + 0x101)
+#define OMAP1510P1_PPT_CONTROL                 (OMAP1510_FPGA_BASE + 0x102)
+
+#define OMAP1510_FPGA_TOUCHSCREEN              (OMAP1510_FPGA_BASE + 0x204)
+
+#define INNOVATOR_FPGA_INFO                    (OMAP1510_FPGA_BASE + 0x205)
+#define INNOVATOR_FPGA_LCD_BRIGHT_LO           (OMAP1510_FPGA_BASE + 0x206)
+#define INNOVATOR_FPGA_LCD_BRIGHT_HI           (OMAP1510_FPGA_BASE + 0x207)
+#define INNOVATOR_FPGA_LED_GRN_LO              (OMAP1510_FPGA_BASE + 0x208)
+#define INNOVATOR_FPGA_LED_GRN_HI              (OMAP1510_FPGA_BASE + 0x209)
+#define INNOVATOR_FPGA_LED_RED_LO              (OMAP1510_FPGA_BASE + 0x20a)
+#define INNOVATOR_FPGA_LED_RED_HI              (OMAP1510_FPGA_BASE + 0x20b)
+#define INNOVATOR_FPGA_CAM_USB_CONTROL         (OMAP1510_FPGA_BASE + 0x20c)
+#define INNOVATOR_FPGA_EXP_CONTROL             (OMAP1510_FPGA_BASE + 0x20d)
+#define INNOVATOR_FPGA_ISR2                    (OMAP1510_FPGA_BASE + 0x20e)
+#define INNOVATOR_FPGA_IMR2                    (OMAP1510_FPGA_BASE + 0x210)
+
+#define OMAP1510_FPGA_ETHR_START               (OMAP1510_FPGA_START + 0x300)
+#define OMAP1510_FPGA_ETHR_BASE                        (OMAP1510_FPGA_BASE + 0x300)
+
+/*
+ * Power up Giga UART driver, turn on HID clock.
+ * Turn off BT power, since we're not using it and it
+ * draws power.
+ */
+#define OMAP1510_FPGA_RESET_VALUE              0x42
+
+#define OMAP1510_FPGA_PCR_IF_PD0               (1 << 7)
+#define OMAP1510_FPGA_PCR_COM2_EN              (1 << 6)
+#define OMAP1510_FPGA_PCR_COM1_EN              (1 << 5)
+#define OMAP1510_FPGA_PCR_EXP_PD0              (1 << 4)
+#define OMAP1510_FPGA_PCR_EXP_PD1              (1 << 3)
+#define OMAP1510_FPGA_PCR_48MHZ_CLK            (1 << 2)
+#define OMAP1510_FPGA_PCR_4MHZ_CLK             (1 << 1)
+#define OMAP1510_FPGA_PCR_RSRVD_BIT0           (1 << 0)
+
+/*
+ * Innovator/OMAP1510 FPGA HID register bit definitions
+ */
+#define OMAP1510_FPGA_HID_SCLK (1<<0)  /* output */
+#define OMAP1510_FPGA_HID_MOSI (1<<1)  /* output */
+#define OMAP1510_FPGA_HID_nSS  (1<<2)  /* output 0/1 chip idle/select */
+#define OMAP1510_FPGA_HID_nHSUS        (1<<3)  /* output 0/1 host active/suspended */
+#define OMAP1510_FPGA_HID_MISO (1<<4)  /* input */
+#define OMAP1510_FPGA_HID_ATN  (1<<5)  /* input  0/1 chip idle/ATN */
+#define OMAP1510_FPGA_HID_rsrvd        (1<<6)
+#define OMAP1510_FPGA_HID_RESETn (1<<7)        /* output - 0/1 USAR reset/run */
+
+/* The FPGA IRQ is cascaded through GPIO_13 */
+#define OMAP1510_INT_FPGA              (IH_GPIO_BASE + 13)
+
+/* IRQ Numbers for interrupts muxed through the FPGA */
+#define OMAP1510_IH_FPGA_BASE          IH_BOARD_BASE
+#define OMAP1510_INT_FPGA_ATN          (OMAP1510_IH_FPGA_BASE + 0)
+#define OMAP1510_INT_FPGA_ACK          (OMAP1510_IH_FPGA_BASE + 1)
+#define OMAP1510_INT_FPGA2             (OMAP1510_IH_FPGA_BASE + 2)
+#define OMAP1510_INT_FPGA3             (OMAP1510_IH_FPGA_BASE + 3)
+#define OMAP1510_INT_FPGA4             (OMAP1510_IH_FPGA_BASE + 4)
+#define OMAP1510_INT_FPGA5             (OMAP1510_IH_FPGA_BASE + 5)
+#define OMAP1510_INT_FPGA6             (OMAP1510_IH_FPGA_BASE + 6)
+#define OMAP1510_INT_FPGA7             (OMAP1510_IH_FPGA_BASE + 7)
+#define OMAP1510_INT_FPGA8             (OMAP1510_IH_FPGA_BASE + 8)
+#define OMAP1510_INT_FPGA9             (OMAP1510_IH_FPGA_BASE + 9)
+#define OMAP1510_INT_FPGA10            (OMAP1510_IH_FPGA_BASE + 10)
+#define OMAP1510_INT_FPGA11            (OMAP1510_IH_FPGA_BASE + 11)
+#define OMAP1510_INT_FPGA12            (OMAP1510_IH_FPGA_BASE + 12)
+#define OMAP1510_INT_ETHER             (OMAP1510_IH_FPGA_BASE + 13)
+#define OMAP1510_INT_FPGAUART1         (OMAP1510_IH_FPGA_BASE + 14)
+#define OMAP1510_INT_FPGAUART2         (OMAP1510_IH_FPGA_BASE + 15)
+#define OMAP1510_INT_FPGA_TS           (OMAP1510_IH_FPGA_BASE + 16)
+#define OMAP1510_INT_FPGA17            (OMAP1510_IH_FPGA_BASE + 17)
+#define OMAP1510_INT_FPGA_CAM          (OMAP1510_IH_FPGA_BASE + 18)
+#define OMAP1510_INT_FPGA_RTC_A                (OMAP1510_IH_FPGA_BASE + 19)
+#define OMAP1510_INT_FPGA_RTC_B                (OMAP1510_IH_FPGA_BASE + 20)
+#define OMAP1510_INT_FPGA_CD           (OMAP1510_IH_FPGA_BASE + 21)
+#define OMAP1510_INT_FPGA22            (OMAP1510_IH_FPGA_BASE + 22)
+#define OMAP1510_INT_FPGA23            (OMAP1510_IH_FPGA_BASE + 23)
 
 #endif
diff --git a/include/asm-arm/arch-omap/mcbsp.h b/include/asm-arm/arch-omap/mcbsp.h
new file mode 100644 (file)
index 0000000..8e490e3
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * linux/include/asm-arm/arch-omap/gpio.h
+ *
+ * Defines for Multi-Channel Buffered Serial Port
+ *
+ * Copyright (C) 2002 RidgeRun, Inc.
+ * Author: Steve Johnson
+ *
+ * This program is free software; you can redistribute 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_OMAP_MCBSP_H
+#define __ASM_ARCH_OMAP_MCBSP_H
+
+#include <asm/arch/hardware.h>
+
+#define OMAP730_MCBSP1_BASE    0xfffb1000
+#define OMAP730_MCBSP2_BASE    0xfffb1800
+
+#define OMAP1510_MCBSP1_BASE   0xe1011000
+#define OMAP1510_MCBSP2_BASE   0xfffb1000
+#define OMAP1510_MCBSP3_BASE   0xe1017000
+
+#define OMAP1610_MCBSP1_BASE   0xe1011800
+#define OMAP1610_MCBSP2_BASE   0xfffb1000
+#define OMAP1610_MCBSP3_BASE   0xe1017000
+
+#define OMAP_MCBSP_REG_DRR2    0x00
+#define OMAP_MCBSP_REG_DRR1    0x02
+#define OMAP_MCBSP_REG_DXR2    0x04
+#define OMAP_MCBSP_REG_DXR1    0x06
+#define OMAP_MCBSP_REG_SPCR2   0x08
+#define OMAP_MCBSP_REG_SPCR1   0x0a
+#define OMAP_MCBSP_REG_RCR2    0x0c
+#define OMAP_MCBSP_REG_RCR1    0x0e
+#define OMAP_MCBSP_REG_XCR2    0x10
+#define OMAP_MCBSP_REG_XCR1    0x12
+#define OMAP_MCBSP_REG_SRGR2   0x14
+#define OMAP_MCBSP_REG_SRGR1   0x16
+#define OMAP_MCBSP_REG_MCR2    0x18
+#define OMAP_MCBSP_REG_MCR1    0x1a
+#define OMAP_MCBSP_REG_RCERA   0x1c
+#define OMAP_MCBSP_REG_RCERB   0x1e
+#define OMAP_MCBSP_REG_XCERA   0x20
+#define OMAP_MCBSP_REG_XCERB   0x22
+#define OMAP_MCBSP_REG_PCR0    0x24
+#define OMAP_MCBSP_REG_RCERC   0x26
+#define OMAP_MCBSP_REG_RCERD   0x28
+#define OMAP_MCBSP_REG_XCERC   0x2A
+#define OMAP_MCBSP_REG_XCERD   0x2C
+#define OMAP_MCBSP_REG_RCERE   0x2E
+#define OMAP_MCBSP_REG_RCERF   0x30
+#define OMAP_MCBSP_REG_XCERE   0x32
+#define OMAP_MCBSP_REG_XCERF   0x34
+#define OMAP_MCBSP_REG_RCERG   0x36
+#define OMAP_MCBSP_REG_RCERH   0x38
+#define OMAP_MCBSP_REG_XCERG   0x3A
+#define OMAP_MCBSP_REG_XCERH   0x3C
+
+#define OMAP_MAX_MCBSP_COUNT 3
+
+#define OMAP_MCBSP_READ(base, reg)             __raw_readw((base) + OMAP_MCBSP_REG_##reg)
+#define OMAP_MCBSP_WRITE(base, reg, val)       __raw_writew((val), (base) + OMAP_MCBSP_REG_##reg)
+
+/************************** McBSP SPCR1 bit definitions ***********************/
+#define RRST                   0x0001
+#define RRDY                   0x0002
+#define RFULL                  0x0004
+#define RSYNC_ERR              0x0008
+#define RINTM(value)           ((value)<<4)    /* bits 4:5 */
+#define ABIS                   0x0040
+#define DXENA                  0x0080
+#define CLKSTP(value)          ((value)<<11)   /* bits 11:12 */
+#define RJUST(value)           ((value)<<13)   /* bits 13:14 */
+#define DLB                    0x8000
+
+/************************** McBSP SPCR2 bit definitions ***********************/
+#define XRST           0x0001
+#define XRDY           0x0002
+#define XEMPTY         0x0004
+#define XSYNC_ERR      0x0008
+#define XINTM(value)   ((value)<<4)            /* bits 4:5 */
+#define GRST           0x0040
+#define FRST           0x0080
+#define SOFT           0x0100
+#define FREE           0x0200
+
+/************************** McBSP PCR bit definitions *************************/
+#define CLKRP          0x0001
+#define CLKXP          0x0002
+#define FSRP           0x0004
+#define FSXP           0x0008
+#define DR_STAT                0x0010
+#define DX_STAT                0x0020
+#define CLKS_STAT      0x0040
+#define SCLKME         0x0080
+#define CLKRM          0x0100
+#define CLKXM          0x0200
+#define FSRM           0x0400
+#define FSXM           0x0800
+#define RIOEN          0x1000
+#define XIOEN          0x2000
+#define IDLE_EN                0x4000
+
+/************************** McBSP RCR1 bit definitions ************************/
+#define RWDLEN1(value)         ((value)<<5)    /* Bits 5:7 */
+#define RFRLEN1(value)         ((value)<<8)    /* Bits 8:14 */
+
+/************************** McBSP XCR1 bit definitions ************************/
+#define XWDLEN1(value)         ((value)<<5)    /* Bits 5:7 */
+#define XFRLEN1(value)         ((value)<<8)    /* Bits 8:14 */
+
+/*************************** McBSP RCR2 bit definitions ***********************/
+#define RDATDLY(value)         (value)         /* Bits 0:1 */
+#define RFIG                   0x0004
+#define RCOMPAND(value)                ((value)<<3)    /* Bits 3:4 */
+#define RWDLEN2(value)         ((value)<<5)    /* Bits 5:7 */
+#define RFRLEN2(value)         ((value)<<8)    /* Bits 8:14 */
+#define RPHASE                 0x8000
+
+/*************************** McBSP XCR2 bit definitions ***********************/
+#define XDATDLY(value)         (value)         /* Bits 0:1 */
+#define XFIG                   0x0004
+#define XCOMPAND(value)                ((value)<<3)    /* Bits 3:4 */
+#define XWDLEN2(value)         ((value)<<5)    /* Bits 5:7 */
+#define XFRLEN2(value)         ((value)<<8)    /* Bits 8:14 */
+#define XPHASE                 0x8000
+
+/************************* McBSP SRGR1 bit definitions ************************/
+#define CLKGDV(value)          (value)         /* Bits 0:7 */
+#define FWID(value)            ((value)<<8)    /* Bits 8:15 */
+
+/************************* McBSP SRGR2 bit definitions ************************/
+#define FPER(value)            (value)         /* Bits 0:11 */
+#define FSGM                   0x1000
+#define CLKSM                  0x2000
+#define CLKSP                  0x4000
+#define GSYNC                  0x8000
+
+/************************* McBSP MCR1 bit definitions *************************/
+#define RMCM                   0x0001
+#define RCBLK(value)           ((value)<<2)    /* Bits 2:4 */
+#define RPABLK(value)          ((value)<<5)    /* Bits 5:6 */
+#define RPBBLK(value)          ((value)<<7)    /* Bits 7:8 */
+
+/************************* McBSP MCR2 bit definitions *************************/
+#define XMCM(value)            (value)         /* Bits 0:1 */
+#define XCBLK(value)           ((value)<<2)    /* Bits 2:4 */
+#define XPABLK(value)          ((value)<<5)    /* Bits 5:6 */
+#define XPBBLK(value)          ((value)<<7)    /* Bits 7:8 */
+
+
+/* we don't do multichannel for now */
+struct omap_mcbsp_reg_cfg {
+       u16 spcr2;
+       u16 spcr1;
+       u16 rcr2;
+       u16 rcr1;
+       u16 xcr2;
+       u16 xcr1;
+       u16 srgr2;
+       u16 srgr1;
+       u16 mcr2;
+       u16 mcr1;
+       u16 pcr0;
+       u16 rcerc;
+       u16 rcerd;
+       u16 xcerc;
+       u16 xcerd;
+       u16 rcere;
+       u16 rcerf;
+       u16 xcere;
+       u16 xcerf;
+       u16 rcerg;
+       u16 rcerh;
+       u16 xcerg;
+       u16 xcerh;
+};
+
+typedef enum {
+       OMAP_MCBSP1 = 0,
+       OMAP_MCBSP2,
+       OMAP_MCBSP3,
+} omap_mcbsp_id;
+
+typedef enum {
+       OMAP_MCBSP_WORD_8 = 0,
+       OMAP_MCBSP_WORD_12,
+       OMAP_MCBSP_WORD_16,
+       OMAP_MCBSP_WORD_20,
+       OMAP_MCBSP_WORD_24,
+       OMAP_MCBSP_WORD_32,
+} omap_mcbsp_word_length;
+
+typedef enum {
+       OMAP_MCBSP_CLK_RISING = 0,
+       OMAP_MCBSP_CLK_FALLING,
+} omap_mcbsp_clk_polarity;
+
+typedef enum {
+       OMAP_MCBSP_FS_ACTIVE_HIGH = 0,
+       OMAP_MCBSP_FS_ACTIVE_LOW,
+} omap_mcbsp_fs_polarity;
+
+typedef enum {
+       OMAP_MCBSP_CLK_STP_MODE_NO_DELAY = 0,
+       OMAP_MCBSP_CLK_STP_MODE_DELAY,
+} omap_mcbsp_clk_stp_mode;
+
+
+/******* SPI specific mode **********/
+typedef enum {
+       OMAP_MCBSP_SPI_MASTER = 0,
+       OMAP_MCBSP_SPI_SLAVE,
+} omap_mcbsp_spi_mode;
+
+struct omap_mcbsp_spi_cfg {
+       omap_mcbsp_spi_mode             spi_mode;
+       omap_mcbsp_clk_polarity         rx_clock_polarity;
+       omap_mcbsp_clk_polarity         tx_clock_polarity;
+       omap_mcbsp_fs_polarity          fsx_polarity;
+       u8                              clk_div;
+       omap_mcbsp_clk_stp_mode         clk_stp_mode;
+       omap_mcbsp_word_length          word_length;
+};
+
+void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
+int omap_mcbsp_request(unsigned int id);
+void omap_mcbsp_free(unsigned int id);
+void omap_mcbsp_start(unsigned int id);
+void omap_mcbsp_stop(unsigned int id);
+void omap_mcbsp_xmit_word(unsigned int id, u32 word);
+u32 omap_mcbsp_recv_word(unsigned int id);
+
+int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
+int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
+
+/* SPI specific API */
+void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
+
+#endif
index b135846..f491a48 100644 (file)
 #define OMAP1510_SRAM_SIZE     (SZ_128K + SZ_64K)
 #define OMAP1510_SRAM_START    0x20000000
 
-#define OMAP1510_MCBSP1_BASE   0xE1011000
-#define OMAP1510_MCBSP1_SIZE   SZ_4K
-#define OMAP1510_MCBSP1_START  0xE1011000
-
-#define OMAP1510_MCBSP2_BASE   0xFFFB1000
-
-#define OMAP1510_MCBSP3_BASE   0xE1017000
-#define OMAP1510_MCBSP3_SIZE   SZ_4K
-#define OMAP1510_MCBSP3_START  0xE1017000
-
 #define OMAP1510_DSP_BASE      0xE0000000
 #define OMAP1510_DSP_SIZE      0x28000
 #define OMAP1510_DSP_START     0xE0000000
 #define OMAP1510_DSPREG_SIZE   SZ_128K
 #define OMAP1510_DSPREG_START  0xE1000000
 
+/*
+ * ----------------------------------------------------------------------------
+ * Memory used by power management
+ * ----------------------------------------------------------------------------
+ */
+
+#define OMAP1510_SRAM_IDLE_SUSPEND     (OMAP1510_SRAM_BASE + OMAP1510_SRAM_SIZE - 0x200)
+#define OMAP1510_SRAM_API_SUSPEND      (OMAP1510_SRAM_IDLE_SUSPEND + 0x100)
+
 #endif /*  __ASM_ARCH_OMAP1510_H */
 
index 667a6f6..6b36752 100644 (file)
 #define OMAP1610_DSPREG_SIZE   SZ_128K
 #define OMAP1610_DSPREG_START  0xE1000000
 
+/*
+ * ----------------------------------------------------------------------------
+ * Memory used by power management
+ * ----------------------------------------------------------------------------
+ */
+
+#define OMAP1610_SRAM_IDLE_SUSPEND     (OMAP1610_SRAM_BASE + OMAP1610_SRAM_SIZE - 0x200)
+#define OMAP1610_SRAM_API_SUSPEND      (OMAP1610_SRAM_IDLE_SUSPEND + 0x100)
+
 /*
  * ---------------------------------------------------------------------------
  * Interrupts
index f996af7..76b554e 100644 (file)
 #define OMAP5912_DSPREG_SIZE   SZ_128K
 #define OMAP5912_DSPREG_START  0xE1000000
 
+/*
+ * ----------------------------------------------------------------------------
+ * Memory used by power management
+ * ----------------------------------------------------------------------------
+ */
+
+#define OMAP5912_SRAM_IDLE_SUSPEND     (OMAP5912_SRAM_BASE + OMAP5912_SRAM_SIZE - 0x200)
+#define OMAP5912_SRAM_API_SUSPEND      (OMAP5912_SRAM_IDLE_SUSPEND + 0x100)
+
 /*
  * ---------------------------------------------------------------------------
  * Interrupts
index 8ca7636..599ab00 100644 (file)
 #define OMAP730_SRAM_SIZE      (SZ_128K + SZ_64K + SZ_8K)
 #define OMAP730_SRAM_START     0x20000000
 
-#define OMAP730_MCBSP1_BASE    0xfffb1000
-#define OMAP730_MCBSP1_SIZE    (SZ_1K * 2)
-#define OMAP730_MCBSP1_START   0xfffb1000
-
-#define OMAP730_MCBSP2_BASE    0xfffb1800
-
 #define OMAP730_DSP_BASE       0xE0000000
 #define OMAP730_DSP_SIZE       0x50000
 #define OMAP730_DSP_START      0xE0000000
diff --git a/include/asm-arm/arch-omap/tps65010.h b/include/asm-arm/arch-omap/tps65010.h
new file mode 100644 (file)
index 0000000..0f97bb2
--- /dev/null
@@ -0,0 +1,80 @@
+/* linux/include/asm-arm/arch-omap/tps65010.h
+ *
+ * Functions to access TPS65010 power management device.
+ *
+ * Copyright (C) 2004 Dirk Behme <dirk.behme@de.bosch.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 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.
+ */
+
+#ifndef __ASM_ARCH_TPS65010_H
+#define __ASM_ARCH_TPS65010_H
+
+/*
+ * ----------------------------------------------------------------------------
+ * Macros used by exported functions
+ * ----------------------------------------------------------------------------
+ */
+
+#define LED1  1
+#define LED2  2
+#define OFF   0
+#define ON    1
+#define BLINK 2
+#define GPIO1 1
+#define GPIO2 2
+#define GPIO3 3
+#define GPIO4 4
+#define LOW   0
+#define HIGH  1
+
+/*
+ * ----------------------------------------------------------------------------
+ * Exported functions
+ * ----------------------------------------------------------------------------
+ */
+
+/* Draw from VBUS:
+ *   0 mA -- DON'T DRAW (might supply power instead)
+ * 100 mA -- usb unit load (slowest charge rate)
+ * 500 mA -- usb high power (fast battery charge)
+ */
+extern int tps65010_set_vbus_draw(unsigned mA);
+
+/* tps65010_set_gpio_out_value parameter:
+ * gpio:  GPIO1, GPIO2, GPIO3 or GPIO4
+ * value: LOW or HIGH
+ */
+extern int tps65010_set_gpio_out_value(unsigned gpio, unsigned value);
+
+/* tps65010_set_led parameter:
+ * led:  LED1 or LED2
+ * mode: ON, OFF or BLINK
+ */
+extern int tps65010_set_led(unsigned led, unsigned mode);
+
+/* tps65010_set_low_pwr parameter:
+ * mode: ON or OFF
+ */
+extern int tps65010_set_low_pwr(unsigned mode);
+
+#endif /*  __ASM_ARCH_TPS65010_H */
+
diff --git a/include/asm-arm/arch-omap/usb.h b/include/asm-arm/arch-omap/usb.h
new file mode 100644 (file)
index 0000000..1438c6c
--- /dev/null
@@ -0,0 +1,108 @@
+// include/asm-arm/mach-omap/usb.h
+
+#ifndef        __ASM_ARCH_OMAP_USB_H
+#define        __ASM_ARCH_OMAP_USB_H
+
+#include <asm/arch/board.h>
+
+/*-------------------------------------------------------------------------*/
+
+#define OTG_BASE                       0xfffb0400
+#define UDC_BASE                       0xfffb4000
+#define OMAP_OHCI_BASE                 0xfffba000
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * OTG and transceiver registers, for OMAPs starting with ARM926
+ */
+#define OTG_REG32(offset)              __REG32(OTG_BASE + (offset))
+#define OTG_REG16(offset)              __REG16(OTG_BASE + (offset))
+
+#define OTG_REV_REG                    OTG_REG32(0x00)
+#define OTG_SYSCON_1_REG               OTG_REG32(0x04)
+#      define   USB2_TRX_MODE(w)       (((w)>>24)&0x07)
+#      define   USB1_TRX_MODE(w)       (((w)>>20)&0x07)
+#      define   USB0_TRX_MODE(w)       (((w)>>16)&0x07)
+#      define   OTG_IDLE_EN            (1 << 15)
+#      define   HST_IDLE_EN            (1 << 14)
+#      define   DEV_IDLE_EN            (1 << 13)
+#      define   OTG_RESET_DONE         (1 << 2)
+#define OTG_SYSCON_2_REG               OTG_REG32(0x08)
+#      define   OTG_EN                 (1 << 31)
+#      define   USBX_SYNCHRO           (1 << 30)
+#      define   OTG_MST16              (1 << 29)
+#      define   SRP_GPDATA             (1 << 28)
+#      define   SRP_GPDVBUS            (1 << 27)
+#      define   SRP_GPUVBUS(w)         (((w)>>24)&0x07)
+#      define   A_WAIT_VRISE(w)        (((w)>>20)&0x07)
+#      define   B_ASE_BRST(w)          (((w)>>16)&0x07)
+#      define   SRP_DPW                (1 << 14)
+#      define   SRP_DATA               (1 << 13)
+#      define   SRP_VBUS               (1 << 12)
+#      define   OTG_PADEN              (1 << 10)
+#      define   HMC_PADEN              (1 << 9)
+#      define   UHOST_EN               (1 << 8)
+#      define   HMC_TLLSPEED           (1 << 7)
+#      define   HMC_TLLATTACH          (1 << 6)
+#      define   OTG_HMC(w)             (((w)>>0)&0x3f)
+#define OTG_CTRL_REG                   OTG_REG32(0x0c)
+#      define   OTG_ASESSVLD           (1 << 20)
+#      define   OTG_BSESSEND           (1 << 19)
+#      define   OTG_BSESSVLD           (1 << 18)
+#      define   OTG_VBUSVLD            (1 << 17)
+#      define   OTG_ID                 (1 << 16)
+#      define   OTG_DRIVER_SEL         (1 << 15)
+#      define   OTG_A_SETB_HNPEN       (1 << 12)
+#      define   OTG_A_BUSREQ           (1 << 11)
+#      define   OTG_B_HNPEN            (1 << 9)
+#      define   OTG_B_BUSREQ           (1 << 8)
+#      define   OTG_BUSDROP            (1 << 7)
+#      define   OTG_PULLDOWN           (1 << 5)
+#      define   OTG_PULLUP             (1 << 4)
+#      define   OTG_DRV_VBUS           (1 << 3)
+#      define   OTG_PD_VBUS            (1 << 2)
+#      define   OTG_PU_VBUS            (1 << 1)
+#      define   OTG_PU_ID              (1 << 0)
+#define OTG_IRQ_EN_REG                 OTG_REG16(0x10)
+#      define   DRIVER_SWITCH          (1 << 15)
+#      define   A_VBUS_ERR             (1 << 13)
+#      define   A_REQ_TMROUT           (1 << 12)
+#      define   A_SRP_DETECT           (1 << 11)
+#      define   B_HNP_FAIL             (1 << 10)
+#      define   B_SRP_TMROUT           (1 << 9)
+#      define   B_SRP_DONE             (1 << 8)
+#      define   B_SRP_STARTED          (1 << 7)
+#      define   OPRT_CHG               (1 << 0)
+#define OTG_IRQ_SRC_REG                        OTG_REG16(0x14)
+       // same bits as in IRQ_EN
+#define OTG_OUTCTRL_REG                        OTG_REG16(0x18)
+#      define   OTGVPD                 (1 << 14)
+#      define   OTGVPU                 (1 << 13)
+#      define   OTGPUID                (1 << 12)
+#      define   USB2VDR                (1 << 10)
+#      define   USB2PDEN               (1 << 9)
+#      define   USB2PUEN               (1 << 8)
+#      define   USB1VDR                (1 << 6)
+#      define   USB1PDEN               (1 << 5)
+#      define   USB1PUEN               (1 << 4)
+#      define   USB0VDR                (1 << 2)
+#      define   USB0PDEN               (1 << 1)
+#      define   USB0PUEN               (1 << 0)
+#define OTG_TEST_REG                   OTG_REG16(0x20)
+#define OTG_VENDOR_CODE_REG            OTG_REG32(0xfc)
+
+/*-------------------------------------------------------------------------*/
+
+#define        USB_TRANSCEIVER_CTRL_REG        __REG32(0xfffe1000 + 0x0064)
+#      define  CONF_USB2_UNI_R         (1 << 8)
+#      define  CONF_USB1_UNI_R         (1 << 7)
+#      define  CONF_USB_PORT0_R(x)     (((x)>>4)&0x7)
+#      define  CONF_USB0_ISOLATE_R     (1 << 3)
+#      define  CONF_USB_PWRDN_DM_R     (1 << 2)
+#      define  CONF_USB_PWRDN_DP_R     (1 << 1)
+
+
+
+
+#endif /* __ASM_ARCH_OMAP_USB_H */
diff --git a/include/asm-arm/arch-pxa/mmc.h b/include/asm-arm/arch-pxa/mmc.h
new file mode 100644 (file)
index 0000000..7492ea7
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef ASMARM_ARCH_MMC_H
+#define ASMARM_ARCH_MMC_H
+
+#include <linux/mmc/protocol.h>
+#include <linux/interrupt.h>
+
+struct device;
+struct mmc_host;
+
+struct pxamci_platform_data {
+       unsigned int ocr_mask;                  /* available voltages */
+       int (*init)(struct device *, irqreturn_t (*)(int, void *, struct pt_regs *), void *);
+       void (*setpower)(struct device *, unsigned int);
+       void (*exit)(struct device *, void *);
+};
+
+extern void pxa_set_mci_info(struct pxamci_platform_data *info);
+
+#endif
index 3ef5d80..1d06b3b 100644 (file)
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <asm/arch/pxa-regs.h>
 
 #define BAUD_BASE      921600
 
index 8d46644..840a46b 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include "hardware.h"
+#include "pxa-regs.h"
 
 static inline void arch_idle(void)
 {
index c4b906d..4428d3e 100644 (file)
@@ -25,7 +25,7 @@ static __inline__ void putc(char c)
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
        while (*s) {
                putc(*s);
index 3f7a236..939aa6a 100644 (file)
  */
 #define __arch_base_getb(b,o)                  \
  ({                                            \
-       unsigned int v, r = (b);                \
+       unsigned int __v, __r = (b);            \
        __asm__ __volatile__(                   \
                "ldrb   %0, [%1, %2]"           \
-               : "=r" (v)                      \
-               : "r" (r), "Ir" (o));           \
-       v;                                      \
+               : "=r" (__v)                    \
+               : "r" (__r), "Ir" (o));         \
+       __v;                                    \
  })
 
 #define __arch_base_getl(b,o)                  \
  ({                                            \
-       unsigned int v, r = (b);                \
+       unsigned int __v, __r = (b);            \
        __asm__ __volatile__(                   \
                "ldr    %0, [%1, %2]"           \
-               : "=r" (v)                      \
-               : "r" (r), "Ir" (o));           \
-       v;                                      \
+               : "=r" (__v)                    \
+               : "r" (__r), "Ir" (o));         \
+       __v;                                    \
  })
 
 #define __arch_base_putb(v,b,o)                        \
  ({                                            \
-       unsigned int r = (b);                   \
+       unsigned int __r = (b);                 \
        __asm__ __volatile__(                   \
                "strb   %0, [%1, %2]"           \
                :                               \
-               : "r" (v), "r" (r), "Ir" (o));  \
+               : "r" (v), "r" (__r), "Ir" (o));\
  })
 
 #define __arch_base_putl(v,b,o)                        \
  ({                                            \
-       unsigned int r = (b);                   \
+       unsigned int __r = (b);                 \
        __asm__ __volatile__(                   \
                "str    %0, [%1, %2]"           \
                :                               \
-               : "r" (v), "r" (r), "Ir" (o));  \
+               : "r" (v), "r" (__r), "Ir" (o));\
  })
 
 /*
@@ -176,15 +176,15 @@ DECLARE_IO(int,l,"")
 
 #define __outwc(value,port)                                                    \
 ({                                                                             \
-       unsigned long v = value;                                                \
+       unsigned long __v = value;                                              \
        if (__PORT_PCIO((port)))                                                \
                __asm__ __volatile__(                                           \
                "str    %0, [%1, %2]    @ outwc"                                \
-               : : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));        \
+               : : "r" (__v|__v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));    \
        else                                                                    \
                __asm__ __volatile__(                                           \
                "str    %0, [%1, %2]    @ outwc"                                \
-               : : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2));           \
+               : : "r" (__v|__v<<16), "r" (IO_BASE), "r" ((port) << 2));               \
 })
 
 #define __inwc(port)                                                           \
@@ -203,15 +203,15 @@ DECLARE_IO(int,l,"")
 
 #define __outlc(value,port)                                                    \
 ({                                                                             \
-       unsigned long v = value;                                                \
+       unsigned long __v = value;                                              \
        if (__PORT_PCIO((port)))                                                \
                __asm__ __volatile__(                                           \
                "str    %0, [%1, %2]    @ outlc"                                \
-               : : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2));              \
+               : : "r" (__v), "r" (PCIO_BASE), "Jr" ((port) << 2));            \
        else                                                                    \
                __asm__ __volatile__(                                           \
                "str    %0, [%1, %2]    @ outlc"                                \
-               : : "r" (v), "r" (IO_BASE), "r" ((port) << 2));                 \
+               : : "r" (__v), "r" (IO_BASE), "r" ((port) << 2));                       \
 })
 
 #define __inlc(port)                                                           \
@@ -250,6 +250,6 @@ DECLARE_IO(int,l,"")
 /*
  * 1:1 mapping for ioremapped regions.
  */
-#define __mem_pci(x)   (x)
+#define __mem_pci(x)   ((unsigned long)(x))
 
 #endif
index cb1430a..e28ca51 100644 (file)
@@ -1,6 +1,6 @@
 /* linux/include/asm-arm/arch-s3c2410/bast-cpld.h
  *
- * (c) 2003 Simtec Electronics
+ * (c) 2003,2004 Simtec Electronics
  *  Ben Dooks <ben@simtec.co.uk>
  *
  * BAST - CPLD control constants
  *
  * Changelog:
  *  25-May-2003 BJD  Created file, added CTRL1 registers
+ *  30-Aug-2004 BJD  Updated definitions from 2.4.26 port
+ *  30-Aug-2004 BJD  Added CTRL3 and CTRL4 definitions
 */
 
 #ifndef __ASM_ARCH_BASTCPLD_H
 #define __ASM_ARCH_BASTCPLD_H
 
+/* CTRL1 - Audio LR routing */
+
 #define BAST_CPLD_CTRL1_LRCOFF     (0x00)
 #define BAST_CPLD_CTRL1_LRCADC     (0x01)
 #define BAST_CPLD_CTRL1_LRCDAC     (0x02)
 #define BAST_CPLD_CTRL1_LRCARM     (0x03)
 #define BAST_CPLD_CTRL1_LRMASK     (0x03)
 
+/* CTRL2 - NAND WP control, IDE Reset assert/check */
+
+#define BAST_CPLD_CTRL2_WNAND       (0x04)
+#define BAST_CPLD_CTLR2_IDERST      (0x08)
+
+/* CTRL3 - rom write control, CPLD identity */
+
+#define BAST_CPLD_CTRL3_IDMASK      (0x0e)
+#define BAST_CPLD_CTRL3_ROMWEN      (0x01)
+
+/* CTRL4 - 8bit LCD interface control/status */
+
+#define BAST_CPLD_CTRL4_LLAT       (0x01)
+#define BAST_CPLD_CTRL4_LCDRW      (0x02)
+#define BAST_CPLD_CTRL4_LCDCMD     (0x04)
+#define BAST_CPLD_CTRL4_LCDE2      (0x01)
+
+/* CTRL5 - DMA routing */
+
+#define BAST_CPLD_DMA0_PRIIDE      (0<<0)
+#define BAST_CPLD_DMA0_SECIDE      (1<<0)
+#define BAST_CPLD_DMA0_ISA15       (2<<0)
+#define BAST_CPLD_DMA0_ISA36       (3<<0)
+
+#define BAST_CPLD_DMA1_PRIIDE      (0<<2)
+#define BAST_CPLD_DMA1_SECIDE      (1<<2)
+#define BAST_CPLD_DMA1_ISA15       (2<<2)
+#define BAST_CPLD_DMA1_ISA36       (3<<2)
+
 #endif /* __ASM_ARCH_BASTCPLD_H */
index 5d74ca6..b79b47f 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  *
  * Changelog:
+ *  14-Sep-2004 BJD  Fixed IRQ_USBOC definition
  *  06-Jan-2003 BJD  Linux 2.6.0 version
  */
 
@@ -18,7 +19,7 @@
 
 /* irq numbers to onboard peripherals */
 
-#define IRQ_USBOC      IRQ_EINT19
+#define IRQ_USBOC      IRQ_EINT18
 #define IRQ_IDE0       IRQ_EINT16
 #define IRQ_IDE1       IRQ_EINT17
 #define IRQ_PCSERIAL1  IRQ_EINT15
index ea084c7..9cae382 100644 (file)
@@ -27,7 +27,7 @@
  *
  */
 #define MAX_DMA_ADDRESS                0x20000000
-#define MAX_DMA_TRANSFER_SIZE  0x100000 /* Data Unit is half word  */
+#define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
 
 
 /* according to the samsung port, we cannot use the regular
 
 
 /* we have 4 dma channels */
-#define S3C2410_DMA_CHANNELS       (4)
+#define S3C2410_DMA_CHANNELS        (4)
 
+/* types */
+
+typedef enum {
+       S3C2410_DMA_IDLE,
+       S3C2410_DMA_RUNNING,
+       S3C2410_DMA_PAUSED
+} s3c2410_dma_state_t;
+
+
+/* s3c2410_dma_loadst_t
+ *
+ * This represents the state of the DMA engine, wrt to the loaded / running
+ * transfers. Since we don't have any way of knowing exactly the state of
+ * the DMA transfers, we need to know the state to make decisions on wether
+ * we can
+ *
+ * S3C2410_DMA_NONE
+ *
+ * There are no buffers loaded (the channel should be inactive)
+ *
+ * S3C2410_DMA_1LOADED
+ *
+ * There is one buffer loaded, however it has not been confirmed to be
+ * loaded by the DMA engine. This may be because the channel is not
+ * yet running, or the DMA driver decided that it was too costly to
+ * sit and wait for it to happen.
+ *
+ * S3C2410_DMA_1RUNNING
+ *
+ * The buffer has been confirmed running, and not finisged
+ *
+ * S3C2410_DMA_1LOADED_1RUNNING
+ *
+ * There is a buffer waiting to be loaded by the DMA engine, and one
+ * currently running.
+*/
+
+typedef enum {
+       S3C2410_DMALOAD_NONE,
+       S3C2410_DMALOAD_1LOADED,
+       S3C2410_DMALOAD_1RUNNING,
+       S3C2410_DMALOAD_1LOADED_1RUNNING,
+} s3c2410_dma_loadst_t;
+
+typedef enum {
+       S3C2410_RES_OK,
+       S3C2410_RES_ERR,
+       S3C2410_RES_ABORT
+} s3c2410_dma_buffresult_t;
+
+
+typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t;
+
+enum s3c2410_dmasrc_e {
+       S3C2410_DMASRC_HW,      /* source is memory */
+       S3C2410_DMASRC_MEM      /* source is hardware */
+};
+
+/* enum s3c2410_chan_op_e
+ *
+ * operation codes passed to the DMA code by the user, and also used
+ * to inform the current channel owner of any changes to the system state
+*/
+
+enum s3c2410_chan_op_e {
+       S3C2410_DMAOP_START,
+       S3C2410_DMAOP_STOP,
+       S3C2410_DMAOP_PAUSE,
+       S3C2410_DMAOP_RESUME,
+       S3C2410_DMAOP_FLUSH,
+       S3C2410_DMAOP_TIMEOUT,           /* internal signal to handler */
+};
+
+typedef enum s3c2410_chan_op_e s3c2410_chan_op_t;
+
+/* flags */
+
+#define S3C2410_DMAF_SLOW         (1<<0)   /* slow, so don't worry about
+                                           * waiting for reloads */
+#define S3C2410_DMAF_AUTOSTART    (1<<1)   /* auto-start if buffer queued */
 
 /* dma buffer */
 
 typedef struct s3c2410_dma_buf_s s3c2410_dma_buf_t;
 
+struct s3c2410_dma_client {
+       char                *name;
+};
+
+typedef struct s3c2410_dma_client s3c2410_dma_client_t;
+
+/* s3c2410_dma_buf_s
+ *
+ * internally used buffer structure to describe a queued or running
+ * buffer.
+*/
+
 struct s3c2410_dma_buf_s {
        s3c2410_dma_buf_t   *next;
-       int                  magic;        /* magic */
-       int                  size;         /* buffer size in bytes */
-       dma_addr_t           data;         /* start of DMA data */
-       dma_addr_t           ptr;          /* where the DMA got to [1] */
-       int                  ref;
-       void                 *id;          /* client's id */
-       unsigned char        no_callback;  /* disable callback for buffer */
+       int                  magic;        /* magic */
+       int                  size;         /* buffer size in bytes */
+       dma_addr_t           data;         /* start of DMA data */
+       dma_addr_t           ptr;          /* where the DMA got to [1] */
+       void                *id;           /* client's id */
 };
 
 /* [1] is this updated for both recv/send modes? */
 
 typedef struct s3c2410_dma_chan_s s3c2410_dma_chan_t;
 
-typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size);
-typedef void (*s3c2410_dma_enfn_t)(s3c2410_dma_chan_t *, int on);
-typedef void (*s3c2410_dma_pausefn_t)(s3c2410_dma_chan_t *, int on);
+/* s3c2410_dma_cbfn_t
+ *
+ * buffer callback routine type
+*/
+
+typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size,
+                                  s3c2410_dma_buffresult_t result);
+
+typedef int  (*s3c2410_dma_opfn_t)(s3c2410_dma_chan_t *,
+                                  s3c2410_chan_op_t );
+
+struct s3c2410_dma_stats_s {
+       unsigned long          loads;
+       unsigned long          timeout_longest;
+       unsigned long          timeout_shortest;
+       unsigned long          timeout_avg;
+       unsigned long          timeout_failed;
+};
+
+typedef struct s3c2410_dma_stats_s s3c2410_dma_stats_t;
+
+/* struct s3c2410_dma_chan_s
+ *
+ * full state information for each DMA channel
+*/
 
 struct s3c2410_dma_chan_s {
-       /* channel state flags */
-       unsigned char          number;        /* number of this dma channel */
-       unsigned char          in_use;        /* channel allocated */
-       unsigned char          started;       /* channel has been started */
-       unsigned char          stopped;       /* channel stopped */
-       unsigned char          sleeping;
-       unsigned char          xfer_unit;     /* size of an transfer */
-       unsigned char          irq_claimed;
+       /* channel state flags and information */
+       unsigned char          number;      /* number of this dma channel */
+       unsigned char          in_use;      /* channel allocated */
+       unsigned char          irq_claimed; /* irq claimed for channel */
+       unsigned char          irq_enabled; /* irq enabled for channel */
+       unsigned char          xfer_unit;   /* size of an transfer */
+
+       /* channel state */
+
+       s3c2410_dma_state_t    state;
+       s3c2410_dma_loadst_t   load_state;
+       s3c2410_dma_client_t  *client;
+
+       /* channel configuration */
+       s3c2410_dmasrc_t       source;
+       unsigned long          dev_addr;
+       unsigned long          load_timeout;
+       unsigned int           flags;        /* channel flags */
 
        /* channel's hardware position and configuration */
-       unsigned long          regs;          /* channels registers */
-       unsigned int           irq;           /* channel irq */
-       unsigned long          addr_reg;      /* data address register for buffs */
-       unsigned long          dcon;          /* default value of DCON */
+       unsigned long          regs;         /* channels registers */
+       unsigned int           irq;          /* channel irq */
+       unsigned long          addr_reg;     /* data address register */
+       unsigned long          dcon;         /* default value of DCON */
 
-       /* driver handlers for channel */
-       s3c2410_dma_cbfn_t     callback_fn;   /* callback function for buf-done */
-       s3c2410_dma_enfn_t     enable_fn;     /* channel enable function */
-       s3c2410_dma_pausefn_t  pause_fn;      /* channel pause function */
+       /* driver handles */
+       s3c2410_dma_cbfn_t     callback_fn;  /* buffer done callback */
+       s3c2410_dma_opfn_t     op_fn;        /* channel operation callback */
 
-       /* buffer list and information */
-       s3c2410_dma_buf_t      *curr;         /* current dma buffer */
-       s3c2410_dma_buf_t      *next;         /* next buffer to load */
-       s3c2410_dma_buf_t      *end;          /* end of queue */
+       /* stats gathering */
+       s3c2410_dma_stats_t   *stats;
+       s3c2410_dma_stats_t    stats_store;
 
-       int                    queue_count;   /* number of items in queue */
-       int                    loaded_count;  /* number of loaded buffers */
+       /* buffer list and information */
+       s3c2410_dma_buf_t      *curr;        /* current dma buffer */
+       s3c2410_dma_buf_t      *next;        /* next buffer to load */
+       s3c2410_dma_buf_t      *end;         /* end of queue */
 };
 
-/* note, we don't really use dma_deivce_t at the moment */
+/* the currently allocated channel information */
+extern s3c2410_dma_chan_t s3c2410_chans[];
+
+/* note, we don't really use dma_device_t at the moment */
 typedef unsigned long dma_device_t;
 
-typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t;
+/* functions --------------------------------------------------------------- */
 
-/* these two defines control the source for the dma channel,
- * wether it is from memory or an device
+/* s3c2410_dma_request
+ *
+ * request a dma channel exclusivley
 */
 
-enum s3c2410_dmasrc_e {
-  S3C2410_DMASRC_HW,     /* source is memory */
-  S3C2410_DMASRC_MEM     /* source is hardware */
-};
+extern int s3c2410_dma_request(dmach_t channel,
+                              s3c2410_dma_client_t *, void *dev);
+
+
+/* s3c2410_dma_ctrl
+ *
+ * change the state of the dma channel
+*/
+
+extern int s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op);
+
+/* s3c2410_dma_setflags
+ *
+ * set the channel's flags to a given state
+*/
 
-/* dma control routines */
+extern int s3c2410_dma_setflags(dmach_t channel,
+                               unsigned int flags);
 
-extern int s3c2410_request_dma(dmach_t channel, const char *devid, void *dev);
-extern int s3c2410_free_dma(dmach_t channel);
-extern int s3c2410_dma_flush_all(dmach_t channel);
+/* s3c2410_dma_free
+ *
+ * free the dma channel (will also abort any outstanding operations)
+*/
 
-extern int s3c2410_dma_stop(dmach_t channel);
-extern int s3c2410_dma_resume(dmach_t channel);
+extern int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *);
 
-extern int s3c2410_dma_queue(dmach_t channel, void *id,
-                            dma_addr_t data, int size);
+/* s3c2410_dma_enqueue
+ *
+ * place the given buffer onto the queue of operations for the channel.
+ * The buffer must be allocated from dma coherent memory, or the Dcache/WB
+ * drained before the buffer is given to the DMA system.
+*/
 
-#define s3c2410_dma_queue_buffer s3c2410_dma_queue
+extern int s3c2410_dma_enqueue(dmach_t channel, void *id,
+                              dma_addr_t data, int size);
 
-/* channel configuration */
+/* s3c2410_dma_config
+ *
+ * configure the dma channel
+*/
 
 extern int s3c2410_dma_config(dmach_t channel, int xferunit, int dcon);
 
+/* s3c2410_dma_devconfig
+ *
+ * configure the device we're talking to
+*/
+
 extern int s3c2410_dma_devconfig(int channel, s3c2410_dmasrc_t source,
                                 int hwcfg, unsigned long devaddr);
 
-extern int s3c2410_dma_set_enablefn(dmach_t, s3c2410_dma_enfn_t rtn);
-extern int s3c2410_dma_set_pausefn(dmach_t, s3c2410_dma_pausefn_t rtn);
-extern int s3c2410_dma_set_callbackfn(dmach_t, s3c2410_dma_cbfn_t rtn);
+extern int s3c2410_dma_set_opfn(dmach_t, s3c2410_dma_opfn_t rtn);
+extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
 
-#define s3c2410_dma_set_callback s3c2410_dma_set_callbackfn
+/* DMA Register definitions */
 
-#define S3C2410_DMA_DISRC      (0x00)
-#define S3C2410_DMA_DISRCC     (0x04)
-#define S3C2410_DMA_DIDST      (0x08)
-#define S3C2410_DMA_DIDSTC     (0x0C)
-#define S3C2410_DMA_DCON       (0x10)
-#define S3C2410_DMA_DSTAT      (0x14)
-#define S3C2410_DMA_DCSRC      (0x18)
-#define S3C2410_DMA_DCDST      (0x1C)
-#define S3C2410_DMA_DMASKTRIG  (0x20)
+#define S3C2410_DMA_DISRC       (0x00)
+#define S3C2410_DMA_DISRCC      (0x04)
+#define S3C2410_DMA_DIDST       (0x08)
+#define S3C2410_DMA_DIDSTC      (0x0C)
+#define S3C2410_DMA_DCON        (0x10)
+#define S3C2410_DMA_DSTAT       (0x14)
+#define S3C2410_DMA_DCSRC       (0x18)
+#define S3C2410_DMA_DCDST       (0x1C)
+#define S3C2410_DMA_DMASKTRIG   (0x20)
 
-#define S3C2410_DMASKTRIG_STOP  (1<<2)
-#define S3C2410_DMASKTRIG_ON    (1<<1)
+#define S3C2410_DMASKTRIG_STOP   (1<<2)
+#define S3C2410_DMASKTRIG_ON     (1<<1)
 #define S3C2410_DMASKTRIG_SWTRIG (1<<0)
 
-#define S3C2410_DCOM_DEMAND    (0<<31)
+#define S3C2410_DCOM_DEMAND     (0<<31)
 #define S3C2410_DCON_HANDSHAKE  (1<<31)
 #define S3C2410_DCON_SYNC_PCLK  (0<<30)
 #define S3C2410_DCON_SYNC_HCLK  (1<<30)
 
-#define S3C2410_DCON_INTREQ    (1<<29)
+#define S3C2410_DCON_INTREQ     (1<<29)
 
-#define S3C2410_DCON_SRCSHIFT  (24)
+#define S3C2410_DCON_SRCSHIFT   (24)
 
-#define S3C2410_DCON_BYTE      (0<<20)
-#define S3C2410_DCON_HALFWORD  (1<<20)
-#define S3C2410_DCON_WORD      (2<<20)
+#define S3C2410_DCON_BYTE       (0<<20)
+#define S3C2410_DCON_HALFWORD   (1<<20)
+#define S3C2410_DCON_WORD       (2<<20)
 
 #define S3C2410_DCON_AUTORELOAD (0<<22)
-#define S3C2410_DCON_HWTRIG    (1<<23)
+#define S3C2410_DCON_NORELOAD   (1<<22)
+#define S3C2410_DCON_HWTRIG     (1<<23)
 
 #endif /* __ASM_ARCH_DMA_H */
index d434d77..5b58f2a 100644 (file)
@@ -14,6 +14,8 @@
  *  06-Jun-2003 BJD  Added CPU frequency settings
  *  03-Sep-2003 BJD  Linux v2.6 support
  *  12-Mar-2004 BJD  Fixed include protection, fixed type of clock vars
+ *  14-Sep-2004 BJD  Added misccr and getpin to gpio
+ *  01-Oct-2004 BJD  Added the new gpio functions
 */
 
 #ifndef __ASM_ARCH_HARDWARE_H
@@ -44,6 +46,35 @@ extern unsigned long s3c2410_fclk;
 
 extern void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
 
+extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
+
+/* s3c2410_gpio_getirq
+ *
+ * turn the given pin number into the corresponding IRQ number
+ *
+ * returns:
+ *     < 0 = no interrupt for this pin
+ *     >=0 = interrupt number for the pin
+*/
+
+extern int s3c2410_gpio_getirq(unsigned int pin);
+
+/* s3c2410_gpio_irqfilter
+ *
+ * set the irq filtering on the given pin
+ *
+ * on = 0 => disable filtering
+ *      1 => enable filtering
+ *
+ * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
+ *          width of filter (0 through 63)
+ *
+ *
+*/
+
+extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+                                 unsigned int config);
+
 /* s3c2410_gpio_pullup
  *
  * configure the pull-up control on the given pin
@@ -61,6 +92,10 @@ extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
 
 extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
 
+extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+extern unsigned int s3c2410_modify_misccr(unsigned int clr, unsigned int chg);
+
 #endif /* __ASSEMBLY__ */
 
 #include <asm/sizes.h>
diff --git a/include/asm-arm/arch-s3c2410/nand.h b/include/asm-arm/arch-s3c2410/nand.h
new file mode 100644 (file)
index 0000000..9148ac0
--- /dev/null
@@ -0,0 +1,48 @@
+/* linux/include/asm-arm/arch-s3c2410/nand.h
+ *
+ * (c) 2004 Simtec Electronics
+ *  Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - NAND device controller platfrom_device info
+ *
+ * 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.
+ *
+ * Changelog:
+ *     23-Sep-2004 BJD  Created file
+*/
+
+/* struct s3c2410_nand_set
+ *
+ * define an set of one or more nand chips registered with an unique mtd
+ *
+ * nr_chips     = number of chips in this set
+ * nr_partitions = number of partitions pointed to be partitoons (or zero)
+ * name                 = name of set (optional)
+ * nr_map       = map for low-layer logical to physical chip numbers (option)
+ * partitions   = mtd partition list
+*/
+
+struct s3c2410_nand_set {
+       int                     nr_chips;
+       int                     nr_partitions;
+       char                    *name;
+       int                     *nr_map;
+       struct mtd_partition    *partitions;
+};
+
+struct s3c2410_platform_nand {
+       /* timing information for controller, all times in nanoseconds */
+
+       int     tacls;  /* time for active CLE/ALE to nWE/nOE */
+       int     twrph0; /* active time for nWE/nOE */
+       int     twrph1; /* time for release CLE/ALE from nWE/nOE inactive */
+
+       int                     nr_sets;
+       struct s3c2410_nand_set *sets;
+
+       void                    (*select_chip)(struct s3c2410_nand_set *,
+                                              int chip);
+};
+
index 9a5fcde..483d3f1 100644 (file)
@@ -22,6 +22,6 @@
  * add a software pre-scaler to the evil timer systems.
 */
 
-#define __KERNEL_HZ   200
+#define HZ   200
 
 #endif /* __ASM_ARCH_PARAM_H */
index a82d55c..0cc629f 100644 (file)
@@ -1,6 +1,6 @@
 /* linux/include/asm/arch-s3c2410/regs-clock.h
  *
- * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
+ * Copyright (c) 2003,2004 Simtec Electronics <linux@simtec.co.uk>
  *                   http://www.simtec.co.uk/products/SWLINUX/
  *
  * This program is free software; you can redistribute it and/or modify
  * S3C2410 clock register definitions
  *
  *  Changelog:
- *    19-06-2003     BJD     Created file
- *    12-03-2004     BJD     Updated include protection
+ *    18-Aug-2004 Ben Dooks      Added 2440 definitions
+ *    08-Aug-2004 Herbert Pötzl  Added CLKCON definitions
+ *    19-06-2003  Ben Dooks      Created file
+ *    12-03-2004  Ben Dooks      Updated include protection
+ *    29-Sep-2004 Ben Dooks     Fixed usage for assembly inclusion
  */
 
-
-
 #ifndef __ASM_ARM_REGS_CLOCK
 #define __ASM_ARM_REGS_CLOCK "$Id: clock.h,v 1.4 2003/04/30 14:50:51 ben Exp $"
 
 #define S3C2410_CLKSLOW            S3C2410_CLKREG(0x10)
 #define S3C2410_CLKDIVN            S3C2410_CLKREG(0x14)
 
+#define S3C2410_CLKCON_IDLE         (1<<2)
+#define S3C2410_CLKCON_POWER        (1<<3)
+#define S3C2410_CLKCON_NAND         (1<<4)
+#define S3C2410_CLKCON_LCDC         (1<<5)
+#define S3C2410_CLKCON_USBH         (1<<6)
+#define S3C2410_CLKCON_USBD         (1<<7)
+#define S3C2410_CLKCON_PWMT         (1<<8)
+#define S3C2410_CLKCON_SDI          (1<<9)
+#define S3C2410_CLKCON_UART0        (1<<10)
+#define S3C2410_CLKCON_UART1        (1<<11)
+#define S3C2410_CLKCON_UART2        (1<<12)
+#define S3C2410_CLKCON_GPIO         (1<<13)
+#define S3C2410_CLKCON_RTC          (1<<14)
+#define S3C2410_CLKCON_ADC          (1<<15)
+#define S3C2410_CLKCON_IIC          (1<<16)
+#define S3C2410_CLKCON_IIS          (1<<17)
+#define S3C2410_CLKCON_SPI          (1<<18)
+
 #define S3C2410_PLLCON_MDIVSHIFT     12
 #define S3C2410_PLLCON_PDIVSHIFT     4
 #define S3C2410_PLLCON_SDIVSHIFT     0
@@ -53,6 +72,8 @@
 #define S3C2410_CLKDIVN_PDIVN       (1<<0)
 #define S3C2410_CLKDIVN_HDIVN       (1<<1)
 
+#ifndef __ASSEMBLY__
+
 static inline unsigned int
 s3c2410_get_pll(int pllval, int baseclk)
 {
@@ -69,4 +90,31 @@ s3c2410_get_pll(int pllval, int baseclk)
   return (baseclk * (mdiv + 8)) / ((pdiv + 2) << sdiv);
 }
 
+#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_CPU_S3C2440
+
+/* extra registers */
+#define S3C2440_CAMDIVN            S3C2410_CLKREG(0x14)
+
+#define S3C2440_CLKCON_CAMERA        (1<<19)
+#define S3C2440_CLKCON_AC97          (1<<20)
+
+#define S3C2440_CLKDIVN_PDIVN       (1<<0)
+#define S3C2440_CLKDIVN_HDIVN_MASK   (3<<1)
+#define S3C2440_CLKDIVN_HDIVN_1      (0<<1)
+#define S3C2440_CLKDIVN_HDIVN_2      (1<<1)
+#define S3C2440_CLKDIVN_HDIVN_4_8    (2<<1)
+#define S3C2440_CLKDIVN_HDIVN_3_6    (3<<1)
+#define S3C2440_CLKDIVN_UCLK         (1<<3)
+
+#define S3C2440_CAMDIVN_CAMCLK_MASK  (0xf<<0)
+#define S3C2440_CAMDIVN_CAMCLK_SEL   (1<<4)
+#define S3C2440_CAMDIVN_HCLK3_HALF   (1<<8)
+#define S3C2440_CAMDIVN_HCLK4_HALF   (1<<9)
+#define S3C2440_CAMDIVN_DVSEN        (1<<12)
+
+#endif /* CONFIG_CPU_S3C2440 */
+
+
 #endif /* __ASM_ARM_REGS_CLOCK */
diff --git a/include/asm-arm/arch-s3c2410/regs-dsc.h b/include/asm-arm/arch-s3c2410/regs-dsc.h
new file mode 100644 (file)
index 0000000..0da1ec7
--- /dev/null
@@ -0,0 +1,183 @@
+/* linux/include/asm/hardware/s3c2410/regs-dsc.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *                   http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2440 Signal Drive Strength Control
+ *
+ *  Changelog:
+ *    11-Aug-2004     BJD     Created file
+ *    25-Aug-2004     BJD     Added the _SELECT_* defs for using with functions
+*/
+
+
+#ifndef __ASM_ARCH_REGS_DSC_H
+#define __ASM_ARCH_REGS_DSC_H "2440-dsc"
+
+#ifdef CONFIG_CPU_S3C2440
+
+#define S3C2440_DSC0      S3C2410_GPIOREG(0xc0)
+#define S3C2440_DSC1      S3C2410_GPIOREG(0xc4)
+
+#define S3C2440_SELECT_DSC0 (0)
+#define S3C2440_SELECT_DSC1 (1<<31)
+
+#define S3C2440_DSC_GETSHIFT(x) ((x) & 31)
+
+#define S3C2440_DSC0_ENABLE     (1<<31)
+
+#define S3C2440_DSC0_ADDR       (S3C2440_SELECT_DSC0 | 8)
+#define S3C2440_DSC0_ADDR_12mA  (0<<8)
+#define S3C2440_DSC0_ADDR_10mA  (1<<8)
+#define S3C2440_DSC0_ADDR_8mA   (2<<8)
+#define S3C2440_DSC0_ADDR_6mA   (3<<8)
+#define S3C2440_DSC0_ADDR_MASK  (3<<8)
+
+/* D24..D31 */
+#define S3C2440_DSC0_DATA3      (S3C2440_SELECT_DSC0 | 6)
+#define S3C2440_DSC0_DATA3_12mA (0<<6)
+#define S3C2440_DSC0_DATA3_10mA (1<<6)
+#define S3C2440_DSC0_DATA3_8mA  (2<<6)
+#define S3C2440_DSC0_DATA3_6mA  (3<<6)
+#define S3C2440_DSC0_DATA3_MASK (3<<6)
+
+/* D16..D23 */
+#define S3C2440_DSC0_DATA2      (S3C2440_SELECT_DSC0 | 4)
+#define S3C2440_DSC0_DATA2_12mA (0<<4)
+#define S3C2440_DSC0_DATA2_10mA (1<<4)
+#define S3C2440_DSC0_DATA2_8mA  (2<<4)
+#define S3C2440_DSC0_DATA2_6mA  (3<<4)
+#define S3C2440_DSC0_DATA2_MASK (3<<4)
+
+/* D8..D15 */
+#define S3C2440_DSC0_DATA1      (S3C2440_SELECT_DSC0 | 2)
+#define S3C2440_DSC0_DATA1_12mA (0<<2)
+#define S3C2440_DSC0_DATA1_10mA (1<<2)
+#define S3C2440_DSC0_DATA1_8mA  (2<<2)
+#define S3C2440_DSC0_DATA1_6mA  (3<<2)
+#define S3C2440_DSC0_DATA1_MASK (3<<2)
+
+/* D0..D7 */
+#define S3C2440_DSC0_DATA0      (S3C2440_SELECT_DSC0 | 0)
+#define S3C2440_DSC0_DATA0_12mA (0<<0)
+#define S3C2440_DSC0_DATA0_10mA (1<<0)
+#define S3C2440_DSC0_DATA0_8mA  (2<<0)
+#define S3C2440_DSC0_DATA0_6mA  (3<<0)
+#define S3C2440_DSC0_DATA0_MASK (3<<0)
+
+#define S3C2440_DSC1_SCK0       (S3C2440_SELECT_DSC1 | 28)
+#define S3C2440_DSC1_SCK0_12mA  (0<<28)
+#define S3C2440_DSC1_SCK0_10mA  (1<<28)
+#define S3C2440_DSC1_SCK0_8mA   (2<<28)
+#define S3C2440_DSC1_SCK0_6mA   (3<<28)
+#define S3C2440_DSC1_SCK0_MASK  (3<<28)
+
+#define S3C2440_DSC1_SCK1       (S3C2440_SELECT_DSC1 | 26)
+#define S3C2440_DSC1_SCK1_12mA  (0<<26)
+#define S3C2440_DSC1_SCK1_10mA  (1<<26)
+#define S3C2440_DSC1_SCK1_8mA   (2<<26)
+#define S3C2440_DSC1_SCK1_6mA   (3<<26)
+#define S3C2440_DSC1_SCK1_MASK  (3<<26)
+
+#define S3C2440_DSC1_SCKE       (S3C2440_SELECT_DSC1 | 24)
+#define S3C2440_DSC1_SCKE_10mA  (0<<24)
+#define S3C2440_DSC1_SCKE_8mA   (1<<24)
+#define S3C2440_DSC1_SCKE_6mA   (2<<24)
+#define S3C2440_DSC1_SCKE_4mA   (3<<24)
+#define S3C2440_DSC1_SCKE_MASK  (3<<24)
+
+/* SDRAM nRAS/nCAS */
+#define S3C2440_DSC1_SDR        (S3C2440_SELECT_DSC1 | 22)
+#define S3C2440_DSC1_SDR_10mA   (0<<22)
+#define S3C2440_DSC1_SDR_8mA    (1<<22)
+#define S3C2440_DSC1_SDR_6mA    (2<<22)
+#define S3C2440_DSC1_SDR_4mA    (3<<22)
+#define S3C2440_DSC1_SDR_MASK   (3<<22)
+
+/* NAND Flash Controller */
+#define S3C2440_DSC1_NFC        (S3C2440_SELECT_DSC1 | 20)
+#define S3C2440_DSC1_NFC_10mA   (0<<20)
+#define S3C2440_DSC1_NFC_8mA    (1<<20)
+#define S3C2440_DSC1_NFC_6mA    (2<<20)
+#define S3C2440_DSC1_NFC_4mA    (3<<20)
+#define S3C2440_DSC1_NFC_MASK   (3<<20)
+
+/* nBE[0..3] */
+#define S3C2440_DSC1_nBE        (S3C2440_SELECT_DSC1 | 18)
+#define S3C2440_DSC1_nBE_10mA   (0<<18)
+#define S3C2440_DSC1_nBE_8mA    (1<<18)
+#define S3C2440_DSC1_nBE_6mA    (2<<18)
+#define S3C2440_DSC1_nBE_4mA    (3<<18)
+#define S3C2440_DSC1_nBE_MASK   (3<<18)
+
+#define S3C2440_DSC1_WOE        (S3C2440_SELECT_DSC1 | 16)
+#define S3C2440_DSC1_WOE_10mA   (0<<16)
+#define S3C2440_DSC1_WOE_8mA    (1<<16)
+#define S3C2440_DSC1_WOE_6mA    (2<<16)
+#define S3C2440_DSC1_WOE_4mA    (3<<16)
+#define S3C2440_DSC1_WOE_MASK   (3<<16)
+
+#define S3C2440_DSC1_CS7        (S3C2440_SELECT_DSC1 | 14)
+#define S3C2440_DSC1_CS7_10mA   (0<<14)
+#define S3C2440_DSC1_CS7_8mA    (1<<14)
+#define S3C2440_DSC1_CS7_6mA    (2<<14)
+#define S3C2440_DSC1_CS7_4mA    (3<<14)
+#define S3C2440_DSC1_CS7_MASK   (3<<14)
+
+#define S3C2440_DSC1_CS6        (S3C2440_SELECT_DSC1 | 12)
+#define S3C2440_DSC1_CS6_10mA   (0<<12)
+#define S3C2440_DSC1_CS6_8mA    (1<<12)
+#define S3C2440_DSC1_CS6_6mA    (2<<12)
+#define S3C2440_DSC1_CS6_4mA    (3<<12)
+#define S3C2440_DSC1_CS6_MASK   (3<<12)
+
+#define S3C2440_DSC1_CS5        (S3C2440_SELECT_DSC1 | 10)
+#define S3C2440_DSC1_CS5_10mA   (0<<10)
+#define S3C2440_DSC1_CS5_8mA    (1<<10)
+#define S3C2440_DSC1_CS5_6mA    (2<<10)
+#define S3C2440_DSC1_CS5_4mA    (3<<10)
+#define S3C2440_DSC1_CS5_MASK   (3<<10)
+
+#define S3C2440_DSC1_CS4        (S3C2440_SELECT_DSC1 | 8)
+#define S3C2440_DSC1_CS4_10mA   (0<<8)
+#define S3C2440_DSC1_CS4_8mA    (1<<8)
+#define S3C2440_DSC1_CS4_6mA    (2<<8)
+#define S3C2440_DSC1_CS4_4mA    (3<<8)
+#define S3C2440_DSC1_CS4_MASK   (3<<8)
+
+#define S3C2440_DSC1_CS3        (S3C2440_SELECT_DSC1 | 6)
+#define S3C2440_DSC1_CS3_10mA   (0<<6)
+#define S3C2440_DSC1_CS3_8mA    (1<<6)
+#define S3C2440_DSC1_CS3_6mA    (2<<6)
+#define S3C2440_DSC1_CS3_4mA    (3<<6)
+#define S3C2440_DSC1_CS3_MASK   (3<<6)
+
+#define S3C2440_DSC1_CS2        (S3C2440_SELECT_DSC1 | 4)
+#define S3C2440_DSC1_CS2_10mA   (0<<4)
+#define S3C2440_DSC1_CS2_8mA    (1<<4)
+#define S3C2440_DSC1_CS2_6mA    (2<<4)
+#define S3C2440_DSC1_CS2_4mA    (3<<4)
+#define S3C2440_DSC1_CS2_MASK   (3<<4)
+
+#define S3C2440_DSC1_CS1        (S3C2440_SELECT_DSC1 | 2)
+#define S3C2440_DSC1_CS1_10mA   (0<<2)
+#define S3C2440_DSC1_CS1_8mA    (1<<2)
+#define S3C2440_DSC1_CS1_6mA    (2<<2)
+#define S3C2440_DSC1_CS1_4mA    (3<<2)
+#define S3C2440_DSC1_CS1_MASK   (3<<2)
+
+#define S3C2440_DSC1_CS0        (S3C2440_SELECT_DSC1 | 0
+#define S3C2440_DSC1_CS0_10mA   (0<<0)
+#define S3C2440_DSC1_CS0_8mA    (1<<0)
+#define S3C2440_DSC1_CS0_6mA    (2<<0)
+#define S3C2440_DSC1_CS0_4mA    (3<<0)
+#define S3C2440_DSC1_CS0_MASK   (3<<0)
+
+#endif /* CONFIG_CPU_S3C2440 */
+
+#endif /* __ASM_ARCH_REGS_DSC_H */
+
index 661cf97..05eb116 100644 (file)
@@ -14,7 +14,8 @@
  *    23-06-2003     BJD     Updated GSTATUS registers
  *    12-03-2004     BJD     Updated include protection
  *    20-07-2004     BJD     Added GPIO pin numbers, added Port A definitions
- */
+ *    04-10-2004     BJD     Fixed number of bugs, added EXT IRQ filter defs
+*/
 
 
 #ifndef __ASM_ARCH_REGS_GPIO_H
 #define S3C2410_GPG10_OUTP    (0x01 << 20)
 #define S3C2410_GPG10_EINT18  (0x02 << 20)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG11         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 11)
 #define S3C2410_GPG11_INP     (0x00 << 22)
 #define S3C2410_GPG11_OUTP    (0x01 << 22)
 #define S3C2410_GPG11_EINT19  (0x02 << 22)
 #define S3C2410_GPG11_TCLK1   (0x03 << 22)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG12         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 12)
 #define S3C2410_GPG12_INP     (0x00 << 24)
 #define S3C2410_GPG12_OUTP    (0x01 << 24)
-#define S3C2410_GPG12_EINT18  (0x02 << 24)
+#define S3C2410_GPG12_EINT20  (0x02 << 24)
 #define S3C2410_GPG12_XMON    (0x03 << 24)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG13         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 13)
 #define S3C2410_GPG13_INP     (0x00 << 26)
 #define S3C2410_GPG13_OUTP    (0x01 << 26)
-#define S3C2410_GPG13_EINT18  (0x02 << 26)
+#define S3C2410_GPG13_EINT21  (0x02 << 26)
 #define S3C2410_GPG13_nXPON   (0x03 << 26)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG14         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 14)
 #define S3C2410_GPG14_INP     (0x00 << 28)
 #define S3C2410_GPG14_OUTP    (0x01 << 28)
-#define S3C2410_GPG14_EINT18  (0x02 << 28)
+#define S3C2410_GPG14_EINT22  (0x02 << 28)
 #define S3C2410_GPG14_YMON    (0x03 << 28)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG15         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 15)
 #define S3C2410_GPG15_INP     (0x00 << 30)
 #define S3C2410_GPG15_OUTP    (0x01 << 30)
-#define S3C2410_GPG15_EINT18  (0x02 << 30)
+#define S3C2410_GPG15_EINT23  (0x02 << 30)
 #define S3C2410_GPG15_nYPON   (0x03 << 30)
 
 
 
 #define S3C2410_MISCCR_nRSTCON     (1<<16)
 
+#define S3C2410_MISCCR_nEN_SCLK0    (1<<17)
+#define S3C2410_MISCCR_nEN_SCLK1    (1<<18)
+#define S3C2410_MISCCR_nEN_SCLKE    (1<<19)
+#define S3C2410_MISCCR_SDSLEEP     (7<<17)
+
 /* external interrupt control... */
 /* S3C2410_EXTINT0 -> irq sense control for EINT0..EINT7
  * S3C2410_EXTINT1 -> irq sense control for EINT8..EINT15
 #define S3C2410_EINFLT2           S3C2410_GPIOREG(0x9C)
 #define S3C2410_EINFLT3           S3C2410_GPIOREG(0xA0)
 
+/* values for interrupt filtering */
+#define S3C2410_EINTFLT_PCLK           (0x00)
+#define S3C2410_EINTFLT_EXTCLK         (1<<7)
+#define S3C2410_EINTFLT_WIDTHMSK(x)    ((x) & 0x3f)
+
 /* removed EINTxxxx defs from here, not meant for this */
 
 /* GSTATUS have miscellaneous information in them
diff --git a/include/asm-arm/arch-s3c2410/regs-gpioj.h b/include/asm-arm/arch-s3c2410/regs-gpioj.h
new file mode 100644 (file)
index 0000000..ca91645
--- /dev/null
@@ -0,0 +1,100 @@
+/* linux/include/asm/hardware/s3c2410/regs-gpioj.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *                   http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2440 GPIO J register definitions
+ *
+ *  Changelog:
+ *    11-Aug-2004     BJD     Created file
+*/
+
+
+#ifndef __ASM_ARCH_REGS_GPIOJ_H
+#define __ASM_ARCH_REGS_GPIOJ_H "gpioj"
+
+/* Port J consists of 13 GPIO/Camera pins
+ *
+ * GPJCON has 2 bits for each of the input pins on port F
+ *   00 = 0 input, 1 output, 2 Camera
+ *
+ * pull up works like all other ports.
+*/
+
+#define S3C2440_GPIO_BANKJ  (416)
+
+#define S3C2440_GPJCON     S3C2410_GPIOREG(0xd0)
+#define S3C2440_GPJDAT     S3C2410_GPIOREG(0xd4)
+#define S3C2440_GPJUP      S3C2410_GPIOREG(0xd8)
+
+#define S3C2440_GPJ0            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 0)
+#define S3C2440_GPJ0_INP        (0x00 << 0)
+#define S3C2440_GPJ0_OUTP       (0x01 << 0)
+#define S3C2440_GPJ0_CAMDATA0   (0x02 << 0)
+
+#define S3C2440_GPJ1            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 1)
+#define S3C2440_GPJ1_INP        (0x00 << 2)
+#define S3C2440_GPJ1_OUTP       (0x01 << 2)
+#define S3C2440_GPJ1_CAMDATA1   (0x02 << 2)
+
+#define S3C2440_GPJ2            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 2)
+#define S3C2440_GPJ2_INP        (0x00 << 4)
+#define S3C2440_GPJ2_OUTP       (0x01 << 4)
+#define S3C2440_GPJ2_CAMDATA2   (0x02 << 4)
+
+#define S3C2440_GPJ3            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 3)
+#define S3C2440_GPJ3_INP        (0x00 << 6)
+#define S3C2440_GPJ3_OUTP       (0x01 << 6)
+#define S3C2440_GPJ3_CAMDATA3   (0x02 << 6)
+
+#define S3C2440_GPJ4            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 4)
+#define S3C2440_GPJ4_INP        (0x00 << 8)
+#define S3C2440_GPJ4_OUTP       (0x01 << 8)
+#define S3C2440_GPJ4_CAMDATA4   (0x02 << 8)
+
+#define S3C2440_GPJ5            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 5)
+#define S3C2440_GPJ5_INP        (0x00 << 10)
+#define S3C2440_GPJ5_OUTP       (0x01 << 10)
+#define S3C2440_GPJ5_CAMDATA5   (0x02 << 10)
+
+#define S3C2440_GPJ6            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 6)
+#define S3C2440_GPJ6_INP        (0x00 << 12)
+#define S3C2440_GPJ6_OUTP       (0x01 << 12)
+#define S3C2440_GPJ6_CAMDATA6   (0x02 << 12)
+
+#define S3C2440_GPJ7            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 7)
+#define S3C2440_GPJ7_INP        (0x00 << 14)
+#define S3C2440_GPJ7_OUTP       (0x01 << 14)
+#define S3C2440_GPJ7_CAMDATA7   (0x02 << 14)
+
+#define S3C2440_GPJ8            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 8)
+#define S3C2440_GPJ8_INP        (0x00 << 16)
+#define S3C2440_GPJ8_OUTP       (0x01 << 16)
+#define S3C2440_GPJ8_CAMPCLK    (0x02 << 16)
+
+#define S3C2440_GPJ9            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 9)
+#define S3C2440_GPJ9_INP        (0x00 << 18)
+#define S3C2440_GPJ9_OUTP       (0x01 << 18)
+#define S3C2440_GPJ9_CAMVSYNC   (0x02 << 18)
+
+#define S3C2440_GPJ10           S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 10)
+#define S3C2440_GPJ10_INP       (0x00 << 20)
+#define S3C2440_GPJ10_OUTP      (0x01 << 20)
+#define S3C2440_GPJ10_CAMHREF   (0x02 << 20)
+
+#define S3C2440_GPJ11           S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 11)
+#define S3C2440_GPJ11_INP       (0x00 << 22)
+#define S3C2440_GPJ11_OUTP      (0x01 << 22)
+#define S3C2440_GPJ11_CAMCLKOUT (0x02 << 22)
+
+#define S3C2440_GPJ12           S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 12)
+#define S3C2440_GPJ12_INP       (0x00 << 24)
+#define S3C2440_GPJ12_OUTP      (0x01 << 24)
+#define S3C2440_GPJ12_CAMCLKOUT (0x02 << 24)
+
+#endif /* __ASM_ARCH_REGS_GPIOJ_H */
+
diff --git a/include/asm-arm/arch-s3c2410/regs-iic.h b/include/asm-arm/arch-s3c2410/regs-iic.h
new file mode 100644 (file)
index 0000000..028ab20
--- /dev/null
@@ -0,0 +1,50 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-iic.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *             http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2410 I2C Controller
+ *
+ *  Changelog:
+ *     03-Oct-2004  BJD  Initial include for Linux
+*/
+
+#ifndef __ASM_ARCH_IIC_H
+#define __ASM_ARCH_IIC_H __FILE__
+
+/* see s3c2410x user guide, v1.1, section 9 (p447) for more info */
+
+#define S3C2410_IICREG(x) (x)
+
+#define S3C2410_IICCON    S3C2410_IICREG(0x00)
+#define S3C2410_IICSTAT   S3C2410_IICREG(0x04)
+#define S3C2410_IICADD    S3C2410_IICREG(0x08)
+#define S3C2410_IICDS     S3C2410_IICREG(0x0C)
+
+#define S3C2410_IICCON_ACKEN           (1<<7)
+#define S3C2410_IICCON_TXDIV_16                (0<<6)
+#define S3C2410_IICCON_TXDIV_512       (1<<6)
+#define S3C2410_IICCON_IRQEN           (1<<5)
+#define S3C2410_IICCON_IRQPEND         (1<<4)
+#define S3C2410_IICCON_SCALE(x)                ((x)&15)
+#define S3C2410_IICCON_SCALEMASK       (0xf)
+
+#define S3C2410_IICSTAT_MASTER_RX      (2<<6)
+#define S3C2410_IICSTAT_MASTER_TX      (3<<6)
+#define S3C2410_IICSTAT_SLAVE_RX       (0<<6)
+#define S3C2410_IICSTAT_SLAVE_TX       (1<<6)
+#define S3C2410_IICSTAT_MODEMASK       (3<<6)
+
+#define S3C2410_IICSTAT_START          (1<<5)
+#define S3C2410_IICSTAT_BUSBUSY                (1<<5)
+#define S3C2410_IICSTAT_TXRXEN         (1<<4)
+#define S3C2410_IICSTAT_ARBITR         (1<<3)
+#define S3C2410_IICSTAT_ASSLAVE                (1<<2)
+#define S3C2410_IICSTAT_ADDR0          (1<<1)
+#define S3C2410_IICSTAT_LASTBIT                (1<<0)
+
+#endif /* __ASM_ARCH_IIC_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-mem.h b/include/asm-arm/arch-s3c2410/regs-mem.h
new file mode 100644 (file)
index 0000000..400fbd7
--- /dev/null
@@ -0,0 +1,190 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-mem.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *             http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2410 Memory Control register definitions
+ *
+ *  Changelog:
+ *     29-Sep-2004  BJD  Initial include for Linux
+ *
+*/
+
+#ifndef __ASM_ARM_MEMREGS_H
+#define __ASM_ARM_MEMREGS_H "$Id: regs.h,v 1.8 2003/05/01 15:55:41 ben Exp $"
+
+#ifndef S3C2410_MEMREG
+#define S3C2410_MEMREG(x) (S3C2410_VA_MEMCTRL + (x))
+#endif
+
+/* bus width, and wait state control */
+#define S3C2410_BWSCON                 S3C2410_MEMREG(0x0000)
+
+/* bank zero config - note, pinstrapped from OM pins! */
+#define S3C2410_BWSCON_DW0_16          (1<<1)
+#define S3C2410_BWSCON_DW0_32          (2<<1)
+
+/* bank one configs */
+#define S3C2410_BWSCON_DW1_8           (0<<4)
+#define S3C2410_BWSCON_DW1_16          (1<<4)
+#define S3C2410_BWSCON_DW1_32          (2<<4)
+#define S3C2410_BWSCON_WS1             (1<<6)
+#define S3C2410_BWSCON_ST1             (1<<7)
+
+/* bank 2 configurations */
+#define S3C2410_BWSCON_DW2_8           (0<<8)
+#define S3C2410_BWSCON_DW2_16          (1<<8)
+#define S3C2410_BWSCON_DW2_32          (2<<8)
+#define S3C2410_BWSCON_WS2             (1<<10)
+#define S3C2410_BWSCON_ST2             (1<<11)
+
+/* bank 3 configurations */
+#define S3C2410_BWSCON_DW3_8           (0<<12)
+#define S3C2410_BWSCON_DW3_16          (1<<12)
+#define S3C2410_BWSCON_DW3_32          (2<<12)
+#define S3C2410_BWSCON_WS3             (1<<14)
+#define S3C2410_BWSCON_ST3             (1<<15)
+
+/* bank 4 configurations */
+#define S3C2410_BWSCON_DW4_8           (0<<16)
+#define S3C2410_BWSCON_DW4_16          (1<<16)
+#define S3C2410_BWSCON_DW4_32          (2<<16)
+#define S3C2410_BWSCON_WS4             (1<<18)
+#define S3C2410_BWSCON_ST4             (1<<19)
+
+/* bank 5 configurations */
+#define S3C2410_BWSCON_DW5_8           (0<<20)
+#define S3C2410_BWSCON_DW5_16          (1<<20)
+#define S3C2410_BWSCON_DW5_32          (2<<20)
+#define S3C2410_BWSCON_WS5             (1<<22)
+#define S3C2410_BWSCON_ST5             (1<<23)
+
+/* bank 6 configurations */
+#define S3C2410_BWSCON_DW6_8           (0<<24)
+#define S3C2410_BWSCON_DW6_16          (1<<24)
+#define S3C2410_BWSCON_DW6_32          (2<<24)
+#define S3C2410_BWSCON_WS6             (1<<26)
+#define S3C2410_BWSCON_ST6             (1<<27)
+
+/* bank 7 configurations */
+#define S3C2410_BWSCON_DW7_8           (0<<28)
+#define S3C2410_BWSCON_DW7_16          (1<<28)
+#define S3C2410_BWSCON_DW7_32          (2<<28)
+#define S3C2410_BWSCON_WS7             (1<<30)
+#define S3C2410_BWSCON_ST7             (1<<31)
+
+/* memory set (rom, ram) */
+#define S3C2410_BANKCON0               S3C2410_MEMREG(0x0004)
+#define S3C2410_BANKCON1               S3C2410_MEMREG(0x0008)
+#define S3C2410_BANKCON2               S3C2410_MEMREG(0x000C)
+#define S3C2410_BANKCON3               S3C2410_MEMREG(0x0010)
+#define S3C2410_BANKCON4               S3C2410_MEMREG(0x0014)
+#define S3C2410_BANKCON5               S3C2410_MEMREG(0x0018)
+#define S3C2410_BANKCON6               S3C2410_MEMREG(0x001C)
+#define S3C2410_BANKCON7               S3C2410_MEMREG(0x0020)
+
+/* bank configuration registers */
+
+#define S3C2410_BANKCON_PMCnorm                (0x00)
+#define S3C2410_BANKCON_PMC4           (0x01)
+#define S3C2410_BANKCON_PMC8           (0x02)
+#define S3C2410_BANKCON_PMC16          (0x03)
+
+/* bank configurations for banks 0..7, note banks
+ * 6 and 7 have differnt configurations depending on
+ * the memory type bits */
+
+#define S3C2410_BANKCON_Tacp2          (0x0 << 2)
+#define S3C2410_BANKCON_Tacp3          (0x1 << 2)
+#define S3C2410_BANKCON_Tacp4          (0x2 << 2)
+#define S3C2410_BANKCON_Tacp6          (0x3 << 2)
+
+#define S3C2410_BANKCON_Tcah0          (0x0 << 4)
+#define S3C2410_BANKCON_Tcah1          (0x1 << 4)
+#define S3C2410_BANKCON_Tcah2          (0x2 << 4)
+#define S3C2410_BANKCON_Tcah4          (0x3 << 4)
+
+#define S3C2410_BANKCON_Tcoh0          (0x0 << 6)
+#define S3C2410_BANKCON_Tcoh1          (0x1 << 6)
+#define S3C2410_BANKCON_Tcoh2          (0x2 << 6)
+#define S3C2410_BANKCON_Tcoh4          (0x3 << 6)
+
+#define S3C2410_BANKCON_Tacc1          (0x0 << 8)
+#define S3C2410_BANKCON_Tacc2          (0x1 << 8)
+#define S3C2410_BANKCON_Tacc3          (0x2 << 8)
+#define S3C2410_BANKCON_Tacc4          (0x3 << 8)
+#define S3C2410_BANKCON_Tacc6          (0x4 << 8)
+#define S3C2410_BANKCON_Tacc8          (0x5 << 8)
+#define S3C2410_BANKCON_Tacc10         (0x6 << 8)
+#define S3C2410_BANKCON_Tacc14         (0x7 << 8)
+
+#define S3C2410_BANKCON_Tcos0          (0x0 << 11)
+#define S3C2410_BANKCON_Tcos1          (0x1 << 11)
+#define S3C2410_BANKCON_Tcos2          (0x2 << 11)
+#define S3C2410_BANKCON_Tcos4          (0x3 << 11)
+
+#define S3C2410_BANKCON_Tacs0          (0x0 << 13)
+#define S3C2410_BANKCON_Tacs1          (0x1 << 13)
+#define S3C2410_BANKCON_Tacs2          (0x2 << 13)
+#define S3C2410_BANKCON_Tacs4          (0x3 << 13)
+
+#define S3C2410_BANKCON_SRAM           (0x0 << 15)
+#define S3C2410_BANKCON_SDRAM          (0x3 << 15)
+
+/* next bits only for SDRAM in 6,7 */
+#define S3C2410_BANKCON_Trdc2          (0x00 << 2)
+#define S3C2410_BANKCON_Trdc3          (0x01 << 2)
+#define S3C2410_BANKCON_Trdc4          (0x02 << 2)
+
+/* control column address select */
+#define S3C2410_BANKCON_SCANb8         (0x00 << 0)
+#define S3C2410_BANKCON_SCANb9         (0x01 << 0)
+#define S3C2410_BANKCON_SCANb10                (0x02 << 0)
+
+#define S3C2410_REFRESH                        S3C2410_MEMREG(0x0024)
+#define S3C2410_BANKSIZE               S3C2410_MEMREG(0x0028)
+#define S3C2410_MRSRB6                 S3C2410_MEMREG(0x002C)
+#define S3C2410_MRSRB7                 S3C2410_MEMREG(0x0030)
+
+/* refresh control */
+
+#define S3C2410_REFRESH_REFEN          (1<<23)
+#define S3C2410_REFRESH_SELF           (1<<22)
+#define S3C2410_REFRESH_REFCOUNTER     ((1<<11)-1)
+
+#define S3C2410_REFRESH_TRP_MASK       (3<<20)
+#define S3C2410_REFRESH_TRP_2clk       (0<<20)
+#define S3C2410_REFRESH_TRP_3clk       (1<<20)
+#define S3C2410_REFRESH_TRP_4clk       (2<<20)
+
+#define S3C2410_REFRESH_TSRC_MASK      (3<<18)
+#define S3C2410_REFRESH_TSRC_4clk      (0<<18)
+#define S3C2410_REFRESH_TSRC_5clk      (1<<18)
+#define S3C2410_REFRESH_TSRC_6clk      (2<<18)
+#define S3C2410_REFRESH_TSRC_7clk      (3<<18)
+
+
+/* mode select register(s) */
+
+#define  S3C2410_MRSRB_CL1             (0x00 << 4)
+#define  S3C2410_MRSRB_CL2             (0x02 << 4)
+#define  S3C2410_MRSRB_CL3             (0x03 << 4)
+
+/* bank size register */
+#define S3C2410_BANKSIZE_128M          (0x2 << 0)
+#define S3C2410_BANKSIZE_64M           (0x1 << 0)
+#define S3C2410_BANKSIZE_32M           (0x0 << 0)
+#define S3C2410_BANKSIZE_16M           (0x7 << 0)
+#define S3C2410_BANKSIZE_8M            (0x6 << 0)
+#define S3C2410_BANKSIZE_4M            (0x5 << 0)
+#define S3C2410_BANKSIZE_2M            (0x4 << 0)
+#define S3C2410_BANKSIZE_MASK          (0x7 << 0)
+#define S3C2410_BANKSIZE_SCLK_EN       (1<<4)
+#define S3C2410_BANKSIZE_SCKE_EN       (1<<5)
+#define S3C2410_BANKSIZE_BURST         (1<<7)
+
+#endif /* __ASM_ARM_MEMREGS_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-nand.h b/include/asm-arm/arch-s3c2410/regs-nand.h
new file mode 100644 (file)
index 0000000..c443ac8
--- /dev/null
@@ -0,0 +1,43 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-nand.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *                   http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2410 clock register definitions
+ *
+ *  Changelog:
+ *    18-Aug-2004    BJD     Copied file from 2.4 and updated
+*/
+
+#ifndef __ASM_ARM_REGS_NAND
+#define __ASM_ARM_REGS_NAND "$Id: nand.h,v 1.3 2003/12/09 11:36:29 ben Exp $"
+
+
+#define S3C2410_NFREG(x) (x)
+
+#define S3C2410_NFCONF  S3C2410_NFREG(0x00)
+#define S3C2410_NFCMD   S3C2410_NFREG(0x04)
+#define S3C2410_NFADDR  S3C2410_NFREG(0x08)
+#define S3C2410_NFDATA  S3C2410_NFREG(0x0C)
+#define S3C2410_NFSTAT  S3C2410_NFREG(0x10)
+#define S3C2410_NFECC   S3C2410_NFREG(0x14)
+
+#define S3C2410_NFCONF_EN          (1<<15)
+#define S3C2410_NFCONF_512BYTE     (1<<14)
+#define S3C2410_NFCONF_4STEP       (1<<13)
+#define S3C2410_NFCONF_INITECC     (1<<12)
+#define S3C2410_NFCONF_nFCE        (1<<11)
+#define S3C2410_NFCONF_TACLS(x)    ((x)<<8)
+#define S3C2410_NFCONF_TWRPH0(x)   ((x)<<4)
+#define S3C2410_NFCONF_TWRPH1(x)   ((x)<<0)
+
+#define S3C2410_NFSTAT_BUSY        (1<<0)
+
+/* think ECC can only be 8bit read? */
+
+#endif /* __ASM_ARM_REGS_NAND */
+
diff --git a/include/asm-arm/arch-s3c2410/regs-sdi.h b/include/asm-arm/arch-s3c2410/regs-sdi.h
new file mode 100644 (file)
index 0000000..fd688ad
--- /dev/null
@@ -0,0 +1,112 @@
+/* linux/include/asm/arch-s3c2410/regs-sdi.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *                   http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2410 MMC/SDIO register definitions
+ *
+ *  Changelog:
+ *    18-Aug-2004 Ben Dooks      Created initial file
+*/
+
+#ifndef __ASM_ARM_REGS_SDI
+#define __ASM_ARM_REGS_SDI "regs-sdi.h"
+
+#define S3C2410_SDICON                (0x00)
+#define S3C2410_SDIPRE                (0x04)
+#define S3C2410_SDICMDARG             (0x08)
+#define S3C2410_SDICMDCON             (0x0C)
+#define S3C2410_SDICMDSTAT            (0x10)
+#define S3C2410_SDIRSP0               (0x14)
+#define S3C2410_SDIRSP1               (0x18)
+#define S3C2410_SDIRSP2               (0x1C)
+#define S3C2410_SDIRSP3               (0x20)
+#define S3C2410_SDITIMER              (0x24)
+#define S3C2410_SDIBSIZE              (0x28)
+#define S3C2410_SDIDCON               (0x2C)
+#define S3C2410_SDIDCNT               (0x30)
+#define S3C2410_SDIDSTA               (0x34)
+#define S3C2410_SDIFSTA               (0x38)
+#define S3C2410_SDIDATA               (0x3C)
+#define S3C2410_SDIIMSK               (0x40)
+
+#define S3C2410_SDICON_BYTEORDER      (1<<4)
+#define S3C2410_SDICON_SDIOIRQ        (1<<3)
+#define S3C2410_SDICON_RWAITEN        (1<<2)
+#define S3C2410_SDICON_FIFORESET      (1<<1)
+#define S3C2410_SDICON_CLOCKTYPE      (1<<0)
+
+#define S3C2410_SDICMDCON_ABORT       (1<<12)
+#define S3C2410_SDICMDCON_WITHDATA    (1<<11)
+#define S3C2410_SDICMDCON_LONGRSP     (1<<10)
+#define S3C2410_SDICMDCON_WAITRSP     (1<<9)
+#define S3C2410_SDICMDCON_CMDSTART    (1<<8)
+#define S3C2410_SDICMDCON_INDEX       (0xff)
+
+#define S3C2410_SDICMDSTAT_CRCFAIL    (1<<12)
+#define S3C2410_SDICMDSTAT_CMDSENT    (1<<11)
+#define S3C2410_SDICMDSTAT_CMDTIMEOUT (1<<10)
+#define S3C2410_SDICMDSTAT_RSPFIN     (1<<9)
+#define S3C2410_SDICMDSTAT_XFERING    (1<<8)
+#define S3C2410_SDICMDSTAT_INDEX      (0xff)
+
+#define S3C2410_SDIDCON_IRQPERIOD     (1<<21)
+#define S3C2410_SDIDCON_TXAFTERRESP   (1<<20)
+#define S3C2410_SDIDCON_RXAFTERCMD    (1<<19)
+#define S3C2410_SDIDCON_BUSYAFTERCMD  (1<<18)
+#define S3C2410_SDIDCON_BLOCKMODE     (1<<17)
+#define S3C2410_SDIDCON_WIDEBUS       (1<<16)
+#define S3C2410_SDIDCON_DMAEN         (1<<15)
+#define S3C2410_SDIDCON_STOP          (1<<14)
+
+#define S3C2410_SDIDCON_XFER_MASK     (3<<12)
+#define S3C2410_SDIDCON_XFER_READY    (0<<12)
+#define S3C2410_SDIDCON_XFER_CHKSTART (1<<12)
+#define S3C2410_SDIDCON_XFER_RXSTART  (2<<12)
+#define S3C2410_SDIDCON_XFER_TXSTART  (3<<12)
+
+#define S3C2410_SDIDCNT_BLKNUM_SHIFT  (12)
+
+#define S3C2410_SDIDSTA_RDYWAITREQ    (1<<10)
+#define S3C2410_SDIDSTA_SDIOIRQDETECT (1<<9)
+#define S3C2410_SDIDSTA_FIFOFAIL      (1<<8)
+#define S3C2410_SDIDSTA_CRCFAIL       (1<<7)
+#define S3C2410_SDIDSTA_RXCRCFAIL     (1<<6)
+#define S3C2410_SDIDSTA_DATATIMEOUT   (1<<5)
+#define S3C2410_SDIDSTA_XFERFINISH    (1<<4)
+#define S3C2410_SDIDSTA_BUSYFINISH    (1<<3)
+#define S3C2410_SDIDSTA_TXDATAON      (1<<1)
+#define S3C2410_SDIDSTA_RXDATAON      (1<<0)
+
+#define S3C2410_SDIFSTA_TXFULL         (1<<13)
+#define S3C2410_SDIFSTA_RXFULL         (1<<12)
+#define S3C2410_SDIFSTA_TXHALF         (1<<11)
+#define S3C2410_SDIFSTA_TXEMPTY        (1<<10)
+#define S3C2410_SDIFSTA_RXLAST         (1<<9)
+#define S3C2410_SDIFSTA_RXFULL         (1<<8)
+#define S3C2410_SDIFSTA_RXHALF         (1<<7)
+#define S3C2410_SDIFSTA_COUNTMASK      (0x7f)
+
+#define S3C2410_SDIIMSK_RESPONSECRC    (1<<17)
+#define S3C2410_SDIIMSK_CMDSENT        (1<<16)
+#define S3C2410_SDIIMSK_CMDTIMEOUT     (1<<15)
+#define S3C2410_SDIIMSK_RESPONSEND     (1<<14)
+#define S3C2410_SDIIMSK_READWAIT       (1<<13)
+#define S3C2410_SDIIMSK_SDIOIRQ        (1<<12)
+#define S3C2410_SDIIMSK_FIFOFAIL       (1<<11)
+#define S3C2410_SDIIMSK_CRCSTATUS      (1<<10)
+#define S3C2410_SDIIMSK_DATACRC        (1<<9)
+#define S3C2410_SDIIMSK_DATATIMEOUT    (1<<8)
+#define S3C2410_SDIIMSK_DATAFINISH     (1<<7)
+#define S3C2410_SDIIMSK_BUSYFINISH     (1<<6)
+#define S3C2410_SDIIMSK_TXFIFOHALF     (1<<4)
+#define S3C2410_SDIIMSK_TXFIFOEMPTY    (1<<3)
+#define S3C2410_SDIIMSK_RXFIFOLAST     (1<<2)
+#define S3C2410_SDIIMSK_RXFIFOFULL     (1<<1)
+#define S3C2410_SDIIMSK_RXFIFOHALF     (1<<0)
+
+#endif /* __ASM_ARM_REGS_SDI */
diff --git a/include/asm-arm/arch-s3c2410/regs-spi.h b/include/asm-arm/arch-s3c2410/regs-spi.h
new file mode 100644 (file)
index 0000000..cb502a8
--- /dev/null
@@ -0,0 +1,56 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-spi.h
+ *
+ * Copyright (c) 2004 Fetron GmbH
+ *
+ * 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.
+ *
+ * S3C2410 SPI register definition
+ *
+ *  Changelog:
+ *    20-04-2004     KF      Created file
+ *    04-10-2004     BJD     Removed VA address (no longer mapped)
+ *                          tidied file for submission
+ */
+
+#ifndef __ASM_ARCH_REGS_SPI_H
+#define __ASM_ARCH_REGS_SPI_H
+
+
+#define S3C2410_SPCON  (0x00)
+
+#define S3C2410_SPCON_SMOD_DMA   (2<<5)        /* DMA mode */
+#define S3C2410_SPCON_SMOD_INT   (1<<5)        /* interrupt mode */
+#define S3C2410_SPCON_SMOD_POLL   (0<<5)       /* polling mode */
+#define S3C2410_SPCON_ENSCK      (1<<4)        /* Enable SCK */
+#define S3C2410_SPCON_MSTR       (1<<3)        /* Master/Slave select
+                                                  0: slave, 1: master */
+#define S3C2410_SPCON_CPOL_HIGH          (1<<2)        /* Clock polarity select */
+#define S3C2410_SPCON_CPOL_LOW   (0<<2)        /* Clock polarity select */
+
+#define S3C2410_SPCON_CPHA_FMTB          (1<<1)        /* Clock Phase Select */
+#define S3C2410_SPCON_CPHA_FMTA          (0<<1)        /* Clock Phase Select */
+
+#define S3C2410_SPCON_TAGD       (1<<0)        /* Tx auto garbage data mode */
+
+
+#define S3C2410_SPSTA   (0x04)
+
+#define S3C2410_SPSTA_DCOL       (1<<2)        /* Data Collision Error */
+#define S3C2410_SPSTA_MULD       (1<<1)        /* Multi Master Error */
+#define S3C2410_SPSTA_READY      (1<<0)        /* Data Tx/Rx ready */
+
+
+#define S3C2410_SPPIN   (0x08)
+
+#define S3C2410_SPPIN_ENMUL      (1<<2)        /* Multi Master Error detect */
+#define S3C2410_SPPIN_RESERVED   (1<<1)
+#define S3C2410_SPPIN_KEEP       (1<<0)        /* Master Out keep */
+
+
+#define S3C2410_SPPRE   (0x0C)
+#define S3C2410_SPTDAT  (0x10)
+#define S3C2410_SPRDAT  (0x14)
+
+#endif /* __ASM_ARCH_REGS_SPI_H */
index 75c5955..b5b4aaf 100644 (file)
@@ -29,6 +29,8 @@
 #define S3C2410_TCFG_PRESCALER0_MASK (255<<0)
 #define S3C2410_TCFG_PRESCALER1_MASK (255<<8)
 #define S3C2410_TCFG_PRESCALER1_SHIFT (8)
+#define S3C2410_TCFG_DEADZONE_MASK   (255<<16)
+#define S3C2410_TCFG_DEADZONE_SHIFT  (16)
 
 #define S3C2410_TCFG1_MUX4_DIV2          (0<<16)
 #define S3C2410_TCFG1_MUX4_DIV4          (1<<16)
diff --git a/include/asm-arm/arch-s3c2410/regs-udc.h b/include/asm-arm/arch-s3c2410/regs-udc.h
new file mode 100644 (file)
index 0000000..aee2805
--- /dev/null
@@ -0,0 +1,162 @@
+/* linux/include/asm/arch-s3c2410/regs-udc.h
+ *
+ * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
+ *
+ * This include file is free software; you can redistribute 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.
+ *
+ *  Changelog:
+ *    01-08-2004       initial creation
+ *    12-09-2004       cleanup for submission
+ */
+
+#ifndef __ASM_ARCH_REGS_UDC_H
+#define __ASM_ARCH_REGS_UDC_H
+
+
+#define S3C2410_USBDREG(x) ((x) + S3C2410_VA_USBDEV)
+
+#define S3C2410_UDC_FUNC_ADDR_REG      S3C2410_USBDREG(0x0140)
+#define S3C2410_UDC_PWR_REG            S3C2410_USBDREG(0x0144)
+#define S3C2410_UDC_EP_INT_REG         S3C2410_USBDREG(0x0148)
+
+#define S3C2410_UDC_USB_INT_REG                S3C2410_USBDREG(0x0158)
+#define S3C2410_UDC_EP_INT_EN_REG      S3C2410_USBDREG(0x015c)
+
+#define S3C2410_UDC_USB_INT_EN_REG     S3C2410_USBDREG(0x016c)
+
+#define S3C2410_UDC_FRAME_NUM1_REG     S3C2410_USBDREG(0x0170)
+#define S3C2410_UDC_FRAME_NUM2_REG     S3C2410_USBDREG(0x0174)
+
+#define S3C2410_UDC_EP0_FIFO_REG       S3C2410_USBDREG(0x01c0)
+#define S3C2410_UDC_EP1_FIFO_REG       S3C2410_USBDREG(0x01c4)
+#define S3C2410_UDC_EP2_FIFO_REG       S3C2410_USBDREG(0x01c8)
+#define S3C2410_UDC_EP3_FIFO_REG       S3C2410_USBDREG(0x01cc)
+#define S3C2410_UDC_EP4_FIFO_REG       S3C2410_USBDREG(0x01d0)
+
+#define S3C2410_UDC_EP1_DMA_CON                S3C2410_USBDREG(0x0200)
+#define S3C2410_UDC_EP1_DMA_UNIT       S3C2410_USBDREG(0x0204)
+#define S3C2410_UDC_EP1_DMA_FIFO       S3C2410_USBDREG(0x0208)
+#define S3C2410_UDC_EP1_DMA_TTC_L      S3C2410_USBDREG(0x020c)
+#define S3C2410_UDC_EP1_DMA_TTC_M      S3C2410_USBDREG(0x0210)
+#define S3C2410_UDC_EP1_DMA_TTC_H      S3C2410_USBDREG(0x0214)
+
+#define S3C2410_UDC_EP2_DMA_CON                S3C2410_USBDREG(0x0218)
+#define S3C2410_UDC_EP2_DMA_UNIT       S3C2410_USBDREG(0x021c)
+#define S3C2410_UDC_EP2_DMA_FIFO       S3C2410_USBDREG(0x0220)
+#define S3C2410_UDC_EP2_DMA_TTC_L      S3C2410_USBDREG(0x0224)
+#define S3C2410_UDC_EP2_DMA_TTC_M      S3C2410_USBDREG(0x0228)
+#define S3C2410_UDC_EP2_DMA_TTC_H      S3C2410_USBDREG(0x022c)
+
+#define S3C2410_UDC_EP3_DMA_CON                S3C2410_USBDREG(0x0240)
+#define S3C2410_UDC_EP3_DMA_UNIT       S3C2410_USBDREG(0x0244)
+#define S3C2410_UDC_EP3_DMA_FIFO       S3C2410_USBDREG(0x0248)
+#define S3C2410_UDC_EP3_DMA_TTC_L      S3C2410_USBDREG(0x024c)
+#define S3C2410_UDC_EP3_DMA_TTC_M      S3C2410_USBDREG(0x0250)
+#define S3C2410_UDC_EP3_DMA_TTC_H      S3C2410_USBDREG(0x0254)
+
+#define S3C2410_UDC_EP4_DMA_CON                S3C2410_USBDREG(0x0258)
+#define S3C2410_UDC_EP4_DMA_UNIT       S3C2410_USBDREG(0x025c)
+#define S3C2410_UDC_EP4_DMA_FIFO       S3C2410_USBDREG(0x0260)
+#define S3C2410_UDC_EP4_DMA_TTC_L      S3C2410_USBDREG(0x0264)
+#define S3C2410_UDC_EP4_DMA_TTC_M      S3C2410_USBDREG(0x0268)
+#define S3C2410_UDC_EP4_DMA_TTC_H      S3C2410_USBDREG(0x026c)
+
+#define S3C2410_UDC_INDEX_REG          S3C2410_USBDREG(0x0178)
+
+/* indexed registers */
+
+#define S3C2410_UDC_MAXP_REG           S3C2410_USBDREG(0x018c)
+
+#define S3C2410_UDC_EP0_CSR_REG                S3C2410_USBDREG(0x0184)
+
+#define S3C2410_UDC_IN_CSR1_REG                S3C2410_USBDREG(0x0184)
+#define S3C2410_UDC_IN_CSR2_REG                S3C2410_USBDREG(0x0188)
+
+#define S3C2410_UDC_OUT_CSR1_REG       S3C2410_USBDREG(0x0190)
+#define S3C2410_UDC_OUT_CSR2_REG       S3C2410_USBDREG(0x0194)
+#define S3C2410_UDC_OUT_FIFO_CNT1_REG  S3C2410_USBDREG(0x0198)
+#define S3C2410_UDC_OUT_FIFO_CNT2_REG  S3C2410_USBDREG(0x019c)
+
+
+
+#define S3C2410_UDC_PWR_ISOUP          (1<<7) // R/W
+#define S3C2410_UDC_PWR_RESET          (1<<3) // R
+#define S3C2410_UDC_PWR_RESUME         (1<<2) // R/W
+#define S3C2410_UDC_PWR_SUSPEND                (1<<1) // R
+#define S3C2410_UDC_PWR_ENSUSPEND      (1<<0) // R/W
+
+#define S3C2410_UDC_PWR_DEFAULT                0x00
+
+#define S3C2410_UDC_INT_EP4            (1<<4) // R/W (clear only)
+#define S3C2410_UDC_INT_EP3            (1<<3) // R/W (clear only)
+#define S3C2410_UDC_INT_EP2            (1<<2) // R/W (clear only)
+#define S3C2410_UDC_INT_EP1            (1<<1) // R/W (clear only)
+#define S3C2410_UDC_INT_EP0            (1<<0) // R/W (clear only)
+
+#define S3C2410_UDC_USBINT_RESET       (1<<2) // R/W (clear only)
+#define S3C2410_UDC_USBINT_RESUME      (1<<1) // R/W (clear only)
+#define S3C2410_UDC_USBINT_SUSPEND     (1<<0) // R/W (clear only)
+
+#define S3C2410_UDC_INTE_EP4           (1<<4) // R/W
+#define S3C2410_UDC_INTE_EP3           (1<<3) // R/W
+#define S3C2410_UDC_INTE_EP2           (1<<2) // R/W
+#define S3C2410_UDC_INTE_EP1           (1<<1) // R/W
+#define S3C2410_UDC_INTE_EP0           (1<<0) // R/W
+
+#define S3C2410_UDC_USBINTE_RESET      (1<<2) // R/W
+#define S3C2410_UDC_USBINTE_SUSPEND    (1<<0) // R/W
+
+
+#define S3C2410_UDC_INDEX_EP0          (0x00)
+#define S3C2410_UDC_INDEX_EP1          (0x01) // ??
+#define S3C2410_UDC_INDEX_EP2          (0x02) // ??
+#define S3C2410_UDC_INDEX_EP3          (0x03) // ??
+#define S3C2410_UDC_INDEX_EP4          (0x04) // ??
+
+#define S3C2410_UDC_ICSR1_CLRDT                (1<<6) // R/W
+#define S3C2410_UDC_ICSR1_SENTSTL      (1<<5) // R/W (clear only)
+#define S3C2410_UDC_ICSR1_SENDSTL      (1<<4) // R/W
+#define S3C2410_UDC_ICSR1_FFLUSH       (1<<3) // W   (set only)
+#define S3C2410_UDC_ICSR1_UNDRUN       (1<<2) // R/W (clear only)
+#define S3C2410_UDC_ICSR1_PKTRDY       (1<<0) // R/W (set only)
+
+#define S3C2410_UDC_ICSR2_AUTOSET      (1<<7) // R/W
+#define S3C2410_UDC_ICSR2_ISO          (1<<6) // R/W
+#define S3C2410_UDC_ICSR2_MODEIN       (1<<5) // R/W
+#define S3C2410_UDC_ICSR2_DMAIEN       (1<<4) // R/W
+
+#define S3C2410_UDC_OCSR1_CLRDT                (1<<7) // R/W
+#define S3C2410_UDC_OCSR1_SENTSTL      (1<<6) // R/W (clear only)
+#define S3C2410_UDC_OCSR1_SENDSTL      (1<<5) // R/W
+#define S3C2410_UDC_OCSR1_FFLUSH       (1<<4) // R/W
+#define S3C2410_UDC_OCSR1_DERROR       (1<<3) // R
+#define S3C2410_UDC_OCSR1_OVRRUN       (1<<2) // R/W (clear only)
+#define S3C2410_UDC_OCSR1_PKTRDY       (1<<0) // R/W (clear only)
+
+#define S3C2410_UDC_OCSR2_AUTOCLR      (1<<7) // R/W
+#define S3C2410_UDC_OCSR2_ISO          (1<<6) // R/W
+#define S3C2410_UDC_OCSR2_DMAIEN       (1<<5) // R/W
+
+#define S3C2410_UDC_SETIX(x)       \
+       __raw_writel(S3C2410_UDC_INDEX_ ## x, 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)
+#define S3C2410_UDC_EP0_CSR_DE         (1<<3)
+#define S3C2410_UDC_EP0_CSR_SE         (1<<4)
+#define S3C2410_UDC_EP0_CSR_SENDSTL    (1<<5)
+#define S3C2410_UDC_EP0_CSR_SOPKTRDY   (1<<6)
+#define S3C2410_UDC_EP0_CSR_SSE        (1<<7)
+
+#define S3C2410_UDC_MAXP_8             (1<<0)
+#define S3C2410_UDC_MAXP_16            (1<<1)
+#define S3C2410_UDC_MAXP_32            (1<<2)
+#define S3C2410_UDC_MAXP_64            (1<<3)
+
+
+#endif
index ab01f53..023f22b 100644 (file)
@@ -100,7 +100,7 @@ putc(char ch)
 }
 
 static void
-puts(const char *ptr)
+putstr(const char *ptr)
 {
        for (; *ptr != '\0'; ptr++) {
                putc(*ptr);
diff --git a/include/asm-arm/arch-s3c2410/usb-control.h b/include/asm-arm/arch-s3c2410/usb-control.h
new file mode 100644 (file)
index 0000000..1cc85a0
--- /dev/null
@@ -0,0 +1,45 @@
+/* linux/include/asm-arm/arch-s3c2410/usb-control.h
+ *
+ * (c) 2004 Simtec Electronics
+ *  Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - usb port information
+ *
+ * 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.
+ *
+ * Changelog:
+ *  11-Sep-2004 BJD  Created file
+ *  21-Sep-2004 BJD  Updated port info
+*/
+
+#ifndef __ASM_ARCH_USBCONTROL_H
+#define __ASM_ARCH_USBCONTROL_H "include/asm-arm/arch-s3c2410/usb-control.h"
+
+#define S3C_HCDFLG_USED        (1)
+
+struct s3c2410_hcd_port {
+       unsigned char   flags;
+       unsigned char   power;
+       unsigned char   oc_status;
+       unsigned char   oc_changed;
+};
+
+struct s3c2410_hcd_info {
+       struct usb_hcd          *hcd;
+       struct s3c2410_hcd_port port[2];
+
+       void            (*power_control)(int port, int to);
+       void            (*enable_oc)(struct s3c2410_hcd_info *, int on);
+       void            (*report_oc)(struct s3c2410_hcd_info *, int ports);
+};
+
+static void inline s3c2410_report_oc(struct s3c2410_hcd_info *info, int ports)
+{
+       if (info->report_oc != NULL) {
+               (info->report_oc)(info, ports);
+       }
+}
+
+#endif /*__ASM_ARCH_USBCONTROL_H */
index 42d28b2..4345350 100644 (file)
@@ -17,7 +17,7 @@
 
 #define UART(x)                (*(volatile unsigned long *)(serial_port + (x)))
 
-static void puts( const char *s )
+static void putstr( const char *s )
 {
        unsigned long serial_port;
 
index 162a75a..910a8e0 100644 (file)
@@ -21,7 +21,7 @@ static __inline__ void putc(char c)
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
        while (*s) {
                putc(*s);
index 5f1c975..994e0ae 100644 (file)
@@ -345,7 +345,7 @@ static inline unsigned long __ffs(unsigned long word)
 extern __inline__ int generic_fls(int x);
 #define fls(x) \
        ( __builtin_constant_p(x) ? generic_fls(x) : \
-         ({ int __r; asm("clz%?\t%0, %1" : "=r"(__r) : "r"(x)); 32-__r; }) )
+         ({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }) )
 #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
 #define __ffs(x) (ffs(x) - 1)
 #define ffz(x) __ffs( ~(x) )
index a1afde7..5e91b90 100644 (file)
@@ -8,23 +8,15 @@ extern volatile void __bug(const char *file, int line, void *data);
 
 /* give file/line information */
 #define BUG()          __bug(__FILE__, __LINE__, NULL)
-#define PAGE_BUG(page) __bug(__FILE__, __LINE__, page)
 
 #else
 
-/* these just cause an oops */
+/* this just causes an oops */
 #define BUG()          (*(int *)0 = 0)
-#define PAGE_BUG(page) (*(int *)0 = 0)
 
 #endif
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
index b67e06c..29533be 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASMARM_ELF_H
 #define __ASMARM_ELF_H
 
+#include <linux/config.h>
+
 /*
  * ELF register definitions..
  */
@@ -14,6 +16,7 @@ typedef unsigned long elf_freg_t[3];
 
 #define EM_ARM 40
 #define EF_ARM_APCS26 0x08
+#define EF_ARM_SOFT_FLOAT 0x200
 
 #define R_ARM_NONE     0
 #define R_ARM_PC24     1
@@ -91,6 +94,8 @@ extern char elf_platform[];
        (( (elf_hwcap & HWCAP_26BIT) && (x)->e_flags & EF_ARM_APCS26) || \
          ((x)->e_flags & EF_ARM_APCS26) == 0)
 
+#ifndef CONFIG_IWMMXT
+
 /* Old NetWinder binaries were compiled in such a way that the iBCS
    heuristic always trips on them.  Until these binaries become uncommon
    enough not to care, don't trust the `ibcs' flag here.  In any case
@@ -99,6 +104,28 @@ extern char elf_platform[];
 #define SET_PERSONALITY(ex,ibcs2) \
        set_personality(((ex).e_flags&EF_ARM_APCS26 ?PER_LINUX :PER_LINUX_32BIT))
 
+#else
+
+/*
+ * All iWMMXt capable CPUs don't support 26-bit mode.  Yet they can run
+ * legacy binaries which used to contain FPA11 floating point instructions
+ * that have always been emulated by the kernel.  PFA11 and iWMMXt overlap
+ * on coprocessor 1 space though.  We therefore must decide if given task
+ * is allowed to use CP 0 and 1 for iWMMXt, or if they should be blocked
+ * at all times for the prefetch exception handler to catch FPA11 opcodes
+ * and emulate them.  The best indication to discriminate those two cases
+ * is the SOFT_FLOAT flag in the ELF header.
+ */
+
+#define SET_PERSONALITY(ex,ibcs2) \
+do { \
+       set_personality(PER_LINUX_32BIT); \
+       if ((ex).e_flags & EF_ARM_SOFT_FLOAT) \
+               set_thread_flag(TIF_USING_IWMMXT); \
+} while (0)
+
+#endif
+
 #endif
 
 #endif
index cb8c525..3f734c4 100644 (file)
@@ -22,31 +22,25 @@ typedef struct {
  *
  * - bits 0-7 are the preemption count (max depth: 256)
  * - bits 8-15 are the softirq count (max # of softirqs: 256)
- * - bits 16-23 are the hardirq count (max # of hardirqs: 256)
+ * - bits 16-24 are the hardirq count (max # of hardirqs: 512)
  * - bit 26 is the PREEMPT_ACTIVE flag
+ *
+ * We optimize HARDIRQ_BITS for immediate constant, and only
+ * increase it if really needed.
  */
 #define PREEMPT_BITS   8
 #define SOFTIRQ_BITS   8
+
+#if NR_IRQS > 256
+#define HARDIRQ_BITS   9
+#else
 #define HARDIRQ_BITS   8
+#endif
 
 #define PREEMPT_SHIFT  0
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK|SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space
  * for potentially all IRQ sources in the system nesting
@@ -56,29 +50,9 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
 #define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# define in_atomic()   ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #ifndef CONFIG_SMP
-
 extern asmlinkage void __do_softirq(void);
 
 #define irq_exit()                                                     \
@@ -88,10 +62,6 @@ extern asmlinkage void __do_softirq(void);
                        __do_softirq();                                 \
                preempt_enable_no_resched();                            \
        } while (0)
-
-#define synchronize_irq(irq)   barrier()
-#else
-extern void synchronize_irq(unsigned int irq);
 #endif
 
 #endif /* __ASM_HARDIRQ_H */
index 283dde1..1fd1a5b 100644 (file)
 
 #include <asm/arch/hardware.h>
 
-#ifndef __ASSEMBLY__
-
-struct platform_device;
-
-extern int platform_add_devices(struct platform_device **, int);
-extern int platform_add_device(struct platform_device *);
-
-#endif
-
 #endif
diff --git a/include/asm-arm/hardware/amba_clcd.h b/include/asm-arm/hardware/amba_clcd.h
new file mode 100644 (file)
index 0000000..65436fe
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * linux/include/asm-arm/hardware/amba_clcd.h -- Integrator LCD panel.
+ *
+ * David A Rusling
+ *
+ * Copyright (C) 2001 ARM Limited
+ *
+ * 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/config.h>
+#include <linux/fb.h>
+
+/*
+ * CLCD Controller Internal Register addresses
+ */
+#define CLCD_TIM0              0x00000000
+#define CLCD_TIM1              0x00000004
+#define CLCD_TIM2              0x00000008
+#define CLCD_TIM3              0x0000000c
+#define CLCD_UBAS              0x00000010
+#define CLCD_LBAS              0x00000014
+
+#ifndef CONFIG_ARCH_VERSATILE_PB
+#define CLCD_IENB              0x00000018
+#define CLCD_CNTL              0x0000001c
+#else
+/*
+ * Someone rearranged these two registers on the Versatile
+ * platform...
+ */
+#define CLCD_IENB              0x0000001c
+#define CLCD_CNTL              0x00000018
+#endif
+
+#define CLCD_STAT              0x00000020
+#define CLCD_INTR              0x00000024
+#define CLCD_UCUR              0x00000028
+#define CLCD_LCUR              0x0000002C
+#define CLCD_PALL              0x00000200
+#define CLCD_PALETTE           0x00000200
+
+#define TIM2_CLKSEL            (1 << 5)
+#define TIM2_IVS               (1 << 11)
+#define TIM2_IHS               (1 << 12)
+#define TIM2_IPC               (1 << 13)
+#define TIM2_IOE               (1 << 14)
+#define TIM2_BCD               (1 << 26)
+
+#define CNTL_LCDEN             (1 << 0)
+#define CNTL_LCDBPP1           (0 << 1)
+#define CNTL_LCDBPP2           (1 << 1)
+#define CNTL_LCDBPP4           (2 << 1)
+#define CNTL_LCDBPP8           (3 << 1)
+#define CNTL_LCDBPP16          (4 << 1)
+#define CNTL_LCDBPP24          (5 << 1)
+#define CNTL_LCDBW             (1 << 4)
+#define CNTL_LCDTFT            (1 << 5)
+#define CNTL_LCDMONO8          (1 << 6)
+#define CNTL_LCDDUAL           (1 << 7)
+#define CNTL_BGR               (1 << 8)
+#define CNTL_BEBO              (1 << 9)
+#define CNTL_BEPO              (1 << 10)
+#define CNTL_LCDPWR            (1 << 11)
+#define CNTL_LCDVCOMP(x)       ((x) << 12)
+#define CNTL_LDMAFIFOTIME      (1 << 15)
+#define CNTL_WATERMARK         (1 << 16)
+
+struct clcd_panel {
+       struct fb_videomode     mode;
+       signed short            width;  /* width in mm */
+       signed short            height; /* height in mm */
+       u32                     tim2;
+       u32                     tim3;
+       u32                     cntl;
+       unsigned int            bpp:8,
+                               fixedtimings:1,
+                               grayscale:1;
+       unsigned int            connector;
+};
+
+struct clcd_regs {
+       u32                     tim0;
+       u32                     tim1;
+       u32                     tim2;
+       u32                     tim3;
+       u32                     cntl;
+       unsigned long           pixclock;
+};
+
+struct clcd_fb;
+
+/*
+ * the board-type specific routines
+ */
+struct clcd_board {
+       const char *name;
+
+       /*
+        * Optional.  Check whether the var structure is acceptable
+        * for this display.
+        */
+       int     (*check)(struct clcd_fb *fb, struct fb_var_screeninfo *var);
+
+       /*
+        * Compulsary.  Decode fb->fb.var into regs->*.  In the case of
+        * fixed timing, set regs->* to the register values required.
+        */
+       void    (*decode)(struct clcd_fb *fb, struct clcd_regs *regs);
+
+       /*
+        * Optional.  Disable any extra display hardware.
+        */
+       void    (*disable)(struct clcd_fb *);
+
+       /*
+        * Optional.  Enable any extra display hardware.
+        */
+       void    (*enable)(struct clcd_fb *);
+
+       /*
+        * Setup platform specific parts of CLCD driver
+        */
+       int     (*setup)(struct clcd_fb *);
+
+       /*
+        * Remove platform specific parts of CLCD driver
+        */
+       void    (*remove)(struct clcd_fb *);
+};
+
+struct amba_device;
+struct clk;
+
+/* this data structure describes each frame buffer device we find */
+struct clcd_fb {
+       struct fb_info          fb;
+       struct amba_device      *dev;
+       struct clk              *clk;
+       struct clcd_panel       *panel;
+       struct clcd_board       *board;
+       void                    *board_data;
+       void                    *regs;
+       u32                     clcd_cntl;
+       u32                     cmap[16];
+};
+
+static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
+{
+       u32 val;
+
+       /*
+        * Program the CLCD controller registers and start the CLCD
+        */
+       val = ((fb->fb.var.xres / 16) - 1) << 2;
+       val |= (fb->fb.var.hsync_len - 1) << 8;
+       val |= (fb->fb.var.right_margin - 1) << 16;
+       val |= (fb->fb.var.left_margin - 1) << 24;
+       regs->tim0 = val;
+
+       val = fb->fb.var.yres - 1;
+       val |= (fb->fb.var.vsync_len - 1) << 10;
+       val |= fb->fb.var.lower_margin << 16;
+       val |= fb->fb.var.upper_margin << 24;
+       regs->tim1 = val;
+
+       val = fb->panel->tim2;
+       val |= fb->fb.var.sync & FB_SYNC_HOR_HIGH_ACT  ? 0 : TIM2_IHS;
+       val |= fb->fb.var.sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS;
+
+       if (fb->panel->cntl & CNTL_LCDTFT)
+               val |= (fb->fb.var.xres_virtual - 1) << 16;
+       else if (fb->panel->cntl & CNTL_LCDBW)
+               printk("what value for CPL for stnmono panels?");
+       else
+               val |= ((fb->fb.var.xres_virtual * 8 / 3) - 1) << 16;
+       regs->tim2 = val;
+
+       regs->tim3 = fb->panel->tim3;
+
+       val = fb->panel->cntl;
+       if (fb->fb.var.grayscale)
+               val |= CNTL_LCDBW;
+
+       switch (fb->fb.var.bits_per_pixel) {
+       case 1:
+               val |= CNTL_LCDBPP1;
+               break;
+       case 2:
+               val |= CNTL_LCDBPP2;
+               break;
+       case 4:
+               val |= CNTL_LCDBPP4;
+               break;
+       case 8:
+               val |= CNTL_LCDBPP8;
+               break;
+       case 16:
+               val |= CNTL_LCDBPP16;
+               break;
+       case 24:
+               val |= CNTL_LCDBPP24;
+               break;
+       }
+
+       regs->cntl = val;
+       regs->pixclock = fb->fb.var.pixclock;
+}
+
+static inline int clcdfb_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+       var->xres_virtual = var->xres = (var->xres + 7) & ~7;
+       var->yres_virtual = var->yres;
+
+#define CHECK(e,l,h) (var->e < l || var->e > h)
+       if (CHECK(right_margin, (5+1), 256) ||  /* back porch */
+           CHECK(left_margin, (5+1), 256) ||   /* front porch */
+           CHECK(hsync_len, (5+1), 256) ||
+           var->xres > 4096 ||
+           var->lower_margin > 255 ||          /* back porch */
+           var->upper_margin > 255 ||          /* front porch */
+           var->vsync_len > 32 ||
+           var->yres > 1024)
+               return -EINVAL;
+#undef CHECK
+
+       /* single panel mode: PCD = max(PCD, 1) */
+       /* dual panel mode: PCD = max(PCD, 5) */
+
+       /*
+        * You can't change the grayscale setting, and
+        * we can only do non-interlaced video.
+        */
+       if (var->grayscale != fb->fb.var.grayscale ||
+           (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+               return -EINVAL;
+
+#define CHECK(e) (var->e != fb->fb.var.e)
+       if (fb->panel->fixedtimings &&
+           (CHECK(xres)                ||
+            CHECK(yres)                ||
+            CHECK(bits_per_pixel)      ||
+            CHECK(pixclock)            ||
+            CHECK(left_margin)         ||
+            CHECK(right_margin)        ||
+            CHECK(upper_margin)        ||
+            CHECK(lower_margin)        ||
+            CHECK(hsync_len)           ||
+            CHECK(vsync_len)           ||
+            CHECK(sync)))
+               return -EINVAL;
+#undef CHECK
+
+       var->nonstd = 0;
+       var->accel_flags = 0;
+
+       return 0;
+}
index 9dfc062..4983449 100644 (file)
@@ -64,7 +64,7 @@ int clk_use(struct clk *clk);
 void clk_unuse(struct clk *clk);
 
 /**
- * clk_get_rate - obtain the current clock rate for a clock source.
+ * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *               This is only valid once the clock source has been enabled.
  * @clk: clock source
  */
@@ -85,16 +85,16 @@ void clk_put(struct clk *clk);
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source
- * @rate: desired clock rate in kHz
+ * @rate: desired clock rate in Hz
  *
- * Returns rounded clock rate, or negative errno.
+ * Returns rounded clock rate in Hz, or negative errno.
  */
 long clk_round_rate(struct clk *clk, unsigned long rate);
  
 /**
  * clk_set_rate - set the clock rate for a clock source
  * @clk: clock source
- * @rate: desired clock rate in kHz
+ * @rate: desired clock rate in Hz
  *
  * Returns success (0) or negative errno.
  */
index 93aa555..1855fb7 100644 (file)
@@ -271,10 +271,12 @@ extern void __iounmap(void *addr);
 #ifndef __arch_ioremap
 #define ioremap(cookie,size)           __ioremap(cookie,size,0,1)
 #define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
+#define ioremap_cached(cookie,size)    __ioremap(cookie,size,L_PTE_CACHEABLE,1)
 #define iounmap(cookie)                        __iounmap(cookie)
 #else
 #define ioremap(cookie,size)           __arch_ioremap((cookie),(size),0,1)
 #define ioremap_nocache(cookie,size)   __arch_ioremap((cookie),(size),0,1)
+#define ioremap_cached(cookie,size)    __arch_ioremap((cookie),(size),L_PTE_CACHEABLE,1)
 #define iounmap(cookie)                        __arch_iounmap(cookie)
 #endif
 
diff --git a/include/asm-arm/mach/mmc.h b/include/asm-arm/mach/mmc.h
new file mode 100644 (file)
index 0000000..41a946e
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  linux/include/asm-arm/mach/mmc.h
+ */
+#ifndef ASMARM_MACH_MMC_H
+#define ASMARM_MACH_MMC_H
+
+#include <linux/mmc/protocol.h>
+
+struct mmc_platform_data {
+       unsigned int mclk;                      /* mmc base clock rate */
+       unsigned int ocr_mask;                  /* available voltages */
+       u32 (*translate_vdd)(struct device *, unsigned int);
+       unsigned int (*status)(struct device *);
+};
+
+#endif
index ea0b992..25d540e 100644 (file)
@@ -52,14 +52,14 @@ void pci_common_init(struct hw_pci *);
 /*
  * PCI controllers
  */
-extern int iop310_setup(int nr, struct pci_sys_data *);
-extern struct pci_bus *iop310_scan_bus(int nr, struct pci_sys_data *);
-extern void iop310_init(void);
-
 extern int iop321_setup(int nr, struct pci_sys_data *);
 extern struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *);
 extern void iop321_init(void);
 
+extern int iop331_setup(int nr, struct pci_sys_data *);
+extern struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *);
+extern void iop331_init(void);
+
 extern int dc21285_setup(int nr, struct pci_sys_data *);
 extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
 extern void dc21285_preinit(void);
index edb6fcc..51728ed 100644 (file)
 extern void (*init_arch_time)(void);
 
 extern int (*set_rtc)(void);
-extern unsigned long(*gettimeoffset)(void);
+extern unsigned long (*gettimeoffset)(void);
 
-void timer_tick(struct pt_regs *);
+extern void timer_tick(struct pt_regs *);
+
+extern void save_time_delta(struct timespec *delta, struct timespec *rtc);
+extern void restore_time_delta(struct timespec *delta, struct timespec *rtc);
 
 #endif
index 41a2f4f..94223d4 100644 (file)
 #ifndef __ASM_PARAM_H
 #define __ASM_PARAM_H
 
-#include <asm/arch/param.h>    /* for HZ */
+#ifdef __KERNEL__
+# include <asm/arch/param.h>           /* for kernel version of HZ */
 
-#ifndef __KERNEL_HZ
-#define __KERNEL_HZ    100
-#endif
+# ifndef HZ
+#  define HZ           100             /* Internal kernel timer frequency */
+# endif
 
-#ifdef __KERNEL__
-# define HZ            __KERNEL_HZ     /* Internal kernel timer frequency */
 # define USER_HZ       100             /* User interfaces are in "ticks" */
 # define CLOCKS_PER_SEC        (USER_HZ)       /* like times() */
 #else
index 162c456..f227d7d 100644 (file)
@@ -131,6 +131,12 @@ static inline int valid_user_regs(struct pt_regs *regs)
 #define instruction_pointer(regs) \
        (pc_pointer((regs)->ARM_pc))
 
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *regs);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
+
 #ifdef __KERNEL__
 extern void show_regs(struct pt_regs *);
 
index 2e47880..60f33e6 100644 (file)
@@ -16,21 +16,12 @@ struct semaphore {
        atomic_t count;
        int sleepers;
        wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-       long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name)        .__magic = (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INIT(name,cnt) {                           \
+#define __SEMAPHORE_INIT(name, cnt)                            \
+{                                                              \
        .count  = ATOMIC_INIT(cnt),                             \
        .wait   = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),   \
-       __SEM_DEBUG_INIT(name)                                  \
 }
 
 #define __MUTEX_INITIALIZER(name) __SEMAPHORE_INIT(name,1)
@@ -46,9 +37,6 @@ static inline void sema_init(struct semaphore *sem, int val)
        atomic_set(&sem->count, val);
        sem->sleepers = 0;
        init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX(struct semaphore *sem)
@@ -85,9 +73,6 @@ extern void __up(struct semaphore * sem);
  */
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        __down_op(sem, __down_failed);
 }
@@ -98,19 +83,12 @@ static inline void down(struct semaphore * sem)
  */
 static inline int down_interruptible (struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        return __down_op_ret(sem, __down_interruptible_failed);
 }
 
 static inline int down_trylock(struct semaphore *sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        return __down_op_ret(sem, __down_trylock_failed);
 }
 
@@ -122,10 +100,6 @@ static inline int down_trylock(struct semaphore *sem)
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        __up_op(sem, __up_wakeup);
 }
 
index b05e717..46d2058 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
index a1afde7..920b705 100644 (file)
@@ -5,26 +5,13 @@
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 extern volatile void __bug(const char *file, int line, void *data);
-
 /* give file/line information */
 #define BUG()          __bug(__FILE__, __LINE__, NULL)
-#define PAGE_BUG(page) __bug(__FILE__, __LINE__, page)
-
 #else
-
-/* these just cause an oops */
 #define BUG()          (*(int *)0 = 0)
-#define PAGE_BUG(page) (*(int *)0 = 0)
-
 #endif
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
index 623b5f8..52feb95 100644 (file)
@@ -32,20 +32,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK|SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space
  * for potentially all IRQ sources in the system nesting
@@ -55,26 +41,8 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
 #define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# define in_atomic()    ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()    (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #ifndef CONFIG_SMP
 #define irq_exit()                                                     \
        do {                                                            \
@@ -84,9 +52,6 @@ typedef struct {
                preempt_enable_no_resched();                            \
        } while (0)
 
-#define synchronize_irq(irq)   barrier()
-#else
-#error SMP not supported
 #endif
 
 #endif /* __ASM_HARDIRQ_H */
index 05aa6e2..6a46b5a 100644 (file)
@@ -30,6 +30,7 @@
 
 #define pc_pointer(v) ((v) & ~PCMASK)   /* convert v to pc type address */
 #define instruction_pointer(regs) (pc_pointer((regs)->ARM_pc)) /* get pc */
+#define profile_pc(regs) instruction_pointer(regs)
 
 /* this struct defines the way the registers are stored on the
    stack during a system call. */
index 4994627..c1b6a1e 100644 (file)
@@ -16,22 +16,14 @@ struct semaphore {
        atomic_t count;
        int sleepers;
        wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-       long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-               , (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INIT(name,count)                   \
-       { ATOMIC_INIT(count), 0,                        \
-         __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
-         __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INIT(name, n)                                      \
+{                                                                      \
+       .count          = ATOMIC_INIT(n),                               \
+       .sleepers       = 0,                                            \
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),   \
+}
 
 #define __MUTEX_INITIALIZER(name) \
        __SEMAPHORE_INIT(name,1)
@@ -47,9 +39,6 @@ static inline void sema_init(struct semaphore *sem, int val)
        atomic_set(&sem->count, val);
        sem->sleepers = 0;
        init_waitqueue_head(&sem->wait);
-#if WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX(struct semaphore *sem)
@@ -81,9 +70,6 @@ extern void __up(struct semaphore * sem);
  */
 static inline void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        __down_op(sem, __down_failed);
 }
@@ -94,19 +80,12 @@ static inline void down(struct semaphore * sem)
  */
 static inline int down_interruptible (struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        return __down_op_ret(sem, __down_interruptible_failed);
 }
 
 static inline int down_trylock(struct semaphore *sem)
 {
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        return __down_op_ret(sem, __down_trylock_failed);
 }
 
@@ -118,10 +97,6 @@ static inline int down_trylock(struct semaphore *sem)
  */
 static inline void up(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        __up_op(sem, __up_wakeup);
 }
 
index b05e717..46d2058 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
index 939d984..fb14c5e 100644 (file)
@@ -109,6 +109,7 @@ struct switch_stack {
 /* bit 8 is user-mode flag */
 #define user_mode(regs) (((regs)->dccr & 0x100) != 0)
 #define instruction_pointer(regs) ((regs)->irp)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 
 #endif
index d6286c2..8dd6b23 100644 (file)
@@ -1,21 +1,4 @@
 #ifndef _CRIS_BUG_H
 #define _CRIS_BUG_H
-
-#define BUG() do { \
-  printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define PAGE_BUG(page) do { \
-         BUG(); \
-} while (0)
-
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
index c75100f..4e28c83 100644 (file)
@@ -40,20 +40,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -63,27 +49,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
 #define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()   ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()                                                     \
 do {                                                                   \
                preempt_count() -= IRQ_EXIT_OFFSET;                     \
@@ -92,6 +58,4 @@ do {                                                                  \
                preempt_enable_no_resched();                            \
 } while (0)
 
-#define synchronize_irq(irq)   barrier()
-
 #endif /* __ASM_HARDIRQ_H */
index b442180..f159b4f 100644 (file)
 
 #define SO_PEERSEC             31
 
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM     1               /* stream (connection) socket   */
-#define SOCK_DGRAM      2               /* datagram (conn.less) socket  */
-#define SOCK_RAW        3               /* raw socket                   */
-#define SOCK_RDM        4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET  5               /* sequential packet socket     */
-#define SOCK_PACKET     10              /* linux specific way of        */
-                                        /* getting packets at the dev   */
-                                        /* level.  For writing rarp and */
-                                        /* other similar things on the  */
-                                        /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
 
 
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
new file mode 100644 (file)
index 0000000..e5913c3
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _ASM_GENERIC_BUG_H
+#define _ASM_GENERIC_BUG_H
+
+#include <linux/compiler.h>
+#include <linux/config.h>
+
+#ifndef HAVE_ARCH_BUG
+#define BUG() do { \
+       printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+       panic("BUG!"); \
+} while (0)
+#endif
+
+#ifndef HAVE_ARCH_PAGE_BUG
+#define PAGE_BUG(page) do { \
+       printk("page BUG for page at %p\n", page); \
+       BUG(); \
+} while (0)
+#endif
+
+#ifndef HAVE_ARCH_BUG_ON
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+#endif
+
+#ifndef HAVE_ARCH_WARN_ON
+#define WARN_ON(condition) do { \
+       if (unlikely((condition)!=0)) { \
+               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+               dump_stack(); \
+       } \
+} while (0)
+#endif
+
+#endif
index 8574de4..1b91d06 100644 (file)
@@ -5,7 +5,7 @@
 #define __ide_outsw    outsw
 #define __ide_outsl    outsl
 
-static __inline__ void __ide_mm_insw(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
 {
        while (count--) {
                *(u16 *)addr = readw(port);
@@ -13,7 +13,7 @@ static __inline__ void __ide_mm_insw(unsigned long port, void *addr, u32 count)
        }
 }
 
-static __inline__ void __ide_mm_insl(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
 {
        while (count--) {
                *(u32 *)addr = readl(port);
@@ -21,7 +21,7 @@ static __inline__ void __ide_mm_insl(unsigned long port, void *addr, u32 count)
        }
 }
 
-static __inline__ void __ide_mm_outsw(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
 {
        while (count--) {
                writew(*(u16 *)addr, port);
@@ -29,7 +29,7 @@ static __inline__ void __ide_mm_outsw(unsigned long port, void *addr, u32 count)
        }
 }
 
-static __inline__ void __ide_mm_outsl(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
 {
        while (count--) {
                writel(*(u32 *)addr, port);
diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h
new file mode 100644 (file)
index 0000000..4991543
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef __GENERIC_IO_H
+#define __GENERIC_IO_H
+
+#include <linux/linkage.h>
+
+/*
+ * These are the "generic" interfaces for doing new-style
+ * memory-mapped or PIO accesses. Architectures may do
+ * their own arch-optimized versions, these just act as
+ * wrappers around the old-style IO register access functions:
+ * read[bwl]/write[bwl]/in[bwl]/out[bwl]
+ *
+ * Don't include this directly, include it from <asm/io.h>.
+ */
+
+/*
+ * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
+ * access or a MMIO access, these functions don't care. The info is
+ * encoded in the hardware mapping set up by the mapping functions
+ * (or the cookie itself, depending on implementation and hw).
+ *
+ * The generic routines just encode the PIO/MMIO as part of the
+ * cookie, and coldly assume that the MMIO IO mappings are not
+ * in the low address range. Architectures for which this is not
+ * true can't use this generic implementation.
+ */
+extern unsigned int fastcall ioread8(void __iomem *);
+extern unsigned int fastcall ioread16(void __iomem *);
+extern unsigned int fastcall ioread32(void __iomem *);
+
+extern void fastcall iowrite8(u8, void __iomem *);
+extern void fastcall iowrite16(u16, void __iomem *);
+extern void fastcall iowrite32(u32, void __iomem *);
+
+/*
+ * "string" versions of the above. Note that they
+ * use native byte ordering for the accesses (on
+ * the assumption that IO and memory agree on a
+ * byte order, and CPU byteorder is irrelevant).
+ *
+ * They do _not_ update the port address. If you
+ * want MMIO that copies stuff laid out in MMIO
+ * memory across multiple ports, use "memcpy_toio()"
+ * and friends.
+ */
+extern void fastcall ioread8_rep(void __iomem *port, void *buf, unsigned long count);
+extern void fastcall ioread16_rep(void __iomem *port, void *buf, unsigned long count);
+extern void fastcall ioread32_rep(void __iomem *port, void *buf, unsigned long count);
+
+extern void fastcall iowrite8_rep(void __iomem *port, const void *buf, unsigned long count);
+extern void fastcall iowrite16_rep(void __iomem *port, const void *buf, unsigned long count);
+extern void fastcall iowrite32_rep(void __iomem *port, const void *buf, unsigned long count);
+
+/* Create a virtual mapping cookie for an IO port range */
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
+#endif
index c814b2f..16fc003 100644 (file)
@@ -3,8 +3,8 @@
 
 #include <linux/config.h>
 #include <linux/percpu.h>
+#include <linux/hardirq.h>
 #include <asm/types.h>
-#include <asm/hardirq.h>
 
 /* An unsigned long type for operations which are atomic for a single
  * CPU.  Usually used in combination with per-cpu variables. */
diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h
new file mode 100644 (file)
index 0000000..549cb3a
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _ASM_GENERIC_UACCESS_H_
+#define _ASM_GENERIC_UACCESS_H_
+
+/*
+ * This macro should be used instead of __get_user() when accessing
+ * values at locations that are not known to be aligned.
+ */
+#define __get_user_unaligned(x, ptr)                                   \
+({                                                                     \
+       __typeof__ (*(ptr)) __x;                                        \
+       __copy_from_user(&__x, (ptr), sizeof(*(ptr))) ? -EFAULT : 0;    \
+       (x) = __x;                                                      \
+})
+
+
+/*
+ * This macro should be used instead of __put_user() when accessing
+ * values at locations that are not known to be aligned.
+ */
+#define __put_user_unaligned(x, ptr)                                   \
+({                                                                     \
+       __typeof__ (*(ptr)) __x = (x);                                  \
+       __copy_to_user((ptr), &__x, sizeof(*(ptr))) ? -EFAULT : 0;      \
+})
+
+#endif /* _ASM_GENERIC_UACCESS_H */
index 3b6f010..edddf5b 100644 (file)
@@ -1,21 +1,4 @@
 #ifndef _H8300_BUG_H
 #define _H8300_BUG_H
-
-#define BUG() do { \
-  printk("%s(%d): kernel BUG!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define PAGE_BUG(page) do { \
-         BUG(); \
-} while (0)
-
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
index 5effc8d..c2e05e4 100644 (file)
@@ -57,6 +57,7 @@ struct pt_regs {
 
 #define user_mode(regs) (!((regs)->ccr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
index 070d46d..af33b85 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
index 433a6e5..c9f0bf3 100644 (file)
 #define BUG() __asm__ __volatile__("ud2\n")
 #endif
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define PAGE_BUG(page) do { \
-       BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
index 52fe4d9..8f5a075 100644 (file)
@@ -37,20 +37,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -60,30 +46,10 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
-#define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
 #define nmi_enter()            (irq_enter())
 #define nmi_exit()             (preempt_count() -= HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()   ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
+#define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
 #define irq_exit()                                                     \
 do {                                                                   \
                preempt_count() -= IRQ_EXIT_OFFSET;                     \
@@ -92,10 +58,4 @@ do {                                                                 \
                preempt_enable_no_resched();                            \
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)  barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* __ASM_HARDIRQ_H */
index 1d9fa56..083e3b8 100644 (file)
@@ -2,6 +2,8 @@
 #define _ASM_IO_H
 
 #include <linux/config.h>
+#include <linux/string.h>
+#include <linux/compiler.h>
 
 /*
  * This file contains the definitions for the x86 IO instructions
@@ -43,6 +45,8 @@
 
 #ifdef __KERNEL__
 
+#include <asm-generic/iomap.h>
+
 #include <linux/vmalloc.h>
 
 /**
@@ -86,7 +90,7 @@ static inline void * phys_to_virt(unsigned long address)
  */
 #define page_to_phys(page)    ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
 
-extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
 /**
  * ioremap     -   map bus memory into CPU space
@@ -100,13 +104,13 @@ extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long
  * address. 
  */
 
-static inline void * ioremap (unsigned long offset, unsigned long size)
+static inline void __iomem * ioremap(unsigned long offset, unsigned long size)
 {
        return __ioremap(offset, size, 0);
 }
 
-extern void * ioremap_nocache (unsigned long offset, unsigned long size);
-extern void iounmap(void *addr);
+extern void __iomem * ioremap_nocache(unsigned long offset, unsigned long size);
+extern void iounmap(volatile void __iomem *addr);
 
 /*
  * bt_ioremap() and bt_iounmap() are for temporary early boot-time
@@ -139,9 +143,18 @@ extern void bt_iounmap(void *addr, unsigned long size);
  * memory location directly.
  */
 
-#define readb(addr) (*(volatile unsigned char *) (addr))
-#define readw(addr) (*(volatile unsigned short *) (addr))
-#define readl(addr) (*(volatile unsigned int *) (addr))
+static inline unsigned char readb(const volatile void __iomem *addr)
+{
+       return *(volatile unsigned char __force *) addr;
+}
+static inline unsigned short readw(const volatile void __iomem *addr)
+{
+       return *(volatile unsigned short __force *) addr;
+}
+static inline unsigned int readl(const volatile void __iomem *addr)
+{
+       return *(volatile unsigned int __force *) addr;
+}
 #define readb_relaxed(addr) readb(addr)
 #define readw_relaxed(addr) readw(addr)
 #define readl_relaxed(addr) readl(addr)
@@ -149,16 +162,34 @@ extern void bt_iounmap(void *addr, unsigned long size);
 #define __raw_readw readw
 #define __raw_readl readl
 
-#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
+static inline void writeb(unsigned char b, volatile void __iomem *addr)
+{
+       *(volatile unsigned char __force *) addr = b;
+}
+static inline void writew(unsigned short b, volatile void __iomem *addr)
+{
+       *(volatile unsigned short __force *) addr = b;
+}
+static inline void writel(unsigned int b, volatile void __iomem *addr)
+{
+       *(volatile unsigned int __force *) addr = b;
+}
 #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))
+static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
+{
+       memset((void __force *) addr, val, count);
+}
+static inline void memcpy_fromio(void *dst, volatile void __iomem *src, int count)
+{
+       __memcpy(dst, (void __force *) src, count);
+}
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
+{
+       __memcpy((void __force *) dst, src, count);
+}
 
 /*
  * ISA space is 'always mapped' on a typical x86 system, no need to
@@ -168,7 +199,7 @@ extern void bt_iounmap(void *addr, unsigned long size);
  * used as the IO-area pointer (it can be iounmapped as well, so the
  * analogy with PCI is quite large):
  */
-#define __ISA_IO_base ((char *)(PAGE_OFFSET))
+#define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
 
 #define isa_readb(a) readb(__ISA_IO_base + (a))
 #define isa_readw(a) readw(__ISA_IO_base + (a))
@@ -185,8 +216,8 @@ extern void bt_iounmap(void *addr, unsigned long size);
  * Again, i386 does not require mem IO specific function.
  */
 
-#define eth_io_copy_and_sum(a,b,c,d)           eth_copy_and_sum((a),(void *)(b),(c),(d))
-#define isa_eth_io_copy_and_sum(a,b,c,d)       eth_copy_and_sum((a),(void *)(__ISA_IO_base + (b)),(c),(d))
+#define eth_io_copy_and_sum(a,b,c,d)           eth_copy_and_sum((a),(void __force *)(b),(c),(d))
+#define isa_eth_io_copy_and_sum(a,b,c,d)       eth_copy_and_sum((a),(void __force *)(__ISA_IO_base + (b)),(c),(d))
 
 /**
  *     check_signature         -       find BIOS signatures
@@ -199,7 +230,7 @@ extern void bt_iounmap(void *addr, unsigned long size);
  *     Returns 1 on a match.
  */
  
-static inline int check_signature(unsigned long io_addr,
+static inline int check_signature(volatile void __iomem * io_addr,
        const unsigned char *signature, int length)
 {
        int retval = 0;
diff --git a/include/asm-i386/kdebug.h b/include/asm-i386/kdebug.h
new file mode 100644 (file)
index 0000000..de6498b
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _I386_KDEBUG_H
+#define _I386_KDEBUG_H 1
+
+/*
+ * Aug-05 2004 Ported by Prasanna S Panchamukhi <prasanna@in.ibm.com>
+ * from x86_64 architecture.
+ */
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+struct die_args {
+       struct pt_regs *regs;
+       const char *str;
+       long err;
+       int trapnr;
+       int signr;
+};
+
+/* Note - you should never unregister because that can race with NMIs.
+   If you really want to do it first unregister - then synchronize_kernel - then free.
+  */
+int register_die_notifier(struct notifier_block *nb);
+extern struct notifier_block *i386die_chain;
+
+
+/* Grossly misnamed. */
+enum die_val {
+       DIE_OOPS = 1,
+       DIE_INT3,
+       DIE_DEBUG,
+       DIE_PANIC,
+       DIE_NMI,
+       DIE_DIE,
+       DIE_NMIWATCHDOG,
+       DIE_KERNELDEBUG,
+       DIE_TRAP,
+       DIE_GPF,
+       DIE_CALL,
+       DIE_NMI_IPI,
+       DIE_PAGE_FAULT,
+};
+
+static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
+{
+       struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig };
+       return notifier_call_chain(&i386die_chain, val, &args);
+}
+
+#endif
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
new file mode 100644 (file)
index 0000000..566e34a
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef _ASM_KPROBES_H
+#define _ASM_KPROBES_H
+/*
+ *  Kernel Probes (KProbes)
+ *  include/asm-i386/kprobes.h
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ *
+ * 2002-Oct    Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
+ *             Probes initial implementation ( includes suggestions from
+ *             Rusty Russell).
+ */
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+struct pt_regs;
+
+typedef u8 kprobe_opcode_t;
+#define BREAKPOINT_INSTRUCTION 0xcc
+#define MAX_INSN_SIZE 16
+#define MAX_STACK_SIZE 64
+#define MIN_STACK_SIZE(ADDR) (((MAX_STACK_SIZE) < \
+       (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) \
+       ? (MAX_STACK_SIZE) \
+       : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
+
+/* trap3/1 are intr gates for kprobes.  So, restore the status of IF,
+ * if necessary, before executing the original int3/1 (trap) handler.
+ */
+static inline void restore_interrupts(struct pt_regs *regs)
+{
+       if (regs->eflags & IF_MASK)
+               local_irq_enable();
+}
+
+#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
+#endif                         /* _ASM_KPROBES_H */
index e48009f..af3d857 100644 (file)
@@ -5,6 +5,10 @@
 #define FASTCALL(x)    x __attribute__((regparm(3)))
 #define fastcall       __attribute__((regparm(3)))
 
+#ifdef CONFIG_REGPARM
+# define prevent_tail_call(ret) __asm__ ("" : "=r" (ret) : "0" (ret))
+#endif
+
 #ifdef CONFIG_X86_ALIGNMENT_16
 #define __ALIGN .align 16,0x90
 #define __ALIGN_STR ".align 16,0x90"
index 4cb4ba4..9404c53 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_sequence(cpumask_t mask, int vector);
+void send_IPI_mask_sequence(cpumask_t mask, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
index 8ac7972..9eb6c9d 100644 (file)
@@ -22,7 +22,7 @@ static inline void do_timer_interrupt_hook(struct pt_regs *regs)
  * system, in that case we have to call the local interrupt handler.
  */
 #ifndef CONFIG_X86_LOCAL_APIC
-       x86_do_profile(regs);
+       profile_tick(CPU_PROFILING, regs);
 #else
        if (!using_apic_timer)
                smp_local_timer_interrupt(regs);
index d419498..6f2b17a 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_bitmask(cpumask_t mask, int vector);
-inline void __send_IPI_shortcut(unsigned int shortcut, int vector);
+void send_IPI_mask_bitmask(cpumask_t mask, int vector);
+void __send_IPI_shortcut(unsigned int shortcut, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
index 29aabcd..1b46fd3 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-static inline void send_IPI_mask_sequence(cpumask_t, int vector);
+inline void send_IPI_mask_sequence(cpumask_t, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
index 4cb4ba4..9404c53 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_sequence(cpumask_t mask, int vector);
+void send_IPI_mask_sequence(cpumask_t mask, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
index 24d510a..1728732 100644 (file)
@@ -15,7 +15,7 @@ static inline void do_timer_interrupt_hook(struct pt_regs *regs)
  * system, in that case we have to call the local interrupt handler.
  */
 #ifndef CONFIG_X86_LOCAL_APIC
-       x86_do_profile(regs);
+       profile_tick(CPU_PROFILING, regs);
 #else
        if (!using_apic_timer)
                smp_local_timer_interrupt(regs);
index 46c5561..5b6ceda 100644 (file)
@@ -67,8 +67,6 @@ struct mtrr_gentry
 
 #ifdef __KERNEL__
 
-extern char *mtrr_strings[]; 
-
 /*  The following functions are for use by other drivers  */
 # ifdef CONFIG_MTRR
 extern int mtrr_add (unsigned long base, unsigned long size,
index d80fd65..2d673af 100644 (file)
@@ -57,6 +57,11 @@ struct pt_regs {
 #ifdef __KERNEL__
 #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
 #define instruction_pointer(regs) ((regs)->eip)
+#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
+extern unsigned long profile_pc(struct pt_regs *regs);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
 #endif
 
 #endif
index 291091d..b57cc7a 100644 (file)
 
 #define __build_read_lock_ptr(rw, helper)   \
        asm volatile(LOCK "subl $1,(%0)\n\t" \
-                    "js 2f\n" \
+                    "jns 1f\n" \
+                    "call " helper "\n\t" \
                     "1:\n" \
-                    LOCK_SECTION_START("") \
-                    "2:\tcall " helper "\n\t" \
-                    "jmp 1b\n" \
-                    LOCK_SECTION_END \
                     ::"a" (rw) : "memory")
 
 #define __build_read_lock_const(rw, helper)   \
        asm volatile(LOCK "subl $1,%0\n\t" \
-                    "js 2f\n" \
-                    "1:\n" \
-                    LOCK_SECTION_START("") \
-                    "2:\tpushl %%eax\n\t" \
+                    "jns 1f\n" \
+                    "pushl %%eax\n\t" \
                     "leal %0,%%eax\n\t" \
                     "call " helper "\n\t" \
                     "popl %%eax\n\t" \
-                    "jmp 1b\n" \
-                    LOCK_SECTION_END \
+                    "1:\n" \
                     :"=m" (*(volatile int *)rw) : : "memory")
 
 #define __build_read_lock(rw, helper)  do { \
 
 #define __build_write_lock_ptr(rw, helper) \
        asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
-                    "jnz 2f\n" \
+                    "jz 1f\n" \
+                    "call " helper "\n\t" \
                     "1:\n" \
-                    LOCK_SECTION_START("") \
-                    "2:\tcall " helper "\n\t" \
-                    "jmp 1b\n" \
-                    LOCK_SECTION_END \
                     ::"a" (rw) : "memory")
 
 #define __build_write_lock_const(rw, helper) \
        asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
-                    "jnz 2f\n" \
-                    "1:\n" \
-                    LOCK_SECTION_START("") \
-                    "2:\tpushl %%eax\n\t" \
+                    "jz 1f\n" \
+                    "pushl %%eax\n\t" \
                     "leal %0,%%eax\n\t" \
                     "call " helper "\n\t" \
                     "popl %%eax\n\t" \
-                    "jmp 1b\n" \
-                    LOCK_SECTION_END \
+                    "1:\n" \
                     :"=m" (*(volatile int *)rw) : : "memory")
 
 #define __build_write_lock(rw, helper) do { \
index 986da20..1db03a6 100644 (file)
@@ -45,21 +45,15 @@ struct semaphore {
        atomic_t count;
        int sleepers;
        wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-       long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-               , (int)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
 
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-       __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)                               \
+{                                                                      \
+       .count          = ATOMIC_INIT(n),                               \
+       .sleepers       = 0,                                            \
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
 
 #define __MUTEX_INITIALIZER(name) \
        __SEMAPHORE_INITIALIZER(name,1)
@@ -81,9 +75,6 @@ static inline void sema_init (struct semaphore *sem, int val)
        atomic_set(&sem->count, val);
        sem->sleepers = 0;
        init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-       sem->__magic = (int)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -113,9 +104,6 @@ asmlinkage void __up(struct semaphore * sem);
  */
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        __asm__ __volatile__(
                "# atomic down operation\n\t"
@@ -139,9 +127,6 @@ static inline int down_interruptible(struct semaphore * sem)
 {
        int result;
 
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        __asm__ __volatile__(
                "# atomic interruptible down operation\n\t"
@@ -167,10 +152,6 @@ static inline int down_trylock(struct semaphore * sem)
 {
        int result;
 
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        __asm__ __volatile__(
                "# atomic interruptible down operation\n\t"
                LOCK "decl %1\n\t"     /* --sem->count */
@@ -195,9 +176,6 @@ static inline int down_trylock(struct semaphore * sem)
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        __asm__ __volatile__(
                "# atomic up operation\n\t"
                LOCK "incl %0\n\t"     /* ++sem->count */
index 711f906..07f6b38 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nasty libc5 fixup - bletch */
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
index 582cd32..cb8ab74 100644 (file)
@@ -67,7 +67,7 @@ static inline cpumask_t pcibus_to_cpumask(int bus)
 }
 
 /* Node-to-Node distance */
-#define node_distance(from, to) (from != to)
+#define node_distance(from, to) ((from) != (to))
 
 /* Cross-node load balancing interval. */
 #define NODE_BALANCE_RATE 100
index abbf37a..2c0cd51 100644 (file)
@@ -8,15 +8,8 @@
 #endif
 #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0)
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define PAGE_BUG(page) do { BUG(); } while (0)
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
+/* should this BUG should be made generic? */
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
index 60ef0ba..cc0ff0a 100644 (file)
@@ -182,17 +182,17 @@ struct compat_shmid64_ds {
  */
 typedef        u32             compat_uptr_t;
 
-static inline void *
+static inline void __user *
 compat_ptr (compat_uptr_t uptr)
 {
-       return (void *) (unsigned long) uptr;
+       return (void __user *) (unsigned long) uptr;
 }
 
-static __inline__ void *
+static __inline__ void __user *
 compat_alloc_user_space (long len)
 {
        struct pt_regs *regs = ia64_task_regs(current);
-       return (void *) (((regs->r12 & 0xffffffff) & -16) - len);
+       return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
 }
 
 #endif /* _ASM_IA64_COMPAT_H */
index 9557b49..8373c39 100644 (file)
@@ -4,7 +4,7 @@
 /*
  * ELF-specific definitions.
  *
- * Copyright (C) 1998-1999, 2002-2003 Hewlett-Packard Co
+ * Copyright (C) 1998-1999, 2002-2004 Hewlett-Packard Co
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
@@ -40,7 +40,7 @@
  * the way of the program that it will "exec", and that there is
  * sufficient room for the brk.
  */
-#define ELF_ET_DYN_BASE                (TASK_UNMAPPED_BASE + 0x800000000)
+#define ELF_ET_DYN_BASE                (TASK_UNMAPPED_BASE + 0x800000000UL)
 
 #define PT_IA_64_UNWIND                0x70000001
 
@@ -175,7 +175,7 @@ extern void ia64_elf_core_copy_regs (struct pt_regs *src, elf_gregset_t dst);
 /* This macro yields a string that ld.so will use to load
    implementation specific libraries for optimization.  Not terribly
    relevant until we have real hardware to play with... */
-#define ELF_PLATFORM   0
+#define ELF_PLATFORM   NULL
 
 /*
  * Architecture-neutral AT_ values are in the range 0-17.  Leave some room for more of
index ec60324..491996a 100644 (file)
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space for potentially all IRQ sources
  * in the system nesting on a single CPU:
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context?
- * Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()           ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()           (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
-#ifdef CONFIG_SMP
-  extern void synchronize_irq (unsigned int irq);
-#else
-# define synchronize_irq(irq)  barrier()
-#endif /* CONFIG_SMP */
+extern void __iomem *ipi_base_addr;
 
 #endif /* _ASM_IA64_HARDIRQ_H */
index a721343..f4e5a4b 100644 (file)
@@ -78,8 +78,6 @@ enum {
 extern __u8 isa_irq_to_vector_map[16];
 #define isa_irq_to_vector(x)   isa_irq_to_vector_map[(x)]
 
-extern unsigned long ipi_base_addr;
-
 extern struct hw_interrupt_type irq_type_ia64_lsapic;  /* CPU-internal interrupt controller */
 
 extern int assign_irq_vector (int irq);        /* allocate a free vector */
index 8b6d0ae..4d19a5b 100644 (file)
@@ -23,7 +23,7 @@
 #define __SLOW_DOWN_IO do { } while (0)
 #define SLOW_DOWN_IO   do { } while (0)
 
-#define __IA64_UNCACHED_OFFSET 0xc000000000000000      /* region 6 */
+#define __IA64_UNCACHED_OFFSET 0xc000000000000000UL    /* region 6 */
 
 /*
  * The legacy I/O space defined by the ia64 architecture supports only 65536 ports, but
@@ -248,7 +248,7 @@ __outsw (unsigned long port, const void *src, unsigned long count)
 }
 
 static inline void
-__outsl (unsigned long port, void *src, unsigned long count)
+__outsl (unsigned long port, const void *src, unsigned long count)
 {
        const unsigned int *sp = src;
 
@@ -290,51 +290,51 @@ __outsl (unsigned long port, void *src, unsigned long count)
  * hopefully it'll stay that way).
  */
 static inline unsigned char
-___ia64_readb (void *addr)
+___ia64_readb (const volatile void __iomem *addr)
 {
-       return *(volatile unsigned char *)addr;
+       return *(volatile unsigned char __force *)addr;
 }
 
 static inline unsigned short
-___ia64_readw (void *addr)
+___ia64_readw (const volatile void __iomem *addr)
 {
-       return *(volatile unsigned short *)addr;
+       return *(volatile unsigned short __force *)addr;
 }
 
 static inline unsigned int
-___ia64_readl (void *addr)
+___ia64_readl (const volatile void __iomem *addr)
 {
-       return *(volatile unsigned int *) addr;
+       return *(volatile unsigned int __force *) addr;
 }
 
 static inline unsigned long
-___ia64_readq (void *addr)
+___ia64_readq (const volatile void __iomem *addr)
 {
-       return *(volatile unsigned long *) addr;
+       return *(volatile unsigned long __force *) addr;
 }
 
 static inline void
-__writeb (unsigned char val, void *addr)
+__writeb (unsigned char val, volatile void __iomem *addr)
 {
-       *(volatile unsigned char *) addr = val;
+       *(volatile unsigned char __force *) addr = val;
 }
 
 static inline void
-__writew (unsigned short val, void *addr)
+__writew (unsigned short val, volatile void __iomem *addr)
 {
-       *(volatile unsigned short *) addr = val;
+       *(volatile unsigned short __force *) addr = val;
 }
 
 static inline void
-__writel (unsigned int val, void *addr)
+__writel (unsigned int val, volatile void __iomem *addr)
 {
-       *(volatile unsigned int *) addr = val;
+       *(volatile unsigned int __force *) addr = val;
 }
 
 static inline void
-__writeq (unsigned long val, void *addr)
+__writeq (unsigned long val, volatile void __iomem *addr)
 {
-       *(volatile unsigned long *) addr = val;
+       *(volatile unsigned long __force *) addr = val;
 }
 
 #define __readb                platform_readb
@@ -346,14 +346,14 @@ __writeq (unsigned long val, void *addr)
 #define __readl_relaxed        platform_readl_relaxed
 #define __readq_relaxed        platform_readq_relaxed
 
-#define readb(a)       __readb((void *)(a))
-#define readw(a)       __readw((void *)(a))
-#define readl(a)       __readl((void *)(a))
-#define readq(a)       __readq((void *)(a))
-#define readb_relaxed(a)       __readb_relaxed((void *)(a))
-#define readw_relaxed(a)       __readw_relaxed((void *)(a))
-#define readl_relaxed(a)       __readl_relaxed((void *)(a))
-#define readq_relaxed(a)       __readq_relaxed((void *)(a))
+#define readb(a)       __readb((a))
+#define readw(a)       __readw((a))
+#define readl(a)       __readl((a))
+#define readq(a)       __readq((a))
+#define readb_relaxed(a)       __readb_relaxed((a))
+#define readw_relaxed(a)       __readw_relaxed((a))
+#define readl_relaxed(a)       __readl_relaxed((a))
+#define readq_relaxed(a)       __readq_relaxed((a))
 #define __raw_readb    readb
 #define __raw_readw    readw
 #define __raw_readl    readl
@@ -362,10 +362,10 @@ __writeq (unsigned long val, void *addr)
 #define __raw_readw_relaxed    readw_relaxed
 #define __raw_readl_relaxed    readl_relaxed
 #define __raw_readq_relaxed    readq_relaxed
-#define writeb(v,a)    __writeb((v), (void *) (a))
-#define writew(v,a)    __writew((v), (void *) (a))
-#define writel(v,a)    __writel((v), (void *) (a))
-#define writeq(v,a)    __writeq((v), (void *) (a))
+#define writeb(v,a)    __writeb((v), (a))
+#define writew(v,a)    __writew((v), (a))
+#define writel(v,a)    __writel((v), (a))
+#define writeq(v,a)    __writeq((v), (a))
 #define __raw_writeb   writeb
 #define __raw_writew   writew
 #define __raw_writel   writel
@@ -397,14 +397,14 @@ __writeq (unsigned long val, void *addr)
  *
  * On ia-64, we access the physical I/O memory space through the uncached kernel region.
  */
-static inline void *
+static inline void __iomem *
 ioremap (unsigned long offset, unsigned long size)
 {
-       return (void *) (__IA64_UNCACHED_OFFSET | (offset));
+       return (void __iomem *) (__IA64_UNCACHED_OFFSET | (offset));
 }
 
 static inline void
-iounmap (void *addr)
+iounmap (volatile void __iomem *addr)
 {
 }
 
@@ -415,17 +415,14 @@ iounmap (void *addr)
 /*
  * String version of IO memory access ops:
  */
-extern void __ia64_memcpy_fromio (void *, unsigned long, long);
-extern void __ia64_memcpy_toio (unsigned long, void *, long);
-extern void __ia64_memset_c_io (unsigned long, unsigned long, long);
-
-#define memcpy_fromio(to,from,len) \
-  __ia64_memcpy_fromio((to),(unsigned long)(from),(len))
-#define memcpy_toio(to,from,len) \
-  __ia64_memcpy_toio((unsigned long)(to),(from),(len))
-#define memset_io(addr,c,len) \
-  __ia64_memset_c_io((unsigned long)(addr),0x0101010101010101UL*(u8)(c),(len))
-
+extern void __ia64_memcpy_fromio (void *, volatile void __iomem *, long);
+extern void __ia64_memcpy_toio (volatile void __iomem *, void *, long);
+extern void __ia64_memset_c_io (volatile void __iomem *, unsigned long, long);
+
+#define memcpy_fromio(to,from,len)     __ia64_memcpy_fromio((to), (from),(len))
+#define memcpy_toio(to,from,len)       __ia64_memcpy_toio((to),(from),(len))
+#define memset_io(addr,c,len)          __ia64_memset_c_io((addr), 0x0101010101010101UL*(u8)(c), \
+                                                          (len))
 
 #define dma_cache_inv(_start,_size)             do { } while (0)
 #define dma_cache_wback(_start,_size)           do { } while (0)
index 0957e2a..1d00069 100644 (file)
 
 #define IA64_MCA_RENDEZ_TIMEOUT                (20 * 1000)     /* value in milliseconds - 20 seconds */
 
+typedef struct ia64_fptr {
+       unsigned long fp;
+       unsigned long gp;
+} ia64_fptr_t;
+
 typedef union cmcv_reg_u {
        u64     cmcv_regval;
        struct  {
@@ -114,6 +119,8 @@ extern void ia64_mca_ucmc_handler(void);
 extern void ia64_monarch_init_handler(void);
 extern void ia64_slave_init_handler(void);
 extern void ia64_mca_cmc_vector_setup(void);
+extern int  ia64_reg_MCA_extension(void*);
+extern void ia64_unreg_MCA_extension(void);
 
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_IA64_MCA_H */
index 2aa8437..55deddd 100644 (file)
        ;;                                                      \
        srlz.d;                                                 \
        mov     r13 = ar.k6;                                    \
-       ;;                                                      \
-       DATA_PA_TO_VA(r13,temp1);                               \
-       ;;                                                      \
        mov     temp2 = ar.bspstore;                            \
        ;;                                                      \
        DATA_PA_TO_VA(temp2,temp1);                             \
index 51558c0..0096e7e 100644 (file)
 
 #include <asm/processor.h>
 
-#define MMU_CONTEXT_DEBUG      0
-
-#if MMU_CONTEXT_DEBUG
-
-#include <ia64intrin.h>
-
-extern struct mmu_trace_entry {
-       char op;
-       u8 cpu;
-       u32 context;
-       void *mm;
-} mmu_tbuf[1024];
-
-extern volatile int mmu_tbuf_index;
-
-# define MMU_TRACE(_op,_cpu,_mm,_ctx)                                                  \
-do {                                                                                   \
-       int i = __sync_fetch_and_add(&mmu_tbuf_index, 1) % ARRAY_SIZE(mmu_tbuf);        \
-       struct mmu_trace_entry e;                                                       \
-       e.op = (_op);                                                                   \
-       e.cpu = (_cpu);                                                                 \
-       e.mm = (_mm);                                                                   \
-       e.context = (_ctx);                                                             \
-       mmu_tbuf[i] = e;                                                                \
-} while (0)
-
-#else
-# define MMU_TRACE(op,cpu,mm,ctx)      do { ; } while (0)
-#endif
-
 struct ia64_ctx {
        spinlock_t lock;
        unsigned int next;      /* next context number to use */
@@ -123,7 +93,6 @@ get_mmu_context (struct mm_struct *mm)
 static inline int
 init_new_context (struct task_struct *p, struct mm_struct *mm)
 {
-       MMU_TRACE('N', smp_processor_id(), mm, 0);
        mm->context = 0;
        return 0;
 }
@@ -132,7 +101,6 @@ static inline void
 destroy_context (struct mm_struct *mm)
 {
        /* Nothing to do.  */
-       MMU_TRACE('D', smp_processor_id(), mm, mm->context);
 }
 
 static inline void
@@ -142,7 +110,7 @@ reload_context (mm_context_t context)
        unsigned long rid_incr = 0;
        unsigned long rr0, rr1, rr2, rr3, rr4, old_rr4;
 
-       old_rr4 = ia64_get_rr(0x8000000000000000);
+       old_rr4 = ia64_get_rr(0x8000000000000000UL);
        rid = context << 3;     /* make space for encoding the region number */
        rid_incr = 1 << 8;
 
@@ -156,11 +124,11 @@ reload_context (mm_context_t context)
        rr4 = (rr4 & (~(0xfcUL))) | (old_rr4 & 0xfc);
 #endif
 
-       ia64_set_rr(0x0000000000000000, rr0);
-       ia64_set_rr(0x2000000000000000, rr1);
-       ia64_set_rr(0x4000000000000000, rr2);
-       ia64_set_rr(0x6000000000000000, rr3);
-       ia64_set_rr(0x8000000000000000, rr4);
+       ia64_set_rr(0x0000000000000000UL, rr0);
+       ia64_set_rr(0x2000000000000000UL, rr1);
+       ia64_set_rr(0x4000000000000000UL, rr2);
+       ia64_set_rr(0x6000000000000000UL, rr3);
+       ia64_set_rr(0x8000000000000000UL, rr4);
        ia64_srlz_i();                  /* srlz.i implies srlz.d */
 }
 
@@ -171,19 +139,14 @@ activate_context (struct mm_struct *mm)
 
        do {
                context = get_mmu_context(mm);
-               MMU_TRACE('A', smp_processor_id(), mm, context);
                if (!cpu_isset(smp_processor_id(), mm->cpu_vm_mask))
                        cpu_set(smp_processor_id(), mm->cpu_vm_mask);
                reload_context(context);
-               MMU_TRACE('a', smp_processor_id(), mm, context);
                /* in the unlikely event of a TLB-flush by another thread, redo the load: */
        } while (unlikely(context != mm->context));
 }
 
-#define deactivate_mm(tsk,mm)                                  \
-do {                                                           \
-       MMU_TRACE('d', smp_processor_id(), mm, mm->context);    \
-} while (0)
+#define deactivate_mm(tsk,mm)  do { } while (0)
 
 /*
  * Switch from address space PREV to address space NEXT.
index f28f0b2..89c392d 100644 (file)
 # define NR_NODE_MEMBLKS       (NR_NODES * 4)
 #endif
 
-extern unsigned long max_low_pfn;
-
-#define pfn_valid(pfn)         (((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
-#define page_to_pfn(page)      ((unsigned long) (page - vmem_map))
-#define pfn_to_page(pfn)       (vmem_map + (pfn))
-
 #else /* CONFIG_DISCONTIGMEM */
 # define NR_NODE_MEMBLKS       4
 #endif /* CONFIG_DISCONTIGMEM */
index 6459f61..f627732 100644 (file)
@@ -59,7 +59,7 @@ extern struct node_cpuid_s node_cpuid[NR_CPUS];
  */
 
 extern u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
-#define node_distance(from,to) (numa_slit[from * numnodes + to])
+#define node_distance(from,to) (numa_slit[(from) * numnodes + (to)])
 
 extern int paddr_to_nid(unsigned long paddr);
 
index 48398a3..2af819b 100644 (file)
@@ -229,6 +229,15 @@ struct switch_stack {
  * the canonical representation by adding to instruction pointer.
  */
 # define instruction_pointer(regs) ((regs)->cr_iip + ia64_psr(regs)->ri)
+/* Conserve space in histogram by encoding slot bits in address
+ * bits 2 and 3 rather than bits 0 and 1.
+ */
+#define profile_pc(regs)                                               \
+({                                                                     \
+       unsigned long __ip = instruction_pointer(regs);                 \
+       (__ip & ~3UL) + ((__ip & 3UL) << 2);                            \
+})
+
   /* given a pointer to a task_struct, return the user's pt_regs */
 # define ia64_task_regs(t)             (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
 # define ia64_psr(regs)                        ((struct ia64_psr *) &(regs)->cr_ipsr)
index b372de0..f468596 100644 (file)
@@ -364,7 +364,7 @@ typedef struct sal_processor_static_info {
        u64 cr[128];
        u64 ar[128];
        u64 rr[8];
-       struct ia64_fpreg fr[128];
+       struct ia64_fpreg __attribute__ ((packed)) fr[128];
 } sal_processor_static_info_t;
 
 struct sal_cpuid_info {
@@ -819,6 +819,16 @@ struct sal_ret_values {
        long r8; long r9; long r10; long r11;
 };
 
+#define IA64_SAL_OEMFUNC_MIN           0x02000000
+#define IA64_SAL_OEMFUNC_MAX           0x03ffffff
+
+extern int ia64_sal_oemcall(struct ia64_sal_retval *, u64, u64, u64, u64, u64,
+                           u64, u64, u64);
+extern int ia64_sal_oemcall_nolock(struct ia64_sal_retval *, u64, u64, u64,
+                                  u64, u64, u64, u64, u64);
+extern int ia64_sal_oemcall_reentrant(struct ia64_sal_retval *, u64, u64, u64,
+                                     u64, u64, u64, u64, u64);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_IA64_SAL_H */
index 44165a6..3a2f0f3 100644 (file)
@@ -15,21 +15,13 @@ struct semaphore {
        atomic_t count;
        int sleepers;
        wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-       long __magic;           /* initialized by __SEM_DEBUG_INIT() */
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name)                , (long) &(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count)                                    \
-{                                                                              \
-       ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)       \
-       __SEM_DEBUG_INIT(name)                                                  \
+#define __SEMAPHORE_INITIALIZER(name, n)                               \
+{                                                                      \
+       .count          = ATOMIC_INIT(n),                               \
+       .sleepers       = 0,                                            \
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
 }
 
 #define __MUTEX_INITIALIZER(name)      __SEMAPHORE_INITIALIZER(name,1)
@@ -70,9 +62,6 @@ extern void __up (struct semaphore * sem);
 static inline void
 down (struct semaphore *sem)
 {
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        if (atomic_dec_return(&sem->count) < 0)
                __down(sem);
@@ -87,9 +76,6 @@ down_interruptible (struct semaphore * sem)
 {
        int ret = 0;
 
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        if (atomic_dec_return(&sem->count) < 0)
                ret = __down_interruptible(sem);
@@ -101,9 +87,6 @@ down_trylock (struct semaphore *sem)
 {
        int ret = 0;
 
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        if (atomic_dec_return(&sem->count) < 0)
                ret = __down_trylock(sem);
        return ret;
@@ -112,9 +95,6 @@ down_trylock (struct semaphore *sem)
 static inline void
 up (struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        if (atomic_inc_return(&sem->count) <= 0)
                __up(sem);
 }
index 52cce1d..d55f139 100644 (file)
@@ -60,7 +60,7 @@ typedef struct siginfo {
 
                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
                struct {
-                       void *_addr;            /* faulting insn/memory ref. */
+                       void __user *_addr;     /* faulting insn/memory ref. */
                        int _imm;               /* immediate value for "break" */
                        unsigned int _flags;    /* see below */
                        unsigned long _isr;     /* isr */
index ac3b00a..e984c57 100644 (file)
@@ -3384,7 +3384,7 @@ typedef ii_icrb0_e_u_t icrbe_t;
 
 #define IO_PERF_SETS   32
 
-#if __KERNEL__
+#ifdef __KERNEL__
 #include <asm/sn/dmamap.h>
 #include <asm/sn/driver.h>
 #include <asm/sn/xtalk/xtalk.h>
diff --git a/include/asm-ia64/sn/sn2/sn_hwperf.h b/include/asm-ia64/sn/sn2/sn_hwperf.h
new file mode 100644 (file)
index 0000000..2036382
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ *
+ * Data types used by the SN_SAL_HWPERF_OP SAL call for monitoring
+ * SGI Altix node and router hardware
+ *
+ * Mark Goodwin <markgw@sgi.com> Mon Aug 30 12:23:46 EST 2004
+ */
+
+#ifndef SN_HWPERF_H
+#define SN_HWPERF_H
+
+/*
+ * object structure. SN_HWPERF_ENUM_OBJECTS and SN_HWPERF_GET_CPU_INFO
+ * return an array of these. Do not change this without also
+ * changing the corresponding SAL code.
+ */
+#define SN_HWPERF_MAXSTRING            128
+struct sn_hwperf_object_info {
+       u32 id;
+       union {
+               struct {
+                       u64 this_part:1;
+                       u64 is_shared:1;
+               } fields;
+               struct {
+                       u64 flags;
+                       u64 reserved;
+               } b;
+       } f;
+       char name[SN_HWPERF_MAXSTRING];
+       char location[SN_HWPERF_MAXSTRING];
+       u32 ports;
+};
+
+#define sn_hwp_this_part       f.fields.this_part
+#define sn_hwp_is_shared       f.fields.is_shared
+#define sn_hwp_flags           f.b.flags
+
+#define SN_HWPERF_FOREIGN(x)   (!(x)->sn_hwp_this_part && !(x)->sn_hwp_is_shared)
+
+/* numa port structure, SN_HWPERF_ENUM_PORTS returns an array of these */
+struct sn_hwperf_port_info {
+       u32 port;
+       u32 conn_id;
+       u32 conn_port;
+};
+
+/* for HWPERF_{GET,SET}_MMRS */
+struct sn_hwperf_data {
+       u64 addr;
+       u64 data;
+};
+
+/* user ioctl() argument, see below */
+struct sn_hwperf_ioctl_args {
+        u64 arg;               /* argument, usually an object id */
+        u64 sz;                 /* size of transfer */
+        void *ptr;              /* pointer to source/target */
+        u32 v0;                        /* second return value */
+};
+
+/*
+ * For SN_HWPERF_{GET,SET}_MMRS and SN_HWPERF_OBJECT_DISTANCE,
+ * sn_hwperf_ioctl_args.arg can be used to specify a CPU on which
+ * to call SAL, and whether to use an interprocessor interrupt
+ * or task migration in order to do so. If the CPU specified is
+ * SN_HWPERF_ARG_ANY_CPU, then the current CPU will be used.
+ */
+#define SN_HWPERF_ARG_ANY_CPU          0x7fffffffUL
+#define SN_HWPERF_ARG_CPU_MASK         0x7fffffff00000000ULL
+#define SN_HWPERF_ARG_USE_IPI_MASK     0x8000000000000000ULL
+#define SN_HWPERF_ARG_OBJID_MASK       0x00000000ffffffffULL
+
+/* 
+ * ioctl requests on the "sn_hwperf" misc device that call SAL.
+ */
+#define SN_HWPERF_OP_MEM_COPYIN                0x1000
+#define SN_HWPERF_OP_MEM_COPYOUT       0x2000
+#define SN_HWPERF_OP_MASK              0x0fff
+
+/*
+ * Determine mem requirement.
+ * arg don't care
+ * sz  8
+ * p   pointer to u64 integer
+ */
+#define        SN_HWPERF_GET_HEAPSIZE          1
+
+/*
+ * Install mem for SAL drvr
+ * arg don't care
+ * sz  sizeof buffer pointed to by p
+ * p   pointer to buffer for scratch area
+ */
+#define SN_HWPERF_INSTALL_HEAP         2
+
+/*
+ * Determine number of objects
+ * arg don't care
+ * sz  8
+ * p   pointer to u64 integer
+ */
+#define SN_HWPERF_OBJECT_COUNT         (10|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * Determine object "distance", relative to a cpu. This operation can
+ * execute on a designated logical cpu number, using either an IPI or
+ * via task migration. If the cpu number is SN_HWPERF_ANY_CPU, then
+ * the current CPU is used. See the SN_HWPERF_ARG_* macros above.
+ *
+ * arg bitmap of IPI flag, cpu number and object id
+ * sz  8
+ * p   pointer to u64 integer
+ */
+#define SN_HWPERF_OBJECT_DISTANCE      (11|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * Enumerate objects. Special case if sz == 8, returns the required
+ * buffer size.
+ * arg don't care
+ * sz  sizeof buffer pointed to by p
+ * p   pointer to array of struct sn_hwperf_object_info
+ */
+#define SN_HWPERF_ENUM_OBJECTS         (12|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * Enumerate NumaLink ports for an object. Special case if sz == 8,
+ * returns the required buffer size.
+ * arg object id
+ * sz  sizeof buffer pointed to by p
+ * p   pointer to array of struct sn_hwperf_port_info
+ */
+#define SN_HWPERF_ENUM_PORTS           (13|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * SET/GET memory mapped registers. These operations can execute
+ * on a designated logical cpu number, using either an IPI or via
+ * task migration. If the cpu number is SN_HWPERF_ANY_CPU, then
+ * the current CPU is used. See the SN_HWPERF_ARG_* macros above.
+ *
+ * arg bitmap of ipi flag, cpu number and object id
+ * sz  sizeof buffer pointed to by p
+ * p   pointer to array of struct sn_hwperf_data
+ */
+#define SN_HWPERF_SET_MMRS             (14|SN_HWPERF_OP_MEM_COPYIN)
+#define SN_HWPERF_GET_MMRS             (15|SN_HWPERF_OP_MEM_COPYOUT| \
+                                           SN_HWPERF_OP_MEM_COPYIN)
+/*
+ * Lock a shared object
+ * arg object id
+ * sz  don't care
+ * p   don't care
+ */
+#define SN_HWPERF_ACQUIRE              16
+
+/*
+ * Unlock a shared object
+ * arg object id
+ * sz  don't care
+ * p   don't care
+ */
+#define SN_HWPERF_RELEASE              17
+
+/*
+ * Break a lock on a shared object
+ * arg object id
+ * sz  don't care
+ * p   don't care
+ */
+#define SN_HWPERF_FORCE_RELEASE                18
+
+/*
+ * ioctl requests on "sn_hwperf" that do not call SAL
+ */
+
+/*
+ * get cpu info as an array of hwperf_object_info_t. 
+ * id is logical CPU number, name is description, location
+ * is geoid (e.g. 001c04#1c). Special case if sz == 8,
+ * returns the required buffer size.
+ *
+ * arg don't care
+ * sz  sizeof buffer pointed to by p
+ * p   pointer to array of struct sn_hwperf_object_info
+ */
+#define SN_HWPERF_GET_CPU_INFO         (100|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * Given an object id, return it's node number (aka cnode).
+ * arg object id
+ * sz  8
+ * p   pointer to u64 integer
+ */
+#define SN_HWPERF_GET_OBJ_NODE         (101|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * Given a node number (cnode), return it's nasid.
+ * arg ordinal node number (aka cnodeid)
+ * sz  8
+ * p   pointer to u64 integer
+ */
+#define SN_HWPERF_GET_NODE_NASID       (102|SN_HWPERF_OP_MEM_COPYOUT)
+
+/* return codes */
+#define SN_HWPERF_OP_OK                        0
+#define SN_HWPERF_OP_NOMEM             1
+#define SN_HWPERF_OP_NO_PERM           2
+#define SN_HWPERF_OP_IO_ERROR          3
+#define SN_HWPERF_OP_BUSY              4
+#define SN_HWPERF_OP_RECONFIGURE       253
+#define SN_HWPERF_OP_INVAL             254
+
+#endif                         /* SN_HWPERF_H */
index b65da04..5475454 100644 (file)
@@ -55,7 +55,7 @@ typedef struct xtalk_piomap_s *xtalk_piomap_t;
 /*
  * Kernel/driver only definitions
  */
-#if __KERNEL__
+#ifdef __KERNEL__
 
 #include <asm/types.h>
 #include <asm/sn/types.h>
index 15a298a..d265bcc 100644 (file)
@@ -183,7 +183,7 @@ typedef struct xwidget_hwid_s {
 
 
 /* Generic crosstalk widget initialization interface */
-#if __KERNEL__
+#ifdef __KERNEL__
 
 extern int              xwidget_driver_register(xwidget_part_num_t part_num,
                                                xwidget_mfg_num_t mfg_num,
index bf4434e..21a9f10 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_IA64_SOCKET_H */
index 049c698..b65c627 100644 (file)
@@ -48,22 +48,19 @@ local_finish_flush_tlb_mm (struct mm_struct *mm)
 static inline void
 flush_tlb_mm (struct mm_struct *mm)
 {
-       MMU_TRACE('F', smp_processor_id(), mm, mm->context);
        if (!mm)
-               goto out;
+               return;
 
        mm->context = 0;
 
        if (atomic_read(&mm->mm_users) == 0)
-               goto out;               /* happens as a result of exit_mmap() */
+               return;         /* happens as a result of exit_mmap() */
 
 #ifdef CONFIG_SMP
        smp_flush_tlb_mm(mm);
 #else
        local_finish_flush_tlb_mm(mm);
 #endif
-  out:
-       MMU_TRACE('f', smp_processor_id(), mm, mm->context);
 }
 
 extern void flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long end);
diff --git a/include/asm-m32r/a.out.h b/include/asm-m32r/a.out.h
new file mode 100644 (file)
index 0000000..4619ba5
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _ASM_M32R_A_OUT_H
+#define _ASM_M32R_A_OUT_H
+
+/* orig : i386 2.4.18 */
+
+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 /* _ASM_M32R_A_OUT_H */
diff --git a/include/asm-m32r/addrspace.h b/include/asm-m32r/addrspace.h
new file mode 100644 (file)
index 0000000..06a83dc
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id$ */
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 by Hiroyuki Kondo
+ *
+ * Defitions for the address spaces of the M32R CPUs.
+ */
+#ifndef __ASM_M32R_ADDRSPACE_H
+#define __ASM_M32R_ADDRSPACE_H
+
+/*
+ * Memory segments (32bit kernel mode addresses)
+ */
+#define KUSEG                   0x00000000
+#define KSEG0                   0x80000000
+#define KSEG1                   0xa0000000
+#define KSEG2                   0xc0000000
+#define KSEG3                   0xe0000000
+
+#define K0BASE  KSEG0
+
+/*
+ * Returns the kernel segment base of a given address
+ */
+#ifndef __ASSEMBLY__
+#define KSEGX(a)                (((unsigned long)(a)) & 0xe0000000)
+#else
+#define KSEGX(a)                ((a) & 0xe0000000)
+#endif
+
+/*
+ * Returns the physical address of a KSEG0/KSEG1 address
+ */
+#ifndef __ASSEMBLY__
+#define PHYSADDR(a)            (((unsigned long)(a)) & 0x1fffffff)
+#else
+#define PHYSADDR(a)            ((a) & 0x1fffffff)
+#endif
+
+/*
+ * Map an address to a certain kernel segment
+ */
+#ifndef __ASSEMBLY__
+#define KSEG0ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG0))
+#define KSEG1ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG1))
+#define KSEG2ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG2))
+#define KSEG3ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG3))
+#else
+#define KSEG0ADDR(a)           (((a) & 0x1fffffff) | KSEG0)
+#define KSEG1ADDR(a)           (((a) & 0x1fffffff) | KSEG1)
+#define KSEG2ADDR(a)           (((a) & 0x1fffffff) | KSEG2)
+#define KSEG3ADDR(a)           (((a) & 0x1fffffff) | KSEG3)
+#endif
+
+#endif /* __ASM_M32R_ADDRSPACE_H */
diff --git a/include/asm-m32r/assembler.h b/include/asm-m32r/assembler.h
new file mode 100644 (file)
index 0000000..bdb52a5
--- /dev/null
@@ -0,0 +1,212 @@
+#ifndef _ASM_M32R_ASSEMBLER_H
+#define _ASM_M32R_ASSEMBLER_H
+
+/* $Id$ */
+
+/*
+ * linux/asm-m32r/assembler.h
+ *
+ * This file contains M32R architecture specific defines.
+ *
+ * Do not include any C declarations in this file - it is included by
+ * assembler source.
+ */
+
+#include <linux/config.h>
+
+
+#undef ENTRY
+#define ENTRY(name) ENTRY_M name
+       .macro  ENTRY_M name
+       .global \name
+       ALIGN
+\name:
+       .endm
+
+/*
+ * LDIMM: load immediate value
+ *
+ * STI: enable interruption
+ * CLI: disable interruption
+ */
+
+#ifdef __ASSEMBLY__
+
+#define LDIMM(reg,x) LDIMM reg x
+       .macro LDIMM reg x
+       seth    \reg, #high(\x)
+       or3     \reg, \reg, #low(\x)
+       .endm
+
+#if !defined(CONFIG_CHIP_M32102)
+#define STI(reg) STI_M reg
+       .macro STI_M reg
+       setpsw  #0x40       ->  nop
+       ; WORKAROUND: "-> nop" is a workaround for the M32700(TS1).
+       .endm
+
+#define CLI(reg) CLI_M reg
+       .macro CLI_M reg
+       clrpsw  #0x40       ->  nop
+       ; WORKAROUND: "-> nop" is a workaround for the M32700(TS1).
+       .endm
+#else  /* CONFIG_CHIP_M32102 */
+#define STI(reg) STI_M reg
+       .macro STI_M reg
+       mvfc    \reg, psw
+       or3     \reg, \reg, #0x0040
+       mvtc    \reg, psw
+       .endm
+
+#define CLI(reg) CLI_M reg
+       .macro CLI_M reg
+       mvfc    \reg, psw
+       and3    \reg, \reg, #0xffbf
+       mvtc    \reg, psw
+       .endm
+#endif /* CONFIG_CHIP_M32102 */
+
+       .macro  SAVE_ALL
+       push    r0              ; orig_r0
+       push    sp              ; spi (r15)
+       push    lr              ; r14
+       push    r13
+       mvfc    r13, cr3        ; spu
+       push    r13
+       mvfc    r13, bbpc
+       push    r13
+       mvfc    r13, bbpsw
+       push    r13
+       mvfc    r13, bpc
+       push    r13
+       mvfc    r13, psw
+       push    r13
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+       mvfaclo r13, a1
+       push    r13
+       mvfachi r13, a1
+       push    r13
+       mvfaclo r13, a0
+       push    r13
+       mvfachi r13, a0
+       push    r13
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+       mvfaclo r13
+       push    r13
+       mvfachi r13
+       push    r13
+#else
+#error unknown isa configuration
+#endif
+       ldi     r13, #-1
+       push    r13             ; syscall_nr (default: -1)
+       push    r12
+       push    r11
+       push    r10
+       push    r9
+       push    r8
+       push    r7
+       push    r3
+       push    r2
+       push    r1
+       push    r0
+       addi    sp, #-4         ; room for implicit pt_regs parameter
+       push    r6
+       push    r5
+       push    r4
+       .endm
+
+       .macro  RESTORE_ALL
+       pop     r4
+       pop     r5
+       pop     r6
+       addi    sp, #4
+       pop     r0
+       pop     r1
+       pop     r2
+       pop     r3
+       pop     r7
+       pop     r8
+       pop     r9
+       pop     r10
+       pop     r11
+       pop     r12
+       addi    r15, #4         ; Skip syscall number
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+       pop     r13
+       mvtachi r13, a0
+       pop     r13
+       mvtaclo r13, a0
+       pop     r13
+       mvtachi r13, a1
+       pop     r13
+       mvtaclo r13, a1
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+       pop     r13
+       mvtachi r13
+       pop     r13
+       mvtaclo r13
+#else
+#error unknown isa configuration
+#endif
+       pop     r14
+       mvtc    r14, psw
+       pop     r14
+       mvtc    r14, bpc
+       addi    sp, #8          ; Skip bbpsw, bbpc
+       pop     r14
+       mvtc    r14, cr3        ; spu
+       pop     r13
+       pop     lr              ; r14
+       pop     sp              ; spi (r15)
+       addi    sp, #4          ; Skip orig_r0
+       .fillinsn
+1:     rte
+       .section .fixup,"ax"
+2:     bl      do_exit
+       .previous
+       .section __ex_table,"a"
+       ALIGN
+       .long   1b, 2b
+       .previous
+       .endm
+
+#define GET_CURRENT(reg)  get_current reg
+       .macro get_current reg
+       ldi  \reg, #-8192
+       and  \reg, sp
+       .endm
+
+#if !defined(CONFIG_CHIP_M32102)
+       .macro  SWITCH_TO_KERNEL_STACK
+       ; switch to kernel stack (spi)
+       clrpsw  #0x80       ->  nop
+       .endm
+#else  /* CONFIG_CHIP_M32102 */
+       .macro  SWITCH_TO_KERNEL_STACK
+       push    r0              ; save r0 for working
+       mvfc    r0, psw
+       and3    r0, r0, #0x00ff7f
+       mvtc    r0, psw
+       slli    r0, #16
+       bltz    r0, 1f          ; check BSM-bit
+;
+       ;; called from kernel context: previous stack = spi
+       pop     r0              ; retrieve r0
+       bra     2f
+       .fillinsn
+1:
+       ;; called from user context: previous stack = spu
+       mvfc    r0, cr3         ; spu
+       addi    r0, #4
+       mvtc    r0, cr3         ; spu
+       ld      r0, @(-4,r0)    ; retrieve r0
+       .fillinsn
+2:
+       .endm
+#endif /* CONFIG_CHIP_M32102 */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_M32R_ASSEMBLER_H */
+
diff --git a/include/asm-m32r/atomic.h b/include/asm-m32r/atomic.h
new file mode 100644 (file)
index 0000000..570cc54
--- /dev/null
@@ -0,0 +1,305 @@
+#ifndef _ASM_M32R_ATOMIC_H
+#define _ASM_M32R_ATOMIC_H
+
+/*
+ *  linux/include/asm-m32r/atomic.h
+ *
+ *  M32R version:
+ *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/config.h>
+#include <asm/system.h>
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+#undef LOAD
+#undef STORE
+#ifdef CONFIG_SMP
+#define LOAD   "lock"
+#define STORE  "unlock"
+#else
+#define LOAD   "ld"
+#define STORE  "st"
+#endif
+
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+typedef struct { volatile int counter; } atomic_t;
+
+#define ATOMIC_INIT(i) { (i) }
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v.
+ */
+#define atomic_read(v) ((v)->counter)
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+#define atomic_set(v,i)        (((v)->counter) = (i))
+
+/**
+ * atomic_add_return - add integer to atomic variable and return it
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v and return (@i + @v).
+ */
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+       unsigned long flags;
+       int result;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# atomic_add_return            \n\t"
+               DCACHE_CLEAR("%0", "r4", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "add    %0, %2;                 \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (result)
+               : "r" (&v->counter), "r" (i)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+
+       return result;
+}
+
+/**
+ * atomic_sub_return - subtract integer from atomic variable and return it
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and return (@v - @i).
+ */
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+       unsigned long flags;
+       int result;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# atomic_sub_return            \n\t"
+               DCACHE_CLEAR("%0", "r4", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "sub    %0, %2;                 \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (result)
+               : "r" (&v->counter), "r" (i)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+
+       return result;
+}
+
+/**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v.
+ */
+#define atomic_add(i,v) ((void) atomic_add_return((i), (v)))
+
+/**
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v.
+ */
+#define atomic_sub(i,v) ((void) atomic_sub_return((i), (v)))
+
+/**
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
+
+/**
+ * atomic_inc_return - increment atomic variable and return it
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1 and returns the result.
+ */
+static inline int atomic_inc_return(atomic_t *v)
+{
+       unsigned long flags;
+       int result;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# atomic_inc_return            \n\t"
+               DCACHE_CLEAR("%0", "r4", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "addi   %0, #1;                 \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (result)
+               : "r" (&v->counter)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+
+       return result;
+}
+
+/**
+ * atomic_dec_return - decrement atomic variable and return it
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and returns the result.
+ */
+static inline int atomic_dec_return(atomic_t *v)
+{
+       unsigned long flags;
+       int result;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# atomic_dec_return            \n\t"
+               DCACHE_CLEAR("%0", "r4", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "addi   %0, #-1;                \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (result)
+               : "r" (&v->counter)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+
+       return result;
+}
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1.
+ */
+#define atomic_inc(v) ((void)atomic_inc_return(v))
+
+/**
+ * atomic_dec - decrement atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1.
+ */
+#define atomic_dec(v) ((void)atomic_dec_return(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)
+
+/**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all
+ * other cases.
+ */
+#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
+
+/**
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+#define atomic_add_negative(i,v) (atomic_add_return((i), (v)) < 0)
+
+static inline void atomic_clear_mask(unsigned long  mask, atomic_t *addr)
+{
+       unsigned long flags;
+       unsigned long tmp;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# atomic_clear_mask            \n\t"
+               DCACHE_CLEAR("%0", "r5", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "and    %0, %2;                 \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (tmp)
+               : "r" (addr), "r" (~mask)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r5"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+}
+
+static inline void atomic_set_mask(unsigned long  mask, atomic_t *addr)
+{
+       unsigned long flags;
+       unsigned long tmp;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# atomic_set_mask              \n\t"
+               DCACHE_CLEAR("%0", "r5", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "or     %0, %2;                 \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (tmp)
+               : "r" (addr), "r" (mask)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r5"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+}
+
+/* Atomic operations are already serializing on m32r */
+#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()
+
+#endif /* _ASM_M32R_ATOMIC_H */
+
diff --git a/include/asm-m32r/bitops.h b/include/asm-m32r/bitops.h
new file mode 100644 (file)
index 0000000..2500575
--- /dev/null
@@ -0,0 +1,716 @@
+#ifndef _ASM_M32R_BITOPS_H
+#define _ASM_M32R_BITOPS_H
+
+/*
+ *  linux/include/asm-m32r/bitops.h
+ *
+ *  Copyright 1992, Linus Torvalds.
+ *
+ *  M32R version:
+ *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/config.h>
+#include <linux/compiler.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include <asm/types.h>
+
+/*
+ * These have to be done with inline assembly: that way the bit-setting
+ * is guaranteed to be atomic. All bit operations return 0 if the bit
+ * was cleared before the operation and != 0 if it was not.
+ *
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+
+#undef LOAD
+#undef STORE
+#ifdef CONFIG_SMP
+#define LOAD   "lock"
+#define STORE  "unlock"
+#else
+#define LOAD   "ld"
+#define STORE  "st"
+#endif
+
+/* #define ADDR (*(volatile long *) addr) */
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered.  See __set_bit()
+ * if you do not require the atomic guarantees.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void set_bit(int nr, volatile void * addr)
+{
+       __u32 mask;
+       volatile __u32 *a = addr;
+       unsigned long flags;
+       unsigned long tmp;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               DCACHE_CLEAR("%0", "r6", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "or     %0, %2;                 \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (tmp)
+               : "r" (a), "r" (mask)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r6"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+}
+
+/**
+ * __set_bit - Set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike set_bit(), this function is non-atomic and may be reordered.
+ * If it's called on the same region of memory simultaneously, the effect
+ * may be that only one operation succeeds.
+ */
+static inline void __set_bit(int nr, volatile void * addr)
+{
+       __u32 mask;
+       volatile __u32 *a = addr;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+       *a |= mask;
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered.  However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+static inline void clear_bit(int nr, volatile void * addr)
+{
+       __u32 mask;
+       volatile __u32 *a = addr;
+       unsigned long flags;
+       unsigned long tmp;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+
+       local_irq_save(flags);
+
+       __asm__ __volatile__ (
+               DCACHE_CLEAR("%0", "r6", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "and    %0, %2;                 \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (tmp)
+               : "r" (a), "r" (~mask)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r6"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+}
+
+static inline void __clear_bit(int nr, volatile unsigned long * addr)
+{
+       unsigned long mask;
+       volatile unsigned long *a = addr;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+       *a &= ~mask;
+}
+
+#define smp_mb__before_clear_bit()     barrier()
+#define smp_mb__after_clear_bit()      barrier()
+
+/**
+ * __change_bit - Toggle a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike change_bit(), this function is non-atomic and may be reordered.
+ * If it's called on the same region of memory simultaneously, the effect
+ * may be that only one operation succeeds.
+ */
+static inline void __change_bit(int nr, volatile void * addr)
+{
+       __u32 mask;
+       volatile __u32 *a = addr;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+       *a ^= mask;
+}
+
+/**
+ * change_bit - Toggle a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * change_bit() is atomic and may not be reordered.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void change_bit(int nr, volatile void * addr)
+{
+       __u32  mask;
+       volatile __u32  *a = addr;
+       unsigned long flags;
+       unsigned long tmp;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               DCACHE_CLEAR("%0", "r6", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "xor    %0, %2;                 \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (tmp)
+               : "r" (a), "r" (mask)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r6"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+}
+
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_set_bit(int nr, volatile void * addr)
+{
+       __u32 mask, oldbit;
+       volatile __u32 *a = addr;
+       unsigned long flags;
+       unsigned long tmp;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               DCACHE_CLEAR("%0", "%1", "%2")
+               LOAD"   %0, @%2;                \n\t"
+               "mv     %1, %0;                 \n\t"
+               "and    %0, %3;                 \n\t"
+               "or     %1, %3;                 \n\t"
+               STORE"  %1, @%2;                \n\t"
+               : "=&r" (oldbit), "=&r" (tmp)
+               : "r" (a), "r" (mask)
+               : "memory"
+       );
+       local_irq_restore(flags);
+
+       return (oldbit != 0);
+}
+
+/**
+ * __test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+static inline int __test_and_set_bit(int nr, volatile void * addr)
+{
+       __u32 mask, oldbit;
+       volatile __u32 *a = addr;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+       oldbit = (*a & mask);
+       *a |= mask;
+
+       return (oldbit != 0);
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_clear_bit(int nr, volatile void * addr)
+{
+       __u32 mask, oldbit;
+       volatile __u32 *a = addr;
+       unsigned long flags;
+       unsigned long tmp;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+
+       local_irq_save(flags);
+
+       __asm__ __volatile__ (
+               DCACHE_CLEAR("%0", "%1", "%3")
+               LOAD"   %0, @%3;                \n\t"
+               "mv     %1, %0; \n\t"
+               "and    %0, %2; \n\t"
+               "not    %2, %2; \n\t"
+               "and    %1, %2; \n\t"
+               STORE"  %1, @%3;                \n\t"
+               : "=&r" (oldbit), "=&r" (tmp), "+r" (mask)
+               : "r" (a)
+               : "memory"
+       );
+       local_irq_restore(flags);
+
+       return (oldbit != 0);
+}
+
+/**
+ * __test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+static inline int __test_and_clear_bit(int nr, volatile void * addr)
+{
+       __u32 mask, oldbit;
+       volatile __u32 *a = addr;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+       oldbit = (*a & mask);
+       *a &= ~mask;
+
+       return (oldbit != 0);
+}
+
+/* WARNING: non atomic and it can be reordered! */
+static inline int __test_and_change_bit(int nr, volatile void * addr)
+{
+       __u32 mask, oldbit;
+       volatile __u32 *a = addr;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+       oldbit = (*a & mask);
+       *a ^= mask;
+
+       return (oldbit != 0);
+}
+
+/**
+ * test_and_change_bit - Change a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_change_bit(int nr, volatile void * addr)
+{
+       __u32 mask, oldbit;
+       volatile __u32 *a = addr;
+       unsigned long flags;
+       unsigned long tmp;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               DCACHE_CLEAR("%0", "%1", "%2")
+               LOAD"   %0, @%2;                \n\t"
+               "mv     %1, %0;                 \n\t"
+               "and    %0, %3;                 \n\t"
+               "xor    %1, %3;                 \n\t"
+               STORE"  %1, @%2;                \n\t"
+               : "=&r" (oldbit), "=&r" (tmp)
+               : "r" (a), "r" (mask)
+               : "memory"
+       );
+       local_irq_restore(flags);
+
+       return (oldbit != 0);
+}
+
+#if 0 /* Fool kernel-doc since it doesn't do macros yet */
+/**
+ * test_bit - Determine whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static int test_bit(int nr, const volatile void * addr);
+#endif
+
+static inline int test_bit(int nr, const volatile void * addr)
+{
+       __u32 mask;
+       const volatile __u32 *a = addr;
+
+       a += (nr >> 5);
+       mask = (1 << (nr & 0x1F));
+
+       return ((*a & mask) != 0);
+}
+
+/**
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static inline unsigned long ffz(unsigned long word)
+{
+       int k;
+
+       word = ~word;
+       k = 0;
+       if (!(word & 0x0000ffff)) { k += 16; word >>= 16; }
+       if (!(word & 0x000000ff)) { k += 8; word >>= 8; }
+       if (!(word & 0x0000000f)) { k += 4; word >>= 4; }
+       if (!(word & 0x00000003)) { k += 2; word >>= 2; }
+       if (!(word & 0x00000001)) { k += 1; }
+
+       return k;
+}
+
+/**
+ * find_first_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first zero bit, not the number of the byte
+ * containing a bit.
+ */
+
+#define find_first_zero_bit(addr, size) \
+       find_next_zero_bit((addr), (size), 0)
+
+/**
+ * find_next_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+static inline int find_next_zero_bit(void *addr, int size, int offset)
+{
+       unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+       unsigned long result = offset & ~31UL;
+       unsigned long tmp;
+
+       if (offset >= size)
+               return size;
+       size -= result;
+       offset &= 31UL;
+       if (offset) {
+               tmp = *(p++);
+               tmp |= ~0UL >> (32-offset);
+               if (size < 32)
+                       goto found_first;
+               if (~tmp)
+                       goto found_middle;
+               size -= 32;
+               result += 32;
+       }
+       while (size & ~31UL) {
+               if (~(tmp = *(p++)))
+                       goto found_middle;
+               result += 32;
+               size -= 32;
+       }
+       if (!size)
+               return result;
+       tmp = *p;
+
+found_first:
+       tmp |= ~0UL << size;
+found_middle:
+       return result + ffz(tmp);
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+       int k = 0;
+
+       if (!(word & 0x0000ffff)) { k += 16; word >>= 16; }
+       if (!(word & 0x000000ff)) { k += 8; word >>= 8; }
+       if (!(word & 0x0000000f)) { k += 4; word >>= 4; }
+       if (!(word & 0x00000003)) { k += 2; word >>= 2; }
+       if (!(word & 0x00000001)) { k += 1;}
+
+       return k;
+}
+
+/*
+ * fls: find last bit set.
+ */
+#define fls(x) generic_fls(x)
+
+#ifdef __KERNEL__
+
+/*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 140-bit bitmap where the first 100 bits are
+ * unlikely to be set. It's guaranteed that at least one of the 140
+ * bits is cleared.
+ */
+static inline int sched_find_first_bit(unsigned long *b)
+{
+       if (unlikely(b[0]))
+               return __ffs(b[0]);
+       if (unlikely(b[1]))
+               return __ffs(b[1]) + 32;
+       if (unlikely(b[2]))
+               return __ffs(b[2]) + 64;
+       if (b[3])
+               return __ffs(b[3]) + 96;
+       return __ffs(b[4]) + 128;
+}
+
+/**
+ * find_next_bit - find the first set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+static inline unsigned long find_next_bit(const unsigned long *addr,
+       unsigned long size, unsigned long offset)
+{
+       unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
+       unsigned int result = offset & ~31UL;
+       unsigned int tmp;
+
+       if (offset >= size)
+               return size;
+       size -= result;
+       offset &= 31UL;
+       if (offset) {
+               tmp = *p++;
+               tmp &= ~0UL << offset;
+               if (size < 32)
+                       goto found_first;
+               if (tmp)
+                       goto found_middle;
+               size -= 32;
+               result += 32;
+       }
+       while (size >= 32) {
+               if ((tmp = *p++) != 0)
+                       goto found_middle;
+               result += 32;
+               size -= 32;
+       }
+       if (!size)
+               return result;
+       tmp = *p;
+
+found_first:
+       tmp &= ~0UL >> (32 - size);
+       if (tmp == 0UL)        /* Are any bits set? */
+               return result + size; /* Nope. */
+found_middle:
+       return result + __ffs(tmp);
+}
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first set bit, not the number of the byte
+ * containing a bit.
+ */
+#define find_first_bit(addr, size) \
+       find_next_bit((addr), (size), 0)
+
+/**
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+#define ffs(x) generic_ffs(x)
+
+/**
+ * hweightN - returns the hamming weight of a N-bit word
+ * @x: the word to weigh
+ *
+ * The Hamming Weight of a number is the total number of bits set in it.
+ */
+
+#define hweight32(x)   generic_hweight32(x)
+#define hweight16(x)   generic_hweight16(x)
+#define hweight8(x)    generic_hweight8(x)
+
+#endif /* __KERNEL__ */
+
+#ifdef __KERNEL__
+
+/*
+ * ext2_XXXX function
+ * orig: include/asm-sh/bitops.h
+ */
+
+#ifdef __LITTLE_ENDIAN__
+#define ext2_set_bit                   test_and_set_bit
+#define ext2_clear_bit                 __test_and_clear_bit
+#define ext2_test_bit                  test_bit
+#define ext2_find_first_zero_bit       find_first_zero_bit
+#define ext2_find_next_zero_bit                find_next_zero_bit
+#else
+static inline int ext2_set_bit(int nr, volatile void * addr)
+{
+       __u8 mask, oldbit;
+       volatile __u8 *a = addr;
+
+       a += (nr >> 3);
+       mask = (1 << (nr & 0x07));
+       oldbit = (*a & mask);
+       *a |= mask;
+
+       return (oldbit != 0);
+}
+
+static inline int ext2_clear_bit(int nr, volatile void * addr)
+{
+       __u8 mask, oldbit;
+       volatile __u8 *a = addr;
+
+       a += (nr >> 3);
+       mask = (1 << (nr & 0x07));
+       oldbit = (*a & mask);
+       *a &= ~mask;
+
+       return (oldbit != 0);
+}
+
+static inline int ext2_test_bit(int nr, const volatile void * addr)
+{
+       __u32 mask;
+       const volatile __u8 *a = addr;
+
+       a += (nr >> 3);
+       mask = (1 << (nr & 0x07));
+
+       return ((mask & *a) != 0);
+}
+
+#define ext2_find_first_zero_bit(addr, size) \
+       ext2_find_next_zero_bit((addr), (size), 0)
+
+static inline unsigned long ext2_find_next_zero_bit(void *addr,
+       unsigned long size, unsigned long offset)
+{
+       unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+       unsigned long result = offset & ~31UL;
+       unsigned long tmp;
+
+       if (offset >= size)
+               return size;
+       size -= result;
+       offset &= 31UL;
+       if(offset) {
+               /* We hold the little endian value in tmp, but then the
+                * shift is illegal. So we could keep a big endian value
+                * in tmp, like this:
+                *
+                * tmp = __swab32(*(p++));
+                * tmp |= ~0UL >> (32-offset);
+                *
+                * but this would decrease preformance, so we change the
+                * shift:
+                */
+               tmp = *(p++);
+               tmp |= __swab32(~0UL >> (32-offset));
+               if(size < 32)
+                       goto found_first;
+               if(~tmp)
+                       goto found_middle;
+               size -= 32;
+               result += 32;
+       }
+       while(size & ~31UL) {
+               if(~(tmp = *(p++)))
+                       goto found_middle;
+               result += 32;
+               size -= 32;
+       }
+       if(!size)
+               return result;
+       tmp = *p;
+
+found_first:
+       /* tmp is little endian, so we would have to swab the shift,
+        * see above. But then we have to swab tmp below for ffz, so
+        * we might as well do this here.
+        */
+       return result + ffz(__swab32(tmp) | (~0UL << size));
+found_middle:
+       return result + ffz(__swab32(tmp));
+}
+#endif
+
+#define ext2_set_bit_atomic(lock, nr, addr)            \
+       ({                                              \
+               int ret;                                \
+               spin_lock(lock);                        \
+               ret = ext2_set_bit((nr), (addr));       \
+               spin_unlock(lock);                      \
+               ret;                                    \
+       })
+
+#define ext2_clear_bit_atomic(lock, nr, addr)          \
+       ({                                              \
+               int ret;                                \
+               spin_lock(lock);                        \
+               ret = ext2_clear_bit((nr), (addr));     \
+               spin_unlock(lock);                      \
+               ret;                                    \
+       })
+
+/* Bitmap functions for the minix filesystem.  */
+#define minix_test_and_set_bit(nr,addr)                __test_and_set_bit(nr,addr)
+#define minix_set_bit(nr,addr)                 __set_bit(nr,addr)
+#define minix_test_and_clear_bit(nr,addr)      __test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size)   find_first_zero_bit(addr,size)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_M32R_BITOPS_H */
diff --git a/include/asm-m32r/bug.h b/include/asm-m32r/bug.h
new file mode 100644 (file)
index 0000000..a6d1efe
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _M32R_BUG_H
+#define _M32R_BUG_H
+
+#define BUG()  do { \
+       printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+} while (0)
+
+#define PAGE_BUG(page) do { BUG(); } while (0)
+
+#define BUG_ON(condition) \
+       do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
+#define WARN_ON(condition) do { \
+       if (unlikely((condition)!=0)) { \
+               printk("Badness in %s at %s:%d\n", __FUNCTION__, \
+               __FILE__, __LINE__); \
+               dump_stack(); \
+       } \
+} while (0)
+
+#endif /* _M32R_BUG_H */
+
diff --git a/include/asm-m32r/bugs.h b/include/asm-m32r/bugs.h
new file mode 100644 (file)
index 0000000..9a56f66
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef _ASM_M32R_BUGS_H
+#define _ASM_M32R_BUGS_H
+
+/* $Id$ */
+
+/*
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Needs:
+ *     void check_bugs(void);
+ */
+#include <asm/processor.h>
+
+static void __init check_bugs(void)
+{
+       extern unsigned long loops_per_jiffy;
+
+       current_cpu_data.loops_per_jiffy = loops_per_jiffy;
+}
+
+#endif  /* _ASM_M32R_BUGS_H */
diff --git a/include/asm-m32r/byteorder.h b/include/asm-m32r/byteorder.h
new file mode 100644 (file)
index 0000000..3c0b9a2
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _ASM_M32R_BYTEORDER_H
+#define _ASM_M32R_BYTEORDER_H
+
+/* $Id$ */
+
+#include <asm/types.h>
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#  define __SWAB_64_THRU_32__
+#endif
+
+#if defined(__LITTLE_ENDIAN__)
+#  include <linux/byteorder/little_endian.h>
+#else
+#  include <linux/byteorder/big_endian.h>
+#endif
+
+#endif /* _ASM_M32R_BYTEORDER_H */
diff --git a/include/asm-m32r/cache.h b/include/asm-m32r/cache.h
new file mode 100644 (file)
index 0000000..7248205
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _ASM_M32R_CACHE_H
+#define _ASM_M32R_CACHE_H
+
+/* $Id$ */
+
+/* L1 cache line size */
+#define L1_CACHE_SHIFT         4
+#define L1_CACHE_BYTES         (1 << L1_CACHE_SHIFT)
+
+#define L1_CACHE_SHIFT_MAX     4
+
+#endif  /* _ASM_M32R_CACHE_H */
diff --git a/include/asm-m32r/cachectl.h b/include/asm-m32r/cachectl.h
new file mode 100644 (file)
index 0000000..2aab8f6
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * cachectl.h -- defines for M32R cache control system calls
+ *
+ * Copyright (C) 2003 by Kazuhiro Inaoka
+ */
+#ifndef        __ASM_M32R_CACHECTL
+#define        __ASM_M32R_CACHECTL
+
+/*
+ * Options for cacheflush system call
+ *
+ * cacheflush() is currently fluch_cache_all().
+ */
+#define        ICACHE  (1<<0)          /* flush instruction cache        */
+#define        DCACHE  (1<<1)          /* writeback and flush data cache */
+#define        BCACHE  (ICACHE|DCACHE) /* flush both caches              */
+
+/*
+ * Caching modes for the cachectl(2) call
+ *
+ * cachectl(2) is currently not supported and returns ENOSYS.
+ */
+#define CACHEABLE      0       /* make pages cacheable */
+#define UNCACHEABLE    1       /* make pages uncacheable */
+
+#endif /* __ASM_M32R_CACHECTL */
diff --git a/include/asm-m32r/cacheflush.h b/include/asm-m32r/cacheflush.h
new file mode 100644 (file)
index 0000000..cf65b74
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef _ASM_M32R_CACHEFLUSH_H
+#define _ASM_M32R_CACHEFLUSH_H
+
+#include <linux/config.h>
+#include <linux/mm.h>
+
+extern void _flush_cache_all(void);
+extern void _flush_cache_copyback_all(void);
+
+#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP)
+#define flush_cache_all()                      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_dcache_page(page)                        do { } while (0)
+#define flush_dcache_mmap_lock(mapping)                do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
+#ifndef CONFIG_SMP
+#define flush_icache_range(start, end)         _flush_cache_copyback_all()
+#define flush_icache_page(vma,pg)              _flush_cache_copyback_all()
+#define flush_icache_user_range(vma,pg,adr,len)        _flush_cache_copyback_all()
+#define flush_cache_sigtramp(addr)             _flush_cache_copyback_all()
+#else  /* CONFIG_SMP */
+extern void smp_flush_cache_all(void);
+#define flush_icache_range(start, end)         smp_flush_cache_all()
+#define flush_icache_page(vma,pg)              smp_flush_cache_all()
+#define flush_icache_user_range(vma,pg,adr,len)        smp_flush_cache_all()
+#define flush_cache_sigtramp(addr)             _flush_cache_copyback_all()
+#endif /* CONFIG_SMP */
+#elif defined(CONFIG_CHIP_M32102)
+#define flush_cache_all()                      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_dcache_page(page)                        do { } while (0)
+#define flush_dcache_mmap_lock(mapping)                do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
+#define flush_icache_range(start, end)         _flush_cache_all()
+#define flush_icache_page(vma,pg)              _flush_cache_all()
+#define flush_icache_user_range(vma,pg,adr,len)        _flush_cache_all()
+#define flush_cache_sigtramp(addr)             _flush_cache_all()
+#else
+#define flush_cache_all()                      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_dcache_page(page)                        do { } while (0)
+#define flush_dcache_mmap_lock(mapping)                do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
+#define flush_icache_range(start, end)         do { } while (0)
+#define flush_icache_page(vma,pg)              do { } while (0)
+#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
+#define flush_cache_sigtramp(addr)             do { } while (0)
+#endif /* CONFIG_CHIP_* */
+
+#define flush_cache_vmap(start, end)   do { } while (0)
+#define flush_cache_vunmap(start, end) do { } while (0)
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len)     \
+do {                                                           \
+       memcpy(dst, src, len);                                  \
+       flush_icache_user_range(vma, page, vaddr, len);         \
+} while (0)
+#define copy_from_user_page(vma, page, vaddr, dst, src, len)   \
+       memcpy(dst, src, len)
+
+#endif /* _ASM_M32R_CACHEFLUSH_H */
+
diff --git a/include/asm-m32r/checksum.h b/include/asm-m32r/checksum.h
new file mode 100644 (file)
index 0000000..433d928
--- /dev/null
@@ -0,0 +1,206 @@
+#ifdef __KERNEL__
+#ifndef _ASM_M32R_CHECKSUM_H
+#define _ASM_M32R_CHECKSUM_H
+
+/*
+ * include/asm-m32r/checksum.h
+ *
+ * IP/TCP/UDP checksum routines
+ *
+ * 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.
+ *
+ * Some code taken from mips and parisc architecture.
+ *
+ *    Copyright (C) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/in6.h>
+
+/*
+ * 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
+ */
+asmlinkage 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
+ */
+extern unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
+                                              int len, unsigned int sum);
+
+/*
+ * This is a new version of the above that records errors it finds in *errp,
+ * but continues and zeros thre rest of the buffer.
+ */
+extern unsigned int csum_partial_copy_from_user(const char __user *src,
+                                                char *dst,
+                                                int len, unsigned int sum,
+                                                int *err_ptr);
+
+/*
+ *     Fold a partial checksum
+ */
+
+static inline unsigned int csum_fold(unsigned int sum)
+{
+       unsigned long tmpreg;
+       __asm__(
+               "       sll3    %1, %0, #16 \n"
+               "       cmp     %0, %0 \n"
+               "       addx    %0, %1 \n"
+               "       ldi     %1, #0 \n"
+               "       srli    %0, #16 \n"
+               "       addx    %0, %1 \n"
+               "       xor3    %0, %0, #0x0000ffff \n"
+               : "=r" (sum), "=&r" (tmpreg)
+               : "0"  (sum)
+               : "cbit"
+       );
+       return sum;
+}
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ */
+static inline unsigned short ip_fast_csum(unsigned char * iph,
+                                         unsigned int ihl) {
+       unsigned long sum, tmpreg0, tmpreg1;
+
+       __asm__ __volatile__(
+               "       ld      %0, @%1+ \n"
+               "       addi    %2, #-4 \n"
+               "#      bgez    %2, 2f \n"
+               "       cmp     %0, %0 \n"
+               "       ld      %3, @%1+ \n"
+               "       ld      %4, @%1+ \n"
+               "       addx    %0, %3 \n"
+               "       ld      %3, @%1+ \n"
+               "       addx    %0, %4 \n"
+               "       addx    %0, %3 \n"
+               "       .fillinsn\n"
+               "1: \n"
+               "       ld      %4, @%1+ \n"
+               "       addi    %2, #-1 \n"
+               "       addx    %0, %4 \n"
+               "       bgtz    %2, 1b \n"
+               "\n"
+               "       ldi     %3, #0 \n"
+               "       addx    %0, %3 \n"
+               "       .fillinsn\n"
+               "2: \n"
+       /* Since the input registers which are loaded with iph and ipl
+          are modified, we must also specify them as outputs, or gcc
+          will assume they contain their original values. */
+       : "=&r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmpreg0), "=&r" (tmpreg1)
+       : "1" (iph), "2" (ihl)
+       : "cbit", "memory");
+
+       return csum_fold(sum);
+}
+
+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
+                                              unsigned long daddr,
+                                              unsigned short len,
+                                              unsigned short proto,
+                                              unsigned int sum)
+{
+#if defined(__LITTLE_ENDIAN)
+       unsigned long len_proto = (ntohs(len)<<16)+proto*256;
+#else
+       unsigned long len_proto = (proto<<16)+len;
+#endif
+       unsigned long tmpreg;
+
+       __asm__(
+               "       cmp     %0, %0 \n"
+               "       addx    %0, %2 \n"
+               "       addx    %0, %3 \n"
+               "       addx    %0, %4 \n"
+               "       ldi     %1, #0 \n"
+               "       addx    %0, %1 \n"
+               : "=r" (sum), "=&r" (tmpreg)
+               : "r" (daddr), "r" (saddr), "r" (len_proto), "0" (sum)
+               : "cbit"
+       );
+
+       return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+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
+ */
+
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+       return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static inline unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+                                                struct in6_addr *daddr,
+                                                __u16 len,
+                                                unsigned short proto,
+                                                unsigned int sum)
+{
+       unsigned long tmpreg0, tmpreg1, tmpreg2, tmpreg3;
+       __asm__(
+               "       ld      %1, @(%5) \n"
+               "       ld      %2, @(4,%5) \n"
+               "       ld      %3, @(8,%5) \n"
+               "       ld      %4, @(12,%5) \n"
+               "       add     %0, %1 \n"
+               "       addx    %0, %2 \n"
+               "       addx    %0, %3 \n"
+               "       addx    %0, %4 \n"
+               "       ld      %1, @(%6) \n"
+               "       ld      %2, @(4,%6) \n"
+               "       ld      %3, @(8,%6) \n"
+               "       ld      %4, @(12,%6) \n"
+               "       addx    %0, %1 \n"
+               "       addx    %0, %2 \n"
+               "       addx    %0, %3 \n"
+               "       addx    %0, %4 \n"
+               "       addx    %0, %7 \n"
+               "       addx    %0, %8 \n"
+               "       ldi     %1, #0 \n"
+               "       addx    %0, %1 \n"
+               : "=&r" (sum), "=&r" (tmpreg0), "=&r" (tmpreg1),
+                 "=&r" (tmpreg2), "=&r" (tmpreg3)
+               : "r" (saddr), "r" (daddr),
+                 "r" (htonl((__u32) (len))), "r" (htonl(proto)), "0" (sum)
+               : "cbit"
+       );
+
+       return csum_fold(sum);
+}
+
+#endif /* _ASM_M32R_CHECKSUM_H */
+#endif /* __KERNEL__ */
diff --git a/include/asm-m32r/current.h b/include/asm-m32r/current.h
new file mode 100644 (file)
index 0000000..c19d927
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _ASM_M32R_CURRENT_H
+#define _ASM_M32R_CURRENT_H
+
+/* $Id$ */
+
+#include <linux/thread_info.h>
+
+struct task_struct;
+
+static __inline__ struct task_struct *get_current(void)
+{
+       return current_thread_info()->task;
+}
+
+#define current        (get_current())
+
+#endif /* _ASM_M32R_CURRENT_H */
+
diff --git a/include/asm-m32r/delay.h b/include/asm-m32r/delay.h
new file mode 100644 (file)
index 0000000..f285eae
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _ASM_M32R_DELAY_H
+#define _ASM_M32R_DELAY_H
+
+/* $Id$ */
+
+/*
+ * Copyright (C) 1993 Linus Torvalds
+ *
+ * Delay routines calling functions in arch/m32r/lib/delay.c
+ */
+
+extern void __bad_udelay(void);
+extern void __bad_ndelay(void);
+
+extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
+extern void __const_udelay(unsigned long usecs);
+extern void __delay(unsigned long loops);
+
+#define udelay(n) (__builtin_constant_p(n) ? \
+       ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
+       __udelay(n))
+
+#define ndelay(n) (__builtin_constant_p(n) ? \
+       ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
+       __ndelay(n))
+
+#endif /* _ASM_M32R_DELAY_H */
diff --git a/include/asm-m32r/div64.h b/include/asm-m32r/div64.h
new file mode 100644 (file)
index 0000000..417a51b
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _ASM_M32R_DIV64
+#define _ASM_M32R_DIV64
+
+/* $Id$ */
+
+/* unsigned long long division.
+ * Input:
+ *  unsigned long long  n
+ *  unsigned long  base
+ * Output:
+ *  n = n / base;
+ *  return value = n % base;
+ */
+#define do_div(n, base)                                                \
+({                                                             \
+       unsigned long _res, _high, _mid, _low;                  \
+                                                               \
+       _low = (n) & 0xffffffffUL;                              \
+       _high = (n) >> 32;                                      \
+       if (_high) {                                            \
+               _mid = (_high % (unsigned long)(base)) << 16;   \
+               _high = _high / (unsigned long)(base);          \
+               _mid += _low >> 16;                             \
+               _low &= 0x0000ffffUL;                           \
+               _low += (_mid % (unsigned long)(base)) << 16;   \
+               _mid = _mid / (unsigned long)(base);            \
+               _res = _low % (unsigned long)(base);            \
+               _low = _low / (unsigned long)(base);            \
+               n = _low + ((long long)_mid << 16) +            \
+                       ((long long)_high << 32);               \
+       } else {                                                \
+               _res = _low % (unsigned long)(base);            \
+               n = (_low / (unsigned long)(base));             \
+       }                                                       \
+       _res;                                                   \
+})
+
+#endif  /* _ASM_M32R_DIV64 */
diff --git a/include/asm-m32r/dma-mapping.h b/include/asm-m32r/dma-mapping.h
new file mode 100644 (file)
index 0000000..3a2db28
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _ASM_M32R_DMA_MAPPING_H
+#define _ASM_M32R_DMA_MAPPING_H
+
+/*
+ * NOTE: Do not include <asm-generic/dma-mapping.h>
+ * Because it requires PCI stuffs, but current M32R don't provide these.
+ */
+
+static inline void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+                  int flag)
+{
+       return (void *)NULL;
+}
+
+static inline void
+dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+                   dma_addr_t dma_handle)
+{
+       return;
+}
+
+#endif /* _ASM_M32R_DMA_MAPPING_H */
diff --git a/include/asm-m32r/dma.h b/include/asm-m32r/dma.h
new file mode 100644 (file)
index 0000000..7263b01
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _ASM_M32R_DMA_H
+#define _ASM_M32R_DMA_H
+
+/* $Id$ */
+
+#include <asm/io.h>
+
+/*
+ * The maximum address that we can perform a DMA transfer
+ * to on this platform
+ */
+#define MAX_DMA_ADDRESS      (PAGE_OFFSET+0x20000000)
+
+#endif /* _ASM_M32R_DMA_H */
diff --git a/include/asm-m32r/elf.h b/include/asm-m32r/elf.h
new file mode 100644 (file)
index 0000000..f601fcb
--- /dev/null
@@ -0,0 +1,172 @@
+#ifndef _ASM_M32R__ELF_H
+#define _ASM_M32R__ELF_H
+
+/*
+ * ELF-specific definitions.
+ *
+ * Copyright (C) 1999-2004, Renesas Technology Corp.
+ *      Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <asm/ptrace.h>
+#include <asm/user.h>
+#include <asm/page.h>
+
+/* M32R relocation types  */
+#define        R_M32R_NONE             0
+#define        R_M32R_16               1
+#define        R_M32R_32               2
+#define        R_M32R_24               3
+#define        R_M32R_10_PCREL         4
+#define        R_M32R_18_PCREL         5
+#define        R_M32R_26_PCREL         6
+#define        R_M32R_HI16_ULO         7
+#define        R_M32R_HI16_SLO         8
+#define        R_M32R_LO16             9
+#define        R_M32R_SDA16            10
+#ifdef OLD_TYPE
+#define        R_M32R_GOT24            11
+#define        R_M32R_26_PLTREL        12
+#define        R_M32R_GOT16_HI_ULO     13
+#define        R_M32R_GOT16_HI_SLO     14
+#define        R_M32R_GOT16_LO         15
+#define        R_M32R_GOTPC24          16
+#define        R_M32R_COPY             17
+#define        R_M32R_GLOB_DAT         18
+#define        R_M32R_JMP_SLOT         19
+#define        R_M32R_RELATIVE         20
+#define        R_M32R_GNU_VTINHERIT    21
+#define        R_M32R_GNU_VTENTRY      22
+
+#define R_M32R_16_RELA         R_M32R_16
+#define R_M32R_32_RELA         R_M32R_32
+#define R_M32R_24_RELA         R_M32R_24
+#define R_M32R_10_PCREL_RELA   R_M32R_10_PCREL
+#define R_M32R_18_PCREL_RELA   R_M32R_18_PCREL
+#define R_M32R_26_PCREL_RELA   R_M32R_26_PCREL
+#define R_M32R_HI16_ULO_RELA   R_M32R_HI16_ULO
+#define R_M32R_HI16_SLO_RELA   R_M32R_HI16_SLO
+#define R_M32R_LO16_RELA       R_M32R_LO16
+#define R_M32R_SDA16_RELA      R_M32R_SDA16
+#else /* not OLD_TYPE */
+#define        R_M32R_GNU_VTINHERIT    11
+#define        R_M32R_GNU_VTENTRY      12
+
+#define        R_M32R_GOT24_SAMPLE             11 /* comflict */
+#define        R_M32R_26_PLTREL_SAMPLE 12 /* comflict */
+#define        R_M32R_GOT16_HI_ULO_SAMPLE      13
+#define        R_M32R_GOT16_HI_SLO_SAMPLE      14
+#define        R_M32R_GOT16_LO_SAMPLE          15
+#define        R_M32R_GOTPC24_SAMPLE           16
+#define        R_M32R_COPY_SAMPLE              17
+#define        R_M32R_GLOB_DAT_SAMPLE          18
+#define        R_M32R_JMP_SLOT_SAMPLE          19
+#define        R_M32R_RELATIVE_SAMPLE          20
+#define        R_M32R_GNU_VTINHERIT_SAMPLE     21
+#define        R_M32R_GNU_VTENTRY_SAMPLE       22
+
+#define R_M32R_16_RELA         33
+#define R_M32R_32_RELA         34
+#define R_M32R_24_RELA         35
+#define R_M32R_10_PCREL_RELA   36
+#define R_M32R_18_PCREL_RELA   37
+#define R_M32R_26_PCREL_RELA   38
+#define R_M32R_HI16_ULO_RELA   39
+#define R_M32R_HI16_SLO_RELA   40
+#define R_M32R_LO16_RELA       41
+#define R_M32R_SDA16_RELA      42
+#define        R_M32R_RELA_GNU_VTINHERIT       43
+#define        R_M32R_RELA_GNU_VTENTRY 44
+
+#define R_M32R_GOT24           48
+#define R_M32R_26_PLTREL       49
+#define R_M32R_COPY            50
+#define R_M32R_GLOB_DAT                51
+#define R_M32R_JMP_SLOT                52
+#define R_M32R_RELATIVE                53
+#define R_M32R_GOTOFF          54
+#define R_M32R_GOTPC24         55
+#define R_M32R_GOT16_HI_ULO    56
+#define R_M32R_GOT16_HI_SLO    57
+#define R_M32R_GOT16_LO                58
+#define R_M32R_GOTPC_HI_ULO    59
+#define R_M32R_GOTPC_HI_SLO    60
+#define R_M32R_GOTPC_LO                61
+#endif /* not OLD_TYPE */
+
+#define R_M32R_NUM             256
+
+/*
+ * ELF register definitions..
+ */
+#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* We have no FP mumumu.  */
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t 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_M32R) || ((x)->e_machine == EM_CYGNUS_M32R))
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS      ELFCLASS32
+#if defined(__LITTLE_ENDIAN)
+#define ELF_DATA       ELFDATA2LSB
+#elif defined(__BIG_ENDIAN)
+#define ELF_DATA       ELFDATA2MSB
+#else
+#error no endian defined
+#endif
+#define ELF_ARCH       EM_M32R
+
+/* r0 is set by ld.so to a pointer to a function which might be
+ * registered using 'atexit'.  This provides a mean for the dynamic
+ * linker to call DT_FINI functions for shared libraries that have
+ * been loaded before the code runs.
+ *
+ * So that we can use the same startup file with static executables,
+ * we start programs with a value of 0 to indicate that there is no
+ * such function.
+ */
+#define ELF_PLAT_INIT(_r, load_addr)   (_r)->r0 = 0
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE      PAGE_SIZE
+
+/*
+ * 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         (TASK_SIZE / 3 * 2)
+
+/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
+   now struct_user_regs, they are different) */
+
+#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(PER_LINUX)
+#endif
+
+#endif  /* _ASM_M32R__ELF_H */
diff --git a/include/asm-m32r/errno.h b/include/asm-m32r/errno.h
new file mode 100644 (file)
index 0000000..7a98520
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _ASM_M32R_ERRNO_H
+#define _ASM_M32R_ERRNO_H
+
+/* $Id$ */
+
+#include <asm-generic/errno.h>
+
+#endif /* _ASM_M32R_ERRNO_H */
+
diff --git a/include/asm-m32r/fcntl.h b/include/asm-m32r/fcntl.h
new file mode 100644 (file)
index 0000000..3e30895
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef _ASM_M32R_FCNTL_H
+#define _ASM_M32R_FCNTL_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE         0003
+#define O_RDONLY            00
+#define O_WRONLY            01
+#define O_RDWR              02
+#define O_CREAT                   0100 /* not fcntl */
+#define O_EXCL            0200 /* not fcntl */
+#define O_NOCTTY          0400 /* not fcntl */
+#define O_TRUNC                  01000 /* not fcntl */
+#define O_APPEND         02000
+#define O_NONBLOCK       04000
+#define O_NDELAY       O_NONBLOCK
+#define O_SYNC          010000
+#define FASYNC          020000 /* fcntl, for BSD compatibility */
+#define O_DIRECT        040000 /* direct disk access hint */
+#define O_LARGEFILE    0100000
+#define O_DIRECTORY    0200000 /* must be a directory */
+#define O_NOFOLLOW     0400000 /* don't follow links */
+#define O_NOATIME      01000000
+
+#define F_DUPFD                0       /* dup */
+#define F_GETFD                1       /* get close_on_exec */
+#define F_SETFD                2       /* set/clear close_on_exec */
+#define F_GETFL                3       /* get file->f_flags */
+#define F_SETFL                4       /* set file->f_flags */
+#define F_GETLK                5
+#define F_SETLK                6
+#define F_SETLKW       7
+
+#define F_SETOWN       8       /*  for sockets. */
+#define F_GETOWN       9       /*  for sockets. */
+#define F_SETSIG       10      /*  for sockets. */
+#define F_GETSIG       11      /*  for sockets. */
+
+#define F_GETLK64      12      /*  using 'struct flock64' */
+#define F_SETLK64      13
+#define F_SETLKW64     14
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK                0
+#define F_WRLCK                1
+#define F_UNLCK                2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK                4       /* or 3 */
+#define F_SHLCK                8       /* or 4 */
+
+/* for leases */
+#define F_INPROGRESS   16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH                1       /* shared lock */
+#define LOCK_EX                2       /* exclusive lock */
+#define LOCK_NB                4       /* or'd with one of the above to prevent
+                                  blocking */
+#define LOCK_UN                8       /* remove lock */
+
+#define LOCK_MAND      32      /* This is a mandatory flock */
+#define LOCK_READ      64      /* ... Which allows concurrent read operations */
+#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
+#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
+
+struct flock {
+       short l_type;
+       short l_whence;
+       off_t l_start;
+       off_t l_len;
+       pid_t l_pid;
+};
+
+struct flock64 {
+       short  l_type;
+       short  l_whence;
+       loff_t l_start;
+       loff_t l_len;
+       pid_t  l_pid;
+};
+
+#define F_LINUX_SPECIFIC_BASE  1024
+
+#endif  /* _ASM_M32R_FCNTL_H */
diff --git a/include/asm-m32r/flat.h b/include/asm-m32r/flat.h
new file mode 100644 (file)
index 0000000..1b285f6
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * include/asm-m32r/flat.h
+ *
+ * uClinux flat-format executables
+ *
+ * Copyright (C) 2004  Kazuhiro Inaoka
+ *
+ * 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 __ASM_M32R_FLAT_H
+#define __ASM_M32R_FLAT_H
+
+#define        flat_stack_align(sp)            (*sp += (*sp & 3 ? (4 - (*sp & 3)): 0))
+#define        flat_argvp_envp_on_stack()              0
+#define        flat_old_ram_flag(flags)                (flags)
+#define        flat_reloc_valid(reloc, size)           \
+       (((reloc) - textlen_for_m32r_lo16_data) <= (size))
+#define flat_get_addr_from_rp(rp, relval, flags) \
+       m32r_flat_get_addr_from_rp(rp, relval, (text_len) )
+
+#define flat_put_addr_at_rp(rp, addr, relval) \
+       m32r_flat_put_addr_at_rp(rp, addr, relval)
+
+/* Convert a relocation entry into an address.  */
+static inline unsigned long
+flat_get_relocate_addr (unsigned long relval)
+{
+        return relval & 0x00ffffff; /* Mask out top 8-bits */
+}
+
+#define        flat_m32r_get_reloc_type(relval)        ((relval) >> 24)
+
+#define M32R_SETH_OPCODE       0xd0c00000 /* SETH instruction code */
+
+#define FLAT_M32R_32           0x00    /* 32bits reloc */
+#define FLAT_M32R_24           0x01    /* unsigned 24bits reloc */
+#define FLAT_M32R_16           0x02    /* 16bits reloc */
+#define FLAT_M32R_LO16         0x03    /* signed low 16bits reloc (low()) */
+#define FLAT_M32R_LO16_DATA    0x04    /* signed low 16bits reloc (low())
+                                          for a symbol in .data section */
+                                       /* High 16bits of an address used
+                                          when the lower 16bbits are treated
+                                          as unsigned.
+                                           To create SETH instruction only.
+                                          0x1X: X means a number of register.
+                                          0x10 - 0x3F are reserved. */
+#define FLAT_M32R_HI16_ULO     0x10    /* reloc for SETH Rn,#high(imm16) */
+                                       /* High 16bits of an address used
+                                          when the lower 16bbits are treated
+                                          as signed.
+                                           To create SETH instruction only.
+                                          0x2X: X means a number of register.
+                                          0x20 - 0x4F are reserved. */
+#define FLAT_M32R_HI16_SLO     0x20    /* reloc for SETH Rn,#shigh(imm16) */
+
+static unsigned long textlen_for_m32r_lo16_data = 0;
+
+static inline unsigned long m32r_flat_get_addr_from_rp (unsigned long *rp,
+                                                        unsigned long relval,
+                                                       unsigned long textlen)
+{
+        unsigned int reloc = flat_m32r_get_reloc_type (relval);
+       textlen_for_m32r_lo16_data = 0;
+       if (reloc & 0xf0) {
+               unsigned long addr = htonl(*rp);
+               switch (reloc & 0xf0)
+               {
+               case FLAT_M32R_HI16_ULO:
+               case FLAT_M32R_HI16_SLO:
+                       if (addr == 0) {
+                               /* put "seth Rn,#0x0" instead of 0 (addr). */
+                               *rp = (M32R_SETH_OPCODE | ((reloc & 0x0f)<<24));
+                       }
+                       return addr;
+               default:
+                       break;
+               }
+       } else {
+               switch (reloc)
+               {
+               case FLAT_M32R_LO16:
+                       return htonl(*rp) & 0xFFFF;
+               case FLAT_M32R_LO16_DATA:
+                        /* FIXME: The return value will decrease by textlen
+                          at m32r_flat_put_addr_at_rp () */
+                       textlen_for_m32r_lo16_data = textlen;
+                       return (htonl(*rp) & 0xFFFF) + textlen;
+               case FLAT_M32R_16:
+                       return htons(*(unsigned short *)rp) & 0xFFFF;
+               case FLAT_M32R_24:
+                       return htonl(*rp) & 0xFFFFFF;
+               case FLAT_M32R_32:
+                       return htonl(*rp);
+               default:
+                       break;
+               }
+       }
+       return ~0;      /* bogus value */
+}
+
+static inline void m32r_flat_put_addr_at_rp (unsigned long *rp,
+                                            unsigned long addr,
+                                             unsigned long relval)
+{
+        unsigned int reloc = flat_m32r_get_reloc_type (relval);
+       if (reloc & 0xf0) {
+               unsigned long Rn = reloc & 0x0f; /* get a number of register */
+               Rn <<= 24; /* 0x0R000000 */
+               reloc &= 0xf0;
+               switch (reloc)
+               {
+               case FLAT_M32R_HI16_ULO: /* To create SETH Rn,#high(imm16) */
+                       *rp = (M32R_SETH_OPCODE | Rn
+                              | ((addr >> 16) & 0xFFFF));
+                       break;
+               case FLAT_M32R_HI16_SLO: /* To create SETH Rn,#shigh(imm16) */
+                       *rp = (M32R_SETH_OPCODE | Rn
+                              | (((addr >> 16) + ((addr & 0x8000) ? 1 : 0))
+                                 & 0xFFFF));
+                       break;
+               }
+       } else {
+               switch (reloc) {
+               case FLAT_M32R_LO16_DATA:
+                       addr -= textlen_for_m32r_lo16_data;
+                       textlen_for_m32r_lo16_data = 0;
+               case FLAT_M32R_LO16:
+                       *rp = (htonl(*rp) & 0xFFFF0000) | (addr & 0xFFFF);
+                       break;
+               case FLAT_M32R_16:
+                       *(unsigned short *)rp = addr & 0xFFFF;
+                       break;
+               case FLAT_M32R_24:
+                       *rp = (htonl(*rp) & 0xFF000000) | (addr & 0xFFFFFF);
+                       break;
+               case FLAT_M32R_32:
+                       *rp = addr;
+                       break;
+               }
+       }
+}
+
+#endif /* __ASM_M32R_FLAT_H */
diff --git a/include/asm-m32r/hardirq.h b/include/asm-m32r/hardirq.h
new file mode 100644 (file)
index 0000000..b46a265
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __ASM_HARDIRQ_H
+#define __ASM_HARDIRQ_H
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/irq.h>
+
+typedef struct {
+       unsigned int __softirq_pending;
+       unsigned int __syscall_count;
+       struct task_struct * __ksoftirqd_task; /* waitqueue is too large */
+} ____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
+ * SOFTIRQ_MASK: 0x0000ff00
+ * HARDIRQ_MASK: 0x00ff0000
+ */
+
+#define PREEMPT_BITS   8
+#define SOFTIRQ_BITS   8
+
+#if NR_IRQS > 256
+#define HARDIRQ_BITS   9
+#else
+#define HARDIRQ_BITS   8
+#endif
+
+#define PREEMPT_SHIFT  0
+#define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
+#define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
+
+/*
+ * The hardirq mask has to be large enough to have
+ * space for potentially all IRQ sources in the system
+ * nesting on a single CPU:
+ */
+#if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+#endif
+
+#define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
+#define nmi_enter()            (irq_enter())
+#define nmi_exit()             (preempt_count() -= HARDIRQ_OFFSET)
+
+#define irq_exit()                                                     \
+do {                                                                   \
+               preempt_count() -= IRQ_EXIT_OFFSET;                     \
+               if (!in_interrupt() && softirq_pending(smp_processor_id())) \
+                       do_softirq();                                   \
+               preempt_enable_no_resched();                            \
+} while (0)
+
+#endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-m32r/hdreg.h b/include/asm-m32r/hdreg.h
new file mode 100644 (file)
index 0000000..7f7fd1a
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/hdreg.h>
diff --git a/include/asm-m32r/hw_irq.h b/include/asm-m32r/hw_irq.h
new file mode 100644 (file)
index 0000000..8d7e9d0
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _ASM_M32R_HW_IRQ_H
+#define _ASM_M32R_HW_IRQ_H
+
+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
+{
+       /* Nothing to do */
+}
+
+#endif /* _ASM_M32R_HW_IRQ_H */
diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
new file mode 100644 (file)
index 0000000..8389f24
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef _ASM_M32R_IDE_H
+#define _ASM_M32R_IDE_H
+
+/* $Id$ */
+
+/*
+ *  linux/include/asm-m32r/ide.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/*
+ *  This file contains the i386 architecture specific IDE code.
+ */
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+
+#ifndef MAX_HWIFS
+# ifdef CONFIG_BLK_DEV_IDEPCI
+#define MAX_HWIFS      10
+# else
+#define MAX_HWIFS      2
+# endif
+#endif
+
+#if defined(CONFIG_PLAT_M32700UT)
+#include <asm/irq.h>
+#include <asm/m32700ut/m32700ut_pld.h>
+#endif
+
+#define IDE_ARCH_OBSOLETE_DEFAULTS
+
+static __inline__ int ide_default_irq(unsigned long base)
+{
+       switch (base) {
+#if defined(CONFIG_PLAT_M32700UT)
+               case 0x1f0: return PLD_IRQ_CFIREQ;
+               default:
+                       return 0;
+#else
+               case 0x1f0: return 14;
+               case 0x170: return 15;
+               case 0x1e8: return 11;
+               case 0x168: return 10;
+               case 0x1e0: return 8;
+               case 0x160: return 12;
+               default:
+                       return 0;
+#endif
+       }
+}
+
+static __inline__ unsigned long ide_default_io_base(int index)
+{
+       switch (index) {
+               case 0: return 0x1f0;
+               case 1: return 0x170;
+               case 2: return 0x1e8;
+               case 3: return 0x168;
+               case 4: return 0x1e0;
+               case 5: return 0x160;
+               default:
+                       return 0;
+       }
+}
+
+#define IDE_ARCH_OBSOLETE_INIT
+#define ide_default_io_ctl(base)       ((base) + 0x206) /* obsolete */
+
+#ifdef CONFIG_BLK_DEV_IDEPCI
+#define ide_init_default_irq(base)     (0)
+#else
+#define ide_init_default_irq(base)     ide_default_irq(base)
+#endif
+
+#include <asm-generic/ide_iops.h>
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_M32R_IDE_H */
diff --git a/include/asm-m32r/io.h b/include/asm-m32r/io.h
new file mode 100644 (file)
index 0000000..97a64d3
--- /dev/null
@@ -0,0 +1,216 @@
+#ifndef _ASM_M32R_IO_H
+#define _ASM_M32R_IO_H
+
+#include <linux/string.h>
+#include <linux/compiler.h>
+#include <asm/page.h>  /* __va */
+
+#ifdef __KERNEL__
+
+#define IO_SPACE_LIMIT  0xFFFFFFFF
+
+/**
+ *     virt_to_phys    -       map virtual addresses to physical
+ *     @address: address to remap
+ *
+ *     The returned physical address is the physical (CPU) mapping for
+ *     the memory address given. It is only valid to use this function on
+ *     addresses directly mapped or allocated via kmalloc.
+ *
+ *     This function does not give bus mappings for DMA transfers. In
+ *     almost all conceivable cases a device driver should not be using
+ *     this function
+ */
+
+static inline unsigned long virt_to_phys(volatile void * address)
+{
+       return __pa(address);
+}
+
+/**
+ *     phys_to_virt    -       map physical address to virtual
+ *     @address: address to remap
+ *
+ *     The returned virtual address is a current CPU mapping for
+ *     the memory address given. It is only valid to use this function on
+ *     addresses that have a kernel mapping
+ *
+ *     This function does not handle bus mappings for DMA transfers. In
+ *     almost all conceivable cases a device driver should not be using
+ *     this function
+ */
+
+static inline void *phys_to_virt(unsigned long address)
+{
+       return __va(address);
+}
+
+extern void __iomem *
+__ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+
+/**
+ *     ioremap         -       map bus memory into CPU space
+ *     @offset:        bus address of the memory
+ *     @size:          size of the resource to map
+ *
+ *     ioremap performs a platform specific sequence of operations to
+ *     make bus memory CPU accessible via the readb/readw/readl/writeb/
+ *     writew/writel functions and the other mmio helpers. The returned
+ *     address is not guaranteed to be usable directly as a virtual
+ *     address.
+ */
+
+static inline void * ioremap(unsigned long offset, unsigned long size)
+{
+       return __ioremap(offset, size, 0);
+}
+
+extern void iounmap(volatile void __iomem *addr);
+#define ioremap_nocache(off,size) ioremap(off,size)
+
+/*
+ * IO bus memory addresses are also 1:1 with the physical address
+ */
+#define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
+#define page_to_bus    page_to_phys
+#define virt_to_bus    virt_to_phys
+
+extern unsigned char _inb(unsigned long);
+extern unsigned short _inw(unsigned long);
+extern unsigned long _inl(unsigned long);
+extern unsigned char _inb_p(unsigned long);
+extern unsigned short _inw_p(unsigned long);
+extern unsigned long _inl_p(unsigned long);
+extern void _outb(unsigned char, unsigned long);
+extern void _outw(unsigned short, unsigned long);
+extern void _outl(unsigned long, unsigned long);
+extern void _outb_p(unsigned char, unsigned long);
+extern void _outw_p(unsigned short, unsigned long);
+extern void _outl_p(unsigned long, unsigned long);
+extern void _insb(unsigned int, void *, unsigned long);
+extern void _insw(unsigned int, void *, unsigned long);
+extern void _insl(unsigned int, void *, unsigned long);
+extern void _outsb(unsigned int, const void *, unsigned long);
+extern void _outsw(unsigned int, const void *, unsigned long);
+extern void _outsl(unsigned int, const void *, unsigned long);
+
+static inline unsigned char _readb(unsigned long addr)
+{
+       return *(volatile unsigned char __force *)addr;
+}
+
+static inline unsigned short _readw(unsigned long addr)
+{
+       return *(volatile unsigned short __force *)addr;
+}
+
+static inline unsigned long _readl(unsigned long addr)
+{
+       return *(volatile unsigned long __force *)addr;
+}
+
+static inline void _writeb(unsigned char b, unsigned long addr)
+{
+       *(volatile unsigned char __force *)addr = b;
+}
+
+static inline void _writew(unsigned short w, unsigned long addr)
+{
+       *(volatile unsigned short __force *)addr = w;
+}
+
+static inline void _writel(unsigned long l, unsigned long addr)
+{
+       *(volatile unsigned long __force *)addr = l;
+}
+
+#define inb     _inb
+#define inw     _inw
+#define inl     _inl
+#define outb    _outb
+#define outw    _outw
+#define outl    _outl
+
+#define inb_p   _inb_p
+#define inw_p   _inw_p
+#define inl_p   _inl_p
+#define outb_p  _outb_p
+#define outw_p  _outw_p
+#define outl_p  _outl_p
+
+#define insb    _insb
+#define insw    _insw
+#define insl    _insl
+#define outsb   _outsb
+#define outsw   _outsw
+#define outsl   _outsl
+
+#define readb(addr)   _readb((unsigned long)(addr))
+#define readw(addr)   _readw((unsigned long)(addr))
+#define readl(addr)   _readl((unsigned long)(addr))
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+
+#define writeb(val, addr)  _writeb((val), (unsigned long)(addr))
+#define writew(val, addr)  _writew((val), (unsigned long)(addr))
+#define writel(val, addr)  _writel((val), (unsigned long)(addr))
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+#define flush_write_buffers() do { } while (0)  /* M32R_FIXME */
+
+/**
+ *     isa_check_signature             -       find BIOS signatures
+ *     @io_addr: mmio address to check
+ *     @signature:  signature block
+ *     @length: length of signature
+ *
+ *     Perform a signature comparison with the ISA mmio address io_addr.
+ *     Returns 1 on a match.
+ *
+ *     This function is deprecated. New drivers should use ioremap and
+ *     check_signature.
+ */
+
+static inline int isa_check_signature(unsigned long io_addr,
+        const unsigned char *signature, int length)
+{
+        int retval = 0;
+#if 0
+printk("isa_check_signature\n");
+        do {
+                if (isa_readb(io_addr) != *signature)
+                        goto out;
+                io_addr++;
+                signature++;
+                length--;
+        } while (length);
+        retval = 1;
+out:
+#endif
+        return retval;
+}
+
+static inline void
+memset_io(volatile void __iomem *addr, unsigned char val, int count)
+{
+       memset((void __force *) addr, val, count);
+}
+
+static inline void
+memcpy_fromio(void *dst, volatile void __iomem *src, int count)
+{
+       memcpy(dst, (void __force *) src, count);
+}
+
+static inline void
+memcpy_toio(volatile void __iomem *dst, const void *src, int count)
+{
+       memcpy((void __force *) dst, src, count);
+}
+
+#endif  /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_IO_H */
diff --git a/include/asm-m32r/ioctl.h b/include/asm-m32r/ioctl.h
new file mode 100644 (file)
index 0000000..87d8f7d
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef _ASM_M32R_IOCTL_H
+#define _ASM_M32R_IOCTL_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * linux/ioctl.h for Linux by H.H. Bergman.
+ */
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms.  The i386 ioctl numbering scheme doesn't really enforce
+ * a type field.  De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here.  Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS    8
+#define _IOC_TYPEBITS  8
+#define _IOC_SIZEBITS  14
+#define _IOC_DIRBITS   2
+
+#define _IOC_NRMASK    ((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK  ((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK  ((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK   ((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT   0
+#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT  (_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE      0U
+#define _IOC_WRITE     1U
+#define _IOC_READ      2U
+
+#define _IOC(dir,type,nr,size) \
+       (((dir)  << _IOC_DIRSHIFT) | \
+        ((type) << _IOC_TYPESHIFT) | \
+        ((nr)   << _IOC_NRSHIFT) | \
+        ((size) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr)           _IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)     _IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)     _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size)    _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr)           (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)          (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)            (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)          (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN         (_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT                (_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT      ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK   (_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT  (_IOC_SIZESHIFT)
+
+#endif /* _ASM_M32R_IOCTL_H */
diff --git a/include/asm-m32r/ioctls.h b/include/asm-m32r/ioctls.h
new file mode 100644 (file)
index 0000000..b350829
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef __ARCH_M32R_IOCTLS_H__
+#define __ARCH_M32R_IOCTLS_H__
+
+/* $Id$ */
+
+/* orig : i386 2.5.67 */
+
+#include <asm/ioctl.h>
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define TCGETS         0x5401
+#define TCSETS         0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
+#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 - Former debugging-only ioctl */
+#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
+#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 TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */
+#define TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */
+#define FIOQSIZE       0x5460
+
+/* 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_M32R_IOCTLS_H__ */
+
diff --git a/include/asm-m32r/ipc.h b/include/asm-m32r/ipc.h
new file mode 100644 (file)
index 0000000..03aac66
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __M32R_IPC_H__
+#define __M32R_IPC_H__
+
+/* orig : i386/ipc.h 2.6.0-test3 */
+
+/*
+ * These are used to wrap system calls on x86.
+ *
+ * See arch/i386/kernel/sys_i386.c for ugly details..
+ */
+struct ipc_kludge {
+       struct msgbuf __user *msgp;
+       long msgtyp;
+};
+
+#define SEMOP           1
+#define SEMGET          2
+#define SEMCTL          3
+#define SEMTIMEDOP      4
+#define MSGSND         11
+#define MSGRCV         12
+#define MSGGET         13
+#define MSGCTL         14
+#define SHMAT          21
+#define SHMDT          22
+#define SHMGET         23
+#define SHMCTL         24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC            25
+
+#define IPCCALL(version,op)    ((version)<<16 | (op))
+
+#endif /* __M32R_IPC_H__ */
+
diff --git a/include/asm-m32r/ipcbuf.h b/include/asm-m32r/ipcbuf.h
new file mode 100644 (file)
index 0000000..7c77fb0
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _ASM_M32R_IPCBUF_H
+#define _ASM_M32R_IPCBUF_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * The ipc64_perm structure for m32r 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 /* _ASM_M32R_IPCBUF_H */
diff --git a/include/asm-m32r/irq.h b/include/asm-m32r/irq.h
new file mode 100644 (file)
index 0000000..f83e59f
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef _ASM_M32R_IRQ_H
+#define _ASM_M32R_IRQ_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+
+#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_USRV)
+/*
+ * IRQ definitions for M32700UT
+ *  M32700 Chip: 64 interrupts
+ *  ICU of M32700UT-on-board PLD: 32 interrupts cascaded to INT1# chip pin
+ */
+#define        M32700UT_NUM_CPU_IRQ    (64)
+#define M32700UT_NUM_PLD_IRQ   (32)
+#define M32700UT_IRQ_BASE      0
+#define M32700UT_CPU_IRQ_BASE  M32700UT_IRQ_BASE
+#define M32700UT_PLD_IRQ_BASE  (M32700UT_CPU_IRQ_BASE + M32700UT_NUM_CPU_IRQ)
+
+#define NR_IRQS        (M32700UT_NUM_CPU_IRQ + M32700UT_NUM_PLD_IRQ)
+#elif defined(CONFIG_PLAT_M32700UT)
+/*
+ * IRQ definitions for M32700UT(Rev.C) + M32R-LAN
+ *  M32700 Chip: 64 interrupts
+ *  ICU of M32700UT-on-board PLD: 32 interrupts cascaded to INT1# chip pin
+ *  ICU of M32R-LCD-on-board PLD: 32 interrupts cascaded to INT2# chip pin
+ *  ICU of M32R-LAN-on-board PLD: 32 interrupts cascaded to INT0# chip pin
+ */
+#define M32700UT_NUM_CPU_IRQ           (64)
+#define M32700UT_NUM_PLD_IRQ           (32)
+#define M32700UT_NUM_LCD_PLD_IRQ       (32)
+#define M32700UT_NUM_LAN_PLD_IRQ       (32)
+#define M32700UT_IRQ_BASE              0
+#define M32700UT_CPU_IRQ_BASE          (M32700UT_IRQ_BASE)
+#define M32700UT_PLD_IRQ_BASE \
+       (M32700UT_CPU_IRQ_BASE + M32700UT_NUM_CPU_IRQ)
+#define M32700UT_LCD_PLD_IRQ_BASE \
+       (M32700UT_PLD_IRQ_BASE + M32700UT_NUM_PLD_IRQ)
+#define M32700UT_LAN_PLD_IRQ_BASE \
+       (M32700UT_LCD_PLD_IRQ_BASE + M32700UT_NUM_LCD_PLD_IRQ)
+
+#define NR_IRQS \
+       (M32700UT_NUM_CPU_IRQ + M32700UT_NUM_PLD_IRQ \
+       + M32700UT_NUM_LCD_PLD_IRQ + M32700UT_NUM_LAN_PLD_IRQ)
+#elif defined(CONFIG_PLAT_OPSPUT)
+/*
+ * IRQ definitions for OPSPUT + M32R-LAN
+ *  OPSP Chip: 64 interrupts
+ *  ICU of OPSPUT-on-board PLD: 32 interrupts cascaded to INT1# chip pin
+ *  ICU of M32R-LCD-on-board PLD: 32 interrupts cascaded to INT2# chip pin
+ *  ICU of M32R-LAN-on-board PLD: 32 interrupts cascaded to INT0# chip pin
+ */
+#define OPSPUT_NUM_CPU_IRQ             (64)
+#define OPSPUT_NUM_PLD_IRQ             (32)
+#define OPSPUT_NUM_LCD_PLD_IRQ (32)
+#define OPSPUT_NUM_LAN_PLD_IRQ (32)
+#define OPSPUT_IRQ_BASE                0
+#define OPSPUT_CPU_IRQ_BASE            (OPSPUT_IRQ_BASE)
+#define OPSPUT_PLD_IRQ_BASE \
+       (OPSPUT_CPU_IRQ_BASE + OPSPUT_NUM_CPU_IRQ)
+#define OPSPUT_LCD_PLD_IRQ_BASE \
+       (OPSPUT_PLD_IRQ_BASE + OPSPUT_NUM_PLD_IRQ)
+#define OPSPUT_LAN_PLD_IRQ_BASE \
+       (OPSPUT_LCD_PLD_IRQ_BASE + OPSPUT_NUM_LCD_PLD_IRQ)
+
+#define NR_IRQS \
+       (OPSPUT_NUM_CPU_IRQ + OPSPUT_NUM_PLD_IRQ \
+       + OPSPUT_NUM_LCD_PLD_IRQ + OPSPUT_NUM_LAN_PLD_IRQ)
+#else
+#define NR_IRQS        64
+#endif
+
+#define irq_canonicalize(irq)  (irq)
+
+#ifndef __ASSEMBLY__
+extern void disable_irq(unsigned int);
+extern void disable_irq_nosync(unsigned int);
+extern void enable_irq(unsigned int);
+
+struct irqaction;
+struct pt_regs;
+int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
+#endif
+
+#endif /* _ASM_M32R_IRQ_H */
+
diff --git a/include/asm-m32r/kmap_types.h b/include/asm-m32r/kmap_types.h
new file mode 100644 (file)
index 0000000..7429591
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __M32R_KMAP_TYPES_H
+#define __M32R_KMAP_TYPES_H
+
+/* Dummy header just to define km_type. */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_DEBUG_HIGHMEM
+# define D(n) __KM_FENCE_##n ,
+#else
+# define D(n)
+#endif
+
+enum km_type {
+D(0)   KM_BOUNCE_READ,
+D(1)   KM_SKB_SUNRPC_DATA,
+D(2)   KM_SKB_DATA_SOFTIRQ,
+D(3)   KM_USER0,
+D(4)   KM_USER1,
+D(5)   KM_BIO_SRC_IRQ,
+D(6)   KM_BIO_DST_IRQ,
+D(7)   KM_PTE0,
+D(8)   KM_PTE1,
+D(9)   KM_IRQ0,
+D(10)  KM_IRQ1,
+D(11)  KM_SOFTIRQ0,
+D(12)  KM_SOFTIRQ1,
+D(13)  KM_TYPE_NR
+};
+
+#undef D
+
+#endif /* __M32R_KMAP_TYPES_H */
+
diff --git a/include/asm-m32r/linkage.h b/include/asm-m32r/linkage.h
new file mode 100644 (file)
index 0000000..a9fb151
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#define __ALIGN                .balign 4
+#define __ALIGN_STR    ".balign 4"
+
+#endif /* __ASM_LINKAGE_H */
diff --git a/include/asm-m32r/local.h b/include/asm-m32r/local.h
new file mode 100644 (file)
index 0000000..def29d0
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __M32R_LOCAL_H
+#define __M32R_LOCAL_H
+
+#include <asm-generic/local.h>
+
+#endif /* __M32R_LOCAL_H */
diff --git a/include/asm-m32r/m32102.h b/include/asm-m32r/m32102.h
new file mode 100644 (file)
index 0000000..38e3a73
--- /dev/null
@@ -0,0 +1,266 @@
+#ifndef _M32102_H_
+#define _M32102_H_
+
+/*
+ * Renesas M32R 32102 group
+ *
+ * Copyright (c) 2001  Hitoshi Yamamoto
+ * Copyright (c) 2003, 2004  Renesas Technology Corp.
+ */
+
+/*======================================================================*
+ * Special Function Register
+ *======================================================================*/
+#define M32R_SFR_OFFSET  (0x00E00000)  /* 0x00E00000-0x00EFFFFF 1[MB] */
+
+/*
+ * Clock and Power Management registers.
+ */
+#define M32R_CPM_OFFSET          (0x000F4000+M32R_SFR_OFFSET)
+
+#define M32R_CPM_CPUCLKCR_PORTL  (0x00+M32R_CPM_OFFSET)
+#define M32R_CPM_CLKMOD_PORTL    (0x04+M32R_CPM_OFFSET)
+#define M32R_CPM_PLLCR_PORTL     (0x08+M32R_CPM_OFFSET)
+
+/*
+ * Multi Function Timer registers.
+ */
+#define M32R_MFT_OFFSET        (0x000FC000+M32R_SFR_OFFSET)
+
+#define M32R_MFTCR_PORTL       (0x000+M32R_MFT_OFFSET)  /* MFT control */
+#define M32R_MFTRPR_PORTL      (0x004+M32R_MFT_OFFSET)  /* MFT real port */
+
+#define M32R_MFT0_OFFSET       (0x100+M32R_MFT_OFFSET)
+#define M32R_MFT0MOD_PORTL     (0x00+M32R_MFT0_OFFSET)  /* MFT0 mode */
+#define M32R_MFT0BOS_PORTL     (0x04+M32R_MFT0_OFFSET)  /* MFT0 b-port output status */
+#define M32R_MFT0CUT_PORTL     (0x08+M32R_MFT0_OFFSET)  /* MFT0 count */
+#define M32R_MFT0RLD_PORTL     (0x0C+M32R_MFT0_OFFSET)  /* MFT0 reload */
+#define M32R_MFT0CMPRLD_PORTL  (0x10+M32R_MFT0_OFFSET)  /* MFT0 compare reload */
+
+#define M32R_MFT1_OFFSET       (0x200+M32R_MFT_OFFSET)
+#define M32R_MFT1MOD_PORTL     (0x00+M32R_MFT1_OFFSET)  /* MFT1 mode */
+#define M32R_MFT1BOS_PORTL     (0x04+M32R_MFT1_OFFSET)  /* MFT1 b-port output status */
+#define M32R_MFT1CUT_PORTL     (0x08+M32R_MFT1_OFFSET)  /* MFT1 count */
+#define M32R_MFT1RLD_PORTL     (0x0C+M32R_MFT1_OFFSET)  /* MFT1 reload */
+#define M32R_MFT1CMPRLD_PORTL  (0x10+M32R_MFT1_OFFSET)  /* MFT1 compare reload */
+
+#define M32R_MFT2_OFFSET       (0x300+M32R_MFT_OFFSET)
+#define M32R_MFT2MOD_PORTL     (0x00+M32R_MFT2_OFFSET)  /* MFT2 mode */
+#define M32R_MFT2BOS_PORTL     (0x04+M32R_MFT2_OFFSET)  /* MFT2 b-port output status */
+#define M32R_MFT2CUT_PORTL     (0x08+M32R_MFT2_OFFSET)  /* MFT2 count */
+#define M32R_MFT2RLD_PORTL     (0x0C+M32R_MFT2_OFFSET)  /* MFT2 reload */
+#define M32R_MFT2CMPRLD_PORTL  (0x10+M32R_MFT2_OFFSET)  /* MFT2 compare reload */
+
+#define M32R_MFT3_OFFSET       (0x400+M32R_MFT_OFFSET)
+#define M32R_MFT3MOD_PORTL     (0x00+M32R_MFT3_OFFSET)  /* MFT3 mode */
+#define M32R_MFT3BOS_PORTL     (0x04+M32R_MFT3_OFFSET)  /* MFT3 b-port output status */
+#define M32R_MFT3CUT_PORTL     (0x08+M32R_MFT3_OFFSET)  /* MFT3 count */
+#define M32R_MFT3RLD_PORTL     (0x0C+M32R_MFT3_OFFSET)  /* MFT3 reload */
+#define M32R_MFT3CMPRLD_PORTL  (0x10+M32R_MFT3_OFFSET)  /* MFT3 compare reload */
+
+#define M32R_MFT4_OFFSET       (0x500+M32R_MFT_OFFSET)
+#define M32R_MFT4MOD_PORTL     (0x00+M32R_MFT4_OFFSET)  /* MFT4 mode */
+#define M32R_MFT4BOS_PORTL     (0x04+M32R_MFT4_OFFSET)  /* MFT4 b-port output status */
+#define M32R_MFT4CUT_PORTL     (0x08+M32R_MFT4_OFFSET)  /* MFT4 count */
+#define M32R_MFT4RLD_PORTL     (0x0C+M32R_MFT4_OFFSET)  /* MFT4 reload */
+#define M32R_MFT4CMPRLD_PORTL  (0x10+M32R_MFT4_OFFSET)  /* MFT4 compare reload */
+
+#define M32R_MFT5_OFFSET       (0x600+M32R_MFT_OFFSET)
+#define M32R_MFT5MOD_PORTL     (0x00+M32R_MFT5_OFFSET)  /* MFT4 mode */
+#define M32R_MFT5BOS_PORTL     (0x04+M32R_MFT5_OFFSET)  /* MFT4 b-port output status */
+#define M32R_MFT5CUT_PORTL     (0x08+M32R_MFT5_OFFSET)  /* MFT4 count */
+#define M32R_MFT5RLD_PORTL     (0x0C+M32R_MFT5_OFFSET)  /* MFT4 reload */
+#define M32R_MFT5CMPRLD_PORTL  (0x10+M32R_MFT5_OFFSET)  /* MFT4 compare reload */
+
+#ifdef CONFIG_CHIP_M32700
+#define M32R_MFTCR_MFT0MSK  (1UL<<31)  /* b0 */
+#define M32R_MFTCR_MFT1MSK  (1UL<<30)  /* b1 */
+#define M32R_MFTCR_MFT2MSK  (1UL<<29)  /* b2 */
+#define M32R_MFTCR_MFT3MSK  (1UL<<28)  /* b3 */
+#define M32R_MFTCR_MFT4MSK  (1UL<<27)  /* b4 */
+#define M32R_MFTCR_MFT5MSK  (1UL<<26)  /* b5 */
+#define M32R_MFTCR_MFT0EN   (1UL<<23)  /* b8 */
+#define M32R_MFTCR_MFT1EN   (1UL<<22)  /* b9 */
+#define M32R_MFTCR_MFT2EN   (1UL<<21)  /* b10 */
+#define M32R_MFTCR_MFT3EN   (1UL<<20)  /* b11 */
+#define M32R_MFTCR_MFT4EN   (1UL<<19)  /* b12 */
+#define M32R_MFTCR_MFT5EN   (1UL<<18)  /* b13 */
+#else  /* not CONFIG_CHIP_M32700 */
+#define M32R_MFTCR_MFT0MSK  (1UL<<15)  /* b16 */
+#define M32R_MFTCR_MFT1MSK  (1UL<<14)  /* b17 */
+#define M32R_MFTCR_MFT2MSK  (1UL<<13)  /* b18 */
+#define M32R_MFTCR_MFT3MSK  (1UL<<12)  /* b19 */
+#define M32R_MFTCR_MFT4MSK  (1UL<<11)  /* b20 */
+#define M32R_MFTCR_MFT5MSK  (1UL<<10)  /* b21 */
+#define M32R_MFTCR_MFT0EN   (1UL<<7)   /* b24 */
+#define M32R_MFTCR_MFT1EN   (1UL<<6)   /* b25 */
+#define M32R_MFTCR_MFT2EN   (1UL<<5)   /* b26 */
+#define M32R_MFTCR_MFT3EN   (1UL<<4)   /* b27 */
+#define M32R_MFTCR_MFT4EN   (1UL<<3)   /* b28 */
+#define M32R_MFTCR_MFT5EN   (1UL<<2)   /* b29 */
+#endif /* not CONFIG_CHIP_M32700 */
+
+#define M32R_MFTMOD_CC_MASK    (1UL<<15)  /* b16 */
+#define M32R_MFTMOD_TCCR       (1UL<<13)  /* b18 */
+#define M32R_MFTMOD_GTSEL000   (0UL<<8)   /* b21-23 : 000 */
+#define M32R_MFTMOD_GTSEL001   (1UL<<8)   /* b21-23 : 001 */
+#define M32R_MFTMOD_GTSEL010   (2UL<<8)   /* b21-23 : 010 */
+#define M32R_MFTMOD_GTSEL011   (3UL<<8)   /* b21-23 : 011 */
+#define M32R_MFTMOD_GTSEL110   (6UL<<8)   /* b21-23 : 110 */
+#define M32R_MFTMOD_GTSEL111   (7UL<<8)   /* b21-23 : 111 */
+#define M32R_MFTMOD_CMSEL      (1UL<<3)   /* b28 */
+#define M32R_MFTMOD_CSSEL000   (0UL<<0)   /* b29-b31 : 000 */
+#define M32R_MFTMOD_CSSEL001   (1UL<<0)   /* b29-b31 : 001 */
+#define M32R_MFTMOD_CSSEL010   (2UL<<0)   /* b29-b31 : 010 */
+#define M32R_MFTMOD_CSSEL011   (3UL<<0)   /* b29-b31 : 011 */
+#define M32R_MFTMOD_CSSEL100   (4UL<<0)   /* b29-b31 : 100 */
+#define M32R_MFTMOD_CSSEL110   (6UL<<0)   /* b29-b31 : 110 */
+
+/*
+ * Serial I/O registers.
+ */
+#define M32R_SIO_OFFSET  (0x000FD000+M32R_SFR_OFFSET)
+
+#define M32R_SIO0_CR_PORTL     (0x000+M32R_SIO_OFFSET)
+#define M32R_SIO0_MOD0_PORTL   (0x004+M32R_SIO_OFFSET)
+#define M32R_SIO0_MOD1_PORTL   (0x008+M32R_SIO_OFFSET)
+#define M32R_SIO0_STS_PORTL    (0x00C+M32R_SIO_OFFSET)
+#define M32R_SIO0_TRCR_PORTL   (0x010+M32R_SIO_OFFSET)
+#define M32R_SIO0_BAUR_PORTL   (0x014+M32R_SIO_OFFSET)
+#define M32R_SIO0_RBAUR_PORTL  (0x018+M32R_SIO_OFFSET)
+#define M32R_SIO0_TXB_PORTL    (0x01C+M32R_SIO_OFFSET)
+#define M32R_SIO0_RXB_PORTL    (0x020+M32R_SIO_OFFSET)
+
+/*
+ * Interrupt Control Unit registers.
+ */
+#define M32R_ICU_OFFSET       (0x000FF000+M32R_SFR_OFFSET)
+#define M32R_ICU_ISTS_PORTL   (0x004+M32R_ICU_OFFSET)
+#define M32R_ICU_IREQ0_PORTL  (0x008+M32R_ICU_OFFSET)
+#define M32R_ICU_IREQ1_PORTL  (0x00C+M32R_ICU_OFFSET)
+#define M32R_ICU_SBICR_PORTL  (0x018+M32R_ICU_OFFSET)
+#define M32R_ICU_IMASK_PORTL  (0x01C+M32R_ICU_OFFSET)
+#define M32R_ICU_CR1_PORTL    (0x200+M32R_ICU_OFFSET)  /* INT0 */
+#define M32R_ICU_CR2_PORTL    (0x204+M32R_ICU_OFFSET)  /* INT1 */
+#define M32R_ICU_CR3_PORTL    (0x208+M32R_ICU_OFFSET)  /* INT2 */
+#define M32R_ICU_CR4_PORTL    (0x20C+M32R_ICU_OFFSET)  /* INT3 */
+#define M32R_ICU_CR5_PORTL    (0x210+M32R_ICU_OFFSET)  /* INT4 */
+#define M32R_ICU_CR6_PORTL    (0x214+M32R_ICU_OFFSET)  /* INT5 */
+#define M32R_ICU_CR7_PORTL    (0x218+M32R_ICU_OFFSET)  /* INT6 */
+#define M32R_ICU_CR16_PORTL   (0x23C+M32R_ICU_OFFSET)  /* MFT0 */
+#define M32R_ICU_CR17_PORTL   (0x240+M32R_ICU_OFFSET)  /* MFT1 */
+#define M32R_ICU_CR18_PORTL   (0x244+M32R_ICU_OFFSET)  /* MFT2 */
+#define M32R_ICU_CR19_PORTL   (0x248+M32R_ICU_OFFSET)  /* MFT3 */
+#define M32R_ICU_CR20_PORTL   (0x24C+M32R_ICU_OFFSET)  /* MFT4 */
+#define M32R_ICU_CR21_PORTL   (0x250+M32R_ICU_OFFSET)  /* MFT5 */
+#define M32R_ICU_CR32_PORTL   (0x27C+M32R_ICU_OFFSET)  /* DMA0 */
+#define M32R_ICU_CR33_PORTL   (0x280+M32R_ICU_OFFSET)  /* DMA1 */
+#define M32R_ICU_CR48_PORTL   (0x2BC+M32R_ICU_OFFSET)  /* SIO0 */
+#define M32R_ICU_CR49_PORTL   (0x2C0+M32R_ICU_OFFSET)  /* SIO0 */
+#define M32R_ICU_CR50_PORTL   (0x2C4+M32R_ICU_OFFSET)  /* SIO1 */
+#define M32R_ICU_CR51_PORTL   (0x2C8+M32R_ICU_OFFSET)  /* SIO1 */
+#define M32R_ICU_CR52_PORTL   (0x2CC+M32R_ICU_OFFSET)  /* SIO2 */
+#define M32R_ICU_CR53_PORTL   (0x2D0+M32R_ICU_OFFSET)  /* SIO2 */
+#define M32R_ICU_CR54_PORTL   (0x2D4+M32R_ICU_OFFSET)  /* SIO3 */
+#define M32R_ICU_CR55_PORTL   (0x2D8+M32R_ICU_OFFSET)  /* SIO3 */
+#define M32R_ICU_CR56_PORTL   (0x2DC+M32R_ICU_OFFSET)  /* SIO4 */
+#define M32R_ICU_CR57_PORTL   (0x2E0+M32R_ICU_OFFSET)  /* SIO4 */
+
+#ifdef CONFIG_SMP
+#define M32R_ICU_IPICR0_PORTL (0x2dc+M32R_ICU_OFFSET)  /* IPI0 */
+#define M32R_ICU_IPICR1_PORTL (0x2e0+M32R_ICU_OFFSET)  /* IPI1 */
+#define M32R_ICU_IPICR2_PORTL (0x2e4+M32R_ICU_OFFSET)  /* IPI2 */
+#define M32R_ICU_IPICR3_PORTL (0x2e8+M32R_ICU_OFFSET)  /* IPI3 */
+#define M32R_ICU_IPICR4_PORTL (0x2ec+M32R_ICU_OFFSET)  /* IPI4 */
+#define M32R_ICU_IPICR5_PORTL (0x2f0+M32R_ICU_OFFSET)  /* IPI5 */
+#define M32R_ICU_IPICR6_PORTL (0x2f4+M32R_ICU_OFFSET)  /* IPI6 */
+#define M32R_ICU_IPICR7_PORTL (0x2f8+M32R_ICU_OFFSET)  /* IPI7 */
+#endif /* CONFIG_SMP */
+
+#define M32R_ICUIMASK_IMSK0  (0UL<<16)  /* b13-b15: Disable interrupt */
+#define M32R_ICUIMASK_IMSK1  (1UL<<16)  /* b13-b15: Enable level 0 interrupt */
+#define M32R_ICUIMASK_IMSK2  (2UL<<16)  /* b13-b15: Enable level 0,1 interrupt */
+#define M32R_ICUIMASK_IMSK3  (3UL<<16)  /* b13-b15: Enable level 0-2 interrupt */
+#define M32R_ICUIMASK_IMSK4  (4UL<<16)  /* b13-b15: Enable level 0-3 interrupt */
+#define M32R_ICUIMASK_IMSK5  (5UL<<16)  /* b13-b15: Enable level 0-4 interrupt */
+#define M32R_ICUIMASK_IMSK6  (6UL<<16)  /* b13-b15: Enable level 0-5 interrupt */
+#define M32R_ICUIMASK_IMSK7  (7UL<<16)  /* b13-b15: Enable level 0-6 interrupt */
+
+#define M32R_ICUCR_IEN      (1UL<<12)  /* b19: Interrupt enable */
+#define M32R_ICUCR_IRQ      (1UL<<8)   /* b23: Interrupt request */
+#define M32R_ICUCR_ISMOD00  (0UL<<4)   /* b26-b27: Interrupt sense mode Edge HtoL */
+#define M32R_ICUCR_ISMOD01  (1UL<<4)   /* b26-b27: Interrupt sense mode Level L */
+#define M32R_ICUCR_ISMOD10  (2UL<<4)   /* b26-b27: Interrupt sense mode Edge LtoH*/
+#define M32R_ICUCR_ISMOD11  (3UL<<4)   /* b26-b27: Interrupt sense mode Level H */
+#define M32R_ICUCR_ILEVEL0  (0UL<<0)   /* b29-b31: Interrupt priority level 0 */
+#define M32R_ICUCR_ILEVEL1  (1UL<<0)   /* b29-b31: Interrupt priority level 1 */
+#define M32R_ICUCR_ILEVEL2  (2UL<<0)   /* b29-b31: Interrupt priority level 2 */
+#define M32R_ICUCR_ILEVEL3  (3UL<<0)   /* b29-b31: Interrupt priority level 3 */
+#define M32R_ICUCR_ILEVEL4  (4UL<<0)   /* b29-b31: Interrupt priority level 4 */
+#define M32R_ICUCR_ILEVEL5  (5UL<<0)   /* b29-b31: Interrupt priority level 5 */
+#define M32R_ICUCR_ILEVEL6  (6UL<<0)   /* b29-b31: Interrupt priority level 6 */
+#define M32R_ICUCR_ILEVEL7  (7UL<<0)   /* b29-b31: Disable interrupt */
+
+#define  M32R_IRQ_INT0    (1)   /* INT0 */
+#define  M32R_IRQ_INT1    (2)   /* INT1 */
+#define  M32R_IRQ_INT2    (3)   /* INT2 */
+#define  M32R_IRQ_INT3    (4)   /* INT3 */
+#define  M32R_IRQ_INT4    (5)   /* INT4 */
+#define  M32R_IRQ_INT5    (6)   /* INT5 */
+#define  M32R_IRQ_INT6    (7)   /* INT6 */
+#define  M32R_IRQ_MFT0    (16)  /* MFT0 */
+#define  M32R_IRQ_MFT1    (17)  /* MFT1 */
+#define  M32R_IRQ_MFT2    (18)  /* MFT2 */
+#define  M32R_IRQ_MFT3    (19)  /* MFT3 */
+#define  M32R_IRQ_MFT4    (20)  /* MFT4 */
+#define  M32R_IRQ_MFT5    (21)  /* MFT5 */
+#define  M32R_IRQ_DMA0    (32)  /* DMA0 */
+#define  M32R_IRQ_DMA1    (33)  /* DMA1 */
+#define  M32R_IRQ_SIO0_R  (48)  /* SIO0 send    */
+#define  M32R_IRQ_SIO0_S  (49)  /* SIO0 receive */
+#define  M32R_IRQ_SIO1_R  (50)  /* SIO1 send    */
+#define  M32R_IRQ_SIO1_S  (51)  /* SIO1 receive */
+#define  M32R_IRQ_SIO2_R  (52)  /* SIO2 send    */
+#define  M32R_IRQ_SIO2_S  (53)  /* SIO2 receive */
+#define  M32R_IRQ_SIO3_R  (54)  /* SIO3 send    */
+#define  M32R_IRQ_SIO3_S  (55)  /* SIO3 receive */
+#define  M32R_IRQ_SIO4_R  (56)  /* SIO4 send    */
+#define  M32R_IRQ_SIO4_S  (57)  /* SIO4 receive */
+
+#ifdef CONFIG_SMP
+#define M32R_IRQ_IPI0 (56)
+#define M32R_IRQ_IPI1 (57)
+#define M32R_IRQ_IPI2 (58)
+#define M32R_IRQ_IPI3 (59)
+#define M32R_IRQ_IPI4 (60)
+#define M32R_IRQ_IPI5 (61)
+#define M32R_IRQ_IPI6 (62)
+#define M32R_IRQ_IPI7 (63)
+#define M32R_CPUID_PORTL (0xffffffe0)
+
+#define M32R_FPGA_TOP (0x000F0000+M32R_SFR_OFFSET)
+
+#define M32R_FPGA_NUM_OF_CPUS_PORTL (0x00+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME0_PORTL   (0x10+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME1_PORTL   (0x14+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME2_PORTL   (0x18+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME3_PORTL   (0x1c+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID0_PORTL   (0x20+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID1_PORTL   (0x24+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID2_PORTL   (0x28+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID3_PORTL   (0x2c+M32R_FPGA_TOP)
+#define M32R_FPGA_VERSION0_PORTL    (0x30+M32R_FPGA_TOP)
+#define M32R_FPGA_VERSION1_PORTL    (0x34+M32R_FPGA_TOP)
+
+#ifndef __ASSEMBLY__
+/* For NETDEV WATCHDOG */
+typedef struct {
+       unsigned long icucr;    /* ICU Control Register */
+} icu_data_t;
+
+extern icu_data_t icu_data[];
+#endif
+
+#endif /* CONFIG_SMP */
+
+#endif /* _M32102_H_ */
diff --git a/include/asm-m32r/m32102peri.h b/include/asm-m32r/m32102peri.h
new file mode 100644 (file)
index 0000000..3c12955
--- /dev/null
@@ -0,0 +1,468 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000,2001 by Hiroyuki Kondo
+ */
+
+#ifndef __ASSEMBLY__
+
+typedef        void    V;
+typedef        char    B;
+typedef        short   S;
+typedef        int             W;
+typedef        long    L;
+typedef        float   F;
+typedef        double  D;
+typedef        unsigned char   UB;
+typedef        unsigned short  US;
+typedef        unsigned int    UW;
+typedef        unsigned long   UL;
+typedef        const unsigned int      CUW;
+
+/*********************************
+
+M32102 ICU
+
+*********************************/
+#define                ICUISTS         (UW *)0xa0EFF004
+#define                ICUIREQ0        (UW *)0xa0EFF008
+#define                ICUIREQ1        (UW *)0xa0EFF00C
+
+#define                ICUSBICR        (UW *)0xa0EFF018
+#define                ICUIMASK        (UW *)0xa0EFF01C
+
+#define                ICUCR1          (UW *)0xa0EFF200        /* INT0 */
+#define                ICUCR2          (UW *)0xa0EFF204        /* INT1 */
+#define                ICUCR3          (UW *)0xa0EFF208        /* INT2 */
+#define                ICUCR4          (UW *)0xa0EFF20C        /* INT3 */
+#define                ICUCR5          (UW *)0xa0EFF210        /* INT4 */
+#define                ICUCR6          (UW *)0xa0EFF214        /* INT5 */
+#define                ICUCR7          (UW *)0xa0EFF218        /* INT6 */
+
+#define                ICUCR16         (UW *)0xa0EFF23C        /* MFT0 */
+#define                ICUCR17         (UW *)0xa0EFF240        /* MFT1 */
+#define                ICUCR18         (UW *)0xa0EFF244        /* MFT2 */
+#define                ICUCR19         (UW *)0xa0EFF248        /* MFT3 */
+#define                ICUCR20         (UW *)0xa0EFF24C        /* MFT4 */
+#define                ICUCR21         (UW *)0xa0EFF250        /* MFT5 */
+
+#define                ICUCR32         (UW *)0xa0EFF27C        /* DMA0 */
+#define                ICUCR33         (UW *)0xa0EFF280        /* DMA1 */
+
+#define                ICUCR48         (UW *)0xa0EFF2BC        /* SIO0R */
+#define                ICUCR49         (UW *)0xa0EFF2C0        /* SIO0S */
+#define                ICUCR50         (UW *)0xa0EFF2C4        /* SIO1R */
+#define                ICUCR51         (UW *)0xa0EFF2C8        /* SIO1S */
+#define                ICUCR52         (UW *)0xa0EFF2CC        /* SIO2R */
+#define                ICUCR53         (UW *)0xa0EFF2D0        /* SIO2S */
+#define                ICUCR54         (UW *)0xa0EFF2D4        /* SIO3R */
+#define                ICUCR55         (UW *)0xa0EFF2D8        /* SIO3S */
+#define                ICUCR56         (UW *)0xa0EFF2DC        /* SIO4R */
+#define                ICUCR57         (UW *)0xa0EFF2E0        /* SIO4S */
+
+/*********************************
+
+M32102 MFT
+
+*********************************/
+#define                MFTCR           (US *)0xa0EFC002
+#define                MFTRPR          (UB *)0xa0EFC006
+
+#define                MFT0MOD         (US *)0xa0EFC102
+#define                MFT0BOS         (US *)0xa0EFC106
+#define                MFT0CUT         (US *)0xa0EFC10A
+#define                MFT0RLD         (US *)0xa0EFC10E
+#define                MFT0CRLD        (US *)0xa0EFC112
+
+#define                MFT1MOD         (US *)0xa0EFC202
+#define                MFT1BOS         (US *)0xa0EFC206
+#define                MFT1CUT         (US *)0xa0EFC20A
+#define                MFT1RLD         (US *)0xa0EFC20E
+#define                MFT1CRLD        (US *)0xa0EFC212
+
+#define                MFT2MOD         (US *)0xa0EFC302
+#define                MFT2BOS         (US *)0xa0EFC306
+#define                MFT2CUT         (US *)0xa0EFC30A
+#define                MFT2RLD         (US *)0xa0EFC30E
+#define                MFT2CRLD        (US *)0xa0EFC312
+
+#define                MFT3MOD         (US *)0xa0EFC402
+#define                MFT3CUT         (US *)0xa0EFC40A
+#define                MFT3RLD         (US *)0xa0EFC40E
+#define                MFT3CRLD        (US *)0xa0EFC412
+
+#define                MFT4MOD         (US *)0xa0EFC502
+#define                MFT4CUT         (US *)0xa0EFC50A
+#define                MFT4RLD         (US *)0xa0EFC50E
+#define                MFT4CRLD        (US *)0xa0EFC512
+
+#define                MFT5MOD         (US *)0xa0EFC602
+#define                MFT5CUT         (US *)0xa0EFC60A
+#define                MFT5RLD         (US *)0xa0EFC60E
+#define                MFT5CRLD        (US *)0xa0EFC612
+
+/*********************************
+
+M32102 SIO
+
+*********************************/
+
+#define SIO0CR     (volatile int *)0xa0efd000
+#define SIO0MOD0   (volatile int *)0xa0efd004
+#define SIO0MOD1   (volatile int *)0xa0efd008
+#define SIO0STS    (volatile int *)0xa0efd00c
+#define SIO0IMASK  (volatile int *)0xa0efd010
+#define SIO0BAUR   (volatile int *)0xa0efd014
+#define SIO0RBAUR  (volatile int *)0xa0efd018
+#define SIO0TXB    (volatile int *)0xa0efd01c
+#define SIO0RXB    (volatile int *)0xa0efd020
+
+#define SIO1CR     (volatile int *)0xa0efd100
+#define SIO1MOD0   (volatile int *)0xa0efd104
+#define SIO1MOD1   (volatile int *)0xa0efd108
+#define SIO1STS    (volatile int *)0xa0efd10c
+#define SIO1IMASK  (volatile int *)0xa0efd110
+#define SIO1BAUR   (volatile int *)0xa0efd114
+#define SIO1RBAUR  (volatile int *)0xa0efd118
+#define SIO1TXB    (volatile int *)0xa0efd11c
+#define SIO1RXB    (volatile int *)0xa0efd120
+/*********************************
+
+M32102 PORT
+
+*********************************/
+#define                PIEN            (UB *)0xa0EF1003        /* input enable */
+
+#define                P0DATA          (UB *)0xa0EF1020        /* data */
+#define                P1DATA          (UB *)0xa0EF1021
+#define                P2DATA          (UB *)0xa0EF1022
+#define                P3DATA          (UB *)0xa0EF1023
+#define                P4DATA          (UB *)0xa0EF1024
+#define                P5DATA          (UB *)0xa0EF1025
+#define                P6DATA          (UB *)0xa0EF1026
+#define                P7DATA          (UB *)0xa0EF1027
+
+#define                P0DIR           (UB *)0xa0EF1040        /* direction */
+#define                P1DIR           (UB *)0xa0EF1041
+#define                P2DIR           (UB *)0xa0EF1042
+#define                P3DIR           (UB *)0xa0EF1043
+#define                P4DIR           (UB *)0xa0EF1044
+#define                P5DIR           (UB *)0xa0EF1045
+#define                P6DIR           (UB *)0xa0EF1046
+#define                P7DIR           (UB *)0xa0EF1047
+
+#define                P0MOD           (US *)0xa0EF1060        /* mode control */
+#define                P1MOD           (US *)0xa0EF1062
+#define                P2MOD           (US *)0xa0EF1064
+#define                P3MOD           (US *)0xa0EF1066
+#define                P4MOD           (US *)0xa0EF1068
+#define                P5MOD           (US *)0xa0EF106A
+#define                P6MOD           (US *)0xa0EF106C
+#define                P7MOD           (US *)0xa0EF106E
+
+#define                P0ODCR          (UB *)0xa0EF1080        /* open-drain control */
+#define                P1ODCR          (UB *)0xa0EF1081
+#define                P2ODCR          (UB *)0xa0EF1082
+#define                P3ODCR          (UB *)0xa0EF1083
+#define                P4ODCR          (UB *)0xa0EF1084
+#define                P5ODCR          (UB *)0xa0EF1085
+#define                P6ODCR          (UB *)0xa0EF1086
+#define                P7ODCR          (UB *)0xa0EF1087
+
+/*********************************
+
+M32102 Cache
+
+********************************/
+
+#define                MCCR    (US *)0xFFFFFFFE
+
+
+#else  /* __ASSEMBLY__ */
+
+;;
+;; PIO     0x80ef1000
+;;
+
+#define PIEN          0xa0ef1000
+
+#define P0DATA        0xa0ef1020
+#define P1DATA        0xa0ef1021
+#define P2DATA        0xa0ef1022
+#define P3DATA        0xa0ef1023
+#define P4DATA        0xa0ef1024
+#define P5DATA        0xa0ef1025
+#define P6DATA        0xa0ef1026
+#define P7DATA        0xa0ef1027
+
+#define P0DIR         0xa0ef1040
+#define P1DIR         0xa0ef1041
+#define P2DIR         0xa0ef1042
+#define P3DIR         0xa0ef1043
+#define P4DIR         0xa0ef1044
+#define P5DIR         0xa0ef1045
+#define P6DIR         0xa0ef1046
+#define P7DIR         0xa0ef1047
+
+#define P0MOD         0xa0ef1060
+#define P1MOD         0xa0ef1062
+#define P2MOD         0xa0ef1064
+#define P3MOD         0xa0ef1066
+#define P4MOD         0xa0ef1068
+#define P5MOD         0xa0ef106a
+#define P6MOD         0xa0ef106c
+#define P7MOD         0xa0ef106e
+;
+#define P0ODCR        0xa0ef1080
+#define P1ODCR        0xa0ef1081
+#define P2ODCR        0xa0ef1082
+#define P3ODCR        0xa0ef1083
+#define P4ODCR        0xa0ef1084
+#define P5ODCR        0xa0ef1085
+#define P6ODCR        0xa0ef1086
+#define P7ODCR        0xa0ef1087
+
+;;
+;; WDT     0xa0ef2000
+;;
+
+#define WDTCR         0xa0ef2000
+
+
+;;
+;; CLK     0xa0ef4000
+;;
+
+#define CPUCLKCR      0xa0ef4000
+#define CLKMOD        0xa0ef4004
+#define PLLCR         0xa0ef4008
+
+
+;;
+;; BSEL    0xa0ef5000
+;;
+
+#define BSEL0CR       0xa0ef5000
+#define BSEL1CR       0xa0ef5004
+#define BSEL2CR       0xa0ef5008
+#define BSEL3CR       0xa0ef500c
+#define BSEL4CR       0xa0ef5010
+#define BSEL5CR       0xa0ef5014
+
+
+;;
+;; SDRAMC  0xa0ef6000
+;;
+
+#define SDRF0         0xa0ef6000
+#define SDRF1         0xa0ef6004
+#define SDIR0         0xa0ef6008
+#define SDIR1         0xa0ef600c
+#define SDBR          0xa0ef6010
+
+;; CH0
+#define SD0ADR        0xa0ef6020
+#define SD0SZ         0xa0ef6022
+#define SD0ER         0xa0ef6024
+#define SD0TR         0xa0ef6028
+#define SD0MOD        0xa0ef602c
+
+;; CH1
+#define SD1ADR        0xa0ef6040
+#define SD1SZ         0xa0ef6042
+#define SD1ER         0xa0ef6044
+#define SD1TR         0xa0ef6048
+#define SD1MOD        0xa0ef604c
+
+
+;;
+;; DMAC    0xa0ef8000
+;;
+
+#define DMAEN         0xa0ef8000
+#define DMAISTS       0xa0ef8004
+#define DMAEDET       0xa0ef8008
+#define DMAASTS       0xa0ef800c
+
+;; CH0
+#define DMA0CR0       0xa0ef8100
+#define DMA0CR1       0xa0ef8104
+#define DMA0CSA       0xa0ef8108
+#define DMA0RSA       0xa0ef810c
+#define DMA0CDA       0xa0ef8110
+#define DMA0RDA       0xa0ef8114
+#define DMA0CBCUT     0xa0ef8118
+#define DMA0RBCUT     0xa0ef811c
+
+;; CH1
+#define DMA1CR0       0xa0ef8200
+#define DMA1CR1       0xa0ef8204
+#define DMA1CSA       0xa0ef8208
+#define DMA1RSA       0xa0ef820c
+#define DMA1CDA       0xa0ef8210
+#define DMA1RDA       0xa0ef8214
+#define DMA1CBCUT     0xa0ef8218
+#define DMA1RBCUT     0xa0ef821c
+
+
+;;
+;; MFT     0xa0efc000
+;;
+
+#define MFTCR        0xa0efc000
+#define MFTRPR       0xa0efc004
+
+;; CH0
+#define MFT0MOD      0xa0efc100
+#define MFT0BOS      0xa0efc104
+#define MFT0CUT      0xa0efc108
+#define MFT0RLD      0xa0efc10c
+#define MFT0CMPRLD   0xa0efc110
+
+;; CH1
+#define MFT1MOD      0xa0efc200
+#define MFT1BOS      0xa0efc204
+#define MFT1CUT      0xa0efc208
+#define MFT1RLD      0xa0efc20c
+#define MFT1CMPRLD   0xa0efc210
+
+;; CH2
+#define MFT2MOD      0xa0efc300
+#define MFT2BOS      0xa0efc304
+#define MFT2CUT      0xa0efc308
+#define MFT2RLD      0xa0efc30c
+#define MFT2CMPRLD   0xa0efc310
+
+;; CH3
+#define MFT3MOD      0xa0efc400
+#define MFT3BOS      0xa0efc404
+#define MFT3CUT      0xa0efc408
+#define MFT3RLD      0xa0efc40c
+#define MFT3CMPRLD   0xa0efc410
+
+;; CH4
+#define MFT4MOD      0xa0efc500
+#define MFT4BOS      0xa0efc504
+#define MFT4CUT      0xa0efc508
+#define MFT4RLD      0xa0efc50c
+#define MFT4CMPRLD   0xa0efc510
+
+;; CH5
+#define MFT5MOD      0xa0efc600
+#define MFT5BOS      0xa0efc604
+#define MFT5CUT      0xa0efc608
+#define MFT5RLD      0xa0efc60c
+#define MFT5CMPRLD   0xa0efc610
+
+
+;;
+;; SIO     0xa0efd000
+;;
+
+;; CH0
+#define SIO0CR        0xa0efd000
+#define SIO0MOD0      0xa0efd004
+#define SIO0MOD1      0xa0efd008
+#define SIO0STS       0xa0efd00c
+#define SIO0IMASK     0xa0efd010
+#define SIO0BAUR      0xa0efd014
+#define SIO0RBAUR     0xa0efd018
+#define SIO0TXB       0xa0efd01c
+#define SIO0RXB       0xa0efd020
+
+;; CH1
+#define SIO1CR        0xa0efd100
+#define SIO1MOD0      0xa0efd104
+#define SIO1MOD1      0xa0efd108
+#define SIO1STS       0xa0efd10c
+#define SIO1IMASK     0xa0efd110
+#define SIO1BAUR      0xa0efd114
+#define SIO1RBAUR     0xa0efd118
+#define SIO1TXB       0xa0efd11c
+#define SIO1RXB       0xa0efd120
+
+;; CH2
+#define SIO2CR        0xa0efd200
+#define SIO2MOD0      0xa0efd204
+#define SIO2MOD1      0xa0efd208
+#define SIO2STS       0xa0efd20c
+#define SIO2IMASK     0xa0efd210
+#define SIO2BAUR      0xa0efd214
+#define SIO2RBAUR     0xa0efd218
+#define SIO2TXB       0xa0efd21c
+#define SIO2RXB       0xa0efd220
+
+;; CH3
+#define SIO3CR        0xa0efd300
+#define SIO3MOD0      0xa0efd304
+#define SIO3MOD1      0xa0efd308
+#define SIO3STS       0xa0efd30c
+#define SIO3IMASK     0xa0efd310
+#define SIO3BAUR      0xa0efd314
+#define SIO3RBAUR     0xa0efd318
+#define SIO3TXB       0xa0efd31c
+#define SIO3RXB       0xa0efd320
+
+;; CH4
+#define SIO4CR        0xa0efd400
+#define SIO4MOD0      0xa0efd404
+#define SIO4MOD1      0xa0efd408
+#define SIO4STS       0xa0efd40c
+#define SIO4IMASK     0xa0efd410
+#define SIO4BAUR      0xa0efd414
+#define SIO4RBAUR     0xa0efd418
+#define SIO4TXB       0xa0efd41c
+#define SIO4RXB       0xa0efd420
+
+
+;;
+;; ICU     0xa0eff000
+;;
+
+#define ICUISTS       0xa0eff004
+#define ICUIREQ0      0xa0eff008
+#define ICUIREQ1      0xa0eff00c
+
+#define ICUSBICR      0xa0eff018
+#define ICUIMASK      0xa0eff01c
+
+#define ICUCR1        0xa0eff200
+#define ICUCR2        0xa0eff204
+#define ICUCR3        0xa0eff208
+#define ICUCR4        0xa0eff20c
+#define ICUCR5        0xa0eff210
+#define ICUCR6        0xa0eff214
+#define ICUCR7        0xa0eff218
+
+#define ICUCR16       0xa0eff23c
+#define ICUCR17       0xa0eff240
+#define ICUCR18       0xa0eff244
+#define ICUCR19       0xa0eff248
+#define ICUCR20       0xa0eff24c
+#define ICUCR21       0xa0eff250
+
+#define ICUCR32       0xa0eff27c
+#define ICUCR33       0xa0eff280
+
+#define ICUCR48       0xa0eff2bc
+#define ICUCR49       0xa0eff2c0
+#define ICUCR50       0xa0eff2c4
+#define ICUCR51       0xa0eff2c8
+#define ICUCR52       0xa0eff2cc
+#define ICUCR53       0xa0eff2d0
+#define ICUCR54       0xa0eff2d4
+#define ICUCR55       0xa0eff2d8
+#define ICUCR56       0xa0eff2dc
+#define ICUCR57       0xa0eff2e0
+
+;;
+;; CACHE
+;;
+
+#define MCCR             0xfffffffc
+
+
+#endif  /* __ASSEMBLY__ */
diff --git a/include/asm-m32r/m32700ut/m32700ut_lan.h b/include/asm-m32r/m32700ut/m32700ut_lan.h
new file mode 100644 (file)
index 0000000..50545ec
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * include/asm/m32700ut_lan.h
+ *
+ * M32700UT-LAN board
+ *
+ * Copyright (c) 2002  Takeo Takahashi
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _M32700UT_M32700UT_LAN_H
+#define _M32700UT_M32700UT_LAN_H
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define M32700UT_LAN_BASE      (0x10000000 /* + NONCACHE_OFFSET */)
+#else
+#define M32700UT_LAN_BASE      (0x10000000 + NONCACHE_OFFSET)
+#endif /* __ASSEMBLY__ */
+
+/* ICU
+ *  ICUISTS:   status register
+ *  ICUIREQ0:  request register
+ *  ICUIREQ1:  request register
+ *  ICUCR3:    control register for CFIREQ# interrupt
+ *  ICUCR4:    control register for CFC Card insert interrupt
+ *  ICUCR5:    control register for CFC Card eject interrupt
+ *  ICUCR6:    control register for external interrupt
+ *  ICUCR11:   control register for MMC Card insert/eject interrupt
+ *  ICUCR13:   control register for SC error interrupt
+ *  ICUCR14:   control register for SC receive interrupt
+ *  ICUCR15:   control register for SC send interrupt
+ *  ICUCR16:   control register for SIO0 receive interrupt
+ *  ICUCR17:   control register for SIO0 send interrupt
+ */
+#define M32700UT_LAN_IRQ_LAN   (M32700UT_LAN_PLD_IRQ_BASE + 1) /* LAN */
+#define M32700UT_LAN_IRQ_I2C   (M32700UT_LAN_PLD_IRQ_BASE + 3) /* I2C */
+
+#define M32700UT_LAN_ICUISTS   __reg16(M32700UT_LAN_BASE + 0xc0002)
+#define M32700UT_LAN_ICUISTS_VECB_MASK (0xf000)
+#define M32700UT_LAN_VECB(x)   ((x) & M32700UT_LAN_ICUISTS_VECB_MASK)
+#define M32700UT_LAN_ICUISTS_ISN_MASK  (0x07c0)
+#define M32700UT_LAN_ICUISTS_ISN(x)    ((x) & M32700UT_LAN_ICUISTS_ISN_MASK)
+#define M32700UT_LAN_ICUIREQ0  __reg16(M32700UT_LAN_BASE + 0xc0004)
+#define M32700UT_LAN_ICUCR1    __reg16(M32700UT_LAN_BASE + 0xc0010)
+#define M32700UT_LAN_ICUCR3    __reg16(M32700UT_LAN_BASE + 0xc0014)
+
+/*
+ * AR register on PLD
+ */
+#define ARVCR0         __reg32(M32700UT_LAN_BASE + 0x40000)
+#define ARVCR0_VDS             0x00080000
+#define ARVCR0_RST             0x00010000
+#define ARVCR1         __reg32(M32700UT_LAN_BASE + 0x40004)
+#define ARVCR1_QVGA            0x02000000
+#define ARVCR1_NORMAL          0x01000000
+#define ARVCR1_HIEN            0x00010000
+#define ARVHCOUNT      __reg32(M32700UT_LAN_BASE + 0x40008)
+#define ARDATA         __reg32(M32700UT_LAN_BASE + 0x40010)
+#define ARINTSEL       __reg32(M32700UT_LAN_BASE + 0x40014)
+#define ARINTSEL_INT3          0x10000000      /* CPU INT3 */
+#define ARDATA32       __reg32(M32700UT_LAN_BASE + 0x04040010) // Block 5
+/*
+#define ARINTSEL_SEL2          0x00002000
+#define ARINTSEL_SEL3          0x00001000
+#define ARINTSEL_SEL6          0x00000200
+#define ARINTSEL_SEL7          0x00000100
+#define ARINTSEL_SEL9          0x00000040
+#define ARINTSEL_SEL10         0x00000020
+#define ARINTSEL_SEL11         0x00000010
+#define ARINTSEL_SEL12         0x00000008
+*/
+
+/*
+ * I2C register on PLD
+ */
+#define PLDI2CCR       __reg32(M32700UT_LAN_BASE + 0x40040)
+#define        PLDI2CCR_ES0            0x00000001      /* enable I2C interface */
+#define PLDI2CMOD      __reg32(M32700UT_LAN_BASE + 0x40044)
+#define PLDI2CMOD_ACKCLK       0x00000200
+#define PLDI2CMOD_DTWD         0x00000100
+#define PLDI2CMOD_10BT         0x00000004
+#define PLDI2CMOD_ATM_NORMAL   0x00000000
+#define PLDI2CMOD_ATM_AUTO     0x00000003
+#define PLDI2CACK      __reg32(M32700UT_LAN_BASE + 0x40048)
+#define PLDI2CACK_ACK          0x00000001
+#define PLDI2CFREQ     __reg32(M32700UT_LAN_BASE + 0x4004c)
+#define PLDI2CCND      __reg32(M32700UT_LAN_BASE + 0x40050)
+#define PLDI2CCND_START                0x00000001
+#define PLDI2CCND_STOP         0x00000002
+#define PLDI2CSTEN     __reg32(M32700UT_LAN_BASE + 0x40054)
+#define PLDI2CSTEN_STEN                0x00000001
+#define PLDI2CDATA     __reg32(M32700UT_LAN_BASE + 0x40060)
+#define PLDI2CSTS      __reg32(M32700UT_LAN_BASE + 0x40064)
+#define PLDI2CSTS_TRX          0x00000020
+#define PLDI2CSTS_BB           0x00000010
+#define PLDI2CSTS_NOACK                0x00000001      /* 0:ack, 1:noack */
+
+#endif /* _M32700UT_M32700UT_LAN_H */
diff --git a/include/asm-m32r/m32700ut/m32700ut_lcd.h b/include/asm-m32r/m32700ut/m32700ut_lcd.h
new file mode 100644 (file)
index 0000000..ede6c77
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * include/asm/m32700ut_lcd.h
+ *
+ * M32700UT-LCD board
+ *
+ * Copyright (c) 2002  Takeo Takahashi
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _M32700UT_M32700UT_LCD_H
+#define _M32700UT_M32700UT_LCD_H
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define M32700UT_LCD_BASE      (0x10000000 /* + NONCACHE_OFFSET */)
+#else
+#define M32700UT_LCD_BASE      (0x10000000 + NONCACHE_OFFSET)
+#endif /* __ASSEMBLY__ */
+
+/*
+ * ICU
+ */
+#define M32700UT_LCD_IRQ_BAT_INT       (M32700UT_LCD_PLD_IRQ_BASE + 1)
+#define M32700UT_LCD_IRQ_USB_INT1      (M32700UT_LCD_PLD_IRQ_BASE + 2)
+#define M32700UT_LCD_IRQ_AUDT0         (M32700UT_LCD_PLD_IRQ_BASE + 3)
+#define M32700UT_LCD_IRQ_AUDT2         (M32700UT_LCD_PLD_IRQ_BASE + 4)
+#define M32700UT_LCD_IRQ_BATSIO_RCV    (M32700UT_LCD_PLD_IRQ_BASE + 16)
+#define M32700UT_LCD_IRQ_BATSIO_SND    (M32700UT_LCD_PLD_IRQ_BASE + 17)
+#define M32700UT_LCD_IRQ_ASNDSIO_RCV   (M32700UT_LCD_PLD_IRQ_BASE + 18)
+#define M32700UT_LCD_IRQ_ASNDSIO_SND   (M32700UT_LCD_PLD_IRQ_BASE + 19)
+#define M32700UT_LCD_IRQ_ACNLSIO_SND   (M32700UT_LCD_PLD_IRQ_BASE + 21)
+
+#define M32700UT_LCD_ICUISTS   __reg16(M32700UT_LCD_BASE + 0x300002)
+#define M32700UT_LCD_ICUISTS_VECB_MASK (0xf000)
+#define M32700UT_LCD_VECB(x)   ((x) & M32700UT_LCD_ICUISTS_VECB_MASK)
+#define M32700UT_LCD_ICUISTS_ISN_MASK  (0x07c0)
+#define M32700UT_LCD_ICUISTS_ISN(x)    ((x) & M32700UT_LCD_ICUISTS_ISN_MASK)
+#define M32700UT_LCD_ICUIREQ0  __reg16(M32700UT_LCD_BASE + 0x300004)
+#define M32700UT_LCD_ICUIREQ1  __reg16(M32700UT_LCD_BASE + 0x300006)
+#define M32700UT_LCD_ICUCR1    __reg16(M32700UT_LCD_BASE + 0x300020)
+#define M32700UT_LCD_ICUCR2    __reg16(M32700UT_LCD_BASE + 0x300022)
+#define M32700UT_LCD_ICUCR3    __reg16(M32700UT_LCD_BASE + 0x300024)
+#define M32700UT_LCD_ICUCR4    __reg16(M32700UT_LCD_BASE + 0x300026)
+#define M32700UT_LCD_ICUCR16   __reg16(M32700UT_LCD_BASE + 0x300030)
+#define M32700UT_LCD_ICUCR17   __reg16(M32700UT_LCD_BASE + 0x300032)
+#define M32700UT_LCD_ICUCR18   __reg16(M32700UT_LCD_BASE + 0x300034)
+#define M32700UT_LCD_ICUCR19   __reg16(M32700UT_LCD_BASE + 0x300036)
+#define M32700UT_LCD_ICUCR21   __reg16(M32700UT_LCD_BASE + 0x30003a)
+
+#endif /* _M32700UT_M32700UT_LCD_H */
diff --git a/include/asm-m32r/m32700ut/m32700ut_pld.h b/include/asm-m32r/m32700ut/m32700ut_pld.h
new file mode 100644 (file)
index 0000000..f5e4794
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * include/asm/m32700ut/m32700ut_pld.h
+ *
+ * Definitions for Programable Logic Device(PLD) on M32700UT board.
+ *
+ * Copyright (c) 2002  Takeo Takahashi
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _M32700UT_M32700UT_PLD_H
+#define _M32700UT_M32700UT_PLD_H
+
+#include <linux/config.h>
+
+#if defined(CONFIG_PLAT_M32700UT_Alpha)
+#define PLD_PLAT_BASE          0x08c00000
+#elif defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV)
+#define PLD_PLAT_BASE          0x04c00000
+#else
+#error "no platform configuration"
+#endif
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define PLD_BASE               (PLD_PLAT_BASE /* + NONCACHE_OFFSET */)
+#define __reg8                 (volatile unsigned char *)
+#define __reg16                        (volatile unsigned short *)
+#define __reg32                        (volatile unsigned int *)
+#else
+#define PLD_BASE               (PLD_PLAT_BASE + NONCACHE_OFFSET)
+#define __reg8
+#define __reg16
+#define __reg32
+#endif /* __ASSEMBLY__ */
+
+/* CFC */
+#define        PLD_CFRSTCR             __reg16(PLD_BASE + 0x0000)
+#define PLD_CFSTS              __reg16(PLD_BASE + 0x0002)
+#define PLD_CFIMASK            __reg16(PLD_BASE + 0x0004)
+#define PLD_CFBUFCR            __reg16(PLD_BASE + 0x0006)
+#define PLD_CFVENCR            __reg16(PLD_BASE + 0x0008)
+#define PLD_CFCR0              __reg16(PLD_BASE + 0x000a)
+#define PLD_CFCR1              __reg16(PLD_BASE + 0x000c)
+#define PLD_IDERSTCR           __reg16(PLD_BASE + 0x0010)
+
+/* MMC */
+#define PLD_MMCCR              __reg16(PLD_BASE + 0x4000)
+#define PLD_MMCMOD             __reg16(PLD_BASE + 0x4002)
+#define PLD_MMCSTS             __reg16(PLD_BASE + 0x4006)
+#define PLD_MMCBAUR            __reg16(PLD_BASE + 0x400a)
+#define PLD_MMCCMDBCUT         __reg16(PLD_BASE + 0x400c)
+#define PLD_MMCCDTBCUT         __reg16(PLD_BASE + 0x400e)
+#define PLD_MMCDET             __reg16(PLD_BASE + 0x4010)
+#define PLD_MMCWP              __reg16(PLD_BASE + 0x4012)
+#define PLD_MMCWDATA           __reg16(PLD_BASE + 0x5000)
+#define PLD_MMCRDATA           __reg16(PLD_BASE + 0x6000)
+#define PLD_MMCCMDDATA         __reg16(PLD_BASE + 0x7000)
+#define PLD_MMCRSPDATA         __reg16(PLD_BASE + 0x7006)
+
+/* ICU
+ *  ICUISTS:   status register
+ *  ICUIREQ0:  request register
+ *  ICUIREQ1:  request register
+ *  ICUCR3:    control register for CFIREQ# interrupt
+ *  ICUCR4:    control register for CFC Card insert interrupt
+ *  ICUCR5:    control register for CFC Card eject interrupt
+ *  ICUCR6:    control register for external interrupt
+ *  ICUCR11:   control register for MMC Card insert/eject interrupt
+ *  ICUCR13:   control register for SC error interrupt
+ *  ICUCR14:   control register for SC receive interrupt
+ *  ICUCR15:   control register for SC send interrupt
+ *  ICUCR16:   control register for SIO0 receive interrupt
+ *  ICUCR17:   control register for SIO0 send interrupt
+ */
+#if !defined(CONFIG_PLAT_USRV)
+#define PLD_IRQ_INT0           (M32700UT_PLD_IRQ_BASE + 0)     /* None */
+#define PLD_IRQ_INT1           (M32700UT_PLD_IRQ_BASE + 1)     /* reserved */
+#define PLD_IRQ_INT2           (M32700UT_PLD_IRQ_BASE + 2)     /* reserved */
+#define PLD_IRQ_CFIREQ         (M32700UT_PLD_IRQ_BASE + 3)     /* CF IREQ */
+#define PLD_IRQ_CFC_INSERT     (M32700UT_PLD_IRQ_BASE + 4)     /* CF Insert */
+#define PLD_IRQ_CFC_EJECT      (M32700UT_PLD_IRQ_BASE + 5)     /* CF Eject */
+#define PLD_IRQ_EXINT          (M32700UT_PLD_IRQ_BASE + 6)     /* EXINT */
+#define PLD_IRQ_INT7           (M32700UT_PLD_IRQ_BASE + 7)     /* reserved */
+#define PLD_IRQ_INT8           (M32700UT_PLD_IRQ_BASE + 8)     /* reserved */
+#define PLD_IRQ_INT9           (M32700UT_PLD_IRQ_BASE + 9)     /* reserved */
+#define PLD_IRQ_INT10          (M32700UT_PLD_IRQ_BASE + 10)    /* reserved */
+#define PLD_IRQ_MMCCARD                (M32700UT_PLD_IRQ_BASE + 11)    /* MMC Insert/Eject */
+#define PLD_IRQ_INT12          (M32700UT_PLD_IRQ_BASE + 12)    /* reserved */
+#define PLD_IRQ_SC_ERROR       (M32700UT_PLD_IRQ_BASE + 13)    /* SC error */
+#define PLD_IRQ_SC_RCV         (M32700UT_PLD_IRQ_BASE + 14)    /* SC receive */
+#define PLD_IRQ_SC_SND         (M32700UT_PLD_IRQ_BASE + 15)    /* SC send */
+#define PLD_IRQ_SIO0_RCV       (M32700UT_PLD_IRQ_BASE + 16)    /* SIO receive */
+#define PLD_IRQ_SIO0_SND       (M32700UT_PLD_IRQ_BASE + 17)    /* SIO send */
+#define PLD_IRQ_INT18          (M32700UT_PLD_IRQ_BASE + 18)    /* reserved */
+#define PLD_IRQ_INT19          (M32700UT_PLD_IRQ_BASE + 19)    /* reserved */
+#define PLD_IRQ_INT20          (M32700UT_PLD_IRQ_BASE + 20)    /* reserved */
+#define PLD_IRQ_INT21          (M32700UT_PLD_IRQ_BASE + 21)    /* reserved */
+#define PLD_IRQ_INT22          (M32700UT_PLD_IRQ_BASE + 22)    /* reserved */
+#define PLD_IRQ_INT23          (M32700UT_PLD_IRQ_BASE + 23)    /* reserved */
+#define PLD_IRQ_INT24          (M32700UT_PLD_IRQ_BASE + 24)    /* reserved */
+#define PLD_IRQ_INT25          (M32700UT_PLD_IRQ_BASE + 25)    /* reserved */
+#define PLD_IRQ_INT26          (M32700UT_PLD_IRQ_BASE + 26)    /* reserved */
+#define PLD_IRQ_INT27          (M32700UT_PLD_IRQ_BASE + 27)    /* reserved */
+#define PLD_IRQ_INT28          (M32700UT_PLD_IRQ_BASE + 28)    /* reserved */
+#define PLD_IRQ_INT29          (M32700UT_PLD_IRQ_BASE + 29)    /* reserved */
+#define PLD_IRQ_INT30          (M32700UT_PLD_IRQ_BASE + 30)    /* reserved */
+#define PLD_IRQ_INT31          (M32700UT_PLD_IRQ_BASE + 31)    /* reserved */
+
+#else  /* CONFIG_PLAT_USRV */
+
+#define PLD_IRQ_INT0           (M32700UT_PLD_IRQ_BASE + 0)     /* None */
+#define PLD_IRQ_INT1           (M32700UT_PLD_IRQ_BASE + 1)     /* reserved */
+#define PLD_IRQ_INT2           (M32700UT_PLD_IRQ_BASE + 2)     /* reserved */
+#define PLD_IRQ_CF0            (M32700UT_PLD_IRQ_BASE + 3)     /* CF0# */
+#define PLD_IRQ_CF1            (M32700UT_PLD_IRQ_BASE + 4)     /* CF1# */
+#define PLD_IRQ_CF2            (M32700UT_PLD_IRQ_BASE + 5)     /* CF2# */
+#define PLD_IRQ_CF3            (M32700UT_PLD_IRQ_BASE + 6)     /* CF3# */
+#define PLD_IRQ_CF4            (M32700UT_PLD_IRQ_BASE + 7)     /* CF4# */
+#define PLD_IRQ_INT8           (M32700UT_PLD_IRQ_BASE + 8)     /* reserved */
+#define PLD_IRQ_INT9           (M32700UT_PLD_IRQ_BASE + 9)     /* reserved */
+#define PLD_IRQ_INT10          (M32700UT_PLD_IRQ_BASE + 10)    /* reserved */
+#define PLD_IRQ_INT11          (M32700UT_PLD_IRQ_BASE + 11)    /* reserved */
+#define PLD_IRQ_UART0          (M32700UT_PLD_IRQ_BASE + 12)    /* UARTIRQ0 */
+#define PLD_IRQ_UART1          (M32700UT_PLD_IRQ_BASE + 13)    /* UARTIRQ1 */
+#define PLD_IRQ_INT14          (M32700UT_PLD_IRQ_BASE + 14)    /* reserved */
+#define PLD_IRQ_INT15          (M32700UT_PLD_IRQ_BASE + 15)    /* reserved */
+#define PLD_IRQ_SNDINT         (M32700UT_PLD_IRQ_BASE + 16)    /* SNDINT# */
+#define PLD_IRQ_INT17          (M32700UT_PLD_IRQ_BASE + 17)    /* reserved */
+#define PLD_IRQ_INT18          (M32700UT_PLD_IRQ_BASE + 18)    /* reserved */
+#define PLD_IRQ_INT19          (M32700UT_PLD_IRQ_BASE + 19)    /* reserved */
+#define PLD_IRQ_INT20          (M32700UT_PLD_IRQ_BASE + 20)    /* reserved */
+#define PLD_IRQ_INT21          (M32700UT_PLD_IRQ_BASE + 21)    /* reserved */
+#define PLD_IRQ_INT22          (M32700UT_PLD_IRQ_BASE + 22)    /* reserved */
+#define PLD_IRQ_INT23          (M32700UT_PLD_IRQ_BASE + 23)    /* reserved */
+#define PLD_IRQ_INT24          (M32700UT_PLD_IRQ_BASE + 24)    /* reserved */
+#define PLD_IRQ_INT25          (M32700UT_PLD_IRQ_BASE + 25)    /* reserved */
+#define PLD_IRQ_INT26          (M32700UT_PLD_IRQ_BASE + 26)    /* reserved */
+#define PLD_IRQ_INT27          (M32700UT_PLD_IRQ_BASE + 27)    /* reserved */
+#define PLD_IRQ_INT28          (M32700UT_PLD_IRQ_BASE + 28)    /* reserved */
+#define PLD_IRQ_INT29          (M32700UT_PLD_IRQ_BASE + 29)    /* reserved */
+#define PLD_IRQ_INT30          (M32700UT_PLD_IRQ_BASE + 30)    /* reserved */
+
+#endif /* CONFIG_PLAT_USRV */
+
+#define PLD_ICUISTS            __reg16(PLD_BASE + 0x8002)
+#define PLD_ICUISTS_VECB_MASK  (0xf000)
+#define PLD_ICUISTS_VECB(x)    ((x) & PLD_ICUISTS_VECB_MASK)
+#define PLD_ICUISTS_ISN_MASK   (0x07c0)
+#define PLD_ICUISTS_ISN(x)     ((x) & PLD_ICUISTS_ISN_MASK)
+#define PLD_ICUIREQ0           __reg16(PLD_BASE + 0x8004)
+#define PLD_ICUIREQ1           __reg16(PLD_BASE + 0x8006)
+#define PLD_ICUCR1             __reg16(PLD_BASE + 0x8100)
+#define PLD_ICUCR2             __reg16(PLD_BASE + 0x8102)
+#define PLD_ICUCR3             __reg16(PLD_BASE + 0x8104)
+#define PLD_ICUCR4             __reg16(PLD_BASE + 0x8106)
+#define PLD_ICUCR5             __reg16(PLD_BASE + 0x8108)
+#define PLD_ICUCR6             __reg16(PLD_BASE + 0x810a)
+#define PLD_ICUCR7             __reg16(PLD_BASE + 0x810c)
+#define PLD_ICUCR8             __reg16(PLD_BASE + 0x810e)
+#define PLD_ICUCR9             __reg16(PLD_BASE + 0x8110)
+#define PLD_ICUCR10            __reg16(PLD_BASE + 0x8112)
+#define PLD_ICUCR11            __reg16(PLD_BASE + 0x8114)
+#define PLD_ICUCR12            __reg16(PLD_BASE + 0x8116)
+#define PLD_ICUCR13            __reg16(PLD_BASE + 0x8118)
+#define PLD_ICUCR14            __reg16(PLD_BASE + 0x811a)
+#define PLD_ICUCR15            __reg16(PLD_BASE + 0x811c)
+#define PLD_ICUCR16            __reg16(PLD_BASE + 0x811e)
+#define PLD_ICUCR17            __reg16(PLD_BASE + 0x8120)
+#define PLD_ICUCR_IEN          (0x1000)
+#define PLD_ICUCR_IREQ         (0x0100)
+#define PLD_ICUCR_ISMOD00      (0x0000)        /* Low edge */
+#define PLD_ICUCR_ISMOD01      (0x0010)        /* Low level */
+#define PLD_ICUCR_ISMOD02      (0x0020)        /* High edge */
+#define PLD_ICUCR_ISMOD03      (0x0030)        /* High level */
+#define PLD_ICUCR_ILEVEL0      (0x0000)
+#define PLD_ICUCR_ILEVEL1      (0x0001)
+#define PLD_ICUCR_ILEVEL2      (0x0002)
+#define PLD_ICUCR_ILEVEL3      (0x0003)
+#define PLD_ICUCR_ILEVEL4      (0x0004)
+#define PLD_ICUCR_ILEVEL5      (0x0005)
+#define PLD_ICUCR_ILEVEL6      (0x0006)
+#define PLD_ICUCR_ILEVEL7      (0x0007)
+
+/* Power Control of MMC and CF */
+#define PLD_CPCR               __reg16(PLD_BASE + 0x14000)
+#define PLD_CPCR_CF            0x0001
+#define PLD_CPCR_MMC           0x0002
+
+/* LED Control
+ *
+ * 1: DIP swich side
+ * 2: Reset switch side
+ */
+#define PLD_IOLEDCR            __reg16(PLD_BASE + 0x14002)
+#define PLD_IOLED_1_ON         0x001
+#define PLD_IOLED_1_OFF                0x000
+#define PLD_IOLED_2_ON         0x002
+#define PLD_IOLED_2_OFF                0x000
+
+/* DIP Switch
+ *  0: Write-protect of Flash Memory (0:protected, 1:non-protected)
+ *  1: -
+ *  2: -
+ *  3: -
+ */
+#define PLD_IOSWSTS            __reg16(PLD_BASE + 0x14004)
+#define        PLD_IOSWSTS_IOSW2       0x0200
+#define        PLD_IOSWSTS_IOSW1       0x0100
+#define        PLD_IOSWSTS_IOWP0       0x0001
+
+/* CRC */
+#define PLD_CRC7DATA           __reg16(PLD_BASE + 0x18000)
+#define PLD_CRC7INDATA         __reg16(PLD_BASE + 0x18002)
+#define PLD_CRC16DATA          __reg16(PLD_BASE + 0x18004)
+#define PLD_CRC16INDATA                __reg16(PLD_BASE + 0x18006)
+#define PLD_CRC16ADATA         __reg16(PLD_BASE + 0x18008)
+#define PLD_CRC16AINDATA       __reg16(PLD_BASE + 0x1800a)
+
+/* RTC */
+#define PLD_RTCCR              __reg16(PLD_BASE + 0x1c000)
+#define PLD_RTCBAUR            __reg16(PLD_BASE + 0x1c002)
+#define PLD_RTCWRDATA          __reg16(PLD_BASE + 0x1c004)
+#define PLD_RTCRDDATA          __reg16(PLD_BASE + 0x1c006)
+#define PLD_RTCRSTODT          __reg16(PLD_BASE + 0x1c008)
+
+/* SIO0 */
+#define PLD_ESIO0CR            __reg16(PLD_BASE + 0x20000)
+#define        PLD_ESIO0CR_TXEN        0x0001
+#define        PLD_ESIO0CR_RXEN        0x0002
+#define PLD_ESIO0MOD0          __reg16(PLD_BASE + 0x20002)
+#define        PLD_ESIO0MOD0_CTSS      0x0040
+#define        PLD_ESIO0MOD0_RTSS      0x0080
+#define PLD_ESIO0MOD1          __reg16(PLD_BASE + 0x20004)
+#define        PLD_ESIO0MOD1_LMFS      0x0010
+#define PLD_ESIO0STS           __reg16(PLD_BASE + 0x20006)
+#define        PLD_ESIO0STS_TEMP       0x0001
+#define        PLD_ESIO0STS_TXCP       0x0002
+#define        PLD_ESIO0STS_RXCP       0x0004
+#define        PLD_ESIO0STS_TXSC       0x0100
+#define        PLD_ESIO0STS_RXSC       0x0200
+#define PLD_ESIO0STS_TXREADY   (PLD_ESIO0STS_TXCP | PLD_ESIO0STS_TEMP)
+#define PLD_ESIO0INTCR         __reg16(PLD_BASE + 0x20008)
+#define        PLD_ESIO0INTCR_TXIEN    0x0002
+#define        PLD_ESIO0INTCR_RXCEN    0x0004
+#define PLD_ESIO0BAUR          __reg16(PLD_BASE + 0x2000a)
+#define PLD_ESIO0TXB           __reg16(PLD_BASE + 0x2000c)
+#define PLD_ESIO0RXB           __reg16(PLD_BASE + 0x2000e)
+
+/* SIM Card */
+#define PLD_SCCR               __reg16(PLD_BASE + 0x38000)
+#define PLD_SCMOD              __reg16(PLD_BASE + 0x38004)
+#define PLD_SCSTS              __reg16(PLD_BASE + 0x38006)
+#define PLD_SCINTCR            __reg16(PLD_BASE + 0x38008)
+#define PLD_SCBAUR             __reg16(PLD_BASE + 0x3800a)
+#define PLD_SCTXB              __reg16(PLD_BASE + 0x3800c)
+#define PLD_SCRXB              __reg16(PLD_BASE + 0x3800e)
+
+#endif /* _M32700UT_M32700UT_PLD.H */
diff --git a/include/asm-m32r/m32r.h b/include/asm-m32r/m32r.h
new file mode 100644 (file)
index 0000000..f116649
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef _ASM_M32R_M32R_H_
+#define _ASM_M32R_M32R_H_
+
+/*
+ * Renesas M32R processor
+ *
+ * Copyright (C) 2003, 2004  Renesas Technology Corp.
+ */
+
+#include <linux/config.h>
+
+/* Chip type */
+#if defined(CONFIG_CHIP_XNUX_MP) || defined(CONFIG_CHIP_XNUX2_MP)
+#include <asm/m32r_mp_fpga.h>
+#elif defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \
+       || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
+        || defined(CONFIG_CHIP_OPSP)
+#include <asm/m32102.h>
+#include <asm/m32102peri.h>
+#endif
+
+/* Platform type */
+#if defined(CONFIG_PLAT_M32700UT)
+#include <asm/m32700ut/m32700ut_pld.h>
+#include <asm/m32700ut/m32700ut_lan.h>
+#include <asm/m32700ut/m32700ut_lcd.h>
+#endif  /* CONFIG_PLAT_M32700UT */
+
+#if defined(CONFIG_PLAT_OPSPUT)
+#include <asm/opsput/opsput_pld.h>
+#include <asm/opsput/opsput_lan.h>
+#include <asm/opsput/opsput_lcd.h>
+#endif  /* CONFIG_PLAT_OPSPUT */
+
+#if defined(CONFIG_PLAT_MAPPI2)
+#include <asm/mappi2/mappi2_pld.h>
+#endif /* CONFIG_PLAT_MAPPI2 */
+
+#if defined(CONFIG_PLAT_USRV)
+#include <asm/m32700ut/m32700ut_pld.h>
+#endif
+
+/*
+ * M32R Register
+ */
+
+/*
+ * MMU Register
+ */
+
+#define MMU_REG_BASE   (0xffff0000)
+#define ITLB_BASE      (0xfe000000)
+#define DTLB_BASE      (0xfe000800)
+
+#define NR_TLB_ENTRIES CONFIG_TLB_ENTRIES
+
+#define MATM   MMU_REG_BASE            /* MMU Address Translation Mode
+                                          Register */
+#define MPSZ   (0x04 + MMU_REG_BASE)   /* MMU Page Size Designation Register */
+#define MASID  (0x08 + MMU_REG_BASE)   /* MMU Address Space ID Register */
+#define MESTS  (0x0c + MMU_REG_BASE)   /* MMU Exception Status Register */
+#define MDEVA  (0x10 + MMU_REG_BASE)   /* MMU Operand Exception Virtual
+                                          Address Register */
+#define MDEVP  (0x14 + MMU_REG_BASE)   /* MMU Operand Exception Virtual Page
+                                          Number Register */
+#define MPTB   (0x18 + MMU_REG_BASE)   /* MMU Page Table Base Register */
+#define MSVA   (0x20 + MMU_REG_BASE)   /* MMU Search Virtual Address
+                                          Register */
+#define MTOP   (0x24 + MMU_REG_BASE)   /* MMU TLB Operation Register */
+#define MIDXI  (0x28 + MMU_REG_BASE)   /* MMU Index Register for
+                                          Instruciton */
+#define MIDXD  (0x2c + MMU_REG_BASE)   /* MMU Index Register for Operand */
+
+#define MATM_offset    (MATM - MMU_REG_BASE)
+#define MPSZ_offset    (MPSZ - MMU_REG_BASE)
+#define MASID_offset   (MASID - MMU_REG_BASE)
+#define MESTS_offset   (MESTS - MMU_REG_BASE)
+#define MDEVA_offset   (MDEVA - MMU_REG_BASE)
+#define MDEVP_offset   (MDEVP - MMU_REG_BASE)
+#define MPTB_offset    (MPTB - MMU_REG_BASE)
+#define MSVA_offset    (MSVA - MMU_REG_BASE)
+#define MTOP_offset    (MTOP - MMU_REG_BASE)
+#define MIDXI_offset   (MIDXI - MMU_REG_BASE)
+#define MIDXD_offset   (MIDXD - MMU_REG_BASE)
+
+#define MESTS_IT       (1 << 0)        /* Instruction TLB miss */
+#define MESTS_IA       (1 << 1)        /* Instruction Access Exception */
+#define MESTS_DT       (1 << 4)        /* Operand TLB miss */
+#define MESTS_DA       (1 << 5)        /* Operand Access Exception */
+#define MESTS_DRW      (1 << 6)        /* Operand Write Exception Flag */
+
+/*
+ * PSW (Processor Status Word)
+ */
+
+/* PSW bit */
+#define M32R_PSW_BIT_SM   (7)    /* Stack Mode */
+#define M32R_PSW_BIT_IE   (6)    /* Interrupt Enable */
+#define M32R_PSW_BIT_PM   (3)    /* Processor Mode [0:Supervisor,1:User] */
+#define M32R_PSW_BIT_C    (0)    /* Condition */
+#define M32R_PSW_BIT_BSM  (7+8)  /* Backup Stack Mode */
+#define M32R_PSW_BIT_BIE  (6+8)  /* Backup Interrupt Enable */
+#define M32R_PSW_BIT_BPM  (3+8)  /* Backup Processor Mode */
+#define M32R_PSW_BIT_BC   (0+8)  /* Backup Condition */
+
+/* PSW bit map */
+#define M32R_PSW_SM   (1UL<< M32R_PSW_BIT_SM)   /* Stack Mode */
+#define M32R_PSW_IE   (1UL<< M32R_PSW_BIT_IE)   /* Interrupt Enable */
+#define M32R_PSW_PM   (1UL<< M32R_PSW_BIT_PM)   /* Processor Mode */
+#define M32R_PSW_C    (1UL<< M32R_PSW_BIT_C)    /* Condition */
+#define M32R_PSW_BSM  (1UL<< M32R_PSW_BIT_BSM)  /* Backup Stack Mode */
+#define M32R_PSW_BIE  (1UL<< M32R_PSW_BIT_BIE)  /* Backup Interrupt Enable */
+#define M32R_PSW_BPM  (1UL<< M32R_PSW_BIT_BPM)  /* Backup Processor Mode */
+#define M32R_PSW_BC   (1UL<< M32R_PSW_BIT_BC)   /* Backup Condition */
+
+/*
+ * Direct address to SFR
+ */
+
+#include <asm/page.h>
+#ifdef CONFIG_MMU
+#define NONCACHE_OFFSET  __PAGE_OFFSET+0x20000000
+#else
+#define NONCACHE_OFFSET  __PAGE_OFFSET
+#endif /* CONFIG_MMU */
+
+#define M32R_ICU_ISTS_ADDR  M32R_ICU_ISTS_PORTL+NONCACHE_OFFSET
+#define M32R_ICU_IPICR_ADDR  M32R_ICU_IPICR0_PORTL+NONCACHE_OFFSET
+#define M32R_ICU_IMASK_ADDR  M32R_ICU_IMASK_PORTL+NONCACHE_OFFSET
+#define M32R_FPGA_CPU_NAME_ADDR  M32R_FPGA_CPU_NAME0_PORTL+NONCACHE_OFFSET
+#define M32R_FPGA_MODEL_ID_ADDR  M32R_FPGA_MODEL_ID0_PORTL+NONCACHE_OFFSET
+#define M32R_FPGA_VERSION_ADDR   M32R_FPGA_VERSION0_PORTL+NONCACHE_OFFSET
+
+#endif /* _ASM_M32R_M32R_H_ */
diff --git a/include/asm-m32r/m32r_mp_fpga.h b/include/asm-m32r/m32r_mp_fpga.h
new file mode 100644 (file)
index 0000000..976d2b9
--- /dev/null
@@ -0,0 +1,313 @@
+#ifndef _ASM_M32R_M32R_MP_FPGA_
+#define _ASM_M32R_M32R_MP_FPGA_
+
+/*
+ * Renesas M32R-MP-FPGA
+ *
+ * Copyright (c) 2002  Hitoshi Yamamoto
+ * Copyright (c) 2003, 2004  Renesas Technology Corp.
+ */
+
+/*
+ * ========================================================
+ * M32R-MP-FPGA Memory Map
+ * ========================================================
+ * 0x00000000 : Block#0 : 64[MB]
+ *              0x03E00000 : SFR
+ *                           0x03E00000 : reserved
+ *                           0x03EF0000 : FPGA
+ *                           0x03EF1000 : reserved
+ *                           0x03EF4000 : CKM
+ *                           0x03EF4000 : BSELC
+ *                           0x03EF5000 : reserved
+ *                           0x03EFC000 : MFT
+ *                           0x03EFD000 : SIO
+ *                           0x03EFE000 : reserved
+ *                           0x03EFF000 : ICU
+ *              0x03F00000 : Internal SRAM 64[KB]
+ *              0x03F10000 : reserved
+ * --------------------------------------------------------
+ * 0x04000000 : Block#1 : 64[MB]
+ *              0x04000000 : Debug board SRAM 4[MB]
+ *              0x04400000 : reserved
+ * --------------------------------------------------------
+ * 0x08000000 : Block#2 : 64[MB]
+ * --------------------------------------------------------
+ * 0x0C000000 : Block#3 : 64[MB]
+ * --------------------------------------------------------
+ * 0x10000000 : Block#4 : 64[MB]
+ * --------------------------------------------------------
+ * 0x14000000 : Block#5 : 64[MB]
+ * --------------------------------------------------------
+ * 0x18000000 : Block#6 : 64[MB]
+ * --------------------------------------------------------
+ * 0x1C000000 : Block#7 : 64[MB]
+ * --------------------------------------------------------
+ * 0xFE000000 : TLB
+ *              0xFE000000 : ITLB
+ *              0xFE000080 : reserved
+ *              0xFE000800 : DTLB
+ *              0xFE000880 : reserved
+ * --------------------------------------------------------
+ * 0xFF000000 : System area
+ *              0xFFFF0000 : MMU
+ *              0xFFFF0030 : reserved
+ *              0xFFFF8000 : Debug function
+ *              0xFFFFA000 : reserved
+ *              0xFFFFC000 : CPU control
+ * 0xFFFFFFFF
+ * ========================================================
+ */
+
+/*======================================================================*
+ * Special Function Register
+ *======================================================================*/
+#define M32R_SFR_OFFSET  (0x00E00000)  /* 0x03E00000-0x03EFFFFF 1[MB] */
+
+/*
+ * FPGA registers.
+ */
+#define M32R_FPGA_TOP  (0x000F0000+M32R_SFR_OFFSET)
+
+#define M32R_FPGA_NUM_OF_CPUS_PORTL  (0x00+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME0_PORTL    (0x10+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME1_PORTL    (0x14+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME2_PORTL    (0x18+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME3_PORTL    (0x1C+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID0_PORTL    (0x20+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID1_PORTL    (0x24+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID2_PORTL    (0x28+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID3_PORTL    (0x2C+M32R_FPGA_TOP)
+#define M32R_FPGA_VERSION0_PORTL     (0x30+M32R_FPGA_TOP)
+#define M32R_FPGA_VERSION1_PORTL     (0x34+M32R_FPGA_TOP)
+
+/*
+ * Clock and Power Manager registers.
+ */
+#define M32R_CPM_OFFSET  (0x000F4000+M32R_SFR_OFFSET)
+
+#define M32R_CPM_CPUCLKCR_PORTL  (0x00+M32R_CPM_OFFSET)
+#define M32R_CPM_CLKMOD_PORTL    (0x04+M32R_CPM_OFFSET)
+#define M32R_CPM_PLLCR_PORTL     (0x08+M32R_CPM_OFFSET)
+
+/*
+ * Block SELect Controller registers.
+ */
+#define M32R_BSELC_OFFSET  (0x000F5000+M32R_SFR_OFFSET)
+
+#define M32R_BSEL0_CR0_PORTL  (0x000+M32R_BSELC_OFFSET)
+#define M32R_BSEL0_CR1_PORTL  (0x004+M32R_BSELC_OFFSET)
+#define M32R_BSEL1_CR0_PORTL  (0x100+M32R_BSELC_OFFSET)
+#define M32R_BSEL1_CR1_PORTL  (0x104+M32R_BSELC_OFFSET)
+#define M32R_BSEL2_CR0_PORTL  (0x200+M32R_BSELC_OFFSET)
+#define M32R_BSEL2_CR1_PORTL  (0x204+M32R_BSELC_OFFSET)
+#define M32R_BSEL3_CR0_PORTL  (0x300+M32R_BSELC_OFFSET)
+#define M32R_BSEL3_CR1_PORTL  (0x304+M32R_BSELC_OFFSET)
+#define M32R_BSEL4_CR0_PORTL  (0x400+M32R_BSELC_OFFSET)
+#define M32R_BSEL4_CR1_PORTL  (0x404+M32R_BSELC_OFFSET)
+#define M32R_BSEL5_CR0_PORTL  (0x500+M32R_BSELC_OFFSET)
+#define M32R_BSEL5_CR1_PORTL  (0x504+M32R_BSELC_OFFSET)
+#define M32R_BSEL6_CR0_PORTL  (0x600+M32R_BSELC_OFFSET)
+#define M32R_BSEL6_CR1_PORTL  (0x604+M32R_BSELC_OFFSET)
+#define M32R_BSEL7_CR0_PORTL  (0x700+M32R_BSELC_OFFSET)
+#define M32R_BSEL7_CR1_PORTL  (0x704+M32R_BSELC_OFFSET)
+
+/*
+ * Multi Function Timer registers.
+ */
+#define M32R_MFT_OFFSET        (0x000FC000+M32R_SFR_OFFSET)
+
+#define M32R_MFTCR_PORTL       (0x000+M32R_MFT_OFFSET)  /* MFT control */
+#define M32R_MFTRPR_PORTL      (0x004+M32R_MFT_OFFSET)  /* MFT real port */
+
+#define M32R_MFT0_OFFSET       (0x100+M32R_MFT_OFFSET)
+#define M32R_MFT0MOD_PORTL     (0x00+M32R_MFT0_OFFSET)  /* MFT0 mode */
+#define M32R_MFT0BOS_PORTL     (0x04+M32R_MFT0_OFFSET)  /* MFT0 b-port output status */
+#define M32R_MFT0CUT_PORTL     (0x08+M32R_MFT0_OFFSET)  /* MFT0 count */
+#define M32R_MFT0RLD_PORTL     (0x0C+M32R_MFT0_OFFSET)  /* MFT0 reload */
+#define M32R_MFT0CMPRLD_PORTL  (0x10+M32R_MFT0_OFFSET)  /* MFT0 compare reload */
+
+#define M32R_MFT1_OFFSET       (0x200+M32R_MFT_OFFSET)
+#define M32R_MFT1MOD_PORTL     (0x00+M32R_MFT1_OFFSET)  /* MFT1 mode */
+#define M32R_MFT1BOS_PORTL     (0x04+M32R_MFT1_OFFSET)  /* MFT1 b-port output status */
+#define M32R_MFT1CUT_PORTL     (0x08+M32R_MFT1_OFFSET)  /* MFT1 count */
+#define M32R_MFT1RLD_PORTL     (0x0C+M32R_MFT1_OFFSET)  /* MFT1 reload */
+#define M32R_MFT1CMPRLD_PORTL  (0x10+M32R_MFT1_OFFSET)  /* MFT1 compare reload */
+
+#define M32R_MFT2_OFFSET       (0x300+M32R_MFT_OFFSET)
+#define M32R_MFT2MOD_PORTL     (0x00+M32R_MFT2_OFFSET)  /* MFT2 mode */
+#define M32R_MFT2BOS_PORTL     (0x04+M32R_MFT2_OFFSET)  /* MFT2 b-port output status */
+#define M32R_MFT2CUT_PORTL     (0x08+M32R_MFT2_OFFSET)  /* MFT2 count */
+#define M32R_MFT2RLD_PORTL     (0x0C+M32R_MFT2_OFFSET)  /* MFT2 reload */
+#define M32R_MFT2CMPRLD_PORTL  (0x10+M32R_MFT2_OFFSET)  /* MFT2 compare reload */
+
+#define M32R_MFT3_OFFSET       (0x400+M32R_MFT_OFFSET)
+#define M32R_MFT3MOD_PORTL     (0x00+M32R_MFT3_OFFSET)  /* MFT3 mode */
+#define M32R_MFT3BOS_PORTL     (0x04+M32R_MFT3_OFFSET)  /* MFT3 b-port output status */
+#define M32R_MFT3CUT_PORTL     (0x08+M32R_MFT3_OFFSET)  /* MFT3 count */
+#define M32R_MFT3RLD_PORTL     (0x0C+M32R_MFT3_OFFSET)  /* MFT3 reload */
+#define M32R_MFT3CMPRLD_PORTL  (0x10+M32R_MFT3_OFFSET)  /* MFT3 compare reload */
+
+#define M32R_MFT4_OFFSET       (0x500+M32R_MFT_OFFSET)
+#define M32R_MFT4MOD_PORTL     (0x00+M32R_MFT4_OFFSET)  /* MFT4 mode */
+#define M32R_MFT4BOS_PORTL     (0x04+M32R_MFT4_OFFSET)  /* MFT4 b-port output status */
+#define M32R_MFT4CUT_PORTL     (0x08+M32R_MFT4_OFFSET)  /* MFT4 count */
+#define M32R_MFT4RLD_PORTL     (0x0C+M32R_MFT4_OFFSET)  /* MFT4 reload */
+#define M32R_MFT4CMPRLD_PORTL  (0x10+M32R_MFT4_OFFSET)  /* MFT4 compare reload */
+
+#define M32R_MFT5_OFFSET       (0x600+M32R_MFT_OFFSET)
+#define M32R_MFT5MOD_PORTL     (0x00+M32R_MFT5_OFFSET)  /* MFT4 mode */
+#define M32R_MFT5BOS_PORTL     (0x04+M32R_MFT5_OFFSET)  /* MFT4 b-port output status */
+#define M32R_MFT5CUT_PORTL     (0x08+M32R_MFT5_OFFSET)  /* MFT4 count */
+#define M32R_MFT5RLD_PORTL     (0x0C+M32R_MFT5_OFFSET)  /* MFT4 reload */
+#define M32R_MFT5CMPRLD_PORTL  (0x10+M32R_MFT5_OFFSET)  /* MFT4 compare reload */
+
+#define M32R_MFTCR_MFT0MSK  (1UL<<15)  /* b16 */
+#define M32R_MFTCR_MFT1MSK  (1UL<<14)  /* b17 */
+#define M32R_MFTCR_MFT2MSK  (1UL<<13)  /* b18 */
+#define M32R_MFTCR_MFT3MSK  (1UL<<12)  /* b19 */
+#define M32R_MFTCR_MFT4MSK  (1UL<<11)  /* b20 */
+#define M32R_MFTCR_MFT5MSK  (1UL<<10)  /* b21 */
+#define M32R_MFTCR_MFT0EN   (1UL<<7)   /* b24 */
+#define M32R_MFTCR_MFT1EN   (1UL<<6)   /* b25 */
+#define M32R_MFTCR_MFT2EN   (1UL<<5)   /* b26 */
+#define M32R_MFTCR_MFT3EN   (1UL<<4)   /* b27 */
+#define M32R_MFTCR_MFT4EN   (1UL<<3)   /* b28 */
+#define M32R_MFTCR_MFT5EN   (1UL<<2)   /* b29 */
+
+#define M32R_MFTMOD_CC_MASK    (1UL<<15)  /* b16 */
+#define M32R_MFTMOD_TCCR       (1UL<<13)  /* b18 */
+#define M32R_MFTMOD_GTSEL000   (0UL<<8)   /* b21-23 : 000 */
+#define M32R_MFTMOD_GTSEL001   (1UL<<8)   /* b21-23 : 001 */
+#define M32R_MFTMOD_GTSEL010   (2UL<<8)   /* b21-23 : 010 */
+#define M32R_MFTMOD_GTSEL011   (3UL<<8)   /* b21-23 : 011 */
+#define M32R_MFTMOD_GTSEL110   (6UL<<8)   /* b21-23 : 110 */
+#define M32R_MFTMOD_GTSEL111   (7UL<<8)   /* b21-23 : 111 */
+#define M32R_MFTMOD_CMSEL      (1UL<<3)   /* b28 */
+#define M32R_MFTMOD_CSSEL000   (0UL<<0)   /* b29-b31 : 000 */
+#define M32R_MFTMOD_CSSEL001   (1UL<<0)   /* b29-b31 : 001 */
+#define M32R_MFTMOD_CSSEL010   (2UL<<0)   /* b29-b31 : 010 */
+#define M32R_MFTMOD_CSSEL011   (3UL<<0)   /* b29-b31 : 011 */
+#define M32R_MFTMOD_CSSEL100   (4UL<<0)   /* b29-b31 : 100 */
+#define M32R_MFTMOD_CSSEL110   (6UL<<0)   /* b29-b31 : 110 */
+
+/*
+ * Serial I/O registers.
+ */
+#define M32R_SIO_OFFSET  (0x000FD000+M32R_SFR_OFFSET)
+
+#define M32R_SIO0_CR_PORTL     (0x000+M32R_SIO_OFFSET)
+#define M32R_SIO0_MOD0_PORTL   (0x004+M32R_SIO_OFFSET)
+#define M32R_SIO0_MOD1_PORTL   (0x008+M32R_SIO_OFFSET)
+#define M32R_SIO0_STS_PORTL    (0x00C+M32R_SIO_OFFSET)
+#define M32R_SIO0_TRCR_PORTL   (0x010+M32R_SIO_OFFSET)
+#define M32R_SIO0_BAUR_PORTL   (0x014+M32R_SIO_OFFSET)
+#define M32R_SIO0_RBAUR_PORTL  (0x018+M32R_SIO_OFFSET)
+#define M32R_SIO0_TXB_PORTL    (0x01C+M32R_SIO_OFFSET)
+#define M32R_SIO0_RXB_PORTL    (0x020+M32R_SIO_OFFSET)
+
+/*
+ * Interrupt Control Unit registers.
+ */
+#define M32R_ICU_OFFSET  (0x000FF000+M32R_SFR_OFFSET)
+
+#define M32R_ICU_ISTS_PORTL     (0x004+M32R_ICU_OFFSET)
+#define M32R_ICU_IREQ0_PORTL    (0x008+M32R_ICU_OFFSET)
+#define M32R_ICU_IREQ1_PORTL    (0x00C+M32R_ICU_OFFSET)
+#define M32R_ICU_SBICR_PORTL    (0x018+M32R_ICU_OFFSET)
+#define M32R_ICU_IMASK_PORTL    (0x01C+M32R_ICU_OFFSET)
+#define M32R_ICU_CR1_PORTL      (0x200+M32R_ICU_OFFSET)  /* INT0 */
+#define M32R_ICU_CR2_PORTL      (0x204+M32R_ICU_OFFSET)  /* INT1 */
+#define M32R_ICU_CR3_PORTL      (0x208+M32R_ICU_OFFSET)  /* INT2 */
+#define M32R_ICU_CR4_PORTL      (0x20C+M32R_ICU_OFFSET)  /* INT3 */
+#define M32R_ICU_CR5_PORTL      (0x210+M32R_ICU_OFFSET)  /* INT4 */
+#define M32R_ICU_CR6_PORTL      (0x214+M32R_ICU_OFFSET)  /* INT5 */
+#define M32R_ICU_CR7_PORTL      (0x218+M32R_ICU_OFFSET)  /* INT6 */
+#define M32R_ICU_CR8_PORTL      (0x218+M32R_ICU_OFFSET)  /* INT7 */
+#define M32R_ICU_CR32_PORTL     (0x27C+M32R_ICU_OFFSET)  /* SIO0 RX */
+#define M32R_ICU_CR33_PORTL     (0x280+M32R_ICU_OFFSET)  /* SIO0 TX */
+#define M32R_ICU_CR40_PORTL     (0x29C+M32R_ICU_OFFSET)  /* DMAC0 */
+#define M32R_ICU_CR41_PORTL     (0x2A0+M32R_ICU_OFFSET)  /* DMAC1 */
+#define M32R_ICU_CR48_PORTL     (0x2BC+M32R_ICU_OFFSET)  /* MFT0 */
+#define M32R_ICU_CR49_PORTL     (0x2C0+M32R_ICU_OFFSET)  /* MFT1 */
+#define M32R_ICU_CR50_PORTL     (0x2C4+M32R_ICU_OFFSET)  /* MFT2 */
+#define M32R_ICU_CR51_PORTL     (0x2C8+M32R_ICU_OFFSET)  /* MFT3 */
+#define M32R_ICU_CR52_PORTL     (0x2CC+M32R_ICU_OFFSET)  /* MFT4 */
+#define M32R_ICU_CR53_PORTL     (0x2D0+M32R_ICU_OFFSET)  /* MFT5 */
+#define M32R_ICU_IPICR0_PORTL   (0x2DC+M32R_ICU_OFFSET)  /* IPI0 */
+#define M32R_ICU_IPICR1_PORTL   (0x2E0+M32R_ICU_OFFSET)  /* IPI1 */
+#define M32R_ICU_IPICR2_PORTL   (0x2E4+M32R_ICU_OFFSET)  /* IPI2 */
+#define M32R_ICU_IPICR3_PORTL   (0x2E8+M32R_ICU_OFFSET)  /* IPI3 */
+#define M32R_ICU_IPICR4_PORTL   (0x2EC+M32R_ICU_OFFSET)  /* IPI4 */
+#define M32R_ICU_IPICR5_PORTL   (0x2F0+M32R_ICU_OFFSET)  /* IPI5 */
+#define M32R_ICU_IPICR6_PORTL   (0x2F4+M32R_ICU_OFFSET)  /* IPI6 */
+#define M32R_ICU_IPICR7_PORTL   (0x2FC+M32R_ICU_OFFSET)  /* IPI7 */
+
+#define M32R_ICUISTS_VECB(val)  ((val>>28) & 0xF)
+#define M32R_ICUISTS_ISN(val)   ((val>>22) & 0x3F)
+#define M32R_ICUISTS_PIML(val)  ((val>>16) & 0x7)
+
+#define M32R_ICUIMASK_IMSK0  (0UL<<16)  /* b13-b15: Disable interrupt */
+#define M32R_ICUIMASK_IMSK1  (1UL<<16)  /* b13-b15: Enable level 0 interrupt */
+#define M32R_ICUIMASK_IMSK2  (2UL<<16)  /* b13-b15: Enable level 0,1 interrupt */
+#define M32R_ICUIMASK_IMSK3  (3UL<<16)  /* b13-b15: Enable level 0-2 interrupt */
+#define M32R_ICUIMASK_IMSK4  (4UL<<16)  /* b13-b15: Enable level 0-3 interrupt */
+#define M32R_ICUIMASK_IMSK5  (5UL<<16)  /* b13-b15: Enable level 0-4 interrupt */
+#define M32R_ICUIMASK_IMSK6  (6UL<<16)  /* b13-b15: Enable level 0-5 interrupt */
+#define M32R_ICUIMASK_IMSK7  (7UL<<16)  /* b13-b15: Enable level 0-6 interrupt */
+
+#define M32R_ICUCR_IEN      (1UL<<12)  /* b19: Interrupt enable */
+#define M32R_ICUCR_IRQ      (1UL<<8)   /* b23: Interrupt request */
+#define M32R_ICUCR_ISMOD00  (0UL<<4)   /* b26-b27: Interrupt sense mode Edge HtoL */
+#define M32R_ICUCR_ISMOD01  (1UL<<4)   /* b26-b27: Interrupt sense mode Level L */
+#define M32R_ICUCR_ISMOD10  (2UL<<4)   /* b26-b27: Interrupt sense mode Edge LtoH*/
+#define M32R_ICUCR_ISMOD11  (3UL<<4)   /* b26-b27: Interrupt sense mode Level H */
+#define M32R_ICUCR_ILEVEL0  (0UL<<0)   /* b29-b31: Interrupt priority level 0 */
+#define M32R_ICUCR_ILEVEL1  (1UL<<0)   /* b29-b31: Interrupt priority level 1 */
+#define M32R_ICUCR_ILEVEL2  (2UL<<0)   /* b29-b31: Interrupt priority level 2 */
+#define M32R_ICUCR_ILEVEL3  (3UL<<0)   /* b29-b31: Interrupt priority level 3 */
+#define M32R_ICUCR_ILEVEL4  (4UL<<0)   /* b29-b31: Interrupt priority level 4 */
+#define M32R_ICUCR_ILEVEL5  (5UL<<0)   /* b29-b31: Interrupt priority level 5 */
+#define M32R_ICUCR_ILEVEL6  (6UL<<0)   /* b29-b31: Interrupt priority level 6 */
+#define M32R_ICUCR_ILEVEL7  (7UL<<0)   /* b29-b31: Disable interrupt */
+#define M32R_ICUCR_ILEVEL_MASK  (7UL)
+
+#define M32R_IRQ_INT0    (1)   /* INT0 */
+#define M32R_IRQ_INT1    (2)   /* INT1 */
+#define M32R_IRQ_INT2    (3)   /* INT2 */
+#define M32R_IRQ_INT3    (4)   /* INT3 */
+#define M32R_IRQ_INT4    (5)   /* INT4 */
+#define M32R_IRQ_INT5    (6)   /* INT5 */
+#define M32R_IRQ_INT6    (7)   /* INT6 */
+#define M32R_IRQ_INT7    (8)   /* INT7 */
+#define M32R_IRQ_MFT0    (16)  /* MFT0 */
+#define M32R_IRQ_MFT1    (17)  /* MFT1 */
+#define M32R_IRQ_MFT2    (18)  /* MFT2 */
+#define M32R_IRQ_MFT3    (19)  /* MFT3 */
+#define M32R_IRQ_MFT4    (20)  /* MFT4 */
+#define M32R_IRQ_MFT5    (21)  /* MFT5 */
+#define M32R_IRQ_DMAC0   (32)  /* DMAC0 */
+#define M32R_IRQ_DMAC1   (33)  /* DMAC1 */
+#define M32R_IRQ_SIO0_R  (48)  /* SIO0 receive */
+#define M32R_IRQ_SIO0_S  (49)  /* SIO0 send    */
+#define M32R_IRQ_SIO1_R  (50)  /* SIO1 send    */
+#define M32R_IRQ_SIO1_S  (51)  /* SIO1 receive */
+#define M32R_IRQ_IPI0    (56)  /* IPI0 */
+#define M32R_IRQ_IPI1    (57)  /* IPI1 */
+#define M32R_IRQ_IPI2    (58)  /* IPI2 */
+#define M32R_IRQ_IPI3    (59)  /* IPI3 */
+#define M32R_IRQ_IPI4    (60)  /* IPI4 */
+#define M32R_IRQ_IPI5    (61)  /* IPI5 */
+#define M32R_IRQ_IPI6    (62)  /* IPI6 */
+#define M32R_IRQ_IPI7    (63)  /* IPI7 */
+
+/*======================================================================*
+ * CPU
+ *======================================================================*/
+
+#define M32R_CPUID_PORTL   (0xFFFFFFE0)
+#define M32R_MCICAR_PORTL  (0xFFFFFFF0)
+#define M32R_MCDCAR_PORTL  (0xFFFFFFF4)
+#define M32R_MCCR_PORTL    (0xFFFFFFFC)
+
+#endif  /* _ASM_M32R_M32R_MP_FPGA_ */
diff --git a/include/asm-m32r/mappi2/mappi2_pld.h b/include/asm-m32r/mappi2/mappi2_pld.h
new file mode 100644 (file)
index 0000000..01dcdd1
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * include/asm/mappi2/mappi2_pld.h
+ *
+ * Definitions for Extended IO Logic on MAPPI2 board.
+ *  based on m32700ut_pld.h by
+ *
+ * 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 _MAPPI2_PLD_H
+#define _MAPPI2_PLD_H
+
+#ifndef __ASSEMBLY__
+/* FIXME:
+ * Some C functions use non-cache address, so can't define non-cache address.
+ */
+#define PLD_BASE               (0x10c00000 /* + NONCACHE_OFFSET */)
+#define __reg8                 (volatile unsigned char *)
+#define __reg16                        (volatile unsigned short *)
+#define __reg32                        (volatile unsigned int *)
+#else
+#define PLD_BASE               (0x10c00000 + NONCACHE_OFFSET)
+#define __reg8
+#define __reg16
+#define __reg32
+#endif /* __ASSEMBLY__ */
+
+/* CFC */
+#define        PLD_CFRSTCR             __reg16(PLD_BASE + 0x0000)
+#define PLD_CFSTS              __reg16(PLD_BASE + 0x0002)
+#define PLD_CFIMASK            __reg16(PLD_BASE + 0x0004)
+#define PLD_CFBUFCR            __reg16(PLD_BASE + 0x0006)
+#define PLD_CFCR0              __reg16(PLD_BASE + 0x000a)
+#define PLD_CFCR1              __reg16(PLD_BASE + 0x000c)
+
+/* MMC */
+#define PLD_MMCCR              __reg16(PLD_BASE + 0x4000)
+#define PLD_MMCMOD             __reg16(PLD_BASE + 0x4002)
+#define PLD_MMCSTS             __reg16(PLD_BASE + 0x4006)
+#define PLD_MMCBAUR            __reg16(PLD_BASE + 0x400a)
+#define PLD_MMCCMDBCUT         __reg16(PLD_BASE + 0x400c)
+#define PLD_MMCCDTBCUT         __reg16(PLD_BASE + 0x400e)
+#define PLD_MMCDET             __reg16(PLD_BASE + 0x4010)
+#define PLD_MMCWP              __reg16(PLD_BASE + 0x4012)
+#define PLD_MMCWDATA           __reg16(PLD_BASE + 0x5000)
+#define PLD_MMCRDATA           __reg16(PLD_BASE + 0x6000)
+#define PLD_MMCCMDDATA         __reg16(PLD_BASE + 0x7000)
+#define PLD_MMCRSPDATA         __reg16(PLD_BASE + 0x7006)
+
+/* Power Control of MMC and CF */
+#define PLD_CPCR               __reg16(PLD_BASE + 0x14000)
+
+
+/*==== ICU ====*/
+#define  M32R_IRQ_PC104        (5)   /* INT4(PC/104) */
+#define  M32R_IRQ_I2C          (28)  /* I2C-BUS     */
+#if 1
+#define  PLD_IRQ_CFIREQ       (40)  /* CFC Card Interrupt */
+#define  PLD_IRQ_CFC_INSERT   (41)  /* CFC Card Insert */
+#define  PLD_IRQ_CFC_EJECT    (42)  /* CFC Card Eject */
+#define  PLD_IRQ_MMCCARD      (43)  /* MMC Card Insert */
+#define  PLD_IRQ_MMCIRQ       (44)  /* MMC Transfer Done */
+#else
+#define  PLD_IRQ_CFIREQ       (34)  /* CFC Card Interrupt */
+#define  PLD_IRQ_CFC_INSERT   (35)  /* CFC Card Insert */
+#define  PLD_IRQ_CFC_EJECT    (36)  /* CFC Card Eject */
+#define  PLD_IRQ_MMCCARD      (37)  /* MMC Card Insert */
+#define  PLD_IRQ_MMCIRQ       (38)  /* MMC Transfer Done */
+#endif
+
+
+#if 0
+/* LED Control
+ *
+ * 1: DIP swich side
+ * 2: Reset switch side
+ */
+#define PLD_IOLEDCR            __reg16(PLD_BASE + 0x14002)
+#define PLD_IOLED_1_ON         0x001
+#define PLD_IOLED_1_OFF                0x000
+#define PLD_IOLED_2_ON         0x002
+#define PLD_IOLED_2_OFF                0x000
+
+/* DIP Switch
+ *  0: Write-protect of Flash Memory (0:protected, 1:non-protected)
+ *  1: -
+ *  2: -
+ *  3: -
+ */
+#define PLD_IOSWSTS            __reg16(PLD_BASE + 0x14004)
+#define        PLD_IOSWSTS_IOSW2       0x0200
+#define        PLD_IOSWSTS_IOSW1       0x0100
+#define        PLD_IOSWSTS_IOWP0       0x0001
+
+#endif
+
+/* CRC */
+#define PLD_CRC7DATA           __reg16(PLD_BASE + 0x18000)
+#define PLD_CRC7INDATA         __reg16(PLD_BASE + 0x18002)
+#define PLD_CRC16DATA          __reg16(PLD_BASE + 0x18004)
+#define PLD_CRC16INDATA                __reg16(PLD_BASE + 0x18006)
+#define PLD_CRC16ADATA         __reg16(PLD_BASE + 0x18008)
+#define PLD_CRC16AINDATA       __reg16(PLD_BASE + 0x1800a)
+
+
+#if 0
+/* RTC */
+#define PLD_RTCCR              __reg16(PLD_BASE + 0x1c000)
+#define PLD_RTCBAUR            __reg16(PLD_BASE + 0x1c002)
+#define PLD_RTCWRDATA          __reg16(PLD_BASE + 0x1c004)
+#define PLD_RTCRDDATA          __reg16(PLD_BASE + 0x1c006)
+#define PLD_RTCRSTODT          __reg16(PLD_BASE + 0x1c008)
+
+/* SIO0 */
+#define PLD_ESIO0CR            __reg16(PLD_BASE + 0x20000)
+#define        PLD_ESIO0CR_TXEN        0x0001
+#define        PLD_ESIO0CR_RXEN        0x0002
+#define PLD_ESIO0MOD0          __reg16(PLD_BASE + 0x20002)
+#define        PLD_ESIO0MOD0_CTSS      0x0040
+#define        PLD_ESIO0MOD0_RTSS      0x0080
+#define PLD_ESIO0MOD1          __reg16(PLD_BASE + 0x20004)
+#define        PLD_ESIO0MOD1_LMFS      0x0010
+#define PLD_ESIO0STS           __reg16(PLD_BASE + 0x20006)
+#define        PLD_ESIO0STS_TEMP       0x0001
+#define        PLD_ESIO0STS_TXCP       0x0002
+#define        PLD_ESIO0STS_RXCP       0x0004
+#define        PLD_ESIO0STS_TXSC       0x0100
+#define        PLD_ESIO0STS_RXSC       0x0200
+#define PLD_ESIO0STS_TXREADY   (PLD_ESIO0STS_TXCP | PLD_ESIO0STS_TEMP)
+#define PLD_ESIO0INTCR         __reg16(PLD_BASE + 0x20008)
+#define        PLD_ESIO0INTCR_TXIEN    0x0002
+#define        PLD_ESIO0INTCR_RXCEN    0x0004
+#define PLD_ESIO0BAUR          __reg16(PLD_BASE + 0x2000a)
+#define PLD_ESIO0TXB           __reg16(PLD_BASE + 0x2000c)
+#define PLD_ESIO0RXB           __reg16(PLD_BASE + 0x2000e)
+
+/* SIM Card */
+#define PLD_SCCR               __reg16(PLD_BASE + 0x38000)
+#define PLD_SCMOD              __reg16(PLD_BASE + 0x38004)
+#define PLD_SCSTS              __reg16(PLD_BASE + 0x38006)
+#define PLD_SCINTCR            __reg16(PLD_BASE + 0x38008)
+#define PLD_SCBAUR             __reg16(PLD_BASE + 0x3800a)
+#define PLD_SCTXB              __reg16(PLD_BASE + 0x3800c)
+#define PLD_SCRXB              __reg16(PLD_BASE + 0x3800e)
+
+#endif
+
+#endif /* _MAPPI2_PLD.H */
diff --git a/include/asm-m32r/mc146818rtc.h b/include/asm-m32r/mc146818rtc.h
new file mode 100644 (file)
index 0000000..755601d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef _ASM_MC146818RTC_H
+#define _ASM_MC146818RTC_H
+
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+// #define RTC_PORT(x) (0x70 + (x))
+#define RTC_PORT(x)    ((x))
+#define RTC_ALWAYS_BCD 1       /* RTC operates in binary mode */
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+#define RTC_IRQ 8
+#if 0
+#endif
+
+#endif /* _ASM_MC146818RTC_H */
diff --git a/include/asm-m32r/mman.h b/include/asm-m32r/mman.h
new file mode 100644 (file)
index 0000000..011f6d9
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __M32R_MMAN_H__
+#define __M32R_MMAN_H__
+
+/* orig : i386 2.6.0-test6 */
+
+#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 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 /* __M32R_MMAN_H__ */
diff --git a/include/asm-m32r/mmu.h b/include/asm-m32r/mmu.h
new file mode 100644 (file)
index 0000000..930093a
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _ASM_M32R_MMU_H
+#define _ASM_M32R_MMU_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+
+#if !defined(CONFIG_MMU)
+struct mm_rblock_struct {
+  int     size;
+  int     refcount;
+  void    *kblock;
+};
+
+struct mm_tblock_struct {
+  struct mm_rblock_struct *rblock;
+  struct mm_tblock_struct *next;
+};
+
+typedef struct {
+  struct mm_tblock_struct tblock;
+  unsigned long           end_brk;
+} mm_context_t;
+#else
+
+/* Default "unsigned long" context */
+#ifndef CONFIG_SMP
+typedef unsigned long mm_context_t;
+#else
+typedef unsigned long mm_context_t[NR_CPUS];
+#endif
+
+#endif  /* CONFIG_MMU */
+#endif  /* _ASM_M32R_MMU_H */
+
diff --git a/include/asm-m32r/mmu_context.h b/include/asm-m32r/mmu_context.h
new file mode 100644 (file)
index 0000000..c16f81c
--- /dev/null
@@ -0,0 +1,169 @@
+#ifndef _ASM_M32R_MMU_CONTEXT_H
+#define _ASM_M32R_MMU_CONTEXT_H
+
+/* $Id */
+
+#include <linux/config.h>
+
+#include <asm/m32r.h>
+
+#define MMU_CONTEXT_ASID_MASK      (0x000000FF)
+#define MMU_CONTEXT_VERSION_MASK   (0xFFFFFF00)
+#define MMU_CONTEXT_FIRST_VERSION  (0x00000100)
+#define NO_CONTEXT                 (0x00000000)
+
+
+#ifndef __ASSEMBLY__
+
+#include <linux/config.h>
+#include <asm/atomic.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu.h>
+#include <asm/tlbflush.h>
+
+/*
+ * Cache of MMU context last used.
+ */
+#ifndef CONFIG_SMP
+extern unsigned long mmu_context_cache_dat;
+#define mmu_context_cache      mmu_context_cache_dat
+#define mm_context(mm)         mm->context
+#else /* not CONFIG_SMP */
+extern unsigned long mmu_context_cache_dat[];
+#define mmu_context_cache      mmu_context_cache_dat[smp_processor_id()]
+#define mm_context(mm)         mm->context[smp_processor_id()]
+#endif /* not CONFIG_SMP */
+
+#define set_tlb_tag(entry, tag)        (*entry = (tag & PAGE_MASK)|get_asid())
+#define set_tlb_data(entry, data)      (*entry = (data | _PAGE_PRESENT))
+
+#ifdef CONFIG_MMU
+#define enter_lazy_tlb(mm, tsk)        do { } while (0)
+
+static __inline__ void get_new_mmu_context(struct mm_struct *mm)
+{
+       unsigned long mc = ++mmu_context_cache;
+
+       if (!(mc & MMU_CONTEXT_ASID_MASK)) {
+               /* We exhaust ASID of this version.
+                  Flush all TLB and start new cycle. */
+               local_flush_tlb_all();
+               /* Fix version if needed.
+                  Note that we avoid version #0 to distingush NO_CONTEXT. */
+               if (!mc)
+                       mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;
+       }
+       mm_context(mm) = mc;
+}
+
+/*
+ * Get MMU context if needed.
+ */
+static __inline__ void get_mmu_context(struct mm_struct *mm)
+{
+       if (mm) {
+               unsigned long mc = mmu_context_cache;
+
+               /* Check if we have old version of context.
+                  If it's old, we need to get new context with new version. */
+               if ((mm_context(mm) ^ mc) & MMU_CONTEXT_VERSION_MASK)
+                       get_new_mmu_context(mm);
+       }
+}
+
+/*
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+static __inline__ int init_new_context(struct task_struct *tsk,
+       struct mm_struct *mm)
+{
+#ifndef CONFIG_SMP
+       mm->context = NO_CONTEXT;
+#else /* CONFIG_SMP */
+       int num_cpus = num_online_cpus();
+       int i;
+
+       for (i = 0 ; i < num_cpus ; i++)
+               mm->context[i] = NO_CONTEXT;
+#endif /* CONFIG_SMP */
+
+       return 0;
+}
+
+/*
+ * Destroy context related info for an mm_struct that is about
+ * to be put to rest.
+ */
+#define destroy_context(mm)    do { } while (0)
+
+static __inline__ void set_asid(unsigned long asid)
+{
+       *(volatile unsigned long *)MASID = (asid & MMU_CONTEXT_ASID_MASK);
+}
+
+static __inline__ unsigned long get_asid(void)
+{
+       unsigned long asid;
+
+       asid = *(volatile long *)MASID;
+       asid &= MMU_CONTEXT_ASID_MASK;
+
+       return asid;
+}
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+static __inline__ void activate_context(struct mm_struct *mm)
+{
+       get_mmu_context(mm);
+       set_asid(mm_context(mm) & MMU_CONTEXT_ASID_MASK);
+}
+
+static __inline__ void switch_mm(struct mm_struct *prev,
+       struct mm_struct *next, struct task_struct *tsk)
+{
+#ifdef CONFIG_SMP
+       int cpu = smp_processor_id();
+#endif /* CONFIG_SMP */
+
+       if (prev != next) {
+#ifdef CONFIG_SMP
+               cpu_set(cpu, next->cpu_vm_mask);
+#endif /* CONFIG_SMP */
+               /* Set MPTB = next->pgd */
+               *(volatile unsigned long *)MPTB = (unsigned long)next->pgd;
+               activate_context(next);
+       }
+#ifdef CONFIG_SMP
+       else
+               if (!cpu_test_and_set(cpu, next->cpu_vm_mask))
+                       activate_context(next);
+#endif /* CONFIG_SMP */
+}
+
+#define deactivate_mm(tsk, mm) do { } while (0)
+
+#define activate_mm(prev, next)        \
+       switch_mm((prev), (next), NULL)
+
+#else
+#define get_mmu_context(mm)             do { } while (0)
+#define init_new_context(tsk,mm)        (0)
+#define destroy_context(mm)             do { } while (0)
+#define set_asid(asid)                  do { } while (0)
+#define get_asid()                      (0)
+#define activate_context(mm)            do { } while (0)
+#define switch_mm(prev,next,tsk)        do { } while (0)
+#define deactivate_mm(mm,tsk)           do { } while (0)
+#define activate_mm(prev,next)          do { } while (0)
+#define enter_lazy_tlb(mm,tsk)          do { } while (0)
+#endif /* CONFIG_MMU */
+
+
+#endif /* not __ASSEMBLY__ */
+
+#endif /* _ASM_M32R_MMU_CONTEXT_H */
+
diff --git a/include/asm-m32r/mmzone.h b/include/asm-m32r/mmzone.h
new file mode 100644 (file)
index 0000000..ebf0228
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Written by Pat Gaughen (gone@us.ibm.com) Mar 2002
+ *
+ */
+
+#ifndef _ASM_MMZONE_H_
+#define _ASM_MMZONE_H_
+
+#include <asm/smp.h>
+
+#ifdef CONFIG_DISCONTIGMEM
+
+extern struct pglist_data *node_data[];
+#define NODE_DATA(nid)         (node_data[nid])
+
+#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn)
+#define node_mem_map(nid)      (NODE_DATA(nid)->node_mem_map)
+#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
+#define node_end_pfn(nid)                                              \
+({                                                                     \
+       pg_data_t *__pgdat = NODE_DATA(nid);                            \
+       __pgdat->node_start_pfn + __pgdat->node_spanned_pages - 1;      \
+})
+
+#define local_mapnr(kvaddr)                                            \
+({                                                                     \
+       unsigned long __pfn = __pa(kvaddr) >> PAGE_SHIFT;               \
+       (__pfn - node_start_pfn(pfn_to_nid(__pfn)));                    \
+})
+
+#define pfn_to_page(pfn)                                               \
+({                                                                     \
+       unsigned long __pfn = pfn;                                      \
+       int __node  = pfn_to_nid(__pfn);                                \
+       &node_mem_map(__node)[node_localnr(__pfn,__node)];              \
+})
+
+#define page_to_pfn(pg)                                                        \
+({                                                                     \
+       struct page *__page = pg;                                       \
+       struct zone *__zone = page_zone(__page);                        \
+       (unsigned long)(__page - __zone->zone_mem_map)                  \
+               + __zone->zone_start_pfn;                               \
+})
+#define pmd_page(pmd)          (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+/*
+ * pfn_valid should be made as fast as possible, and the current definition
+ * is valid for machines that are NUMA, but still contiguous, which is what
+ * is currently supported. A more generalised, but slower definition would
+ * be something like this - mbligh:
+ * ( pfn_to_pgdat(pfn) && ((pfn) < node_end_pfn(pfn_to_nid(pfn))) )
+ */
+#if 1  /* M32R_FIXME */
+#define pfn_valid(pfn) (1)
+#else
+#define pfn_valid(pfn) ((pfn) < num_physpages)
+#endif
+
+/*
+ * generic node memory support, the following assumptions apply:
+ */
+
+static __inline__ int pfn_to_nid(unsigned long pfn)
+{
+       int node;
+
+       for (node = 0 ; node < MAX_NUMNODES ; node++)
+               if (pfn >= node_start_pfn(node) && pfn <= node_end_pfn(node))
+                       break;
+
+       return node;
+}
+
+static __inline__ struct pglist_data *pfn_to_pgdat(unsigned long pfn)
+{
+       return(NODE_DATA(pfn_to_nid(pfn)));
+}
+
+#endif /* CONFIG_DISCONTIGMEM */
+#endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-m32r/module.h b/include/asm-m32r/module.h
new file mode 100644 (file)
index 0000000..3f2541c
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _ASM_M32R_MODULE_H
+#define _ASM_M32R_MODULE_H
+
+/* $Id$ */
+
+struct mod_arch_specific { };
+
+#define Elf_Shdr       Elf32_Shdr
+#define Elf_Sym                Elf32_Sym
+#define Elf_Ehdr       Elf32_Ehdr
+
+#endif /* _ASM_M32R_MODULE_H */
+
diff --git a/include/asm-m32r/msgbuf.h b/include/asm-m32r/msgbuf.h
new file mode 100644 (file)
index 0000000..852ff52
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _ASM_M32R_MSGBUF_H
+#define _ASM_M32R_MSGBUF_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * The msqid64_ds structure for m32r 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 /* _ASM_M32R_MSGBUF_H */
diff --git a/include/asm-m32r/namei.h b/include/asm-m32r/namei.h
new file mode 100644 (file)
index 0000000..7172d3d
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef _ASM_M32R_NAMEI_H
+#define _ASM_M32R_NAMEI_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * linux/include/asm-m32r/namei.h
+ *
+ * Included from linux/fs/namei.c
+ */
+
+/* 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 /* _ASM_M32R_NAMEI_H */
diff --git a/include/asm-m32r/numnodes.h b/include/asm-m32r/numnodes.h
new file mode 100644 (file)
index 0000000..479a39d
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _ASM_NUMNODES_H_
+#define _ASM_NUMNODES_H_
+
+#include <linux/config.h>
+
+#ifdef CONFIG_DISCONTIGMEM
+
+#if defined(CONFIG_CHIP_M32700)
+#define        NODES_SHIFT     1       /* Max 2 Nodes */
+#endif /* CONFIG_CHIP_M32700 */
+
+#endif /* CONFIG_DISCONTIGMEM */
+
+#endif /* _ASM_NUMNODES_H_ */
+
diff --git a/include/asm-m32r/opsput/opsput_lan.h b/include/asm-m32r/opsput/opsput_lan.h
new file mode 100644 (file)
index 0000000..7a2a839
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * include/asm/opsput_lan.h
+ *
+ * OPSPUT-LAN board
+ *
+ * Copyright (c) 2002-2004     Takeo Takahashi, Mamoru Sakugawa
+ *
+ * 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.
+ *
+ * $Id: opsput_lan.h,v 1.1 2004/07/27 06:54:20 sakugawa Exp $
+ */
+
+#ifndef _OPSPUT_OPSPUT_LAN_H
+#define _OPSPUT_OPSPUT_LAN_H
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define OPSPUT_LAN_BASE        (0x10000000 /* + NONCACHE_OFFSET */)
+#else
+#define OPSPUT_LAN_BASE        (0x10000000 + NONCACHE_OFFSET)
+#endif /* __ASSEMBLY__ */
+
+/* ICU
+ *  ICUISTS:   status register
+ *  ICUIREQ0:  request register
+ *  ICUIREQ1:  request register
+ *  ICUCR3:    control register for CFIREQ# interrupt
+ *  ICUCR4:    control register for CFC Card insert interrupt
+ *  ICUCR5:    control register for CFC Card eject interrupt
+ *  ICUCR6:    control register for external interrupt
+ *  ICUCR11:   control register for MMC Card insert/eject interrupt
+ *  ICUCR13:   control register for SC error interrupt
+ *  ICUCR14:   control register for SC receive interrupt
+ *  ICUCR15:   control register for SC send interrupt
+ *  ICUCR16:   control register for SIO0 receive interrupt
+ *  ICUCR17:   control register for SIO0 send interrupt
+ */
+#define OPSPUT_LAN_IRQ_LAN     (OPSPUT_LAN_PLD_IRQ_BASE + 1)   /* LAN */
+#define OPSPUT_LAN_IRQ_I2C     (OPSPUT_LAN_PLD_IRQ_BASE + 3)   /* I2C */
+
+#define OPSPUT_LAN_ICUISTS     __reg16(OPSPUT_LAN_BASE + 0xc0002)
+#define OPSPUT_LAN_ICUISTS_VECB_MASK   (0xf000)
+#define OPSPUT_LAN_VECB(x)     ((x) & OPSPUT_LAN_ICUISTS_VECB_MASK)
+#define OPSPUT_LAN_ICUISTS_ISN_MASK    (0x07c0)
+#define OPSPUT_LAN_ICUISTS_ISN(x)      ((x) & OPSPUT_LAN_ICUISTS_ISN_MASK)
+#define OPSPUT_LAN_ICUIREQ0    __reg16(OPSPUT_LAN_BASE + 0xc0004)
+#define OPSPUT_LAN_ICUCR1      __reg16(OPSPUT_LAN_BASE + 0xc0010)
+#define OPSPUT_LAN_ICUCR3      __reg16(OPSPUT_LAN_BASE + 0xc0014)
+
+#endif /* _OPSPUT_OPSPUT_LAN_H */
diff --git a/include/asm-m32r/opsput/opsput_lcd.h b/include/asm-m32r/opsput/opsput_lcd.h
new file mode 100644 (file)
index 0000000..3a883e3
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * include/asm/opsput_lcd.h
+ *
+ * OPSPUT-LCD board
+ *
+ * Copyright (c) 2002  Takeo Takahashi
+ *
+ * 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.
+ *
+ * $Id: opsput_lcd.h,v 1.1 2004/07/27 06:54:20 sakugawa Exp $
+ */
+
+#ifndef _OPSPUT_OPSPUT_LCD_H
+#define _OPSPUT_OPSPUT_LCD_H
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define OPSPUT_LCD_BASE        (0x10000000 /* + NONCACHE_OFFSET */)
+#else
+#define OPSPUT_LCD_BASE        (0x10000000 + NONCACHE_OFFSET)
+#endif /* __ASSEMBLY__ */
+
+/*
+ * ICU
+ */
+#define OPSPUT_LCD_IRQ_BAT_INT (OPSPUT_LCD_PLD_IRQ_BASE + 1)
+#define OPSPUT_LCD_IRQ_USB_INT1        (OPSPUT_LCD_PLD_IRQ_BASE + 2)
+#define OPSPUT_LCD_IRQ_AUDT0           (OPSPUT_LCD_PLD_IRQ_BASE + 3)
+#define OPSPUT_LCD_IRQ_AUDT2           (OPSPUT_LCD_PLD_IRQ_BASE + 4)
+#define OPSPUT_LCD_IRQ_BATSIO_RCV      (OPSPUT_LCD_PLD_IRQ_BASE + 16)
+#define OPSPUT_LCD_IRQ_BATSIO_SND      (OPSPUT_LCD_PLD_IRQ_BASE + 17)
+#define OPSPUT_LCD_IRQ_ASNDSIO_RCV     (OPSPUT_LCD_PLD_IRQ_BASE + 18)
+#define OPSPUT_LCD_IRQ_ASNDSIO_SND     (OPSPUT_LCD_PLD_IRQ_BASE + 19)
+#define OPSPUT_LCD_IRQ_ACNLSIO_SND     (OPSPUT_LCD_PLD_IRQ_BASE + 21)
+
+#define OPSPUT_LCD_ICUISTS     __reg16(OPSPUT_LCD_BASE + 0x300002)
+#define OPSPUT_LCD_ICUISTS_VECB_MASK   (0xf000)
+#define OPSPUT_LCD_VECB(x)     ((x) & OPSPUT_LCD_ICUISTS_VECB_MASK)
+#define OPSPUT_LCD_ICUISTS_ISN_MASK    (0x07c0)
+#define OPSPUT_LCD_ICUISTS_ISN(x)      ((x) & OPSPUT_LCD_ICUISTS_ISN_MASK)
+#define OPSPUT_LCD_ICUIREQ0    __reg16(OPSPUT_LCD_BASE + 0x300004)
+#define OPSPUT_LCD_ICUIREQ1    __reg16(OPSPUT_LCD_BASE + 0x300006)
+#define OPSPUT_LCD_ICUCR1      __reg16(OPSPUT_LCD_BASE + 0x300020)
+#define OPSPUT_LCD_ICUCR2      __reg16(OPSPUT_LCD_BASE + 0x300022)
+#define OPSPUT_LCD_ICUCR3      __reg16(OPSPUT_LCD_BASE + 0x300024)
+#define OPSPUT_LCD_ICUCR4      __reg16(OPSPUT_LCD_BASE + 0x300026)
+#define OPSPUT_LCD_ICUCR16     __reg16(OPSPUT_LCD_BASE + 0x300030)
+#define OPSPUT_LCD_ICUCR17     __reg16(OPSPUT_LCD_BASE + 0x300032)
+#define OPSPUT_LCD_ICUCR18     __reg16(OPSPUT_LCD_BASE + 0x300034)
+#define OPSPUT_LCD_ICUCR19     __reg16(OPSPUT_LCD_BASE + 0x300036)
+#define OPSPUT_LCD_ICUCR21     __reg16(OPSPUT_LCD_BASE + 0x30003a)
+
+#endif /* _OPSPUT_OPSPUT_LCD_H */
diff --git a/include/asm-m32r/opsput/opsput_pld.h b/include/asm-m32r/opsput/opsput_pld.h
new file mode 100644 (file)
index 0000000..2018e69
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * include/asm/opsput/opsput_pld.h
+ *
+ * Definitions for Programable Logic Device(PLD) on OPSPUT board.
+ *
+ * Copyright (c) 2002  Takeo Takahashi
+ *
+ * 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.
+ *
+ * $Id: opsput_pld.h,v 1.1 2004/07/27 06:54:20 sakugawa Exp $
+ */
+
+#ifndef _OPSPUT_OPSPUT_PLD_H
+#define _OPSPUT_OPSPUT_PLD_H
+
+#include <linux/config.h>
+
+#define PLD_PLAT_BASE          0x1cc00000
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define PLD_BASE               (PLD_PLAT_BASE /* + NONCACHE_OFFSET */)
+#define __reg8                 (volatile unsigned char *)
+#define __reg16                        (volatile unsigned short *)
+#define __reg32                        (volatile unsigned int *)
+#else
+#define PLD_BASE               (PLD_PLAT_BASE + NONCACHE_OFFSET)
+#define __reg8
+#define __reg16
+#define __reg32
+#endif /* __ASSEMBLY__ */
+
+/* CFC */
+#define        PLD_CFRSTCR             __reg16(PLD_BASE + 0x0000)
+#define PLD_CFSTS              __reg16(PLD_BASE + 0x0002)
+#define PLD_CFIMASK            __reg16(PLD_BASE + 0x0004)
+#define PLD_CFBUFCR            __reg16(PLD_BASE + 0x0006)
+#define PLD_CFVENCR            __reg16(PLD_BASE + 0x0008)
+#define PLD_CFCR0              __reg16(PLD_BASE + 0x000a)
+#define PLD_CFCR1              __reg16(PLD_BASE + 0x000c)
+#define PLD_IDERSTCR           __reg16(PLD_BASE + 0x0010)
+
+/* MMC */
+#define PLD_MMCCR              __reg16(PLD_BASE + 0x4000)
+#define PLD_MMCMOD             __reg16(PLD_BASE + 0x4002)
+#define PLD_MMCSTS             __reg16(PLD_BASE + 0x4006)
+#define PLD_MMCBAUR            __reg16(PLD_BASE + 0x400a)
+#define PLD_MMCCMDBCUT         __reg16(PLD_BASE + 0x400c)
+#define PLD_MMCCDTBCUT         __reg16(PLD_BASE + 0x400e)
+#define PLD_MMCDET             __reg16(PLD_BASE + 0x4010)
+#define PLD_MMCWP              __reg16(PLD_BASE + 0x4012)
+#define PLD_MMCWDATA           __reg16(PLD_BASE + 0x5000)
+#define PLD_MMCRDATA           __reg16(PLD_BASE + 0x6000)
+#define PLD_MMCCMDDATA         __reg16(PLD_BASE + 0x7000)
+#define PLD_MMCRSPDATA         __reg16(PLD_BASE + 0x7006)
+
+/* ICU
+ *  ICUISTS:   status register
+ *  ICUIREQ0:  request register
+ *  ICUIREQ1:  request register
+ *  ICUCR3:    control register for CFIREQ# interrupt
+ *  ICUCR4:    control register for CFC Card insert interrupt
+ *  ICUCR5:    control register for CFC Card eject interrupt
+ *  ICUCR6:    control register for external interrupt
+ *  ICUCR11:   control register for MMC Card insert/eject interrupt
+ *  ICUCR13:   control register for SC error interrupt
+ *  ICUCR14:   control register for SC receive interrupt
+ *  ICUCR15:   control register for SC send interrupt
+ *  ICUCR16:   control register for SIO0 receive interrupt
+ *  ICUCR17:   control register for SIO0 send interrupt
+ */
+#if !defined(CONFIG_PLAT_USRV)
+#define PLD_IRQ_INT0           (OPSPUT_PLD_IRQ_BASE + 0)       /* None */
+#define PLD_IRQ_INT1           (OPSPUT_PLD_IRQ_BASE + 1)       /* reserved */
+#define PLD_IRQ_INT2           (OPSPUT_PLD_IRQ_BASE + 2)       /* reserved */
+#define PLD_IRQ_CFIREQ         (OPSPUT_PLD_IRQ_BASE + 3)       /* CF IREQ */
+#define PLD_IRQ_CFC_INSERT     (OPSPUT_PLD_IRQ_BASE + 4)       /* CF Insert */
+#define PLD_IRQ_CFC_EJECT      (OPSPUT_PLD_IRQ_BASE + 5)       /* CF Eject */
+#define PLD_IRQ_EXINT          (OPSPUT_PLD_IRQ_BASE + 6)       /* EXINT */
+#define PLD_IRQ_INT7           (OPSPUT_PLD_IRQ_BASE + 7)       /* reserved */
+#define PLD_IRQ_INT8           (OPSPUT_PLD_IRQ_BASE + 8)       /* reserved */
+#define PLD_IRQ_INT9           (OPSPUT_PLD_IRQ_BASE + 9)       /* reserved */
+#define PLD_IRQ_INT10          (OPSPUT_PLD_IRQ_BASE + 10)      /* reserved */
+#define PLD_IRQ_MMCCARD                (OPSPUT_PLD_IRQ_BASE + 11)      /* MMC Insert/Eject */
+#define PLD_IRQ_INT12          (OPSPUT_PLD_IRQ_BASE + 12)      /* reserved */
+#define PLD_IRQ_SC_ERROR       (OPSPUT_PLD_IRQ_BASE + 13)      /* SC error */
+#define PLD_IRQ_SC_RCV         (OPSPUT_PLD_IRQ_BASE + 14)      /* SC receive */
+#define PLD_IRQ_SC_SND         (OPSPUT_PLD_IRQ_BASE + 15)      /* SC send */
+#define PLD_IRQ_SIO0_RCV       (OPSPUT_PLD_IRQ_BASE + 16)      /* SIO receive */
+#define PLD_IRQ_SIO0_SND       (OPSPUT_PLD_IRQ_BASE + 17)      /* SIO send */
+#define PLD_IRQ_INT18          (OPSPUT_PLD_IRQ_BASE + 18)      /* reserved */
+#define PLD_IRQ_INT19          (OPSPUT_PLD_IRQ_BASE + 19)      /* reserved */
+#define PLD_IRQ_INT20          (OPSPUT_PLD_IRQ_BASE + 20)      /* reserved */
+#define PLD_IRQ_INT21          (OPSPUT_PLD_IRQ_BASE + 21)      /* reserved */
+#define PLD_IRQ_INT22          (OPSPUT_PLD_IRQ_BASE + 22)      /* reserved */
+#define PLD_IRQ_INT23          (OPSPUT_PLD_IRQ_BASE + 23)      /* reserved */
+#define PLD_IRQ_INT24          (OPSPUT_PLD_IRQ_BASE + 24)      /* reserved */
+#define PLD_IRQ_INT25          (OPSPUT_PLD_IRQ_BASE + 25)      /* reserved */
+#define PLD_IRQ_INT26          (OPSPUT_PLD_IRQ_BASE + 26)      /* reserved */
+#define PLD_IRQ_INT27          (OPSPUT_PLD_IRQ_BASE + 27)      /* reserved */
+#define PLD_IRQ_INT28          (OPSPUT_PLD_IRQ_BASE + 28)      /* reserved */
+#define PLD_IRQ_INT29          (OPSPUT_PLD_IRQ_BASE + 29)      /* reserved */
+#define PLD_IRQ_INT30          (OPSPUT_PLD_IRQ_BASE + 30)      /* reserved */
+#define PLD_IRQ_INT31          (OPSPUT_PLD_IRQ_BASE + 31)      /* reserved */
+
+#else  /* CONFIG_PLAT_USRV */
+
+#define PLD_IRQ_INT0           (OPSPUT_PLD_IRQ_BASE + 0)       /* None */
+#define PLD_IRQ_INT1           (OPSPUT_PLD_IRQ_BASE + 1)       /* reserved */
+#define PLD_IRQ_INT2           (OPSPUT_PLD_IRQ_BASE + 2)       /* reserved */
+#define PLD_IRQ_CF0            (OPSPUT_PLD_IRQ_BASE + 3)       /* CF0# */
+#define PLD_IRQ_CF1            (OPSPUT_PLD_IRQ_BASE + 4)       /* CF1# */
+#define PLD_IRQ_CF2            (OPSPUT_PLD_IRQ_BASE + 5)       /* CF2# */
+#define PLD_IRQ_CF3            (OPSPUT_PLD_IRQ_BASE + 6)       /* CF3# */
+#define PLD_IRQ_CF4            (OPSPUT_PLD_IRQ_BASE + 7)       /* CF4# */
+#define PLD_IRQ_INT8           (OPSPUT_PLD_IRQ_BASE + 8)       /* reserved */
+#define PLD_IRQ_INT9           (OPSPUT_PLD_IRQ_BASE + 9)       /* reserved */
+#define PLD_IRQ_INT10          (OPSPUT_PLD_IRQ_BASE + 10)      /* reserved */
+#define PLD_IRQ_INT11          (OPSPUT_PLD_IRQ_BASE + 11)      /* reserved */
+#define PLD_IRQ_UART0          (OPSPUT_PLD_IRQ_BASE + 12)      /* UARTIRQ0 */
+#define PLD_IRQ_UART1          (OPSPUT_PLD_IRQ_BASE + 13)      /* UARTIRQ1 */
+#define PLD_IRQ_INT14          (OPSPUT_PLD_IRQ_BASE + 14)      /* reserved */
+#define PLD_IRQ_INT15          (OPSPUT_PLD_IRQ_BASE + 15)      /* reserved */
+#define PLD_IRQ_SNDINT         (OPSPUT_PLD_IRQ_BASE + 16)      /* SNDINT# */
+#define PLD_IRQ_INT17          (OPSPUT_PLD_IRQ_BASE + 17)      /* reserved */
+#define PLD_IRQ_INT18          (OPSPUT_PLD_IRQ_BASE + 18)      /* reserved */
+#define PLD_IRQ_INT19          (OPSPUT_PLD_IRQ_BASE + 19)      /* reserved */
+#define PLD_IRQ_INT20          (OPSPUT_PLD_IRQ_BASE + 20)      /* reserved */
+#define PLD_IRQ_INT21          (OPSPUT_PLD_IRQ_BASE + 21)      /* reserved */
+#define PLD_IRQ_INT22          (OPSPUT_PLD_IRQ_BASE + 22)      /* reserved */
+#define PLD_IRQ_INT23          (OPSPUT_PLD_IRQ_BASE + 23)      /* reserved */
+#define PLD_IRQ_INT24          (OPSPUT_PLD_IRQ_BASE + 24)      /* reserved */
+#define PLD_IRQ_INT25          (OPSPUT_PLD_IRQ_BASE + 25)      /* reserved */
+#define PLD_IRQ_INT26          (OPSPUT_PLD_IRQ_BASE + 26)      /* reserved */
+#define PLD_IRQ_INT27          (OPSPUT_PLD_IRQ_BASE + 27)      /* reserved */
+#define PLD_IRQ_INT28          (OPSPUT_PLD_IRQ_BASE + 28)      /* reserved */
+#define PLD_IRQ_INT29          (OPSPUT_PLD_IRQ_BASE + 29)      /* reserved */
+#define PLD_IRQ_INT30          (OPSPUT_PLD_IRQ_BASE + 30)      /* reserved */
+
+#endif /* CONFIG_PLAT_USRV */
+
+#define PLD_ICUISTS            __reg16(PLD_BASE + 0x8002)
+#define PLD_ICUISTS_VECB_MASK  (0xf000)
+#define PLD_ICUISTS_VECB(x)    ((x) & PLD_ICUISTS_VECB_MASK)
+#define PLD_ICUISTS_ISN_MASK   (0x07c0)
+#define PLD_ICUISTS_ISN(x)     ((x) & PLD_ICUISTS_ISN_MASK)
+#define PLD_ICUIREQ0           __reg16(PLD_BASE + 0x8004)
+#define PLD_ICUIREQ1           __reg16(PLD_BASE + 0x8006)
+#define PLD_ICUCR1             __reg16(PLD_BASE + 0x8100)
+#define PLD_ICUCR2             __reg16(PLD_BASE + 0x8102)
+#define PLD_ICUCR3             __reg16(PLD_BASE + 0x8104)
+#define PLD_ICUCR4             __reg16(PLD_BASE + 0x8106)
+#define PLD_ICUCR5             __reg16(PLD_BASE + 0x8108)
+#define PLD_ICUCR6             __reg16(PLD_BASE + 0x810a)
+#define PLD_ICUCR7             __reg16(PLD_BASE + 0x810c)
+#define PLD_ICUCR8             __reg16(PLD_BASE + 0x810e)
+#define PLD_ICUCR9             __reg16(PLD_BASE + 0x8110)
+#define PLD_ICUCR10            __reg16(PLD_BASE + 0x8112)
+#define PLD_ICUCR11            __reg16(PLD_BASE + 0x8114)
+#define PLD_ICUCR12            __reg16(PLD_BASE + 0x8116)
+#define PLD_ICUCR13            __reg16(PLD_BASE + 0x8118)
+#define PLD_ICUCR14            __reg16(PLD_BASE + 0x811a)
+#define PLD_ICUCR15            __reg16(PLD_BASE + 0x811c)
+#define PLD_ICUCR16            __reg16(PLD_BASE + 0x811e)
+#define PLD_ICUCR17            __reg16(PLD_BASE + 0x8120)
+#define PLD_ICUCR_IEN          (0x1000)
+#define PLD_ICUCR_IREQ         (0x0100)
+#define PLD_ICUCR_ISMOD00      (0x0000)        /* Low edge */
+#define PLD_ICUCR_ISMOD01      (0x0010)        /* Low level */
+#define PLD_ICUCR_ISMOD02      (0x0020)        /* High edge */
+#define PLD_ICUCR_ISMOD03      (0x0030)        /* High level */
+#define PLD_ICUCR_ILEVEL0      (0x0000)
+#define PLD_ICUCR_ILEVEL1      (0x0001)
+#define PLD_ICUCR_ILEVEL2      (0x0002)
+#define PLD_ICUCR_ILEVEL3      (0x0003)
+#define PLD_ICUCR_ILEVEL4      (0x0004)
+#define PLD_ICUCR_ILEVEL5      (0x0005)
+#define PLD_ICUCR_ILEVEL6      (0x0006)
+#define PLD_ICUCR_ILEVEL7      (0x0007)
+
+/* Power Control of MMC and CF */
+#define PLD_CPCR               __reg16(PLD_BASE + 0x14000)
+#define PLD_CPCR_CF            0x0001
+#define PLD_CPCR_MMC           0x0002
+
+/* LED Control
+ *
+ * 1: DIP swich side
+ * 2: Reset switch side
+ */
+#define PLD_IOLEDCR            __reg16(PLD_BASE + 0x14002)
+#define PLD_IOLED_1_ON         0x001
+#define PLD_IOLED_1_OFF                0x000
+#define PLD_IOLED_2_ON         0x002
+#define PLD_IOLED_2_OFF                0x000
+
+/* DIP Switch
+ *  0: Write-protect of Flash Memory (0:protected, 1:non-protected)
+ *  1: -
+ *  2: -
+ *  3: -
+ */
+#define PLD_IOSWSTS            __reg16(PLD_BASE + 0x14004)
+#define        PLD_IOSWSTS_IOSW2       0x0200
+#define        PLD_IOSWSTS_IOSW1       0x0100
+#define        PLD_IOSWSTS_IOWP0       0x0001
+
+/* CRC */
+#define PLD_CRC7DATA           __reg16(PLD_BASE + 0x18000)
+#define PLD_CRC7INDATA         __reg16(PLD_BASE + 0x18002)
+#define PLD_CRC16DATA          __reg16(PLD_BASE + 0x18004)
+#define PLD_CRC16INDATA                __reg16(PLD_BASE + 0x18006)
+#define PLD_CRC16ADATA         __reg16(PLD_BASE + 0x18008)
+#define PLD_CRC16AINDATA       __reg16(PLD_BASE + 0x1800a)
+
+/* RTC */
+#define PLD_RTCCR              __reg16(PLD_BASE + 0x1c000)
+#define PLD_RTCBAUR            __reg16(PLD_BASE + 0x1c002)
+#define PLD_RTCWRDATA          __reg16(PLD_BASE + 0x1c004)
+#define PLD_RTCRDDATA          __reg16(PLD_BASE + 0x1c006)
+#define PLD_RTCRSTODT          __reg16(PLD_BASE + 0x1c008)
+
+/* SIO0 */
+#define PLD_ESIO0CR            __reg16(PLD_BASE + 0x20000)
+#define        PLD_ESIO0CR_TXEN        0x0001
+#define        PLD_ESIO0CR_RXEN        0x0002
+#define PLD_ESIO0MOD0          __reg16(PLD_BASE + 0x20002)
+#define        PLD_ESIO0MOD0_CTSS      0x0040
+#define        PLD_ESIO0MOD0_RTSS      0x0080
+#define PLD_ESIO0MOD1          __reg16(PLD_BASE + 0x20004)
+#define        PLD_ESIO0MOD1_LMFS      0x0010
+#define PLD_ESIO0STS           __reg16(PLD_BASE + 0x20006)
+#define        PLD_ESIO0STS_TEMP       0x0001
+#define        PLD_ESIO0STS_TXCP       0x0002
+#define        PLD_ESIO0STS_RXCP       0x0004
+#define        PLD_ESIO0STS_TXSC       0x0100
+#define        PLD_ESIO0STS_RXSC       0x0200
+#define PLD_ESIO0STS_TXREADY   (PLD_ESIO0STS_TXCP | PLD_ESIO0STS_TEMP)
+#define PLD_ESIO0INTCR         __reg16(PLD_BASE + 0x20008)
+#define        PLD_ESIO0INTCR_TXIEN    0x0002
+#define        PLD_ESIO0INTCR_RXCEN    0x0004
+#define PLD_ESIO0BAUR          __reg16(PLD_BASE + 0x2000a)
+#define PLD_ESIO0TXB           __reg16(PLD_BASE + 0x2000c)
+#define PLD_ESIO0RXB           __reg16(PLD_BASE + 0x2000e)
+
+/* SIM Card */
+#define PLD_SCCR               __reg16(PLD_BASE + 0x38000)
+#define PLD_SCMOD              __reg16(PLD_BASE + 0x38004)
+#define PLD_SCSTS              __reg16(PLD_BASE + 0x38006)
+#define PLD_SCINTCR            __reg16(PLD_BASE + 0x38008)
+#define PLD_SCBAUR             __reg16(PLD_BASE + 0x3800a)
+#define PLD_SCTXB              __reg16(PLD_BASE + 0x3800c)
+#define PLD_SCRXB              __reg16(PLD_BASE + 0x3800e)
+
+#endif /* _OPSPUT_OPSPUT_PLD.H */
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h
new file mode 100644 (file)
index 0000000..ea2d1f9
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef _ASM_M32R_PAGE_H
+#define _ASM_M32R_PAGE_H
+
+#include <linux/config.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__
+#ifndef __ASSEMBLY__
+
+extern void clear_page(void *to);
+extern void copy_page(void *to, void *from);
+
+#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; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+#define pte_val(x)     ((x).pte)
+#define PTE_MASK       PAGE_MASK
+
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pmd_val(x)     ((x).pmd)
+#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) } )
+
+#endif /* !__ASSEMBLY__ */
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)       (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
+
+/*
+ * This handles the memory map.. We could make this a config
+ * option, but too many people screw it up, and too few need
+ * it.
+ *
+ * A __PAGE_OFFSET of 0xC0000000 means that the kernel has
+ * a virtual address space of one gigabyte, which limits the
+ * amount of physical memory you can use to about 950MB.
+ *
+ * If you want more physical memory than this then see the CONFIG_HIGHMEM4G
+ * and CONFIG_HIGHMEM64G options in the kernel configuration.
+ */
+
+
+/* This handles the memory map.. */
+
+#ifndef __ASSEMBLY__
+
+/* Pure 2^n version of get_order */
+static __inline__ int get_order(unsigned long size)
+{
+       int order;
+
+       size = (size - 1) >> (PAGE_SHIFT - 1);
+       order = -1;
+       do {
+               size >>= 1;
+               order++;
+       } while (size);
+
+       return order;
+}
+
+#endif /* __ASSEMBLY__ */
+
+#define __MEMORY_START  CONFIG_MEMORY_START
+#define __MEMORY_SIZE   CONFIG_MEMORY_SIZE
+
+#ifdef CONFIG_MMU
+#define __PAGE_OFFSET  (0x80000000)
+#else
+#define __PAGE_OFFSET  (0x00000000)
+#endif
+
+#define PAGE_OFFSET            ((unsigned long)__PAGE_OFFSET)
+#define __pa(x)                        ((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x)                        ((void *)((unsigned long)(x) + PAGE_OFFSET))
+
+#ifndef CONFIG_DISCONTIGMEM
+#define PFN_BASE               (CONFIG_MEMORY_START >> PAGE_SHIFT)
+#define pfn_to_page(pfn)       (mem_map + ((pfn) - PFN_BASE))
+#define page_to_pfn(page)      \
+       ((unsigned long)((page) - mem_map) + PFN_BASE)
+#define pfn_valid(pfn)         (((pfn) - PFN_BASE) < max_mapnr)
+#endif  /* !CONFIG_DISCONTIGMEM */
+
+#define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+#define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | VM_EXEC | \
+                                VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC )
+
+#define devmem_is_allowed(x) 1
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_M32R_PAGE_H */
+
diff --git a/include/asm-m32r/param.h b/include/asm-m32r/param.h
new file mode 100644 (file)
index 0000000..750b938
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _ASM_M32R_PARAM_H
+#define _ASM_M32R_PARAM_H
+
+/* $Id$ */
+
+/* orig : i386 2.5.67 */
+
+#ifdef __KERNEL__
+# define HZ            100             /* Internal kernel timer frequency */
+# define USER_HZ       100             /* .. some user interfaces are in "ticks" */
+# define CLOCKS_PER_SEC        (USER_HZ)       /* like times() */
+#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 /* _ASM_M32R_PARAM_H */
+
diff --git a/include/asm-m32r/pci.h b/include/asm-m32r/pci.h
new file mode 100644 (file)
index 0000000..00d7b6f
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _ASM_M32R_PCI_H
+#define _ASM_M32R_PCI_H
+
+/* $Id$ */
+
+#include <asm-generic/pci.h>
+
+#define PCI_DMA_BUS_IS_PHYS    (1)
+
+#endif /* _ASM_M32R_PCI_H */
diff --git a/include/asm-m32r/percpu.h b/include/asm-m32r/percpu.h
new file mode 100644 (file)
index 0000000..e316930
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ARCH_M32R_PERCPU__
+#define __ARCH_M32R_PERCPU__
+
+#include <asm-generic/percpu.h>
+
+#endif /* __ARCH_M32R_PERCPU__ */
diff --git a/include/asm-m32r/pgalloc.h b/include/asm-m32r/pgalloc.h
new file mode 100644 (file)
index 0000000..8d5a444
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef _ASM_M32R_PGALLOC_H
+#define _ASM_M32R_PGALLOC_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+
+#define pmd_populate_kernel(mm, pmd, pte)      \
+       set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
+
+static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+       struct page *pte)
+{
+       set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte)));
+}
+
+/*
+ * Allocate and free page tables.
+ */
+static __inline__ pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+       pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
+
+       if (pgd)
+               clear_page(pgd);
+
+       return pgd;
+}
+
+static __inline__ void pgd_free(pgd_t *pgd)
+{
+       free_page((unsigned long)pgd);
+}
+
+static __inline__ pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+       unsigned long address)
+{
+       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL);
+
+       if (pte)
+               clear_page(pte);
+
+       return pte;
+}
+
+static __inline__ struct page *pte_alloc_one(struct mm_struct *mm,
+       unsigned long address)
+{
+       struct page *pte = alloc_page(GFP_KERNEL);
+
+       if (pte)
+               clear_page(page_address(pte));
+
+       return pte;
+}
+
+static __inline__ void pte_free_kernel(pte_t *pte)
+{
+       free_page((unsigned long)pte);
+}
+
+static __inline__ void pte_free(struct page *pte)
+{
+       __free_page(pte);
+}
+
+#define __pte_free_tlb(tlb, pte)       pte_free((pte))
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ * (In the PAE case we free the pmds as part of the pgd.)
+ */
+
+#define pmd_alloc_one(mm, addr)                ({ BUG(); ((pmd_t *)2); })
+#define pmd_free(x)                    do { } while (0)
+#define __pmd_free_tlb(tlb, x)         do { } while (0)
+#define pgd_populate(mm, pmd, pte)     BUG()
+
+#define check_pgt_cache()      do { } while (0)
+
+#endif /* _ASM_M32R_PGALLOC_H */
+
diff --git a/include/asm-m32r/pgtable-2level.h b/include/asm-m32r/pgtable-2level.h
new file mode 100644 (file)
index 0000000..7755c2b
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef _ASM_M32R_PGTABLE_2LEVEL_H
+#define _ASM_M32R_PGTABLE_2LEVEL_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+
+/*
+ * traditional M32R two-level paging structure:
+ */
+
+#define PGDIR_SHIFT    22
+#define PTRS_PER_PGD   1024
+
+/*
+ * the M32R is two-level, so we don't really have any
+ * PMD directory physically.
+ */
+#define PMD_SHIFT      22
+#define PTRS_PER_PMD   1
+
+#define PTRS_PER_PTE   1024
+
+#define pte_ERROR(e) \
+       printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pmd_ERROR(e) \
+       printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pgd_ERROR(e) \
+       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+static __inline__ int pgd_none(pgd_t pgd)      { return 0; }
+static __inline__ int pgd_bad(pgd_t pgd)       { return 0; }
+static __inline__ int pgd_present(pgd_t pgd)   { return 1; }
+#define pgd_clear(xp)                          do { } while (0)
+
+/*
+ * Certain architectures need to do special things when PTEs
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#define set_pte_atomic(pteptr, pteval) set_pte(pteptr, pteval)
+/*
+ * (pmds are folded into pgds so this doesnt get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
+#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval)
+
+#define pgd_page(pgd) \
+((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
+
+static __inline__ pmd_t *pmd_offset(pgd_t * dir, unsigned long address)
+{
+       return (pmd_t *) dir;
+}
+
+#define ptep_get_and_clear(xp) __pte(xchg(&(xp)->pte, 0))
+#define pte_same(a, b)         (pte_val(a) == pte_val(b))
+#define pte_page(x)            pfn_to_page(pte_pfn(x))
+#define pte_none(x)            (!pte_val(x))
+#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))
+
+/* M32R_FIXME : PTE_FILE_MAX_BITS, pte_to_pgoff, pgoff_to_pte */
+#define PTE_FILE_MAX_BITS      31
+#define pte_to_pgoff(pte)      (pte_val(pte) >> 1)
+#define pgoff_to_pte(off)      ((pte_t) { ((off) << 1) | _PAGE_FILE })
+
+#endif /* _ASM_M32R_PGTABLE_2LEVEL_H */
+
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
new file mode 100644 (file)
index 0000000..8894d84
--- /dev/null
@@ -0,0 +1,422 @@
+#ifndef _ASM_M32R_PGTABLE_H
+#define _ASM_M32R_PGTABLE_H
+
+/* $Id$ */
+
+/*
+ * The Linux memory management assumes a three-level page table setup. On
+ * the M32R, we use that, but "fold" the mid level into the top-level page
+ * table, so that we physically have the same two-level page table as the
+ * M32R mmu expects.
+ *
+ * This file contains the functions and defines necessary to modify and use
+ * the M32R page table tree.
+ */
+
+/* CAUTION!: If you change macro definitions in this file, you might have to
+ * change arch/m32r/mmu.S manually.
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/addrspace.h>
+#include <asm/bitops.h>
+#include <asm/page.h>
+
+extern pgd_t swapper_pg_dir[1024];
+extern void paging_init(void);
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[1024];
+#define ZERO_PAGE(vaddr)       (virt_to_page(empty_zero_page))
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * The Linux x86 paging architecture is 'compile-time dual-mode', it
+ * implements both the traditional 2-level x86 page tables and the
+ * newer 3-level PAE-mode page tables.
+ */
+#ifndef __ASSEMBLY__
+#include <asm/pgtable-2level.h>
+#endif
+
+#define pgtable_cache_init()   do { } while (0)
+
+#define PMD_SIZE       (1UL << PMD_SHIFT)
+#define PMD_MASK       (~(PMD_SIZE - 1))
+#define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK     (~(PGDIR_SIZE - 1))
+
+#define USER_PTRS_PER_PGD      (TASK_SIZE / PGDIR_SIZE)
+#define FIRST_USER_PGD_NR      0
+
+#ifndef __ASSEMBLY__
+/* Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_START          KSEG2
+#define VMALLOC_END            KSEG3
+
+/*
+ * The 4MB page is guessing..  Detailed in the infamous "Chapter H"
+ * of the Pentium details, but assuming intel did the straightforward
+ * thing, this bit set in the page directory entry just means that
+ * the page directory entry points directly to a 4MB-aligned block of
+ * memory.
+ */
+
+/*
+ *     M32R TLB format
+ *
+ *     [0]    [1:19]           [20:23]       [24:31]
+ *     +-----------------------+----+-------------+
+ *     |          VPN          |0000|    ASID     |
+ *     +-----------------------+----+-------------+
+ *     +-+---------------------+----+-+---+-+-+-+-+
+ *     |0         PPN          |0000|N|AC |L|G|V| |
+ *     +-+---------------------+----+-+---+-+-+-+-+
+ *                                     RWX
+ */
+
+#define _PAGE_BIT_DIRTY                0       /* software */
+#define _PAGE_BIT_FILE         0       /* when !present: nonlinear file
+                                          mapping */
+#define _PAGE_BIT_PRESENT      1       /* Valid */
+#define _PAGE_BIT_GLOBAL       2       /* Global */
+#define _PAGE_BIT_LARGE                3       /* Large */
+#define _PAGE_BIT_EXEC         4       /* Execute */
+#define _PAGE_BIT_WRITE                5       /* Write */
+#define _PAGE_BIT_READ         6       /* Read */
+#define _PAGE_BIT_NONCACHABLE  7       /* Non cachable */
+#define _PAGE_BIT_USER         8       /* software */
+#define _PAGE_BIT_ACCESSED     9       /* software */
+
+#define _PAGE_DIRTY    \
+       (1UL << _PAGE_BIT_DIRTY)        /* software : page changed */
+#define _PAGE_FILE     \
+       (1UL << _PAGE_BIT_FILE)         /* when !present: nonlinear file
+                                          mapping */
+#define _PAGE_PRESENT  \
+       (1UL << _PAGE_BIT_PRESENT)      /* Valid : Page is Valid */
+#define _PAGE_GLOBAL   \
+       (1UL << _PAGE_BIT_GLOBAL)       /* Global */
+#define _PAGE_LARGE    \
+       (1UL << _PAGE_BIT_LARGE)        /* Large */
+#define _PAGE_EXEC     \
+       (1UL << _PAGE_BIT_EXEC)         /* Execute */
+#define _PAGE_WRITE    \
+       (1UL << _PAGE_BIT_WRITE)        /* Write */
+#define _PAGE_READ     \
+       (1UL << _PAGE_BIT_READ)         /* Read */
+#define _PAGE_NONCACHABLE      \
+       (1UL<<_PAGE_BIT_NONCACHABLE)    /* Non cachable */
+#define _PAGE_USER     \
+       (1UL << _PAGE_BIT_USER)         /* software : user space access
+                                          allowed */
+#define _PAGE_ACCESSED \
+       (1UL << _PAGE_BIT_ACCESSED)     /* software : page referenced */
+
+#define _PAGE_TABLE    \
+       ( _PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | _PAGE_USER \
+       | _PAGE_ACCESSED | _PAGE_DIRTY )
+#define _KERNPG_TABLE  \
+       ( _PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | _PAGE_ACCESSED \
+       | _PAGE_DIRTY )
+#define _PAGE_CHG_MASK \
+       ( PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY )
+
+#ifdef CONFIG_MMU
+#define PAGE_NONE      \
+       __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define PAGE_SHARED    \
+       __pgprot(_PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | _PAGE_USER \
+               | _PAGE_ACCESSED)
+#define PAGE_SHARED_X  \
+       __pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_WRITE | _PAGE_READ \
+               | _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_COPY      \
+       __pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_USER \
+               | _PAGE_ACCESSED)
+#define PAGE_COPY_X    \
+       __pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_USER \
+               | _PAGE_ACCESSED)
+#define PAGE_READONLY  \
+       __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_READONLY_X        \
+       __pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_USER \
+               | _PAGE_ACCESSED)
+
+#define __PAGE_KERNEL  \
+       ( _PAGE_PRESENT | _PAGE_EXEC | _PAGE_WRITE | _PAGE_READ | _PAGE_DIRTY \
+       | _PAGE_ACCESSED )
+#define __PAGE_KERNEL_RO       ( __PAGE_KERNEL & ~_PAGE_WRITE )
+#define __PAGE_KERNEL_NOCACHE  ( __PAGE_KERNEL | _PAGE_NONCACHABLE)
+
+#define MAKE_GLOBAL(x) __pgprot((x) | _PAGE_GLOBAL)
+
+#define PAGE_KERNEL            MAKE_GLOBAL(__PAGE_KERNEL)
+#define PAGE_KERNEL_RO         MAKE_GLOBAL(__PAGE_KERNEL_RO)
+#define PAGE_KERNEL_NOCACHE    MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
+
+#else
+#define PAGE_NONE               __pgprot(0)
+#define PAGE_SHARED             __pgprot(0)
+#define PAGE_SHARED_X           __pgprot(0)
+#define PAGE_COPY               __pgprot(0)
+#define PAGE_COPY_X             __pgprot(0)
+#define PAGE_READONLY           __pgprot(0)
+#define PAGE_READONLY_X         __pgprot(0)
+
+#define PAGE_KERNEL             __pgprot(0)
+#define PAGE_KERNEL_RO          __pgprot(0)
+#define PAGE_KERNEL_NOCACHE     __pgprot(0)
+#endif /* CONFIG_MMU */
+
+/*
+ * The i386 can't do page protection for execute, and considers that
+ * the same are read. Also, write permissions imply read permissions.
+ * This is the closest we can get..
+ */
+       /* rwx */
+#define __P000 PAGE_NONE
+#define __P001 PAGE_READONLY_X
+#define __P010 PAGE_COPY_X
+#define __P011 PAGE_COPY_X
+#define __P100 PAGE_READONLY
+#define __P101 PAGE_READONLY_X
+#define __P110 PAGE_COPY_X
+#define __P111 PAGE_COPY_X
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY_X
+#define __S010 PAGE_SHARED
+#define __S011 PAGE_SHARED_X
+#define __S100 PAGE_READONLY
+#define __S101 PAGE_READONLY_X
+#define __S110 PAGE_SHARED
+#define __S111 PAGE_SHARED_X
+
+/* page table for 0-4MB for everybody */
+
+#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
+#define pte_clear(xp)  do { set_pte(xp, __pte(0)); } while (0)
+
+#define pmd_none(x)    (!pmd_val(x))
+#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
+#define pmd_clear(xp)  do { set_pmd(xp, __pmd(0)); } while (0)
+#define        pmd_bad(x)      ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) \
+       != _KERNPG_TABLE)
+
+#define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT))
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+static __inline__ int pte_user(pte_t pte)
+{
+       return pte_val(pte) & _PAGE_USER;
+}
+
+static __inline__ int pte_read(pte_t pte)
+{
+       return pte_val(pte) & _PAGE_READ;
+}
+
+static __inline__ int pte_exec(pte_t pte)
+{
+       return pte_val(pte) & _PAGE_EXEC;
+}
+
+static __inline__ int pte_dirty(pte_t pte)
+{
+       return pte_val(pte) & _PAGE_DIRTY;
+}
+
+static __inline__ int pte_young(pte_t pte)
+{
+       return pte_val(pte) & _PAGE_ACCESSED;
+}
+
+static __inline__ int pte_write(pte_t pte)
+{
+       return pte_val(pte) & _PAGE_WRITE;
+}
+
+/*
+ * The following only works if pte_present() is not true.
+ */
+static __inline__ int pte_file(pte_t pte)
+{
+       return pte_val(pte) & _PAGE_FILE;
+}
+
+static __inline__ pte_t pte_rdprotect(pte_t pte)
+{
+       pte_val(pte) &= ~_PAGE_READ;
+       return pte;
+}
+
+static __inline__ pte_t pte_exprotect(pte_t pte)
+{
+       pte_val(pte) &= ~_PAGE_EXEC;
+       return pte;
+}
+
+static __inline__ pte_t pte_mkclean(pte_t pte)
+{
+       pte_val(pte) &= ~_PAGE_DIRTY;
+       return pte;
+}
+
+static __inline__ pte_t pte_mkold(pte_t pte)
+{
+       pte_val(pte) &= ~_PAGE_ACCESSED;return pte;}
+
+static __inline__ pte_t pte_wrprotect(pte_t pte)
+{
+       pte_val(pte) &= ~_PAGE_WRITE;
+       return pte;
+}
+
+static __inline__ pte_t pte_mkread(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_READ;
+       return pte;
+}
+
+static __inline__ pte_t pte_mkexec(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_EXEC;
+       return pte;
+}
+
+static __inline__ pte_t pte_mkdirty(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_DIRTY;
+       return pte;
+}
+
+static __inline__ pte_t pte_mkyoung(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_ACCESSED;
+       return pte;
+}
+
+static __inline__ pte_t pte_mkwrite(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_WRITE;
+       return pte;
+}
+
+static __inline__  int ptep_test_and_clear_dirty(pte_t *ptep)
+{
+       return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
+}
+
+static __inline__  int ptep_test_and_clear_young(pte_t *ptep)
+{
+       return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
+}
+
+static __inline__ void ptep_set_wrprotect(pte_t *ptep)
+{
+       clear_bit(_PAGE_BIT_WRITE, ptep);
+}
+
+static __inline__ void ptep_mkdirty(pte_t *ptep)
+{
+       set_bit(_PAGE_BIT_DIRTY, ptep);
+}
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define mk_pte(page, pgprot)   pfn_pte(page_to_pfn(page), pgprot)
+
+static __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+       set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) \
+               | pgprot_val(newprot)));
+
+       return pte;
+}
+
+#define page_pte(page) page_pte_prot(page, __pgprot(0))
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+
+static __inline__ void pmd_set(pmd_t * pmdp, pte_t * ptep)
+{
+       pmd_val(*pmdp) = (((unsigned long) ptep) & PAGE_MASK);
+}
+
+#define pmd_page_kernel(pmd)   \
+       ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+#ifndef CONFIG_DISCONTIGMEM
+#define pmd_page(pmd)  (mem_map + ((pmd_val(pmd) >> PAGE_SHIFT) - PFN_BASE))
+#endif /* !CONFIG_DISCONTIGMEM */
+
+/* to find an entry in a page-table-directory. */
+#define pgd_index(address)     \
+       (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
+
+#define pgd_offset(mm, address)        ((mm)->pgd + pgd_index(address))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address)  pgd_offset(&init_mm, address)
+
+#define pmd_index(address)     \
+       (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+
+#define pte_index(address)     \
+       (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir, address)        \
+       ((pte_t *)pmd_page_kernel(*(dir)) + pte_index(address))
+#define pte_offset_map(dir, address)   \
+       ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
+#define pte_offset_map_nested(dir, address)    pte_offset_map(dir, address)
+#define pte_unmap(pte)         do { } while (0)
+#define pte_unmap_nested(pte)  do { } while (0)
+
+/* Encode and de-code a swap entry */
+#define __swp_type(x)                  (((x).val >> 1) & 0x3f)
+#define __swp_offset(x)                        ((x).val >> 8)
+#define __swp_entry(type, offset)      \
+       ((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+#define __pte_to_swp_entry(pte)                ((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)          ((pte_t) { (x).val })
+
+#endif /* !__ASSEMBLY__ */
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define kern_addr_valid(addr)  (1)
+
+#define io_remap_page_range    remap_page_range
+
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+#define __HAVE_ARCH_PTEP_MKDIRTY
+#define __HAVE_ARCH_PTE_SAME
+#include <asm-generic/pgtable.h>
+
+#endif /* _ASM_M32R_PGTABLE_H */
+
diff --git a/include/asm-m32r/poll.h b/include/asm-m32r/poll.h
new file mode 100644 (file)
index 0000000..43b7acf
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _ASM_M32R_POLL_H
+#define _ASM_M32R_POLL_H
+
+/*
+ * poll(2) bit definitions.  Based on <asm-i386/poll.h>.
+ *
+ * Modified 2004
+ *      Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#define POLLIN         0x0001
+#define POLLPRI                0x0002
+#define POLLOUT                0x0004
+#define POLLERR                0x0008
+#define POLLHUP                0x0010
+#define POLLNVAL       0x0020
+
+#define POLLRDNORM     0x0040
+#define POLLRDBAND     0x0080
+#define POLLWRNORM     0x0100
+#define POLLWRBAND     0x0200
+#define POLLMSG                0x0400
+#define POLLREMOVE     0x1000
+
+struct pollfd {
+       int fd;
+       short events;
+       short revents;
+};
+
+#endif  /* _ASM_M32R_POLL_H */
diff --git a/include/asm-m32r/posix_types.h b/include/asm-m32r/posix_types.h
new file mode 100644 (file)
index 0000000..47e7e85
--- /dev/null
@@ -0,0 +1,126 @@
+#ifndef _ASM_M32R_POSIX_TYPES_H
+#define _ASM_M32R_POSIX_TYPES_H
+
+/* $Id$ */
+
+/* orig : i386, sh 2.4.18 */
+
+/*
+ * 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 short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+typedef unsigned int   __kernel_size_t;
+typedef int            __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
+static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+       unsigned long __tmp = __fd / __NFDBITS;
+       unsigned long __rem = __fd % __NFDBITS;
+       __fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
+}
+
+#undef __FD_CLR
+static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+       unsigned long __tmp = __fd / __NFDBITS;
+       unsigned long __rem = __fd % __NFDBITS;
+       __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
+}
+
+
+#undef __FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
+{
+       unsigned long __tmp = __fd / __NFDBITS;
+       unsigned long __rem = __fd % __NFDBITS;
+       return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
+ */
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
+{
+       unsigned long *__tmp = __p->fds_bits;
+       int __i;
+
+       if (__builtin_constant_p(__FDSET_LONGS)) {
+               switch (__FDSET_LONGS) {
+               case 16:
+                       __tmp[ 0] = 0; __tmp[ 1] = 0;
+                       __tmp[ 2] = 0; __tmp[ 3] = 0;
+                       __tmp[ 4] = 0; __tmp[ 5] = 0;
+                       __tmp[ 6] = 0; __tmp[ 7] = 0;
+                       __tmp[ 8] = 0; __tmp[ 9] = 0;
+                       __tmp[10] = 0; __tmp[11] = 0;
+                       __tmp[12] = 0; __tmp[13] = 0;
+                       __tmp[14] = 0; __tmp[15] = 0;
+                       return;
+
+               case 8:
+                       __tmp[ 0] = 0; __tmp[ 1] = 0;
+                       __tmp[ 2] = 0; __tmp[ 3] = 0;
+                       __tmp[ 4] = 0; __tmp[ 5] = 0;
+                       __tmp[ 6] = 0; __tmp[ 7] = 0;
+                       return;
+
+               case 4:
+                       __tmp[ 0] = 0; __tmp[ 1] = 0;
+                       __tmp[ 2] = 0; __tmp[ 3] = 0;
+                       return;
+               }
+       }
+       __i = __FDSET_LONGS;
+       while (__i) {
+               __i--;
+               *__tmp = 0;
+               __tmp++;
+       }
+}
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif  /* _ASM_M32R_POSIX_TYPES_H */
diff --git a/include/asm-m32r/processor.h b/include/asm-m32r/processor.h
new file mode 100644 (file)
index 0000000..24caabe
--- /dev/null
@@ -0,0 +1,157 @@
+#ifndef _ASM_M32R_PROCESSOR_H
+#define _ASM_M32R_PROCESSOR_H
+
+/* $Id$ */
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001  by Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ */
+
+/*
+ * include/asm-m32r/processor.h
+ *
+ * Copyright (C) 1994 Linus Torvalds
+ */
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <asm/cache.h>
+#include <asm/ptrace.h>  /* pt_regs */
+
+#include <asm/cachectl.h>
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+/*
+ *  CPU type and hardware bug flags. Kept separately for each CPU.
+ *  Members of this structure are referenced in head.S, so think twice
+ *  before touching them. [mj]
+ */
+
+struct cpuinfo_m32r {
+       unsigned long pgtable_cache_sz;
+       unsigned long cpu_clock;
+       unsigned long bus_clock;
+       unsigned long timer_divide;
+       unsigned long loops_per_jiffy;
+};
+
+/*
+ * capabilities of CPUs
+ */
+
+extern struct cpuinfo_m32r boot_cpu_data;
+
+#ifdef CONFIG_SMP
+extern struct cpuinfo_m32r cpu_data[];
+#define current_cpu_data cpu_data[smp_processor_id()]
+#else
+#define cpu_data &boot_cpu_data
+#define current_cpu_data boot_cpu_data
+#endif
+
+/*
+ * User space process size: 2GB (default).
+ */
+#ifdef CONFIG_MMU
+#define TASK_SIZE  (0x80000000UL)
+#else
+#define TASK_SIZE  (0x00400000UL)
+#endif
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE     PAGE_ALIGN(TASK_SIZE / 3)
+
+typedef struct {
+       unsigned long seg;
+} mm_segment_t;
+
+struct debug_trap {
+       int nr_trap;
+       unsigned long   addr;
+       unsigned long   insn;
+};
+
+struct thread_struct {
+       unsigned long address;
+       unsigned long trap_no;          /* Trap number  */
+       unsigned long error_code;       /* Error code of trap */
+       unsigned long lr;               /* saved pc */
+       unsigned long sp;               /* user stack pointer */
+       struct debug_trap debug_trap;
+};
+
+#define INIT_SP        (sizeof(init_stack) + (unsigned long) &init_stack)
+
+#define INIT_THREAD    {       \
+       .sp = INIT_SP,          \
+}
+
+/*
+ * Do necessary setup to start up a newly executed thread.
+ */
+
+/* User process Backup PSW */
+#define USERPS_BPSW (M32R_PSW_BSM|M32R_PSW_BIE|M32R_PSW_BPM)
+
+#define start_thread(regs, new_pc, new_spu)                            \
+       do {                                                            \
+               set_fs(USER_DS);                                        \
+               regs->psw = (regs->psw | USERPS_BPSW) & 0x0000FFFFUL;   \
+               regs->bpc = new_pc;                                     \
+               regs->spu = new_spu;                                    \
+       } while (0)
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+struct mm_struct;
+
+/* Free all resources held by a thread. */
+extern void release_thread(struct task_struct *);
+
+#define prepare_to_copy(tsk)   do { } while (0)
+
+/*
+ * create a kernel thread without removing it from tasklists
+ */
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+/* Copy and release all segment info associated with a VM */
+extern void copy_segments(struct task_struct *p, struct mm_struct * mm);
+extern void release_segments(struct mm_struct * mm);
+
+extern unsigned long thread_saved_pc(struct task_struct *);
+
+/* Copy and release all segment info associated with a VM */
+#define copy_segments(p, mm)  do { } while (0)
+#define release_segments(mm)  do { } while (0)
+
+unsigned long get_wchan(struct task_struct *p);
+#define KSTK_EIP(tsk)  ((tsk)->thread.lr)
+#define KSTK_ESP(tsk)  ((tsk)->thread.sp)
+
+#define THREAD_SIZE (2*PAGE_SIZE)
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static __inline__ void rep_nop(void)
+{
+       __asm__ __volatile__(
+               "nop \n\t"
+               "nop \n\t"
+               :
+               :
+               : "memory");
+}
+
+#define cpu_relax()     rep_nop()
+
+#endif /* _ASM_M32R_PROCESSOR_H */
diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h
new file mode 100644 (file)
index 0000000..9764171
--- /dev/null
@@ -0,0 +1,165 @@
+#ifndef _ASM_M32R_PTRACE_H
+#define _ASM_M32R_PTRACE_H
+
+/*
+ * linux/include/asm-m32r/ptrace.h
+ *
+ * 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.
+ *
+ * M32R version:
+ *   Copyright (C) 2001-2002, 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>          /* M32R_PSW_BSM, M32R_PSW_BPM */
+
+/* 0 - 13 are integer registers (general purpose registers).  */
+#define PT_R4          0
+#define PT_R5          1
+#define PT_R6          2
+#define PT_REGS        3
+#define PT_R0          4
+#define PT_R1          5
+#define PT_R2          6
+#define PT_R3          7
+#define PT_R7          8
+#define PT_R8          9
+#define PT_R9          10
+#define PT_R10         11
+#define PT_R11         12
+#define PT_R12         13
+#define PT_SYSCNR      14
+#define PT_R13         PT_FP
+#define PT_R14         PT_LR
+#define PT_R15         PT_SP
+
+/* processor status and miscellaneous context registers.  */
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+#define PT_ACC0H       15
+#define PT_ACC0L       16
+#define PT_ACC1H       17
+#define PT_ACC1L       18
+#define PT_ACCH                PT_ACC0H
+#define PT_ACCL                PT_ACC0L
+#define PT_PSW         19
+#define PT_BPC         20
+#define PT_BBPSW       21
+#define PT_BBPC                22
+#define PT_SPU         23
+#define PT_FP          24
+#define PT_LR          25
+#define PT_SPI         26
+#define PT_ORIGR0      27
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define PT_ACCH                15
+#define PT_ACCL                16
+#define PT_PSW         17
+#define PT_BPC         18
+#define PT_BBPSW       19
+#define PT_BBPC                20
+#define PT_SPU         21
+#define PT_FP          22
+#define PT_LR          23
+#define PT_SPI         24
+#define PT_ORIGR0      25
+#else
+#error unknown isa conifiguration
+#endif
+
+/* virtual pt_reg entry for gdb */
+#define PT_PC          30
+#define PT_CBR         31
+#define PT_EVB         32
+
+
+/* Control registers.  */
+#define SPR_CR0 PT_PSW
+#define SPR_CR1 PT_CBR         /* read only */
+#define SPR_CR2 PT_SPI
+#define SPR_CR3 PT_SPU
+#define SPR_CR4
+#define SPR_CR5 PT_EVB         /* part of M32R/E, M32R/I core only */
+#define SPR_CR6 PT_BPC
+#define SPR_CR7
+#define SPR_CR8 PT_BBPSW
+#define SPR_CR9
+#define SPR_CR10
+#define SPR_CR11
+#define SPR_CR12
+#define SPR_CR13 PT_WR
+#define SPR_CR14 PT_BBPC
+#define SPR_CR15
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+struct pt_regs {
+       /* Saved main processor registers. */
+       unsigned long r4;
+       unsigned long r5;
+       unsigned long r6;
+       struct pt_regs *pt_regs;
+       unsigned long r0;
+       unsigned long r1;
+       unsigned long r2;
+       unsigned long r3;
+       unsigned long r7;
+       unsigned long r8;
+       unsigned long r9;
+       unsigned long r10;
+       unsigned long r11;
+       unsigned long r12;
+       long syscall_nr;
+
+       /* Saved main processor status and miscellaneous context registers. */
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+       unsigned long acc0h;
+       unsigned long acc0l;
+       unsigned long acc1h;
+       unsigned long acc1l;
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+       unsigned long acch;
+       unsigned long accl;
+#else
+#error unknown isa configuration
+#endif
+       unsigned long psw;
+       unsigned long bpc;              /* saved PC for TRAP syscalls */
+       unsigned long bbpsw;
+       unsigned long bbpc;
+       unsigned long spu;              /* saved user stack */
+       unsigned long fp;
+       unsigned long lr;               /* saved PC for JL syscalls */
+       unsigned long spi;              /* saved kernel stack */
+       unsigned long orig_r0;
+};
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS         12
+#define PTRACE_SETREGS         13
+
+#define PTRACE_OLDSETOPTIONS   21
+
+/* options set using PTRACE_SETOPTIONS */
+#define PTRACE_O_TRACESYSGOOD  0x00000001
+
+#ifdef __KERNEL__
+#if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2)
+#define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0)
+#elif defined(CONFIG_ISA_M32R)
+#define user_mode(regs) ((M32R_PSW_BSM & (regs)->psw) != 0)
+#else
+#error unknown isa configuration
+#endif
+
+#define instruction_pointer(regs) ((regs)->bpc)
+#define profile_pc(regs) instruction_pointer(regs)
+
+extern void show_regs(struct pt_regs *);
+
+extern void withdraw_debug_trap(struct pt_regs *regs);
+
+#endif /* __KERNEL */
+
+#endif /* _ASM_M32R_PTRACE_H */
diff --git a/include/asm-m32r/resource.h b/include/asm-m32r/resource.h
new file mode 100644 (file)
index 0000000..69ece06
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef _ASM_M32R_RESOURCE_H
+#define _ASM_M32R_RESOURCE_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * Resource limits
+ */
+
+#define RLIMIT_CPU     0               /* CPU time in ms */
+#define RLIMIT_FSIZE   1               /* Maximum filesize */
+#define RLIMIT_DATA    2               /* max data size */
+#define RLIMIT_STACK   3               /* max stack size */
+#define RLIMIT_CORE    4               /* max core file size */
+#define RLIMIT_RSS     5               /* max resident set size */
+#define RLIMIT_NPROC   6               /* max number of processes */
+#define RLIMIT_NOFILE  7               /* max number of open files */
+#define RLIMIT_MEMLOCK 8               /* max locked-in-memory address space */
+#define RLIMIT_AS      9               /* address space limit */
+#define RLIMIT_LOCKS   10              /* maximum file locks held */
+#define RLIMIT_SIGPENDING 11           /* max number of pending signals */
+#define RLIMIT_MSGQUEUE        12              /* maximum bytes in POSIX mqueues */
+
+#define RLIM_NLIMITS   13
+
+/*
+ * SuS says limits have to be unsigned.
+ * Which makes a ton more sense anyway.
+ */
+#define RLIM_INFINITY  (~0UL)
+
+#ifdef __KERNEL__
+
+#define INIT_RLIMITS                                   \
+{                                                      \
+       { RLIM_INFINITY, RLIM_INFINITY },               \
+       { RLIM_INFINITY, RLIM_INFINITY },               \
+       { RLIM_INFINITY, RLIM_INFINITY },               \
+       {      _STK_LIM, RLIM_INFINITY },               \
+       {             0, RLIM_INFINITY },               \
+       { RLIM_INFINITY, RLIM_INFINITY },               \
+       {             0,             0 },               \
+       {      INR_OPEN,     INR_OPEN  },               \
+       { MLOCK_LIMIT,   MLOCK_LIMIT   },               \
+       { RLIM_INFINITY, RLIM_INFINITY },               \
+       { RLIM_INFINITY, RLIM_INFINITY },               \
+       { MAX_SIGPENDING, MAX_SIGPENDING },             \
+       { MQ_BYTES_MAX, MQ_BYTES_MAX },                 \
+}
+
+#endif /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_RESOURCE_H */
diff --git a/include/asm-m32r/rtc.h b/include/asm-m32r/rtc.h
new file mode 100644 (file)
index 0000000..3696bb1
--- /dev/null
@@ -0,0 +1,70 @@
+/* $Id: rtc.h,v 1.1.1.1 2004/03/25 04:29:22 hitoshiy Exp $ */
+
+#ifndef __RTC_H__
+#define __RTC_H__
+
+
+#include <linux/config.h>
+
+   /* Dallas DS1302 clock/calendar register numbers. */
+#  define RTC_SECONDS      0
+#  define RTC_MINUTES      1
+#  define RTC_HOURS        2
+#  define RTC_DAY_OF_MONTH 3
+#  define RTC_MONTH        4
+#  define RTC_WEEKDAY      5
+#  define RTC_YEAR         6
+#  define RTC_CONTROL      7
+
+   /* Bits in CONTROL register. */
+#  define RTC_CONTROL_WRITEPROTECT     0x80
+#  define RTC_TRICKLECHARGER           8
+
+  /* Bits in TRICKLECHARGER register TCS TCS TCS TCS DS DS RS RS. */
+#  define RTC_TCR_PATTERN      0xA0    /* 1010xxxx */
+#  define RTC_TCR_1DIOD        0x04    /* xxxx01xx */
+#  define RTC_TCR_2DIOD        0x08    /* xxxx10xx */
+#  define RTC_TCR_DISABLED     0x00    /* xxxxxx00 Disabled */
+#  define RTC_TCR_2KOHM        0x01    /* xxxxxx01 2KOhm */
+#  define RTC_TCR_4KOHM        0x02    /* xxxxxx10 4kOhm */
+#  define RTC_TCR_8KOHM        0x03    /* xxxxxx11 8kOhm */
+
+#ifdef CONFIG_M32700UT_DS1302
+extern unsigned char ds1302_readreg(int reg);
+extern void ds1302_writereg(int reg, unsigned char val);
+extern int ds1302_init(void);
+#  define CMOS_READ(x) ds1302_readreg(x)
+#  define CMOS_WRITE(val,reg) ds1302_writereg(reg,val)
+#  define RTC_INIT() ds1302_init()
+#else
+  /* No RTC configured so we shouldn't try to access any. */
+#  define CMOS_READ(x) 42
+#  define CMOS_WRITE(x,y)
+#  define RTC_INIT() (-1)
+#endif
+
+/*
+ * The struct used to pass data via the following ioctl. Similar to the
+ * struct tm in <time.h>, but it needs to be here so that the kernel
+ * source is self contained, allowing cross-compiles, etc. etc.
+ */
+struct rtc_time {
+       int tm_sec;
+       int tm_min;
+       int tm_hour;
+       int tm_mday;
+       int tm_mon;
+       int tm_year;
+       int tm_wday;
+       int tm_yday;
+       int tm_isdst;
+};
+
+/* ioctl() calls that are permitted to the /dev/rtc interface. */
+#define RTC_MAGIC 'p'
+#define RTC_RD_TIME            _IOR(RTC_MAGIC, 0x09, struct rtc_time)  /* Read RTC time. */
+#define RTC_SET_TIME           _IOW(RTC_MAGIC, 0x0a, struct rtc_time)  /* Set RTC time. */
+#define RTC_SET_CHARGE         _IOW(RTC_MAGIC, 0x0b, int)
+#define RTC_MAX_IOCTL 0x0b
+
+#endif /* __RTC_H__ */
diff --git a/include/asm-m32r/scatterlist.h b/include/asm-m32r/scatterlist.h
new file mode 100644 (file)
index 0000000..09a10e4
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _ASM_M32R_SCATTERLIST_H
+#define _ASM_M32R_SCATTERLIST_H
+
+/* $Id$ */
+
+struct scatterlist {
+    char *  address;    /* Location data is to be transferred to, NULL for
+                         * highmem page */
+    struct page * page; /* Location for highmem page, if any */
+    unsigned int offset;/* for highmem, page offset */
+
+    dma_addr_t dma_address;
+    unsigned int length;
+};
+
+#define ISA_DMA_THRESHOLD (0x1fffffff)
+
+#endif /* _ASM_M32R_SCATTERLIST_H */
diff --git a/include/asm-m32r/sections.h b/include/asm-m32r/sections.h
new file mode 100644 (file)
index 0000000..6b969e5
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _M32R_SECTIONS_H
+#define _M32R_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+#endif /* _M32R_SECTIONS_H */
+
diff --git a/include/asm-m32r/segment.h b/include/asm-m32r/segment.h
new file mode 100644 (file)
index 0000000..e45db68
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _ASM_M32R_SEGMENT_H
+#define _ASM_M32R_SEGMENT_H
+
+/* $Id$ */
+
+/* orig : i386 (2.4.18) */
+
+#define __KERNEL_CS    0x10
+#define __KERNEL_DS    0x18
+
+#define __USER_CS      0x23
+#define __USER_DS      0x2B
+
+#endif  /* _ASM_M32R_SEGMENT_H */
diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
new file mode 100644 (file)
index 0000000..5aca12f
--- /dev/null
@@ -0,0 +1,214 @@
+#ifndef _ASM_M32R_SEMAPHORE_H
+#define _ASM_M32R_SEMAPHORE_H
+
+#include <linux/linkage.h>
+
+#ifdef __KERNEL__
+
+/*
+ * SMP- and interrupt-safe semaphores..
+ *
+ * Copyright (C) 1996  Linus Torvalds
+ * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/config.h>
+#include <linux/wait.h>
+#include <linux/rwsem.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+#undef LOAD
+#undef STORE
+#ifdef CONFIG_SMP
+#define LOAD   "lock"
+#define STORE  "unlock"
+#else
+#define LOAD   "ld"
+#define STORE  "st"
+#endif
+
+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 __MUTEX_INITIALIZER(name) \
+       __SEMAPHORE_INITIALIZER(name,1)
+
+#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);
+ *
+ * i'd rather use the more flexible initialization above, but sadly
+ * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
+ */
+       atomic_set(&sem->count, val);
+       sem->sleepers = 0;
+       init_waitqueue_head(&sem->wait);
+}
+
+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_failed(void /* special register calling convention */);
+asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
+asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+asmlinkage void __up_wakeup(void /* special register calling convention */);
+
+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);
+
+/*
+ * Atomically decrement the semaphore's count.  If it goes negative,
+ * block the calling thread in the TASK_UNINTERRUPTIBLE state.
+ */
+static inline void down(struct semaphore * sem)
+{
+       unsigned long flags;
+       long count;
+
+       might_sleep();
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# down                         \n\t"
+               DCACHE_CLEAR("%0", "r4", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "addi   %0, #-1;                \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (count)
+               : "r" (&sem->count)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+
+       if (unlikely(count < 0))
+               __down(sem);
+}
+
+/*
+ * Interruptible try to acquire a semaphore.  If we obtained
+ * it, return zero.  If we were interrupted, returns -EINTR
+ */
+static inline int down_interruptible(struct semaphore * sem)
+{
+       unsigned long flags;
+       long count;
+       int result = 0;
+
+       might_sleep();
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# down_interruptible           \n\t"
+               DCACHE_CLEAR("%0", "r4", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "addi   %0, #-1;                \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (count)
+               : "r" (&sem->count)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+
+       if (unlikely(count < 0))
+               result = __down_interruptible(sem);
+
+       return result;
+}
+
+/*
+ * Non-blockingly attempt to down() a semaphore.
+ * Returns zero if we acquired it
+ */
+static inline int down_trylock(struct semaphore * sem)
+{
+       unsigned long flags;
+       long count;
+       int result = 0;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# down_trylock                 \n\t"
+               DCACHE_CLEAR("%0", "r4", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "addi   %0, #-1;                \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (count)
+               : "r" (&sem->count)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+
+       if (unlikely(count < 0))
+               result = __down_trylock(sem);
+
+       return result;
+}
+
+/*
+ * 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)
+{
+       unsigned long flags;
+       long count;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# up                           \n\t"
+               DCACHE_CLEAR("%0", "r4", "%1")
+               LOAD"   %0, @%1;                \n\t"
+               "addi   %0, #1;                 \n\t"
+               STORE"  %0, @%1;                \n\t"
+               : "=&r" (count)
+               : "r" (&sem->count)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+
+       if (unlikely(count <= 0))
+               __up(sem);
+}
+
+#endif  /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_SEMAPHORE_H */
diff --git a/include/asm-m32r/sembuf.h b/include/asm-m32r/sembuf.h
new file mode 100644 (file)
index 0000000..e69018e
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _ASM_M32R_SEMBUF_H
+#define _ASM_M32R_SEMBUF_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * The semid64_ds structure for m32r 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 /* _ASM_M32R_SEMBUF_H */
diff --git a/include/asm-m32r/serial.h b/include/asm-m32r/serial.h
new file mode 100644 (file)
index 0000000..bf14299
--- /dev/null
@@ -0,0 +1,151 @@
+#ifndef _ASM_M32R_SERIAL_H
+#define _ASM_M32R_SERIAL_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * include/asm-m32r/serial.h
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD ( 1843200 / 16 )
+
+/* Standard COM flags (except for COM4, because of the 8514 problem) */
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
+#endif
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define FOURPORT_FLAGS ASYNC_FOURPORT
+#define ACCENT_FLAGS 0
+#define BOCA_FLAGS 0
+#define HUB6_FLAGS 0
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE
+#endif
+
+#define MCA_COM_FLAGS  (STD_COM_FLAGS|ASYNC_BOOT_ONLYMCA)
+
+/*
+ * The following define the access methods for the HUB6 card. All
+ * access is through two ports for all 24 possible chips. The card is
+ * selected through the high 2 bits, the port on that card with the
+ * "middle" 3 bits, and the register on that port with the bottom
+ * 3 bits.
+ *
+ * While the access port and interrupt is configurable, the default
+ * port locations are 0x302 for the port control register, and 0x303
+ * for the data read/write register. Normally, the interrupt is at irq3
+ * but can be anything from 3 to 7 inclusive. Note that using 3 will
+ * require disabling com2.
+ */
+
+#define C_P(card,port) (((card)<<6|(port)<<3) + 1)
+
+#define STD_SERIAL_PORT_DEFNS                  \
+       /* UART CLK   PORT IRQ     FLAGS        */                      \
+       { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },      /* ttyS0 */     \
+       { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },      /* ttyS1 */     \
+       { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },      /* ttyS2 */     \
+       { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },     /* ttyS3 */
+
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define EXTRA_SERIAL_PORT_DEFNS                        \
+       { 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS },     /* ttyS4 */     \
+       { 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS },     /* ttyS5 */     \
+       { 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS },     /* ttyS6 */     \
+       { 0, BASE_BAUD, 0x1B8, 9, FOURPORT_FLAGS },     /* ttyS7 */     \
+       { 0, BASE_BAUD, 0x2A0, 5, FOURPORT_FLAGS },     /* ttyS8 */     \
+       { 0, BASE_BAUD, 0x2A8, 5, FOURPORT_FLAGS },     /* ttyS9 */     \
+       { 0, BASE_BAUD, 0x2B0, 5, FOURPORT_FLAGS },     /* ttyS10 */    \
+       { 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS },     /* ttyS11 */    \
+       { 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS },       /* ttyS12 */    \
+       { 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS },       /* ttyS13 */    \
+       { 0, BASE_BAUD, 0x000, 0, 0 },  /* ttyS14 (spare) */            \
+       { 0, BASE_BAUD, 0x000, 0, 0 },  /* ttyS15 (spare) */            \
+       { 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS },        /* ttyS16 */    \
+       { 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS },        /* ttyS17 */    \
+       { 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS },        /* ttyS18 */    \
+       { 0, BASE_BAUD, 0x118, 12, BOCA_FLAGS },        /* ttyS19 */    \
+       { 0, BASE_BAUD, 0x120, 12, BOCA_FLAGS },        /* ttyS20 */    \
+       { 0, BASE_BAUD, 0x128, 12, BOCA_FLAGS },        /* ttyS21 */    \
+       { 0, BASE_BAUD, 0x130, 12, BOCA_FLAGS },        /* ttyS22 */    \
+       { 0, BASE_BAUD, 0x138, 12, BOCA_FLAGS },        /* ttyS23 */    \
+       { 0, BASE_BAUD, 0x140, 12, BOCA_FLAGS },        /* ttyS24 */    \
+       { 0, BASE_BAUD, 0x148, 12, BOCA_FLAGS },        /* ttyS25 */    \
+       { 0, BASE_BAUD, 0x150, 12, BOCA_FLAGS },        /* ttyS26 */    \
+       { 0, BASE_BAUD, 0x158, 12, BOCA_FLAGS },        /* ttyS27 */    \
+       { 0, BASE_BAUD, 0x160, 12, BOCA_FLAGS },        /* ttyS28 */    \
+       { 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS },        /* ttyS29 */    \
+       { 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS },        /* ttyS30 */    \
+       { 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS },        /* ttyS31 */
+#else
+#define EXTRA_SERIAL_PORT_DEFNS
+#endif
+
+/* You can have up to four HUB6's in the system, but I've only
+ * included two cards here for a total of twelve ports.
+ */
+#if (defined(CONFIG_HUB6) && defined(CONFIG_SERIAL_MANY_PORTS))
+#define HUB6_SERIAL_PORT_DFNS          \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,0) },  /* ttyS32 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,1) },  /* ttyS33 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,2) },  /* ttyS34 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,3) },  /* ttyS35 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,4) },  /* ttyS36 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,5) },  /* ttyS37 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,0) },  /* ttyS38 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,1) },  /* ttyS39 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,2) },  /* ttyS40 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,3) },  /* ttyS41 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) },  /* ttyS42 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) },  /* ttyS43 */
+#else
+#define HUB6_SERIAL_PORT_DFNS
+#endif
+
+#ifdef CONFIG_MCA
+#define MCA_SERIAL_PORT_DFNS                   \
+       { 0, BASE_BAUD, 0x3220, 3, MCA_COM_FLAGS },     \
+       { 0, BASE_BAUD, 0x3228, 3, MCA_COM_FLAGS },     \
+       { 0, BASE_BAUD, 0x4220, 3, MCA_COM_FLAGS },     \
+       { 0, BASE_BAUD, 0x4228, 3, MCA_COM_FLAGS },     \
+       { 0, BASE_BAUD, 0x5220, 3, MCA_COM_FLAGS },     \
+       { 0, BASE_BAUD, 0x5228, 3, MCA_COM_FLAGS },
+#else
+#define MCA_SERIAL_PORT_DFNS
+#endif
+
+#ifndef CONFIG_PLAT_USRV
+#define SERIAL_PORT_DFNS               \
+       STD_SERIAL_PORT_DEFNS           \
+       EXTRA_SERIAL_PORT_DEFNS         \
+       HUB6_SERIAL_PORT_DFNS           \
+       MCA_SERIAL_PORT_DFNS
+
+#else  /* CONFIG_PLAT_USRV */
+
+#define SERIAL_PORT_DFNS               \
+       /* UART CLK   PORT IRQ     FLAGS        */                      \
+       { 0, BASE_BAUD, 0x3F8, PLD_IRQ_UART0, STD_COM_FLAGS },  /* ttyS0 */     \
+       { 0, BASE_BAUD, 0x2F8, PLD_IRQ_UART1, STD_COM_FLAGS },  /* ttyS1 */
+#endif /* CONFIG_PLAT_USRV */
+
+#endif  /* _ASM_M32R_SERIAL_H */
diff --git a/include/asm-m32r/setup.h b/include/asm-m32r/setup.h
new file mode 100644 (file)
index 0000000..5f028dc
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+#define PARAM                  ((unsigned char *)empty_zero_page)
+
+#define MOUNT_ROOT_RDONLY      (*(unsigned long *) (PARAM+0x000))
+#define RAMDISK_FLAGS          (*(unsigned long *) (PARAM+0x004))
+#define ORIG_ROOT_DEV          (*(unsigned long *) (PARAM+0x008))
+#define LOADER_TYPE            (*(unsigned long *) (PARAM+0x00c))
+#define INITRD_START           (*(unsigned long *) (PARAM+0x010))
+#define INITRD_SIZE            (*(unsigned long *) (PARAM+0x014))
+
+#define M32R_CPUCLK            (*(unsigned long *) (PARAM+0x018))
+#define M32R_BUSCLK            (*(unsigned long *) (PARAM+0x01c))
+#define M32R_TIMER_DIVIDE      (*(unsigned long *) (PARAM+0x020))
+
+#define COMMAND_LINE           ((char *) (PARAM+0x100))
+
+#define SCREEN_INFO            (*(struct screen_info *) (PARAM+0x200))
+
+#define COMMAND_LINE_SIZE      (512)
+
+#define RAMDISK_IMAGE_START_MASK       (0x07FF)
+#define RAMDISK_PROMPT_FLAG            (0x8000)
+#define RAMDISK_LOAD_FLAG              (0x4000)
+
+#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x)    ((x) << PAGE_SHIFT)
+
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+
diff --git a/include/asm-m32r/shmbuf.h b/include/asm-m32r/shmbuf.h
new file mode 100644 (file)
index 0000000..b84e897
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _ASM_M32R_SHMBUF_H
+#define _ASM_M32R_SHMBUF_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * The shmid64_ds structure for M32R 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 /* _ASM_M32R_SHMBUF_H */
diff --git a/include/asm-m32r/shmparam.h b/include/asm-m32r/shmparam.h
new file mode 100644 (file)
index 0000000..db0019b
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _ASM_M32R_SHMPARAM_H
+#define _ASM_M32R_SHMPARAM_H
+
+/* $Id$ */
+
+#define        SHMLBA PAGE_SIZE                 /* attach addr a multiple of this */
+
+#endif /* _ASM_M32R_SHMPARAM_H */
diff --git a/include/asm-m32r/sigcontext.h b/include/asm-m32r/sigcontext.h
new file mode 100644 (file)
index 0000000..c233e2d
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _ASM_M32R_SIGCONTEXT_H
+#define _ASM_M32R_SIGCONTEXT_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+
+struct sigcontext {
+       /* CPU registers */
+       /* Saved main processor registers. */
+       unsigned long sc_r4;
+       unsigned long sc_r5;
+       unsigned long sc_r6;
+       struct pt_regs *sc_pt_regs;
+       unsigned long sc_r0;
+       unsigned long sc_r1;
+       unsigned long sc_r2;
+       unsigned long sc_r3;
+       unsigned long sc_r7;
+       unsigned long sc_r8;
+       unsigned long sc_r9;
+       unsigned long sc_r10;
+       unsigned long sc_r11;
+       unsigned long sc_r12;
+
+       /* Saved main processor status and miscellaneous context registers. */
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+       unsigned long sc_acc0h;
+       unsigned long sc_acc0l;
+       unsigned long sc_acc1h;
+       unsigned long sc_acc1l;
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+       unsigned long sc_acch;
+       unsigned long sc_accl;
+#else
+#error unknown isa configuration
+#endif
+       unsigned long sc_psw;
+       unsigned long sc_bpc;           /* saved PC for TRAP syscalls */
+       unsigned long sc_bbpsw;
+       unsigned long sc_bbpc;
+       unsigned long sc_spu;           /* saved user stack */
+       unsigned long sc_fp;
+       unsigned long sc_lr;            /* saved PC for JL syscalls */
+       unsigned long sc_spi;           /* saved kernel stack */
+
+       unsigned long   oldmask;
+};
+
+#endif  /* _ASM_M32R_SIGCONTEXT_H */
diff --git a/include/asm-m32r/siginfo.h b/include/asm-m32r/siginfo.h
new file mode 100644 (file)
index 0000000..482202f
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _M32R_SIGINFO_H
+#define _M32R_SIGINFO_H
+
+/* $Id$ */
+
+#include <asm-generic/siginfo.h>
+
+#endif /* _M32R_SIGINFO_H */
diff --git a/include/asm-m32r/signal.h b/include/asm-m32r/signal.h
new file mode 100644 (file)
index 0000000..ce46eae
--- /dev/null
@@ -0,0 +1,200 @@
+#ifndef _ASM_M32R_SIGNAL_H
+#define _ASM_M32R_SIGNAL_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+#include <linux/types.h>
+#include <linux/linkage.h>
+#include <linux/time.h>
+#include <linux/compiler.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   0x00000001u
+#define SA_NOCLDWAIT   0x00000002u
+#define SA_SIGINFO     0x00000004u
+#define SA_ONSTACK     0x08000000u
+#define SA_RESTART     0x10000000u
+#define SA_NODEFER     0x40000000u
+#define SA_RESETHAND   0x80000000u
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+#define SA_INTERRUPT   0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER    0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    2048
+#define SIGSTKSZ       8192
+
+#ifdef __KERNEL__
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE               SA_ONESHOT
+#define SA_SAMPLE_RANDOM       SA_RESTART
+#define SA_SHIRQ               0x04000000
+#endif
+
+#define SIG_BLOCK          0   /* for blocking signals */
+#define SIG_UNBLOCK        1   /* for unblocking signals */
+#define SIG_SETMASK        2   /* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void __signalfn_t(int);
+typedef __signalfn_t __user *__sighandler_t;
+
+typedef void __restorefn_t(void);
+typedef __restorefn_t __user *__sigrestore_t;
+
+#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
+#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
+#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
+
+#ifdef __KERNEL__
+struct old_sigaction {
+       __sighandler_t sa_handler;
+       old_sigset_t sa_mask;
+       unsigned long sa_flags;
+       __sigrestore_t sa_restorer;
+};
+
+struct sigaction {
+       __sighandler_t sa_handler;
+       unsigned long sa_flags;
+       __sigrestore_t sa_restorer;
+       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 __user *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+
+#undef __HAVE_ARCH_SIG_BITOPS
+
+struct pt_regs;
+extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
+
+#define ptrace_signal_deliver(regs, cookie)    do { } while (0)
+
+#endif /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_SIGNAL_H */
diff --git a/include/asm-m32r/smp.h b/include/asm-m32r/smp.h
new file mode 100644 (file)
index 0000000..7857c8b
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef _ASM_M32R_SMP_H
+#define _ASM_M32R_SMP_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+#ifndef __ASSEMBLY__
+
+#include <linux/cpumask.h>
+#include <linux/spinlock.h>
+#include <linux/threads.h>
+#include <asm/m32r.h>
+
+#define PHYSID_ARRAY_SIZE       1
+
+struct physid_mask
+{
+       unsigned long mask[PHYSID_ARRAY_SIZE];
+};
+
+typedef struct physid_mask physid_mask_t;
+
+#define physid_set(physid, map)                 set_bit(physid, (map).mask)
+#define physid_clear(physid, map)               clear_bit(physid, (map).mask)
+#define physid_isset(physid, map)               test_bit(physid, (map).mask)
+#define physid_test_and_set(physid, map)        test_and_set_bit(physid, (map).mask)
+
+#define physids_and(dst, src1, src2)            bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+#define physids_or(dst, src1, src2)             bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+#define physids_clear(map)                      bitmap_zero((map).mask, MAX_APICS)
+#define physids_complement(dst, src)            bitmap_complement((dst).mask,(src).mask, MAX_APICS)
+#define physids_empty(map)                      bitmap_empty((map).mask, MAX_APICS)
+#define physids_equal(map1, map2)               bitmap_equal((map1).mask, (map2).mask, MAX_APICS)
+#define physids_weight(map)                     bitmap_weight((map).mask, MAX_APICS)
+#define physids_shift_right(d, s, n)            bitmap_shift_right((d).mask, (s).mask, n, MAX_APICS)
+#define physids_shift_left(d, s, n)             bitmap_shift_left((d).mask, (s).mask, n, MAX_APICS)
+#define physids_coerce(map)                     ((map).mask[0])
+
+#define physids_promote(physids)                                       \
+       ({                                                              \
+               physid_mask_t __physid_mask = PHYSID_MASK_NONE;         \
+               __physid_mask.mask[0] = physids;                        \
+               __physid_mask;                                          \
+       })
+
+#define physid_mask_of_physid(physid)                                  \
+       ({                                                              \
+               physid_mask_t __physid_mask = PHYSID_MASK_NONE;         \
+               physid_set(physid, __physid_mask);                      \
+               __physid_mask;                                          \
+       })
+
+#define PHYSID_MASK_ALL         { {[0 ... PHYSID_ARRAY_SIZE-1] = ~0UL} }
+#define PHYSID_MASK_NONE        { {[0 ... PHYSID_ARRAY_SIZE-1] = 0UL} }
+
+extern physid_mask_t phys_cpu_present_map;
+
+/*
+ * Some lowlevel functions might want to know about
+ * the real CPU ID <-> CPU # mapping.
+ */
+extern volatile int physid_2_cpu[NR_CPUS];
+extern volatile int cpu_2_physid[NR_CPUS];
+#define physid_to_cpu(physid)  physid_2_cpu[physid]
+#define cpu_to_physid(cpu_id)  cpu_2_physid[cpu_id]
+
+#define smp_processor_id()     (current_thread_info()->cpu)
+
+extern cpumask_t cpu_callout_map;
+#define cpu_possible_map cpu_callout_map
+
+static __inline__ int hard_smp_processor_id(void)
+{
+       return (int)*(volatile long *)M32R_CPUID_PORTL;
+}
+
+static __inline__ int cpu_logical_map(int cpu)
+{
+       return cpu;
+}
+
+static __inline__ int cpu_number_map(int cpu)
+{
+       return cpu;
+}
+
+static __inline__ unsigned int num_booting_cpus(void)
+{
+       return cpus_weight(cpu_callout_map);
+}
+
+extern void smp_send_timer(void);
+extern void calibrate_delay(void);
+extern unsigned long send_IPI_mask_phys(cpumask_t, int, int);
+
+#endif /* not __ASSEMBLY__ */
+
+#define NO_PROC_ID (0xff)      /* No processor magic marker */
+
+#define PROC_CHANGE_PENALTY    (15)    /* Schedule penalty */
+
+/*
+ * M32R-mp IPI
+ */
+#define RESCHEDULE_IPI         (M32R_IRQ_IPI0-M32R_IRQ_IPI0)
+#define INVALIDATE_TLB_IPI     (M32R_IRQ_IPI1-M32R_IRQ_IPI0)
+#define CALL_FUNCTION_IPI      (M32R_IRQ_IPI2-M32R_IRQ_IPI0)
+#define LOCAL_TIMER_IPI                (M32R_IRQ_IPI3-M32R_IRQ_IPI0)
+#define INVALIDATE_CACHE_IPI   (M32R_IRQ_IPI4-M32R_IRQ_IPI0)
+#define CPU_BOOT_IPI           (M32R_IRQ_IPI5-M32R_IRQ_IPI0)
+
+#define IPI_SHIFT      (0)
+#define NR_IPIS                (8)
+
+#endif /* CONFIG_SMP */
+
+#endif /* _ASM_M32R_SMP_H */
diff --git a/include/asm-m32r/socket.h b/include/asm-m32r/socket.h
new file mode 100644 (file)
index 0000000..159519d
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _ASM_M32R_SOCKET_H
+#define _ASM_M32R_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_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
+
+#endif /* _ASM_M32R_SOCKET_H */
diff --git a/include/asm-m32r/sockios.h b/include/asm-m32r/sockios.h
new file mode 100644 (file)
index 0000000..147a118
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _ASM_M32R_SOCKIOS_H
+#define _ASM_M32R_SOCKIOS_H
+
+/* $Id$ */
+
+/* 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 */
+
+#endif  /* _ASM_M32R_SOCKIOS_H */
diff --git a/include/asm-m32r/spinlock.h b/include/asm-m32r/spinlock.h
new file mode 100644 (file)
index 0000000..6fd012a
--- /dev/null
@@ -0,0 +1,382 @@
+#ifndef _ASM_M32R_SPINLOCK_H
+#define _ASM_M32R_SPINLOCK_H
+
+/*
+ *  linux/include/asm-m32r/spinlock.h
+ *
+ *  M32R version:
+ *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/config.h>      /* CONFIG_DEBUG_SPINLOCK, CONFIG_SMP */
+#include <linux/compiler.h>
+#include <asm/atomic.h>
+#include <asm/page.h>
+
+extern int printk(const char * fmt, ...)
+       __attribute__ ((format (printf, 1, 2)));
+
+#define RW_LOCK_BIAS            0x01000000
+#define RW_LOCK_BIAS_STR       "0x01000000"
+
+/* It seems that people are forgetting to
+ * initialize their spinlocks properly, tsk tsk.
+ * Remember to turn this off in 2.4. -ben
+ */
+#if defined(CONFIG_DEBUG_SPINLOCK)
+#define SPINLOCK_DEBUG 1
+#else
+#define SPINLOCK_DEBUG 0
+#endif
+
+/*
+ * Your basic SMP spinlocks, allowing only a single CPU anywhere
+ */
+
+typedef struct {
+       volatile int lock;
+#if SPINLOCK_DEBUG
+       unsigned magic;
+#endif
+#ifdef CONFIG_PREEMPT
+       unsigned int break_lock;
+#endif
+} spinlock_t;
+
+#define SPINLOCK_MAGIC 0xdead4ead
+
+#if SPINLOCK_DEBUG
+#define SPINLOCK_MAGIC_INIT    , SPINLOCK_MAGIC
+#else
+#define SPINLOCK_MAGIC_INIT    /* */
+#endif
+
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
+
+#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
+
+/*
+ * Simple spin lock operations.  There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
+#define spin_is_locked(x)      (*(volatile int *)(&(x)->lock) <= 0)
+#define spin_unlock_wait(x)    do { barrier(); } while(spin_is_locked(x))
+#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+
+/**
+ * _raw_spin_trylock - Try spin lock and return a result
+ * @lock: Pointer to the lock variable
+ *
+ * _raw_spin_trylock() tries to get the lock and returns a result.
+ * On the m32r, the result value is 1 (= Success) or 0 (= Failure).
+ */
+static inline int _raw_spin_trylock(spinlock_t *lock)
+{
+       int oldval;
+       unsigned long tmp1, tmp2;
+
+       /*
+        * lock->lock :  =1 : unlock
+        *            : <=0 : lock
+        * {
+        *   oldval = lock->lock; <--+ need atomic operation
+        *   lock->lock = 0;      <--+
+        * }
+        */
+       __asm__ __volatile__ (
+               "# spin_trylock                 \n\t"
+               "ldi    %1, #0;                 \n\t"
+               "mvfc   %2, psw;                \n\t"
+               "clrpsw #0x40 -> nop;           \n\t"
+               DCACHE_CLEAR("%0", "r6", "%3")
+               "lock   %0, @%3;                \n\t"
+               "unlock %1, @%3;                \n\t"
+               "mvtc   %2, psw;                \n\t"
+               : "=&r" (oldval), "=&r" (tmp1), "=&r" (tmp2)
+               : "r" (&lock->lock)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r6"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+
+       return (oldval > 0);
+}
+
+static inline void _raw_spin_lock(spinlock_t *lock)
+{
+       unsigned long tmp0, tmp1;
+
+#if SPINLOCK_DEBUG
+       __label__ here;
+here:
+       if (lock->magic != SPINLOCK_MAGIC) {
+               printk("eip: %p\n", &&here);
+               BUG();
+       }
+#endif
+       /*
+        * lock->lock :  =1 : unlock
+        *            : <=0 : lock
+        *
+        * for ( ; ; ) {
+        *   lock->lock -= 1;  <-- need atomic operation
+        *   if (lock->lock == 0) break;
+        *   for ( ; lock->lock <= 0 ; );
+        * }
+        */
+       __asm__ __volatile__ (
+               "# spin_lock                    \n\t"
+               ".fillinsn                      \n"
+               "1:                             \n\t"
+               "mvfc   %1, psw;                \n\t"
+               "clrpsw #0x40 -> nop;           \n\t"
+               DCACHE_CLEAR("%0", "r6", "%2")
+               "lock   %0, @%2;                \n\t"
+               "addi   %0, #-1;                \n\t"
+               "unlock %0, @%2;                \n\t"
+               "mvtc   %1, psw;                \n\t"
+               "bltz   %0, 2f;                 \n\t"
+               LOCK_SECTION_START(".balign 4 \n\t")
+               ".fillinsn                      \n"
+               "2:                             \n\t"
+               "ld     %0, @%2;                \n\t"
+               "bgtz   %0, 1b;                 \n\t"
+               "bra    2b;                     \n\t"
+               LOCK_SECTION_END
+               : "=&r" (tmp0), "=&r" (tmp1)
+               : "r" (&lock->lock)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r6"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+}
+
+static inline void _raw_spin_unlock(spinlock_t *lock)
+{
+#if SPINLOCK_DEBUG
+       BUG_ON(lock->magic != SPINLOCK_MAGIC);
+       BUG_ON(!spin_is_locked(lock));
+#endif
+       mb();
+       lock->lock = 1;
+}
+
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+typedef struct {
+       volatile int lock;
+#if SPINLOCK_DEBUG
+       unsigned magic;
+#endif
+#ifdef CONFIG_PREEMPT
+       unsigned int break_lock;
+#endif
+} rwlock_t;
+
+#define RWLOCK_MAGIC   0xdeaf1eed
+
+#if SPINLOCK_DEBUG
+#define RWLOCK_MAGIC_INIT      , RWLOCK_MAGIC
+#else
+#define RWLOCK_MAGIC_INIT      /* */
+#endif
+
+#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
+
+#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+
+#define rwlock_is_locked(x)    ((x)->lock != RW_LOCK_BIAS)
+
+/*
+ * On x86, we implement read-write locks as a 32-bit counter
+ * with the high bit (sign) being the "contended" bit.
+ *
+ * The inline assembly is non-obvious. Think about it.
+ *
+ * Changed to use the same technique as rw semaphores.  See
+ * semaphore.h for details.  -ben
+ */
+/* the spinlock helpers are in arch/i386/kernel/semaphore.c */
+
+static inline void _raw_read_lock(rwlock_t *rw)
+{
+       unsigned long tmp0, tmp1;
+
+#if SPINLOCK_DEBUG
+       BUG_ON(rw->magic != RWLOCK_MAGIC);
+#endif
+       /*
+        * rw->lock :  >0 : unlock
+        *          : <=0 : lock
+        *
+        * for ( ; ; ) {
+        *   rw->lock -= 1;  <-- need atomic operation
+        *   if (rw->lock >= 0) break;
+        *   rw->lock += 1;  <-- need atomic operation
+        *   for ( ; rw->lock <= 0 ; );
+        * }
+        */
+       __asm__ __volatile__ (
+               "# read_lock                    \n\t"
+               ".fillinsn                      \n"
+               "1:                             \n\t"
+               "mvfc   %1, psw;                \n\t"
+               "clrpsw #0x40 -> nop;           \n\t"
+               DCACHE_CLEAR("%0", "r6", "%2")
+               "lock   %0, @%2;                \n\t"
+               "addi   %0, #-1;                \n\t"
+               "unlock %0, @%2;                \n\t"
+               "mvtc   %1, psw;                \n\t"
+               "bltz   %0, 2f;                 \n\t"
+               LOCK_SECTION_START(".balign 4 \n\t")
+               ".fillinsn                      \n"
+               "2:                             \n\t"
+               "clrpsw #0x40 -> nop;           \n\t"
+               DCACHE_CLEAR("%0", "r6", "%2")
+               "lock   %0, @%2;                \n\t"
+               "addi   %0, #1;                 \n\t"
+               "unlock %0, @%2;                \n\t"
+               "mvtc   %1, psw;                \n\t"
+               ".fillinsn                      \n"
+               "3:                             \n\t"
+               "ld     %0, @%2;                \n\t"
+               "bgtz   %0, 1b;                 \n\t"
+               "bra    3b;                     \n\t"
+               LOCK_SECTION_END
+               : "=&r" (tmp0), "=&r" (tmp1)
+               : "r" (&rw->lock)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r6"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+}
+
+static inline void _raw_write_lock(rwlock_t *rw)
+{
+       unsigned long tmp0, tmp1, tmp2;
+
+#if SPINLOCK_DEBUG
+       BUG_ON(rw->magic != RWLOCK_MAGIC);
+#endif
+       /*
+        * rw->lock :  =RW_LOCK_BIAS_STR : unlock
+        *          : !=RW_LOCK_BIAS_STR : lock
+        *
+        * for ( ; ; ) {
+        *   rw->lock -= RW_LOCK_BIAS_STR;  <-- need atomic operation
+        *   if (rw->lock == 0) break;
+        *   rw->lock += RW_LOCK_BIAS_STR;  <-- need atomic operation
+        *   for ( ; rw->lock != RW_LOCK_BIAS_STR ; ) ;
+        * }
+        */
+       __asm__ __volatile__ (
+               "# write_lock                                   \n\t"
+               "seth   %1, #high(" RW_LOCK_BIAS_STR ");        \n\t"
+               "or3    %1, %1, #low(" RW_LOCK_BIAS_STR ");     \n\t"
+               ".fillinsn                                      \n"
+               "1:                                             \n\t"
+               "mvfc   %2, psw;                                \n\t"
+               "clrpsw #0x40 -> nop;                           \n\t"
+               DCACHE_CLEAR("%0", "r7", "%3")
+               "lock   %0, @%3;                                \n\t"
+               "sub    %0, %1;                                 \n\t"
+               "unlock %0, @%3;                                \n\t"
+               "mvtc   %2, psw;                                \n\t"
+               "bnez   %0, 2f;                                 \n\t"
+               LOCK_SECTION_START(".balign 4 \n\t")
+               ".fillinsn                                      \n"
+               "2:                                             \n\t"
+               "clrpsw #0x40 -> nop;                           \n\t"
+               DCACHE_CLEAR("%0", "r7", "%3")
+               "lock   %0, @%3;                                \n\t"
+               "add    %0, %1;                                 \n\t"
+               "unlock %0, @%3;                                \n\t"
+               "mvtc   %2, psw;                                \n\t"
+               ".fillinsn                                      \n"
+               "3:                                             \n\t"
+               "ld     %0, @%3;                                \n\t"
+               "beq    %0, %1, 1b;                             \n\t"
+               "bra    3b;                                     \n\t"
+               LOCK_SECTION_END
+               : "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
+               : "r" (&rw->lock)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r7"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+}
+
+static inline void _raw_read_unlock(rwlock_t *rw)
+{
+       unsigned long tmp0, tmp1;
+
+       __asm__ __volatile__ (
+               "# read_unlock                  \n\t"
+               "mvfc   %1, psw;                \n\t"
+               "clrpsw #0x40 -> nop;           \n\t"
+               DCACHE_CLEAR("%0", "r6", "%2")
+               "lock   %0, @%2;                \n\t"
+               "addi   %0, #1;                 \n\t"
+               "unlock %0, @%2;                \n\t"
+               "mvtc   %1, psw;                \n\t"
+               : "=&r" (tmp0), "=&r" (tmp1)
+               : "r" (&rw->lock)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r6"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+}
+
+static inline void _raw_write_unlock(rwlock_t *rw)
+{
+       unsigned long tmp0, tmp1, tmp2;
+
+       __asm__ __volatile__ (
+               "# write_unlock                                 \n\t"
+               "seth   %1, #high(" RW_LOCK_BIAS_STR ");        \n\t"
+               "or3    %1, %1, #low(" RW_LOCK_BIAS_STR ");     \n\t"
+               "mvfc   %2, psw;                                \n\t"
+               "clrpsw #0x40 -> nop;                           \n\t"
+               DCACHE_CLEAR("%0", "r7", "%3")
+               "lock   %0, @%3;                                \n\t"
+               "add    %0, %1;                                 \n\t"
+               "unlock %0, @%3;                                \n\t"
+               "mvtc   %2, psw;                                \n\t"
+               : "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
+               : "r" (&rw->lock)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r7"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+}
+
+#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+
+static inline int _raw_write_trylock(rwlock_t *lock)
+{
+       atomic_t *count = (atomic_t *)lock;
+       if (atomic_sub_and_test(RW_LOCK_BIAS, count))
+               return 1;
+       atomic_add(RW_LOCK_BIAS, count);
+       return 0;
+}
+
+#endif /* _ASM_M32R_SPINLOCK_H */
diff --git a/include/asm-m32r/stat.h b/include/asm-m32r/stat.h
new file mode 100644 (file)
index 0000000..05748fe
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef _ASM_M32R_STAT_H
+#define _ASM_M32R_STAT_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+#include <asm/byteorder.h>
+
+struct __old_kernel_stat {
+       unsigned short st_dev;
+       unsigned short st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+       unsigned long  st_size;
+       unsigned long  st_atime;
+       unsigned long  st_mtime;
+       unsigned long  st_ctime;
+};
+
+#define STAT_HAVE_NSEC 1
+
+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  st_atime_nsec;
+       unsigned long  st_mtime;
+       unsigned long  st_mtime_nsec;
+       unsigned long  st_ctime;
+       unsigned long  st_ctime_nsec;
+       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   __pad0[4];
+#define STAT64_HAS_BROKEN_ST_INO
+       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   __pad3[4];
+
+       long long       st_size;
+       unsigned long   st_blksize;
+
+#if defined(__BIG_ENDIAN)
+       unsigned long   __pad4;         /* future possible st_blocks high bits */
+       unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
+#elif defined(__LITTLE_ENDIAN)
+       unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
+       unsigned long   __pad4;         /* future possible st_blocks high bits */
+#else
+#error no endian defined
+#endif
+       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  /* _ASM_M32R_STAT_H */
diff --git a/include/asm-m32r/statfs.h b/include/asm-m32r/statfs.h
new file mode 100644 (file)
index 0000000..6eb4c60
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_M32R_STATFS_H
+#define _ASM_M32R_STATFS_H
+
+#include <asm-generic/statfs.h>
+
+#endif  /* _ASM_M32R_STATFS_H */
diff --git a/include/asm-m32r/string.h b/include/asm-m32r/string.h
new file mode 100644 (file)
index 0000000..cb54bcc
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _ASM_M32R_STRING_H
+#define _ASM_M32R_STRING_H
+
+/* $Id$ */
+
+#define  __HAVE_ARCH_STRLEN
+extern size_t strlen(const char * s);
+
+#define  __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
+
+#define  __HAVE_ARCH_MEMSET
+extern void *memset(void *__s, int __c, size_t __count);
+
+#endif  /* _ASM_M32R_STRING_H */
diff --git a/include/asm-m32r/syscall.h b/include/asm-m32r/syscall.h
new file mode 100644 (file)
index 0000000..d8d4b2c
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _ASM_M32R_SYSCALL_H
+#define _ASM_M32R_SYSCALL_H
+
+/* $Id$ */
+
+/* Definitions for the system call vector.  */
+#define SYSCALL_VECTOR          "2"
+#define SYSCALL_VECTOR_ADDRESS  "0xa0"
+
+#endif /* _ASM_M32R_SYSCALL_H */
+
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
new file mode 100644 (file)
index 0000000..cca922a
--- /dev/null
@@ -0,0 +1,301 @@
+#ifndef _ASM_M32R_SYSTEM_H
+#define _ASM_M32R_SYSTEM_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001  by Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ */
+
+#include <linux/config.h>
+
+#ifdef __KERNEL__
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.
+ *
+ * `next' and `prev' should be struct task_struct, but it isn't always defined
+ */
+
+#ifndef CONFIG_SMP
+#define prepare_to_switch()  do { } while(0)
+#endif /* not CONFIG_SMP */
+
+#define switch_to(prev, next, last)  do { \
+       register unsigned long  arg0 __asm__ ("r0") = (unsigned long)prev; \
+       register unsigned long  arg1 __asm__ ("r1") = (unsigned long)next; \
+       register unsigned long  *oldsp __asm__ ("r2") = &(prev->thread.sp); \
+       register unsigned long  *newsp __asm__ ("r3") = &(next->thread.sp); \
+       register unsigned long  *oldlr __asm__ ("r4") = &(prev->thread.lr); \
+       register unsigned long  *newlr __asm__ ("r5") = &(next->thread.lr); \
+       register struct task_struct  *__last __asm__ ("r6"); \
+       __asm__ __volatile__ ( \
+               "st     r8, @-r15                                 \n\t" \
+               "st     r9, @-r15                                 \n\t" \
+               "st    r10, @-r15                                 \n\t" \
+               "st    r11, @-r15                                 \n\t" \
+               "st    r12, @-r15                                 \n\t" \
+               "st    r13, @-r15                                 \n\t" \
+               "st    r14, @-r15                                 \n\t" \
+               "seth  r14, #high(1f)                             \n\t" \
+               "or3   r14, r14, #low(1f)                         \n\t" \
+               "st    r14, @r4    ; store old LR                 \n\t" \
+               "st    r15, @r2    ; store old SP                 \n\t" \
+               "ld    r15, @r3    ; load new SP                  \n\t" \
+               "st     r0, @-r15  ; store 'prev' onto new stack  \n\t" \
+               "ld    r14, @r5    ; load new LR                  \n\t" \
+               "jmp   r14                                        \n\t" \
+               ".fillinsn                                        \n  " \
+               "1:                                               \n\t" \
+               "ld     r6, @r15+  ; load 'prev' from new stack   \n\t" \
+               "ld    r14, @r15+                                 \n\t" \
+               "ld    r13, @r15+                                 \n\t" \
+               "ld    r12, @r15+                                 \n\t" \
+               "ld    r11, @r15+                                 \n\t" \
+               "ld    r10, @r15+                                 \n\t" \
+               "ld     r9, @r15+                                 \n\t" \
+               "ld     r8, @r15+                                 \n\t" \
+               : "=&r" (__last) \
+               : "r" (arg0), "r" (arg1), "r" (oldsp), "r" (newsp), \
+                 "r" (oldlr), "r" (newlr) \
+               : "memory" \
+       ); \
+       last = __last; \
+} while(0)
+
+/* Interrupt Control */
+#if !defined(CONFIG_CHIP_M32102)
+#define local_irq_enable() \
+       __asm__ __volatile__ ("setpsw #0x40 -> nop": : :"memory")
+#define local_irq_disable() \
+       __asm__ __volatile__ ("clrpsw #0x40 -> nop": : :"memory")
+#else  /* CONFIG_CHIP_M32102 */
+static __inline__ void local_irq_enable(void)
+{
+       unsigned long tmpreg;
+       __asm__ __volatile__(
+               "mvfc   %0, psw;                \n\t"
+               "or3    %0, %0, #0x0040;        \n\t"
+               "mvtc   %0, psw;                \n\t"
+       : "=&r" (tmpreg) : : "cbit", "memory");
+}
+
+static __inline__ void local_irq_disable(void)
+{
+       unsigned long tmpreg0, tmpreg1;
+       __asm__ __volatile__(
+               "ld24   %0, #0  ; Use 32-bit insn. \n\t"
+               "mvfc   %1, psw ; No interrupt can be accepted here. \n\t"
+               "mvtc   %0, psw \n\t"
+               "and3   %0, %1, #0xffbf \n\t"
+               "mvtc   %0, psw \n\t"
+       : "=&r" (tmpreg0), "=&r" (tmpreg1) : : "cbit", "memory");
+}
+#endif /* CONFIG_CHIP_M32102 */
+
+#define local_save_flags(x) \
+       __asm__ __volatile__("mvfc %0,psw" : "=r"(x) : /* no input */)
+
+#define local_irq_restore(x) \
+       __asm__ __volatile__("mvtc %0,psw" : /* no outputs */ \
+               : "r" (x) : "cbit", "memory")
+
+#if !defined(CONFIG_CHIP_M32102)
+#define local_irq_save(x)                              \
+       __asm__ __volatile__(                           \
+               "mvfc   %0, psw;                \n\t"   \
+               "clrpsw #0x40 -> nop;           \n\t"   \
+               : "=r" (x) : /* no input */ : "memory")
+#else  /* CONFIG_CHIP_M32102 */
+#define local_irq_save(x)                              \
+       ({                                              \
+               unsigned long tmpreg;                   \
+               __asm__ __volatile__(                   \
+                       "ld24   %1, #0 \n\t"            \
+                       "mvfc   %0, psw \n\t"           \
+                       "mvtc   %1, psw \n\t"           \
+                       "and3   %1, %0, #0xffbf \n\t"   \
+                       "mvtc   %1, psw \n\t"           \
+                       : "=r" (x), "=&r" (tmpreg)      \
+                       : : "cbit", "memory");          \
+       })
+#endif /* CONFIG_CHIP_M32102 */
+
+#define irqs_disabled()                                        \
+       ({                                              \
+               unsigned long flags;                    \
+               local_save_flags(flags);                \
+               !(flags & 0x40);                        \
+       })
+
+#endif  /* __KERNEL__ */
+
+#define nop()  __asm__ __volatile__ ("nop" : : )
+
+#define xchg(ptr,x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+#define tas(ptr)       (xchg((ptr),1))
+
+#ifdef CONFIG_SMP
+extern void  __xchg_called_with_bad_pointer(void);
+#endif
+
+#ifdef CONFIG_CHIP_M32700_TS1
+#define DCACHE_CLEAR(reg0, reg1, addr)                         \
+       "seth   "reg1", #high(dcache_dummy);            \n\t"   \
+       "or3    "reg1", "reg1", #low(dcache_dummy);     \n\t"   \
+       "lock   "reg0", @"reg1";                        \n\t"   \
+       "add3   "reg0", "addr", #0x1000;                \n\t"   \
+       "ld     "reg0", @"reg0";                        \n\t"   \
+       "add3   "reg0", "addr", #0x2000;                \n\t"   \
+       "ld     "reg0", @"reg0";                        \n\t"   \
+       "unlock "reg0", @"reg1";                        \n\t"
+       /* FIXME: This workaround code cannot handle kenrel modules
+        * correctly under SMP environment.
+        */
+#else  /* CONFIG_CHIP_M32700_TS1 */
+#define DCACHE_CLEAR(reg0, reg1, addr)
+#endif /* CONFIG_CHIP_M32700_TS1 */
+
+static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
+       int size)
+{
+       unsigned long flags;
+       unsigned long tmp = 0;
+
+       local_irq_save(flags);
+
+       switch (size) {
+#ifndef CONFIG_SMP
+       case 1:
+               __asm__ __volatile__ (
+                       "ldb    %0, @%2 \n\t"
+                       "stb    %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       case 2:
+               __asm__ __volatile__ (
+                       "ldh    %0, @%2 \n\t"
+                       "sth    %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       case 4:
+               __asm__ __volatile__ (
+                       "ld     %0, @%2 \n\t"
+                       "st     %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+#else  /* CONFIG_SMP */
+       case 4:
+               __asm__ __volatile__ (
+                       DCACHE_CLEAR("%0", "r4", "%2")
+                       "lock   %0, @%2;        \n\t"
+                       "unlock %1, @%2;        \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr)
+                       : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+                       , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+               );
+               break;
+       default:
+               __xchg_called_with_bad_pointer();
+#endif  /* CONFIG_SMP */
+       }
+
+       local_irq_restore(flags);
+
+       return (tmp);
+}
+
+/*
+ * Memory barrier.
+ *
+ * mb() prevents loads and stores being reordered across this point.
+ * rmb() prevents loads being reordered across this point.
+ * wmb() prevents stores being reordered across this point.
+ */
+#if 0
+#define mb()   __asm__ __volatile__ ("push r0; \n\t pop r0;" : : : "memory")
+#else
+#define mb()   __asm__ __volatile__ ("" : : : "memory")
+#endif
+#define rmb()  mb()
+#define wmb()  mb()
+
+/**
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *      CPU 0                           CPU 1
+ *
+ *      b = 2;
+ *      memory_barrier();
+ *      p = &b;                         q = p;
+ *                                      read_barrier_depends();
+ *                                      d = *q;
+ * </programlisting>
+ *
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *      CPU 0                           CPU 1
+ *
+ *      a = 2;
+ *      memory_barrier();
+ *      b = 3;                          y = b;
+ *                                      read_barrier_depends();
+ *                                      x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like thiswhere there are no data dependencies.
+ **/
+
+#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 set_mb(var, value) do { xchg(&var, value); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+
+#endif  /* _ASM_M32R_SYSTEM_H */
+
diff --git a/include/asm-m32r/termbits.h b/include/asm-m32r/termbits.h
new file mode 100644 (file)
index 0000000..aa5a829
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef _ASM_M32R_TERMBITS_H
+#define _ASM_M32R_TERMBITS_H
+
+/* $Id$ */
+
+#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 */
+};
+
+/* 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  /* _ASM_M32R_TERMBITS_H */
diff --git a/include/asm-m32r/termios.h b/include/asm-m32r/termios.h
new file mode 100644 (file)
index 0000000..fc99d2e
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef _M32R_TERMIOS_H
+#define _M32R_TERMIOS_H
+
+/* orig : i386 2.6.0-test5 */
+
+#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__
+#include <linux/module.h>
+
+/*     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 /* _M32R_TERMIOS_H */
diff --git a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h
new file mode 100644 (file)
index 0000000..de7d3f1
--- /dev/null
@@ -0,0 +1,149 @@
+/* thread_info.h: i386 low-level thread information
+ *
+ * Copyright (C) 2002  David Howells (dhowells@redhat.com)
+ * - Incorporating suggestions made by Linus Torvalds and Dave Miller
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#endif
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants must also be changed
+ */
+#ifndef __ASSEMBLY__
+
+struct thread_info {
+       struct task_struct      *task;          /* main task structure */
+       struct exec_domain      *exec_domain;   /* execution domain */
+       unsigned long           flags;          /* low level flags */
+       unsigned long           status;         /* thread-synchronous flags */
+       __u32                   cpu;            /* current CPU */
+       __s32                   preempt_count; /* 0 => preemptable, <0 => BUG */
+
+       mm_segment_t            addr_limit;     /* thread address space:
+                                                  0-0xBFFFFFFF for user-thead
+                                                  0-0xFFFFFFFF for kernel-thread
+                                               */
+       struct restart_block    restart_block;
+
+       __u8                    supervisor_stack[0];
+};
+
+#else /* !__ASSEMBLY__ */
+
+/* offsets into the thread_info struct for assembly code access */
+#define TI_TASK                0x00000000
+#define TI_EXEC_DOMAIN 0x00000004
+#define TI_FLAGS       0x00000008
+#define TI_STATUS      0x0000000C
+#define TI_CPU         0x00000010
+#define TI_PRE_COUNT   0x00000014
+#define TI_ADDR_LIMIT  0x00000018
+#define TI_RESTART_BLOCK 0x000001C
+
+#endif
+
+#define PREEMPT_ACTIVE         0x4000000
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk)                  \
+{                                              \
+       .task           = &tsk,                 \
+       .exec_domain    = &default_exec_domain, \
+       .flags          = 0,                    \
+       .cpu            = 0,                    \
+       .preempt_count  = 1,                    \
+       .addr_limit     = KERNEL_DS,            \
+       .restart_block = {                      \
+               .fn = do_no_restart_syscall,    \
+       },                                      \
+}
+
+#define init_thread_info       (init_thread_union.thread_info)
+#define init_stack             (init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+       struct thread_info *ti;
+
+       __asm__ __volatile__ (
+               "ldi    %0, #0xffffe000;        \n\t"
+               "and    %0, sp;                 \n\t"
+               : "=r" (ti)
+       );
+
+       return ti;
+}
+
+/* thread information allocation */
+#define THREAD_SIZE (2*PAGE_SIZE)
+#define alloc_thread_info(task) \
+       ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
+#else /* !__ASSEMBLY__ */
+
+/* how to get the thread information struct from ASM */
+#define GET_THREAD_INFO(reg)   GET_THREAD_INFO reg
+       .macro GET_THREAD_INFO reg
+       ldi     \reg, #0xffffe000
+       and     \reg, sp
+       .endm
+
+#endif
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#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_SINGLESTEP         4       /* restore singlestep on return to user mode */
+#define TIF_IRET               5       /* return with iret */
+#define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
+
+#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_SINGLESTEP                (1<<TIF_SINGLESTEP)
+#define _TIF_IRET              (1<<TIF_IRET)
+#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
+
+#define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
+#define _TIF_ALLWORK_MASK      0x0000FFFF      /* work to do on any return to u-space */
+
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+#define TS_USEDFPU             0x0001  /* FPU was used by this task this quantum (SMP) */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff --git a/include/asm-m32r/timex.h b/include/asm-m32r/timex.h
new file mode 100644 (file)
index 0000000..e102aaf
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _ASM_M32R_TIMEX_H
+#define _ASM_M32R_TIMEX_H
+
+/* $Id$ */
+
+/*
+ * linux/include/asm-m32r/timex.h
+ *
+ * m32r architecture timex specifications
+ */
+
+#include <linux/config.h>
+
+#define CLOCK_TICK_RATE        (CONFIG_BUS_CLOCK / CONFIG_TIMER_DIVIDE)
+#define CLOCK_TICK_FACTOR      20      /* Factor of both 1000000 and CLOCK_TICK_RATE */
+#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
+       (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
+               << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
+
+#ifdef __KERNEL__
+/*
+ * Standard way to access the cycle counter.
+ * Currently only used on SMP.
+ */
+
+typedef unsigned long long cycles_t;
+
+extern cycles_t cacheflush_time;
+
+static __inline__ cycles_t get_cycles (void)
+{
+       return 0;
+}
+#endif  /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_TIMEX_H */
diff --git a/include/asm-m32r/tlb.h b/include/asm-m32r/tlb.h
new file mode 100644 (file)
index 0000000..c7ebd8d
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _M32R_TLB_H
+#define _M32R_TLB_H
+
+/*
+ * x86 doesn't need any special per-pte or
+ * per-vma handling..
+ */
+#define tlb_start_vma(tlb, vma) do { } while (0)
+#define tlb_end_vma(tlb, vma) do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, pte, 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 /* _M32R_TLB_H */
diff --git a/include/asm-m32r/tlbflush.h b/include/asm-m32r/tlbflush.h
new file mode 100644 (file)
index 0000000..bc7c407
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef _ASM_M32R_TLBFLUSH_H
+#define _ASM_M32R_TLBFLUSH_H
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb() flushes the current mm struct TLBs
+ *  - flush_tlb_all() flushes all processes TLBs
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - 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
+ */
+
+extern void local_flush_tlb_all(void);
+extern void local_flush_tlb_mm(struct mm_struct *);
+extern void local_flush_tlb_page(struct vm_area_struct *, unsigned long);
+extern void local_flush_tlb_range(struct vm_area_struct *, unsigned long,
+       unsigned long);
+
+#ifndef CONFIG_SMP
+#ifdef CONFIG_MMU
+#define flush_tlb_all()                        local_flush_tlb_all()
+#define flush_tlb_mm(mm)               local_flush_tlb_mm(mm)
+#define flush_tlb_page(vma, page)      local_flush_tlb_page(vma, page)
+#define flush_tlb_range(vma, start, end)       \
+       local_flush_tlb_range(vma, start, end)
+#define flush_tlb_kernel_range(start, end)     local_flush_tlb_all()
+#else  /* CONFIG_MMU */
+#define flush_tlb_all()                        do { } while (0)
+#define flush_tlb_mm(mm)               do { } while (0)
+#define flush_tlb_page(vma, vmaddr)    do { } while (0)
+#define flush_tlb_range(vma, start, end)       do { } while (0)
+#endif /* CONFIG_MMU */
+#else  /* CONFIG_SMP */
+extern void smp_flush_tlb_all(void);
+extern void smp_flush_tlb_mm(struct mm_struct *);
+extern void smp_flush_tlb_page(struct vm_area_struct *, unsigned long);
+extern void smp_flush_tlb_range(struct vm_area_struct *, unsigned long,
+       unsigned long);
+
+#define flush_tlb_all()                        smp_flush_tlb_all()
+#define flush_tlb_mm(mm)               smp_flush_tlb_mm(mm)
+#define flush_tlb_page(vma, page)      smp_flush_tlb_page(vma, page)
+#define flush_tlb_range(vma, start, end)       \
+       smp_flush_tlb_range(vma, start, end)
+#define flush_tlb_kernel_range(start, end)     smp_flush_tlb_all()
+#endif /* CONFIG_SMP */
+
+static __inline__ void __flush_tlb_page(unsigned long page)
+{
+       unsigned int tmpreg0, tmpreg1, tmpreg2;
+
+       __asm__ __volatile__ (
+               "seth   %0, #high(%4)   \n\t"
+               "st     %3, @(%5, %0)   \n\t"
+               "ldi    %1, #1          \n\t"
+               "st     %1, @(%6, %0)   \n\t"
+               "add3   %1, %0, %7      \n\t"
+               ".fillinsn              \n"
+               "1:                     \n\t"
+               "ld     %2, @(%6, %0)   \n\t"
+               "bnez   %2, 1b          \n\t"
+               "ld     %0, @%1+        \n\t"
+               "ld     %1, @%1         \n\t"
+               "st     %2, @+%0        \n\t"
+               "st     %2, @+%1        \n\t"
+               : "=&r" (tmpreg0), "=&r" (tmpreg1), "=&r" (tmpreg2)
+               : "r" (page), "i" (MMU_REG_BASE), "i" (MSVA_offset),
+               "i" (MTOP_offset), "i" (MIDXI_offset)
+               : "memory"
+       );
+}
+
+static __inline__ void __flush_tlb_all(void)
+{
+       unsigned int tmpreg0, tmpreg1;
+
+       __asm__ __volatile__ (
+               "seth   %0, #high(%2)           \n\t"
+               "or3    %0, %0, #low(%2)        \n\t"
+               "ldi    %1, #0xc                \n\t"
+               "st     %1, @%0                 \n\t"
+               ".fillinsn                      \n"
+               "1:                             \n\t"
+               "ld     %1, @%0                 \n\t"
+               "bnez   %1, 1b                  \n\t"
+               : "=&r" (tmpreg0), "=&r" (tmpreg1)
+               : "i" (MTOP) : "memory"
+       );
+}
+
+#define flush_tlb_pgtables(mm, start, end)     do { } while (0)
+
+extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
+
+#endif /* _ASM_M32R_TLBFLUSH_H */
+
diff --git a/include/asm-m32r/topology.h b/include/asm-m32r/topology.h
new file mode 100644 (file)
index 0000000..b5a3ea1
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * linux/include/asm-generic/topology.h
+ *
+ * Written by: Matthew Dobson, IBM Corporation
+ *
+ * Copyright (C) 2002, IBM Corp.
+ *
+ * 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.
+ *
+ * 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 <colpatch@us.ibm.com>
+ */
+#ifndef _ASM_M32R_TOPOLOGY_H
+#define _ASM_M32R_TOPOLOGY_H
+
+/* Other architectures wishing to use this simple topology API should fill
+   in the below functions as appropriate in their own <asm/topology.h> file. */
+
+#define cpu_to_node(cpu)       (0)
+
+#ifndef parent_node
+#define parent_node(node)      (0)
+#endif
+#ifndef node_to_cpumask
+#define node_to_cpumask(node)  (cpu_online_map)
+#endif
+#ifndef node_to_first_cpu
+#define node_to_first_cpu(node)        (0)
+#endif
+#ifndef pcibus_to_cpumask
+#define pcibus_to_cpumask(bus) (cpu_online_map)
+#endif
+
+/* Cross-node load balancing interval. */
+#ifndef NODE_BALANCE_RATE
+#define NODE_BALANCE_RATE 10
+#endif
+
+#endif /* _ASM_M32R_TOPOLOGY_H */
diff --git a/include/asm-m32r/types.h b/include/asm-m32r/types.h
new file mode 100644 (file)
index 0000000..ca0a887
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef _ASM_M32R_TYPES_H
+#define _ASM_M32R_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+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;
+
+#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;
+
+typedef unsigned short kmem_bufctl_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_TYPES_H */
diff --git a/include/asm-m32r/uaccess.h b/include/asm-m32r/uaccess.h
new file mode 100644 (file)
index 0000000..58530a3
--- /dev/null
@@ -0,0 +1,752 @@
+#ifndef _ASM_M32R_UACCESS_H
+#define _ASM_M32R_UACCESS_H
+
+/*
+ *  linux/include/asm-m32r/uaccess.h
+ *
+ *  M32R version.
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#undef UACCESS_DEBUG
+
+#ifdef UACCESS_DEBUG
+#define UAPRINTK(args...) printk(args)
+#else
+#define UAPRINTK(args...)
+#endif /* UACCESS_DEBUG */
+
+/*
+ * User space memory access functions
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/thread_info.h>
+#include <asm/page.h>
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+/*
+ * 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.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+
+#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
+
+#ifdef CONFIG_MMU
+#define KERNEL_DS      MAKE_MM_SEG(0xFFFFFFFF)
+#define USER_DS                MAKE_MM_SEG(PAGE_OFFSET)
+#else
+#define KERNEL_DS      MAKE_MM_SEG(0xFFFFFFFF)
+#define USER_DS                MAKE_MM_SEG(0xFFFFFFFF)
+#endif /* CONFIG_MMU */
+
+#define get_ds()       (KERNEL_DS)
+#ifdef CONFIG_MMU
+#define get_fs()       (current_thread_info()->addr_limit)
+#define set_fs(x)      (current_thread_info()->addr_limit = (x))
+#else
+static inline mm_segment_t get_fs(void)
+{
+  return USER_DS;
+}
+
+static inline void set_fs(mm_segment_t s)
+{
+}
+#endif /* CONFIG_MMU */
+
+#define segment_eq(a,b)        ((a).seg == (b).seg)
+
+#define __addr_ok(addr) \
+       ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
+
+/*
+ * Test whether a block of memory is a valid user space address.
+ * Returns 0 if the range is valid, nonzero otherwise.
+ *
+ * This is equivalent to the following test:
+ * (u33)addr + (u33)size >= (u33)current->addr_limit.seg
+ *
+ * This needs 33-bit arithmetic. We have a carry...
+ */
+#define __range_ok(addr,size) ({                                       \
+       unsigned long flag, sum;                                        \
+       __chk_user_ptr(addr);                                           \
+       asm (                                                           \
+               "       cmpu    %1, %1    ; clear cbit\n"               \
+               "       addx    %1, %3    ; set cbit if overflow\n"     \
+               "       subx    %0, %0\n"                               \
+               "       cmpu    %4, %1\n"                               \
+               "       subx    %0, %5\n"                               \
+               : "=&r"(flag), "=r"(sum)                                \
+               : "1"(addr), "r"((int)(size)),                          \
+                 "r"(current_thread_info()->addr_limit.seg), "r"(0)    \
+               : "cbit" );                                             \
+       flag; })
+
+/**
+ * access_ok: - Checks if a user space pointer is valid
+ * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE.  Note that
+ *        %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
+ *        to write to a block, it is always safe to read from it.
+ * @addr: User space pointer to start of block to check
+ * @size: Size of block to check
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Checks if a pointer to a block of memory in user space is valid.
+ *
+ * Returns true (nonzero) if the memory block may be valid, false (zero)
+ * if it is definitely invalid.
+ *
+ * Note that, depending on architecture, this function probably just
+ * checks that the pointer is in the user space range - after calling
+ * this function, memory access functions may still return -EFAULT.
+ */
+#ifdef CONFIG_MMU
+#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
+#else
+static inline int access_ok(int type, const void *addr, unsigned long size)
+{
+  extern unsigned long memory_start, memory_end;
+  unsigned long val = (unsigned long)addr;
+
+  return ((val >= memory_start) && ((val + size) < memory_end));
+}
+#endif /* CONFIG_MMU */
+
+/**
+ * verify_area: - Obsolete, use access_ok()
+ * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
+ * @addr: User space pointer to start of block to check
+ * @size: Size of block to check
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This function has been replaced by access_ok().
+ *
+ * Checks if a pointer to a block of memory in user space is valid.
+ *
+ * Returns zero if the memory block may be valid, -EFAULT
+ * if it is definitely invalid.
+ *
+ * See access_ok() for more details.
+ */
+static inline int verify_area(int type, const void __user *addr,
+                             unsigned long size)
+{
+       return access_ok(type, addr, size) ? 0 : -EFAULT;
+}
+
+
+/*
+ * 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;
+};
+
+extern int fixup_exception(struct pt_regs *regs);
+
+/*
+ * These are the main single-value transfer routines.  They automatically
+ * use the right size if we just have the right pointer type.
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the uglyness from the user.
+ *
+ * The "__xxx" versions of the user access functions are versions that
+ * do not verify the address space, that must have been done previously
+ * with a separate "access_ok()" call (this is used when we do multiple
+ * accesses to the same area of user memory).
+ */
+
+extern void __get_user_1(void);
+extern void __get_user_2(void);
+extern void __get_user_4(void);
+
+#ifndef MODULE
+#define __get_user_x(size,ret,x,ptr)                                   \
+       __asm__ __volatile__(                                           \
+               "       mv      r0, %0\n"                               \
+               "       mv      r1, %1\n"                               \
+               "       bl __get_user_" #size "\n"                      \
+               "       mv      %0, r0\n"                               \
+               "       mv      %1, r1\n"                               \
+               : "=r"(ret), "=r"(x)                                    \
+               : "0"(ptr)                                              \
+               : "r0", "r1", "r14" )
+#else /* MODULE */
+/*
+ * Use "jl" instead of "bl" for MODULE
+ */
+#define __get_user_x(size,ret,x,ptr)                                   \
+       __asm__ __volatile__(                                           \
+               "       mv      r0, %0\n"                               \
+               "       mv      r1, %1\n"                               \
+               "       seth    lr, #high(__get_user_" #size ")\n"      \
+               "       or3     lr, lr, #low(__get_user_" #size ")\n"   \
+               "       jl      lr\n"                                   \
+               "       mv      %0, r0\n"                               \
+               "       mv      %1, r1\n"                               \
+               : "=r"(ret), "=r"(x)                                    \
+               : "0"(ptr)                                              \
+               : "r0", "r1", "r14" )
+#endif
+
+/* Careful: we have to cast the result to the type of the pointer for sign
+   reasons */
+/**
+ * get_user: - Get a simple variable from user space.
+ * @x:   Variable to store result.
+ * @ptr: Source address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple variable from user space to kernel
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and the result of
+ * dereferencing @ptr must be assignable to @x without a cast.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
+#define get_user(x,ptr)                                                        \
+({     int __ret_gu,__val_gu;                                          \
+       __chk_user_ptr(ptr);                                            \
+       switch(sizeof (*(ptr))) {                                       \
+       case 1:  __get_user_x(1,__ret_gu,__val_gu,ptr); break;          \
+       case 2:  __get_user_x(2,__ret_gu,__val_gu,ptr); break;          \
+       case 4:  __get_user_x(4,__ret_gu,__val_gu,ptr); break;          \
+       default: __get_user_x(X,__ret_gu,__val_gu,ptr); break;          \
+       }                                                               \
+       (x) = (__typeof__(*(ptr)))__val_gu;                             \
+       __ret_gu;                                                       \
+})
+
+extern void __put_user_bad(void);
+
+/**
+ * put_user: - Write a simple value into user space.
+ * @x:   Value to copy to user space.
+ * @ptr: Destination address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple value from kernel space to user
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and @x must be assignable
+ * to the result of dereferencing @ptr.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ */
+#define put_user(x,ptr)                                                        \
+  __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
+
+/**
+ * __get_user: - Get a simple variable from user space, with less checking.
+ * @x:   Variable to store result.
+ * @ptr: Source address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple variable from user space to kernel
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and the result of
+ * dereferencing @ptr must be assignable to @x without a cast.
+ *
+ * Caller must check the pointer with access_ok() before calling this
+ * function.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
+#define __get_user(x,ptr) \
+  __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+
+/**
+ * __put_user: - Write a simple value into user space, with less checking.
+ * @x:   Value to copy to user space.
+ * @ptr: Destination address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple value from kernel space to user
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and @x must be assignable
+ * to the result of dereferencing @ptr.
+ *
+ * Caller must check the pointer with access_ok() before calling this
+ * function.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ */
+#define __put_user(x,ptr) \
+  __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
+#define __put_user_nocheck(x,ptr,size)                                 \
+({                                                                     \
+       long __pu_err;                                                  \
+       __put_user_size((x),(ptr),(size),__pu_err);                     \
+       __pu_err;                                                       \
+})
+
+
+#define __put_user_check(x,ptr,size)                                   \
+({                                                                     \
+       long __pu_err = -EFAULT;                                        \
+       __typeof__(*(ptr)) __user *__pu_addr = (ptr);                   \
+       might_sleep();                                                  \
+       if (access_ok(VERIFY_WRITE,__pu_addr,size))                     \
+               __put_user_size((x),__pu_addr,(size),__pu_err);         \
+       __pu_err;                                                       \
+})
+
+#if defined(__LITTLE_ENDIAN__)
+#define __put_user_u64(x, addr, err)                                    \
+        __asm__ __volatile__(                                           \
+                "       .fillinsn\n"                                    \
+                "1:     st %L1,@%2\n"                                    \
+                "       .fillinsn\n"                                    \
+                "2:     st %H1,@(4,%2)\n"                                \
+                "       .fillinsn\n"                                    \
+                "3:\n"                                                  \
+                ".section .fixup,\"ax\"\n"                              \
+                "       .balign 4\n"                                    \
+                "4:     ldi %0,%3\n"                                    \
+                "       seth r14,#high(3b)\n"                           \
+                "       or3 r14,r14,#low(3b)\n"                         \
+                "       jmp r14\n"                                      \
+                ".previous\n"                                           \
+                ".section __ex_table,\"a\"\n"                           \
+                "       .balign 4\n"                                    \
+                "       .long 1b,4b\n"                                  \
+                "       .long 2b,4b\n"                                  \
+                ".previous"                                             \
+                : "=r"(err)                                             \
+                : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)            \
+                : "r14", "memory")
+
+#elif defined(__BIG_ENDIAN__)
+#define __put_user_u64(x, addr, err)                                   \
+       __asm__ __volatile__(                                           \
+               "       .fillinsn\n"                                    \
+               "1:     st %H1,@%2\n"                                   \
+               "       .fillinsn\n"                                    \
+               "2:     st %L1,@(4,%2)\n"                               \
+               "       .fillinsn\n"                                    \
+               "3:\n"                                                  \
+               ".section .fixup,\"ax\"\n"                              \
+               "       .balign 4\n"                                    \
+               "4:     ldi %0,%3\n"                                    \
+               "       seth r14,#high(3b)\n"                           \
+               "       or3 r14,r14,#low(3b)\n"                         \
+               "       jmp r14\n"                                      \
+               ".previous\n"                                           \
+               ".section __ex_table,\"a\"\n"                           \
+               "       .balign 4\n"                                    \
+               "       .long 1b,4b\n"                                  \
+               "       .long 2b,4b\n"                                  \
+               ".previous"                                             \
+               : "=r"(err)                                             \
+               : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)             \
+               : "r14", "memory")
+#else
+#error no endian defined
+#endif
+
+#define __put_user_size(x,ptr,size,retval)                             \
+do {                                                                   \
+       retval = 0;                                                     \
+       __chk_user_ptr(ptr);                                            \
+       switch (size) {                                                 \
+         case 1: __put_user_asm(x,ptr,retval,"b"); break;              \
+         case 2: __put_user_asm(x,ptr,retval,"h"); break;              \
+         case 4: __put_user_asm(x,ptr,retval,""); break;               \
+         case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\
+         default: __put_user_bad();                                    \
+       }                                                               \
+} while (0)
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+/*
+ * 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 __put_user_asm(x, addr, err, itype)                            \
+       __asm__ __volatile__(                                           \
+               "       .fillinsn\n"                                    \
+               "1:     st"itype" %1,@%2\n"                             \
+               "       .fillinsn\n"                                    \
+               "2:\n"                                                  \
+               ".section .fixup,\"ax\"\n"                              \
+               "       .balign 4\n"                                    \
+               "3:     ldi %0,%3\n"                                    \
+               "       seth r14,#high(2b)\n"                           \
+               "       or3 r14,r14,#low(2b)\n"                         \
+               "       jmp r14\n"                                      \
+               ".previous\n"                                           \
+               ".section __ex_table,\"a\"\n"                           \
+               "       .balign 4\n"                                    \
+               "       .long 1b,3b\n"                                  \
+               ".previous"                                             \
+               : "=r"(err)                                             \
+               : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)             \
+               : "r14", "memory")
+
+#define __get_user_nocheck(x,ptr,size)                                 \
+({                                                                     \
+       long __gu_err, __gu_val;                                        \
+       __get_user_size(__gu_val,(ptr),(size),__gu_err);                \
+       (x) = (__typeof__(*(ptr)))__gu_val;                             \
+       __gu_err;                                                       \
+})
+
+extern long __get_user_bad(void);
+
+#define __get_user_size(x,ptr,size,retval)                             \
+do {                                                                   \
+       retval = 0;                                                     \
+       __chk_user_ptr(ptr);                                            \
+       switch (size) {                                                 \
+         case 1: __get_user_asm(x,ptr,retval,"ub"); break;             \
+         case 2: __get_user_asm(x,ptr,retval,"uh"); break;             \
+         case 4: __get_user_asm(x,ptr,retval,""); break;               \
+         default: (x) = __get_user_bad();                              \
+       }                                                               \
+} while (0)
+
+#define __get_user_asm(x, addr, err, itype)                            \
+       __asm__ __volatile__(                                           \
+               "       .fillinsn\n"                                    \
+               "1:     ld"itype" %1,@%2\n"                             \
+               "       .fillinsn\n"                                    \
+               "2:\n"                                                  \
+               ".section .fixup,\"ax\"\n"                              \
+               "       .balign 4\n"                                    \
+               "3:     ldi %0,%3\n"                                    \
+               "       seth r14,#high(2b)\n"                           \
+               "       or3 r14,r14,#low(2b)\n"                         \
+               "       jmp r14\n"                                      \
+               ".previous\n"                                           \
+               ".section __ex_table,\"a\"\n"                           \
+               "       .balign 4\n"                                    \
+               "       .long 1b,3b\n"                                  \
+               ".previous"                                             \
+               : "=r"(err), "=&r"(x)                                   \
+               : "r"(addr), "i"(-EFAULT), "0"(err)                     \
+               : "r14", "memory")
+
+/*
+ * 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 m32r will not write
+ * anything, so this is accurate.
+ */
+
+
+/*
+ * Copy To/From Userspace
+ */
+
+/* Generic arbitrary sized copy.  */
+/* Return the number of bytes NOT copied.  */
+#define __copy_user(to,from,size)                                      \
+do {                                                                   \
+       unsigned long __dst, __src, __c;                                \
+       __asm__ __volatile__ (                                          \
+               "       mv      r14, %0\n"                              \
+               "       or      r14, %1\n"                              \
+               "       beq     %0, %1, 9f\n"                           \
+               "       beqz    %2, 9f\n"                               \
+               "       and3    r14, r14, #3\n"                         \
+               "       bnez    r14, 2f\n"                              \
+               "       and3    %2, %2, #3\n"                           \
+               "       beqz    %3, 2f\n"                               \
+               "       addi    %0, #-4         ; word_copy \n"         \
+               "       .fillinsn\n"                                    \
+               "0:     ld      r14, @%1+\n"                            \
+               "       addi    %3, #-1\n"                              \
+               "       .fillinsn\n"                                    \
+               "1:     st      r14, @+%0\n"                            \
+               "       bnez    %3, 0b\n"                               \
+               "       beqz    %2, 9f\n"                               \
+               "       addi    %0, #4\n"                               \
+               "       .fillinsn\n"                                    \
+               "2:     ldb     r14, @%1        ; byte_copy \n"         \
+               "       .fillinsn\n"                                    \
+               "3:     stb     r14, @%0\n"                             \
+               "       addi    %1, #1\n"                               \
+               "       addi    %2, #-1\n"                              \
+               "       addi    %0, #1\n"                               \
+               "       bnez    %2, 2b\n"                               \
+               "       .fillinsn\n"                                    \
+               "9:\n"                                                  \
+               ".section .fixup,\"ax\"\n"                              \
+               "       .balign 4\n"                                    \
+               "5:     addi    %3, #1\n"                               \
+               "       addi    %1, #-4\n"                              \
+               "       .fillinsn\n"                                    \
+               "6:     slli    %3, #2\n"                               \
+               "       add     %2, %3\n"                               \
+               "       addi    %0, #4\n"                               \
+               "       .fillinsn\n"                                    \
+               "7:     seth    r14, #high(9b)\n"                       \
+               "       or3     r14, r14, #low(9b)\n"                   \
+               "       jmp     r14\n"                                  \
+               ".previous\n"                                           \
+               ".section __ex_table,\"a\"\n"                           \
+               "       .balign 4\n"                                    \
+               "       .long 0b,6b\n"                                  \
+               "       .long 1b,5b\n"                                  \
+               "       .long 2b,9b\n"                                  \
+               "       .long 3b,9b\n"                                  \
+               ".previous\n"                                           \
+               : "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c)   \
+               : "0"(to), "1"(from), "2"(size), "3"(size / 4)          \
+               : "r14", "memory");                                     \
+} while (0)
+
+#define __copy_user_zeroing(to,from,size)                              \
+do {                                                                   \
+       unsigned long __dst, __src, __c;                                \
+       __asm__ __volatile__ (                                          \
+               "       mv      r14, %0\n"                              \
+               "       or      r14, %1\n"                              \
+               "       beq     %0, %1, 9f\n"                           \
+               "       beqz    %2, 9f\n"                               \
+               "       and3    r14, r14, #3\n"                         \
+               "       bnez    r14, 2f\n"                              \
+               "       and3    %2, %2, #3\n"                           \
+               "       beqz    %3, 2f\n"                               \
+               "       addi    %0, #-4         ; word_copy \n"         \
+               "       .fillinsn\n"                                    \
+               "0:     ld      r14, @%1+\n"                            \
+               "       addi    %3, #-1\n"                              \
+               "       .fillinsn\n"                                    \
+               "1:     st      r14, @+%0\n"                            \
+               "       bnez    %3, 0b\n"                               \
+               "       beqz    %2, 9f\n"                               \
+               "       addi    %0, #4\n"                               \
+               "       .fillinsn\n"                                    \
+               "2:     ldb     r14, @%1        ; byte_copy \n"         \
+               "       .fillinsn\n"                                    \
+               "3:     stb     r14, @%0\n"                             \
+               "       addi    %1, #1\n"                               \
+               "       addi    %2, #-1\n"                              \
+               "       addi    %0, #1\n"                               \
+               "       bnez    %2, 2b\n"                               \
+               "       .fillinsn\n"                                    \
+               "9:\n"                                                  \
+               ".section .fixup,\"ax\"\n"                              \
+               "       .balign 4\n"                                    \
+               "5:     addi    %3, #1\n"                               \
+               "       addi    %1, #-4\n"                              \
+               "       .fillinsn\n"                                    \
+               "6:     slli    %3, #2\n"                               \
+               "       add     %2, %3\n"                               \
+               "       addi    %0, #4\n"                               \
+               "       .fillinsn\n"                                    \
+               "7:     ldi     r14, #0         ; store zero \n"        \
+               "       .fillinsn\n"                                    \
+               "8:     addi    %2, #-1\n"                              \
+               "       stb     r14, @%0        ; ACE? \n"              \
+               "       addi    %0, #1\n"                               \
+               "       bnez    %2, 8b\n"                               \
+               "       seth    r14, #high(9b)\n"                       \
+               "       or3     r14, r14, #low(9b)\n"                   \
+               "       jmp     r14\n"                                  \
+               ".previous\n"                                           \
+               ".section __ex_table,\"a\"\n"                           \
+               "       .balign 4\n"                                    \
+               "       .long 0b,6b\n"                                  \
+               "       .long 1b,5b\n"                                  \
+               "       .long 2b,7b\n"                                  \
+               "       .long 3b,7b\n"                                  \
+               ".previous\n"                                           \
+               : "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c)   \
+               : "0"(to), "1"(from), "2"(size), "3"(size / 4)          \
+               : "r14", "memory");                                     \
+} while (0)
+
+
+/* We let the __ versions of copy_from/to_user inline, because they're often
+ * used in fast paths and have only a small space overhead.
+ */
+static inline unsigned long __generic_copy_from_user_nocheck(void *to,
+       const void __user *from, unsigned long n)
+{
+       __copy_user_zeroing(to,from,n);
+       return n;
+}
+
+static inline unsigned long __generic_copy_to_user_nocheck(void __user *to,
+       const void *from, unsigned long n)
+{
+       __copy_user(to,from,n);
+       return n;
+}
+
+unsigned long __generic_copy_to_user(void *, const void *, unsigned long);
+unsigned long __generic_copy_from_user(void *, const void *, unsigned long);
+
+/**
+ * __copy_to_user: - 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.  This function may sleep.
+ *
+ * Copy data from kernel space to user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+#define __copy_to_user(to,from,n)                      \
+       __generic_copy_to_user_nocheck((to),(from),(n))
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+/**
+ * copy_to_user: - Copy a block of data into user space.
+ * @to:   Destination address, in user space.
+ * @from: Source address, in kernel space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from kernel space to user space.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+#define copy_to_user(to,from,n)                                \
+({                                                     \
+       might_sleep();                                  \
+       __generic_copy_to_user((to),(from),(n));        \
+})
+
+/**
+ * __copy_from_user: - Copy a block of data from user space, with less checking. * @to:   Destination address, in kernel space.
+ * @from: Source address, in user space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from user space to kernel space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ *
+ * If some data could not be copied, this function will pad the copied
+ * data to the requested size using zero bytes.
+ */
+#define __copy_from_user(to,from,n)                    \
+       __generic_copy_from_user_nocheck((to),(from),(n))
+
+/**
+ * copy_from_user: - Copy a block of data from user space.
+ * @to:   Destination address, in kernel space.
+ * @from: Source address, in user space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from user space to kernel space.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ *
+ * If some data could not be copied, this function will pad the copied
+ * data to the requested size using zero bytes.
+ */
+#define copy_from_user(to,from,n)                      \
+({                                                     \
+       might_sleep();                                  \
+__generic_copy_from_user((to),(from),(n));     \
+})
+
+long __must_check strncpy_from_user(char *dst, const char __user *src,
+                               long count);
+long __must_check __strncpy_from_user(char *dst,
+                               const char __user *src, long count);
+
+/**
+ * __clear_user: - Zero a block of memory in user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+unsigned long __clear_user(void __user *mem, unsigned long len);
+
+/**
+ * clear_user: - Zero a block of memory in user space.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+unsigned long clear_user(void __user *mem, unsigned long len);
+
+/**
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ *
+ * If there is a limit on the length of a valid string, you may wish to
+ * consider using strnlen_user() instead.
+ */
+#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
+long strnlen_user(const char __user *str, long n);
+
+#endif /* _ASM_M32R_UACCESS_H */
diff --git a/include/asm-m32r/ucontext.h b/include/asm-m32r/ucontext.h
new file mode 100644 (file)
index 0000000..2de709a
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _ASM_M32R_UCONTEXT_H
+#define _ASM_M32R_UCONTEXT_H
+
+/* orig : i386 2.4.18 */
+
+struct ucontext {
+       unsigned long     uc_flags;
+       struct ucontext  *uc_link;
+       stack_t           uc_stack;
+       struct sigcontext uc_mcontext;
+       sigset_t          uc_sigmask;   /* mask last for extensibility */
+};
+
+#endif /* _ASM_M32R_UCONTEXT_H */
diff --git a/include/asm-m32r/unaligned.h b/include/asm-m32r/unaligned.h
new file mode 100644 (file)
index 0000000..3aef9ac
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _ASM_M32R_UNALIGNED_H
+#define _ASM_M32R_UNALIGNED_H
+
+/* $Id$ */
+
+/* orig : generic 2.4.18 */
+
+/*
+ * For the benefit of those who are trying to port Linux to another
+ * architecture, here are some C-language equivalents.
+ */
+
+#include <asm/string.h>
+
+
+#define get_unaligned(ptr) \
+  ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+
+#define put_unaligned(val, ptr)                                \
+  ({ __typeof__(*(ptr)) __tmp = (val);                 \
+     memmove((ptr), &__tmp, sizeof(*(ptr)));           \
+     (void)0; })
+
+
+#endif  /* _ASM_M32R_UNALIGNED_H */
diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
new file mode 100644 (file)
index 0000000..a506573
--- /dev/null
@@ -0,0 +1,483 @@
+#ifndef _ASM_M32R_UNISTD_H
+#define _ASM_M32R_UNISTD_H
+
+/* $Id$ */
+
+#include <asm/syscall.h>       /* SYSCALL_* */
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_restart_syscall     0
+#define __NR_exit                1
+#define __NR_fork                2
+#define __NR_read                3
+#define __NR_write               4
+#define __NR_open                5
+#define __NR_close               6
+#define __NR_waitpid             7
+#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_lchown             16
+#define __NR_break              17
+#define __NR_oldstat            18
+#define __NR_lseek              19
+#define __NR_getpid             20
+#define __NR_mount              21
+#define __NR_umount             22
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_ptrace             26
+#define __NR_alarm              27
+#define __NR_oldfstat           28
+#define __NR_pause              29
+#define __NR_utime              30
+#define __NR_cacheflush                 31 /* old #define __NR_stty             31*/
+#define __NR_cachectl           32 /* old #define __NR_gtty             32*/
+#define __NR_access             33
+#define __NR_nice               34
+#define __NR_ftime              35
+#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
+#define __NR_prof               44
+#define __NR_brk                45
+#define __NR_setgid             46
+#define __NR_getgid             47
+#define __NR_signal             48
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_acct               51
+#define __NR_umount2            52
+#define __NR_lock               53
+#define __NR_ioctl              54
+#define __NR_fcntl              55
+#define __NR_mpx                56
+#define __NR_setpgid            57
+#define __NR_ulimit             58
+#define __NR_oldolduname        59
+#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
+#define __NR_sigaction          67
+#define __NR_sgetmask           68
+#define __NR_ssetmask           69
+#define __NR_setreuid           70
+#define __NR_setregid           71
+#define __NR_sigsuspend                 72
+#define __NR_sigpending                 73
+#define __NR_sethostname        74
+#define __NR_setrlimit          75
+#define __NR_getrlimit          76     /* Back compatible 2Gig limited rlimit */
+#define __NR_getrusage          77
+#define __NR_gettimeofday       78
+#define __NR_settimeofday       79
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+#define __NR_select             82
+#define __NR_symlink            83
+#define __NR_oldlstat           84
+#define __NR_readlink           85
+#define __NR_uselib             86
+#define __NR_swapon             87
+#define __NR_reboot             88
+#define __NR_readdir            89
+#define __NR_mmap               90
+#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
+#define __NR_profil             98
+#define __NR_statfs             99
+#define __NR_fstatfs           100
+#define __NR_ioperm            101
+#define __NR_socketcall                102
+#define __NR_syslog            103
+#define __NR_setitimer         104
+#define __NR_getitimer         105
+#define __NR_stat              106
+#define __NR_lstat             107
+#define __NR_fstat             108
+#define __NR_olduname          109
+#define __NR_iopl              110
+#define __NR_vhangup           111
+#define __NR_idle              112
+#define __NR_vm86old           113
+#define __NR_wait4             114
+#define __NR_swapoff           115
+#define __NR_sysinfo           116
+#define __NR_ipc               117
+#define __NR_fsync             118
+#define __NR_sigreturn         119
+#define __NR_clone             120
+#define __NR_setdomainname     121
+#define __NR_uname             122
+#define __NR_modify_ldt                123
+#define __NR_adjtimex          124
+#define __NR_mprotect          125
+#define __NR_sigprocmask       126
+#define __NR_create_module     127
+#define __NR_init_module       128
+#define __NR_delete_module     129
+#define __NR_get_kernel_syms   130
+#define __NR_quotactl          131
+#define __NR_getpgid           132
+#define __NR_fchdir            133
+#define __NR_bdflush           134
+#define __NR_sysfs             135
+#define __NR_personality       136
+#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR_getdents          141
+#define __NR__newselect                142
+#define __NR_flock             143
+#define __NR_msync             144
+#define __NR_readv             145
+#define __NR_writev            146
+#define __NR_getsid            147
+#define __NR_fdatasync         148
+#define __NR__sysctl           149
+#define __NR_mlock             150
+#define __NR_munlock           151
+#define __NR_mlockall          152
+#define __NR_munlockall                153
+#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
+#define __NR_mremap            163
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+#define __NR_tas               166
+#define __NR_query_module      167
+#define __NR_poll              168
+#define __NR_nfsservctl                169
+#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_pread64           180
+#define __NR_pwrite64          181
+#define __NR_chown             182
+#define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
+#define __NR_sigaltstack       186
+#define __NR_sendfile          187
+#define __NR_getpmsg           188     /* some people actually want streams */
+#define __NR_putpmsg           189     /* some people actually want streams */
+#define __NR_vfork             190
+#define __NR_ugetrlimit                191     /* SuS compliant getrlimit */
+#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_lchown32          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_chown32           212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_pivot_root                217
+#define __NR_mincore           218
+#define __NR_madvise           219
+#define __NR_madvise1          219     /* delete when C lib stub is removed */
+#define __NR_getdents64                220
+#define __NR_fcntl64           221
+#define __NR_security           223     /* syscall for security modules */
+#define __NR_gettid             224
+#define __NR_readahead          225
+#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
+#define __NR_set_thread_area    243
+#define __NR_get_thread_area    244
+#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
+#define __NR_fadvise64          250
+
+#define __NR_exit_group         252
+#define __NR_lookup_dcookie     253
+#define __NR_epoll_create       254
+#define __NR_epoll_ctl          255
+#define __NR_epoll_wait         256
+#define __NR_remap_file_pages   257
+#define __NR_set_tid_address    258
+#define __NR_timer_create       259
+#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           268
+#define __NR_fstatfs64          269
+#define __NR_tgkill             270
+#define __NR_utimes             271
+#define __NR_fadvise64_64       272
+#define __NR_vserver            273
+#define __NR_mbind              274
+#define __NR_get_mempolicy      275
+#define __NR_set_mempolicy      276
+#define __NR_mq_open            277
+#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)
+#define __NR_sys_kexec_load    283
+#define __NR_waitid            284
+
+#define NR_syscalls 285
+
+/* user-visible error numbers are in the range -1 - -124: see
+ * <asm-m32r/errno.h>
+ */
+
+#define __syscall_return(type, res) \
+do { \
+       if ((unsigned long)(res) >= (unsigned long)(-(124 + 1))) { \
+       /* Avoid using "res" which is declared to be in register r0; \
+          errno might expand to a function call and clobber it.  */ \
+               int __err = -(res); \
+               errno = __err; \
+               res = -1; \
+       } \
+       return (type) (res); \
+} while (0)
+
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __res __asm__("r0"); \
+__asm__ __volatile__ (\
+       "trap #" SYSCALL_VECTOR \
+       : "=r" (__res) \
+       : "r" (__scno) \
+       : "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __res __asm__ ("r0") = (long)(arg1); \
+__asm__ __volatile__ (\
+       "trap #" SYSCALL_VECTOR \
+       : "=r" (__res) \
+       : "r" (__scno), "0" (__res) \
+       : "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __arg2 __asm__ ("r1") = (long)(arg2); \
+register long __res __asm__ ("r0") = (long)(arg1); \
+__asm__ __volatile__ (\
+       "trap #" SYSCALL_VECTOR \
+       : "=r" (__res) \
+       : "r" (__scno), "0" (__res), "r" (__arg2) \
+       : "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __arg3 __asm__ ("r2") = (long)(arg3); \
+register long __arg2 __asm__ ("r1") = (long)(arg2); \
+register long __res __asm__ ("r0") = (long)(arg1); \
+__asm__ __volatile__ (\
+       "trap #" SYSCALL_VECTOR \
+       : "=r" (__res) \
+       : "r" (__scno), "0" (__res), "r" (__arg2), \
+               "r" (__arg3) \
+       : "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name(type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __arg4 __asm__ ("r3") = (long)(arg4); \
+register long __arg3 __asm__ ("r2") = (long)(arg3); \
+register long __arg2 __asm__ ("r1") = (long)(arg2); \
+register long __res __asm__ ("r0") = (long)(arg1); \
+__asm__ __volatile__ (\
+       "trap #" SYSCALL_VECTOR \
+       : "=r" (__res) \
+       : "r" (__scno), "0" (__res), "r" (__arg2), \
+               "r" (__arg3), "r" (__arg4) \
+       : "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+       type5,arg5) \
+type name(type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __arg5 __asm__ ("r4") = (long)(arg5); \
+register long __arg4 __asm__ ("r3") = (long)(arg4); \
+register long __arg3 __asm__ ("r2") = (long)(arg3); \
+register long __arg2 __asm__ ("r1") = (long)(arg2); \
+register long __res __asm__ ("r0") = (long)(arg1); \
+__asm__ __volatile__ (\
+       "trap #" SYSCALL_VECTOR \
+       : "=r" (__res) \
+       : "r" (__scno), "0" (__res), "r" (__arg2), \
+               "r" (__arg3), "r" (__arg4), "r" (__arg5) \
+       : "memory"); \
+__syscall_return(type,__res); \
+}
+
+#ifdef __KERNEL__
+#define __ARCH_WANT_IPC_PARSE_VERSION
+#define __ARCH_WANT_OLD_READDIR
+#define __ARCH_WANT_OLD_STAT
+#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_SIGNAL
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_WAITPID
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGACTION
+#endif
+
+#ifdef __KERNEL_SYSCALLS__
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+
+/*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+ * is no problem, but for the stack. This is handled by not letting
+ * main() use the stack at all after fork(). Thus, no function
+ * calls - which means inline code for fork too, as otherwise we
+ * would use the stack upon exit from 'fork()'.
+ *
+ * Actually only pause and fork are needed inline, so that there
+ * won't be any messing with the stack from main(), but we define
+ * some others too.
+ */
+static __inline__ _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+
+asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount);
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+                         unsigned long prot, unsigned long flags,
+                         unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_execve(struct pt_regs regs);
+asmlinkage int sys_clone(struct pt_regs regs);
+asmlinkage int sys_fork(struct pt_regs regs);
+asmlinkage int sys_vfork(struct pt_regs regs);
+asmlinkage int sys_pipe(unsigned long __user *fildes);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+asmlinkage long sys_iopl(unsigned long unused);
+struct sigaction;
+asmlinkage long sys_rt_sigaction(int sig,
+                                const struct sigaction __user *act,
+                                struct sigaction __user *oact,
+                                size_t sigsetsize);
+
+#endif /* __KERNEL_SYSCALLS__ */
+
+/*
+ * "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
+ */
+#ifndef cond_syscall
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#endif
+
+#endif /* _ASM_M32R_UNISTD_H */
diff --git a/include/asm-m32r/user.h b/include/asm-m32r/user.h
new file mode 100644 (file)
index 0000000..2ffd0c6
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef _ASM_M32R_USER_H
+#define _ASM_M32R_USER_H
+
+/* $Id$ */
+
+/* orig : sh 2.4.18
+ * mod  : remove fpu registers
+ */
+
+#include <linux/types.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/page.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).
+ *
+ * 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 handy 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 sbrk'ed.  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 usp to
+ *     current->start_stack, so we round each of these off in order to be
+ *     able to write an integer number of pages.
+ */
+
+struct user {
+       struct pt_regs  regs;                   /* entire machine state */
+       size_t          u_tsize;                /* text size (pages) */
+       size_t          u_dsize;                /* data size (pages) */
+       size_t          u_ssize;                /* stack size (pages) */
+       unsigned long   start_code;             /* text starting address */
+       unsigned long   start_data;             /* data starting address */
+       unsigned long   start_stack;            /* stack starting address */
+       long int        signal;                 /* signal causing core dump */
+       struct regs *   u_ar0;                  /* help gdb find registers */
+       unsigned long   magic;                  /* identifies a core file */
+       char            u_comm[32];             /* user command name */
+};
+
+#define NBPG                   PAGE_SIZE
+#define UPAGES                 1
+#define HOST_TEXT_START_ADDR   (u.start_code)
+#define HOST_DATA_START_ADDR   (u.start_data)
+#define HOST_STACK_END_ADDR    (u.start_stack + u.u_ssize * NBPG)
+
+#endif /* _ASM_M32R_USER_H */
diff --git a/include/asm-m32r/vga.h b/include/asm-m32r/vga.h
new file mode 100644 (file)
index 0000000..d0f4b6e
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _ASM_M32R_VGA_H
+#define _ASM_M32R_VGA_H
+
+/* $Id$ */
+
+/*
+ *     Access to VGA videoram
+ *
+ *     (c) 1998 Martin Mares <mj@ucw.cz>
+ */
+
+/*
+ *     On the PC, we can just recalculate addresses and then
+ *     access the videoram directly without any black magic.
+ */
+
+#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x)
+
+#define vga_readb(x) (*(x))
+#define vga_writeb(x,y) (*(y) = (x))
+
+#endif  /* _ASM_M32R_VGA_H */
diff --git a/include/asm-m32r/xor.h b/include/asm-m32r/xor.h
new file mode 100644 (file)
index 0000000..fd960dc
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _ASM_M32R_XOR_H
+#define _ASM_M32R_XOR_H
+
+/* $Id$ */
+
+#include <asm-generic/xor.h>
+
+#endif  /* _ASM_M32R_XOR_H */
index 1f21b0d..3e1d226 100644 (file)
 } while (0)
 #endif
 
-#define BUG_ON(condition) do { \
-       if (unlikely((condition)!=0)) \
-               BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-       BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
index 80c86ec..c74ad77 100644 (file)
@@ -35,20 +35,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -58,27 +44,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
 #define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()   (preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()                                                     \
 do {                                                                   \
                preempt_count() -= IRQ_EXIT_OFFSET;                     \
@@ -87,6 +53,4 @@ do {                                                                  \
                preempt_enable_no_resched();                            \
 } while (0)
 
-#define synchronize_irq(irq)   barrier()
-
 #endif
index f62c54e..57e763d 100644 (file)
@@ -73,6 +73,7 @@ struct switch_stack {
 
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
index 213d4f7..ab94cf3 100644 (file)
@@ -27,21 +27,14 @@ struct semaphore {
        atomic_t count;
        atomic_t waking;
        wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-       long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-               , (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-       __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)                               \
+{                                                                      \
+       .count          = ATOMIC_INIT(n),                               \
+       .waking         = ATOMIC_INIT(0),                               \
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
 
 #define __MUTEX_INITIALIZER(name) \
        __SEMAPHORE_INITIALIZER(name,1)
@@ -86,9 +79,6 @@ static inline void down(struct semaphore *sem)
 {
        register struct semaphore *sem1 __asm__ ("%a1") = sem;
 
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        __asm__ __volatile__(
                "| atomic down operation\n\t"
@@ -109,9 +99,6 @@ static inline int down_interruptible(struct semaphore *sem)
        register struct semaphore *sem1 __asm__ ("%a1") = sem;
        register int result __asm__ ("%d0");
 
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        __asm__ __volatile__(
                "| atomic interruptible down operation\n\t"
@@ -134,10 +121,6 @@ static inline int down_trylock(struct semaphore *sem)
        register struct semaphore *sem1 __asm__ ("%a1") = sem;
        register int result __asm__ ("%d0");
 
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        __asm__ __volatile__(
                "| atomic down trylock operation\n\t"
                "subql #1,%1@\n\t"
@@ -164,10 +147,6 @@ static inline void up(struct semaphore *sem)
 {
        register struct semaphore *sem1 __asm__ ("%a1") = sem;
 
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        __asm__ __volatile__(
                "| atomic up operation\n\t"
                "addql #1,%0@\n\t"
index 68a33bf..8d0b9fc 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
index 5a9c74c..f0f36fc 100644 (file)
@@ -51,7 +51,7 @@ asmlinkage void resume(void);
 #if 0
 #define local_irq_enable() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory")
 #else
-#include <asm/hardirq.h>
+#include <linux/hardirq.h>
 #define local_irq_enable() ({                                                  \
        if (MACH_IS_Q40 || !hardirq_count())                                    \
                asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory");    \
index bc027ea..70e7dc0 100644 (file)
@@ -1,24 +1,4 @@
 #ifndef _M68KNOMMU_BUG_H
 #define _M68KNOMMU_BUG_H
-
-#define BUG() do { \
-  printk("%s(%d): kernel BUG!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define BUG_ON(condition) do { \
-       if (unlikely((condition)!=0)) \
-               BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-         BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
index f8dbdf2..840eac2 100644 (file)
@@ -36,20 +36,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -59,33 +45,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
 #define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()   (preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()                                                     \
 do {                                                                   \
                preempt_count() -= IRQ_EXIT_OFFSET;                     \
@@ -94,10 +54,4 @@ do {                                                                 \
                preempt_enable_no_resched();                            \
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)  barrier()
-#else
-# error m68knommu SMP is not available
-#endif /* CONFIG_SMP */
-
 #endif /* __M68K_HARDIRQ_H */
index ac38686..f65bd90 100644 (file)
@@ -84,6 +84,7 @@ struct switch_stack {
 
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
index f85d311..febe85a 100644 (file)
@@ -26,21 +26,14 @@ struct semaphore {
        atomic_t count;
        atomic_t waking;
        wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-       long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-               , (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-       __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)                               \
+{                                                                      \
+       .count          = ATOMIC_INIT(n),                               \
+       .waking         = ATOMIC_INIT(0),                               \
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
 
 #define __MUTEX_INITIALIZER(name) \
        __SEMAPHORE_INITIALIZER(name,1)
@@ -85,9 +78,6 @@ extern spinlock_t semaphore_wake_lock;
  */
 extern inline void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        __asm__ __volatile__(
                "| atomic down operation\n\t"
@@ -105,9 +95,6 @@ extern inline int down_interruptible(struct semaphore * sem)
 {
        int ret;
 
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        __asm__ __volatile__(
                "| atomic down operation\n\t"
@@ -128,10 +115,6 @@ extern inline int down_trylock(struct semaphore * sem)
        register struct semaphore *sem1 __asm__ ("%a1") = sem;
        register int result __asm__ ("%d0");
 
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        __asm__ __volatile__(
                "| atomic down trylock operation\n\t"
                "subql #1,%1@\n\t"
@@ -157,10 +140,6 @@ extern inline int down_trylock(struct semaphore * sem)
  */
 extern inline void up(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        __asm__ __volatile__(
                "| atomic up operation\n\t"
                "movel  %0, %%a1\n\t"
index f1f483d..eb94bb9 100644 (file)
@@ -7,14 +7,8 @@
 do {                                                                   \
        __asm__ __volatile__("break %0" : : "i" (BRK_BUG));             \
 } while (0)
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-#define PAGE_BUG(page) do {  BUG(); } while (0)
 
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-       dump_stack(); \
-       } \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
index a11cf99..7169511 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_DMA_MAPPING_H
 #define _ASM_DMA_MAPPING_H
 
-#include <linux/device.h>
 #include <asm/scatterlist.h>
 #include <asm/cache.h>
 
index a045970..7562703 100644 (file)
@@ -43,20 +43,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -66,27 +52,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
 #define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()   ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()                                                     \
 do {                                                                   \
        preempt_count() -= IRQ_EXIT_OFFSET;                     \
@@ -95,10 +61,4 @@ do {                                                                   \
        preempt_enable_no_resched();                            \
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)  barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* _ASM_HARDIRQ_H */
index c980cb9..fec2169 100644 (file)
@@ -47,8 +47,8 @@ typedef struct siginfo {
                struct {
                        pid_t _pid;             /* which child */
                        uid_t _uid;             /* sender's uid */
-                       clock_t _utime;
                        int _status;            /* exit code */
+                       clock_t _utime;
                        clock_t _stime;
                } _sigchld;
 
index 6556c10..eba99d2 100644 (file)
@@ -68,20 +68,31 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse.  */
 
 #define SO_PEERSEC             30
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_DGRAM     1               /* datagram (conn.less) socket  */
-#define SOCK_STREAM    2               /* stream (connection) socket   */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
+/** sock_type - Socket types
+ *
+ * Please notice that for binary compat reasons MIPS has to
+ * override the enum sock_type in include/linux/net.h, so
+ * we define ARCH_HAS_SOCKET_TYPES here.
+ *
+ * @SOCK_DGRAM - datagram (conn.less) socket
+ * @SOCK_STREAM - stream (connection) socket
+ * @SOCK_RAW - raw socket
+ * @SOCK_RDM - reliably-delivered message
+ * @SOCK_SEQPACKET - sequential packet socket 
+ * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+ *               For writing rarp and other similar things on the user level.
+ */
+enum sock_type {
+       SOCK_DGRAM      = 1,
+       SOCK_STREAM     = 2,
+       SOCK_RAW        = 3,
+       SOCK_RDM        = 4,
+       SOCK_SEQPACKET  = 5,
+       SOCK_PACKET     = 10,
+};
+
+#define SOCK_MAX (SOCK_PACKET + 1)
+
+#define ARCH_HAS_SOCKET_TYPES
 
 #endif /* _ASM_SOCKET_H */
index 00d6aa7..98d36ad 100644 (file)
@@ -1,29 +1,4 @@
 #ifndef _PARISC_BUG_H
 #define _PARISC_BUG_H
-
-/*
- * Tell the user there is some problem.
- */
-#define BUG() do { \
-       extern void dump_stack(void); \
-       printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-       dump_stack(); \
-} while (0)
-
-#define BUG_ON(condition) do { \
-       if (unlikely((condition)!=0)) \
-               BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-       BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
index dc9b4b7..7ebdebb 100644 (file)
@@ -51,20 +51,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space for potentially all IRQ sources
  * in the system nesting on a single CPU:
@@ -73,29 +59,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context?
- * Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
 #define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# error CONFIG_PREEMT currently not supported.
-# define in_atomic()    BUG()
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()                                                             \
 do {                                                                           \
                preempt_count() -= IRQ_EXIT_OFFSET;                             \
@@ -104,10 +68,4 @@ do {                                                                                \
                preempt_enable_no_resched();                                    \
 } while (0)
 
-#ifdef CONFIG_SMP
-  extern void synchronize_irq (unsigned int irq);
-#else
-# define synchronize_irq(irq)  barrier()
-#endif /* CONFIG_SMP */
-
 #endif /* _PARISC_HARDIRQ_H */
index 181fc75..c276c09 100644 (file)
@@ -48,6 +48,7 @@ struct pt_regs {
 /* XXX should we use iaoq[1] or iaoq[0] ? */
 #define user_mode(regs)                        (((regs)->iaoq[0] &  3) ? 1 : 0)
 #define instruction_pointer(regs)      ((regs)->iaoq[0] & ~3)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif
 
index f9ab172..f78bb2e 100644 (file)
@@ -40,21 +40,14 @@ struct semaphore {
        spinlock_t      sentry;
        int             count;
        wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-       long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-               , (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ SPIN_LOCK_UNLOCKED, count, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-       __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)                               \
+{                                                                      \
+       .sentry         = SPIN_LOCK_UNLOCKED,                           \
+       .count          = n,                                            \
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
 
 #define __MUTEX_INITIALIZER(name) \
        __SEMAPHORE_INITIALIZER(name,1)
@@ -95,9 +88,6 @@ asmlinkage void __up(struct semaphore * sem);
 
 extern __inline__ void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        spin_lock_irq(&sem->sentry);
        if (sem->count > 0) {
@@ -111,9 +101,6 @@ extern __inline__ void down(struct semaphore * sem)
 extern __inline__ int down_interruptible(struct semaphore * sem)
 {
        int ret = 0;
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
        spin_lock_irq(&sem->sentry);
        if (sem->count > 0) {
@@ -132,9 +119,6 @@ extern __inline__ int down_interruptible(struct semaphore * sem)
 extern __inline__ int down_trylock(struct semaphore * sem)
 {
        int flags, count;
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
 
        spin_lock_irqsave(&sem->sentry, flags);
        count = sem->count - 1;
@@ -151,9 +135,6 @@ extern __inline__ int down_trylock(struct semaphore * sem)
 extern __inline__ void up(struct semaphore * sem)
 {
        int flags;
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        spin_lock_irqsave(&sem->sentry, flags);
        if (sem->count < 0) {
                __up(sem);
index fd3f0f2..4a77996 100644 (file)
 
 #define SO_PEERSEC             0x401d
 
-#if defined(__KERNEL__)
-#define SOCK_STREAM    1       /* stream (connection) socket   */
-#define SOCK_DGRAM     2       /* datagram (conn.less) socket  */
-#define SOCK_RAW       3       /* raw socket                   */
-#define SOCK_RDM       4       /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5       /* sequential packet socket     */
-#define SOCK_PACKET    10      /* linux specific way of        */
-                               /* getting packets at the dev   */
-                               /* level.  For writing rarp and */
-                               /* other similar things on the  */
-                               /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-ppc/8253pit.h b/include/asm-ppc/8253pit.h
new file mode 100644 (file)
index 0000000..285f784
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * 8253/8254 Programmable Interval Timer
+ */
+
+#ifndef _8253PIT_H
+#define _8253PIT_H
+
+#define PIT_TICK_RATE  1193182UL
+
+#endif
index 6b2579d..e99c6cb 100644 (file)
@@ -35,8 +35,6 @@ struct bug_entry {
        }                                                               \
 } while (0)
 
-#define PAGE_BUG(page) BUG()
-
 #define WARN_ON(x) do {                                                        \
        if (!__builtin_constant_p(x) || (x)) {                          \
                __asm__ __volatile__(                                   \
@@ -49,4 +47,9 @@ struct bug_entry {
        }                                                               \
 } while (0)
 
+#define HAVE_ARCH_BUG
+#define HAVE_ARCH_BUG_ON
+#define HAVE_ARCH_WARN_ON
+#include <asm-generic/bug.h>
+
 #endif
index d98a93d..cf953a9 100644 (file)
@@ -33,7 +33,7 @@ extern unsigned int csum_partial_copy_generic(const char *src, char *dst,
                                              int *src_err, int *dst_err);
 
 #define csum_partial_copy_from_user(src, dst, len, sum, errp)  \
-       csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL)
+       csum_partial_copy_generic((__force void *)(src), (dst), (len), (sum), (errp), NULL)
 
 /* FIXME: this needs to be written to really do no check -- Cort */
 #define csum_partial_copy_nocheck(src, dst, len, sum)  \
index 9f88999..050fbba 100644 (file)
@@ -48,7 +48,7 @@ struct ocp_fs_i2c_data {
 
 /* Flags for I2C */
 #define FS_I2C_SEPARATE_DFSRR  0x02
-#define FS_I2C_32BIT           0x01
+#define FS_I2C_CLOCK_5200      0x01
 
 #endif /* __ASM_FS_OCP_H__ */
 #endif /* __KERNEL__ */
index 2531c3b..dfb8472 100644 (file)
@@ -44,20 +44,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -67,31 +53,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
 #define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()   ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define preemptible() (preempt_count() == 0 && !irqs_disabled())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define preemptible() 0
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()                                                     \
 do {                                                                   \
        preempt_count() -= IRQ_EXIT_OFFSET;                             \
@@ -100,11 +62,5 @@ do {                                                                        \
        preempt_enable_no_resched();                                    \
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)  barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* __ASM_HARDIRQ_H */
 #endif /* __KERNEL__ */
index 4fb6e57..76e4402 100644 (file)
@@ -42,6 +42,7 @@ struct ocp_def;
 #define MPC52xx_MBAR_VIRT      0xf0000000      /* Virt address */
 
 #define MPC52xx_MMAP_CTL       (MPC52xx_MBAR + 0x0000)
+#define MPC52xx_SDRAM          (MPC52xx_MBAR + 0x0100)
 #define MPC52xx_CDM            (MPC52xx_MBAR + 0x0200)
 #define MPC52xx_SFTRST         (MPC52xx_MBAR + 0x0220)
 #define MPC52xx_SFTRST_BIT     0x01000000
@@ -51,6 +52,7 @@ struct ocp_def;
 #define MPC52xx_MSCAN1         (MPC52xx_MBAR + 0x0900)
 #define MPC52xx_MSCAN2         (MPC52xx_MBAR + 0x0980)
 #define MPC52xx_GPIO           (MPC52xx_MBAR + 0x0b00)
+#define MPC52xx_GPIO_WKUP      (MPC52xx_MBAR + 0x0c00)
 #define MPC52xx_PCI            (MPC52xx_MBAR + 0x0d00)
 #define MPC52xx_USB_OHCI       (MPC52xx_MBAR + 0x1000)
 #define MPC52xx_SDMA           (MPC52xx_MBAR + 0x1200)
@@ -71,10 +73,6 @@ struct ocp_def;
 /* SRAM used for SDMA */
 #define MPC52xx_SRAM           (MPC52xx_MBAR + 0x8000)
 #define MPC52xx_SRAM_SIZE      (16*1024)
-#define MPC52xx_SDMA_MAX_TASKS 16
-
-       /* Memory allocation block size */
-#define MPC52xx_SDRAM_UNIT     0x8000          /* 32K byte */
 
 
 /* ======================================================================== */
@@ -137,206 +135,240 @@ struct ocp_def;
 
 /* Memory Mapping Control */
 struct mpc52xx_mmap_ctl {
-       volatile u32    mbar;           /* MMAP_CTRL + 0x00 */
-
-       volatile u32    cs0_start;      /* MMAP_CTRL + 0x04 */
-       volatile u32    cs0_stop;       /* MMAP_CTRL + 0x08 */
-       volatile u32    cs1_start;      /* MMAP_CTRL + 0x0c */
-       volatile u32    cs1_stop;       /* MMAP_CTRL + 0x10 */
-       volatile u32    cs2_start;      /* MMAP_CTRL + 0x14 */
-       volatile u32    cs2_stop;       /* MMAP_CTRL + 0x18 */
-       volatile u32    cs3_start;      /* MMAP_CTRL + 0x1c */
-       volatile u32    cs3_stop;       /* MMAP_CTRL + 0x20 */
-       volatile u32    cs4_start;      /* MMAP_CTRL + 0x24 */
-       volatile u32    cs4_stop;       /* MMAP_CTRL + 0x28 */
-       volatile u32    cs5_start;      /* MMAP_CTRL + 0x2c */
-       volatile u32    cs5_stop;       /* MMAP_CTRL + 0x30 */
-
-       volatile u32    sdram0;         /* MMAP_CTRL + 0x34 */
-       volatile u32    sdram1;         /* MMAP_CTRL + 0X38 */
-
-       volatile u32    reserved[4];    /* MMAP_CTRL + 0x3c .. 0x48 */
-
-       volatile u32    boot_start;     /* MMAP_CTRL + 0x4c */
-       volatile u32    boot_stop;      /* MMAP_CTRL + 0x50 */
-       
-       volatile u32    ipbi_ws_ctrl;   /* MMAP_CTRL + 0x54 */
-       
-       volatile u32    cs6_start;      /* MMAP_CTRL + 0x58 */
-       volatile u32    cs6_stop;       /* MMAP_CTRL + 0x5c */
-       volatile u32    cs7_start;      /* MMAP_CTRL + 0x60 */
-       volatile u32    cs7_stop;       /* MMAP_CTRL + 0x60 */
+       u32     mbar;           /* MMAP_CTRL + 0x00 */
+
+       u32     cs0_start;      /* MMAP_CTRL + 0x04 */
+       u32     cs0_stop;       /* MMAP_CTRL + 0x08 */
+       u32     cs1_start;      /* MMAP_CTRL + 0x0c */
+       u32     cs1_stop;       /* MMAP_CTRL + 0x10 */
+       u32     cs2_start;      /* MMAP_CTRL + 0x14 */
+       u32     cs2_stop;       /* MMAP_CTRL + 0x18 */
+       u32     cs3_start;      /* MMAP_CTRL + 0x1c */
+       u32     cs3_stop;       /* MMAP_CTRL + 0x20 */
+       u32     cs4_start;      /* MMAP_CTRL + 0x24 */
+       u32     cs4_stop;       /* MMAP_CTRL + 0x28 */
+       u32     cs5_start;      /* MMAP_CTRL + 0x2c */
+       u32     cs5_stop;       /* MMAP_CTRL + 0x30 */
+
+       u32     sdram0;         /* MMAP_CTRL + 0x34 */
+       u32     sdram1;         /* MMAP_CTRL + 0X38 */
+
+       u32     reserved[4];    /* MMAP_CTRL + 0x3c .. 0x48 */
+
+       u32     boot_start;     /* MMAP_CTRL + 0x4c */
+       u32     boot_stop;      /* MMAP_CTRL + 0x50 */
+
+       u32     ipbi_ws_ctrl;   /* MMAP_CTRL + 0x54 */
+
+       u32     cs6_start;      /* MMAP_CTRL + 0x58 */
+       u32     cs6_stop;       /* MMAP_CTRL + 0x5c */
+       u32     cs7_start;      /* MMAP_CTRL + 0x60 */
+       u32     cs7_stop;       /* MMAP_CTRL + 0x60 */
+};
+
+/* SDRAM control */
+struct mpc52xx_sdram {
+       u32     mode;           /* SDRAM + 0x00 */
+       u32     ctrl;           /* SDRAM + 0x04 */
+       u32     config1;        /* SDRAM + 0x08 */
+       u32     config2;        /* SDRAM + 0x0c */
 };
 
 /* Interrupt controller */
 struct mpc52xx_intr {
-       volatile u32    per_mask;       /* INTR + 0x00 */
-       volatile u32    per_pri1;       /* INTR + 0x04 */
-       volatile u32    per_pri2;       /* INTR + 0x08 */
-       volatile u32    per_pri3;       /* INTR + 0x0c */
-       volatile u32    ctrl;           /* INTR + 0x10 */
-       volatile u32    main_mask;      /* INTR + 0x14 */
-       volatile u32    main_pri1;      /* INTR + 0x18 */
-       volatile u32    main_pri2;      /* INTR + 0x1c */
-       volatile u32    reserved1;      /* INTR + 0x20 */
-       volatile u32    enc_status;     /* INTR + 0x24 */
-       volatile u32    crit_status;    /* INTR + 0x28 */
-       volatile u32    main_status;    /* INTR + 0x2c */
-       volatile u32    per_status;     /* INTR + 0x30 */
-       volatile u32    reserved2;      /* INTR + 0x34 */
-       volatile u32    per_error;      /* INTR + 0x38 */
+       u32     per_mask;       /* INTR + 0x00 */
+       u32     per_pri1;       /* INTR + 0x04 */
+       u32     per_pri2;       /* INTR + 0x08 */
+       u32     per_pri3;       /* INTR + 0x0c */
+       u32     ctrl;           /* INTR + 0x10 */
+       u32     main_mask;      /* INTR + 0x14 */
+       u32     main_pri1;      /* INTR + 0x18 */
+       u32     main_pri2;      /* INTR + 0x1c */
+       u32     reserved1;      /* INTR + 0x20 */
+       u32     enc_status;     /* INTR + 0x24 */
+       u32     crit_status;    /* INTR + 0x28 */
+       u32     main_status;    /* INTR + 0x2c */
+       u32     per_status;     /* INTR + 0x30 */
+       u32     reserved2;      /* INTR + 0x34 */
+       u32     per_error;      /* INTR + 0x38 */
 };
 
 /* SDMA */
 struct mpc52xx_sdma {
-       volatile u32    taskBar;        /* SDMA + 0x00 */
-       volatile u32    currentPointer; /* SDMA + 0x04 */
-       volatile u32    endPointer;     /* SDMA + 0x08 */
-       volatile u32    variablePointer;/* SDMA + 0x0c */
-
-       volatile u8     IntVect1;       /* SDMA + 0x10 */
-       volatile u8     IntVect2;       /* SDMA + 0x11 */
-       volatile u16    PtdCntrl;       /* SDMA + 0x12 */
-
-       volatile u32    IntPend;        /* SDMA + 0x14 */
-       volatile u32    IntMask;        /* SDMA + 0x18 */
-       
-       volatile u16    tcr[16];        /* SDMA + 0x1c .. 0x3a */
-
-       volatile u8     ipr[31];        /* SDMA + 0x3c .. 5b */
-
-       volatile u32    res1;           /* SDMA + 0x5c */
-       volatile u32    task_size0;     /* SDMA + 0x60 */
-       volatile u32    task_size1;     /* SDMA + 0x64 */
-       volatile u32    MDEDebug;       /* SDMA + 0x68 */
-       volatile u32    ADSDebug;       /* SDMA + 0x6c */
-       volatile u32    Value1;         /* SDMA + 0x70 */
-       volatile u32    Value2;         /* SDMA + 0x74 */
-       volatile u32    Control;        /* SDMA + 0x78 */
-       volatile u32    Status;         /* SDMA + 0x7c */
+       u32     taskBar;        /* SDMA + 0x00 */
+       u32     currentPointer; /* SDMA + 0x04 */
+       u32     endPointer;     /* SDMA + 0x08 */
+       u32     variablePointer;/* SDMA + 0x0c */
+
+       u8      IntVect1;       /* SDMA + 0x10 */
+       u8      IntVect2;       /* SDMA + 0x11 */
+       u16     PtdCntrl;       /* SDMA + 0x12 */
+
+       u32     IntPend;        /* SDMA + 0x14 */
+       u32     IntMask;        /* SDMA + 0x18 */
+
+       u16     tcr[16];        /* SDMA + 0x1c .. 0x3a */
+
+       u8      ipr[32];        /* SDMA + 0x3c .. 5b */
+
+       u32     cReqSelect;     /* SDMA + 0x5c */
+       u32     task_size0;     /* SDMA + 0x60 */
+       u32     task_size1;     /* SDMA + 0x64 */
+       u32     MDEDebug;       /* SDMA + 0x68 */
+       u32     ADSDebug;       /* SDMA + 0x6c */
+       u32     Value1;         /* SDMA + 0x70 */
+       u32     Value2;         /* SDMA + 0x74 */
+       u32     Control;        /* SDMA + 0x78 */
+       u32     Status;         /* SDMA + 0x7c */
+       u32     PTDDebug;       /* SDMA + 0x80 */
 };
 
 /* GPT */
 struct mpc52xx_gpt {
-       volatile u32    mode;           /* GPTx + 0x00 */
-       volatile u32    count;          /* GPTx + 0x04 */
-       volatile u32    pwm;            /* GPTx + 0x08 */
-       volatile u32    status;         /* GPTx + 0X0c */
+       u32     mode;           /* GPTx + 0x00 */
+       u32     count;          /* GPTx + 0x04 */
+       u32     pwm;            /* GPTx + 0x08 */
+       u32     status;         /* GPTx + 0X0c */
 };
 
 /* RTC */
 struct mpc52xx_rtc {
-       volatile u32    time_set;       /* RTC + 0x00 */
-       volatile u32    date_set;       /* RTC + 0x04 */
-       volatile u32    stopwatch;      /* RTC + 0x08 */
-       volatile u32    int_enable;     /* RTC + 0x0c */
-       volatile u32    time;           /* RTC + 0x10 */
-       volatile u32    date;           /* RTC + 0x14 */
-       volatile u32    stopwatch_intr; /* RTC + 0x18 */
-       volatile u32    bus_error;      /* RTC + 0x1c */
-       volatile u32    dividers;       /* RTC + 0x20 */
+       u32     time_set;       /* RTC + 0x00 */
+       u32     date_set;       /* RTC + 0x04 */
+       u32     stopwatch;      /* RTC + 0x08 */
+       u32     int_enable;     /* RTC + 0x0c */
+       u32     time;           /* RTC + 0x10 */
+       u32     date;           /* RTC + 0x14 */
+       u32     stopwatch_intr; /* RTC + 0x18 */
+       u32     bus_error;      /* RTC + 0x1c */
+       u32     dividers;       /* RTC + 0x20 */
 };
 
 /* GPIO */
 struct mpc52xx_gpio {
-       volatile u32    port_config;    /* GPIO + 0x00 */
-       volatile u32    simple_gpioe;   /* GPIO + 0x04 */
-       volatile u32    simple_ode;     /* GPIO + 0x08 */
-       volatile u32    simple_ddr;     /* GPIO + 0x0c */
-       volatile u32    simple_dvo;     /* GPIO + 0x10 */
-       volatile u32    simple_ival;    /* GPIO + 0x14 */
-       volatile u8     outo_gpioe;     /* GPIO + 0x18 */
-       volatile u8     reserved1[3];   /* GPIO + 0x19 */
-       volatile u8     outo_dvo;       /* GPIO + 0x1c */
-       volatile u8     reserved2[3];   /* GPIO + 0x1d */
-       volatile u8     sint_gpioe;     /* GPIO + 0x20 */
-       volatile u8     reserved3[3];   /* GPIO + 0x21 */
-       volatile u8     sint_ode;       /* GPIO + 0x24 */
-       volatile u8     reserved4[3];   /* GPIO + 0x25 */
-       volatile u8     sint_ddr;       /* GPIO + 0x28 */
-       volatile u8     reserved5[3];   /* GPIO + 0x29 */
-       volatile u8     sint_dvo;       /* GPIO + 0x2c */
-       volatile u8     reserved6[3];   /* GPIO + 0x2d */
-       volatile u8     sint_inten;     /* GPIO + 0x30 */
-       volatile u8     reserved7[3];   /* GPIO + 0x31 */
-       volatile u16    sint_itype;     /* GPIO + 0x34 */
-       volatile u16    reserved8;      /* GPIO + 0x36 */
-       volatile u8     gpio_control;   /* GPIO + 0x38 */
-       volatile u8     reserved9[3];   /* GPIO + 0x39 */
-       volatile u8     sint_istat;     /* GPIO + 0x3c */
-       volatile u8     sint_ival;      /* GPIO + 0x3d */
-       volatile u8     bus_errs;       /* GPIO + 0x3e */
-       volatile u8     reserved10;     /* GPIO + 0x3f */
+       u32     port_config;    /* GPIO + 0x00 */
+       u32     simple_gpioe;   /* GPIO + 0x04 */
+       u32     simple_ode;     /* GPIO + 0x08 */
+       u32     simple_ddr;     /* GPIO + 0x0c */
+       u32     simple_dvo;     /* GPIO + 0x10 */
+       u32     simple_ival;    /* GPIO + 0x14 */
+       u8      outo_gpioe;     /* GPIO + 0x18 */
+       u8      reserved1[3];   /* GPIO + 0x19 */
+       u8      outo_dvo;       /* GPIO + 0x1c */
+       u8      reserved2[3];   /* GPIO + 0x1d */
+       u8      sint_gpioe;     /* GPIO + 0x20 */
+       u8      reserved3[3];   /* GPIO + 0x21 */
+       u8      sint_ode;       /* GPIO + 0x24 */
+       u8      reserved4[3];   /* GPIO + 0x25 */
+       u8      sint_ddr;       /* GPIO + 0x28 */
+       u8      reserved5[3];   /* GPIO + 0x29 */
+       u8      sint_dvo;       /* GPIO + 0x2c */
+       u8      reserved6[3];   /* GPIO + 0x2d */
+       u8      sint_inten;     /* GPIO + 0x30 */
+       u8      reserved7[3];   /* GPIO + 0x31 */
+       u16     sint_itype;     /* GPIO + 0x34 */
+       u16     reserved8;      /* GPIO + 0x36 */
+       u8      gpio_control;   /* GPIO + 0x38 */
+       u8      reserved9[3];   /* GPIO + 0x39 */
+       u8      sint_istat;     /* GPIO + 0x3c */
+       u8      sint_ival;      /* GPIO + 0x3d */
+       u8      bus_errs;       /* GPIO + 0x3e */
+       u8      reserved10;     /* GPIO + 0x3f */
 };
 
 #define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD        4
 #define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD   5
 #define MPC52xx_GPIO_PCI_DIS                   (1<<15)
 
+/* GPIO with WakeUp*/
+struct mpc52xx_gpio_wkup {
+       u8      wkup_gpioe;     /* GPIO_WKUP + 0x00 */
+       u8      reserved1[3];   /* GPIO_WKUP + 0x03 */
+       u8      wkup_ode;       /* GPIO_WKUP + 0x04 */
+       u8      reserved2[3];   /* GPIO_WKUP + 0x05 */
+       u8      wkup_ddr;       /* GPIO_WKUP + 0x08 */
+       u8      reserved3[3];   /* GPIO_WKUP + 0x09 */
+       u8      wkup_dvo;       /* GPIO_WKUP + 0x0C */
+       u8      reserved4[3];   /* GPIO_WKUP + 0x0D */
+       u8      wkup_inten;     /* GPIO_WKUP + 0x10 */
+       u8      reserved5[3];   /* GPIO_WKUP + 0x11 */
+       u8      wkup_iinten;    /* GPIO_WKUP + 0x14 */
+       u8      reserved6[3];   /* GPIO_WKUP + 0x15 */
+       u16     wkup_itype;     /* GPIO_WKUP + 0x18 */
+       u8      reserved7[2];   /* GPIO_WKUP + 0x1A */
+       u8      wkup_maste;     /* GPIO_WKUP + 0x1C */
+       u8      reserved8[3];   /* GPIO_WKUP + 0x1D */
+       u8      wkup_ival;      /* GPIO_WKUP + 0x20 */
+       u8      reserved9[3];   /* GPIO_WKUP + 0x21 */
+       u8      wkup_istat;     /* GPIO_WKUP + 0x24 */
+       u8      reserved10[3];  /* GPIO_WKUP + 0x25 */
+};
+
 /* XLB Bus control */
 struct mpc52xx_xlb {
-       volatile u8 reserved[0x40];
-       volatile u32 config;            /* XLB + 0x40 */
-       volatile u32 version;           /* XLB + 0x44 */
-       volatile u32 status;            /* XLB + 0x48 */
-       volatile u32 int_enable;        /* XLB + 0x4c */
-       volatile u32 addr_capture;      /* XLB + 0x50 */
-       volatile u32 bus_sig_capture;   /* XLB + 0x54 */
-       volatile u32 addr_timeout;      /* XLB + 0x58 */
-       volatile u32 data_timeout;      /* XLB + 0x5c */
-       volatile u32 bus_act_timeout;   /* XLB + 0x60 */
-       volatile u32 master_pri_enable; /* XLB + 0x64 */
-       volatile u32 master_priority;   /* XLB + 0x68 */
-       volatile u32 base_address;      /* XLB + 0x6c */
-       volatile u32 snoop_window;      /* XLB + 0x70 */
+       u8      reserved[0x40];
+       u32     config;                 /* XLB + 0x40 */
+       u32     version;                /* XLB + 0x44 */
+       u32     status;                 /* XLB + 0x48 */
+       u32     int_enable;             /* XLB + 0x4c */
+       u32     addr_capture;           /* XLB + 0x50 */
+       u32     bus_sig_capture;        /* XLB + 0x54 */
+       u32     addr_timeout;           /* XLB + 0x58 */
+       u32     data_timeout;           /* XLB + 0x5c */
+       u32     bus_act_timeout;        /* XLB + 0x60 */
+       u32     master_pri_enable;      /* XLB + 0x64 */
+       u32     master_priority;        /* XLB + 0x68 */
+       u32     base_address;           /* XLB + 0x6c */
+       u32     snoop_window;           /* XLB + 0x70 */
 };
 
+#define MPC52xx_XLB_CFG_SNOOP          (1 << 15)
 
 /* Clock Distribution control */
 struct mpc52xx_cdm {
-       volatile u32    jtag_id;        /* MBAR_CDM + 0x00  reg0 read only */
-       volatile u32    rstcfg;         /* MBAR_CDM + 0x04  reg1 read only */
-       volatile u32    breadcrumb;     /* MBAR_CDM + 0x08  reg2 */
-
-       volatile u8     mem_clk_sel;    /* MBAR_CDM + 0x0c  reg3 byte0 */
-       volatile u8     xlb_clk_sel;    /* MBAR_CDM + 0x0d  reg3 byte1 read only */
-       volatile u8     ipb_clk_sel;    /* MBAR_CDM + 0x0e  reg3 byte2 */
-       volatile u8     pci_clk_sel;    /* MBAR_CDM + 0x0f  reg3 byte3 */
-
-       volatile u8     ext_48mhz_en;   /* MBAR_CDM + 0x10  reg4 byte0 */
-       volatile u8     fd_enable;      /* MBAR_CDM + 0x11  reg4 byte1 */
-       volatile u16    fd_counters;    /* MBAR_CDM + 0x12  reg4 byte2,3 */
-
-       volatile u32    clk_enables;    /* MBAR_CDM + 0x14  reg5 */
-
-       volatile u8     osc_disable;    /* MBAR_CDM + 0x18  reg6 byte0 */
-       volatile u8     reserved0[3];   /* MBAR_CDM + 0x19  reg6 byte1,2,3 */
-
-       volatile u8     ccs_sleep_enable;/* MBAR_CDM + 0x1c  reg7 byte0 */
-       volatile u8     osc_sleep_enable;/* MBAR_CDM + 0x1d  reg7 byte1 */
-       volatile u8     reserved1;      /* MBAR_CDM + 0x1e  reg7 byte2 */
-       volatile u8     ccs_qreq_test;  /* MBAR_CDM + 0x1f  reg7 byte3 */
-
-       volatile u8     soft_reset;     /* MBAR_CDM + 0x20  u8 byte0 */
-       volatile u8     no_ckstp;       /* MBAR_CDM + 0x21  u8 byte0 */
-       volatile u8     reserved2[2];   /* MBAR_CDM + 0x22  u8 byte1,2,3 */
-
-       volatile u8     pll_lock;       /* MBAR_CDM + 0x24  reg9 byte0 */
-       volatile u8     pll_looselock;  /* MBAR_CDM + 0x25  reg9 byte1 */
-       volatile u8     pll_sm_lockwin; /* MBAR_CDM + 0x26  reg9 byte2 */
-       volatile u8     reserved3;      /* MBAR_CDM + 0x27  reg9 byte3 */
-
-       volatile u16    reserved4;      /* MBAR_CDM + 0x28  reg10 byte0,1 */
-       volatile u16    mclken_div_psc1;/* MBAR_CDM + 0x2a  reg10 byte2,3 */
-    
-       volatile u16    reserved5;      /* MBAR_CDM + 0x2c  reg11 byte0,1 */
-       volatile u16    mclken_div_psc2;/* MBAR_CDM + 0x2e  reg11 byte2,3 */
-               
-       volatile u16    reserved6;      /* MBAR_CDM + 0x30  reg12 byte0,1 */
-       volatile u16    mclken_div_psc3;/* MBAR_CDM + 0x32  reg12 byte2,3 */
-    
-       volatile u16    reserved7;      /* MBAR_CDM + 0x34  reg13 byte0,1 */
-       volatile u16    mclken_div_psc6;/* MBAR_CDM + 0x36  reg13 byte2,3 */
+       u32     jtag_id;                /* CDM + 0x00  reg0 read only */
+       u32     rstcfg;                 /* CDM + 0x04  reg1 read only */
+       u32     breadcrumb;             /* CDM + 0x08  reg2 */
+
+       u8      mem_clk_sel;            /* CDM + 0x0c  reg3 byte0 */
+       u8      xlb_clk_sel;            /* CDM + 0x0d  reg3 byte1 read only */
+       u8      ipb_clk_sel;            /* CDM + 0x0e  reg3 byte2 */
+       u8      pci_clk_sel;            /* CDM + 0x0f  reg3 byte3 */
+
+       u8      ext_48mhz_en;           /* CDM + 0x10  reg4 byte0 */
+       u8      fd_enable;              /* CDM + 0x11  reg4 byte1 */
+       u16     fd_counters;            /* CDM + 0x12  reg4 byte2,3 */
+
+       u32     clk_enables;            /* CDM + 0x14  reg5 */
+
+       u8      osc_disable;            /* CDM + 0x18  reg6 byte0 */
+       u8      reserved0[3];           /* CDM + 0x19  reg6 byte1,2,3 */
+
+       u8      ccs_sleep_enable;       /* CDM + 0x1c  reg7 byte0 */
+       u8      osc_sleep_enable;       /* CDM + 0x1d  reg7 byte1 */
+       u8      reserved1;              /* CDM + 0x1e  reg7 byte2 */
+       u8      ccs_qreq_test;          /* CDM + 0x1f  reg7 byte3 */
+
+       u8      soft_reset;             /* CDM + 0x20  u8 byte0 */
+       u8      no_ckstp;               /* CDM + 0x21  u8 byte0 */
+       u8      reserved2[2];           /* CDM + 0x22  u8 byte1,2,3 */
+
+       u8      pll_lock;               /* CDM + 0x24  reg9 byte0 */
+       u8      pll_looselock;          /* CDM + 0x25  reg9 byte1 */
+       u8      pll_sm_lockwin;         /* CDM + 0x26  reg9 byte2 */
+       u8      reserved3;              /* CDM + 0x27  reg9 byte3 */
+
+       u16     reserved4;              /* CDM + 0x28  reg10 byte0,1 */
+       u16     mclken_div_psc1;        /* CDM + 0x2a  reg10 byte2,3 */
+
+       u16     reserved5;              /* CDM + 0x2c  reg11 byte0,1 */
+       u16     mclken_div_psc2;        /* CDM + 0x2e  reg11 byte2,3 */
+
+       u16     reserved6;              /* CDM + 0x30  reg12 byte0,1 */
+       u16     mclken_div_psc3;        /* CDM + 0x32  reg12 byte2,3 */
+
+       u16     reserved7;              /* CDM + 0x34  reg13 byte0,1 */
+       u16     mclken_div_psc6;        /* CDM + 0x36  reg13 byte2,3 */
 };
 
 #endif /* __ASSEMBLY__ */
index 38d8edb..289761f 100644 (file)
@@ -23,7 +23,7 @@
 
 #define OPENPIC_VEC_TIMER      110     /* and up */
 #define OPENPIC_VEC_IPI                118     /* and up */
-#define OPENPIC_VEC_SPURIOUS   127
+#define OPENPIC_VEC_SPURIOUS   255
 
 /* OpenPIC IRQ controller structure */
 extern struct hw_interrupt_type open_pic;
index 4231758..934810d 100644 (file)
@@ -315,11 +315,20 @@ typedef struct _RESIDUAL {
   } RESIDUAL;
 
 
+/*
+ * Forward declaration - we can't include <linux/pci.h> because it
+ * breaks the boot loader
+ */
+struct pci_dev;
+
 extern RESIDUAL *res;
 extern void print_residual_device_info(void);
 extern PPC_DEVICE *residual_find_device(unsigned long BusMask,
                                        unsigned char * DevID, int BaseType,
                                        int SubType, int Interface, int n);
+extern int residual_pcidev_irq(struct pci_dev *dev);
+extern void residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+extern unsigned int residual_isapic_addr(void);
 extern PnP_TAG_PACKET *PnP_find_packet(unsigned char *p, unsigned packet_tag,
                                       int n);
 extern PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
@@ -328,6 +337,13 @@ extern PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
 extern PnP_TAG_PACKET *PnP_find_large_vendor_packet(unsigned char *p,
                                                    unsigned packet_type,
                                                    int n);
+
+#ifdef CONFIG_PREP_RESIDUAL
+#define have_residual_data     (res && res->ResidualLength)
+#else
+#define have_residual_data     0
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif  /* ndef _RESIDUAL_ */
 
index 87616e1..89e6e73 100644 (file)
@@ -29,22 +29,13 @@ struct semaphore {
         */
        atomic_t count;
        wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-       long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-               , (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name, count) \
-       { ATOMIC_INIT(count), \
-         __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-         __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)                               \
+{                                                                      \
+       .count          = ATOMIC_INIT(n),                               \
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
 
 #define __MUTEX_INITIALIZER(name) \
        __SEMAPHORE_INITIALIZER(name, 1)
@@ -59,9 +50,6 @@ static inline void sema_init (struct semaphore *sem, int val)
 {
        atomic_set(&sem->count, val);
        init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -80,9 +68,6 @@ extern void __up(struct semaphore * sem);
 
 extern inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
 
        /*
@@ -97,9 +82,6 @@ extern inline int down_interruptible(struct semaphore * sem)
 {
        int ret = 0;
 
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
 
        if (atomic_dec_return(&sem->count) < 0)
@@ -112,10 +94,6 @@ extern inline int down_trylock(struct semaphore * sem)
 {
        int ret;
 
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        ret = atomic_dec_if_positive(&sem->count) < 0;
        smp_wmb();
        return ret;
@@ -123,10 +101,6 @@ extern inline int down_trylock(struct semaphore * sem)
 
 extern inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        smp_wmb();
        if (atomic_inc_return(&sem->count) <= 0)
                __up(sem);
index bad94c3..4134376 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_SOCKET_H */
index 62aeec9..340235d 100644 (file)
@@ -65,16 +65,6 @@ static inline struct thread_info *current_thread_info(void)
  */
 #define THREAD_SIZE            8192    /* 2 pages */
 
-/*
- * Offsets in thread_info structure, used in assembly code
- */
-#define TI_TASK                0
-#define TI_EXECDOMAIN  4
-#define TI_FLAGS       8
-#define TI_LOCAL_FLAGS 12
-#define TI_CPU         16
-#define TI_PREEMPT     20
-
 #define PREEMPT_ACTIVE         0x4000000
 
 /*
diff --git a/include/asm-ppc64/8253pit.h b/include/asm-ppc64/8253pit.h
new file mode 100644 (file)
index 0000000..285f784
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * 8253/8254 Programmable Interval Timer
+ */
+
+#ifndef _8253PIT_H
+#define _8253PIT_H
+
+#define PIT_TICK_RATE  1193182UL
+
+#endif
index ba6b5b3..67aef0c 100644 (file)
@@ -7,23 +7,20 @@
 #define __PPC_BTEXT_H
 #ifdef __KERNEL__
 
-#include <asm/bootx.h>
-
 extern void btext_clearscreen(void);
 extern void btext_flushscreen(void);
 
-extern boot_infos_t disp_bi;
 extern int boot_text_mapped;
 
-void btext_setup_display(int width, int height, int depth, int pitch,
-                        unsigned long address);
-void map_boot_text(void);
-void btext_update_display(unsigned long phys, int width, int height,
-                         int depth, int pitch);
+extern int btext_initialize(struct device_node *np);
+
+extern void map_boot_text(void);
+extern void btext_update_display(unsigned long phys, int width, int height,
+                                int depth, int pitch);
 
-void btext_drawchar(char c);
-void btext_drawstring(const char *str);
-void btext_drawhex(unsigned long v);
+extern void btext_drawchar(char c);
+extern void btext_drawstring(const char *str);
+extern void btext_drawhex(unsigned long v);
 
 #endif /* __KERNEL__ */
 #endif /* __PPC_BTEXT_H */
index 9e439ee..790bc56 100644 (file)
@@ -43,8 +43,6 @@ struct bug_entry {
                    "i" (__FUNCTION__));                        \
 } while (0)
 
-#define PAGE_BUG(page) do { BUG(); } while (0)
-
 #define WARN_ON(x) do {                                                \
        __asm__ __volatile__(                                   \
                "1:     tdnei %0,0\n"                           \
@@ -56,4 +54,10 @@ struct bug_entry {
 } while (0)
 
 #endif
+
+#define HAVE_ARCH_BUG
+#define HAVE_ARCH_BUG_ON
+#define HAVE_ARCH_WARN_ON
+#include <asm-generic/bug.h>
+
 #endif
index 5ae7cdb..d22d446 100644 (file)
@@ -84,10 +84,10 @@ static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
 }
 
 #define csum_partial_copy_from_user(src, dst, len, sum, errp)   \
-        csum_partial_copy_generic((src), (dst), (len), (sum), (errp), 0)
+        csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL)
 
 #define csum_partial_copy_nocheck(src, dst, len, sum)   \
-        csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0)
+        csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
 
 static inline u32 csum_tcpudp_nofold(u32 saddr,
                                      u32 daddr,
index 0cdc534..1e05f38 100644 (file)
@@ -8,7 +8,6 @@
 #define _ASM_DMA_MAPPING_H
 
 #include <linux/types.h>
-#include <linux/device.h>
 #include <linux/cache.h>
 /* need struct page definitions */
 #include <linux/mm.h>
index f47cc03..6ce5ef9 100644 (file)
 #define H_VIO_SIGNAL           0x104
 #define H_SEND_CRQ             0x108
 #define H_COPY_RDMA             0x110
-#define H_POLL_PENDING         0x1D8
+#define H_STUFF_TCE            0x138
+#define H_PUT_TCE_INDIRECT     0x13C
 #define H_VTERM_PARTNER_INFO   0x150
-#define H_REGISTER_VTERM               0x154
-#define H_FREE_VTERM                   0x158
+#define H_REGISTER_VTERM       0x154
+#define H_FREE_VTERM           0x158
+#define H_POLL_PENDING         0x1D8
 
 /* plpar_hcall() -- Generic call interface using above opcodes
  *
index 1715486..d89d94c 100644 (file)
 #ifndef _PPC64_HVCONSOLE_H
 #define _PPC64_HVCONSOLE_H
 
-extern int hvc_get_chars(int index, char *buf, int count);
-extern int hvc_put_chars(int index, const char *buf, int count);
-extern int hvc_count(int *start_termno);
+/*
+ * This is the max number of console adapters that can/will be found as
+ * console devices on first stage console init.  Any number beyond this range
+ * can't be used as a console device but is still a valid tty device.
+ */
+#define MAX_NR_HVC_CONSOLES    16
 
-#endif /* _PPC64_HVCONSOLE_H */
+extern int hvc_get_chars(uint32_t vtermno, char *buf, int count);
+extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count);
 
+/* Early discovery of console adapters. */
+extern int hvc_find_vtys(void);
+
+/* Implemented by a console driver */
+extern int hvc_instantiate(uint32_t vtermno, int index);
+#endif /* _PPC64_HVCONSOLE_H */
index cee9a14..aecba96 100644 (file)
 /* Converged Location Code length */
 #define HVCS_CLC_LENGTH        79
 
+/**
+ * hvcs_partner_info - an element in a list of partner info
+ * @node: list_head denoting this partner_info struct's position in the list of
+ *     partner info.
+ * @unit_address: The partner unit address of this entry.
+ * @partition_ID: The partner partition ID of this entry.
+ * @location_code: The converged location code of this entry + 1 char for the
+ *     null-term.
+ *
+ * This structure outlines the format that partner info is presented to a caller
+ * of the hvcs partner info fetching functions.  These are strung together into
+ * a list using linux kernel lists.
+ */
 struct hvcs_partner_info {
        struct list_head node;
-       unsigned int unit_address;
-       unsigned int partition_ID;
+       uint32_t unit_address;
+       uint32_t partition_ID;
        char location_code[HVCS_CLC_LENGTH + 1]; /* CLC + 1 null-term char */
 };
 
 extern int hvcs_free_partner_info(struct list_head *head);
-extern int hvcs_get_partner_info(unsigned int unit_address,
+extern int hvcs_get_partner_info(uint32_t unit_address,
                struct list_head *head, unsigned long *pi_buff);
-extern int hvcs_register_connection(unsigned int unit_address,
-               unsigned int p_partition_ID, unsigned int p_unit_address);
-extern int hvcs_free_connection(unsigned int unit_address);
+extern int hvcs_register_connection(uint32_t unit_address,
+               uint32_t p_partition_ID, uint32_t p_unit_address);
+extern int hvcs_free_connection(uint32_t unit_address);
 
 #endif /* _PPC64_HVCSERVER_H */
index 96b07b1..f52b759 100644 (file)
 /*   Created December 28, 2000                                          */
 /* End Change Activity                                                  */
 /************************************************************************/
-extern u8   iSeries_Read_Byte(void* IoAddress);
-extern u16  iSeries_Read_Word(void* IoAddress);
-extern u32  iSeries_Read_Long(void* IoAddress);
-extern void iSeries_Write_Byte(u8  IoData,void* IoAddress);
-extern void iSeries_Write_Word(u16 IoData,void* IoAddress);
-extern void iSeries_Write_Long(u32 IoData,void* IoAddress);
+extern u8   iSeries_Read_Byte(const volatile void __iomem * IoAddress);
+extern u16  iSeries_Read_Word(const volatile void __iomem * IoAddress);
+extern u32  iSeries_Read_Long(const volatile void __iomem * IoAddress);
+extern void iSeries_Write_Byte(u8  IoData, volatile void __iomem * IoAddress);
+extern void iSeries_Write_Word(u16 IoData, volatile void __iomem * IoAddress);
+extern void iSeries_Write_Long(u32 IoData, volatile void __iomem * IoAddress);
 
-extern void* iSeries_memset_io(void *dest, char x, size_t n);
-extern void* iSeries_memcpy_toio(void *dest, void *source, size_t n);
-extern void* iSeries_memcpy_fromio(void *dest, void *source, size_t n);
+extern void iSeries_memset_io(volatile void __iomem *dest, char x, size_t n);
+extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t n);
+extern void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *source, size_t n);
 
 #endif /* CONFIG_PPC_ISERIES */
 #endif /* _ISERIES_IO_H */
index 43a2f70..f1c1f0a 100644 (file)
@@ -20,12 +20,6 @@ extern unsigned long reloc_offset(void);
 
 #define MAX_LMB_REGIONS 128
 
-union lmb_reg_property { 
-       struct reg_property32    addr32[MAX_LMB_REGIONS];
-       struct reg_property64    addr64[MAX_LMB_REGIONS];
-       struct reg_property_pmac addrPM[MAX_LMB_REGIONS];
-};
-
 #define LMB_ALLOC_ANYWHERE     0
 
 struct lmb_property {
@@ -47,7 +41,7 @@ struct lmb {
        struct lmb_region reserved;
 };
 
-extern struct lmb lmb __initdata;
+extern struct lmb lmb;
 
 extern void __init lmb_init(void);
 extern void __init lmb_analyze(void);
@@ -60,6 +54,8 @@ extern unsigned long __init lmb_phys_mem_size(void);
 extern unsigned long __init lmb_end_of_DRAM(void);
 extern unsigned long __init lmb_abs_to_phys(unsigned long);
 
+extern void lmb_dump_all(void);
+
 extern unsigned long io_hole_start;
 
 #endif /* _PPC64_LMB_H */
index 40c4a6e..56e09fa 100644 (file)
@@ -56,14 +56,4 @@ static inline void isync(void)
 #define HMT_MEDIUM_HIGH "\tor   5,5,5           # medium high priority\n"
 #define HMT_HIGH       "\tor   3,3,3           # high priority\n"
 
-/* 
- * Various operational modes for SMT
- * Off    : never run threaded
- * On     : always run threaded
- * Dynamic: Allow the system to switch modes as needed
- */
-#define SMT_OFF      0
-#define SMT_ON       1
-#define SMT_DYNAMIC  2
-
 #endif
index acb6aff..a51c604 100644 (file)
@@ -33,9 +33,9 @@ enum phb_types {
 struct pci_controller {
        char what[8];                     /* Eye catcher      */
        enum phb_types type;              /* Type of hardware */
-       struct pci_controller *next;
        struct pci_bus *bus;
        void *arch_data;
+       struct list_head list_node;
 
        int first_busno;
        int last_busno;
@@ -70,8 +70,8 @@ struct pci_controller {
  * for a device on a PCI bus, given its device_node struct.
  * It returns 0 if OK, -1 on error.
  */
-int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
-                  unsigned char *devfn_ptr);
+extern int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
+                         unsigned char *devfn_ptr);
 
 struct device_node *fetch_dev_dn(struct pci_dev *dev);
 
@@ -87,6 +87,9 @@ static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
                return fetch_dev_dn(dev);
 }
 
+extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
+                                        struct device_node *dev, int primary);
+
 /* Use this macro after the PCI bus walk for max performance when it
  * is known that sysdata is correct.
  */
diff --git a/include/asm-ppc64/plpar_wrappers.h b/include/asm-ppc64/plpar_wrappers.h
new file mode 100644 (file)
index 0000000..17452d3
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef _PPC64_PLPAR_WRAPPERS_H
+#define _PPC64_PLPAR_WRAPPERS_H
+
+#include <asm/hvcall.h>
+
+static inline long poll_pending(void)
+{
+       unsigned long dummy;
+       return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0,
+                          &dummy, &dummy, &dummy);
+}
+
+static inline long prod_processor(void)
+{
+       plpar_hcall_norets(H_PROD);
+       return(0); 
+}
+
+static inline long cede_processor(void)
+{
+       plpar_hcall_norets(H_CEDE);
+       return(0); 
+}
+
+static inline long register_vpa(unsigned long flags, unsigned long proc, unsigned long vpa)
+{
+       plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa);
+       return(0); 
+}
+
+static inline long plpar_pte_remove(unsigned long flags,
+                                   unsigned long ptex,
+                                   unsigned long avpn,
+                                   unsigned long *old_pteh_ret,
+                                   unsigned long *old_ptel_ret)
+{
+       unsigned long dummy;
+       return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0,
+                          old_pteh_ret, old_ptel_ret, &dummy);
+}
+
+static inline long plpar_pte_read(unsigned long flags,
+                                 unsigned long ptex,
+                                 unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
+{
+       unsigned long dummy;
+       return plpar_hcall(H_READ, flags, ptex, 0, 0,
+                          old_pteh_ret, old_ptel_ret, &dummy);
+}
+
+static inline long plpar_pte_protect(unsigned long flags,
+                                    unsigned long ptex,
+                                    unsigned long avpn)
+{
+       return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn);
+}
+
+static inline long plpar_tce_get(unsigned long liobn,
+                                unsigned long ioba,
+                                unsigned long *tce_ret)
+{
+       unsigned long dummy;
+       return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0,
+                          tce_ret, &dummy, &dummy);
+}
+
+static inline long plpar_tce_put(unsigned long liobn,
+                                unsigned long ioba,
+                                unsigned long tceval)
+{
+       return plpar_hcall_norets(H_PUT_TCE, liobn, ioba, tceval);
+}
+
+static inline long plpar_tce_put_indirect(unsigned long liobn,
+                                         unsigned long ioba,
+                                         unsigned long page,
+                                         unsigned long count)
+{
+       return plpar_hcall_norets(H_PUT_TCE_INDIRECT, liobn, ioba, page, count);
+}
+
+static inline long plpar_tce_stuff(unsigned long liobn,
+                                  unsigned long ioba,
+                                  unsigned long tceval,
+                                  unsigned long count)
+{
+       return plpar_hcall_norets(H_STUFF_TCE, liobn, ioba, tceval, count);
+}
+
+static inline long plpar_get_term_char(unsigned long termno,
+                                      unsigned long *len_ret,
+                                      char *buf_ret)
+{
+       unsigned long *lbuf = (unsigned long *)buf_ret;  /* ToDo: alignment? */
+       return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0,
+                          len_ret, lbuf+0, lbuf+1);
+}
+
+static inline long plpar_put_term_char(unsigned long termno,
+                                      unsigned long len,
+                                      const char *buffer)
+{
+       unsigned long *lbuf = (unsigned long *)buffer;  /* ToDo: alignment? */
+       return plpar_hcall_norets(H_PUT_TERM_CHAR, termno, len, lbuf[0],
+                                 lbuf[1]);
+}
+
+
+#endif /* _PPC64_PLPAR_WRAPPERS_H */
index 22dfee7..aefe775 100644 (file)
@@ -23,22 +23,13 @@ struct semaphore {
         */
        atomic_t count;
        wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-       long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-               , (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name, count) \
-       { ATOMIC_INIT(count), \
-         __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-         __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)                               \
+{                                                                      \
+       .count          = ATOMIC_INIT(n),                               \
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
 
 #define __MUTEX_INITIALIZER(name) \
        __SEMAPHORE_INITIALIZER(name, 1)
@@ -53,9 +44,6 @@ static inline void sema_init (struct semaphore *sem, int val)
 {
        atomic_set(&sem->count, val);
        init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -74,9 +62,6 @@ extern void __up(struct semaphore * sem);
 
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
 
        /*
@@ -90,9 +75,6 @@ static inline int down_interruptible(struct semaphore * sem)
 {
        int ret = 0;
 
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        might_sleep();
 
        if (unlikely(atomic_dec_return(&sem->count) < 0))
@@ -102,19 +84,11 @@ static inline int down_interruptible(struct semaphore * sem)
 
 static inline int down_trylock(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        return atomic_dec_if_positive(&sem->count) < 0;
 }
 
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        if (unlikely(atomic_inc_return(&sem->count) <= 0))
                __up(sem);
 }
index 1021a52..59e00df 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
index 6fafb87..97cb696 100644 (file)
 #include <asm/tlbflush.h>
 
 struct mmu_gather;
-static inline void tlb_flush(struct mmu_gather *tlb);
+
+extern void pte_free_finish(void);
+
+static inline void tlb_flush(struct mmu_gather *tlb)
+{
+       flush_tlb_pending();
+       pte_free_finish();
+}
 
 /* Avoid pulling in another include just for this */
 #define check_pgt_cache()      do { } while (0)
@@ -29,12 +36,4 @@ static inline void tlb_flush(struct mmu_gather *tlb);
 
 #define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
 
-extern void pte_free_finish(void);
-
-static inline void tlb_flush(struct mmu_gather *tlb)
-{
-       flush_tlb_pending();
-       pte_free_finish();
-}
-
 #endif /* _PPC64_TLB_H */
index d596393..2b8d6d4 100644 (file)
@@ -6,22 +6,9 @@
 #define BUG() do { \
         printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
         __asm__ __volatile__(".long 0"); \
-} while (0)                                       
-
-#define BUG_ON(condition) do { \
-       if (unlikely((condition)!=0)) \
-               BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-        BUG(); \
-} while (0)                      
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
 } while (0)
 
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
+
 #endif
index 87edaa9..09bb7b0 100644 (file)
@@ -9,17 +9,6 @@
 #ifndef _ASM_DMA_MAPPING_H
 #define _ASM_DMA_MAPPING_H
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                        dma_addr_t *dma_handle, int flag)
-{
-       BUG();
-       return 0;
-}
-
-static inline void dma_free_coherent(struct device *dev, size_t size,
-                      void *vaddr, dma_addr_t dma_handle)
-{
-       BUG();
-}
+#include <asm-generic/dma-mapping-broken.h>
 
 #endif /* _ASM_DMA_MAPPING_H */
index 1092143..363b0a8 100644 (file)
@@ -61,57 +61,20 @@ softirq_pending(unsigned int cpu)
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
+extern void account_ticks(struct pt_regs *);
 
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
+#define __ARCH_HAS_DO_SOFTIRQ
 
 #define irq_enter()                                                    \
 do {                                                                   \
        (preempt_count() += HARDIRQ_OFFSET);                            \
 } while(0)
-       
-
-extern void do_call_softirq(void);
-extern void account_ticks(struct pt_regs *);
-
-#define invoke_softirq() do_call_softirq()
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()   ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()                                                     \
 do {                                                                   \
        preempt_count() -= IRQ_EXIT_OFFSET;                             \
        if (!in_interrupt() && local_softirq_pending())                 \
                /* Use the async. stack for softirq */                  \
-               do_call_softirq();                                      \
+               do_softirq();                                           \
        preempt_enable_no_resched();                                    \
 } while (0)
 
index 8f72c9b..8038858 100644 (file)
@@ -35,7 +35,7 @@ static inline int
 idal_is_needed(void *vaddr, unsigned int length)
 {
 #ifdef __s390x__
-       return ((__pa(vaddr) + length) >> 31) != 0;
+       return ((__pa(vaddr) + length - 1) >> 31) != 0;
 #else
        return 0;
 #endif
index cac6b30..916a1aa 100644 (file)
@@ -2,7 +2,7 @@
 #define _ASM_IRQ_H
 
 #ifdef __KERNEL__
-#include <asm/hardirq.h>
+#include <linux/hardirq.h>
 
 /*
  * the definition of irqs has changed in 2.5.46:
index 1430f4d..0aa1c0f 100644 (file)
@@ -68,6 +68,7 @@
 #define __LC_ASYNC_STACK                0xC48
 #define __LC_KERNEL_ASCE               0xC4C
 #define __LC_USER_ASCE                 0xC50
+#define __LC_PANIC_STACK                0xC54
 #define __LC_CPUID                      0xC60
 #define __LC_CPUADDR                    0xC68
 #define __LC_IPLDEV                     0xC7C
@@ -80,6 +81,7 @@
 #define __LC_ASYNC_STACK                0xD50
 #define __LC_KERNEL_ASCE               0xD58
 #define __LC_USER_ASCE                 0xD60
+#define __LC_PANIC_STACK                0xD68
 #define __LC_CPUID                      0xD90
 #define __LC_CPUADDR                    0xD98
 #define __LC_IPLDEV                     0xDB8
@@ -176,7 +178,8 @@ struct _lowcore
        __u32        async_stack;              /* 0xc48 */
        __u32        kernel_asce;              /* 0xc4c */
        __u32        user_asce;                /* 0xc50 */
-       __u8         pad10[0xc60-0xc54];       /* 0xc54 */
+       __u32        panic_stack;              /* 0xc54 */
+       __u8         pad10[0xc60-0xc58];       /* 0xc58 */
        /* entry.S sensitive area start */
        struct       cpuinfo_S390 cpu_data;    /* 0xc60 */
        __u32        ipl_device;               /* 0xc7c */
@@ -257,7 +260,8 @@ struct _lowcore
        __u64        async_stack;              /* 0xd50 */
        __u64        kernel_asce;              /* 0xd58 */
        __u64        user_asce;                /* 0xd60 */
-       __u8         pad10[0xd80-0xd68];       /* 0xd68 */
+       __u64        panic_stack;              /* 0xd68 */
+       __u8         pad10[0xd80-0xd70];       /* 0xd70 */
        /* entry.S sensitive area start */
        struct       cpuinfo_S390 cpu_data;    /* 0xd80 */
        __u32        ipl_device;               /* 0xdb8 */
index fe6e1e3..1dc8066 100644 (file)
@@ -466,6 +466,7 @@ struct user_regs_struct
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs * regs);
 #endif
 
index 1855ec7..0e96eec 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
index bb49c69..454d1ea 100644 (file)
@@ -45,6 +45,4 @@ extern void add_virt_timer_periodic(void *new);
 extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires);
 extern int del_virt_timer(struct vtimer_list *timer);
 
-int stop_timers(void);
-
 #endif
index 0ffc708..ea41e17 100644 (file)
        asm volatile("nop"); \
 } while (0)
 
-#define BUG_ON(condition) do { \
-       if (unlikely((condition)!=0)) \
-               BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-       BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
index 24ce486..beb860a 100644 (file)
@@ -14,10 +14,16 @@ extern void __flush_invalidate_region(void *start, int size);
 #define flush_cache_vunmap(start, end)         flush_cache_all()
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_icache_user_range(vma, page, vaddr, len); \
-} while (0)
+       do {                                                    \
+               flush_cache_page(vma, vaddr);                   \
+               memcpy(dst, src, len);                          \
+               flush_icache_user_range(vma, page, vaddr, len); \
+       } while (0)
+
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-       memcpy(dst, src, len)
+       do {                                                    \
+               flush_cache_page(vma, vaddr);                   \
+               memcpy(dst, src, len);                          \
+       } while (0)
 
 #endif /* __ASM_SH_CACHEFLUSH_H */
index a57b94d..1d7135a 100644 (file)
@@ -35,20 +35,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -58,29 +44,10 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we in an interrupt context? Either doing bottom half
- * or hardware interrupt processing?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
-#define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
 #define nmi_enter()            (irq_enter())
 #define nmi_exit()             (preempt_count() -= HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# define in_atomic()   ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
+#define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
 #define irq_exit()                                                     \
 do {                                                                   \
                preempt_count() -= IRQ_EXIT_OFFSET;                     \
@@ -89,10 +56,4 @@ do {                                                                 \
                preempt_enable_no_resched();                            \
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)  barrier()
-#else
-extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* __ASM_SH_HARDIRQ_H */
index d0ca02c..0f75e16 100644 (file)
@@ -90,6 +90,15 @@ struct pt_dspregs {
 #define user_mode(regs) (((regs)->sr & 0x40000000)==0)
 #define instruction_pointer(regs) ((regs)->pc)
 extern void show_regs(struct pt_regs *);
+
+static inline unsigned long profile_pc(struct pt_regs *regs)
+{
+       unsigned long pc = instruction_pointer(regs);
+
+       if (pc >= 0xa0000000UL && pc < 0xc0000000UL)
+               pc -= 0x20000000;
+       return pc;
+}
 #endif
 
 #endif /* __ASM_SH_PTRACE_H */
index dc8955e..b923a77 100644 (file)
@@ -24,21 +24,14 @@ struct semaphore {
        atomic_t count;
        int sleepers;
        wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-       long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-               , (int)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-       __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)                               \
+{                                                                      \
+       .count          = ATOMIC_INIT(n),                               \
+       .sleepers       = 0,                                            \
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
 
 #define __MUTEX_INITIALIZER(name) \
        __SEMAPHORE_INITIALIZER(name,1)
@@ -60,9 +53,6 @@ static inline void sema_init (struct semaphore *sem, int val)
        atomic_set(&sem->count, val);
        sem->sleepers = 0;
        init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-       sem->__magic = (int)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -91,10 +81,6 @@ extern spinlock_t semaphore_wake_lock;
 
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
        might_sleep();
        if (atomic_dec_return(&sem->count) < 0)
                __down(sem);
@@ -103,9 +89,6 @@ static inline void down(struct semaphore * sem)
 static inline int down_interruptible(struct semaphore * sem)
 {
        int ret = 0;
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
 
        might_sleep();
        if (atomic_dec_return(&sem->count) < 0)
@@ -116,9 +99,6 @@ static inline int down_interruptible(struct semaphore * sem)
 static inline int down_trylock(struct semaphore * sem)
 {
        int ret = 0;
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
 
        if (atomic_dec_return(&sem->count) < 0)
                ret = __down_trylock(sem);
@@ -131,9 +111,6 @@ static inline int down_trylock(struct semaphore * sem)
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
        if (atomic_inc_return(&sem->count) <= 0)
                __up(sem);
 }
index 2b94694..dde696c 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* __ASM_SH_SOCKET_H */
index 6dcc872..877c12f 100644 (file)
@@ -30,13 +30,17 @@ extern void flush_icache_user_range(struct vm_area_struct *vma,
 #define flush_icache_page(vma, page)   do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_icache_user_range(vma, page, vaddr, len); \
-} while (0)
+       do {                                                    \
+               flush_cache_page(vma, vaddr);                   \
+               memcpy(dst, src, len);                          \
+               flush_icache_user_range(vma, page, vaddr, len); \
+       } while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-       memcpy(dst, src, len)
-
+       do {                                                    \
+               flush_cache_page(vma, vaddr);                   \
+               memcpy(dst, src, len);                          \
+       } while (0)
 
 #endif /* __ASSEMBLY__ */
 
index 3a64249..b8d26fe 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
-#include <linux/device.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
 
index 56f836e..56190f5 100644 (file)
@@ -28,6 +28,7 @@ struct pt_regs {
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->sr & 0x40000000)==0)
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif
 
index 0207bae..588065c 100644 (file)
@@ -261,6 +261,9 @@ if (__copy_from_user(to,from,n)) \
        return retval; \
 })
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 /* XXX: Not sure it works well..
    should be such that: 4byte clear and the rest. */
 extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
index 08ede04..2dc5bb8 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASM_SPARC_DMA_MAPPING_H
 
 #include <linux/config.h>
-#include <linux/device.h>
 
 #ifdef CONFIG_PCI
 #include <asm-generic/dma-mapping.h>
index 68ecd78..dd9d94d 100644 (file)
@@ -62,6 +62,7 @@ struct sparc_stackf {
 #ifdef __KERNEL__
 #define user_mode(regs) (!((regs)->psr & PSR_PS))
 #define instruction_pointer(regs) ((regs)->pc)
+unsigned long profile_pc(struct pt_regs *);
 extern void show_regs(struct pt_regs *);
 #endif
 
index ff9ccda..86dc000 100644 (file)
@@ -57,20 +57,6 @@ typedef struct {
        } si_fpqueue [16];
 } __siginfo_fpu_t;
 
-#ifdef __KERNEL__
-
-/* This magic should be in g_upper[0] for all upper parts
-   to be valid.
-   This is generated by sparc64 only, but for 32bit processes,
-   so we define it here as well.  */
-#define SIGINFO_EXTRA_V8PLUS_MAGIC      0x130e269
-typedef struct {
-       unsigned   int g_upper[8];
-       unsigned   int o_upper[8];
-} siginfo_extra_v8plus_t;
-
-#endif
-
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC_SIGCONTEXT_H) */
index cfa529d..c1154e3 100644 (file)
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       0x5002
 #define SO_SECURITY_ENCRYPTION_NETWORK         0x5004
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
index d74f4df..9109739 100644 (file)
@@ -33,9 +33,9 @@
 
 #define SUN4M_IOBASE_VADDR     0xfd000000 /* Base for mapping pages */
 #define IOBASE_VADDR           0xfe000000
-#define IOBASE_END             0xfe300000
+#define IOBASE_END             0xfe600000
 
-#define VMALLOC_START          0xfe300000
+#define VMALLOC_START          0xfe600000
 
 /* XXX Alter this when I get around to fixing sun4c - Anton */
 #define VMALLOC_END            0xffc00000
index 13de4b1..2901ea0 100644 (file)
@@ -1,7 +1,11 @@
-/* $Id: delay.h,v 1.13 2002/02/02 03:33:48 kanoj Exp $
- * delay.h: Linux delay routines on the V9.
+/* delay.h: Linux delay routines on sparc64.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu).
+ * Copyright (C) 1996, 2004 David S. Miller (davem@davemloft.net).
+ *
+ * Based heavily upon x86 variant which is:
+ * Copyright (C) 1993 Linus Torvalds
+ *
+ * Delay routines calling functions in arch/sparc64/lib/delay.c
  */
 
 #ifndef __SPARC64_DELAY_H
 
 #ifndef __ASSEMBLY__
 
-static __inline__ void __delay(unsigned long loops)
-{
-       __asm__ __volatile__(
-"      b,pt    %%xcc, 1f\n"
-"       cmp    %0, 0\n"
-"      .align  32\n"
-"1:\n"
-"      bne,pt  %%xcc, 1b\n"
-"       subcc  %0, 1, %0\n"
-       : "=&r" (loops)
-       : "0" (loops)
-       : "cc");
-}
-
-static __inline__ void __udelay(unsigned long usecs, unsigned long lps)
-{
-       usecs *= 0x00000000000010c6UL;          /* 2**32 / 1000000 */
-
-       __asm__ __volatile__(
-"      mulx    %1, %2, %0\n"
-"      srlx    %0, 32, %0\n"
-       : "=r" (usecs)
-       : "r" (usecs), "r" (lps));
-
-       __delay(usecs * HZ);
-}
-
-extern __inline__ void __ndelay(unsigned long usecs, unsigned long lps)
-{
-       usecs *= 0x0000000000000005UL;          /* 2**32 / 10000 */
-
-       __asm__ __volatile__(
-"      mulx    %1, %2, %0\n"
-"      srlx    %0, 32, %0\n"
-       : "=r" (usecs)
-       : "r" (usecs), "r" (lps));
-
-       __delay(usecs * HZ);
-}
-
-#define __udelay_val cpu_data(smp_processor_id()).udelay_val
-
-#define udelay(usecs) __udelay((usecs),__udelay_val)
-#define ndelay(usecs) __ndelay((usecs),__udelay_val)
+extern void __bad_udelay(void);
+extern void __bad_ndelay(void);
+
+extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
+extern void __const_udelay(unsigned long usecs);
+extern void __delay(unsigned long loops);
+
+#define udelay(n) (__builtin_constant_p(n) ? \
+       ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
+       __udelay(n))
+       
+#define ndelay(n) (__builtin_constant_p(n) ? \
+       ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
+       __ndelay(n))
 
 #endif /* !__ASSEMBLY__ */
 
index b80f2f7..1aab3c8 100644 (file)
@@ -62,7 +62,7 @@ enum dvma_rev {
 struct sbus_dma {
        struct sbus_dma *next;
        struct sbus_dev *sdev;
-       unsigned long regs;
+       void __iomem *regs;
 
        /* Status, misc info */
        int node;                /* Prom node for this DMA device */
index 82e8376..543e4e5 100644 (file)
@@ -53,7 +53,7 @@ struct linux_ebus {
 
 struct ebus_dma_info {
        spinlock_t      lock;
-       unsigned long   regs;
+       void __iomem    *regs;
 
        unsigned int    flags;
 #define EBUS_DMA_FLAG_USE_EBDMA_HANDLER                0x00000001
index 88a7ee8..9145811 100644 (file)
@@ -94,12 +94,12 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 #define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs)      \
 do {   unsigned long *dest = &(__elf_regs[0]);         \
        struct pt_regs *src = (__pt_regs);              \
-       unsigned long *sp;                              \
+       unsigned long __user *sp;                       \
        int i;                                          \
        for(i = 0; i < 16; i++)                         \
                dest[i] = src->u_regs[i];               \
        /* Don't try this at home kids... */            \
-       sp = (unsigned long *)                          \
+       sp = (unsigned long __user *)                   \
         ((src->u_regs[14] + STACK_BIAS)                \
          & 0xfffffffffffffff8UL);                      \
        for(i = 0; i < 16; i++)                         \
index 65862f7..f70d3da 100644 (file)
@@ -1,9 +1,52 @@
 #ifndef _SPARC64_KDEBUG_H
 #define _SPARC64_KDEBUG_H
 
-/* 
- * No kernel debugger on sparc64. Kept here because drivers/sbus/char/
- * includes it for sparc32 sake.
+/* Nearly identical to x86_64/i386 code. */
+
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+struct die_args {
+       struct pt_regs *regs;
+       const char *str;
+       long err;
+       int trapnr;
+       int signr;
+};
+
+/* Note - you should never unregister because that can race with NMIs.
+ * If you really want to do it first unregister - then synchronize_kernel
+ * - then free.
  */
+int register_die_notifier(struct notifier_block *nb);
+extern struct notifier_block *sparc64die_chain;
+
+extern void bad_trap(struct pt_regs *, long);
+
+/* Grossly misnamed. */
+enum die_val {
+       DIE_OOPS = 1,
+       DIE_DEBUG,      /* ta 0x70 */
+       DIE_DEBUG_2,    /* ta 0x71 */
+       DIE_DIE,
+       DIE_TRAP,
+       DIE_TRAP_TL1,
+       DIE_GPF,
+       DIE_CALL,
+       DIE_PAGE_FAULT,
+};
+
+static inline int notify_die(enum die_val val,char *str, struct pt_regs *regs,
+                            long err, int trap, int sig)
+{
+       struct die_args args = { .regs          = regs,
+                                .str           = str,
+                                .err           = err,
+                                .trapnr        = trap,
+                                .signr         = sig };
+
+       return notifier_call_chain(&sparc64die_chain, val, &args);
+}
 
 #endif
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
new file mode 100644 (file)
index 0000000..42b4cc6
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _SPARC64_KPROBES_H
+#define _SPARC64_KPROBES_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+typedef u32 kprobe_opcode_t;
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+#define MAX_INSN_SIZE 2
+
+#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
+
+#endif /* _SPARC64_KPROBES_H */
index 676f67e..ab88349 100644 (file)
@@ -126,10 +126,14 @@ static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
                        if (ebus_ecpp_p(edev)) {
                                unsigned long base = edev->resource[0].start;
                                unsigned long config = edev->resource[1].start;
+                               unsigned long d_base = edev->resource[2].start;
+                               unsigned long d_len;
 
                                spin_lock_init(&sparc_ebus_dmas[count].info.lock);
+                               d_len = (edev->resource[2].end -
+                                        d_base) + 1;
                                sparc_ebus_dmas[count].info.regs =
-                                       edev->resource[2].start;
+                                       ioremap(d_base, d_len);
                                if (!sparc_ebus_dmas[count].info.regs)
                                        continue;
                                sparc_ebus_dmas[count].info.flags = 0;
index 0cddbd2..9299963 100644 (file)
@@ -70,6 +70,13 @@ struct pci_iommu {
         */
        u32             lowest_consistent_map;
 
+       /* In order to deal with some buggy third-party PCI bridges that
+        * do wrong prefetching, we never mark valid mappings as invalid.
+        * Instead we point them at this dummy page.
+        */
+       unsigned long   dummy_page;
+       unsigned long   dummy_page_pa;
+
        /* If PBM_NCLUSTERS is ever decreased to 4 or lower,
         * or if largest supported page_table_sz * 8K goes above
         * 2GB, you must increase the size of the type of
@@ -93,6 +100,8 @@ struct pci_iommu {
        u32 dma_addr_mask;
 };
 
+extern void pci_iommu_table_init(struct pci_iommu *, int);
+
 /* This describes a PCI bus module's streaming buffer. */
 struct pci_strbuf {
        int             strbuf_enabled;         /* Present and using it? */
index c679d2c..2d2b5a1 100644 (file)
@@ -98,6 +98,11 @@ struct sparc_trapf {
        set_thread_flag(TIF_SYSCALL_SUCCESS)
 #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
 #define instruction_pointer(regs) ((regs)->tpc)
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
 extern void show_regs(struct pt_regs *);
 #endif
 
index d7128a8..d807337 100644 (file)
@@ -83,18 +83,6 @@ struct sigcontext {
        unsigned long           sigc_mask;
 };
 
-#ifdef __KERNEL__
-
-/* This magic should be in g_upper[0] for all upper parts
-   to be valid.  */
-#define SIGINFO_EXTRA_V8PLUS_MAGIC     0x130e269
-typedef struct {
-       unsigned   int g_upper[8];
-       unsigned   int o_upper[8];
-} siginfo_extra_v8plus_t;
-
-#endif
-
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC64_SIGCONTEXT_H) */
index ba2230b..865547a 100644 (file)
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       0x5002
 #define SO_SECURITY_ENCRYPTION_NETWORK         0x5004
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
index c1a4f1d..c7d8862 100644 (file)
 
 #include <asm/asi.h>
 
-extern void __memmove(void *,const void *,__kernel_size_t);
 extern void *__memset(void *,int,__kernel_size_t);
-extern void *__builtin_memset(void *,int,__kernel_size_t);
 
 #ifndef EXPORT_SYMTAB_STROPS
 
 /* First the mem*() things. */
-#define __HAVE_ARCH_BCOPY
 #define __HAVE_ARCH_MEMMOVE
-
-#undef memmove
-#define memmove(_to, _from, _n) \
-({ \
-       void *_t = (_to); \
-       __memmove(_t, (_from), (_n)); \
-       _t; \
-})
+extern void *memmove(void *, const void *, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMCPY
-
-extern void * memcpy(void *,const void *,__kernel_size_t);
+extern void *memcpy(void *, const void *, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMSET
+extern void *__builtin_memset(void *,int,__kernel_size_t);
 
 static inline void *__constant_memset(void *s, int c, __kernel_size_t count)
 {
        extern __kernel_size_t __bzero(void *, __kernel_size_t);
 
-       if(!c) {
+       if (!c) {
                __bzero(s, count);
                return s;
        } else
@@ -61,19 +51,19 @@ static inline void *__constant_memset(void *s, int c, __kernel_size_t count)
 #define __HAVE_ARCH_MEMSCAN
 
 #undef memscan
-#define memscan(__arg0, __char, __arg2)                                                \
-({                                                                             \
-       extern void *__memscan_zero(void *, size_t);                            \
-       extern void *__memscan_generic(void *, int, size_t);                    \
-       void *__retval, *__addr = (__arg0);                                     \
-       size_t __size = (__arg2);                                               \
-                                                                               \
-       if(__builtin_constant_p(__char) && !(__char))                           \
-               __retval = __memscan_zero(__addr, __size);                      \
-       else                                                                    \
-               __retval = __memscan_generic(__addr, (__char), __size);         \
-                                                                               \
-       __retval;                                                               \
+#define memscan(__arg0, __char, __arg2)                                        \
+({                                                                     \
+       extern void *__memscan_zero(void *, size_t);                    \
+       extern void *__memscan_generic(void *, int, size_t);            \
+       void *__retval, *__addr = (__arg0);                             \
+       size_t __size = (__arg2);                                       \
+                                                                       \
+       if(__builtin_constant_p(__char) && !(__char))                   \
+               __retval = __memscan_zero(__addr, __size);              \
+       else                                                            \
+               __retval = __memscan_generic(__addr, (__char), __size); \
+                                                                       \
+       __retval;                                                       \
 })
 
 #define __HAVE_ARCH_MEMCMP
@@ -81,73 +71,10 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
 
 /* Now the str*() stuff... */
 #define __HAVE_ARCH_STRLEN
-
-extern __kernel_size_t __strlen(const char *);
 extern __kernel_size_t strlen(const char *);
 
 #define __HAVE_ARCH_STRNCMP
-
-extern int __strncmp(const char *, const char *, __kernel_size_t);
-
-static inline int __constant_strncmp(const char *src, const char *dest, __kernel_size_t count)
-{
-       register int retval;
-       switch(count) {
-       case 0: return 0;
-       case 1: return (src[0] - dest[0]);
-       case 2: retval = (src[0] - dest[0]);
-               if(!retval && src[0])
-                 retval = (src[1] - dest[1]);
-               return retval;
-       case 3: retval = (src[0] - dest[0]);
-               if(!retval && src[0]) {
-                 retval = (src[1] - dest[1]);
-                 if(!retval && src[1])
-                   retval = (src[2] - dest[2]);
-               }
-               return retval;
-       case 4: retval = (src[0] - dest[0]);
-               if(!retval && src[0]) {
-                 retval = (src[1] - dest[1]);
-                 if(!retval && src[1]) {
-                   retval = (src[2] - dest[2]);
-                   if (!retval && src[2])
-                     retval = (src[3] - dest[3]);
-                 }
-               }
-               return retval;
-       case 5: retval = (src[0] - dest[0]);
-               if(!retval && src[0]) {
-                 retval = (src[1] - dest[1]);
-                 if(!retval && src[1]) {
-                   retval = (src[2] - dest[2]);
-                   if (!retval && src[2]) {
-                     retval = (src[3] - dest[3]);
-                     if (!retval && src[3])
-                       retval = (src[4] - dest[4]);
-                   }
-                 }
-               }
-               return retval;
-       default:
-               retval = (src[0] - dest[0]);
-               if(!retval && src[0]) {
-                 retval = (src[1] - dest[1]);
-                 if(!retval && src[1]) {
-                   retval = (src[2] - dest[2]);
-                   if(!retval && src[2])
-                     retval = __strncmp(src+3,dest+3,count-3);
-                 }
-               }
-               return retval;
-       }
-}
-
-#undef strncmp
-#define strncmp(__arg0, __arg1, __arg2)        \
-(__builtin_constant_p(__arg2) ?        \
- __constant_strncmp(__arg0, __arg1, __arg2) : \
- __strncmp(__arg0, __arg1, __arg2))
+extern int strncmp(const char *, const char *, __kernel_size_t);
 
 #endif /* !EXPORT_SYMTAB_STROPS */
 
index 2b454ef..2784f80 100644 (file)
        ba,pt   %xcc, rtrap_clr_l6;                                     \
         stx    %l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
                
+#ifdef CONFIG_KPROBES
+#define KPROBES_TRAP(lvl) TRAP_IRQ(kprobe_trap, lvl)
+#else
+#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
+#endif
+
 /* Before touching these macros, you owe it to yourself to go and
  * see how arch/sparc64/kernel/winfixup.S works... -DaveM
  *
index c2f5529..9c57eb3 100644 (file)
@@ -11,6 +11,9 @@
 
 #define VT_BUF_HAVE_RW
 
+#undef scr_writew
+#undef scr_readw
+
 static inline void scr_writew(u16 val, u16 *addr)
 {
        BUG_ON((long) addr >= 0);
diff --git a/include/asm-um/module-i386.h b/include/asm-um/module-i386.h
new file mode 100644 (file)
index 0000000..5ead4a0
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __UM_MODULE_I386_H
+#define __UM_MODULE_I386_H
+
+/* UML is simple */
+struct mod_arch_specific
+{
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+#endif
index c5a13e6..8c472eb 100644 (file)
@@ -45,6 +45,8 @@ struct pt_regs {
 
 #define PT_REGS_SC(r) UPT_SC(&(r)->regs)
 
+#define instruction_pointer(regs) PT_REGS_IP(regs)
+
 struct task_struct;
 
 extern unsigned long getreg(struct task_struct *child, int regno);
index ce68b9a..c778916 100644 (file)
 
 extern void __bug (void) __attribute__ ((noreturn));
 #define BUG()          __bug()
-#define PAGE_BUG(page) __bug()
-
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif /* __V850_BUG_H__ */
index a997f9f..7493d6d 100644 (file)
@@ -36,20 +36,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -59,27 +45,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
 #define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()    (preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()    (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()                                                           \
 do {                                                                         \
        preempt_count() -= IRQ_EXIT_OFFSET;                                   \
@@ -88,10 +54,4 @@ do {                                                                       \
        preempt_enable_no_resched();                                          \
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)  barrier()
-#else
-# error v850nommu SMP is not available
-#endif /* CONFIG_SMP */
-
 #endif /* __V850_HARDIRQ_H__ */
index 62b2b38..7bf72bb 100644 (file)
@@ -76,6 +76,7 @@ struct pt_regs
 
 
 #define instruction_pointer(regs)      ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 #define user_mode(regs)                        (!(regs)->kernel_mode)
 
 /* When a struct pt_regs is used to save user state for a system call in
index 7d7f80e..213b852 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* __V850_SOCKET_H__ */
index 44ec801..62ccf88 100644 (file)
@@ -7,15 +7,29 @@
 #include <asm/apicdef.h>
 #include <asm/system.h>
 
-#ifdef CONFIG_X86_LOCAL_APIC
+#define Dprintk(x...)
 
-#define APIC_DEBUG 0
+/*
+ * Debugging macros
+ */
+#define APIC_QUIET   0
+#define APIC_VERBOSE 1
+#define APIC_DEBUG   2
 
-#if APIC_DEBUG
-#define Dprintk(x...) printk(x)
-#else
-#define Dprintk(x...)
-#endif
+extern int apic_verbosity;
+
+/*
+ * Define the default level of output to be very little
+ * This can be turned up by using apic=verbose for more
+ * information and apic=debug for _lots_ of information.
+ * apic_verbosity is defined in apic.c
+ */
+#define apic_printk(v, s, a...) do {       \
+               if ((v) <= apic_verbosity) \
+                       printk(s, ##a);    \
+       } while (0)
+
+#ifdef CONFIG_X86_LOCAL_APIC
 
 struct pt_regs;
 
index 8ba1d6e..4852d9a 100644 (file)
 
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 
-#define MAX_IO_APICS 16
+#define MAX_IO_APICS 32
 
 /*
  * the local APIC register structure, memory mapped. Not terribly well
index baf472f..e2b1f48 100644 (file)
@@ -178,6 +178,166 @@ static __inline__ int atomic_add_negative(int i, atomic_t *v)
        return c;
 }
 
+/* An 64bit atomic type */
+
+typedef struct { volatile long counter; } atomic64_t;
+
+#define ATOMIC64_INIT(i)       { (i) }
+
+/**
+ * atomic64_read - read atomic64 variable
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically reads the value of @v.
+ * Doesn't imply a read memory barrier.
+ */
+#define atomic64_read(v)               ((v)->counter)
+
+/**
+ * atomic64_set - set atomic64 variable
+ * @v: pointer to type atomic64_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+#define atomic64_set(v,i)              (((v)->counter) = (i))
+
+/**
+ * atomic64_add - add integer to atomic64 variable
+ * @i: integer value to add
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically adds @i to @v.
+ */
+static __inline__ void atomic64_add(long i, atomic64_t *v)
+{
+       __asm__ __volatile__(
+               LOCK "addq %1,%0"
+               :"=m" (v->counter)
+               :"ir" (i), "m" (v->counter));
+}
+
+/**
+ * atomic64_sub - subtract the atomic64 variable
+ * @i: integer value to subtract
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically subtracts @i from @v.
+ */
+static __inline__ void atomic64_sub(long i, atomic64_t *v)
+{
+       __asm__ __volatile__(
+               LOCK "subq %1,%0"
+               :"=m" (v->counter)
+               :"ir" (i), "m" (v->counter));
+}
+
+/**
+ * atomic64_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               LOCK "subq %2,%0; sete %1"
+               :"=m" (v->counter), "=qm" (c)
+               :"ir" (i), "m" (v->counter) : "memory");
+       return c;
+}
+
+/**
+ * atomic64_inc - increment atomic64 variable
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically increments @v by 1.
+ */
+static __inline__ void atomic64_inc(atomic64_t *v)
+{
+       __asm__ __volatile__(
+               LOCK "incq %0"
+               :"=m" (v->counter)
+               :"m" (v->counter));
+}
+
+/**
+ * atomic64_dec - decrement atomic64 variable
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically decrements @v by 1.
+ */
+static __inline__ void atomic64_dec(atomic64_t *v)
+{
+       __asm__ __volatile__(
+               LOCK "decq %0"
+               :"=m" (v->counter)
+               :"m" (v->counter));
+}
+
+/**
+ * atomic64_dec_and_test - decrement and test
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static __inline__ int atomic64_dec_and_test(atomic64_t *v)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               LOCK "decq %0; sete %1"
+               :"=m" (v->counter), "=qm" (c)
+               :"m" (v->counter) : "memory");
+       return c != 0;
+}
+
+/**
+ * atomic64_inc_and_test - increment and test
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int atomic64_inc_and_test(atomic64_t *v)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               LOCK "incq %0; sete %1"
+               :"=m" (v->counter), "=qm" (c)
+               :"m" (v->counter) : "memory");
+       return c != 0;
+}
+
+/**
+ * atomic64_add_negative - add and test if negative
+ * @v: pointer to atomic64_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+static __inline__ long atomic64_add_negative(long i, atomic64_t *v)
+{
+       unsigned char c;
+
+       __asm__ __volatile__(
+               LOCK "addq %2,%0; sets %1"
+               :"=m" (v->counter), "=qm" (c)
+               :"ir" (i), "m" (v->counter) : "memory");
+       return c;
+}
+
 /* These are x86-specific, used by some header files */
 #define atomic_clear_mask(mask, addr) \
 __asm__ __volatile__(LOCK "andl %0,%1" \
index 44d70de..d2032f5 100644 (file)
@@ -6,27 +6,20 @@
 /*
  * Tell the user there is some problem.  The exception handler decodes 
  * this frame.
- */ 
-struct bug_frame { 
-       unsigned char ud2[2];          
+ */
+struct bug_frame {
+       unsigned char ud2[2];
        /* should use 32bit offset instead, but the assembler doesn't 
-          like it */ 
-       char *filename;   
-       unsigned short line; 
-} __attribute__((packed)); 
+          like it */
+       char *filename;
+       unsigned short line;
+} __attribute__((packed));
 
+#define HAVE_ARCH_BUG
 #define BUG() \
        asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \
                     "i"(__LINE__), "i" (__stringify(KBUILD_BASENAME)))
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-#define PAGE_BUG(page) BUG()
 void out_of_line_bug(void);
-
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-               dump_stack(); \
-       } \
-} while (0)
+#include <asm-generic/bug.h>
 
 #endif
index d82d840..8a1025f 100644 (file)
@@ -7,7 +7,7 @@
 #ifndef __ASM_X8664_CPUFEATURE_H
 #define __ASM_X8664_CPUFEATURE_H
 
-#define NCAPINTS       5       /* Currently we have 4 32-bit words worth of info */
+#define NCAPINTS       6
 
 /* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
 #define X86_FEATURE_FPU                (0*32+ 0) /* Onboard FPU */
 #define X86_FEATURE_K8_C       (3*32+ 4) /* C stepping K8 */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
-#define X86_FEATURE_EST                (4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_XMM3       (4*32+ 0) /* Streaming SIMD Extensions-3 */
 #define X86_FEATURE_MWAIT      (4*32+ 3) /* Monitor/Mwait support */
+#define X86_FEATURE_DSCPL      (4*32+ 4) /* CPL Qualified Debug Store */
+#define X86_FEATURE_EST                (4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_TM2                (4*32+ 8) /* Thermal Monitor 2 */
+#define X86_FEATURE_CID                (4*32+10) /* Context ID */
+#define X86_FEATURE_CX16       (4*32+13) /* CMPXCHG16B */
+#define X86_FEATURE_XTPR       (4*32+14) /* Send Task Priority Messages */
+
+/* More extended AMD flags: CPUID level 0x80000001, ecx, word 5 */
+#define X86_FEATURE_HTVALID    (5*32+ 0) /* HyperThreading valid, otherwise CMP */
 
 #define cpu_has(c, bit)                test_bit(bit, (c)->x86_capability)
 #define boot_cpu_has(bit)      test_bit(bit, boot_cpu_data.x86_capability)
@@ -81,6 +90,8 @@
 #define cpu_has_mmx            1
 #define cpu_has_fxsr           1
 #define cpu_has_xmm            1
+#define cpu_has_xmm2           1
+#define cpu_has_xmm3           boot_cpu_has(X86_FEATURE_XMM3)
 #define cpu_has_ht             boot_cpu_has(X86_FEATURE_HT)
 #define cpu_has_mp             1 /* XXX */
 #define cpu_has_k6_mtrr        0
index b454364..004888f 100644 (file)
@@ -128,13 +128,13 @@ static inline void set_tss_desc(unsigned cpu, void *addr)
 { 
        set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_TSS], (unsigned long)addr, 
                              DESC_TSS,
-                             sizeof(struct tss_struct)); 
+                             sizeof(struct tss_struct) - 1);
 } 
 
 static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
 { 
        set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (unsigned long)addr, 
-                             DESC_LDT, size * 8);
+                             DESC_LDT, size * 8 - 1);
 }
 
 static inline void set_seg_base(unsigned cpu, int entry, void *base)
index 414efa3..a416dc3 100644 (file)
@@ -1,6 +1,138 @@
 #ifndef _X8664_DMA_MAPPING_H
 #define _X8664_DMA_MAPPING_H 1
 
-#include <asm-generic/dma-mapping.h>
+/*
+ * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for
+ * documentation.
+ */
+
+#include <linux/config.h>
+
+#include <asm/scatterlist.h>
+#include <asm/io.h>
+#include <asm/swiotlb.h>
+
+extern dma_addr_t bad_dma_address;
+#define dma_mapping_error(x) \
+       (swiotlb ? swiotlb_dma_mapping_error(x) : ((x) == bad_dma_address))
+
+void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+                        unsigned gfp);
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+                        dma_addr_t dma_handle);
+
+#ifdef CONFIG_GART_IOMMU
+
+extern dma_addr_t dma_map_single(struct device *hwdev, void *ptr, size_t size,
+                                int direction);
+extern void dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
+                            int direction);
+
+#else
+
+/* No IOMMU */
+
+static inline dma_addr_t dma_map_single(struct device *hwdev, void *ptr,
+                                       size_t size, int direction)
+{
+       dma_addr_t addr;
+
+       if (direction == DMA_NONE)
+               out_of_line_bug();
+       addr = virt_to_bus(ptr);
+
+       if ((addr+size) & ~*hwdev->dma_mask)
+               out_of_line_bug();
+       return addr;
+}
+
+static inline void dma_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
+                                   size_t size, int direction)
+{
+       if (direction == DMA_NONE)
+               out_of_line_bug();
+       /* Nothing to do */
+}
+
+#endif
+
+#define dma_map_page(dev,page,offset,size,dir) \
+       dma_map_single((dev), page_address(page)+(offset), (size), (dir))
+
+static inline void dma_sync_single_for_cpu(struct device *hwdev,
+                                              dma_addr_t dma_handle,
+                                              size_t size, int direction)
+{
+       if (direction == DMA_NONE)
+               out_of_line_bug();
+
+       if (swiotlb)
+               return swiotlb_sync_single_for_cpu(hwdev,dma_handle,size,direction);
+
+       flush_write_buffers();
+}
+
+static inline void dma_sync_single_for_device(struct device *hwdev,
+                                                 dma_addr_t dma_handle,
+                                                 size_t size, int direction)
+{
+        if (direction == DMA_NONE)
+               out_of_line_bug();
+
+       if (swiotlb)
+               return swiotlb_sync_single_for_device(hwdev,dma_handle,size,direction);
+
+       flush_write_buffers();
+}
+
+static inline void dma_sync_sg_for_cpu(struct device *hwdev,
+                                      struct scatterlist *sg,
+                                      int nelems, int direction)
+{
+       if (direction == DMA_NONE)
+               out_of_line_bug();
+
+       if (swiotlb)
+               return swiotlb_sync_sg_for_cpu(hwdev,sg,nelems,direction);
+
+       flush_write_buffers();
+}
+
+static inline void dma_sync_sg_for_device(struct device *hwdev,
+                                         struct scatterlist *sg,
+                                         int nelems, int direction)
+{
+       if (direction == DMA_NONE)
+               out_of_line_bug();
+
+       if (swiotlb)
+               return swiotlb_sync_sg_for_device(hwdev,sg,nelems,direction);
+
+       flush_write_buffers();
+}
+
+extern int dma_map_sg(struct device *hwdev, struct scatterlist *sg,
+                     int nents, int direction);
+extern void dma_unmap_sg(struct device *hwdev, struct scatterlist *sg,
+                        int nents, int direction);
+
+#define dma_unmap_page dma_unmap_single
+
+extern int dma_supported(struct device *hwdev, u64 mask);
+extern int dma_get_cache_alignment(void);
+#define dma_is_consistent(h) 1
+
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+       if (!dev->dma_mask || !dma_supported(dev, mask))
+               return -EIO;
+       *dev->dma_mask = mask;
+       return 0;
+}
+
+static inline void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction dir)
+{
+       flush_write_buffers();
+}
 
 #endif
index e72f10f..9839b92 100644 (file)
@@ -144,6 +144,13 @@ typedef struct user_i387_struct elf_fpregset_t;
 extern void set_personality_64bit(void);
 #define SET_PERSONALITY(ex, ibcs2) set_personality_64bit()
        
+/*
+ * An executable for which elf_read_implies_exec() returns TRUE will
+ * have the READ_IMPLIES_EXEC personality flag set automatically.
+ */
+#define elf_read_implies_exec_binary(ex, have_pt_gnu_stack)   \
+        (!(have_pt_gnu_stack))
+
 extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
 extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
 
index d3c08b2..9ce1a78 100644 (file)
 #define SOFTIRQ_SHIFT  (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT  (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)      ((1UL << (x))-1)
-
-#define PREEMPT_MASK   (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK   (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK   (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
-#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()               (hardirq_count())
-#define in_softirq()           (softirq_count())
-#define in_interrupt()         (irq_count())
-
-
-#define hardirq_trylock()      (!in_interrupt())
-#define hardirq_endlock()      do { } while (0)
-
-#define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
 #define nmi_enter()            (irq_enter())
 #define nmi_exit()             (preempt_count() -= HARDIRQ_OFFSET)
 
-
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()   ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
+#define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
 #define irq_exit()                                                     \
 do {                                                                   \
                preempt_count() -= IRQ_EXIT_OFFSET;                     \
@@ -93,10 +58,4 @@ do {                                                                 \
                preempt_enable_no_resched();                            \
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)  barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* __ASM_HARDIRQ_H */
index 5e20e10..aa4f76c 100644 (file)
@@ -71,8 +71,6 @@ struct mtrr_gentry
 
 #ifdef __KERNEL__
 
-extern char *mtrr_strings[MTRR_NUM_TYPES];
-
 /*  The following functions are for use by other drivers  */
 # ifdef CONFIG_MTRR
 extern int mtrr_add (unsigned long base, unsigned long size,
index ac9e958..1b2423f 100644 (file)
@@ -44,81 +44,25 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
 #include <asm/io.h>
 #include <asm/page.h>
 
-struct pci_dev;
-
 extern int iommu_setup(char *opt);
 
-extern dma_addr_t bad_dma_address;
-#define pci_dma_mapping_error(x) ((x) == bad_dma_address)
-
-/* Allocate and map kernel buffer using consistent mode DMA for a device.
- * hwdev should be valid struct pci_dev pointer for PCI devices,
- * NULL for PCI-like buses (ISA, EISA).
- * Returns non-NULL cpu-view pointer to the buffer if successful and
- * sets *dma_addrp to the pci side dma address as well, else *dma_addrp
- * is undefined.
- */
-extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                                 dma_addr_t *dma_handle);
-
-/* Free and unmap a consistent DMA buffer.
- * cpu_addr is what was returned from pci_alloc_consistent,
- * size must be the same as what as passed into pci_alloc_consistent,
- * and likewise dma_addr must be the same as what *dma_addrp was set to.
- *
- * References to the memory and mappings associated with cpu_addr/dma_addr
- * past this call are illegal.
- */
-extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-                               void *vaddr, dma_addr_t dma_handle);
-
-#ifdef CONFIG_SWIOTLB
-extern int swiotlb; 
-extern dma_addr_t swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, 
-                                     int dir);
-extern void swiotlb_unmap_single (struct device *hwdev, dma_addr_t dev_addr,
-                                 size_t size, int dir);
-extern void swiotlb_sync_single_for_cpu (struct device *hwdev,
-                                        dma_addr_t dev_addr,
-                                        size_t size, int dir);
-extern void swiotlb_sync_single_for_device (struct device *hwdev,
-                                           dma_addr_t dev_addr,
-                                           size_t size, int dir);
-extern void swiotlb_sync_sg_for_cpu (struct device *hwdev,
-                                    struct scatterlist *sg, int nelems,
-                                    int dir);
-extern void swiotlb_sync_sg_for_device (struct device *hwdev,
-                                       struct scatterlist *sg, int nelems,
-                                       int dir);
-extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
-                     int nents, int direction);
-extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
-                        int nents, int direction);
-
-#endif
-
 #ifdef CONFIG_GART_IOMMU
-
-/* Map a single buffer of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
+/* The PCI address space does equal the physical memory
+ * address space.  The networking and block device layers use
+ * this boolean for bounce buffer decisions
  *
- * Once the device is given the dma address, the device owns this memory
- * until either pci_unmap_single or pci_dma_sync_single_for_cpu is performed.
+ * On AMD64 it mostly equals, but we set it to zero to tell some subsystems
+ * that an IOMMU is available.
  */
-extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, 
-                                int direction);
-
-
-void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t addr,
-                                  size_t size, int direction);
+#define PCI_DMA_BUS_IS_PHYS    (no_iommu ? 1 : 0)
 
 /*
- * pci_{map,unmap}_single_page maps a kernel page to a dma_addr_t. identical
- * to pci_map_single, but takes a struct page instead of a virtual address
+ * x86-64 always supports DAC, but sometimes it is useful to force
+ * devices through the IOMMU to get automatic sg list merging.
+ * Optional right now.
  */
-
-#define pci_map_page(dev,page,offset,size,dir) \
-       pci_map_single((dev), page_address(page)+(offset), (size), (dir)) 
+extern int iommu_sac_force;
+#define pci_dac_dma_supported(pci_dev, mask)   (!iommu_sac_force)
 
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)      \
        dma_addr_t ADDR_NAME;
@@ -133,113 +77,12 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t addr,
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)          \
        (((PTR)->LEN_NAME) = (VAL))
 
-static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev,
-                                              dma_addr_t dma_handle,
-                                              size_t size, int direction)
-{
-       BUG_ON(direction == PCI_DMA_NONE); 
-
-#ifdef CONFIG_SWIOTLB
-       if (swiotlb)
-               return swiotlb_sync_single_for_cpu(&hwdev->dev,dma_handle,size,direction);
-#endif
-
-       flush_write_buffers();
-} 
-
-static inline void pci_dma_sync_single_for_device(struct pci_dev *hwdev,
-                                                 dma_addr_t dma_handle,
-                                                 size_t size, int direction)
-{
-       BUG_ON(direction == PCI_DMA_NONE);
-
-#ifdef CONFIG_SWIOTLB
-       if (swiotlb)
-               return swiotlb_sync_single_for_device(&hwdev->dev,dma_handle,size,direction);
-#endif
-
-       flush_write_buffers();
-}
-
-static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev,
-                                          struct scatterlist *sg,
-                                          int nelems, int direction)
-{
-       BUG_ON(direction == PCI_DMA_NONE);
-
-#ifdef CONFIG_SWIOTLB
-       if (swiotlb)
-               return swiotlb_sync_sg_for_cpu(&hwdev->dev,sg,nelems,direction);
-#endif
-       flush_write_buffers();
-}
-
-static inline void pci_dma_sync_sg_for_device(struct pci_dev *hwdev,
-                                             struct scatterlist *sg,
-                                             int nelems, int direction)
-{ 
-       BUG_ON(direction == PCI_DMA_NONE); 
-
-#ifdef CONFIG_SWIOTLB
-       if (swiotlb)
-               return swiotlb_sync_sg_for_device(&hwdev->dev,sg,nelems,direction);
-#endif
-       flush_write_buffers();
-} 
-
-/* The PCI address space does equal the physical memory
- * address space.  The networking and block device layers use
- * this boolean for bounce buffer decisions
- *
- * On AMD64 it mostly equals, but we set it to zero to tell some subsystems
- * that an IOMMU is available.
- */
-#define PCI_DMA_BUS_IS_PHYS    (no_iommu ? 1 : 0) 
-
-/* We lie slightly when the IOMMU is forced to get the device to 
-   use SAC instead of DAC. */
-#define pci_dac_dma_supported(pci_dev, mask)   (force_iommu ? 0 : 1)
-
 #else
-static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
-                                       size_t size, int direction)
-{
-       dma_addr_t addr; 
+/* No IOMMU */
 
-       if (direction == PCI_DMA_NONE)
-               out_of_line_bug();      
-       addr = virt_to_bus(ptr); 
-
-       /* 
-        * This is gross, but what should I do.
-        * Unfortunately drivers do not test the return value of this.
- */
-       if ((addr+size) & ~hwdev->dma_mask) 
-               out_of_line_bug(); 
-       return addr;
-}
-
-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)
-               out_of_line_bug();
-       /* Nothing to do */
-}
-
-static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
-                                     unsigned long offset, size_t size, int direction)
-{
-       dma_addr_t addr;
-       if (direction == PCI_DMA_NONE)
-               out_of_line_bug();      
-       addr = page_to_pfn(page) * PAGE_SIZE + offset;
-       if ((addr+size) & ~hwdev->dma_mask) 
-               out_of_line_bug();
-       return addr;
-}
+#define PCI_DMA_BUS_IS_PHYS    1
+#define pci_dac_dma_supported(pci_dev, mask)    1
 
-/* pci_unmap_{page,single} is a nop so... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
 #define pci_unmap_addr(PTR, ADDR_NAME)         (0)
@@ -247,74 +90,9 @@ static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
 #define pci_unmap_len(PTR, LEN_NAME)           (0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
 
-/* 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, you
- * must first perform a pci_dma_sync_for_device, and then the
- * device again owns the buffer.
- */
-static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev,
-                                              dma_addr_t dma_handle,
-                                              size_t size, int direction)
-{
-       if (direction == PCI_DMA_NONE)
-               out_of_line_bug();
-}
-
-static inline void pci_dma_sync_single_for_device(struct pci_dev *hwdev,
-                                                 dma_addr_t dma_handle,
-                                                 size_t size, int direction)
-{
-       if (direction == PCI_DMA_NONE)
-               out_of_line_bug();
-       flush_write_buffers();
-}
-
-/* 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_for_cpu(struct pci_dev *hwdev,
-                                          struct scatterlist *sg,
-                                          int nelems, int direction)
-{
-       if (direction == PCI_DMA_NONE)
-               out_of_line_bug();
-}
-
-static inline void pci_dma_sync_sg_for_device(struct pci_dev *hwdev,
-                                             struct scatterlist *sg,
-                                             int nelems, int direction)
-{
-       if (direction == PCI_DMA_NONE)
-               out_of_line_bug();
-       flush_write_buffers();
-}
-
-#define PCI_DMA_BUS_IS_PHYS    1
-
-#define pci_dac_dma_supported(pci_dev, mask)   1
 #endif
 
-extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-                     int nents, int direction);
-extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-                        int nents, int direction);
-
-#define pci_unmap_page pci_unmap_single
-
-/* Return whether the given PCI device DMA address mask can
- * be supported properly.  For example, if your device can
- * only drive the low 24-bits during PCI bus mastering, then
- * you would pass 0x00ffffff as the mask to this function.
- */
-extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
+#include <asm-generic/pci-dma-compat.h>
 
 static inline dma64_addr_t
 pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
@@ -359,7 +137,6 @@ static inline void pcibios_add_platform_entries(struct pci_dev *dev)
 /* generic pci stuff */
 #ifdef CONFIG_PCI
 #include <asm-generic/pci.h>
-#include <linux/dma-mapping.h>
 #endif
 
 #endif /* __x8664_PCI_H */
index 25faf9f..f222306 100644 (file)
@@ -70,6 +70,7 @@ extern void __show_regs(struct pt_regs * regs);
 extern void show_regs(struct pt_regs * regs);
 
 extern int map_syscall32(struct mm_struct *mm, unsigned long address);
+extern int __map_syscall32(struct mm_struct *mm, unsigned long address);
 extern char *syscall32_page;
 extern void syscall32_cpu_init(void);
 
@@ -82,7 +83,6 @@ extern int unhandled_signal(struct task_struct *tsk, int sig);
 
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 extern void swiotlb_init(void);
-extern int swiotlb;
 
 extern unsigned long max_mapnr;
 extern unsigned long end_pfn; 
@@ -103,6 +103,8 @@ extern int fallback_aper_force;
 extern int iommu_aperture;
 extern int iommu_aperture_disabled;
 extern int iommu_aperture_allowed;
+extern int fix_aperture;
+extern int force_iommu;
 
 extern void smp_local_timer_interrupt(struct pt_regs * regs);
 
index 373e7ab..d9a252e 100644 (file)
 
 #define SO_PEERSEC             31
 
-/* Nasty libc5 fixup - bletch */
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h
new file mode 100644 (file)
index 0000000..c25270a
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _ASM_SWIOTLB_H
+#define _ASM_SWTIOLB_H 1
+
+#include <linux/config.h>
+
+/* SWIOTLB interface */
+
+extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr, size_t size,
+                                     int dir);
+extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
+                                 size_t size, int dir);
+extern void swiotlb_sync_single_for_cpu(struct device *hwdev,
+                                        dma_addr_t dev_addr,
+                                        size_t size, int dir);
+extern void swiotlb_sync_single_for_device(struct device *hwdev,
+                                           dma_addr_t dev_addr,
+                                           size_t size, int dir);
+extern void swiotlb_sync_sg_for_cpu(struct device *hwdev,
+                                    struct scatterlist *sg, int nelems,
+                                    int dir);
+extern void swiotlb_sync_sg_for_device(struct device *hwdev,
+                                       struct scatterlist *sg, int nelems,
+                                       int dir);
+extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
+                     int nents, int direction);
+extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
+                        int nents, int direction);
+extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr);
+
+#ifdef CONFIG_SWIOTLB
+extern int swiotlb;
+#else
+#define swiotlb 0
+#endif
+
+#endif
index 6abaf66..6671eb6 100644 (file)
@@ -297,11 +297,11 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 #define mb()   asm volatile("mfence":::"memory")
 #define rmb()  asm volatile("lfence":::"memory")
 
-/* could use SFENCE here, but it would be only needed for unordered SSE
-   store instructions and we always do an explicit sfence with them currently.
-   the ordering of normal stores is serialized enough. Just make it a compile
-   barrier. */
+#ifdef CONFIG_UNORDERED_IO
+#define wmb()  asm volatile("sfence" ::: "memory")
+#else
 #define wmb()  asm volatile("" ::: "memory")
+#endif
 #define read_barrier_depends() do {} while(0)
 #define set_mb(var, value) do { xchg(&var, value); } while (0)
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
index 9b49e9f..4a5d50c 100644 (file)
@@ -17,20 +17,20 @@ struct adfs_discrecord {
     __u8  bootoption;
     __u8  lowsector;
     __u8  nzones;
-    __u16 zone_spare;
-    __u32 root;
-    __u32 disc_size;
-    __u16 disc_id;
+    __le16 zone_spare;
+    __le32 root;
+    __le32 disc_size;
+    __le16 disc_id;
     __u8  disc_name[10];
-    __u32 disc_type;
-    __u32 disc_size_high;
+    __le32 disc_type;
+    __le32 disc_size_high;
     __u8  log2sharesize:4;
     __u8  unused40:4;
     __u8  big_flag:1;
     __u8  unused41:1;
     __u8  nzones_high;
-    __u32 format_version;
-    __u32 root_size;
+    __le32 format_version;
+    __le32 root_size;
     __u8  unused52[60 - 52];
 };
 
index 6341f70..cb54303 100644 (file)
@@ -17,7 +17,7 @@ struct adfs_inode_info {
        __u32           execaddr;       /* RISC OS exec address         */
        unsigned int    filetype;       /* RISC OS file type            */
        unsigned int    attr;           /* RISC OS permissions          */
-       int             stamped:1;      /* RISC OS file has date/time   */
+       unsigned int    stamped:1;      /* RISC OS file has date/time   */
        struct inode vfs_inode;
 };
 
index 30082c8..d9bf05c 100644 (file)
@@ -31,7 +31,7 @@ struct adfs_sb_info {
        unsigned long   s_size;         /* total size (in blocks) of this fs     */
        signed int      s_map2blk;      /* shift left by this for map->sector    */
        unsigned int    s_log2sharesize;/* log2 share size                       */
-       unsigned int    s_version;      /* disc format version                   */
+       __le32          s_version;      /* disc format version                   */
        unsigned int    s_namelen;      /* maximum number of characters in name  */
 };
 
index ae893e0..3fb8699 100644 (file)
@@ -5,13 +5,13 @@
 
 struct RigidDiskBlock {
        u32     rdb_ID;
-       u32     rdb_SummedLongs;
+       __be32  rdb_SummedLongs;
        s32     rdb_ChkSum;
        u32     rdb_HostID;
-       u32     rdb_BlockBytes;
+       __be32  rdb_BlockBytes;
        u32     rdb_Flags;
        u32     rdb_BadBlockList;
-       u32     rdb_PartitionList;
+       __be32  rdb_PartitionList;
        u32     rdb_FileSysHeaderList;
        u32     rdb_DriveInit;
        u32     rdb_Reserved1[6];
@@ -45,17 +45,17 @@ struct RigidDiskBlock {
 #define        IDNAME_RIGIDDISK        0x5244534B      /* "RDSK" */
 
 struct PartitionBlock {
-       u32     pb_ID;
-       u32     pb_SummedLongs;
+       __be32  pb_ID;
+       __be32  pb_SummedLongs;
        s32     pb_ChkSum;
        u32     pb_HostID;
-       u32     pb_Next;
+       __be32  pb_Next;
        u32     pb_Flags;
        u32     pb_Reserved1[2];
        u32     pb_DevFlags;
        u8      pb_DriveName[32];
        u32     pb_Reserved2[15];
-       u32     pb_Environment[17];
+       __be32  pb_Environment[17];
        u32     pb_EReserved[15];
 };
 
index 6fb6bb5..b9a0ee6 100644 (file)
@@ -80,14 +80,14 @@ affs_brelse(struct buffer_head *bh)
 static inline void
 affs_adjust_checksum(struct buffer_head *bh, u32 val)
 {
-       u32 tmp = be32_to_cpu(((u32 *)bh->b_data)[5]);
-       ((u32 *)bh->b_data)[5] = cpu_to_be32(tmp - val);
+       u32 tmp = be32_to_cpu(((__be32 *)bh->b_data)[5]);
+       ((__be32 *)bh->b_data)[5] = cpu_to_be32(tmp - val);
 }
 static inline void
 affs_adjust_bitmapchecksum(struct buffer_head *bh, u32 val)
 {
-       u32 tmp = be32_to_cpu(((u32 *)bh->b_data)[0]);
-       ((u32 *)bh->b_data)[0] = cpu_to_be32(tmp - val);
+       u32 tmp = be32_to_cpu(((__be32 *)bh->b_data)[0]);
+       ((__be32 *)bh->b_data)[0] = cpu_to_be32(tmp - val);
 }
 
 static inline void
@@ -164,89 +164,89 @@ affs_unlock_ext(struct inode *inode)
 #define AFFS_DATA(bh)          (((struct affs_data_head *)(bh)->b_data)->data)
 
 struct affs_date {
-       u32 days;
-       u32 mins;
-       u32 ticks;
+       __be32 days;
+       __be32 mins;
+       __be32 ticks;
 };
 
 struct affs_short_date {
-       u16 days;
-       u16 mins;
-       u16 ticks;
+       __be16 days;
+       __be16 mins;
+       __be16 ticks;
 };
 
 struct affs_root_head {
-       u32 ptype;
-       u32 spare1;
-       u32 spare2;
-       u32 hash_size;
-       u32 spare3;
-       u32 checksum;
-       u32 hashtable[1];
+       __be32 ptype;
+       __be32 spare1;
+       __be32 spare2;
+       __be32 hash_size;
+       __be32 spare3;
+       __be32 checksum;
+       __be32 hashtable[1];
 };
 
 struct affs_root_tail {
-       u32 bm_flag;
-       u32 bm_blk[AFFS_ROOT_BMAPS];
-       u32 bm_ext;
+       __be32 bm_flag;
+       __be32 bm_blk[AFFS_ROOT_BMAPS];
+       __be32 bm_ext;
        struct affs_date root_change;
        u8 disk_name[32];
-       u32 spare1;
-       u32 spare2;
+       __be32 spare1;
+       __be32 spare2;
        struct affs_date disk_change;
        struct affs_date disk_create;
-       u32 spare3;
-       u32 spare4;
-       u32 dcache;
-       u32 stype;
+       __be32 spare3;
+       __be32 spare4;
+       __be32 dcache;
+       __be32 stype;
 };
 
 struct affs_head {
-       u32 ptype;
-       u32 key;
-       u32 block_count;
-       u32 spare1;
-       u32 first_data;
-       u32 checksum;
-       u32 table[1];
+       __be32 ptype;
+       __be32 key;
+       __be32 block_count;
+       __be32 spare1;
+       __be32 first_data;
+       __be32 checksum;
+       __be32 table[1];
 };
 
 struct affs_tail {
-       u32 spare1;
-       u16 uid;
-       u16 gid;
-       u32 protect;
-       u32 size;
+       __be32 spare1;
+       __be16 uid;
+       __be16 gid;
+       __be32 protect;
+       __be32 size;
        u8 comment[92];
        struct affs_date change;
        u8 name[32];
-       u32 spare2;
-       u32 original;
-       u32 link_chain;
-       u32 spare[5];
-       u32 hash_chain;
-       u32 parent;
-       u32 extension;
-       u32 stype;
+       __be32 spare2;
+       __be32 original;
+       __be32 link_chain;
+       __be32 spare[5];
+       __be32 hash_chain;
+       __be32 parent;
+       __be32 extension;
+       __be32 stype;
 };
 
 struct slink_front
 {
-       u32 ptype;
-       u32 key;
-       u32 spare1[3];
-       u32 checksum;
+       __be32 ptype;
+       __be32 key;
+       __be32 spare1[3];
+       __be32 checksum;
        u8 symname[1];  /* depends on block size */
 };
 
 struct affs_data_head
 {
-       u32 ptype;
-       u32 key;
-       u32 sequence;
-       u32 size;
-       u32 next;
-       u32 checksum;
+       __be32 ptype;
+       __be32 key;
+       __be32 sequence;
+       __be32 size;
+       __be32 next;
+       __be32 checksum;
        u8 data[1];     /* depends on block size */
 };
 
index 3a3759f..9d2429f 100644 (file)
@@ -305,7 +305,7 @@ struct arcnet_local {
                                        void *buf, int count);
        } hw;
 
-       void *mem_start;        /* pointer to ioremap'ed MMIO */
+       void __iomem *mem_start;        /* pointer to ioremap'ed MMIO */
 };
 
 
index c4d2a09..2a9b820 100644 (file)
@@ -191,10 +191,13 @@ extern int                 aarp_send_ddp(struct net_device *dev,
 extern void             aarp_send_probe(struct net_device *dev,
                                         struct atalk_addr *addr);
 extern void             aarp_device_down(struct net_device *dev);
+extern void             aarp_probe_network(struct atalk_iface *atif);
+extern int              aarp_proxy_probe_network(struct atalk_iface *atif,
+                                    struct atalk_addr *sa);
+extern void             aarp_proxy_remove(struct net_device *dev,
+                                          struct atalk_addr *sa);
 
-#ifdef MODULE
-extern void aarp_cleanup_module(void);
-#endif /* MODULE */
+extern void            aarp_cleanup_module(void);
 
 #define at_sk(__sk) ((struct atalk_sock *)(__sk)->sk_protinfo)
 
@@ -209,8 +212,28 @@ extern rwlock_t atalk_interfaces_lock;
 
 extern struct atalk_route atrtr_default;
 
+extern struct file_operations atalk_seq_arp_fops;
+
+extern int sysctl_aarp_expiry_time;
+extern int sysctl_aarp_tick_time;
+extern int sysctl_aarp_retransmit_limit;
+extern int sysctl_aarp_resolve_time;
+
+#ifdef CONFIG_SYSCTL
+extern void atalk_register_sysctl(void);
+extern void atalk_unregister_sysctl(void);
+#else
+#define atalk_register_sysctl()                do { } while(0)
+#define atalk_unregister_sysctl()      do { } while(0)
+#endif
+
+#ifdef CONFIG_PROC_FS
 extern int atalk_proc_init(void);
 extern void atalk_proc_exit(void);
+#else
+#define atalk_proc_init()      0
+#define atalk_proc_exit()      do { } while(0)
+#endif /* CONFIG_PROC_FS */
 
 #endif /* __KERNEL__ */
 #endif /* __LINUX_ATALK_H__ */
index b84efd7..40d40b4 100644 (file)
@@ -8,48 +8,86 @@
 #define __BIG_ENDIAN_BITFIELD
 #endif
 
+#include <linux/types.h>
 #include <linux/byteorder/swab.h>
 
-#define __constant_htonl(x) ((__u32)(x))
-#define __constant_ntohl(x) ((__u32)(x))
-#define __constant_htons(x) ((__u16)(x))
-#define __constant_ntohs(x) ((__u16)(x))
-#define __constant_cpu_to_le64(x) ___constant_swab64((x))
-#define __constant_le64_to_cpu(x) ___constant_swab64((x))
-#define __constant_cpu_to_le32(x) ___constant_swab32((x))
-#define __constant_le32_to_cpu(x) ___constant_swab32((x))
-#define __constant_cpu_to_le16(x) ___constant_swab16((x))
-#define __constant_le16_to_cpu(x) ___constant_swab16((x))
-#define __constant_cpu_to_be64(x) ((__u64)(x))
-#define __constant_be64_to_cpu(x) ((__u64)(x))
-#define __constant_cpu_to_be32(x) ((__u32)(x))
-#define __constant_be32_to_cpu(x) ((__u32)(x))
-#define __constant_cpu_to_be16(x) ((__u16)(x))
-#define __constant_be16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_le64(x) __swab64((x))
-#define __le64_to_cpu(x) __swab64((x))
-#define __cpu_to_le32(x) __swab32((x))
-#define __le32_to_cpu(x) __swab32((x))
-#define __cpu_to_le16(x) __swab16((x))
-#define __le16_to_cpu(x) __swab16((x))
-#define __cpu_to_be64(x) ((__u64)(x))
-#define __be64_to_cpu(x) ((__u64)(x))
-#define __cpu_to_be32(x) ((__u32)(x))
-#define __be32_to_cpu(x) ((__u32)(x))
-#define __cpu_to_be16(x) ((__u16)(x))
-#define __be16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_le64p(x) __swab64p((x))
-#define __le64_to_cpup(x) __swab64p((x))
-#define __cpu_to_le32p(x) __swab32p((x))
-#define __le32_to_cpup(x) __swab32p((x))
-#define __cpu_to_le16p(x) __swab16p((x))
-#define __le16_to_cpup(x) __swab16p((x))
-#define __cpu_to_be64p(x) (*(__u64*)(x))
-#define __be64_to_cpup(x) (*(__u64*)(x))
-#define __cpu_to_be32p(x) (*(__u32*)(x))
-#define __be32_to_cpup(x) (*(__u32*)(x))
-#define __cpu_to_be16p(x) (*(__u16*)(x))
-#define __be16_to_cpup(x) (*(__u16*)(x))
+#define __constant_htonl(x) ((__force __be32)(__u32)(x))
+#define __constant_ntohl(x) ((__force __u32)(__be32)(x))
+#define __constant_htons(x) ((__force __be16)(__u16)(x))
+#define __constant_ntohs(x) ((__force __u16)(__be16)(x))
+#define __constant_cpu_to_le64(x) ((__force __le64)___constant_swab64((x)))
+#define __constant_le64_to_cpu(x) ___constant_swab64((__force __u64)(__le64)(x))
+#define __constant_cpu_to_le32(x) ((__force __le32)___constant_swab32((x)))
+#define __constant_le32_to_cpu(x) ___constant_swab32((__force __u32)(__le32)(x))
+#define __constant_cpu_to_le16(x) ((__force __le16)___constant_swab16((x)))
+#define __constant_le16_to_cpu(x) ___constant_swab16((__force __u16)(__le16)(x))
+#define __constant_cpu_to_be64(x) ((__force __be64)(__u64)(x))
+#define __constant_be64_to_cpu(x) ((__force __u64)(__be64)(x))
+#define __constant_cpu_to_be32(x) ((__force __be32)(__u32)(x))
+#define __constant_be32_to_cpu(x) ((__force __u32)(__be32)(x))
+#define __constant_cpu_to_be16(x) ((__force __be16)(__u16)(x))
+#define __constant_be16_to_cpu(x) ((__force __u16)(__be16)(x))
+#define __cpu_to_le64(x) ((__force __le64)___swab64((x)))
+#define __le64_to_cpu(x) ___swab64((__force __u64)(__le64)(x))
+#define __cpu_to_le32(x) ((__force __le32)___swab32((x)))
+#define __le32_to_cpu(x) ___swab32((__force __u32)(__le32)(x))
+#define __cpu_to_le16(x) ((__force __le16)___swab16((x)))
+#define __le16_to_cpu(x) ___swab16((__force __u16)(__le16)(x))
+#define __cpu_to_be64(x) ((__force __be64)(__u64)(x))
+#define __be64_to_cpu(x) ((__force __u64)(__be64)(x))
+#define __cpu_to_be32(x) ((__force __be32)(__u32)(x))
+#define __be32_to_cpu(x) ((__force __u32)(__be32)(x))
+#define __cpu_to_be16(x) ((__force __be16)(__u16)(x))
+#define __be16_to_cpu(x) ((__force __u16)(__be16)(x))
+
+static inline __le64 __cpu_to_le64p(const __u64 *p)
+{
+       return (__force __le64)__swab64p(p);
+}
+static inline __u64 __le64_to_cpup(const __le64 *p)
+{
+       return __swab64p((__u64 *)p);
+}
+static inline __le32 __cpu_to_le32p(const __u32 *p)
+{
+       return (__force __le32)__swab32p(p);
+}
+static inline __u32 __le32_to_cpup(const __le32 *p)
+{
+       return __swab32p((__u32 *)p);
+}
+static inline __le16 __cpu_to_le16p(const __u16 *p)
+{
+       return (__force __le16)__swab16p(p);
+}
+static inline __u16 __le16_to_cpup(const __le16 *p)
+{
+       return __swab16p((__u16 *)p);
+}
+static inline __be64 __cpu_to_be64p(const __u64 *p)
+{
+       return (__force __be64)*p;
+}
+static inline __u64 __be64_to_cpup(const __be64 *p)
+{
+       return (__force __u64)*p;
+}
+static inline __be32 __cpu_to_be32p(const __u32 *p)
+{
+       return (__force __be32)*p;
+}
+static inline __u32 __be32_to_cpup(const __be32 *p)
+{
+       return (__force __u32)*p;
+}
+static inline __be16 __cpu_to_be16p(const __u16 *p)
+{
+       return (__force __be16)*p;
+}
+static inline __u16 __be16_to_cpup(const __be16 *p)
+{
+       return (__force __u16)*p;
+}
 #define __cpu_to_le64s(x) __swab64s((x))
 #define __le64_to_cpus(x) __swab64s((x))
 #define __cpu_to_le32s(x) __swab32s((x))
index 5f33f56..5fde6f4 100644 (file)
  * Do the prototypes. Somebody might want to take the
  * address or some such sick thing..
  */
-extern __u32                   ntohl(__u32);
-extern __u32                   htonl(__u32);
-extern unsigned short int      ntohs(unsigned short int);
-extern unsigned short int      htons(unsigned short int);
+extern __u32                   ntohl(__be32);
+extern __be32                  htonl(__u32);
+extern __u16                   ntohs(__be16);
+extern __be16                  htons(__u16);
 
 #if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
 
index 1431663..c05349b 100644 (file)
@@ -8,48 +8,86 @@
 #define __LITTLE_ENDIAN_BITFIELD
 #endif
 
+#include <linux/types.h>
 #include <linux/byteorder/swab.h>
 
-#define __constant_htonl(x) ___constant_swab32((x))
-#define __constant_ntohl(x) ___constant_swab32((x))
-#define __constant_htons(x) ___constant_swab16((x))
-#define __constant_ntohs(x) ___constant_swab16((x))
-#define __constant_cpu_to_le64(x) ((__u64)(x))
-#define __constant_le64_to_cpu(x) ((__u64)(x))
-#define __constant_cpu_to_le32(x) ((__u32)(x))
-#define __constant_le32_to_cpu(x) ((__u32)(x))
-#define __constant_cpu_to_le16(x) ((__u16)(x))
-#define __constant_le16_to_cpu(x) ((__u16)(x))
-#define __constant_cpu_to_be64(x) ___constant_swab64((x))
-#define __constant_be64_to_cpu(x) ___constant_swab64((x))
-#define __constant_cpu_to_be32(x) ___constant_swab32((x))
-#define __constant_be32_to_cpu(x) ___constant_swab32((x))
-#define __constant_cpu_to_be16(x) ___constant_swab16((x))
-#define __constant_be16_to_cpu(x) ___constant_swab16((x))
-#define __cpu_to_le64(x) ((__u64)(x))
-#define __le64_to_cpu(x) ((__u64)(x))
-#define __cpu_to_le32(x) ((__u32)(x))
-#define __le32_to_cpu(x) ((__u32)(x))
-#define __cpu_to_le16(x) ((__u16)(x))
-#define __le16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_be64(x) __swab64((x))
-#define __be64_to_cpu(x) __swab64((x))
-#define __cpu_to_be32(x) __swab32((x))
-#define __be32_to_cpu(x) __swab32((x))
-#define __cpu_to_be16(x) __swab16((x))
-#define __be16_to_cpu(x) __swab16((x))
-#define __cpu_to_le64p(x) (*(__u64*)(x))
-#define __le64_to_cpup(x) (*(__u64*)(x))
-#define __cpu_to_le32p(x) (*(__u32*)(x))
-#define __le32_to_cpup(x) (*(__u32*)(x))
-#define __cpu_to_le16p(x) (*(__u16*)(x))
-#define __le16_to_cpup(x) (*(__u16*)(x))
-#define __cpu_to_be64p(x) __swab64p((x))
-#define __be64_to_cpup(x) __swab64p((x))
-#define __cpu_to_be32p(x) __swab32p((x))
-#define __be32_to_cpup(x) __swab32p((x))
-#define __cpu_to_be16p(x) __swab16p((x))
-#define __be16_to_cpup(x) __swab16p((x))
+#define __constant_htonl(x) ((__force __be32)___constant_swab32((x)))
+#define __constant_ntohl(x) ___constant_swab32((__force __be32)(x))
+#define __constant_htons(x) ((__force __be16)___constant_swab16((x)))
+#define __constant_ntohs(x) ___constant_swab16((__force __be16)(x))
+#define __constant_cpu_to_le64(x) ((__force __le64)(__u64)(x))
+#define __constant_le64_to_cpu(x) ((__force __u64)(__le64)(x))
+#define __constant_cpu_to_le32(x) ((__force __le32)(__u32)(x))
+#define __constant_le32_to_cpu(x) ((__force __u32)(__le32)(x))
+#define __constant_cpu_to_le16(x) ((__force __le16)(__u16)(x))
+#define __constant_le16_to_cpu(x) ((__force __u16)(__le16)(x))
+#define __constant_cpu_to_be64(x) ((__force __be64)___constant_swab64((x)))
+#define __constant_be64_to_cpu(x) ___constant_swab64((__force __u64)(__be64)(x))
+#define __constant_cpu_to_be32(x) ((__force __be32)___constant_swab32((x)))
+#define __constant_be32_to_cpu(x) ___constant_swab32((__force __u32)(__be32)(x))
+#define __constant_cpu_to_be16(x) ((__force __be16)___constant_swab16((x)))
+#define __constant_be16_to_cpu(x) ___constant_swab16((__force __u16)(__be16)(x))
+#define __cpu_to_le64(x) ((__force __le64)(__u64)(x))
+#define __le64_to_cpu(x) ((__force __u64)(__le64)(x))
+#define __cpu_to_le32(x) ((__force __le32)(__u32)(x))
+#define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
+#define __cpu_to_le16(x) ((__force __le16)(__u16)(x))
+#define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
+#define __cpu_to_be64(x) ((__force __be64)___swab64((x)))
+#define __be64_to_cpu(x) ___swab64((__force __u64)(__be64)(x))
+#define __cpu_to_be32(x) ((__force __be32)___swab32((x)))
+#define __be32_to_cpu(x) ___swab32((__force __u32)(__be32)(x))
+#define __cpu_to_be16(x) ((__force __be16)___swab16((x)))
+#define __be16_to_cpu(x) ___swab16((__force __u16)(__be16)(x))
+
+static inline __le64 __cpu_to_le64p(const __u64 *p)
+{
+       return (__force __le64)*p;
+}
+static inline __u64 __le64_to_cpup(const __le64 *p)
+{
+       return (__force __u64)*p;
+}
+static inline __le32 __cpu_to_le32p(const __u32 *p)
+{
+       return (__force __le32)*p;
+}
+static inline __u32 __le32_to_cpup(const __le32 *p)
+{
+       return (__force __u32)*p;
+}
+static inline __le16 __cpu_to_le16p(const __u16 *p)
+{
+       return (__force __le16)*p;
+}
+static inline __u16 __le16_to_cpup(const __le16 *p)
+{
+       return (__force __u16)*p;
+}
+static inline __be64 __cpu_to_be64p(const __u64 *p)
+{
+       return (__force __be64)__swab64p(p);
+}
+static inline __u64 __be64_to_cpup(const __be64 *p)
+{
+       return __swab64p((__u64 *)p);
+}
+static inline __be32 __cpu_to_be32p(const __u32 *p)
+{
+       return (__force __be32)__swab32p(p);
+}
+static inline __u32 __be32_to_cpup(const __be32 *p)
+{
+       return __swab32p((__u32 *)p);
+}
+static inline __be16 __cpu_to_be16p(const __u16 *p)
+{
+       return (__force __be16)__swab16p(p);
+}
+static inline __u16 __be16_to_cpup(const __be16 *p)
+{
+       return __swab16p((__u16 *)p);
+}
 #define __cpu_to_le64s(x) do {} while (0)
 #define __le64_to_cpus(x) do {} while (0)
 #define __cpu_to_le32s(x) do {} while (0)
index eb921d6..309cbbe 100644 (file)
@@ -200,7 +200,7 @@ typedef u_int32_t vuid_t;
 typedef u_int32_t vgid_t;
 #endif /*_VUID_T_ */
 
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 struct CodaFid {
        u_int32_t opaque[3];
 };
@@ -220,7 +220,7 @@ struct coda_cred {
     vgid_t cr_groupid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */
 };
 
-#else /* not defined(CODA_FS_OLD_API) */
+#else /* not defined(CONFIG_CODA_FS_OLD_API) */
 
 struct CodaFid {
        u_int32_t opaque[4];
@@ -318,7 +318,7 @@ struct coda_statfs {
 #define CODA_KERNEL_VERSION 0 /* don't care about kernel version number */
 #define CODA_KERNEL_VERSION 1 /* The old venus 4.6 compatible interface */
 #endif
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 #define CODA_KERNEL_VERSION 2 /* venus_lookup got an extra parameter */
 #else
 #define CODA_KERNEL_VERSION 3 /* 128-bit file identifiers */
@@ -330,7 +330,7 @@ struct coda_statfs {
 struct coda_in_hdr {
     u_int32_t opcode;
     u_int32_t unique;      /* Keep multiple outstanding msgs distinct */
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
     u_int16_t pid;         /* Common to all */
     u_int16_t pgid;        /* Common to all */
     u_int16_t sid;          /* Common to all */
@@ -614,7 +614,7 @@ struct coda_vget_out {
 /* CODA_PURGEUSER is a venus->kernel call */
 struct coda_purgeuser_out {
     struct coda_out_hdr oh;
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
     struct coda_cred cred;
 #else
     vuid_t uid;
index cc59850..46d8254 100644 (file)
@@ -511,8 +511,8 @@ struct resource;
 struct cyclades_card {
     unsigned long base_phys;
     unsigned long ctl_phys;
-    unsigned long base_addr;
-    unsigned long ctl_addr;
+    void __iomem *base_addr;
+    void __iomem *ctl_addr;
     int irq;
     int num_chips;     /* 0 if card absent, -1 if Z/PCI, else Y */
     int first_line;    /* minor number of first channel on card */
@@ -539,9 +539,9 @@ struct cyclades_chip {
  * (required to support Alpha systems) *
  ***************************************/
 
-#define cy_writeb(port,val)     {writeb((ucchar)(val),(ulong)(port)); mb();}
-#define cy_writew(port,val)     {writew((ushort)(val),(ulong)(port)); mb();}
-#define cy_writel(port,val)     {writel((uclong)(val),(ulong)(port)); mb();}
+#define cy_writeb(port,val)     {writeb((val),(port)); mb();}
+#define cy_writew(port,val)     {writew((val),(port)); mb();}
+#define cy_writel(port,val)     {writel((val),(port)); mb();}
 
 #define cy_readb(port)  readb(port)
 #define cy_readw(port)  readw(port)
index 330f23e..bf2d657 100644 (file)
@@ -1,34 +1,22 @@
 /*
- * Copyright (c) 1995-2001 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 1995-2001,2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2.1 of the GNU Lesser General Public License
  * as published by the Free Software Foundation.
  *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 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.
  *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
  *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
- * USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ * Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ * Mountain View, CA 94043, USA, or: http://www.sgi.com
  */
 #ifndef _LINUX_DQBLK_XFS_H
 #define _LINUX_DQBLK_XFS_H
  */
 
 #define XQM_CMD(x)     (('X'<<8)+(x))  /* note: forms first QCMD argument */
-#define Q_XQUOTAON     XQM_CMD(0x1)    /* enable accounting/enforcement */
-#define Q_XQUOTAOFF    XQM_CMD(0x2)    /* disable accounting/enforcement */
-#define Q_XGETQUOTA    XQM_CMD(0x3)    /* get disk limits and usage */
-#define Q_XSETQLIM     XQM_CMD(0x4)    /* set disk limits */
-#define Q_XGETQSTAT    XQM_CMD(0x5)    /* get quota subsystem status */
-#define Q_XQUOTARM     XQM_CMD(0x6)    /* free disk space used by dquots */
+#define Q_XQUOTAON     XQM_CMD(1)      /* enable accounting/enforcement */
+#define Q_XQUOTAOFF    XQM_CMD(2)      /* disable accounting/enforcement */
+#define Q_XGETQUOTA    XQM_CMD(3)      /* get disk limits and usage */
+#define Q_XSETQLIM     XQM_CMD(4)      /* set disk limits */
+#define Q_XGETQSTAT    XQM_CMD(5)      /* get quota subsystem status */
+#define Q_XQUOTARM     XQM_CMD(6)      /* free disk space used by dquots */
 
 /*
  * fs_disk_quota structure:
@@ -104,6 +92,19 @@ typedef struct fs_disk_quota {
 #define FS_DQ_RTBTIMER         (1<<8)
 #define FS_DQ_TIMER_MASK       (FS_DQ_BTIMER | FS_DQ_ITIMER | FS_DQ_RTBTIMER)
 
+/*
+ * Warning counts are set in both super user's dquot and others. For others,
+ * warnings are set/cleared by the administrators (or automatically by going
+ * below the soft limit).  Superusers warning values set the warning limits
+ * for the rest.  In case these values are zero, the DQ_{F,B}WARNLIMIT values
+ * defined below are used. 
+ * These values also apply only to the d_fieldmask field for Q_XSETQLIM.
+ */
+#define FS_DQ_BWARNS   (1<<9)
+#define FS_DQ_IWARNS   (1<<10)
+#define FS_DQ_RTBWARNS (1<<11)
+#define FS_DQ_WARNS_MASK       (FS_DQ_BWARNS | FS_DQ_IWARNS | FS_DQ_RTBWARNS)
+
 /*
  * Various flags related to quotactl(2).  Only relevant to XFS filesystems.
  */
@@ -111,9 +112,11 @@ typedef struct fs_disk_quota {
 #define XFS_QUOTA_UDQ_ENFD     (1<<1)  /* user quota limits enforcement */
 #define XFS_QUOTA_GDQ_ACCT     (1<<2)  /* group quota accounting */
 #define XFS_QUOTA_GDQ_ENFD     (1<<3)  /* group quota limits enforcement */
+#define XFS_QUOTA_PDQ_ACCT     (1<<4)  /* project quota accounting */
+#define XFS_QUOTA_PDQ_ENFD     (1<<5)  /* project quota limits enforcement */
 
 #define XFS_USER_QUOTA         (1<<0)  /* user quota type */
-#define XFS_PROJ_QUOTA         (1<<1)  /* (IRIX) project quota type */
+#define XFS_PROJ_QUOTA         (1<<1)  /* project quota type */
 #define XFS_GROUP_QUOTA                (1<<2)  /* group quota type */
 
 /*
index 3315241..a09ec01 100644 (file)
@@ -11,7 +11,7 @@
 #define EFS_DIRBSIZE           (1 << EFS_DIRBSIZE_BITS)
 
 struct efs_dentry {
-       unsigned int    inode;
+       __be32          inode;
        unsigned char   namelen;
        char            name[3];
 };
@@ -23,7 +23,7 @@ struct efs_dentry {
 #define EFS_DIRBLK_MAGIC       0xbeef  /* moo */
 
 struct efs_dir {
-       unsigned short  magic;
+       __be16  magic;
        unsigned char   firstused;
        unsigned char   slots;
 
index 1640eb8..f7c8446 100644 (file)
@@ -40,11 +40,9 @@ extern struct inode_operations efs_dir_inode_operations;
 extern struct file_operations efs_dir_operations;
 extern struct address_space_operations efs_symlink_aops;
 
-extern int efs_fill_super(struct super_block *, void *, int);
-extern int efs_statfs(struct super_block *, struct kstatfs *);
-
 extern void efs_read_inode(struct inode *);
 extern efs_block_t efs_map_block(struct inode *, efs_block_t);
+extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
 extern int efs_bmap(struct inode *, int);
index 64fe538..617c474 100644 (file)
@@ -28,8 +28,8 @@ typedef union extent_u {
 } efs_extent;
 
 typedef struct edevs {
-       short           odev;
-       unsigned int    ndev;
+       __be16          odev;
+       __be32          ndev;
 } efs_devs;
 
 /*
@@ -37,16 +37,16 @@ typedef struct edevs {
  * is exactly 128 bytes long.
  */
 struct efs_dinode {
-       u_short         di_mode;        /* mode and type of file */
-       short           di_nlink;       /* number of links to file */
-       u_short         di_uid;         /* owner's user id */
-       u_short         di_gid;         /* owner's group id */
-       int32_t         di_size;        /* number of bytes in file */
-       int32_t         di_atime;       /* time last accessed */
-       int32_t         di_mtime;       /* time last modified */
-       int32_t         di_ctime;       /* time created */
-       uint32_t        di_gen;         /* generation number */
-       short           di_numextents;  /* # of extents */
+       __be16          di_mode;        /* mode and type of file */
+       __be16          di_nlink;       /* number of links to file */
+       __be16          di_uid;         /* owner's user id */
+       __be16          di_gid;         /* owner's group id */
+       __be32          di_size;        /* number of bytes in file */
+       __be32          di_atime;       /* time last accessed */
+       __be32          di_mtime;       /* time last modified */
+       __be32          di_ctime;       /* time created */
+       __be32          di_gen;         /* generation number */
+       __be16          di_numextents;  /* # of extents */
        u_char          di_version;     /* version of inode */
        u_char          di_spare;       /* spare - used by AFS */
        union di_addr {
index 21d01d0..c76088b 100644 (file)
 
 /* efs superblock on disk */
 struct efs_super {
-       int32_t         fs_size;        /* size of filesystem, in sectors */
-       int32_t         fs_firstcg;     /* bb offset to first cg */
-       int32_t         fs_cgfsize;     /* size of cylinder group in bb's */
-       short           fs_cgisize;     /* bb's of inodes per cylinder group */
-       short           fs_sectors;     /* sectors per track */
-       short           fs_heads;       /* heads per cylinder */
-       short           fs_ncg;         /* # of cylinder groups in filesystem */
-       short           fs_dirty;       /* fs needs to be fsck'd */
-       int32_t         fs_time;        /* last super-block update */
-       int32_t         fs_magic;       /* magic number */
+       __be32          fs_size;        /* size of filesystem, in sectors */
+       __be32          fs_firstcg;     /* bb offset to first cg */
+       __be32          fs_cgfsize;     /* size of cylinder group in bb's */
+       __be16          fs_cgisize;     /* bb's of inodes per cylinder group */
+       __be16          fs_sectors;     /* sectors per track */
+       __be16          fs_heads;       /* heads per cylinder */
+       __be16          fs_ncg;         /* # of cylinder groups in filesystem */
+       __be16          fs_dirty;       /* fs needs to be fsck'd */
+       __be32          fs_time;        /* last super-block update */
+       __be32          fs_magic;       /* magic number */
        char            fs_fname[6];    /* file system name */
        char            fs_fpack[6];    /* file system pack name */
-       int32_t         fs_bmsize;      /* size of bitmap in bytes */
-       int32_t         fs_tfree;       /* total free data blocks */
-       int32_t         fs_tinode;      /* total free inodes */
-       int32_t         fs_bmblock;     /* bitmap location. */
-       int32_t         fs_replsb;      /* Location of replicated superblock. */
-       int32_t         fs_lastialloc;  /* last allocated inode */
+       __be32          fs_bmsize;      /* size of bitmap in bytes */
+       __be32          fs_tfree;       /* total free data blocks */
+       __be32          fs_tinode;      /* total free inodes */
+       __be32          fs_bmblock;     /* bitmap location. */
+       __be32          fs_replsb;      /* Location of replicated superblock. */
+       __be32          fs_lastialloc;  /* last allocated inode */
        char            fs_spare[20];   /* space for expansion - MUST BE ZERO */
-       int32_t         fs_checksum;    /* checksum of volume portion of fs */
+       __be32          fs_checksum;    /* checksum of volume portion of fs */
 };
 
 /* efs superblock information in memory */
 struct efs_sb_info {
-       int32_t fs_magic;       /* superblock magic number */
-       int32_t fs_start;       /* first block of filesystem */
-       int32_t first_block;    /* first data block in filesystem */
-       int32_t total_blocks;   /* total number of blocks in filesystem */
-       int32_t group_size;     /* # of blocks a group consists of */ 
-       int32_t data_free;      /* # of free data blocks */
-       int32_t inode_free;     /* # of free inodes */
-       short   inode_blocks;   /* # of blocks used for inodes in every grp */
-       short   total_groups;   /* # of groups */
+       __u32   fs_magic;       /* superblock magic number */
+       __u32   fs_start;       /* first block of filesystem */
+       __u32   first_block;    /* first data block in filesystem */
+       __u32   total_blocks;   /* total number of blocks in filesystem */
+       __u32   group_size;     /* # of blocks a group consists of */ 
+       __u32   data_free;      /* # of free data blocks */
+       __u32   inode_free;     /* # of free inodes */
+       __u16   inode_blocks;   /* # of blocks used for inodes in every grp */
+       __u16   total_groups;   /* # of groups */
 };
 
 #endif /* __EFS_FS_SB_H__ */
index b9d7e4d..b3df61e 100644 (file)
 
 struct volume_directory {
        char    vd_name[VDNAMESIZE];    /* name */
-       int     vd_lbn;                 /* logical block number */
-       int     vd_nbytes;              /* file length in bytes */
+       __be32  vd_lbn;                 /* logical block number */
+       __be32  vd_nbytes;              /* file length in bytes */
 };
 
 struct partition_table {       /* one per logical partition */
-       int     pt_nblks;       /* # of logical blks in partition */
-       int     pt_firstlbn;    /* first lbn of partition */
-       int     pt_type;        /* use of partition */
+       __be32  pt_nblks;       /* # of logical blks in partition */
+       __be32  pt_firstlbn;    /* first lbn of partition */
+       __be32  pt_type;        /* use of partition */
 };
 
 struct volume_header {
-       int     vh_magic;                       /* identifies volume header */
-       short   vh_rootpt;                      /* root partition number */
-       short   vh_swappt;                      /* swap partition number */
+       __be32  vh_magic;                       /* identifies volume header */
+       __be16  vh_rootpt;                      /* root partition number */
+       __be16  vh_swappt;                      /* swap partition number */
        char    vh_bootfile[BFNAMESIZE];        /* name of file to boot */
        char    pad[48];                        /* device param space */
        struct volume_directory vh_vd[NVDIR];   /* other vol hdr contents */
        struct partition_table  vh_pt[NPARTAB]; /* device partition layout */
-       int     vh_csum;                        /* volume header checksum */
-       int     vh_fill;                        /* fill out to 512 bytes */
+       __be32  vh_csum;                        /* volume header checksum */
+       __be32  vh_fill;                        /* fill out to 512 bytes */
 };
 
 /* partition type sysv is used for EFS format CD-ROM partitions */
index 92cab64..17c55df 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LINUX_ERR_H
 #define _LINUX_ERR_H
 
+#include <linux/compiler.h>
+
 #include <asm/errno.h>
 
 /*
@@ -23,7 +25,7 @@ static inline long PTR_ERR(const void *ptr)
 
 static inline long IS_ERR(const void *ptr)
 {
-       return (unsigned long)ptr > (unsigned long)-1000L;
+       return unlikely((unsigned long)ptr > (unsigned long)-1000L);
 }
 
 #endif /* _LINUX_ERR_H */
diff --git a/include/linux/gen_stats.h b/include/linux/gen_stats.h
new file mode 100644 (file)
index 0000000..ab631c3
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef __LINUX_GEN_STATS_H
+#define __LINUX_GEN_STATS_H
+
+#include <linux/types.h>
+
+enum {
+       TCA_STATS_UNSPEC,
+       TCA_STATS_BASIC,
+       TCA_STATS_RATE_EST,
+       TCA_STATS_QUEUE,
+       TCA_STATS_APP,
+       __TCA_STATS_MAX,
+};
+#define TCA_STATS_MAX (__TCA_STATS_MAX - 1)
+
+/**
+ * @bytes: number of seen bytes
+ * @packets: number of seen packets
+ */
+struct gnet_stats_basic
+{
+       __u64   bytes;
+       __u32   packets;
+};
+
+/**
+ * @bps: current byte rate
+ * @pps: current packet rate
+ */
+struct gnet_stats_rate_est
+{
+       __u32   bps;
+       __u32   pps;
+};
+
+/**
+ * @qlen: queue length
+ * @backlog: backlog size of queue
+ * @drops: number of dropped packets
+ * @requeues: number of requeues
+ */
+struct gnet_stats_queue
+{
+       __u32   qlen;
+       __u32   backlog;
+       __u32   drops;
+       __u32   requeues;
+       __u32   overlimits;
+};
+
+/**
+ * @interval: sampling period
+ * @ewma_log: the log of measurement window weight
+ */
+struct gnet_estimator
+{
+       signed char     interval;
+       unsigned char   ewma_log;
+};
+
+
+#endif /* __LINUX_GEN_STATS_H */
index 884d18d..749992d 100644 (file)
@@ -42,6 +42,8 @@ enum {
        UNIXWARE_PARTITION = 0x63,      /* Same as GNU_HURD and SCO Unix */
 };
 
+#ifndef __KERNEL__
+
 struct partition {
        unsigned char boot_ind;         /* 0x80 - active */
        unsigned char head;             /* starting head */
@@ -55,7 +57,22 @@ struct partition {
        unsigned int nr_sects;          /* nr of sectors in partition */
 } __attribute__((packed));
 
+#endif
+
 #ifdef __KERNEL__
+struct partition {
+       unsigned char boot_ind;         /* 0x80 - active */
+       unsigned char head;             /* starting head */
+       unsigned char sector;           /* starting sector */
+       unsigned char cyl;              /* starting cylinder */
+       unsigned char sys_ind;          /* What partition type */
+       unsigned char end_head;         /* end head */
+       unsigned char end_sector;       /* end sector */
+       unsigned char end_cyl;          /* end cylinder */
+       __le32 start_sect;      /* starting sector counting from 0 */
+       __le32 nr_sects;                /* nr of sectors in partition */
+} __attribute__((packed));
+
 struct hd_struct {
        sector_t start_sect;
        sector_t nr_sects;
@@ -100,7 +117,7 @@ struct gendisk {
        struct timer_rand_state *random;
        int policy;
 
-       unsigned sync_io;               /* RAID */
+       atomic_t sync_io;               /* RAID */
        unsigned long stamp, stamp_idle;
        int in_flight;
 #ifdef CONFIG_SMP
@@ -218,19 +235,19 @@ static inline void set_capacity(struct gendisk *disk, sector_t size)
 #define SOLARIS_X86_VTOC_SANE  (0x600DDEEEUL)
 
 struct solaris_x86_slice {
-       ushort  s_tag;                  /* ID tag of partition */
-       ushort  s_flag;                 /* permission flags */
-       unsigned int s_start;           /* start sector no of partition */
-       unsigned int s_size;            /* # of blocks in partition */
+       __le16 s_tag;           /* ID tag of partition */
+       __le16 s_flag;          /* permission flags */
+       __le32 s_start;         /* start sector no of partition */
+       __le32 s_size;          /* # of blocks in partition */
 };
 
 struct solaris_x86_vtoc {
        unsigned int v_bootinfo[3];     /* info needed by mboot (unsupported) */
-       unsigned int v_sanity;          /* to verify vtoc sanity */
-       unsigned int v_version;         /* layout version */
+       __le32 v_sanity;                /* to verify vtoc sanity */
+       __le32 v_version;               /* layout version */
        char    v_volume[8];            /* volume name */
-       ushort  v_sectorsz;             /* sector size in bytes */
-       ushort  v_nparts;               /* number of partitions */
+       __le16  v_sectorsz;             /* sector size in bytes */
+       __le16  v_nparts;               /* number of partitions */
        unsigned int v_reserved[10];    /* free space */
        struct solaris_x86_slice
                v_slice[SOLARIS_X86_NUMSLICE]; /* slice headers */
@@ -249,11 +266,11 @@ struct solaris_x86_vtoc {
 /* check against BSD src/sys/sys/disklabel.h for consistency */
 
 #define BSD_DISKMAGIC  (0x82564557UL)  /* The disk magic number */
-#define BSD_MAXPARTITIONS      8
+#define BSD_MAXPARTITIONS      16
 #define OPENBSD_MAXPARTITIONS  16
 #define BSD_FS_UNUSED          0       /* disklabel unused partition entry ID */
 struct bsd_disklabel {
-       __u32   d_magic;                /* the magic number */
+       __le32  d_magic;                /* the magic number */
        __s16   d_type;                 /* drive type */
        __s16   d_subtype;              /* controller/d_type specific */
        char    d_typename[16];         /* type name, e.g. "eagle" */
@@ -278,20 +295,20 @@ struct bsd_disklabel {
        __u32   d_drivedata[NDDATA];    /* drive-type specific information */
 #define NSPARE 5
        __u32   d_spare[NSPARE];        /* reserved for future use */
-       __u32   d_magic2;               /* the magic number (again) */
-       __u16   d_checksum;             /* xor of data incl. partitions */
+       __le32  d_magic2;               /* the magic number (again) */
+       __le16  d_checksum;             /* xor of data incl. partitions */
 
                        /* filesystem and partition information: */
-       __u16   d_npartitions;          /* number of partitions in following */
-       __u32   d_bbsize;               /* size of boot area at sn0, bytes */
-       __u32   d_sbsize;               /* max size of fs superblock, bytes */
+       __le16  d_npartitions;          /* number of partitions in following */
+       __le32  d_bbsize;               /* size of boot area at sn0, bytes */
+       __le32  d_sbsize;               /* max size of fs superblock, bytes */
        struct  bsd_partition {         /* the partition table */
-               __u32   p_size;         /* number of sectors in partition */
-               __u32   p_offset;       /* starting sector */
-               __u32   p_fsize;        /* filesystem basic fragment size */
+               __le32  p_size;         /* number of sectors in partition */
+               __le32  p_offset;       /* starting sector */
+               __le32  p_fsize;        /* filesystem basic fragment size */
                __u8    p_fstype;       /* filesystem type, see below */
                __u8    p_frag;         /* filesystem fragments per block */
-               __u16   p_cpg;          /* filesystem cylinders per group */
+               __le16  p_cpg;          /* filesystem cylinders per group */
        } d_partitions[BSD_MAXPARTITIONS];      /* actually may be more */
 };
 
@@ -309,40 +326,40 @@ struct bsd_disklabel {
 #define UNIXWARE_FS_UNUSED     0               /* Unused slice entry ID */
 
 struct unixware_slice {
-       __u16   s_label;        /* label */
-       __u16   s_flags;        /* permission flags */
-       __u32   start_sect;     /* starting sector */
-       __u32   nr_sects;       /* number of sectors in slice */
+       __le16   s_label;       /* label */
+       __le16   s_flags;       /* permission flags */
+       __le32   start_sect;    /* starting sector */
+       __le32   nr_sects;      /* number of sectors in slice */
 };
 
 struct unixware_disklabel {
-       __u32   d_type;                 /* drive type */
-       __u32   d_magic;                /* the magic number */
-       __u32   d_version;              /* version number */
+       __le32   d_type;                /* drive type */
+       __le32   d_magic;                /* the magic number */
+       __le32   d_version;              /* version number */
        char    d_serial[12];           /* serial number of the device */
-       __u32   d_ncylinders;           /* # of data cylinders per device */
-       __u32   d_ntracks;              /* # of tracks per cylinder */
-       __u32   d_nsectors;             /* # of data sectors per track */
-       __u32   d_secsize;              /* # of bytes per sector */
-       __u32   d_part_start;           /* # of first sector of this partition */
-       __u32   d_unknown1[12];         /* ? */
-       __u32   d_alt_tbl;              /* byte offset of alternate table */
-       __u32   d_alt_len;              /* byte length of alternate table */
-       __u32   d_phys_cyl;             /* # of physical cylinders per device */
-       __u32   d_phys_trk;             /* # of physical tracks per cylinder */
-       __u32   d_phys_sec;             /* # of physical sectors per track */
-       __u32   d_phys_bytes;           /* # of physical bytes per sector */
-       __u32   d_unknown2;             /* ? */
-       __u32   d_unknown3;             /* ? */
-       __u32   d_pad[8];               /* pad */
+       __le32   d_ncylinders;           /* # of data cylinders per device */
+       __le32   d_ntracks;              /* # of tracks per cylinder */
+       __le32   d_nsectors;             /* # of data sectors per track */
+       __le32   d_secsize;              /* # of bytes per sector */
+       __le32   d_part_start;           /* # of first sector of this partition */
+       __le32   d_unknown1[12];         /* ? */
+       __le32  d_alt_tbl;              /* byte offset of alternate table */
+       __le32  d_alt_len;              /* byte length of alternate table */
+       __le32  d_phys_cyl;             /* # of physical cylinders per device */
+       __le32  d_phys_trk;             /* # of physical tracks per cylinder */
+       __le32  d_phys_sec;             /* # of physical sectors per track */
+       __le32  d_phys_bytes;           /* # of physical bytes per sector */
+       __le32  d_unknown2;             /* ? */
+       __le32   d_unknown3;             /* ? */
+       __le32  d_pad[8];               /* pad */
 
        struct unixware_vtoc {
-               __u32   v_magic;                /* the magic number */
-               __u32   v_version;              /* version number */
+               __le32  v_magic;                /* the magic number */
+               __le32  v_version;              /* version number */
                char    v_name[8];              /* volume name */
-               __u16   v_nslices;              /* # of slices */
-               __u16   v_unknown1;             /* ? */
-               __u32   v_reserved[10];         /* reserved */
+               __le16  v_nslices;              /* # of slices */
+               __le16  v_unknown1;             /* ? */
+               __le32  v_reserved[10];         /* reserved */
                struct unixware_slice
                        v_slice[UNIXWARE_NUMSLICE];     /* slice headers */
        } vtoc;
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
new file mode 100644 (file)
index 0000000..7e1aad3
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef LINUX_HARDIRQ_H
+#define LINUX_HARDIRQ_H
+
+#include <linux/config.h>
+#include <linux/smp_lock.h>
+#include <asm/hardirq.h>
+
+#define __IRQ_MASK(x)  ((1UL << (x))-1)
+
+#define PREEMPT_MASK   (__IRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
+#define HARDIRQ_MASK   (__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
+#define SOFTIRQ_MASK   (__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
+
+#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
+#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
+#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
+
+#define hardirq_count()        (preempt_count() & HARDIRQ_MASK)
+#define softirq_count()        (preempt_count() & SOFTIRQ_MASK)
+#define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
+
+/*
+ * Are we doing bottom half or hardware interrupt processing?
+ * Are we in a softirq context? Interrupt context?
+ */
+#define in_irq()               (hardirq_count())
+#define in_softirq()           (softirq_count())
+#define in_interrupt()         (irq_count())
+
+#ifdef CONFIG_PREEMPT
+# define in_atomic()   ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
+# define preemptible() (preempt_count() == 0 && !irqs_disabled())
+# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
+#else
+# define in_atomic()   (preempt_count() != 0)
+# define preemptible() 0
+# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
+#endif
+
+#ifdef CONFIG_SMP
+extern void synchronize_irq(unsigned int irq);
+#else
+# define synchronize_irq(irq)  barrier()
+#endif
+
+#endif /* LINUX_HARDIRQ_H */
index 3d53bea..54ad63b 100644 (file)
@@ -449,9 +449,8 @@ enum {
 /* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x033n/0x033n */
 /* 0x330 is reserved - used to be HDIO_GETGEO_BIG */
 /* 0x331 is reserved - used to be HDIO_GETGEO_BIG_RAW */
-
-#define HDIO_SET_IDE_SCSI      0x0338
-#define HDIO_SET_SCSI_IDE      0x0339
+/* 0x338 is reserved - used to be HDIO_SET_IDE_SCSI */
+/* 0x339 is reserved - used to be HDIO_SET_SCSI_IDE */
 
 #define __NEW_HD_DRIVE_ID
 
index 75c1fa0..695423d 100644 (file)
@@ -128,10 +128,11 @@ struct hiddev_usage_ref {
 
 /* hiddev_usage_ref_multi is used for sending multiple bytes to a control.
  * It really manifests itself as setting the value of consecutive usages */
+#define HID_MAX_MULTI_USAGES 1024
 struct hiddev_usage_ref_multi {
        struct hiddev_usage_ref uref;
        __u32 num_values;
-       __s32 values[HID_MAX_USAGES];
+       __s32 values[HID_MAX_MULTI_USAGES];
 };
 
 /* FIELD_INDEX_NONE is returned in read() data from the kernel when flags
@@ -212,6 +213,11 @@ struct hiddev_usage_ref_multi {
  * In-kernel definitions.
  */
 
+struct hid_device;
+struct hid_usage;
+struct hid_field;
+struct hid_report;
+
 #ifdef CONFIG_USB_HIDDEV
 int hiddev_connect(struct hid_device *);
 void hiddev_disconnect(struct hid_device *);
index 811cac9..53ecac3 100644 (file)
@@ -44,8 +44,8 @@ extern void __bad_gid(void);
 #ifdef CONFIG_UID16
 
 /* prevent uid mod 65536 effect by returning a default value for high UIDs */
-#define high2lowuid(uid) ((uid) > 65535 ? (old_uid_t)overflowuid : (old_uid_t)(uid))
-#define high2lowgid(gid) ((gid) > 65535 ? (old_gid_t)overflowgid : (old_gid_t)(gid))
+#define high2lowuid(uid) ((uid) & ~0xFFFF ? (old_uid_t)overflowuid : (old_uid_t)(uid))
+#define high2lowgid(gid) ((gid) & ~0xFFFF ? (old_gid_t)overflowgid : (old_gid_t)(gid))
 /*
  * -1 is different in 16 bits than it is in 32 bits
  * these macros are used by chown(), setreuid(), ...,
@@ -89,8 +89,8 @@ extern int fs_overflowgid;
  * Since these macros are used in architectures that only need limited
  * 16-bit UID back compatibility, we won't use old_uid_t and old_gid_t
  */
-#define fs_high2lowuid(uid) ((uid) > 65535 ? (uid16_t)fs_overflowuid : (uid16_t)(uid))
-#define fs_high2lowgid(gid) ((gid) > 65535 ? (gid16_t)fs_overflowgid : (gid16_t)(gid))
+#define fs_high2lowuid(uid) ((uid) & ~0xFFFF ? (uid16_t)fs_overflowuid : (uid16_t)(uid))
+#define fs_high2lowgid(gid) ((gid) & ~0xFFFF ? (gid16_t)fs_overflowgid : (gid16_t)(gid))
 
 #define low_16_bits(x) ((x) & 0xFFFF)
 #define high_16_bits(x)        (((x) & 0xFFFF0000) >> 16)
index af4da7d..142de4a 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef        __HPET__
 #define        __HPET__ 1
 
+#include <linux/compiler.h>
+
 /*
  * Offsets into HPET Registers
  */
@@ -110,7 +112,7 @@ struct hpet_task {
 };
 
 struct hpet_data {
-       unsigned long hd_address;
+       void __iomem *hd_address;
        unsigned short hd_nirqs;
        unsigned short hd_flags;
        unsigned int hd_state;  /* timer allocated */
diff --git a/include/linux/i2c-algo-pca.h b/include/linux/i2c-algo-pca.h
new file mode 100644 (file)
index 0000000..941b786
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _LINUX_I2C_ALGO_PCA_H
+#define _LINUX_I2C_ALGO_PCA_H
+
+struct i2c_algo_pca_data {
+       int  (*get_own)                 (struct i2c_algo_pca_data *adap); /* Obtain own address */
+       int  (*get_clock)               (struct i2c_algo_pca_data *adap);
+       void (*write_byte)              (struct i2c_algo_pca_data *adap, int reg, int val);
+       int  (*read_byte)               (struct i2c_algo_pca_data *adap, int reg);
+       int  (*wait_for_interrupt)      (struct i2c_algo_pca_data *adap);
+};
+
+#define I2C_PCA_ADAP_MAX       16
+
+int i2c_pca_add_bus(struct i2c_adapter *);
+int i2c_pca_del_bus(struct i2c_adapter *);
+
+#endif /* _LINUX_I2C_ALGO_PCA_H */
index 86ed117..6242409 100644 (file)
     to avoid floating point in the kernel.
 */
 
+int i2c_which_vrm(void);
+
 #define DEFAULT_VRM    82
 
 static inline int vid_from_reg(int val, int vrm)
 {
        switch(vrm) {
-
+       case  0:
+               return 0;
        case 91:                /* VRM 9.1 */
        case 90:                /* VRM 9.0 */
                return(val == 0x1f ? 0 :
index 11f31f6..4037aaa 100644 (file)
@@ -59,6 +59,8 @@
 #define ETH_P_8021Q    0x8100          /* 802.1Q VLAN Extended Header  */
 #define ETH_P_IPX      0x8137          /* IPX over DIX                 */
 #define ETH_P_IPV6     0x86DD          /* IPv6 over bluebook           */
+#define ETH_P_WCCP     0x883E          /* Web-cache coordination protocol
+                                        * defined in draft-wilson-wrec-wccp-v2-00.txt */
 #define ETH_P_PPP_DISC 0x8863          /* PPPoE discovery messages     */
 #define ETH_P_PPP_SES  0x8864          /* PPPoE session messages       */
 #define ETH_P_MPLS_UC  0x8847          /* MPLS Unicast traffic         */
  *     This is an Ethernet frame header.
  */
  
-struct ethhdr 
-{
+struct ethhdr {
        unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
        unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
        unsigned short  h_proto;                /* packet type ID field */
 } __attribute__((packed));
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
+static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
+{
+       return (struct ethhdr *)skb->mac.raw;
+}
+#endif
+
 #endif /* _LINUX_IF_ETHER_H */
index 2217963..a912818 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Global definitions for the ANSI FDDI interface.
  *
- * Version:    @(#)if_fddi.h   1.0.1   09/16/96
+ * Version:    @(#)if_fddi.h   1.0.2   Sep 29 2004
  *
  * Author:     Lawrence V. Stefani, <stefani@lkg.dec.com>
  *
@@ -103,38 +103,12 @@ struct fddihdr
        } __attribute__ ((packed));
 
 /* Define FDDI statistics structure */
-struct fddi_statistics
-       {
-       __u32   rx_packets;                             /* total packets received */
-       __u32   tx_packets;                             /* total packets transmitted */
-       __u32   rx_bytes;                               /* total bytes received */
-       __u32   tx_bytes;                               /* total bytes transmitted */
-       __u32   rx_errors;                              /* bad packets received */
-       __u32   tx_errors;                              /* packet transmit problems     */
-       __u32   rx_dropped;                             /* no space in linux buffers */
-       __u32   tx_dropped;                             /* no space available in linux */
-       __u32   multicast;                              /* multicast packets received */
-       __u32   transmit_collision;             /* always 0 for FDDI */
+struct fddi_statistics {
+
+       /* Generic statistics. */
 
-       /* detailed rx_errors */
-       __u32   rx_length_errors;
-       __u32   rx_over_errors;         /* receiver ring buff overflow  */
-       __u32   rx_crc_errors;          /* recved pkt with crc error    */
-       __u32   rx_frame_errors;        /* recv'd frame alignment error */
-       __u32   rx_fifo_errors;         /* recv'r fifo overrun          */
-       __u32   rx_missed_errors;       /* receiver missed packet       */
+       struct net_device_stats gen;
 
-       /* detailed tx_errors */
-       __u32   tx_aborted_errors;
-       __u32   tx_carrier_errors;
-       __u32   tx_fifo_errors;
-       __u32   tx_heartbeat_errors;
-       __u32   tx_window_errors;
-       
-       /* for cslip etc */
-       __u32   rx_compressed;
-       __u32   tx_compressed;
-   
        /* Detailed FDDI statistics.  Adopted from RFC 1512 */
 
        __u8    smt_station_id[8];
index f7c97ee..4fd451f 100644 (file)
@@ -48,6 +48,15 @@ struct trh_hdr {
        __u16 rseg[8];                  /* routing registers */
 };
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
+static inline struct trh_hdr *tr_hdr(const struct sk_buff *skb)
+{
+       return (struct trh_hdr *)skb->mac.raw;
+}
+#endif
+
 /* This is an Token-Ring LLC structure */
 struct trllc {
        __u8  dsap;                     /* destination SAP */
index 420767f..29b6e10 100644 (file)
@@ -18,7 +18,6 @@
 /* externally defined structs */
 struct vlan_group;
 struct net_device;
-struct sk_buff;
 struct packet_type;
 struct vlan_collection;
 struct vlan_dev_info;
@@ -48,6 +47,13 @@ struct vlan_ethhdr {
    unsigned short      h_vlan_encapsulated_proto; /* packet type ID field (or len) */
 };
 
+#include <linux/skbuff.h>
+
+static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
+{
+       return (struct vlan_ethhdr *)skb->mac.raw;
+}
+
 struct vlan_hdr {
    unsigned short       h_vlan_TCI;                /* Encapsulates priority and VLAN ID */
    unsigned short       h_vlan_encapsulated_proto; /* packet type ID field (or len) */
@@ -152,7 +158,7 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb,
        skb->real_dev = skb->dev;
        skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK];
        if (skb->dev == NULL) {
-               kfree_skb(skb);
+               dev_kfree_skb_any(skb);
 
                /* Not NET_RX_DROP, this is not being dropped
                 * due to congestion.
@@ -180,7 +186,7 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb,
                 * This allows the VLAN to have a different MAC than the underlying
                 * device, and still route correctly.
                 */
-               if (!memcmp(skb->mac.ethernet->h_dest, skb->dev->dev_addr, ETH_ALEN))
+               if (!memcmp(eth_hdr(skb)->h_dest, skb->dev->dev_addr, ETH_ALEN))
                        skb->pkt_type = PACKET_HOST;
                break;
        };
index b7a30bb..43cb25e 100644 (file)
@@ -527,6 +527,8 @@ struct input_absinfo {
 #define MSC_SERIAL             0x00
 #define MSC_PULSELED           0x01
 #define MSC_GESTURE            0x02
+#define MSC_RAW                        0x03
+#define MSC_SCAN               0x04
 #define MSC_MAX                        0x07
 
 /*
index e5bff65..e1a6418 100644 (file)
@@ -3,6 +3,15 @@
 
 struct file;
 
+typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,
+                                       unsigned long, struct file *);
+
+struct ioctl_trans {
+       unsigned long cmd;
+       ioctl_trans_handler_t handler;
+       struct ioctl_trans *next;
+};
+
 /* 
  * Register an 32bit ioctl translation handler for ioctl cmd.
  *
@@ -13,16 +22,16 @@ struct file;
  *                        struct file *file: file descriptor pointer.
  */ 
 
-extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *));
-
+#ifdef CONFIG_COMPAT
+extern int register_ioctl32_conversion(unsigned int cmd,
+                               ioctl_trans_handler_t handler);
 extern int unregister_ioctl32_conversion(unsigned int cmd);
 
-typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int, unsigned long, struct file *);
+#else
 
-struct ioctl_trans {
-       unsigned long cmd;
-       ioctl_trans_handler_t handler;
-       struct ioctl_trans *next;
-};
+#define register_ioctl32_conversion(cmd, handler)      ({ 0; })
+#define unregister_ioctl32_conversion(cmd)             ({ 0; })
+
+#endif
 
 #endif
index 85805a7..5c23aeb 100644 (file)
@@ -16,6 +16,8 @@
 #define IP6_TNL_F_USE_ORIG_FLOWLABEL 0x4
 /* being used for Mobile IPv6 */
 #define IP6_TNL_F_MIP6_DEV 0x8
+/* copy DSCP from the outer packet */
+#define IP6_TNL_F_RCV_DSCP_COPY 0x10
 
 struct ip6_tnl_parm {
        char name[IFNAMSIZ];    /* name of tunnel device */
index ccc084d..d7d1673 100644 (file)
@@ -182,8 +182,7 @@ enum {
    as offsets from skb->nh.
  */
 
-struct inet6_skb_parm
-{
+struct inet6_skb_parm {
        int                     iif;
        __u16                   ra;
        __u16                   hop;
@@ -194,6 +193,14 @@ struct inet6_skb_parm
 
 #define IP6CB(skb)     ((struct inet6_skb_parm*)((skb)->cb))
 
+/**
+ * struct ipv6_pinfo - ipv6 private area
+ *
+ * In the struct sock hierarchy (tcp6_sock, upd6_sock, etc)
+ * this _must_ be the last member, so that inet6_sk_generic
+ * is able to calculate its offset from the base struct sock
+ * by using the struct proto->slab_obj_size member. -acme
+ */
 struct ipv6_pinfo {
        struct in6_addr         saddr;
        struct in6_addr         rcv_saddr;
index a5a3eea..f997463 100644 (file)
@@ -102,7 +102,6 @@ typedef     struct  {
 #define ClearInterrupt(base) (inw((base)+0x0a))        
 
 #define        BOARD(line)  (((line) >> 4) & 0x3)
-#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
 
        /*      isi kill queue bitmap   */
        
index a484f52..588f4c6 100644 (file)
@@ -35,6 +35,7 @@ static inline int request_module(const char * name, ...) { return -ENOSYS; }
 
 #define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
 extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait);
+extern void usermodehelper_init(void);
 
 #ifdef CONFIG_HOTPLUG
 extern char hotplug_path [];
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
new file mode 100644 (file)
index 0000000..172b7f4
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef _LINUX_KPROBES_H
+#define _LINUX_KPROBES_H
+/*
+ *  Kernel Probes (KProbes)
+ *  include/linux/kprobes.h
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ *
+ * 2002-Oct    Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
+ *             Probes initial implementation ( includes suggestions from
+ *             Rusty Russell).
+ * 2004-July   Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
+ *             interface to access function arguments.
+ */
+#include <linux/config.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/smp.h>
+#include <asm/kprobes.h>
+
+struct kprobe;
+struct pt_regs;
+typedef int (*kprobe_pre_handler_t) (struct kprobe *, struct pt_regs *);
+typedef int (*kprobe_break_handler_t) (struct kprobe *, struct pt_regs *);
+typedef void (*kprobe_post_handler_t) (struct kprobe *, struct pt_regs *,
+                                      unsigned long flags);
+typedef int (*kprobe_fault_handler_t) (struct kprobe *, struct pt_regs *,
+                                      int trapnr);
+struct kprobe {
+       struct hlist_node hlist;
+
+       /* location of the probe point */
+       kprobe_opcode_t *addr;
+
+       /* Called before addr is executed. */
+       kprobe_pre_handler_t pre_handler;
+
+       /* Called after addr is executed, unless... */
+       kprobe_post_handler_t post_handler;
+
+       /* ... called if executing addr causes a fault (eg. page fault).
+        * Return 1 if it handled fault, otherwise kernel will see it. */
+       kprobe_fault_handler_t fault_handler;
+
+       /* ... called if breakpoint trap occurs in probe handler.
+        * Return 1 if it handled break, otherwise kernel will see it. */
+       kprobe_break_handler_t break_handler;
+
+       /* Saved opcode (which has been replaced with breakpoint) */
+       kprobe_opcode_t opcode;
+
+       /* copy of the original instruction */
+       kprobe_opcode_t insn[MAX_INSN_SIZE];
+};
+
+/*
+ * Special probe type that uses setjmp-longjmp type tricks to resume
+ * execution at a specified entry with a matching prototype corresponding
+ * to the probed function - a trick to enable arguments to become
+ * accessible seamlessly by probe handling logic.
+ * Note:
+ * Because of the way compilers allocate stack space for local variables
+ * etc upfront, regardless of sub-scopes within a function, this mirroring
+ * principle currently works only for probes placed on function entry points.
+ */
+struct jprobe {
+       struct kprobe kp;
+       kprobe_opcode_t *entry; /* probe handling code to jump to */
+};
+
+#ifdef CONFIG_KPROBES
+/* Locks kprobe: irq must be disabled */
+void lock_kprobes(void);
+void unlock_kprobes(void);
+
+/* kprobe running now on this CPU? */
+static inline int kprobe_running(void)
+{
+       extern unsigned int kprobe_cpu;
+       return kprobe_cpu == smp_processor_id();
+}
+
+extern void arch_prepare_kprobe(struct kprobe *p);
+extern void show_registers(struct pt_regs *regs);
+
+/* Get the kprobe at this addr (if any).  Must have called lock_kprobes */
+struct kprobe *get_kprobe(void *addr);
+
+int register_kprobe(struct kprobe *p);
+void unregister_kprobe(struct kprobe *p);
+int setjmp_pre_handler(struct kprobe *, struct pt_regs *);
+int longjmp_break_handler(struct kprobe *, struct pt_regs *);
+int register_jprobe(struct jprobe *p);
+void unregister_jprobe(struct jprobe *p);
+void jprobe_return(void);
+
+#else
+static inline int kprobe_running(void)
+{
+       return 0;
+}
+static inline int register_kprobe(struct kprobe *p)
+{
+       return -ENOSYS;
+}
+static inline void unregister_kprobe(struct kprobe *p)
+{
+}
+static inline int register_jprobe(struct jprobe *p)
+{
+       return -ENOSYS;
+}
+static inline void unregister_jprobe(struct jprobe *p)
+{
+}
+static inline void jprobe_return(void)
+{
+}
+#endif
+#endif                         /* _LINUX_KPROBES_H */
index 82284b7..ea59487 100644 (file)
  *
  */
 
-#if defined(__KERNEL__) && !defined(_KREF_H_)
+#ifndef _KREF_H_
 #define _KREF_H_
 
+#ifdef __KERNEL__
+
 #include <linux/types.h>
 #include <asm/atomic.h>
 
-
 struct kref {
        atomic_t refcount;
-       void (*release)(struct kref *kref);
 };
 
-void kref_init(struct kref *kref, void (*release)(struct kref *));
-struct kref *kref_get(struct kref *kref);
-void kref_put(struct kref *kref);
-
+void kref_init(struct kref *kref);
+void kref_get(struct kref *kref);
+void kref_put(struct kref *kref, void (*release) (struct kref *kref));
 
+#endif /* __KERNEL__ */
 #endif /* _KREF_H_ */
index 09955c0..338f779 100644 (file)
 #define asmlinkage CPP_ASMLINKAGE
 #endif
 
+#ifndef prevent_tail_call
+# define prevent_tail_call(ret) do { } while (0)
+#endif
+
 #ifndef __ALIGN
 #define __ALIGN                .align 4,0x90
 #define __ALIGN_STR    ".align 4,0x90"
index 33b863b..94bed0f 100644 (file)
@@ -195,6 +195,21 @@ static inline void list_del_rcu(struct list_head *entry)
        entry->prev = LIST_POISON2;
 }
 
+/*
+ * list_replace_rcu - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * The old entry will be replaced with the new entry atomically.
+ */
+static inline void list_replace_rcu(struct list_head *old, struct list_head *new){
+       new->next = old->next;
+       new->prev = old->prev;
+       smp_wmb();
+       new->next->prev = new;
+       new->prev->next = new;
+}
+
 /**
  * list_del_init - deletes entry from list and reinitialize it.
  * @entry: the element to delete from the list.
@@ -420,11 +435,11 @@ static inline void list_splice_init(struct list_head *list,
  */
 #define list_for_each_rcu(pos, head) \
        for (pos = (head)->next, prefetch(pos->next); pos != (head); \
-               pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
+               pos = rcu_dereference(pos->next), prefetch(pos->next))
 
 #define __list_for_each_rcu(pos, head) \
        for (pos = (head)->next; pos != (head); \
-               pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
+               pos = rcu_dereference(pos->next))
 
 /**
  * list_for_each_safe_rcu      -       iterate over an rcu-protected list safe
@@ -439,7 +454,7 @@ static inline void list_splice_init(struct list_head *list,
  */
 #define list_for_each_safe_rcu(pos, n, head) \
        for (pos = (head)->next, n = pos->next; pos != (head); \
-               pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
+               pos = rcu_dereference(n), n = pos->next)
 
 /**
  * list_for_each_entry_rcu     -       iterate over rcu list of given type
@@ -455,8 +470,8 @@ static inline void list_splice_init(struct list_head *list,
        for (pos = list_entry((head)->next, typeof(*pos), member),      \
                     prefetch(pos->member.next);                        \
             &pos->member != (head);                                    \
-            pos = list_entry(pos->member.next, typeof(*pos), member),  \
-                    ({ smp_read_barrier_depends(); 0;}),               \
+            pos = rcu_dereference(list_entry(pos->member.next,         \
+                                       typeof(*pos), member)),         \
                     prefetch(pos->member.next))
 
 
@@ -472,7 +487,7 @@ static inline void list_splice_init(struct list_head *list,
  */
 #define list_for_each_continue_rcu(pos, head) \
        for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
-               (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
+               (pos) = rcu_dereference((pos)->next), prefetch((pos)->next))
 
 /*
  * Double linked lists with a single pointer list head.
@@ -578,12 +593,9 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
  * or hlist_del_rcu(), running on this same list.
  * However, it is perfectly legal to run concurrently with
  * the _rcu list-traversal primitives, such as
- * hlist_for_each_entry(), but only if smp_read_barrier_depends()
- * is used to prevent memory-consistency problems on Alpha CPUs.
- * Regardless of the type of CPU, the list-traversal primitive
- * must be guarded by rcu_read_lock().
- *
- * OK, so why don't we have an hlist_for_each_entry_rcu()???
+ * hlist_for_each_rcu(), used to prevent memory-consistency
+ * problems on Alpha CPUs.  Regardless of the type of CPU, the
+ * list-traversal primitive must be guarded by rcu_read_lock().
  */
 static inline void hlist_add_head_rcu(struct hlist_node *n,
                                        struct hlist_head *h)
@@ -628,6 +640,10 @@ static inline void hlist_add_after(struct hlist_node *n,
        for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
             pos = n)
 
+#define hlist_for_each_rcu(pos, head) \
+       for ((pos) = (head)->first; pos && ({ prefetch((pos)->next); 1; }); \
+               (pos) = rcu_dereference((pos)->next))
+
 /**
  * hlist_for_each_entry        - iterate over list of given type
  * @tpos:      the type * to use as a loop counter.
@@ -693,7 +709,7 @@ static inline void hlist_add_after(struct hlist_node *n,
        for (pos = (head)->first;                                        \
             pos && ({ prefetch(pos->next); 1;}) &&                      \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
-            pos = pos->next, ({ smp_read_barrier_depends(); 0; }) )
+            pos = rcu_dereference(pos->next))
 
 #else
 #warning "don't include kernel headers in userspace"
index 2a03cf1..b054deb 100644 (file)
@@ -20,7 +20,7 @@ struct svc_rqst;
 struct nlmsvc_binding {
        u32                     (*fopen)(struct svc_rqst *,
                                                struct nfs_fh *,
-                                               struct file *);
+                                               struct file **);
        void                    (*fclose)(struct file *);
 };
 
index e0db6e1..5a173a6 100644 (file)
@@ -52,10 +52,25 @@ struct nlm_host {
        wait_queue_head_t       h_gracewait;    /* wait while reclaiming */
        u32                     h_state;        /* pseudo-state counter */
        u32                     h_nsmstate;     /* true remote NSM state */
-       unsigned int            h_count;        /* reference count */
+       u32                     h_pidcount;     /* Pseudopids */
+       atomic_t                h_count;        /* reference count */
        struct semaphore        h_sema;         /* mutex for pmap binding */
        unsigned long           h_nextrebind;   /* next portmap call */
        unsigned long           h_expires;      /* eligible for GC */
+       struct list_head        h_lockowners;   /* Lockowners for the client */
+       spinlock_t              h_lock;
+};
+
+/*
+ * Map an fl_owner_t into a unique 32-bit "pid"
+ */
+struct nlm_lockowner {
+       struct list_head list;
+       atomic_t count;
+
+       struct nlm_host *host;
+       fl_owner_t owner;
+       uint32_t pid;
 };
 
 /*
@@ -77,7 +92,7 @@ struct nlm_rqst {
 struct nlm_file {
        struct nlm_file *       f_next;         /* linked list */
        struct nfs_fh           f_handle;       /* NFS file handle */
-       struct file             f_file;         /* VFS file pointer */
+       struct file *           f_file;         /* VFS file pointer */
        struct nlm_share *      f_shares;       /* DOS shares */
        struct nlm_block *      f_blocks;       /* blocked locks */
        unsigned int            f_locks;        /* guesstimate # of locks */
@@ -180,7 +195,7 @@ void                  nlmsvc_invalidate_all(void);
 static __inline__ struct inode *
 nlmsvc_file_inode(struct nlm_file *file)
 {
-       return file->f_file.f_dentry->d_inode;
+       return file->f_file->f_dentry->d_inode;
 }
 
 /*
@@ -205,6 +220,8 @@ nlm_compare_locks(struct file_lock *fl1, struct file_lock *fl2)
             &&(fl1->fl_type  == fl2->fl_type || fl2->fl_type == F_UNLCK);
 }
 
+extern struct lock_manager_operations nlmsvc_lock_operations;
+
 #endif /* __KERNEL__ */
 
 #endif /* LINUX_LOCKD_LOCKD_H */
index 775c415..9835ac2 100644 (file)
@@ -68,9 +68,6 @@ struct mempolicy {
        } v;
 };
 
-/* An NULL mempolicy pointer is a synonym of &default_policy. */
-extern struct mempolicy default_policy;
-
 /*
  * Support for managing mempolicy data objects (clone, copy, destroy)
  * The default fast path of a NULL MPOL_DEFAULT policy is always inlined.
index c87b17f..c674b2e 100644 (file)
@@ -33,7 +33,8 @@
 #define MII_NCONFIG         0x1c        /* Network interface config    */
 
 /* Basic mode control register. */
-#define BMCR_RESV               0x007f  /* Unused...                   */
+#define BMCR_RESV               0x003f  /* Unused...                   */
+#define BMCR_SPEED1000         0x0040  /* MSB of Speed (1000)         */
 #define BMCR_CTST               0x0080  /* Collision test              */
 #define BMCR_FULLDPLX           0x0100  /* Full duplex                 */
 #define BMCR_ANRESTART          0x0200  /* Auto negotiation restart    */
index 07da84f..18a5689 100644 (file)
@@ -10,6 +10,9 @@
 #define MREMAP_MAYMOVE 1
 #define MREMAP_FIXED   2
 
+#define OVERCOMMIT_GUESS               0
+#define OVERCOMMIT_ALWAYS              1
+#define OVERCOMMIT_NEVER               2
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern atomic_t vm_committed_space;
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
new file mode 100644 (file)
index 0000000..44da5ac
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *  linux/include/linux/mmc/card.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.
+ *
+ *  Card driver specific definitions.
+ */
+#ifndef LINUX_MMC_CARD_H
+#define LINUX_MMC_CARD_H
+
+#include <linux/mmc/mmc.h>
+
+struct mmc_cid {
+       unsigned int            manfid;
+       char                    prod_name[8];
+       unsigned int            serial;
+       unsigned short          oemid;
+       unsigned short          year;
+       unsigned char           hwrev;
+       unsigned char           fwrev;
+       unsigned char           month;
+};
+
+struct mmc_csd {
+       unsigned char           mmca_vsn;
+       unsigned short          cmdclass;
+       unsigned short          tacc_clks;
+       unsigned int            tacc_ns;
+       unsigned int            max_dtr;
+       unsigned int            read_blkbits;
+       unsigned int            capacity;
+};
+
+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            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 */
+       u32                     raw_cid[4];     /* raw card CID */
+       u32                     raw_csd[4];     /* raw card CSD */
+       struct mmc_cid          cid;            /* card identification */
+       struct mmc_csd          csd;            /* card specific */
+};
+
+#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_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_name(c)       ((c)->cid.prod_name)
+#define mmc_card_id(c)         ((c)->dev.bus_id)
+
+#define mmc_list_to_card(l)    container_of(l, struct mmc_card, node)
+#define mmc_get_drvdata(c)     dev_get_drvdata(&(c)->dev)
+#define mmc_set_drvdata(c,d)   dev_set_drvdata(&(c)->dev, d)
+
+/*
+ * MMC device driver (e.g., Flash card, I/O card...)
+ */
+struct mmc_driver {
+       struct device_driver drv;
+       int (*probe)(struct mmc_card *);
+       void (*remove)(struct mmc_card *);
+       int (*suspend)(struct mmc_card *, u32);
+       int (*resume)(struct mmc_card *);
+};
+
+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/host.h b/include/linux/mmc/host.h
new file mode 100644 (file)
index 0000000..f67686c
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *  linux/include/linux/mmc/host.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.
+ *
+ *  Host driver specific definitions.
+ */
+#ifndef LINUX_MMC_HOST_H
+#define LINUX_MMC_HOST_H
+
+#include <linux/mmc/mmc.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
+
+       unsigned char   bus_mode;               /* command output mode */
+
+#define MMC_BUSMODE_OPENDRAIN  1
+#define MMC_BUSMODE_PUSHPULL   2
+
+       unsigned char   power_mode;             /* power supply mode */
+
+#define MMC_POWER_OFF          0
+#define MMC_POWER_UP           1
+#define MMC_POWER_ON           2
+};
+
+struct mmc_host_ops {
+       void    (*request)(struct mmc_host *host, struct mmc_request *req);
+       void    (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
+};
+
+struct mmc_card;
+struct device;
+
+struct mmc_host {
+       struct device           *dev;
+       struct mmc_host_ops     *ops;
+       unsigned int            f_min;
+       unsigned int            f_max;
+       u32                     ocr_avail;
+       char                    host_name[8];
+
+       /* host specific block data */
+       unsigned int            max_seg_size;   /* see blk_queue_max_segment_size */
+       unsigned short          max_hw_segs;    /* see blk_queue_max_hw_segments */
+       unsigned short          max_phys_segs;  /* see blk_queue_max_phys_segments */
+       unsigned short          max_sectors;    /* see blk_queue_max_sectors */
+       unsigned short          unused;
+
+       /* private data */
+       struct mmc_ios          ios;            /* current io bus settings */
+       u32                     ocr;            /* the current OCR setting */
+
+       struct list_head        cards;          /* devices attached to this host */
+
+       wait_queue_head_t       wq;
+       spinlock_t              lock;           /* card_busy lock */
+       struct mmc_card         *card_busy;     /* the MMC card claiming host */
+       struct mmc_card         *card_selected; /* the selected MMC card */
+
+       struct work_struct      detect;
+};
+
+extern struct mmc_host *mmc_alloc_host(int extra, struct device *);
+extern int mmc_add_host(struct mmc_host *);
+extern void mmc_remove_host(struct mmc_host *);
+extern void mmc_free_host(struct mmc_host *);
+
+#define mmc_priv(x)    ((void *)((x) + 1))
+#define mmc_dev(x)     ((x)->dev)
+
+extern int mmc_suspend_host(struct mmc_host *, u32);
+extern int mmc_resume_host(struct mmc_host *);
+
+extern void mmc_detect_change(struct mmc_host *);
+extern void mmc_request_done(struct mmc_host *, struct mmc_request *);
+
+#endif
+
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
new file mode 100644 (file)
index 0000000..c288ae6
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  linux/include/linux/mmc/mmc.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 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_NONE   (0 << 0)
+#define MMC_RSP_SHORT  (1 << 0)
+#define MMC_RSP_LONG   (2 << 0)
+#define MMC_RSP_MASK   (3 << 0)
+#define MMC_RSP_CRC    (1 << 3)                /* expect valid crc */
+#define MMC_RSP_BUSY   (1 << 4)                /* card may send busy */
+
+/*
+ * 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_R1     (MMC_RSP_SHORT|MMC_RSP_CRC)
+#define MMC_RSP_R1B    (MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_BUSY)
+#define MMC_RSP_R2     (MMC_RSP_LONG|MMC_RSP_CRC)
+#define MMC_RSP_R3     (MMC_RSP_SHORT)
+
+       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;           /* assoicated 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_bits;     /* data block size */
+       unsigned int            blocks;         /* number of blocks */
+       struct request          *req;           /* request structure */
+       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)
+
+       unsigned int            bytes_xfered;
+
+       struct mmc_command      *stop;          /* stop command */
+       struct mmc_request      *mrq;           /* assoicated request */
+};
+
+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_claim_host(struct mmc_host *host, struct mmc_card *card);
+
+static inline void mmc_claim_host(struct mmc_host *host)
+{
+       __mmc_claim_host(host, (struct mmc_card *)-1);
+}
+
+extern void mmc_release_host(struct mmc_host *host);
+
+#endif
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
new file mode 100644 (file)
index 0000000..5b79ed4
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * 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 (3.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_SELECT_CARD           7   /* ac   [31:16] RCA        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                37   /* 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          R1b */
+
+/*
+  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 << 7)        /* 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 */
+
+
+/*
+ * 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       */
+
+#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 */
+
+#endif  /* MMC_MMC_PROTOCOL_H */
+
diff --git a/include/linux/mmtimer.h b/include/linux/mmtimer.h
new file mode 100644 (file)
index 0000000..884cabf
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Intel Multimedia Timer device interface
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2001-2004 Silicon Graphics, Inc.  All rights reserved.
+ *
+ * This file should define an interface compatible with the IA-PC Multimedia
+ * Timers Draft Specification (rev. 0.97) from Intel.  Note that some
+ * hardware may not be able to safely export its registers to userspace,
+ * so the ioctl interface should support all necessary functionality.
+ *
+ * 11/01/01 - jbarnes - initial revision
+ * 9/10/04 - Christoph Lameter - remove interrupt support
+ * 9/17/04 - jbarnes - remove test program, move some #defines to the driver
+ */
+
+#ifndef _LINUX_MMTIMER_H
+#define _LINUX_MMTIMER_H
+
+/*
+ * Breakdown of the ioctl's available.  An 'optional' next to the command
+ * indicates that supporting this command is optional, while 'required'
+ * commands must be implemented if conformance is desired.
+ *
+ * MMTIMER_GETOFFSET - optional
+ *   Should return the offset (relative to the start of the page where the
+ *   registers are mapped) for the counter in question.
+ *
+ * MMTIMER_GETRES - required
+ *   The resolution of the clock in femto (10^-15) seconds
+ *
+ * MMTIMER_GETFREQ - required
+ *   Frequency of the clock in Hz
+ *
+ * MMTIMER_GETBITS - required
+ *   Number of bits in the clock's counter
+ *
+ * MMTIMER_MMAPAVAIL - required
+ *   Returns nonzero if the registers can be mmap'd into userspace, 0 otherwise
+ *
+ * MMTIMER_GETCOUNTER - required
+ *   Gets the current value in the counter
+ */
+#define MMTIMER_IOCTL_BASE 'm'
+
+#define MMTIMER_GETOFFSET _IO(MMTIMER_IOCTL_BASE, 0)
+#define MMTIMER_GETRES _IOR(MMTIMER_IOCTL_BASE, 1, unsigned long)
+#define MMTIMER_GETFREQ _IOR(MMTIMER_IOCTL_BASE, 2, unsigned long)
+#define MMTIMER_GETBITS _IO(MMTIMER_IOCTL_BASE, 4)
+#define MMTIMER_MMAPAVAIL _IO(MMTIMER_IOCTL_BASE, 6)
+#define MMTIMER_GETCOUNTER _IOR(MMTIMER_IOCTL_BASE, 9, unsigned long)
+
+#endif /* _LINUX_MMTIMER_H */
index d8916f9..d35fe74 100644 (file)
@@ -123,34 +123,34 @@ struct fat_boot_sector {
                                   partition manager volumes */
        __u8    sector_size[2]; /* bytes per logical sector */
        __u8    sec_per_clus;   /* sectors/cluster */
-       __u16   reserved;       /* reserved sectors */
+       __le16  reserved;       /* reserved sectors */
        __u8    fats;           /* number of FATs */
        __u8    dir_entries[2]; /* root directory entries */
        __u8    sectors[2];     /* number of sectors */
        __u8    media;          /* media code */
-       __u16   fat_length;     /* sectors/FAT */
-       __u16   secs_track;     /* sectors per track */
-       __u16   heads;          /* number of heads */
-       __u32   hidden;         /* hidden sectors (unused) */
-       __u32   total_sect;     /* number of sectors (if sectors == 0) */
+       __le16  fat_length;     /* sectors/FAT */
+       __le16  secs_track;     /* sectors per track */
+       __le16  heads;          /* number of heads */
+       __le32  hidden;         /* hidden sectors (unused) */
+       __le32  total_sect;     /* number of sectors (if sectors == 0) */
 
        /* The following fields are only used by FAT32 */
-       __u32   fat32_length;   /* sectors/FAT */
-       __u16   flags;          /* bit 8: fat mirroring, low 4: active fat */
+       __le32  fat32_length;   /* sectors/FAT */
+       __le16  flags;          /* bit 8: fat mirroring, low 4: active fat */
        __u8    version[2];     /* major, minor filesystem version */
-       __u32   root_cluster;   /* first cluster in root directory */
-       __u16   info_sector;    /* filesystem info sector */
-       __u16   backup_boot;    /* backup boot sector */
-       __u16   reserved2[6];   /* Unused */
+       __le32  root_cluster;   /* first cluster in root directory */
+       __le16  info_sector;    /* filesystem info sector */
+       __le16  backup_boot;    /* backup boot sector */
+       __le16  reserved2[6];   /* Unused */
 };
 
 struct fat_boot_fsinfo {
-       __u32   signature1;     /* 0x41615252L */
-       __u32   reserved1[120]; /* Nothing as far as I can tell */
-       __u32   signature2;     /* 0x61417272L */
-       __u32   free_clusters;  /* Free cluster count.  -1 if unknown */
-       __u32   next_cluster;   /* Most recently allocated cluster */
-       __u32   reserved2[4];
+       __le32   signature1;    /* 0x41615252L */
+       __le32   reserved1[120];        /* Nothing as far as I can tell */
+       __le32   signature2;    /* 0x61417272L */
+       __le32   free_clusters; /* Free cluster count.  -1 if unknown */
+       __le32   next_cluster;  /* Most recently allocated cluster */
+       __le32   reserved2[4];
 };
 
 struct msdos_dir_entry {
@@ -158,12 +158,12 @@ struct msdos_dir_entry {
        __u8    attr;           /* attribute bits */
        __u8    lcase;          /* Case for base and extension */
        __u8    ctime_ms;       /* Creation time, milliseconds */
-       __u16   ctime;          /* Creation time */
-       __u16   cdate;          /* Creation date */
-       __u16   adate;          /* Last access date */
-       __u16   starthi;        /* High 16 bits of cluster in FAT32 */
-       __u16   time,date,start;/* time, date and first cluster */
-       __u32   size;           /* file size (in bytes) */
+       __le16  ctime;          /* Creation time */
+       __le16  cdate;          /* Creation date */
+       __le16  adate;          /* Last access date */
+       __le16   starthi;       /* High 16 bits of cluster in FAT32 */
+       __le16  time,date,start;/* time, date and first cluster */
+       __le32  size;           /* file size (in bytes) */
 };
 
 /* Up to 13 characters of the name */
@@ -174,7 +174,7 @@ struct msdos_dir_slot {
        __u8    reserved;       /* always 0 */
        __u8    alias_checksum; /* checksum for 8.3 alias */
        __u8    name5_10[12];   /* 6 more characters in name */
-       __u16   start;          /* starting cluster number, 0 in long slots */
+       __le16   start;         /* starting cluster number, 0 in long slots */
        __u8    name11_12[4];   /* last 2 characters in name */
 };
 
@@ -233,8 +233,6 @@ extern int fat_access(struct super_block *sb, int nr, int new_value);
 extern int __fat_access(struct super_block *sb, int nr, int new_value);
 extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys);
 extern void fat_cache_init(struct super_block *sb);
-extern void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu,
-                            int *d_clu);
 extern void fat_cache_add(struct inode *inode, int f_clu, int d_clu);
 extern void fat_cache_inval_inode(struct inode *inode);
 extern int fat_get_cluster(struct inode *inode, int cluster,
@@ -278,7 +276,7 @@ extern void fat_put_super(struct super_block *sb);
 int fat_fill_super(struct super_block *sb, void *data, int silent,
                   struct inode_operations *fs_dir_inode_ops, int isvfat);
 extern int fat_statfs(struct super_block *sb, struct kstatfs *buf);
-extern void fat_write_inode(struct inode *inode, int wait);
+extern int fat_write_inode(struct inode *inode, int wait);
 extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
 
 /* fat/misc.c */
@@ -289,8 +287,7 @@ extern void fat_clusters_flush(struct super_block *sb);
 extern int fat_add_cluster(struct inode *inode);
 extern struct buffer_head *fat_extend_dir(struct inode *inode);
 extern int date_dos2unix(unsigned short time, unsigned short date);
-extern void fat_date_unix2dos(int unix_date, unsigned short *time,
-                             unsigned short *date);
+extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
 extern int fat__get_entry(struct inode *dir, loff_t *pos,
                          struct buffer_head **bh,
                          struct msdos_dir_entry **de, loff_t *i_pos);
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
new file mode 100644 (file)
index 0000000..a889dd9
--- /dev/null
@@ -0,0 +1,1039 @@
+/*
+ * mv64340.h - MV-64340 Internal registers definition file.
+ *
+ * Copyright 2002 Momentum Computer, Inc.
+ *     Author: Matthew Dharm <mdharm@momenco.com>
+ * Copyright 2002 GALILEO TECHNOLOGY, LTD. 
+ *
+ * This program is free software; you can redistribute  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 __ASM_MV64340_H
+#define __ASM_MV64340_H
+
+#include <asm/addrspace.h>
+#include <asm/marvell.h>
+
+/****************************************/
+/* Processor Address Space              */
+/****************************************/
+
+/* DDR SDRAM BAR and size registers */
+
+#define MV64340_CS_0_BASE_ADDR                                      0x008
+#define MV64340_CS_0_SIZE                                           0x010
+#define MV64340_CS_1_BASE_ADDR                                      0x208
+#define MV64340_CS_1_SIZE                                           0x210
+#define MV64340_CS_2_BASE_ADDR                                      0x018
+#define MV64340_CS_2_SIZE                                           0x020
+#define MV64340_CS_3_BASE_ADDR                                      0x218
+#define MV64340_CS_3_SIZE                                           0x220
+
+/* Devices BAR and size registers */
+
+#define MV64340_DEV_CS0_BASE_ADDR                                   0x028
+#define MV64340_DEV_CS0_SIZE                                        0x030
+#define MV64340_DEV_CS1_BASE_ADDR                                   0x228
+#define MV64340_DEV_CS1_SIZE                                        0x230
+#define MV64340_DEV_CS2_BASE_ADDR                                   0x248
+#define MV64340_DEV_CS2_SIZE                                        0x250
+#define MV64340_DEV_CS3_BASE_ADDR                                   0x038
+#define MV64340_DEV_CS3_SIZE                                        0x040
+#define MV64340_BOOTCS_BASE_ADDR                                    0x238
+#define MV64340_BOOTCS_SIZE                                         0x240
+
+/* PCI 0 BAR and size registers */
+
+#define MV64340_PCI_0_IO_BASE_ADDR                                  0x048
+#define MV64340_PCI_0_IO_SIZE                                       0x050
+#define MV64340_PCI_0_MEMORY0_BASE_ADDR                             0x058
+#define MV64340_PCI_0_MEMORY0_SIZE                                  0x060
+#define MV64340_PCI_0_MEMORY1_BASE_ADDR                             0x080
+#define MV64340_PCI_0_MEMORY1_SIZE                                  0x088
+#define MV64340_PCI_0_MEMORY2_BASE_ADDR                             0x258
+#define MV64340_PCI_0_MEMORY2_SIZE                                  0x260
+#define MV64340_PCI_0_MEMORY3_BASE_ADDR                             0x280
+#define MV64340_PCI_0_MEMORY3_SIZE                                  0x288
+
+/* PCI 1 BAR and size registers */
+#define MV64340_PCI_1_IO_BASE_ADDR                                  0x090
+#define MV64340_PCI_1_IO_SIZE                                       0x098
+#define MV64340_PCI_1_MEMORY0_BASE_ADDR                             0x0a0
+#define MV64340_PCI_1_MEMORY0_SIZE                                  0x0a8
+#define MV64340_PCI_1_MEMORY1_BASE_ADDR                             0x0b0
+#define MV64340_PCI_1_MEMORY1_SIZE                                  0x0b8
+#define MV64340_PCI_1_MEMORY2_BASE_ADDR                             0x2a0
+#define MV64340_PCI_1_MEMORY2_SIZE                                  0x2a8
+#define MV64340_PCI_1_MEMORY3_BASE_ADDR                             0x2b0
+#define MV64340_PCI_1_MEMORY3_SIZE                                  0x2b8
+
+/* SRAM base address */
+#define MV64340_INTEGRATED_SRAM_BASE_ADDR                           0x268
+
+/* internal registers space base address */
+#define MV64340_INTERNAL_SPACE_BASE_ADDR                            0x068
+
+/* Enables the CS , DEV_CS , PCI 0 and PCI 1 
+   windows above */
+#define MV64340_BASE_ADDR_ENABLE                                    0x278
+
+/****************************************/
+/* PCI remap registers                  */
+/****************************************/
+      /* PCI 0 */
+#define MV64340_PCI_0_IO_ADDR_REMAP                                 0x0f0
+#define MV64340_PCI_0_MEMORY0_LOW_ADDR_REMAP                        0x0f8
+#define MV64340_PCI_0_MEMORY0_HIGH_ADDR_REMAP                       0x320
+#define MV64340_PCI_0_MEMORY1_LOW_ADDR_REMAP                        0x100
+#define MV64340_PCI_0_MEMORY1_HIGH_ADDR_REMAP                       0x328
+#define MV64340_PCI_0_MEMORY2_LOW_ADDR_REMAP                        0x2f8
+#define MV64340_PCI_0_MEMORY2_HIGH_ADDR_REMAP                       0x330
+#define MV64340_PCI_0_MEMORY3_LOW_ADDR_REMAP                        0x300
+#define MV64340_PCI_0_MEMORY3_HIGH_ADDR_REMAP                       0x338
+      /* PCI 1 */
+#define MV64340_PCI_1_IO_ADDR_REMAP                                 0x108
+#define MV64340_PCI_1_MEMORY0_LOW_ADDR_REMAP                        0x110
+#define MV64340_PCI_1_MEMORY0_HIGH_ADDR_REMAP                       0x340
+#define MV64340_PCI_1_MEMORY1_LOW_ADDR_REMAP                        0x118
+#define MV64340_PCI_1_MEMORY1_HIGH_ADDR_REMAP                       0x348
+#define MV64340_PCI_1_MEMORY2_LOW_ADDR_REMAP                        0x310
+#define MV64340_PCI_1_MEMORY2_HIGH_ADDR_REMAP                       0x350
+#define MV64340_PCI_1_MEMORY3_LOW_ADDR_REMAP                        0x318
+#define MV64340_PCI_1_MEMORY3_HIGH_ADDR_REMAP                       0x358
+#define MV64340_CPU_PCI_0_HEADERS_RETARGET_CONTROL                  0x3b0
+#define MV64340_CPU_PCI_0_HEADERS_RETARGET_BASE                     0x3b8
+#define MV64340_CPU_PCI_1_HEADERS_RETARGET_CONTROL                  0x3c0
+#define MV64340_CPU_PCI_1_HEADERS_RETARGET_BASE                     0x3c8
+#define MV64340_CPU_GE_HEADERS_RETARGET_CONTROL                     0x3d0
+#define MV64340_CPU_GE_HEADERS_RETARGET_BASE                        0x3d8
+#define MV64340_CPU_IDMA_HEADERS_RETARGET_CONTROL                   0x3e0
+#define MV64340_CPU_IDMA_HEADERS_RETARGET_BASE                      0x3e8
+
+/****************************************/
+/*         CPU Control Registers        */
+/****************************************/
+
+#define MV64340_CPU_CONFIG                                          0x000
+#define MV64340_CPU_MODE                                            0x120
+#define MV64340_CPU_MASTER_CONTROL                                  0x160
+#define MV64340_CPU_CROSS_BAR_CONTROL_LOW                           0x150
+#define MV64340_CPU_CROSS_BAR_CONTROL_HIGH                          0x158
+#define MV64340_CPU_CROSS_BAR_TIMEOUT                               0x168
+
+/****************************************/
+/* SMP RegisterS                        */
+/****************************************/
+
+#define MV64340_SMP_WHO_AM_I                                        0x200
+#define MV64340_SMP_CPU0_DOORBELL                                   0x214
+#define MV64340_SMP_CPU0_DOORBELL_CLEAR                             0x21C
+#define MV64340_SMP_CPU1_DOORBELL                                   0x224
+#define MV64340_SMP_CPU1_DOORBELL_CLEAR                             0x22C
+#define MV64340_SMP_CPU0_DOORBELL_MASK                              0x234
+#define MV64340_SMP_CPU1_DOORBELL_MASK                              0x23C
+#define MV64340_SMP_SEMAPHOR0                                       0x244
+#define MV64340_SMP_SEMAPHOR1                                       0x24c
+#define MV64340_SMP_SEMAPHOR2                                       0x254
+#define MV64340_SMP_SEMAPHOR3                                       0x25c
+#define MV64340_SMP_SEMAPHOR4                                       0x264
+#define MV64340_SMP_SEMAPHOR5                                       0x26c
+#define MV64340_SMP_SEMAPHOR6                                       0x274
+#define MV64340_SMP_SEMAPHOR7                                       0x27c
+
+/****************************************/
+/*  CPU Sync Barrier Register           */
+/****************************************/
+
+#define MV64340_CPU_0_SYNC_BARRIER_TRIGGER                          0x0c0
+#define MV64340_CPU_0_SYNC_BARRIER_VIRTUAL                          0x0c8
+#define MV64340_CPU_1_SYNC_BARRIER_TRIGGER                          0x0d0
+#define MV64340_CPU_1_SYNC_BARRIER_VIRTUAL                          0x0d8
+
+/****************************************/
+/* CPU Access Protect                   */
+/****************************************/
+
+#define MV64340_CPU_PROTECT_WINDOW_0_BASE_ADDR                      0x180
+#define MV64340_CPU_PROTECT_WINDOW_0_SIZE                           0x188
+#define MV64340_CPU_PROTECT_WINDOW_1_BASE_ADDR                      0x190
+#define MV64340_CPU_PROTECT_WINDOW_1_SIZE                           0x198
+#define MV64340_CPU_PROTECT_WINDOW_2_BASE_ADDR                      0x1a0
+#define MV64340_CPU_PROTECT_WINDOW_2_SIZE                           0x1a8
+#define MV64340_CPU_PROTECT_WINDOW_3_BASE_ADDR                      0x1b0
+#define MV64340_CPU_PROTECT_WINDOW_3_SIZE                           0x1b8
+
+
+/****************************************/
+/*          CPU Error Report            */
+/****************************************/
+
+#define MV64340_CPU_ERROR_ADDR_LOW                                  0x070
+#define MV64340_CPU_ERROR_ADDR_HIGH                                 0x078
+#define MV64340_CPU_ERROR_DATA_LOW                                  0x128
+#define MV64340_CPU_ERROR_DATA_HIGH                                 0x130
+#define MV64340_CPU_ERROR_PARITY                                    0x138
+#define MV64340_CPU_ERROR_CAUSE                                     0x140
+#define MV64340_CPU_ERROR_MASK                                      0x148
+
+/****************************************/
+/*      CPU Interface Debug Registers  */
+/****************************************/
+
+#define MV64340_PUNIT_SLAVE_DEBUG_LOW                               0x360
+#define MV64340_PUNIT_SLAVE_DEBUG_HIGH                              0x368
+#define MV64340_PUNIT_MASTER_DEBUG_LOW                              0x370
+#define MV64340_PUNIT_MASTER_DEBUG_HIGH                             0x378
+#define MV64340_PUNIT_MMASK                                         0x3e4
+
+/****************************************/
+/*  Integrated SRAM Registers           */
+/****************************************/
+
+#define MV64340_SRAM_CONFIG                                         0x380
+#define MV64340_SRAM_TEST_MODE                                      0X3F4
+#define MV64340_SRAM_ERROR_CAUSE                                    0x388
+#define MV64340_SRAM_ERROR_ADDR                                     0x390
+#define MV64340_SRAM_ERROR_ADDR_HIGH                                0X3F8
+#define MV64340_SRAM_ERROR_DATA_LOW                                 0x398
+#define MV64340_SRAM_ERROR_DATA_HIGH                                0x3a0
+#define MV64340_SRAM_ERROR_DATA_PARITY                              0x3a8
+
+/****************************************/
+/* SDRAM Configuration                  */
+/****************************************/
+
+#define MV64340_SDRAM_CONFIG                                        0x1400
+#define MV64340_D_UNIT_CONTROL_LOW                                  0x1404
+#define MV64340_D_UNIT_CONTROL_HIGH                                 0x1424
+#define MV64340_SDRAM_TIMING_CONTROL_LOW                            0x1408
+#define MV64340_SDRAM_TIMING_CONTROL_HIGH                           0x140c
+#define MV64340_SDRAM_ADDR_CONTROL                                  0x1410
+#define MV64340_SDRAM_OPEN_PAGES_CONTROL                            0x1414
+#define MV64340_SDRAM_OPERATION                                     0x1418
+#define MV64340_SDRAM_MODE                                          0x141c
+#define MV64340_EXTENDED_DRAM_MODE                                  0x1420
+#define MV64340_SDRAM_CROSS_BAR_CONTROL_LOW                         0x1430
+#define MV64340_SDRAM_CROSS_BAR_CONTROL_HIGH                        0x1434
+#define MV64340_SDRAM_CROSS_BAR_TIMEOUT                             0x1438
+#define MV64340_SDRAM_ADDR_CTRL_PADS_CALIBRATION                    0x14c0
+#define MV64340_SDRAM_DATA_PADS_CALIBRATION                         0x14c4
+
+/****************************************/
+/* SDRAM Error Report                   */
+/****************************************/
+
+#define MV64340_SDRAM_ERROR_DATA_LOW                                0x1444
+#define MV64340_SDRAM_ERROR_DATA_HIGH                               0x1440
+#define MV64340_SDRAM_ERROR_ADDR                                    0x1450
+#define MV64340_SDRAM_RECEIVED_ECC                                  0x1448
+#define MV64340_SDRAM_CALCULATED_ECC                                0x144c
+#define MV64340_SDRAM_ECC_CONTROL                                   0x1454
+#define MV64340_SDRAM_ECC_ERROR_COUNTER                             0x1458
+
+/******************************************/
+/*  Controlled Delay Line (CDL) Registers */
+/******************************************/
+
+#define MV64340_DFCDL_CONFIG0                                       0x1480
+#define MV64340_DFCDL_CONFIG1                                       0x1484
+#define MV64340_DLL_WRITE                                           0x1488
+#define MV64340_DLL_READ                                            0x148c
+#define MV64340_SRAM_ADDR                                           0x1490
+#define MV64340_SRAM_DATA0                                          0x1494
+#define MV64340_SRAM_DATA1                                          0x1498
+#define MV64340_SRAM_DATA2                                          0x149c
+#define MV64340_DFCL_PROBE                                          0x14a0
+
+/******************************************/
+/*   Debug Registers                      */
+/******************************************/
+
+#define MV64340_DUNIT_DEBUG_LOW                                     0x1460
+#define MV64340_DUNIT_DEBUG_HIGH                                    0x1464
+#define MV64340_DUNIT_MMASK                                         0X1b40
+
+/****************************************/
+/* Device Parameters                   */
+/****************************************/
+
+#define MV64340_DEVICE_BANK0_PARAMETERS                                    0x45c
+#define MV64340_DEVICE_BANK1_PARAMETERS                                    0x460
+#define MV64340_DEVICE_BANK2_PARAMETERS                                    0x464
+#define MV64340_DEVICE_BANK3_PARAMETERS                                    0x468
+#define MV64340_DEVICE_BOOT_BANK_PARAMETERS                        0x46c
+#define MV64340_DEVICE_INTERFACE_CONTROL                            0x4c0
+#define MV64340_DEVICE_INTERFACE_CROSS_BAR_CONTROL_LOW              0x4c8
+#define MV64340_DEVICE_INTERFACE_CROSS_BAR_CONTROL_HIGH             0x4cc
+#define MV64340_DEVICE_INTERFACE_CROSS_BAR_TIMEOUT                  0x4c4
+
+/****************************************/
+/* Device interrupt registers          */
+/****************************************/
+
+#define MV64340_DEVICE_INTERRUPT_CAUSE                             0x4d0
+#define MV64340_DEVICE_INTERRUPT_MASK                              0x4d4
+#define MV64340_DEVICE_ERROR_ADDR                                  0x4d8
+#define MV64340_DEVICE_ERROR_DATA                                  0x4dc
+#define MV64340_DEVICE_ERROR_PARITY                                0x4e0
+
+/****************************************/
+/* Device debug registers              */
+/****************************************/
+
+#define MV64340_DEVICE_DEBUG_LOW                                   0x4e4
+#define MV64340_DEVICE_DEBUG_HIGH                                  0x4e8
+#define MV64340_RUNIT_MMASK                                         0x4f0
+
+/****************************************/
+/* PCI Slave Address Decoding registers */
+/****************************************/
+
+#define MV64340_PCI_0_CS_0_BANK_SIZE                                0xc08
+#define MV64340_PCI_1_CS_0_BANK_SIZE                                0xc88
+#define MV64340_PCI_0_CS_1_BANK_SIZE                                0xd08
+#define MV64340_PCI_1_CS_1_BANK_SIZE                                0xd88
+#define MV64340_PCI_0_CS_2_BANK_SIZE                                0xc0c
+#define MV64340_PCI_1_CS_2_BANK_SIZE                                0xc8c
+#define MV64340_PCI_0_CS_3_BANK_SIZE                                0xd0c
+#define MV64340_PCI_1_CS_3_BANK_SIZE                                0xd8c
+#define MV64340_PCI_0_DEVCS_0_BANK_SIZE                             0xc10
+#define MV64340_PCI_1_DEVCS_0_BANK_SIZE                             0xc90
+#define MV64340_PCI_0_DEVCS_1_BANK_SIZE                             0xd10
+#define MV64340_PCI_1_DEVCS_1_BANK_SIZE                             0xd90
+#define MV64340_PCI_0_DEVCS_2_BANK_SIZE                             0xd18
+#define MV64340_PCI_1_DEVCS_2_BANK_SIZE                             0xd98
+#define MV64340_PCI_0_DEVCS_3_BANK_SIZE                             0xc14
+#define MV64340_PCI_1_DEVCS_3_BANK_SIZE                             0xc94
+#define MV64340_PCI_0_DEVCS_BOOT_BANK_SIZE                          0xd14
+#define MV64340_PCI_1_DEVCS_BOOT_BANK_SIZE                          0xd94
+#define MV64340_PCI_0_P2P_MEM0_BAR_SIZE                             0xd1c
+#define MV64340_PCI_1_P2P_MEM0_BAR_SIZE                             0xd9c
+#define MV64340_PCI_0_P2P_MEM1_BAR_SIZE                             0xd20
+#define MV64340_PCI_1_P2P_MEM1_BAR_SIZE                             0xda0
+#define MV64340_PCI_0_P2P_I_O_BAR_SIZE                              0xd24
+#define MV64340_PCI_1_P2P_I_O_BAR_SIZE                              0xda4
+#define MV64340_PCI_0_CPU_BAR_SIZE                                  0xd28
+#define MV64340_PCI_1_CPU_BAR_SIZE                                  0xda8
+#define MV64340_PCI_0_INTERNAL_SRAM_BAR_SIZE                        0xe00
+#define MV64340_PCI_1_INTERNAL_SRAM_BAR_SIZE                        0xe80
+#define MV64340_PCI_0_EXPANSION_ROM_BAR_SIZE                        0xd2c
+#define MV64340_PCI_1_EXPANSION_ROM_BAR_SIZE                        0xd9c
+#define MV64340_PCI_0_BASE_ADDR_REG_ENABLE                          0xc3c
+#define MV64340_PCI_1_BASE_ADDR_REG_ENABLE                          0xcbc
+#define MV64340_PCI_0_CS_0_BASE_ADDR_REMAP                         0xc48
+#define MV64340_PCI_1_CS_0_BASE_ADDR_REMAP                         0xcc8
+#define MV64340_PCI_0_CS_1_BASE_ADDR_REMAP                         0xd48
+#define MV64340_PCI_1_CS_1_BASE_ADDR_REMAP                         0xdc8
+#define MV64340_PCI_0_CS_2_BASE_ADDR_REMAP                         0xc4c
+#define MV64340_PCI_1_CS_2_BASE_ADDR_REMAP                         0xccc
+#define MV64340_PCI_0_CS_3_BASE_ADDR_REMAP                         0xd4c
+#define MV64340_PCI_1_CS_3_BASE_ADDR_REMAP                         0xdcc
+#define MV64340_PCI_0_CS_0_BASE_HIGH_ADDR_REMAP                            0xF04
+#define MV64340_PCI_1_CS_0_BASE_HIGH_ADDR_REMAP                            0xF84
+#define MV64340_PCI_0_CS_1_BASE_HIGH_ADDR_REMAP                            0xF08
+#define MV64340_PCI_1_CS_1_BASE_HIGH_ADDR_REMAP                            0xF88
+#define MV64340_PCI_0_CS_2_BASE_HIGH_ADDR_REMAP                            0xF0C
+#define MV64340_PCI_1_CS_2_BASE_HIGH_ADDR_REMAP                            0xF8C
+#define MV64340_PCI_0_CS_3_BASE_HIGH_ADDR_REMAP                            0xF10
+#define MV64340_PCI_1_CS_3_BASE_HIGH_ADDR_REMAP                            0xF90
+#define MV64340_PCI_0_DEVCS_0_BASE_ADDR_REMAP                      0xc50
+#define MV64340_PCI_1_DEVCS_0_BASE_ADDR_REMAP                      0xcd0
+#define MV64340_PCI_0_DEVCS_1_BASE_ADDR_REMAP                      0xd50
+#define MV64340_PCI_1_DEVCS_1_BASE_ADDR_REMAP                      0xdd0
+#define MV64340_PCI_0_DEVCS_2_BASE_ADDR_REMAP                      0xd58
+#define MV64340_PCI_1_DEVCS_2_BASE_ADDR_REMAP                      0xdd8
+#define MV64340_PCI_0_DEVCS_3_BASE_ADDR_REMAP                      0xc54
+#define MV64340_PCI_1_DEVCS_3_BASE_ADDR_REMAP                      0xcd4
+#define MV64340_PCI_0_DEVCS_BOOTCS_BASE_ADDR_REMAP                 0xd54
+#define MV64340_PCI_1_DEVCS_BOOTCS_BASE_ADDR_REMAP                 0xdd4
+#define MV64340_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_LOW                  0xd5c
+#define MV64340_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_LOW                  0xddc
+#define MV64340_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_HIGH                 0xd60
+#define MV64340_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_HIGH                 0xde0
+#define MV64340_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_LOW                  0xd64
+#define MV64340_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_LOW                  0xde4
+#define MV64340_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_HIGH                 0xd68
+#define MV64340_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_HIGH                 0xde8
+#define MV64340_PCI_0_P2P_I_O_BASE_ADDR_REMAP                       0xd6c
+#define MV64340_PCI_1_P2P_I_O_BASE_ADDR_REMAP                       0xdec 
+#define MV64340_PCI_0_CPU_BASE_ADDR_REMAP_LOW                       0xd70
+#define MV64340_PCI_1_CPU_BASE_ADDR_REMAP_LOW                       0xdf0
+#define MV64340_PCI_0_CPU_BASE_ADDR_REMAP_HIGH                      0xd74
+#define MV64340_PCI_1_CPU_BASE_ADDR_REMAP_HIGH                      0xdf4
+#define MV64340_PCI_0_INTEGRATED_SRAM_BASE_ADDR_REMAP               0xf00
+#define MV64340_PCI_1_INTEGRATED_SRAM_BASE_ADDR_REMAP               0xf80
+#define MV64340_PCI_0_EXPANSION_ROM_BASE_ADDR_REMAP                 0xf38
+#define MV64340_PCI_1_EXPANSION_ROM_BASE_ADDR_REMAP                 0xfb8
+#define MV64340_PCI_0_ADDR_DECODE_CONTROL                           0xd3c
+#define MV64340_PCI_1_ADDR_DECODE_CONTROL                           0xdbc
+#define MV64340_PCI_0_HEADERS_RETARGET_CONTROL                      0xF40
+#define MV64340_PCI_1_HEADERS_RETARGET_CONTROL                      0xFc0
+#define MV64340_PCI_0_HEADERS_RETARGET_BASE                         0xF44
+#define MV64340_PCI_1_HEADERS_RETARGET_BASE                         0xFc4
+#define MV64340_PCI_0_HEADERS_RETARGET_HIGH                         0xF48
+#define MV64340_PCI_1_HEADERS_RETARGET_HIGH                         0xFc8
+
+/***********************************/
+/*   PCI Control Register Map      */
+/***********************************/
+
+#define MV64340_PCI_0_DLL_STATUS_AND_COMMAND                        0x1d20
+#define MV64340_PCI_1_DLL_STATUS_AND_COMMAND                        0x1da0
+#define MV64340_PCI_0_MPP_PADS_DRIVE_CONTROL                        0x1d1C
+#define MV64340_PCI_1_MPP_PADS_DRIVE_CONTROL                        0x1d9C
+#define MV64340_PCI_0_COMMAND                                      0xc00
+#define MV64340_PCI_1_COMMAND                                      0xc80
+#define MV64340_PCI_0_MODE                                          0xd00
+#define MV64340_PCI_1_MODE                                          0xd80
+#define MV64340_PCI_0_RETRY                                        0xc04
+#define MV64340_PCI_1_RETRY                                        0xc84
+#define MV64340_PCI_0_READ_BUFFER_DISCARD_TIMER                     0xd04
+#define MV64340_PCI_1_READ_BUFFER_DISCARD_TIMER                     0xd84
+#define MV64340_PCI_0_MSI_TRIGGER_TIMER                             0xc38
+#define MV64340_PCI_1_MSI_TRIGGER_TIMER                             0xcb8
+#define MV64340_PCI_0_ARBITER_CONTROL                               0x1d00
+#define MV64340_PCI_1_ARBITER_CONTROL                               0x1d80
+#define MV64340_PCI_0_CROSS_BAR_CONTROL_LOW                         0x1d08
+#define MV64340_PCI_1_CROSS_BAR_CONTROL_LOW                         0x1d88
+#define MV64340_PCI_0_CROSS_BAR_CONTROL_HIGH                        0x1d0c
+#define MV64340_PCI_1_CROSS_BAR_CONTROL_HIGH                        0x1d8c
+#define MV64340_PCI_0_CROSS_BAR_TIMEOUT                             0x1d04
+#define MV64340_PCI_1_CROSS_BAR_TIMEOUT                             0x1d84
+#define MV64340_PCI_0_SYNC_BARRIER_TRIGGER_REG                      0x1D18
+#define MV64340_PCI_1_SYNC_BARRIER_TRIGGER_REG                      0x1D98
+#define MV64340_PCI_0_SYNC_BARRIER_VIRTUAL_REG                      0x1d10
+#define MV64340_PCI_1_SYNC_BARRIER_VIRTUAL_REG                      0x1d90
+#define MV64340_PCI_0_P2P_CONFIG                                    0x1d14
+#define MV64340_PCI_1_P2P_CONFIG                                    0x1d94
+
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_0_LOW                     0x1e00
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_0_HIGH                    0x1e04
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_0                         0x1e08
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_1_LOW                     0x1e10
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_1_HIGH                    0x1e14
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_1                         0x1e18
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_2_LOW                     0x1e20
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_2_HIGH                    0x1e24
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_2                         0x1e28
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_3_LOW                     0x1e30
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_3_HIGH                    0x1e34
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_3                         0x1e38
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_4_LOW                     0x1e40
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_4_HIGH                    0x1e44
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_4                         0x1e48
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_5_LOW                     0x1e50
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_5_HIGH                    0x1e54
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_5                         0x1e58
+
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_0_LOW                     0x1e80
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_0_HIGH                    0x1e84
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_0                         0x1e88
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_1_LOW                     0x1e90
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_1_HIGH                    0x1e94
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_1                         0x1e98
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_2_LOW                     0x1ea0
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_2_HIGH                    0x1ea4
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_2                         0x1ea8
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_3_LOW                     0x1eb0
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_3_HIGH                    0x1eb4
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_3                         0x1eb8
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_4_LOW                     0x1ec0
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_4_HIGH                    0x1ec4
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_4                         0x1ec8
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_5_LOW                     0x1ed0
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_5_HIGH                    0x1ed4
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_5                         0x1ed8
+
+/****************************************/
+/*   PCI Configuration Access Registers */
+/****************************************/
+
+#define MV64340_PCI_0_CONFIG_ADDR                                  0xcf8
+#define MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG                       0xcfc
+#define MV64340_PCI_1_CONFIG_ADDR                                  0xc78
+#define MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG                       0xc7c
+#define MV64340_PCI_0_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG                    0xc34
+#define MV64340_PCI_1_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG                    0xcb4
+
+/****************************************/
+/*   PCI Error Report Registers         */
+/****************************************/
+
+#define MV64340_PCI_0_SERR_MASK                                            0xc28
+#define MV64340_PCI_1_SERR_MASK                                            0xca8
+#define MV64340_PCI_0_ERROR_ADDR_LOW                                0x1d40
+#define MV64340_PCI_1_ERROR_ADDR_LOW                                0x1dc0
+#define MV64340_PCI_0_ERROR_ADDR_HIGH                               0x1d44
+#define MV64340_PCI_1_ERROR_ADDR_HIGH                               0x1dc4
+#define MV64340_PCI_0_ERROR_ATTRIBUTE                               0x1d48
+#define MV64340_PCI_1_ERROR_ATTRIBUTE                               0x1dc8
+#define MV64340_PCI_0_ERROR_COMMAND                                 0x1d50
+#define MV64340_PCI_1_ERROR_COMMAND                                 0x1dd0
+#define MV64340_PCI_0_ERROR_CAUSE                                   0x1d58
+#define MV64340_PCI_1_ERROR_CAUSE                                   0x1dd8
+#define MV64340_PCI_0_ERROR_MASK                                    0x1d5c
+#define MV64340_PCI_1_ERROR_MASK                                    0x1ddc
+
+/****************************************/
+/*   PCI Debug Registers                */
+/****************************************/
+
+#define MV64340_PCI_0_MMASK                                         0X1D24
+#define MV64340_PCI_1_MMASK                                         0X1DA4
+
+/*********************************************/
+/* PCI Configuration, Function 0, Registers  */
+/*********************************************/
+
+#define MV64340_PCI_DEVICE_AND_VENDOR_ID                           0x000
+#define MV64340_PCI_STATUS_AND_COMMAND                             0x004
+#define MV64340_PCI_CLASS_CODE_AND_REVISION_ID                     0x008
+#define MV64340_PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE      0x00C
+
+#define MV64340_PCI_SCS_0_BASE_ADDR_LOW                            0x010
+#define MV64340_PCI_SCS_0_BASE_ADDR_HIGH                           0x014
+#define MV64340_PCI_SCS_1_BASE_ADDR_LOW                            0x018
+#define MV64340_PCI_SCS_1_BASE_ADDR_HIGH                           0x01C
+#define MV64340_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_LOW                  0x020
+#define MV64340_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_HIGH                 0x024
+#define MV64340_PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID           0x02c
+#define MV64340_PCI_EXPANSION_ROM_BASE_ADDR_REG                            0x030
+#define MV64340_PCI_CAPABILTY_LIST_POINTER                          0x034
+#define MV64340_PCI_INTERRUPT_PIN_AND_LINE                         0x03C
+       /* capability list */
+#define MV64340_PCI_POWER_MANAGEMENT_CAPABILITY                     0x040
+#define MV64340_PCI_POWER_MANAGEMENT_STATUS_AND_CONTROL             0x044
+#define MV64340_PCI_VPD_ADDR                                        0x048
+#define MV64340_PCI_VPD_DATA                                        0x04c
+#define MV64340_PCI_MSI_MESSAGE_CONTROL                             0x050
+#define MV64340_PCI_MSI_MESSAGE_ADDR                                0x054
+#define MV64340_PCI_MSI_MESSAGE_UPPER_ADDR                          0x058
+#define MV64340_PCI_MSI_MESSAGE_DATA                                0x05c
+#define MV64340_PCI_X_COMMAND                                       0x060
+#define MV64340_PCI_X_STATUS                                        0x064
+#define MV64340_PCI_COMPACT_PCI_HOT_SWAP                            0x068
+
+/***********************************************/
+/*   PCI Configuration, Function 1, Registers  */
+/***********************************************/
+
+#define MV64340_PCI_SCS_2_BASE_ADDR_LOW                            0x110
+#define MV64340_PCI_SCS_2_BASE_ADDR_HIGH                           0x114
+#define MV64340_PCI_SCS_3_BASE_ADDR_LOW                            0x118
+#define MV64340_PCI_SCS_3_BASE_ADDR_HIGH                           0x11c
+#define MV64340_PCI_INTERNAL_SRAM_BASE_ADDR_LOW                    0x120
+#define MV64340_PCI_INTERNAL_SRAM_BASE_ADDR_HIGH                   0x124
+
+/***********************************************/
+/*  PCI Configuration, Function 2, Registers   */
+/***********************************************/
+
+#define MV64340_PCI_DEVCS_0_BASE_ADDR_LOW                          0x210
+#define MV64340_PCI_DEVCS_0_BASE_ADDR_HIGH                         0x214
+#define MV64340_PCI_DEVCS_1_BASE_ADDR_LOW                          0x218
+#define MV64340_PCI_DEVCS_1_BASE_ADDR_HIGH                         0x21c
+#define MV64340_PCI_DEVCS_2_BASE_ADDR_LOW                          0x220
+#define MV64340_PCI_DEVCS_2_BASE_ADDR_HIGH                         0x224
+
+/***********************************************/
+/*  PCI Configuration, Function 3, Registers   */
+/***********************************************/
+
+#define MV64340_PCI_DEVCS_3_BASE_ADDR_LOW                          0x310
+#define MV64340_PCI_DEVCS_3_BASE_ADDR_HIGH                         0x314
+#define MV64340_PCI_BOOT_CS_BASE_ADDR_LOW                          0x318
+#define MV64340_PCI_BOOT_CS_BASE_ADDR_HIGH                         0x31c
+#define MV64340_PCI_CPU_BASE_ADDR_LOW                              0x220
+#define MV64340_PCI_CPU_BASE_ADDR_HIGH                             0x224
+
+/***********************************************/
+/*  PCI Configuration, Function 4, Registers   */
+/***********************************************/
+
+#define MV64340_PCI_P2P_MEM0_BASE_ADDR_LOW                         0x410
+#define MV64340_PCI_P2P_MEM0_BASE_ADDR_HIGH                        0x414
+#define MV64340_PCI_P2P_MEM1_BASE_ADDR_LOW                         0x418
+#define MV64340_PCI_P2P_MEM1_BASE_ADDR_HIGH                        0x41c
+#define MV64340_PCI_P2P_I_O_BASE_ADDR                              0x420
+#define MV64340_PCI_INTERNAL_REGS_I_O_MAPPED_BASE_ADDR              0x424
+
+/****************************************/
+/* Messaging Unit Registers (I20)      */
+/****************************************/
+
+#define MV64340_I2O_INBOUND_MESSAGE_REG0_PCI_0_SIDE                0x010
+#define MV64340_I2O_INBOUND_MESSAGE_REG1_PCI_0_SIDE                0x014
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_PCI_0_SIDE               0x018
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_PCI_0_SIDE               0x01C
+#define MV64340_I2O_INBOUND_DOORBELL_REG_PCI_0_SIDE                0x020
+#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE          0x024
+#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE          0x028
+#define MV64340_I2O_OUTBOUND_DOORBELL_REG_PCI_0_SIDE               0x02C
+#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE         0x030
+#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE          0x034
+#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE       0x040
+#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE      0x044
+#define MV64340_I2O_QUEUE_CONTROL_REG_PCI_0_SIDE                   0x050
+#define MV64340_I2O_QUEUE_BASE_ADDR_REG_PCI_0_SIDE                 0x054
+#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE        0x060
+#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE        0x064
+#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE        0x068
+#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE        0x06C
+#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE       0x070
+#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE       0x074
+#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE       0x0F8
+#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE       0x0FC
+
+#define MV64340_I2O_INBOUND_MESSAGE_REG0_PCI_1_SIDE                0x090
+#define MV64340_I2O_INBOUND_MESSAGE_REG1_PCI_1_SIDE                0x094
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_PCI_1_SIDE               0x098
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_PCI_1_SIDE               0x09C
+#define MV64340_I2O_INBOUND_DOORBELL_REG_PCI_1_SIDE                0x0A0
+#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE          0x0A4
+#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE          0x0A8
+#define MV64340_I2O_OUTBOUND_DOORBELL_REG_PCI_1_SIDE               0x0AC
+#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE         0x0B0
+#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE          0x0B4
+#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE       0x0C0
+#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE      0x0C4
+#define MV64340_I2O_QUEUE_CONTROL_REG_PCI_1_SIDE                   0x0D0
+#define MV64340_I2O_QUEUE_BASE_ADDR_REG_PCI_1_SIDE                 0x0D4
+#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE        0x0E0
+#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE        0x0E4
+#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE        0x0E8
+#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE        0x0EC
+#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE       0x0F0
+#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE       0x0F4
+#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE       0x078
+#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE       0x07C
+
+#define MV64340_I2O_INBOUND_MESSAGE_REG0_CPU0_SIDE                 0x1C10
+#define MV64340_I2O_INBOUND_MESSAGE_REG1_CPU0_SIDE                 0x1C14
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_CPU0_SIDE                0x1C18
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_CPU0_SIDE                0x1C1C
+#define MV64340_I2O_INBOUND_DOORBELL_REG_CPU0_SIDE                 0x1C20
+#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE          0x1C24
+#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_CPU0_SIDE           0x1C28
+#define MV64340_I2O_OUTBOUND_DOORBELL_REG_CPU0_SIDE                0x1C2C
+#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE          0x1C30
+#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU0_SIDE           0x1C34
+#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE        0x1C40
+#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE       0x1C44
+#define MV64340_I2O_QUEUE_CONTROL_REG_CPU0_SIDE                    0x1C50
+#define MV64340_I2O_QUEUE_BASE_ADDR_REG_CPU0_SIDE                  0x1C54
+#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE         0x1C60
+#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE         0x1C64
+#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE         0x1C68
+#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE         0x1C6C
+#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE        0x1C70
+#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE        0x1C74
+#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE        0x1CF8
+#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE        0x1CFC
+#define MV64340_I2O_INBOUND_MESSAGE_REG0_CPU1_SIDE                 0x1C90
+#define MV64340_I2O_INBOUND_MESSAGE_REG1_CPU1_SIDE                 0x1C94
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_CPU1_SIDE                0x1C98
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_CPU1_SIDE                0x1C9C
+#define MV64340_I2O_INBOUND_DOORBELL_REG_CPU1_SIDE                 0x1CA0
+#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE          0x1CA4
+#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_CPU1_SIDE           0x1CA8
+#define MV64340_I2O_OUTBOUND_DOORBELL_REG_CPU1_SIDE                0x1CAC
+#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE          0x1CB0
+#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU1_SIDE           0x1CB4
+#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE        0x1CC0
+#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE       0x1CC4
+#define MV64340_I2O_QUEUE_CONTROL_REG_CPU1_SIDE                    0x1CD0
+#define MV64340_I2O_QUEUE_BASE_ADDR_REG_CPU1_SIDE                  0x1CD4
+#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE         0x1CE0
+#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE         0x1CE4
+#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE         0x1CE8
+#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE         0x1CEC
+#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE        0x1CF0
+#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE        0x1CF4
+#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE        0x1C78
+#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE        0x1C7C
+
+/****************************************/
+/*        Ethernet Unit Registers              */
+/****************************************/
+
+#define MV64340_ETH_PHY_ADDR_REG                                    0x2000
+#define MV64340_ETH_SMI_REG                                         0x2004
+#define MV64340_ETH_UNIT_DEFAULT_ADDR_REG                           0x2008
+#define MV64340_ETH_UNIT_DEFAULTID_REG                              0x200c
+#define MV64340_ETH_UNIT_INTERRUPT_CAUSE_REG                        0x2080
+#define MV64340_ETH_UNIT_INTERRUPT_MASK_REG                         0x2084
+#define MV64340_ETH_UNIT_INTERNAL_USE_REG                           0x24fc
+#define MV64340_ETH_UNIT_ERROR_ADDR_REG                             0x2094
+#define MV64340_ETH_BAR_0                                           0x2200
+#define MV64340_ETH_BAR_1                                           0x2208
+#define MV64340_ETH_BAR_2                                           0x2210
+#define MV64340_ETH_BAR_3                                           0x2218
+#define MV64340_ETH_BAR_4                                           0x2220
+#define MV64340_ETH_BAR_5                                           0x2228
+#define MV64340_ETH_SIZE_REG_0                                      0x2204
+#define MV64340_ETH_SIZE_REG_1                                      0x220c
+#define MV64340_ETH_SIZE_REG_2                                      0x2214
+#define MV64340_ETH_SIZE_REG_3                                      0x221c
+#define MV64340_ETH_SIZE_REG_4                                      0x2224
+#define MV64340_ETH_SIZE_REG_5                                      0x222c
+#define MV64340_ETH_HEADERS_RETARGET_BASE_REG                       0x2230
+#define MV64340_ETH_HEADERS_RETARGET_CONTROL_REG                    0x2234
+#define MV64340_ETH_HIGH_ADDR_REMAP_REG_0                           0x2280
+#define MV64340_ETH_HIGH_ADDR_REMAP_REG_1                           0x2284
+#define MV64340_ETH_HIGH_ADDR_REMAP_REG_2                           0x2288
+#define MV64340_ETH_HIGH_ADDR_REMAP_REG_3                           0x228c
+#define MV64340_ETH_BASE_ADDR_ENABLE_REG                            0x2290
+#define MV64340_ETH_ACCESS_PROTECTION_REG(port)                    (0x2294 + (port<<2))
+#define MV64340_ETH_MIB_COUNTERS_BASE(port)                        (0x3000 + (port<<7))
+#define MV64340_ETH_PORT_CONFIG_REG(port)                          (0x2400 + (port<<10))
+#define MV64340_ETH_PORT_CONFIG_EXTEND_REG(port)                   (0x2404 + (port<<10))
+#define MV64340_ETH_MII_SERIAL_PARAMETRS_REG(port)                 (0x2408 + (port<<10))
+#define MV64340_ETH_GMII_SERIAL_PARAMETRS_REG(port)                (0x240c + (port<<10))
+#define MV64340_ETH_VLAN_ETHERTYPE_REG(port)                       (0x2410 + (port<<10))
+#define MV64340_ETH_MAC_ADDR_LOW(port)                             (0x2414 + (port<<10))
+#define MV64340_ETH_MAC_ADDR_HIGH(port)                            (0x2418 + (port<<10))
+#define MV64340_ETH_SDMA_CONFIG_REG(port)                          (0x241c + (port<<10))
+#define MV64340_ETH_DSCP_0(port)                                   (0x2420 + (port<<10))
+#define MV64340_ETH_DSCP_1(port)                                   (0x2424 + (port<<10))
+#define MV64340_ETH_DSCP_2(port)                                   (0x2428 + (port<<10))
+#define MV64340_ETH_DSCP_3(port)                                   (0x242c + (port<<10))
+#define MV64340_ETH_DSCP_4(port)                                   (0x2430 + (port<<10))
+#define MV64340_ETH_DSCP_5(port)                                   (0x2434 + (port<<10))
+#define MV64340_ETH_DSCP_6(port)                                   (0x2438 + (port<<10))
+#define MV64340_ETH_PORT_SERIAL_CONTROL_REG(port)                  (0x243c + (port<<10))
+#define MV64340_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port)            (0x2440 + (port<<10))
+#define MV64340_ETH_PORT_STATUS_REG(port)                          (0x2444 + (port<<10))
+#define MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port)               (0x2448 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_FIXED_PRIORITY(port)                  (0x244c + (port<<10))
+#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port)         (0x2450 + (port<<10))
+#define MV64340_ETH_MAXIMUM_TRANSMIT_UNIT(port)                    (0x2458 + (port<<10))
+#define MV64340_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port)           (0x245c + (port<<10))
+#define MV64340_ETH_INTERRUPT_CAUSE_REG(port)                      (0x2460 + (port<<10))
+#define MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port)               (0x2464 + (port<<10))
+#define MV64340_ETH_INTERRUPT_MASK_REG(port)                       (0x2468 + (port<<10))
+#define MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port)                (0x246c + (port<<10))
+#define MV64340_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2470 + (port<<10))
+#define MV64340_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2474 + (port<<10))
+#define MV64340_ETH_RX_MINIMAL_FRAME_SIZE_REG(port)                (0x247c + (port<<10))
+#define MV64340_ETH_RX_DISCARDED_FRAMES_COUNTER(port)              (0x2484 + (port<<10)
+#define MV64340_ETH_PORT_DEBUG_0_REG(port)                         (0x248c + (port<<10))
+#define MV64340_ETH_PORT_DEBUG_1_REG(port)                         (0x2490 + (port<<10))
+#define MV64340_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port)             (0x2494 + (port<<10))
+#define MV64340_ETH_INTERNAL_USE_REG(port)                         (0x24fc + (port<<10))
+#define MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port)                (0x2680 + (port<<10))
+#define MV64340_ETH_CURRENT_SERVED_TX_DESC_PTR(port)               (0x2684 + (port<<10))      
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x260c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x261c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x262c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x263c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x264c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x265c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x266c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x267c + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x26c0 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x26c4 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x26c8 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x26cc + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x26d0 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x26d4 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x26d8 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x26dc + (port<<10))     
+#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port)            (0x2700 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port)            (0x2710 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port)            (0x2720 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port)            (0x2730 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port)            (0x2740 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port)            (0x2750 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port)            (0x2760 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port)            (0x2770 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port)           (0x2704 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port)           (0x2714 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port)           (0x2724 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port)           (0x2734 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port)           (0x2744 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port)           (0x2754 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port)           (0x2764 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port)           (0x2774 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_0_ARBITER_CONFIG(port)                (0x2708 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_1_ARBITER_CONFIG(port)                (0x2718 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_2_ARBITER_CONFIG(port)                (0x2728 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_3_ARBITER_CONFIG(port)                (0x2738 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_4_ARBITER_CONFIG(port)                (0x2748 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_5_ARBITER_CONFIG(port)                (0x2758 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_6_ARBITER_CONFIG(port)                (0x2768 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_7_ARBITER_CONFIG(port)                (0x2778 + (port<<10))
+#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port)               (0x2780 + (port<<10))
+#define MV64340_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port)   (0x3400 + (port<<10))
+#define MV64340_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port)     (0x3500 + (port<<10))
+#define MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE(port)             (0x3600 + (port<<10))
+
+/*******************************************/
+/*          CUNIT  Registers               */
+/*******************************************/
+
+         /* Address Decoding Register Map */
+           
+#define MV64340_CUNIT_BASE_ADDR_REG0                                0xf200
+#define MV64340_CUNIT_BASE_ADDR_REG1                                0xf208
+#define MV64340_CUNIT_BASE_ADDR_REG2                                0xf210
+#define MV64340_CUNIT_BASE_ADDR_REG3                                0xf218
+#define MV64340_CUNIT_SIZE0                                         0xf204
+#define MV64340_CUNIT_SIZE1                                         0xf20c
+#define MV64340_CUNIT_SIZE2                                         0xf214
+#define MV64340_CUNIT_SIZE3                                         0xf21c
+#define MV64340_CUNIT_HIGH_ADDR_REMAP_REG0                          0xf240
+#define MV64340_CUNIT_HIGH_ADDR_REMAP_REG1                          0xf244
+#define MV64340_CUNIT_BASE_ADDR_ENABLE_REG                          0xf250
+#define MV64340_MPSC0_ACCESS_PROTECTION_REG                         0xf254
+#define MV64340_MPSC1_ACCESS_PROTECTION_REG                         0xf258
+#define MV64340_CUNIT_INTERNAL_SPACE_BASE_ADDR_REG                  0xf25C
+
+        /*  Error Report Registers  */
+
+#define MV64340_CUNIT_INTERRUPT_CAUSE_REG                           0xf310
+#define MV64340_CUNIT_INTERRUPT_MASK_REG                            0xf314
+#define MV64340_CUNIT_ERROR_ADDR                                    0xf318
+
+        /*  Cunit Control Registers */
+
+#define MV64340_CUNIT_ARBITER_CONTROL_REG                           0xf300
+#define MV64340_CUNIT_CONFIG_REG                                    0xb40c
+#define MV64340_CUNIT_CRROSBAR_TIMEOUT_REG                          0xf304
+
+        /*  Cunit Debug Registers   */
+
+#define MV64340_CUNIT_DEBUG_LOW                                     0xf340
+#define MV64340_CUNIT_DEBUG_HIGH                                    0xf344
+#define MV64340_CUNIT_MMASK                                         0xf380
+
+        /*  MPSCs Clocks Routing Registers  */
+
+#define MV64340_MPSC_ROUTING_REG                                    0xb400
+#define MV64340_MPSC_RX_CLOCK_ROUTING_REG                           0xb404
+#define MV64340_MPSC_TX_CLOCK_ROUTING_REG                           0xb408
+
+        /*  MPSCs Interrupts Registers    */
+
+#define MV64340_MPSC_CAUSE_REG(port)                               (0xb804 + (port<<3))
+#define MV64340_MPSC_MASK_REG(port)                                (0xb884 + (port<<3))
+#define MV64340_MPSC_MAIN_CONFIG_LOW(port)                         (0x8000 + (port<<12))
+#define MV64340_MPSC_MAIN_CONFIG_HIGH(port)                        (0x8004 + (port<<12))    
+#define MV64340_MPSC_PROTOCOL_CONFIG(port)                         (0x8008 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG1(port)                            (0x800c + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG2(port)                            (0x8010 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG3(port)                            (0x8014 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG4(port)                            (0x8018 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG5(port)                            (0x801c + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG6(port)                            (0x8020 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG7(port)                            (0x8024 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG8(port)                            (0x8028 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG9(port)                            (0x802c + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG10(port)                           (0x8030 + (port<<12))    
+        
+        /*  MPSC0 Registers      */
+
+
+/***************************************/
+/*          SDMA Registers             */
+/***************************************/
+
+#define MV64340_SDMA_CONFIG_REG(channel)                        (0x4000 + (channel<<13))        
+#define MV64340_SDMA_COMMAND_REG(channel)                       (0x4008 + (channel<<13))        
+#define MV64340_SDMA_CURRENT_RX_DESCRIPTOR_POINTER(channel)     (0x4810 + (channel<<13))        
+#define MV64340_SDMA_CURRENT_TX_DESCRIPTOR_POINTER(channel)     (0x4c10 + (channel<<13))        
+#define MV64340_SDMA_FIRST_TX_DESCRIPTOR_POINTER(channel)       (0x4c14 + (channel<<13)) 
+
+#define MV64340_SDMA_CAUSE_REG                                      0xb800
+#define MV64340_SDMA_MASK_REG                                       0xb880
+         
+/* BRG Interrupts */
+
+#define MV64340_BRG_CONFIG_REG(brg)                              (0xb200 + (brg<<3))
+#define MV64340_BRG_BAUDE_TUNING_REG(brg)                        (0xb208 + (brg<<3))
+#define MV64340_BRG_CAUSE_REG                                       0xb834
+#define MV64340_BRG_MASK_REG                                        0xb8b4
+
+/****************************************/
+/* DMA Channel Control                 */
+/****************************************/
+
+#define MV64340_DMA_CHANNEL0_CONTROL                               0x840
+#define MV64340_DMA_CHANNEL0_CONTROL_HIGH                          0x880
+#define MV64340_DMA_CHANNEL1_CONTROL                               0x844
+#define MV64340_DMA_CHANNEL1_CONTROL_HIGH                          0x884
+#define MV64340_DMA_CHANNEL2_CONTROL                               0x848
+#define MV64340_DMA_CHANNEL2_CONTROL_HIGH                          0x888
+#define MV64340_DMA_CHANNEL3_CONTROL                               0x84C
+#define MV64340_DMA_CHANNEL3_CONTROL_HIGH                          0x88C
+
+
+/****************************************/
+/*           IDMA Registers             */
+/****************************************/
+
+#define MV64340_DMA_CHANNEL0_BYTE_COUNT                             0x800
+#define MV64340_DMA_CHANNEL1_BYTE_COUNT                             0x804
+#define MV64340_DMA_CHANNEL2_BYTE_COUNT                             0x808
+#define MV64340_DMA_CHANNEL3_BYTE_COUNT                             0x80C
+#define MV64340_DMA_CHANNEL0_SOURCE_ADDR                            0x810
+#define MV64340_DMA_CHANNEL1_SOURCE_ADDR                            0x814
+#define MV64340_DMA_CHANNEL2_SOURCE_ADDR                            0x818
+#define MV64340_DMA_CHANNEL3_SOURCE_ADDR                            0x81c
+#define MV64340_DMA_CHANNEL0_DESTINATION_ADDR                       0x820
+#define MV64340_DMA_CHANNEL1_DESTINATION_ADDR                       0x824
+#define MV64340_DMA_CHANNEL2_DESTINATION_ADDR                       0x828
+#define MV64340_DMA_CHANNEL3_DESTINATION_ADDR                       0x82C
+#define MV64340_DMA_CHANNEL0_NEXT_DESCRIPTOR_POINTER                0x830
+#define MV64340_DMA_CHANNEL1_NEXT_DESCRIPTOR_POINTER                0x834
+#define MV64340_DMA_CHANNEL2_NEXT_DESCRIPTOR_POINTER                0x838
+#define MV64340_DMA_CHANNEL3_NEXT_DESCRIPTOR_POINTER                0x83C
+#define MV64340_DMA_CHANNEL0_CURRENT_DESCRIPTOR_POINTER             0x870
+#define MV64340_DMA_CHANNEL1_CURRENT_DESCRIPTOR_POINTER             0x874
+#define MV64340_DMA_CHANNEL2_CURRENT_DESCRIPTOR_POINTER             0x878
+#define MV64340_DMA_CHANNEL3_CURRENT_DESCRIPTOR_POINTER             0x87C
+
+ /*  IDMA Address Decoding Base Address Registers  */
+#define MV64340_DMA_BASE_ADDR_REG0                                  0xa00
+#define MV64340_DMA_BASE_ADDR_REG1                                  0xa08
+#define MV64340_DMA_BASE_ADDR_REG2                                  0xa10
+#define MV64340_DMA_BASE_ADDR_REG3                                  0xa18
+#define MV64340_DMA_BASE_ADDR_REG4                                  0xa20
+#define MV64340_DMA_BASE_ADDR_REG5                                  0xa28
+#define MV64340_DMA_BASE_ADDR_REG6                                  0xa30
+#define MV64340_DMA_BASE_ADDR_REG7                                  0xa38
+ /*  IDMA Address Decoding Size Address Register   */
+#define MV64340_DMA_SIZE_REG0                                       0xa04
+#define MV64340_DMA_SIZE_REG1                                       0xa0c
+#define MV64340_DMA_SIZE_REG2                                       0xa14
+#define MV64340_DMA_SIZE_REG3                                       0xa1c
+#define MV64340_DMA_SIZE_REG4                                       0xa24
+#define MV64340_DMA_SIZE_REG5                                       0xa2c
+#define MV64340_DMA_SIZE_REG6                                       0xa34
+#define MV64340_DMA_SIZE_REG7                                       0xa3C
+
+ /* IDMA Address Decoding High Address Remap and Access 
+                  Protection Registers                    */
+                  
+#define MV64340_DMA_HIGH_ADDR_REMAP_REG0                            0xa60
+#define MV64340_DMA_HIGH_ADDR_REMAP_REG1                            0xa64
+#define MV64340_DMA_HIGH_ADDR_REMAP_REG2                            0xa68
+#define MV64340_DMA_HIGH_ADDR_REMAP_REG3                            0xa6C
+#define MV64340_DMA_BASE_ADDR_ENABLE_REG                            0xa80
+#define MV64340_DMA_CHANNEL0_ACCESS_PROTECTION_REG                  0xa70
+#define MV64340_DMA_CHANNEL1_ACCESS_PROTECTION_REG                  0xa74
+#define MV64340_DMA_CHANNEL2_ACCESS_PROTECTION_REG                  0xa78
+#define MV64340_DMA_CHANNEL3_ACCESS_PROTECTION_REG                  0xa7c
+#define MV64340_DMA_ARBITER_CONTROL                                 0x860
+#define MV64340_DMA_CROSS_BAR_TIMEOUT                               0x8d0
+
+ /*  IDMA Headers Retarget Registers   */
+
+#define MV64340_DMA_HEADERS_RETARGET_CONTROL                        0xa84
+#define MV64340_DMA_HEADERS_RETARGET_BASE                           0xa88
+
+ /*  IDMA Interrupt Register  */
+
+#define MV64340_DMA_INTERRUPT_CAUSE_REG                             0x8c0
+#define MV64340_DMA_INTERRUPT_CAUSE_MASK                            0x8c4
+#define MV64340_DMA_ERROR_ADDR                                      0x8c8
+#define MV64340_DMA_ERROR_SELECT                                    0x8cc
+
+ /*  IDMA Debug Register ( for internal use )    */
+
+#define MV64340_DMA_DEBUG_LOW                                       0x8e0
+#define MV64340_DMA_DEBUG_HIGH                                      0x8e4
+#define MV64340_DMA_SPARE                                           0xA8C
+
+/****************************************/
+/* Timer_Counter                       */
+/****************************************/
+
+#define MV64340_TIMER_COUNTER0                                     0x850
+#define MV64340_TIMER_COUNTER1                                     0x854
+#define MV64340_TIMER_COUNTER2                                     0x858
+#define MV64340_TIMER_COUNTER3                                     0x85C
+#define MV64340_TIMER_COUNTER_0_3_CONTROL                          0x864
+#define MV64340_TIMER_COUNTER_0_3_INTERRUPT_CAUSE                  0x868
+#define MV64340_TIMER_COUNTER_0_3_INTERRUPT_MASK                   0x86c
+
+/****************************************/
+/*         Watchdog registers                  */
+/****************************************/
+
+#define MV64340_WATCHDOG_CONFIG_REG                                 0xb410
+#define MV64340_WATCHDOG_VALUE_REG                                  0xb414
+
+/****************************************/
+/* I2C Registers                        */
+/****************************************/
+
+#define MV64340_I2C_SLAVE_ADDR                                      0xc000
+#define MV64340_I2C_EXTENDED_SLAVE_ADDR                             0xc010
+#define MV64340_I2C_DATA                                            0xc004
+#define MV64340_I2C_CONTROL                                         0xc008
+#define MV64340_I2C_STATUS_BAUDE_RATE                               0xc00C
+#define MV64340_I2C_SOFT_RESET                                      0xc01c
+
+/****************************************/
+/* GPP Interface Registers              */
+/****************************************/
+
+#define MV64340_GPP_IO_CONTROL                                      0xf100
+#define MV64340_GPP_LEVEL_CONTROL                                   0xf110
+#define MV64340_GPP_VALUE                                           0xf104
+#define MV64340_GPP_INTERRUPT_CAUSE                                 0xf108
+#define MV64340_GPP_INTERRUPT_MASK0                                 0xf10c
+#define MV64340_GPP_INTERRUPT_MASK1                                 0xf114
+#define MV64340_GPP_VALUE_SET                                       0xf118
+#define MV64340_GPP_VALUE_CLEAR                                     0xf11c
+
+/****************************************/
+/* Interrupt Controller Registers       */
+/****************************************/
+
+/****************************************/
+/* Interrupts                          */
+/****************************************/
+
+#define MV64340_MAIN_INTERRUPT_CAUSE_LOW                            0x004
+#define MV64340_MAIN_INTERRUPT_CAUSE_HIGH                           0x00c
+#define MV64340_CPU_INTERRUPT0_MASK_LOW                             0x014
+#define MV64340_CPU_INTERRUPT0_MASK_HIGH                            0x01c
+#define MV64340_CPU_INTERRUPT0_SELECT_CAUSE                         0x024
+#define MV64340_CPU_INTERRUPT1_MASK_LOW                             0x034
+#define MV64340_CPU_INTERRUPT1_MASK_HIGH                            0x03c
+#define MV64340_CPU_INTERRUPT1_SELECT_CAUSE                         0x044
+#define MV64340_INTERRUPT0_MASK_0_LOW                               0x054
+#define MV64340_INTERRUPT0_MASK_0_HIGH                              0x05c
+#define MV64340_INTERRUPT0_SELECT_CAUSE                             0x064
+#define MV64340_INTERRUPT1_MASK_0_LOW                               0x074
+#define MV64340_INTERRUPT1_MASK_0_HIGH                              0x07c
+#define MV64340_INTERRUPT1_SELECT_CAUSE                             0x084
+
+/****************************************/
+/*      MPP Interface Registers         */
+/****************************************/
+
+#define MV64340_MPP_CONTROL0                                        0xf000
+#define MV64340_MPP_CONTROL1                                        0xf004
+#define MV64340_MPP_CONTROL2                                        0xf008
+#define MV64340_MPP_CONTROL3                                        0xf00c
+
+/****************************************/
+/*    Serial Initialization registers   */
+/****************************************/
+
+#define MV64340_SERIAL_INIT_LAST_DATA                               0xf324
+#define MV64340_SERIAL_INIT_CONTROL                                 0xf328
+#define MV64340_SERIAL_INIT_STATUS                                  0xf32c
+
+extern void mv64340_irq_init(unsigned int base);
+
+#endif /* __ASM_MV64340_H */
index 9206244..99f7787 100644 (file)
@@ -57,9 +57,9 @@ struct ncp_volume_info {
        char volume_name[NCP_VOLNAME_LEN + 1];
 };
 
-#define AR_READ      (ntohs(0x0100))
-#define AR_WRITE     (ntohs(0x0200))
-#define AR_EXCLUSIVE (ntohs(0x2000))
+#define AR_READ      (cpu_to_le16(1))
+#define AR_WRITE     (cpu_to_le16(2))
+#define AR_EXCLUSIVE (cpu_to_le16(0x20))
 
 #define NCP_FILE_ID_LEN 6
 
@@ -71,20 +71,20 @@ struct ncp_volume_info {
 #define NW_NS_OS2     4
 
 /*  Defines for ReturnInformationMask */
-#define RIM_NAME             (ntohl(0x01000000L))
-#define RIM_SPACE_ALLOCATED   (ntohl(0x02000000L))
-#define RIM_ATTRIBUTES       (ntohl(0x04000000L))
-#define RIM_DATA_SIZE        (ntohl(0x08000000L))
-#define RIM_TOTAL_SIZE       (ntohl(0x10000000L))
-#define RIM_EXT_ATTR_INFO     (ntohl(0x20000000L))
-#define RIM_ARCHIVE          (ntohl(0x40000000L))
-#define RIM_MODIFY           (ntohl(0x80000000L))
-#define RIM_CREATION         (ntohl(0x00010000L))
-#define RIM_OWNING_NAMESPACE  (ntohl(0x00020000L))
-#define RIM_DIRECTORY        (ntohl(0x00040000L))
-#define RIM_RIGHTS           (ntohl(0x00080000L))
-#define RIM_ALL              (ntohl(0xFF0F0000L))
-#define RIM_COMPRESSED_INFO   (ntohl(0x00000080L))
+#define RIM_NAME             (cpu_to_le32(1))
+#define RIM_SPACE_ALLOCATED   (cpu_to_le32(2))
+#define RIM_ATTRIBUTES       (cpu_to_le32(4))
+#define RIM_DATA_SIZE        (cpu_to_le32(8))
+#define RIM_TOTAL_SIZE       (cpu_to_le32(0x10))
+#define RIM_EXT_ATTR_INFO     (cpu_to_le32(0x20))
+#define RIM_ARCHIVE          (cpu_to_le32(0x40))
+#define RIM_MODIFY           (cpu_to_le32(0x80))
+#define RIM_CREATION         (cpu_to_le32(0x100))
+#define RIM_OWNING_NAMESPACE  (cpu_to_le32(0x200))
+#define RIM_DIRECTORY        (cpu_to_le32(0x400))
+#define RIM_RIGHTS           (cpu_to_le32(0x800))
+#define RIM_ALL              (cpu_to_le32(0xFFF))
+#define RIM_COMPRESSED_INFO   (cpu_to_le32(0x80000000))
 
 /* Defines for NSInfoBitMask */
 #define NSIBM_NFS_NAME         0x0001
@@ -129,24 +129,24 @@ struct nw_nfs_info {
 
 struct nw_info_struct {
        __u32 spaceAlloc __attribute__((packed));
-       __u32 attributes __attribute__((packed));
+       __le32 attributes __attribute__((packed));
        __u16 flags __attribute__((packed));
-       __u32 dataStreamSize __attribute__((packed));
-       __u32 totalStreamSize __attribute__((packed));
+       __le32 dataStreamSize __attribute__((packed));
+       __le32 totalStreamSize __attribute__((packed));
        __u16 numberOfStreams __attribute__((packed));
-       __u16 creationTime __attribute__((packed));
-       __u16 creationDate __attribute__((packed));
+       __le16 creationTime __attribute__((packed));
+       __le16 creationDate __attribute__((packed));
        __u32 creatorID __attribute__((packed));
-       __u16 modifyTime __attribute__((packed));
-       __u16 modifyDate __attribute__((packed));
+       __le16 modifyTime __attribute__((packed));
+       __le16 modifyDate __attribute__((packed));
        __u32 modifierID __attribute__((packed));
-       __u16 lastAccessDate __attribute__((packed));
+       __le16 lastAccessDate __attribute__((packed));
        __u16 archiveTime __attribute__((packed));
        __u16 archiveDate __attribute__((packed));
        __u32 archiverID __attribute__((packed));
        __u16 inheritedRightsMask __attribute__((packed));
-       __u32 dirEntNum __attribute__((packed));
-       __u32 DosDirNum __attribute__((packed));
+       __le32 dirEntNum __attribute__((packed));
+       __le32 DosDirNum __attribute__((packed));
        __u32 volNumber __attribute__((packed));
        __u32 EADataSize __attribute__((packed));
        __u32 EAKeyCount __attribute__((packed));
@@ -161,32 +161,32 @@ struct nw_info_struct {
 };
 
 /* modify mask - use with MODIFY_DOS_INFO structure */
-#define DM_ATTRIBUTES            (ntohl(0x02000000L))
-#define DM_CREATE_DATE           (ntohl(0x04000000L))
-#define DM_CREATE_TIME           (ntohl(0x08000000L))
-#define DM_CREATOR_ID            (ntohl(0x10000000L))
-#define DM_ARCHIVE_DATE          (ntohl(0x20000000L))
-#define DM_ARCHIVE_TIME          (ntohl(0x40000000L))
-#define DM_ARCHIVER_ID           (ntohl(0x80000000L))
-#define DM_MODIFY_DATE           (ntohl(0x00010000L))
-#define DM_MODIFY_TIME           (ntohl(0x00020000L))
-#define DM_MODIFIER_ID           (ntohl(0x00040000L))
-#define DM_LAST_ACCESS_DATE      (ntohl(0x00080000L))
-#define DM_INHERITED_RIGHTS_MASK  (ntohl(0x00100000L))
-#define DM_MAXIMUM_SPACE         (ntohl(0x00200000L))
+#define DM_ATTRIBUTES            (cpu_to_le32(0x02))
+#define DM_CREATE_DATE           (cpu_to_le32(0x04))
+#define DM_CREATE_TIME           (cpu_to_le32(0x08))
+#define DM_CREATOR_ID            (cpu_to_le32(0x10))
+#define DM_ARCHIVE_DATE          (cpu_to_le32(0x20))
+#define DM_ARCHIVE_TIME          (cpu_to_le32(0x40))
+#define DM_ARCHIVER_ID           (cpu_to_le32(0x80))
+#define DM_MODIFY_DATE           (cpu_to_le32(0x0100))
+#define DM_MODIFY_TIME           (cpu_to_le32(0x0200))
+#define DM_MODIFIER_ID           (cpu_to_le32(0x0400))
+#define DM_LAST_ACCESS_DATE      (cpu_to_le32(0x0800))
+#define DM_INHERITED_RIGHTS_MASK  (cpu_to_le32(0x1000))
+#define DM_MAXIMUM_SPACE         (cpu_to_le32(0x2000))
 
 struct nw_modify_dos_info {
-       __u32 attributes __attribute__((packed));
-       __u16 creationDate __attribute__((packed));
-       __u16 creationTime __attribute__((packed));
+       __le32 attributes __attribute__((packed));
+       __le16 creationDate __attribute__((packed));
+       __le16 creationTime __attribute__((packed));
        __u32 creatorID __attribute__((packed));
-       __u16 modifyDate __attribute__((packed));
-       __u16 modifyTime __attribute__((packed));
+       __le16 modifyDate __attribute__((packed));
+       __le16 modifyTime __attribute__((packed));
        __u32 modifierID __attribute__((packed));
        __u16 archiveDate __attribute__((packed));
        __u16 archiveTime __attribute__((packed));
        __u32 archiverID __attribute__((packed));
-       __u16 lastAccessDate __attribute__((packed));
+       __le16 lastAccessDate __attribute__((packed));
        __u16 inheritanceGrantMask __attribute__((packed));
        __u16 inheritanceRevokeMask __attribute__((packed));
        __u32 maximumSpace __attribute__((packed));
index 009dd38..415be1e 100644 (file)
  * all the information we need to work with an inode after creation.
  */
 struct ncp_inode_info {
-       __u32   dirEntNum;
-       __u32   DosDirNum;
-       __u32   volNumber;
-       __u32   nwattr;
+       __le32  dirEntNum;
+       __le32  DosDirNum;
+       __u   volNumber;
+       __le32  nwattr;
        struct semaphore open_sem;
        atomic_t        opened;
        int     access;
index a4523ed..f56a696 100644 (file)
@@ -2,18 +2,18 @@
 #define _NCP_NO
 
 /* these define the attribute byte as seen by NCP */
-#define aRONLY                 (ntohl(0x01000000))
-#define aHIDDEN                        (__constant_ntohl(0x02000000))
-#define aSYSTEM                        (__constant_ntohl(0x04000000))
-#define aEXECUTE               (ntohl(0x08000000))
-#define aDIR                   (ntohl(0x10000000))
-#define aARCH                  (ntohl(0x20000000))
-#define aSHARED                        (ntohl(0x80000000))
-#define aDONTSUBALLOCATE       (ntohl(1L<<(11+8)))
-#define aTRANSACTIONAL         (ntohl(1L<<(12+8)))
-#define aPURGE                 (ntohl(1L<<(16-8)))
-#define aRENAMEINHIBIT         (ntohl(1L<<(17-8)))
-#define aDELETEINHIBIT         (ntohl(1L<<(18-8)))
-#define aDONTCOMPRESS          (nothl(1L<<(27-24)))
+#define aRONLY                 (__constant_cpu_to_le32(1))
+#define aHIDDEN                        (__constant_cpu_to_le32(2))
+#define aSYSTEM                        (__constant_cpu_to_le32(4))
+#define aEXECUTE               (__constant_cpu_to_le32(8))
+#define aDIR                   (__constant_cpu_to_le32(0x10))
+#define aARCH                  (__constant_cpu_to_le32(0x20))
+#define aSHARED                        (__constant_cpu_to_le32(0x80))
+#define aDONTSUBALLOCATE       (__constant_cpu_to_le32(1L<<11))
+#define aTRANSACTIONAL         (__constant_cpu_to_le32(1L<<12))
+#define aPURGE                 (__constant_cpu_to_le32(1L<<16))
+#define aRENAMEINHIBIT         (__constant_cpu_to_le32(1L<<17))
+#define aDELETEINHIBIT         (__constant_cpu_to_le32(1L<<18))
+#define aDONTCOMPRESS          (__constant_cpu_to_le32(1L<<27))
 
 #endif /* _NCP_NO */
index b3d6c32..b9f712c 100644 (file)
@@ -49,6 +49,15 @@ struct ebt_802_3_hdr {
        } llc;
 };
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
+static inline struct ebt_802_3_hdr *ebt_802_3_hdr(const struct sk_buff *skb)
+{
+       return (struct ebt_802_3_hdr *)skb->mac.raw;
+}
+#endif
+
 struct ebt_802_3_info 
 {
        uint8_t  sap;
index 4c8b5d1..bb9b11c 100644 (file)
@@ -16,34 +16,32 @@ extern int ip_conntrack_init(void);
 extern void ip_conntrack_cleanup(void);
 
 struct ip_conntrack_protocol;
-extern struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol);
-/* Like above, but you already have conntrack read lock. */
-extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol);
-extern struct list_head protocol_list;
-
-/* Returns conntrack if it dealt with ICMP, and filled in skb->nfct */
-extern struct ip_conntrack *icmp_error_track(struct sk_buff *skb,
-                                            enum ip_conntrack_info *ctinfo,
-                                            unsigned int hooknum);
-extern int get_tuple(const struct iphdr *iph,
-                    const struct sk_buff *skb,
-                    unsigned int dataoff,
-                    struct ip_conntrack_tuple *tuple,
-                    const struct ip_conntrack_protocol *protocol);
+
+extern int
+ip_ct_get_tuple(const struct iphdr *iph,
+               const struct sk_buff *skb,
+               unsigned int dataoff,
+               struct ip_conntrack_tuple *tuple,
+               const struct ip_conntrack_protocol *protocol);
+
+extern int
+ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
+                  const struct ip_conntrack_tuple *orig,
+                  const struct ip_conntrack_protocol *protocol);
 
 /* Find a connection corresponding to a tuple. */
 struct ip_conntrack_tuple_hash *
 ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
                      const struct ip_conntrack *ignored_conntrack);
 
-extern int __ip_conntrack_confirm(struct nf_ct_info *nfct);
+extern int __ip_conntrack_confirm(struct sk_buff *skb);
 
 /* Confirm a connection: returns NF_DROP if packet must be dropped. */
 static inline int ip_conntrack_confirm(struct sk_buff *skb)
 {
        if (skb->nfct
-           && !is_confirmed((struct ip_conntrack *)skb->nfct->master))
-               return __ip_conntrack_confirm(skb->nfct);
+           && !is_confirmed((struct ip_conntrack *)skb->nfct))
+               return __ip_conntrack_confirm(skb);
        return NF_ACCEPT;
 }
 
index 677db49..2f85006 100644 (file)
@@ -4,11 +4,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/netfilter_ipv4/lockhelp.h>
-
-/* Protects ftp part of conntracks */
-DECLARE_LOCK_EXTERN(ip_ftp_lock);
-
 #define FTP_PORT       21
 
 #endif /* __KERNEL__ */
index 170248f..0cd24a0 100644 (file)
@@ -33,13 +33,8 @@ struct ip_ct_irc_master {
 
 #ifdef __KERNEL__
 
-#include <linux/netfilter_ipv4/lockhelp.h>
-
 #define IRC_PORT       6667
 
-/* Protects irc part of conntracks */
-DECLARE_LOCK_EXTERN(ip_irc_lock);
-
 #endif /* __KERNEL__ */
 
 #endif /* _IP_CONNTRACK_IRC_H */
index 56e37ef..0ff067b 100644 (file)
@@ -3,11 +3,10 @@
 #define _IP_CONNTRACK_PROTOCOL_H
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 
+struct seq_file;
+
 struct ip_conntrack_protocol
 {
-       /* Next pointer. */
-       struct list_head list;
-
        /* Protocol number. */
        u_int8_t proto;
 
@@ -26,13 +25,12 @@ struct ip_conntrack_protocol
        int (*invert_tuple)(struct ip_conntrack_tuple *inverse,
                            const struct ip_conntrack_tuple *orig);
 
-       /* Print out the per-protocol part of the tuple. */
-       unsigned int (*print_tuple)(char *buffer,
-                                   const struct ip_conntrack_tuple *);
+       /* Print out the per-protocol part of the tuple. Return like seq_* */
+       int (*print_tuple)(struct seq_file *,
+                          const struct ip_conntrack_tuple *);
 
        /* Print out the private part of the conntrack. */
-       unsigned int (*print_conntrack)(char *buffer,
-                                       const struct ip_conntrack *);
+       int (*print_conntrack)(struct seq_file *, const struct ip_conntrack *);
 
        /* Returns verdict for packet, or -1 for invalid. */
        int (*packet)(struct ip_conntrack *conntrack,
@@ -50,17 +48,46 @@ struct ip_conntrack_protocol
        int (*exp_matches_pkt)(struct ip_conntrack_expect *exp,
                               const struct sk_buff *skb);
 
+       int (*error)(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
+                    unsigned int hooknum);
+
        /* Module (if any) which this is connected to. */
        struct module *me;
 };
 
+#define MAX_IP_CT_PROTO 256
+extern struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO];
+
 /* Protocol registration. */
 extern int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto);
 extern void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto);
 
+static inline struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
+{
+       return ip_ct_protos[protocol];
+}
+
 /* Existing built-in protocols */
 extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp;
 extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
 extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp;
+extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
 extern int ip_conntrack_protocol_tcp_init(void);
+
+/* Log invalid packets */
+extern unsigned int ip_ct_log_invalid;
+
+#ifdef CONFIG_SYSCTL
+#ifdef DEBUG_INVALID_PACKETS
+#define LOG_INVALID(proto) \
+       (ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW)
+#else
+#define LOG_INVALID(proto) \
+       ((ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW) \
+        && net_ratelimit())
+#endif
+#else
+#define LOG_INVALID(proto) 0
+#endif /* CONFIG_SYSCTL */
+
 #endif /*_IP_CONNTRACK_PROTOCOL_H*/
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sctp.h b/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
new file mode 100644 (file)
index 0000000..7a8d869
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _IP_CONNTRACK_SCTP_H
+#define _IP_CONNTRACK_SCTP_H
+/* SCTP tracking. */
+
+enum sctp_conntrack {
+       SCTP_CONNTRACK_NONE,
+       SCTP_CONNTRACK_CLOSED,
+       SCTP_CONNTRACK_COOKIE_WAIT,
+       SCTP_CONNTRACK_COOKIE_ECHOED,
+       SCTP_CONNTRACK_ESTABLISHED,
+       SCTP_CONNTRACK_SHUTDOWN_SENT,
+       SCTP_CONNTRACK_SHUTDOWN_RECD,
+       SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
+       SCTP_CONNTRACK_MAX
+};
+
+struct ip_ct_sctp
+{
+       enum sctp_conntrack state;
+
+       u_int32_t vtag[IP_CT_DIR_MAX];
+       u_int32_t ttag[IP_CT_DIR_MAX];
+};
+
+#endif /* _IP_CONNTRACK_SCTP_H */
index d6698c9..0ab4590 100644 (file)
@@ -4,25 +4,44 @@
 
 enum tcp_conntrack {
        TCP_CONNTRACK_NONE,
-       TCP_CONNTRACK_ESTABLISHED,
        TCP_CONNTRACK_SYN_SENT,
        TCP_CONNTRACK_SYN_RECV,
+       TCP_CONNTRACK_ESTABLISHED,
        TCP_CONNTRACK_FIN_WAIT,
-       TCP_CONNTRACK_TIME_WAIT,
-       TCP_CONNTRACK_CLOSE,
        TCP_CONNTRACK_CLOSE_WAIT,
        TCP_CONNTRACK_LAST_ACK,
+       TCP_CONNTRACK_TIME_WAIT,
+       TCP_CONNTRACK_CLOSE,
        TCP_CONNTRACK_LISTEN,
-       TCP_CONNTRACK_MAX
+       TCP_CONNTRACK_MAX,
+       TCP_CONNTRACK_IGNORE
+};
+
+/* Window scaling is advertised by the sender */
+#define IP_CT_TCP_STATE_FLAG_WINDOW_SCALE      0x01
+
+/* SACK is permitted by the sender */
+#define IP_CT_TCP_FLAG_SACK_PERM               0x02
+
+struct ip_ct_tcp_state {
+       u_int32_t       td_end;         /* max of seq + len */
+       u_int32_t       td_maxend;      /* max of ack + max(win, 1) */
+       u_int32_t       td_maxwin;      /* max(win) */
+       u_int8_t        td_scale;       /* window scale factor */
+       u_int8_t        loose;          /* used when connection picked up from the middle */
+       u_int8_t        flags;          /* per direction state flags */
 };
 
 struct ip_ct_tcp
 {
-       enum tcp_conntrack state;
-
-       /* Poor man's window tracking: sequence number of valid ACK
-           handshake completion packet */
-       u_int32_t handshake_ack;
+       struct ip_ct_tcp_state seen[2]; /* connection parameters per direction */
+       u_int8_t        state;          /* state of the connection (enum tcp_conntrack) */
+       /* For detecting stale connections */
+       u_int8_t        last_dir;       /* Direction of the last packet (enum ip_conntrack_dir) */
+       u_int8_t        retrans;        /* Number of retransmitted packets */
+       u_int8_t        last_index;     /* Index of the last packet */
+       u_int32_t       last_seq;       /* Last sequence number seen in dir */
+       u_int32_t       last_end;       /* Last seq + len */
 };
 
 #endif /* _IP_CONNTRACK_TCP_H */
index 1a4e46b..c4a3622 100644 (file)
@@ -80,27 +80,18 @@ struct ip_nat_info_manip
 /* Protects NAT hash tables, and NAT-private part of conntracks. */
 DECLARE_RWLOCK_EXTERN(ip_nat_lock);
 
-/* Hashes for by-source and IP/protocol. */
-struct ip_nat_hash
-{
-       struct list_head list;
-
-       /* conntrack we're embedded in: NULL if not in hash. */
-       struct ip_conntrack *conntrack;
-};
-
 /* The structure embedded in the conntrack structure. */
 struct ip_nat_info
 {
        /* Set to zero when conntrack created: bitmask of maniptypes */
-       int initialized;
+       u_int16_t initialized;
 
-       unsigned int num_manips;
+       u_int16_t num_manips;
 
        /* Manipulations to be done on this conntrack. */
        struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
 
-       struct ip_nat_hash bysource, byipsproto;
+       struct list_head bysource, byipsproto;
 
        /* Helper (NULL if none). */
        struct ip_nat_helper *helper;
index a8bcdc9..4f01f88 100644 (file)
@@ -14,8 +14,6 @@ extern unsigned int do_bindings(struct ip_conntrack *ct,
                                unsigned int hooknum,
                                struct sk_buff **pskb);
 
-extern struct list_head protos;
-
 extern int icmp_reply_translation(struct sk_buff **pskb,
                                  struct ip_conntrack *conntrack,
                                  unsigned int hooknum,
@@ -26,8 +24,4 @@ extern void replace_in_hashes(struct ip_conntrack *conntrack,
 extern void place_in_hashes(struct ip_conntrack *conntrack,
                            struct ip_nat_info *info);
 
-/* Built-in protocols. */
-extern struct ip_nat_protocol ip_nat_protocol_tcp;
-extern struct ip_nat_protocol ip_nat_protocol_udp;
-extern struct ip_nat_protocol ip_nat_protocol_icmp;
 #endif /* _IP_NAT_CORE_H */
index 185a24a..b34e4ce 100644 (file)
@@ -38,11 +38,15 @@ struct ip_nat_helper
                               struct ip_nat_info *info);
 };
 
-extern struct list_head helpers;
-
 extern int ip_nat_helper_register(struct ip_nat_helper *me);
 extern void ip_nat_helper_unregister(struct ip_nat_helper *me);
 
+extern struct ip_nat_helper *
+ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
+
+extern struct ip_nat_helper *
+__ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
+
 /* These return true or false. */
 extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb,
                                struct ip_conntrack *ct,
index 998ab2b..e817958 100644 (file)
@@ -9,8 +9,6 @@ struct ip_nat_range;
 
 struct ip_nat_protocol
 {
-       struct list_head list;
-
        /* Protocol name */
        const char *name;
 
@@ -47,10 +45,24 @@ struct ip_nat_protocol
                                    const struct ip_nat_range *range);
 };
 
+#define MAX_IP_NAT_PROTO 256
+extern struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO];
+
 /* Protocol registration. */
 extern int ip_nat_protocol_register(struct ip_nat_protocol *proto);
 extern void ip_nat_protocol_unregister(struct ip_nat_protocol *proto);
 
+static inline struct ip_nat_protocol *ip_nat_find_proto(u_int8_t protocol)
+{
+       return ip_nat_protos[protocol];
+}
+
+/* Built-in protocols. */
+extern struct ip_nat_protocol ip_nat_protocol_tcp;
+extern struct ip_nat_protocol ip_nat_protocol_udp;
+extern struct ip_nat_protocol ip_nat_protocol_icmp;
+extern struct ip_nat_protocol ip_nat_unknown_protocol;
+
 extern int init_protocols(void) __init;
 extern void cleanup_protocols(void);
 extern struct ip_nat_protocol *find_nat_proto(u_int16_t protonum);
diff --git a/include/linux/netfilter_ipv4/ipt_comment.h b/include/linux/netfilter_ipv4/ipt_comment.h
new file mode 100644 (file)
index 0000000..85c1123
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _IPT_COMMENT_H
+#define _IPT_COMMENT_H
+
+#define IPT_MAX_COMMENT_LEN 256
+
+struct ipt_comment_info {
+       unsigned char comment[IPT_MAX_COMMENT_LEN];
+};
+
+#endif /* _IPT_COMMENT_H */
diff --git a/include/linux/netfilter_ipv4/ipt_sctp.h b/include/linux/netfilter_ipv4/ipt_sctp.h
new file mode 100644 (file)
index 0000000..e93a9ec
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef _IPT_SCTP_H_
+#define _IPT_SCTP_H_
+
+#define IPT_SCTP_SRC_PORTS             0x01
+#define IPT_SCTP_DEST_PORTS            0x02
+#define IPT_SCTP_CHUNK_TYPES           0x04
+
+#define IPT_SCTP_VALID_FLAGS           0x07
+
+#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
+
+
+struct ipt_sctp_flag_info {
+       u_int8_t chunktype;
+       u_int8_t flag;
+       u_int8_t flag_mask;
+};
+
+#define IPT_NUM_SCTP_FLAGS     4
+
+struct ipt_sctp_info {
+       u_int16_t dpts[2];  /* Min, Max */
+       u_int16_t spts[2];  /* Min, Max */
+
+       u_int32_t chunkmap[256 / sizeof (u_int32_t)];  /* Bit mask of chunks to be matched according to RFC 2960 */
+
+#define SCTP_CHUNK_MATCH_ANY   0x01  /* Match if any of the chunk types are present */
+#define SCTP_CHUNK_MATCH_ALL   0x02  /* Match if all of the chunk types are present */
+#define SCTP_CHUNK_MATCH_ONLY  0x04  /* Match if these are the only chunk types present */
+
+       u_int32_t chunk_match_type;
+       struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
+       int flag_count;
+
+       u_int32_t flags;
+       u_int32_t invflags;
+};
+
+#define bytes(type) (sizeof(type) * 8)
+
+#define SCTP_CHUNKMAP_SET(chunkmap, type)              \
+       do {                                            \
+               chunkmap[type / bytes(u_int32_t)] |=    \
+                       1 << (type % bytes(u_int32_t)); \
+       } while (0)
+
+#define SCTP_CHUNKMAP_CLEAR(chunkmap, type)                    \
+       do {                                                    \
+               chunkmap[type / bytes(u_int32_t)] &=            \
+                       ~(1 << (type % bytes(u_int32_t)));      \
+       } while (0)
+
+#define SCTP_CHUNKMAP_IS_SET(chunkmap, type)                   \
+({                                                             \
+       (chunkmap[type / bytes (u_int32_t)] &                   \
+               (1 << (type % bytes (u_int32_t)))) ? 1: 0;      \
+})
+
+#define SCTP_CHUNKMAP_RESET(chunkmap)                          \
+       do {                                                    \
+               int i;                                          \
+               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
+                       chunkmap[i] = 0;                        \
+       } while (0)
+
+#define SCTP_CHUNKMAP_SET_ALL(chunkmap)                        \
+       do {                                                    \
+               int i;                                          \
+               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
+                       chunkmap[i] = ~0;                       \
+       } while (0)
+
+#define SCTP_CHUNKMAP_COPY(destmap, srcmap)                    \
+       do {                                                    \
+               int i;                                          \
+               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
+                       destmap[i] = srcmap[i];                 \
+       } while (0)
+
+#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap)               \
+({                                                     \
+       int i;                                          \
+       int flag = 1;                                   \
+       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
+               if (chunkmap[i]) {                      \
+                       flag = 0;                       \
+                       break;                          \
+               }                                       \
+       }                                               \
+        flag;                                          \
+})
+
+#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)             \
+({                                                     \
+       int i;                                          \
+       int flag = 1;                                   \
+       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
+               if (chunkmap[i] != ~0) {                \
+                       flag = 0;                       \
+                               break;                  \
+               }                                       \
+       }                                               \
+        flag;                                          \
+})
+
+#endif /* _IPT_SCTP_H_ */
+
index ad7d8a4..bee7a5e 100644 (file)
@@ -58,8 +58,10 @@ enum nf_ip6_hook_priorities {
        NF_IP6_PRI_FIRST = INT_MIN,
        NF_IP6_PRI_SELINUX_FIRST = -225,
        NF_IP6_PRI_CONNTRACK = -200,
+       NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
        NF_IP6_PRI_MANGLE = -150,
        NF_IP6_PRI_NAT_DST = -100,
+       NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50,
        NF_IP6_PRI_FILTER = 0,
        NF_IP6_PRI_NAT_SRC = 100,
        NF_IP6_PRI_SELINUX_LAST = 225,
diff --git a/include/linux/netfilter_ipv6/ip6t_physdev.h b/include/linux/netfilter_ipv6/ip6t_physdev.h
new file mode 100644 (file)
index 0000000..c234731
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _IP6T_PHYSDEV_H
+#define _IP6T_PHYSDEV_H
+
+#ifdef __KERNEL__
+#include <linux/if.h>
+#endif
+
+#define IP6T_PHYSDEV_OP_IN             0x01
+#define IP6T_PHYSDEV_OP_OUT            0x02
+#define IP6T_PHYSDEV_OP_BRIDGED                0x04
+#define IP6T_PHYSDEV_OP_ISIN           0x08
+#define IP6T_PHYSDEV_OP_ISOUT          0x10
+#define IP6T_PHYSDEV_OP_MASK           (0x20 - 1)
+
+struct ip6t_physdev_info {
+       char physindev[IFNAMSIZ];
+       char in_mask[IFNAMSIZ];
+       char physoutdev[IFNAMSIZ];
+       char out_mask[IFNAMSIZ];
+       u_int8_t invert;
+       u_int8_t bitmask;
+};
+
+#endif /*_IP6T_PHYSDEV_H*/
index b30265f..ca2ffa6 100644 (file)
@@ -8,6 +8,7 @@
 #define _LINUX_NFS_H
 
 #include <linux/sunrpc/msg_prot.h>
+#include <linux/string.h>
 
 #define NFS_PROGRAM    100003
 #define NFS_PORT       2049
@@ -138,6 +139,22 @@ struct nfs_fh {
        unsigned char           data[NFS_MAXFHSIZE];
 };
 
+/*
+ * Returns a zero iff the size and data fields match.
+ * Checks only "size" bytes in the data field.
+ */
+static inline int nfs_compare_fh(const struct nfs_fh *a, const struct nfs_fh *b)
+{
+       return a->size != b->size || memcmp(a->data, b->data, a->size) != 0;
+}
+
+static inline void nfs_copy_fh(struct nfs_fh *target, const struct nfs_fh *source)
+{
+       target->size = source->size;
+       memcpy(target->data, source->data, source->size);
+}
+
+
 /*
  * This is really a general kernel constant, but since nothing like
  * this is defined in the kernel headers, I have to do it here.
index 89da81c..96974ab 100644 (file)
 #ifndef _LINUX_NFS4_H
 #define _LINUX_NFS4_H
 
+#include <linux/types.h>
+#include <linux/list.h>
+
 #define NFS4_VERIFIER_SIZE     8
 #define NFS4_FHSIZE            128
+#define NFS4_MAXPATHLEN                PATH_MAX
 #define NFS4_MAXNAMLEN         NAME_MAX
 
 #define NFS4_ACCESS_READ        0x0001
 #define ACL4_SUPPORT_AUDIT_ACL 0x04
 #define ACL4_SUPPORT_ALARM_ACL 0x08
 
+#define NFS4_ACE_FILE_INHERIT_ACE             0x00000001
+#define NFS4_ACE_DIRECTORY_INHERIT_ACE        0x00000002
+#define NFS4_ACE_NO_PROPAGATE_INHERIT_ACE     0x00000004
+#define NFS4_ACE_INHERIT_ONLY_ACE             0x00000008
+#define NFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG   0x00000010
+#define NFS4_ACE_FAILED_ACCESS_ACE_FLAG       0x00000020
+#define NFS4_ACE_IDENTIFIER_GROUP             0x00000040
+#define NFS4_ACE_OWNER                        0x00000080
+#define NFS4_ACE_GROUP                        0x00000100
+#define NFS4_ACE_EVERYONE                     0x00000200
+
+#define NFS4_ACE_READ_DATA                    0x00000001
+#define NFS4_ACE_LIST_DIRECTORY               0x00000001
+#define NFS4_ACE_WRITE_DATA                   0x00000002
+#define NFS4_ACE_ADD_FILE                     0x00000002
+#define NFS4_ACE_APPEND_DATA                  0x00000004
+#define NFS4_ACE_ADD_SUBDIRECTORY             0x00000004
+#define NFS4_ACE_READ_NAMED_ATTRS             0x00000008
+#define NFS4_ACE_WRITE_NAMED_ATTRS            0x00000010
+#define NFS4_ACE_EXECUTE                      0x00000020
+#define NFS4_ACE_DELETE_CHILD                 0x00000040
+#define NFS4_ACE_READ_ATTRIBUTES              0x00000080
+#define NFS4_ACE_WRITE_ATTRIBUTES             0x00000100
+#define NFS4_ACE_DELETE                       0x00010000
+#define NFS4_ACE_READ_ACL                     0x00020000
+#define NFS4_ACE_WRITE_ACL                    0x00040000
+#define NFS4_ACE_WRITE_OWNER                  0x00080000
+#define NFS4_ACE_SYNCHRONIZE                  0x00100000
+#define NFS4_ACE_GENERIC_READ                 0x00120081
+#define NFS4_ACE_GENERIC_WRITE                0x00160106
+#define NFS4_ACE_GENERIC_EXECUTE              0x001200A0
+#define NFS4_ACE_MASK_ALL                     0x001F01FF
+
+enum nfs4_acl_whotype {
+       NFS4_ACL_WHO_NAMED = 0,
+       NFS4_ACL_WHO_OWNER,
+       NFS4_ACL_WHO_GROUP,
+       NFS4_ACL_WHO_EVERYONE,
+};
+
+struct nfs4_ace {
+       uint32_t        type;
+       uint32_t        flag;
+       uint32_t        access_mask;
+       int             whotype;
+       uid_t           who;
+       struct list_head l_ace;
+};
+
+struct nfs4_acl {
+       uint32_t        naces;
+       struct list_head ace_head;
+};
+
 typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
 typedef struct { char data[16]; } nfs4_stateid;
 
@@ -297,7 +355,7 @@ enum {
        NFSPROC4_CLNT_COMMIT,
        NFSPROC4_CLNT_OPEN,
        NFSPROC4_CLNT_OPEN_CONFIRM,
-       NFSPROC4_CLNT_OPEN_RECLAIM,
+       NFSPROC4_CLNT_OPEN_NOATTR,
        NFSPROC4_CLNT_OPEN_DOWNGRADE,
        NFSPROC4_CLNT_CLOSE,
        NFSPROC4_CLNT_SETATTR,
@@ -315,12 +373,14 @@ enum {
        NFSPROC4_CLNT_REMOVE,
        NFSPROC4_CLNT_RENAME,
        NFSPROC4_CLNT_LINK,
+       NFSPROC4_CLNT_SYMLINK,
        NFSPROC4_CLNT_CREATE,
        NFSPROC4_CLNT_PATHCONF,
        NFSPROC4_CLNT_STATFS,
        NFSPROC4_CLNT_READLINK,
        NFSPROC4_CLNT_READDIR,
        NFSPROC4_CLNT_SERVER_CAPS,
+       NFSPROC4_CLNT_DELEGRETURN,
 };
 
 #endif
diff --git a/include/linux/nfs4_acl.h b/include/linux/nfs4_acl.h
new file mode 100644 (file)
index 0000000..22aff4d
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  include/linux/nfs4_acl.c
+ *
+ *  Common NFSv4 ACL handling definitions.
+ *
+ *  Copyright (c) 2002 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Marius Aamodt Eriksen <marius@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#ifndef LINUX_NFS4_ACL_H
+#define LINUX_NFS4_ACL_H
+
+#include <linux/posix_acl.h>
+
+struct nfs4_acl *nfs4_acl_new(void);
+void nfs4_acl_free(struct nfs4_acl *);
+int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
+int nfs4_acl_get_whotype(char *, u32);
+int nfs4_acl_write_who(int who, char *p);
+int nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
+                                       uid_t who, u32 mask);
+
+#define NFS4_ACL_TYPE_DEFAULT  0x01
+#define NFS4_ACL_DIR           0x02
+#define NFS4_ACL_OWNER         0x04
+
+struct nfs4_acl *nfs4_acl_posix_to_nfsv4(struct posix_acl *,
+                               struct posix_acl *, unsigned int flags);
+int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *, struct posix_acl **,
+                               struct posix_acl **, unsigned int flags);
+
+#endif /* LINUX_NFS4_ACL_H */
index 5a4fa8d..e9a7495 100644 (file)
@@ -5,13 +5,15 @@
 #include <linux/list.h>
 #include <linux/nfs.h>
 
+struct nlm_lockowner;
+
 /*
  * NFS lock info
  */
 struct nfs_lock_info {
        u32             state;
        u32             flags;
-       struct nlm_host *host;
+       struct nlm_lockowner *owner;
 };
 
 /*
index 428355f..a43a386 100644 (file)
@@ -18,6 +18,7 @@ struct nfs_server {
        unsigned int            rpages;         /* read size (in pages) */
        unsigned int            wsize;          /* write size */
        unsigned int            wpages;         /* write size (in pages) */
+       unsigned int            wtmult;         /* server disk block size */
        unsigned int            dtsize;         /* readdir size */
        unsigned int            bsize;          /* server block size */
        unsigned int            acregmin;       /* attr cache timeouts */
index 4545871..39e4895 100644 (file)
 struct nfs_page {
        struct list_head        wb_list,        /* Defines state of page: */
                                *wb_list_head;  /*      read/write/commit */
-       struct file             *wb_file;
-       fl_owner_t              wb_lockowner;
-       struct inode            *wb_inode;
-       struct rpc_cred         *wb_cred;
-       struct nfs4_state       *wb_state;
        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 */
-       wait_queue_head_t       wb_wait;        /* wait queue */
        unsigned long           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 */
-                               wb_count;       /* reference count */
+                               wb_bytes;       /* Length of request */
+       atomic_t                wb_count;       /* reference count */
        unsigned long           wb_flags;
        struct nfs_writeverf    wb_verf;        /* Commit cookie */
 };
@@ -50,9 +45,11 @@ struct nfs_page {
 #define NFS_NEED_COMMIT(req)   (test_bit(PG_NEED_COMMIT,&(req)->wb_flags))
 #define NFS_NEED_RESCHED(req)  (test_bit(PG_NEED_RESCHED,&(req)->wb_flags))
 
-extern struct nfs_page *nfs_create_request(struct file *, struct inode *,
-                                           struct page *,
-                                           unsigned int, unsigned int);
+extern struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
+                                           struct inode *inode,
+                                           struct page *page,
+                                           unsigned int offset,
+                                           unsigned int count);
 extern void nfs_clear_request(struct nfs_page *req);
 extern void nfs_release_request(struct nfs_page *req);
 
@@ -64,8 +61,7 @@ extern        int nfs_scan_list(struct list_head *, struct list_head *,
 extern int nfs_coalesce_requests(struct list_head *, struct list_head *,
                                  unsigned int);
 extern  int nfs_wait_on_request(struct nfs_page *);
-
-extern spinlock_t nfs_wreq_lock;
+extern void nfs_unlock_request(struct nfs_page *req);
 
 /*
  * Lock the page of an asynchronous request without incrementing the wb_count
@@ -86,23 +82,10 @@ nfs_lock_request(struct nfs_page *req)
 {
        if (test_and_set_bit(PG_BUSY, &req->wb_flags))
                return 0;
-       req->wb_count++;
+       atomic_inc(&req->wb_count);
        return 1;
 }
 
-static inline void
-nfs_unlock_request(struct nfs_page *req)
-{
-       if (!NFS_WBACK_BUSY(req)) {
-               printk(KERN_ERR "NFS: Invalid unlock attempted\n");
-               BUG();
-       }
-       smp_mb__before_clear_bit();
-       clear_bit(PG_BUSY, &req->wb_flags);
-       smp_mb__after_clear_bit();
-       wake_up_all(&req->wb_wait);
-       nfs_release_request(req);
-}
 
 /**
  * nfs_list_remove_request - Remove a request from its wb_list
index f47e3c2..f140234 100644 (file)
@@ -99,20 +99,21 @@ struct nfs4_change_info {
  * Arguments to the open call.
  */
 struct nfs_openargs {
-       struct nfs_fh *         fh;
+       const struct nfs_fh *   fh;
        __u32                   seqid;
-       __u32                   share_access;
+       int                     open_flags;
        __u64                   clientid;
        __u32                   id;
-       __u32                   opentype;
-       __u32                   createmode;
        union {
                struct iattr *  attrs;    /* UNCHECKED, GUARDED */
                nfs4_verifier   verifier; /* EXCLUSIVE */
+               nfs4_stateid    delegation;             /* CLAIM_DELEGATE_CUR */
+               int             delegation_type;        /* CLAIM_PREVIOUS */
        } u;
        const struct qstr *     name;
        const struct nfs_server *server;         /* Needed for ID mapping */
        const u32 *             bitmask;
+       __u32                   claim;
 };
 
 struct nfs_openres {
@@ -122,13 +123,17 @@ struct nfs_openres {
        __u32                   rflags;
        struct nfs_fattr *      f_attr;
        const struct nfs_server *server;
+       int                     delegation_type;
+       nfs4_stateid            delegation;
+       __u32                   do_recall;
+       __u64                   maxsize;
 };
 
 /*
  * Arguments to the open_confirm call.
  */
 struct nfs_open_confirmargs {
-       struct nfs_fh *         fh;
+       const struct nfs_fh *   fh;
        nfs4_stateid            stateid;
        __u32                   seqid;
 };
@@ -137,19 +142,6 @@ struct nfs_open_confirmres {
        nfs4_stateid            stateid;
 };
 
-/*
- * Arguments to the open_reclaim call.
- */
-struct nfs_open_reclaimargs {
-       struct nfs_fh *         fh;
-       __u64                   clientid;
-       __u32                   seqid;
-       __u32                   id;
-       __u32                   share_access;
-       __u32                   claim;
-       const __u32 *           bitmask;
-};
-
 /*
  * Arguments to the close call.
  */
@@ -157,7 +149,7 @@ struct nfs_closeargs {
        struct nfs_fh *         fh;
        nfs4_stateid            stateid;
        __u32                   seqid;
-       __u32                   share_access;
+       int                     open_flags;
 };
 
 struct nfs_closeres {
@@ -224,6 +216,11 @@ struct nfs_lockres {
        const struct nfs_server *       server;
 };
 
+struct nfs4_delegreturnargs {
+       const struct nfs_fh *fhandle;
+       const nfs4_stateid *stateid;
+};
+
 /*
  * Arguments to the read call.
  */
@@ -235,8 +232,7 @@ struct nfs_lockres {
 
 struct nfs_readargs {
        struct nfs_fh *         fh;
-       fl_owner_t              lockowner;
-       struct nfs4_state *     state;
+       struct nfs_open_context *context;
        __u64                   offset;
        __u32                   count;
        unsigned int            pgbase;
@@ -259,8 +255,7 @@ struct nfs_readres {
 
 struct nfs_writeargs {
        struct nfs_fh *         fh;
-       fl_owner_t              lockowner;
-       struct nfs4_state *     state;
+       struct nfs_open_context *context;
        __u64                   offset;
        __u32                   count;
        enum nfs3_stable_how    stable;
@@ -366,7 +361,8 @@ struct nfs_diropok {
 
 struct nfs_readlinkargs {
        struct nfs_fh *         fh;
-       unsigned int            count;
+       unsigned int            pgbase;
+       unsigned int            pglen;
        struct page **          pages;
 };
 
@@ -460,7 +456,8 @@ struct nfs3_accessres {
 
 struct nfs3_readlinkargs {
        struct nfs_fh *         fh;
-       unsigned int            count;
+       unsigned int            pgbase;
+       unsigned int            pglen;
        struct page **          pages;
 };
 
@@ -575,7 +572,8 @@ struct nfs4_readdir_res {
 
 struct nfs4_readlink {
        const struct nfs_fh *           fh;
-       u32                             count;   /* zero-copy data */
+       unsigned int                    pgbase;
+       unsigned int                    pglen;   /* zero-copy data */
        struct page **                  pages;   /* zero-copy data */
 };
 
@@ -597,13 +595,15 @@ struct nfs4_rename_res {
 };
 
 struct nfs4_setclientid {
-       nfs4_verifier                   sc_verifier;      /* request */
-       char *                          sc_name;          /* request */
+       const nfs4_verifier *           sc_verifier;      /* request */
+       unsigned int                    sc_name_len;
+       char                            sc_name[32];      /* request */
        u32                             sc_prog;          /* request */
+       unsigned int                    sc_netid_len;
        char                            sc_netid[4];      /* request */
+       unsigned int                    sc_uaddr_len;
        char                            sc_uaddr[24];     /* request */
        u32                             sc_cb_ident;      /* request */
-       struct nfs4_client *            sc_state;         /* response */
 };
 
 struct nfs4_statfs_arg {
@@ -657,6 +657,8 @@ struct nfs_write_data {
        void (*complete) (struct nfs_write_data *, int);
 };
 
+struct nfs_access_entry;
+
 /*
  * RPC procedure vector for NFSv2/NFSv3 demuxing
  */
@@ -667,16 +669,18 @@ struct nfs_rpc_ops {
 
        int     (*getroot) (struct nfs_server *, struct nfs_fh *,
                            struct nfs_fsinfo *);
-       int     (*getattr) (struct inode *, struct nfs_fattr *);
+       int     (*getattr) (struct nfs_server *, struct nfs_fh *,
+                           struct nfs_fattr *);
        int     (*setattr) (struct dentry *, struct nfs_fattr *,
                            struct iattr *);
        int     (*lookup)  (struct inode *, struct qstr *,
                            struct nfs_fh *, struct nfs_fattr *);
-       int     (*access)  (struct inode *, struct rpc_cred *, int);
-       int     (*readlink)(struct inode *, struct page *);
-       int     (*read)    (struct nfs_read_data *, struct file *);
-       int     (*write)   (struct nfs_write_data *, struct file *);
-       int     (*commit)  (struct nfs_write_data *, struct file *);
+       int     (*access)  (struct inode *, struct nfs_access_entry *);
+       int     (*readlink)(struct inode *, struct page *, unsigned int,
+                           unsigned int);
+       int     (*read)    (struct nfs_read_data *);
+       int     (*write)   (struct nfs_write_data *);
+       int     (*commit)  (struct nfs_write_data *);
        struct inode *  (*create)  (struct inode *, struct qstr *,
                            struct iattr *, int);
        int     (*remove)  (struct inode *, struct qstr *);
@@ -708,8 +712,6 @@ struct nfs_rpc_ops {
        void    (*commit_setup) (struct nfs_write_data *, int how);
        int     (*file_open)   (struct inode *, struct file *);
        int     (*file_release) (struct inode *, struct file *);
-       void    (*request_init)(struct nfs_page *, struct file *);
-       int     (*request_compatible)(struct nfs_page *, struct file *, struct page *);
        int     (*lock)(struct file *, int, struct file_lock *);
 };
 
index 1c657d4..816c04a 100644 (file)
@@ -33,6 +33,31 @@ extern int utf8_mbstowcs(wchar_t *, const __u8 *, int);
 extern int utf8_wctomb(__u8 *, wchar_t, int);
 extern int utf8_wcstombs(__u8 *, const wchar_t *, int);
 
+static inline unsigned char nls_tolower(struct nls_table *t, unsigned char c)
+{
+       unsigned char nc = t->charset2lower[c];
+
+       return nc ? nc : c;
+}
+
+static inline unsigned char nls_toupper(struct nls_table *t, unsigned char c)
+{
+       unsigned char nc = t->charset2upper[c];
+
+       return nc ? nc : c;
+}
+
+static inline int nls_strnicmp(struct nls_table *t, const unsigned char *s1,
+               const unsigned char *s2, int len)
+{
+       while (len--) {
+               if (nls_tolower(t, *s1++) != nls_tolower(t, *s2++))
+                       return 1;
+       }
+
+       return 0;
+}
+
 #define MODULE_ALIAS_NLS(name) MODULE_ALIAS("nls_" __stringify(name))
 
 #endif /* _LINUX_NLS_H */
index 6b8d64c..6e0a697 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/cpumask.h>
 
 struct node {
-       cpumask_t cpumap;       /* Bitmap of CPUs on the Node */
        struct sys_device       sysdev;
 };
 
index 5a8775b..900d43e 100644 (file)
@@ -29,6 +29,10 @@ extern int notifier_call_chain(struct notifier_block **n, unsigned long val, voi
 #define NOTIFY_OK              0x0001          /* Suits me */
 #define NOTIFY_STOP_MASK       0x8000          /* Don't call further */
 #define NOTIFY_BAD             (NOTIFY_STOP_MASK|0x0002)       /* Bad/Veto action      */
+/*
+ * Clean way to return from the notifier and stop further calls.
+ */
+#define NOTIFY_STOP            (NOTIFY_OK|NOTIFY_STOP_MASK)
 
 /*
  *     Declared notifiers so far. I can imagine quite a few more chains
index 6aedd71..5451eb1 100644 (file)
@@ -24,8 +24,8 @@ struct percpu_data {
 
 /* 
  * Use this to get to a cpu's version of the per-cpu object allocated using
- * alloc_percpu.  If you want to get "this cpu's version", maybe you want
- * to use get_cpu_ptr... 
+ * alloc_percpu.  Non-atomic access to the current CPU's version should
+ * probably be combined with get_cpu()/put_cpu().
  */ 
 #define per_cpu_ptr(ptr, cpu)                   \
 ({                                              \
@@ -58,26 +58,4 @@ static inline void free_percpu(const void *ptr)
 #define alloc_percpu(type) \
        ((type *)(__alloc_percpu(sizeof(type), __alignof__(type))))
 
-/* 
- * Use these with alloc_percpu. If
- * 1. You want to operate on memory allocated by alloc_percpu (dereference
- *    and read/modify/write)  AND 
- * 2. You want "this cpu's version" of the object AND 
- * 3. You want to do this safely since:
- *    a. On multiprocessors, you don't want to switch between cpus after 
- *    you've read the current processor id due to preemption -- this would 
- *    take away the implicit  advantage to not have any kind of traditional 
- *    serialization for per-cpu data
- *    b. On uniprocessors, you don't want another kernel thread messing
- *    up with the same per-cpu data due to preemption
- *    
- * So, Use get_cpu_ptr to disable preemption and get pointer to the 
- * local cpu version of the per-cpu object. Use put_cpu_ptr to enable
- * preemption.  Operations on per-cpu data between get_ and put_ is
- * then considered to be safe. And ofcourse, "Thou shalt not sleep between 
- * get_cpu_ptr and put_cpu_ptr"
- */
-#define get_cpu_ptr(ptr) per_cpu_ptr(ptr, get_cpu())
-#define put_cpu_ptr(ptr) put_cpu()
-
 #endif /* __LINUX_PERCPU_H */
index a48a3ec..e6b5192 100644 (file)
@@ -245,6 +245,7 @@ struct sadb_x_nat_t_port {
 
 /* Security Association flags */
 #define SADB_SAFLAGS_PFS       1
+#define SADB_SAFLAGS_DECAP_DSCP        0x40000000
 #define SADB_SAFLAGS_NOECN     0x80000000
 
 /* Security Association states */
index 9e7213c..5b2fcb1 100644 (file)
@@ -12,34 +12,22 @@ enum pid_type
 
 struct pid
 {
+       /* Try to keep pid_chain in the same cacheline as nr for find_pid */
        int nr;
-       atomic_t count;
-       struct task_struct *task;
-       struct list_head task_list;
-       struct list_head hash_chain;
-};
-
-struct pid_link
-{
-       struct list_head pid_chain;
-       struct pid *pidptr;
-       struct pid pid;
+       struct hlist_node pid_chain;
+       /* list of pids with the same nr, only one of them is in the hash */
+       struct list_head pid_list;
 };
 
 #define pid_task(elem, type) \
-       list_entry(elem, struct task_struct, pids[type].pid_chain)
+       list_entry(elem, struct task_struct, pids[type].pid_list)
 
 /*
- * attach_pid() and link_pid() must be called with the tasklist_lock
+ * attach_pid() and detach_pid() must be called with the tasklist_lock
  * write-held.
  */
 extern int FASTCALL(attach_pid(struct task_struct *task, enum pid_type type, int nr));
 
-extern void FASTCALL(link_pid(struct task_struct *task, struct pid_link *link, struct pid *pid));
-
-/*
- * detach_pid() must be called with the tasklist_lock write-held.
- */
 extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
 
 /*
@@ -52,13 +40,16 @@ extern int alloc_pidmap(void);
 extern void FASTCALL(free_pidmap(int));
 extern void switch_exec_pids(struct task_struct *leader, struct task_struct *thread);
 
-#define for_each_task_pid(who, type, task, elem, pid)          \
-       if ((pid = find_pid(type, who)))                        \
-               for (elem = pid->task_list.next,                        \
-                       prefetch(elem->next),                           \
-                       task = pid_task(elem, type);                    \
-                       elem != &pid->task_list;                        \
-                       elem = elem->next, prefetch(elem->next),        \
-                       task = pid_task(elem, type))
+#define do_each_task_pid(who, type, task)                              \
+       if ((task = find_task_by_pid_type(type, who))) {                \
+               prefetch((task)->pids[type].pid_list.next);             \
+               do {
+
+#define while_each_task_pid(who, type, task)                           \
+               } while (task = pid_task((task)->pids[type].pid_list.next,\
+                                               type),                  \
+                       prefetch((task)->pids[type].pid_list.next),     \
+                       hlist_unhashed(&(task)->pids[type].pid_chain)); \
+       }                                                               \
 
 #endif /* _LINUX_PID_H */
index 7593cb2..a22f4a1 100644 (file)
@@ -6,24 +6,28 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/cpumask.h>
 #include <asm/errno.h>
 
-/* parse command line */
-int __init profile_setup(char * str);
+#define CPU_PROFILING  1
+#define SCHED_PROFILING        2
+
+struct proc_dir_entry;
+struct pt_regs;
 
 /* init basic kernel profiler */
 void __init profile_init(void);
-
-extern unsigned int * prof_buffer;
-extern unsigned long prof_len;
-extern unsigned long prof_shift;
-extern int prof_on;
-
+void profile_tick(int, struct pt_regs *);
+void profile_hit(int, void *);
+#ifdef CONFIG_PROC_FS
+void create_prof_cpu_mask(struct proc_dir_entry *);
+#else
+#define create_prof_cpu_mask(x)                        do { (void)(x); } while (0)
+#endif
 
 enum profile_type {
-       EXIT_TASK,
-       EXIT_MMAP,
-       EXEC_UNMAP
+       PROFILE_TASK_EXIT,
+       PROFILE_MUNMAP
 };
 
 #ifdef CONFIG_PROFILING
@@ -33,16 +37,20 @@ struct task_struct;
 struct mm_struct;
 
 /* task is in do_exit() */
-void profile_exit_task(struct task_struct * task);
+void profile_task_exit(struct task_struct * task);
 
-/* change of vma mappings */
-void profile_exec_unmap(struct mm_struct * mm);
+/* task is dead, free task struct ? Returns 1 if
+ * the task was taken, 0 if the task should be freed.
+ */
+int profile_handoff_task(struct task_struct * task);
 
-/* exit of all vmas for a task */
-void profile_exit_mmap(struct mm_struct * mm);
+/* sys_munmap */
+void profile_munmap(unsigned long addr);
 
-int profile_event_register(enum profile_type, struct notifier_block * n);
+int task_handoff_register(struct notifier_block * n);
+int task_handoff_unregister(struct notifier_block * n);
 
+int profile_event_register(enum profile_type, struct notifier_block * n);
 int profile_event_unregister(enum profile_type, struct notifier_block * n);
 
 int register_profile_notifier(struct notifier_block * nb);
@@ -55,6 +63,16 @@ void profile_hook(struct pt_regs * regs);
 
 #else
 
+static inline int task_handoff_register(struct notifier_block * n)
+{
+       return -ENOSYS;
+}
+
+static inline int task_handoff_unregister(struct notifier_block * n)
+{
+       return -ENOSYS;
+}
+
 static inline int profile_event_register(enum profile_type t, struct notifier_block * n)
 {
        return -ENOSYS;
@@ -65,9 +83,9 @@ static inline int profile_event_unregister(enum profile_type t, struct notifier_
        return -ENOSYS;
 }
 
-#define profile_exit_task(a) do { } while (0)
-#define profile_exec_unmap(a) do { } while (0)
-#define profile_exit_mmap(a) do { } while (0)
+#define profile_task_exit(a) do { } while (0)
+#define profile_handoff_task(a) (0)
+#define profile_munmap(a) do { } while (0)
 
 static inline int register_profile_notifier(struct notifier_block * nb)
 {
index 9c06e77..fad5699 100644 (file)
@@ -69,12 +69,10 @@ extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev),
 extern void md_unregister_thread (mdk_thread_t *thread);
 extern void md_wakeup_thread(mdk_thread_t *thread);
 extern void md_check_recovery(mddev_t *mddev);
-extern void md_interrupt_thread (mdk_thread_t *thread);
 extern void md_write_start(mddev_t *mddev);
 extern void md_write_end(mddev_t *mddev);
 extern void md_handle_safemode(mddev_t *mddev);
 extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
-extern void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors);
 extern void md_error (mddev_t *mddev, mdk_rdev_t *rdev);
 extern void md_unplug_mddev(mddev_t *mddev);
 
index faa400c..945346e 100644 (file)
@@ -24,7 +24,8 @@
 #define HSM               6UL
 #define MULTIPATH         7UL
 #define RAID6            8UL
-#define MAX_PERSONALITY   9UL
+#define        RAID10            9UL
+#define MAX_PERSONALITY   10UL
 
 #define        LEVEL_MULTIPATH         (-4)
 #define        LEVEL_LINEAR            (-1)
@@ -43,6 +44,7 @@ static inline int pers_to_level (int pers)
                case RAID1:             return 1;
                case RAID5:             return 5;
                case RAID6:             return 6;
+               case RAID10:            return 10;
        }
        BUG();
        return MD_RESERVED;
@@ -60,6 +62,7 @@ static inline int level_to_pers (int level)
                case 4:
                case 5: return RAID5;
                case 6: return RAID6;
+               case 10: return RAID10;
        }
        return MD_RESERVED;
 }
@@ -216,6 +219,7 @@ struct mddev_s
        unsigned long                   resync_mark;    /* a recent timestamp */
        sector_t                        resync_mark_cnt;/* blocks written at resync_mark */
 
+       sector_t                        resync_max_sectors; /* may be set by personality */
        /* recovery/resync flags 
         * NEEDED:   we might need to start a resync/recover
         * RUNNING:  a thread is running, or about to be started
@@ -263,6 +267,11 @@ static inline void rdev_dec_pending(mdk_rdev_t *rdev, mddev_t *mddev)
                set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 }
 
+static inline void md_sync_acct(struct block_device *bdev, unsigned long nr_sectors)
+{
+        atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io);
+}
+
 struct mdk_personality_s
 {
        char *name;
diff --git a/include/linux/raid/raid10.h b/include/linux/raid/raid10.h
new file mode 100644 (file)
index 0000000..6070878
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef _RAID10_H
+#define _RAID10_H
+
+#include <linux/raid/md.h>
+
+typedef struct mirror_info mirror_info_t;
+
+struct mirror_info {
+       mdk_rdev_t      *rdev;
+       sector_t        head_position;
+};
+
+typedef struct r10bio_s r10bio_t;
+
+struct r10_private_data_s {
+       mddev_t                 *mddev;
+       mirror_info_t           *mirrors;
+       int                     raid_disks;
+       int                     working_disks;
+       spinlock_t              device_lock;
+
+       /* geometry */
+       int                     near_copies;  /* number of copies layed out raid0 style */
+       int                     far_copies;   /* number of copies layed out
+                                              * at large strides across drives
+                                              */
+       int                     copies;       /* near_copies * far_copies.
+                                              * must be <= raid_disks
+                                              */
+       sector_t                stride;       /* distance between far copies.
+                                              * This is size / far_copies
+                                              */
+
+       int chunk_shift; /* shift from chunks to sectors */
+       sector_t chunk_mask;
+
+       struct list_head        retry_list;
+       /* for use when syncing mirrors: */
+
+       spinlock_t              resync_lock;
+       int nr_pending;
+       int barrier;
+       sector_t                next_resync;
+
+       wait_queue_head_t       wait_idle;
+       wait_queue_head_t       wait_resume;
+
+       mempool_t *r10bio_pool;
+       mempool_t *r10buf_pool;
+};
+
+typedef struct r10_private_data_s conf_t;
+
+/*
+ * this is the only point in the RAID code where we violate
+ * C type safety. mddev->private is an 'opaque' pointer.
+ */
+#define mddev_to_conf(mddev) ((conf_t *) mddev->private)
+
+/*
+ * this is our 'private' RAID10 bio.
+ *
+ * it contains information about what kind of IO operations were started
+ * for this RAID10 operation, and about their status:
+ */
+
+struct r10bio_s {
+       atomic_t                remaining; /* 'have we finished' count,
+                                           * used from IRQ handlers
+                                           */
+       sector_t                sector; /* virtual sector number */
+       int                     sectors;
+       unsigned long           state;
+       mddev_t                 *mddev;
+       /*
+        * original bio going to /dev/mdx
+        */
+       struct bio              *master_bio;
+       /*
+        * if the IO is in READ direction, then this is where we read
+        */
+       int                     read_slot;
+
+       struct list_head        retry_list;
+       /*
+        * if the IO is in WRITE direction, then multiple bios are used,
+        * one for each copy.
+        * When resyncing we also use one for each copy.
+        * When reconstructing, we use 2 bios, one for read, one for write.
+        * We choose the number when they are allocated.
+        */
+       struct {
+               struct bio              *bio;
+               sector_t addr;
+               int devnum;
+       } devs[0];
+};
+
+/* bits for r10bio.state */
+#define        R10BIO_Uptodate 0
+#define        R10BIO_IsSync   1
+#define        R10BIO_IsRecover 2
+#endif
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
new file mode 100644 (file)
index 0000000..e0a4faa
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _LINUX_RAMFS_H
+#define _LINUX_RAMFS_H
+
+struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev);
+struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
+        int flags, const char *dev_name, void *data);
+
+extern struct file_operations ramfs_file_operations;
+extern struct vm_operations_struct generic_file_vm_ops;
+
+#endif
index fb2088f..3ae0c6e 100644 (file)
@@ -123,6 +123,7 @@ extern void rb_erase(struct rb_node *, struct rb_root *);
 extern struct rb_node *rb_next(struct rb_node *);
 extern struct rb_node *rb_prev(struct rb_node *);
 extern struct rb_node *rb_first(struct rb_root *);
+extern struct rb_node *rb_last(struct rb_root *);
 
 /* Fast replacement of a single node without remove/rebalance/add/rebalance */
 extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 
index 8f452cb..e20bbf9 100644 (file)
 
 #define __mkw(h,l) (((h)&0x00ff)<< 8|((l)&0x00ff))
 #define __mkl(h,l) (((h)&0xffff)<<16|((l)&0xffff))
-#define __mk4(a,b,c,d) htonl(__mkl(__mkw(a,b),__mkw(c,d)))
+#define __mk4(a,b,c,d) cpu_to_be32(__mkl(__mkw(a,b),__mkw(c,d)))
 #define ROMSB_WORD0 __mk4('-','r','o','m')
 #define ROMSB_WORD1 __mk4('1','f','s','-')
 
 /* On-disk "super block" */
 
 struct romfs_super_block {
-       __u32 word0;
-       __u32 word1;
-       __u32 size;
-       __u32 checksum;
+       __be32 word0;
+       __be32 word1;
+       __be32 size;
+       __be32 checksum;
        char name[0];           /* volume name */
 };
 
 /* On disk inode */
 
 struct romfs_inode {
-       __u32 next;             /* low 4 bits see ROMFH_ */
-       __u32 spec;
-       __u32 size;
-       __u32 checksum;
+       __be32 next;            /* low 4 bits see ROMFH_ */
+       __be32 spec;
+       __be32 size;
+       __be32 checksum;
        char name[0];
 };
 
index dfa2322..b3a2cad 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LINUX_STDDEF_H
 #define _LINUX_STDDEF_H
 
+#include <linux/compiler.h>
+
 #undef NULL
 #if defined(__cplusplus)
 #define NULL 0
@@ -9,6 +11,10 @@
 #endif
 
 #undef offsetof
+#ifdef __compiler_offsetof
+#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
+#else
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
 
 #endif
index adaff41..5bff5a1 100644 (file)
 #define _LINUX_SUNRPC_AUTH_GSS_H
 
 #ifdef __KERNEL__
-#ifdef __linux__
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/gss_api.h>
-#endif
 
 #define RPC_GSS_VERSION                1
 
diff --git a/include/linux/sunrpc/gss_spkm3.h b/include/linux/sunrpc/gss_spkm3.h
new file mode 100644 (file)
index 0000000..b5c9968
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *  linux/include/linux/sunrpc/gss_spkm3.h
+ *
+ *  Copyright (c) 2000 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson   <andros@umich.edu>
+ */
+
+#include <linux/sunrpc/auth_gss.h>
+#include <linux/sunrpc/gss_err.h>
+#include <linux/sunrpc/gss_asn1.h>
+
+struct spkm3_ctx {
+       struct xdr_netobj       ctx_id; /* per message context id */
+       int                     qop;         /* negotiated qop */
+       struct xdr_netobj       mech_used;
+       unsigned int            ret_flags ;
+       unsigned int            req_flags ;
+       struct xdr_netobj       share_key;
+       int                     conf_alg;
+       struct crypto_tfm*      derived_conf_key;
+       int                     intg_alg;
+       struct crypto_tfm*      derived_integ_key;
+       int                     keyestb_alg;   /* alg used to get share_key */
+       int                     owf_alg;   /* one way function */
+};
+
+/* from openssl/objects.h */
+/* XXX need SEAL_ALG_NONE */
+#define NID_md5                4
+#define NID_dhKeyAgreement     28 
+#define NID_des_cbc            31 
+#define NID_sha1               64
+#define NID_cast5_cbc          108
+
+/* SPKM InnerContext Token types */
+
+#define SPKM_ERROR_TOK 3
+#define SPKM_MIC_TOK   4
+#define SPKM_WRAP_TOK  5
+#define SPKM_DEL_TOK   6
+
+u32 spkm3_make_token(struct spkm3_ctx *ctx, int qop_req, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
+
+u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int *qop_state, int toktype);
+
+#define CKSUMTYPE_RSA_MD5            0x0007
+
+s32 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
+                   struct xdr_netobj *cksum);
+void asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits);
+int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, 
+                   int explen);
+void spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, 
+                   unsigned char *ctxhdr, int elen, int zbit);
+void spkm3_make_mic_token(unsigned  char **tokp, int toklen, 
+                   struct xdr_netobj *mic_hdr,
+                   struct xdr_netobj *md5cksum, int md5elen, int md5zbit);
+u32 spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, 
+                   unsigned char **cksum);
index be2e6ef..6959ed0 100644 (file)
@@ -113,6 +113,7 @@ typedef void                        (*rpc_action)(struct rpc_task *);
 #define RPC_TASK_DYNAMIC       0x0080          /* task was kmalloc'ed */
 #define RPC_TASK_KILLED                0x0100          /* task was killed */
 #define RPC_TASK_SOFT          0x0200          /* Use soft timeouts */
+#define RPC_TASK_NOINTR                0x0400          /* uninterruptible task */
 
 #define RPC_IS_ASYNC(t)                ((t)->tk_flags & RPC_TASK_ASYNC)
 #define RPC_IS_SETUID(t)       ((t)->tk_flags & RPC_TASK_SETUID)
@@ -123,6 +124,7 @@ typedef void                        (*rpc_action)(struct rpc_task *);
 #define RPC_IS_ACTIVATED(t)    ((t)->tk_active)
 #define RPC_DO_CALLBACK(t)     ((t)->tk_callback != NULL)
 #define RPC_IS_SOFT(t)         ((t)->tk_flags & RPC_TASK_SOFT)
+#define RPC_TASK_UNINTERRUPTIBLE(t) ((t)->tk_flags & RPC_TASK_NOINTR)
 
 #define RPC_TASK_SLEEPING      0
 #define RPC_TASK_RUNNING       1
index 7abde58..f464260 100644 (file)
@@ -87,6 +87,14 @@ static inline u32 svc_getu32(struct kvec *iov)
        iov->iov_len -= sizeof(u32);
        return val;
 }
+
+static inline void svc_ungetu32(struct kvec *iov)
+{
+       u32 *vp = (u32 *)iov->iov_base;
+       iov->iov_base = (void *)(vp - 1);
+       iov->iov_len += sizeof(*vp);
+}
+
 static inline void svc_putu32(struct kvec *iov, u32 val)
 {
        u32 *vp = iov->iov_base + iov->iov_len;
@@ -243,6 +251,8 @@ struct svc_program {
        char *                  pg_name;        /* service name */
        char *                  pg_class;       /* class name: services sharing authentication */
        struct svc_stat *       pg_stats;       /* rpc statistics */
+       /* Override authentication. NULL means use default */
+       int                     (*pg_authenticate)(struct svc_rqst *, u32 *);
 };
 
 /*
index 4159f32..e024863 100644 (file)
@@ -8,13 +8,18 @@
 #endif
 
 
+#ifndef __KERNEL__
+typedef u16 __fs16;
+typedef u32 __fs16;
+#endif
+
 /* inode numbers are 16 bit */
-typedef u16 sysv_ino_t;
+typedef __fs16 sysv_ino_t;
 
 /* Block numbers are 24 bit, sometimes stored in 32 bit.
    On Coherent FS, they are always stored in PDP-11 manner: the least
    significant 16 bits come last. */
-typedef u32 sysv_zone_t;
+typedef __fs32 sysv_zone_t;
 
 /* 0 is non-existent */
 #define SYSV_BADBL_INO 1       /* inode of bad blocks file */
@@ -25,29 +30,29 @@ typedef u32 sysv_zone_t;
 #define XENIX_NICINOD  100     /* number of inode cache entries */
 #define XENIX_NICFREE  100     /* number of free block list chunk entries */
 struct xenix_super_block {
-       u16             s_isize; /* index of first data zone */
-       u32             s_fsize __packed2__; /* total number of zones of this fs */
+       __fs16          s_isize; /* index of first data zone */
+       __fs32          s_fsize __packed2__; /* total number of zones of this fs */
        /* the start of the free block list: */
-       u16             s_nfree;        /* number of free blocks in s_free, <= XENIX_NICFREE */
-       u32             s_free[XENIX_NICFREE]; /* first free block list chunk */
+       __fs16          s_nfree;        /* number of free blocks in s_free, <= XENIX_NICFREE */
+       sysv_zone_t     s_free[XENIX_NICFREE]; /* first free block list chunk */
        /* the cache of free inodes: */
-       u16             s_ninode; /* number of free inodes in s_inode, <= XENIX_NICINOD */
+       __fs16          s_ninode; /* number of free inodes in s_inode, <= XENIX_NICINOD */
        sysv_ino_t      s_inode[XENIX_NICINOD]; /* some free inodes */
        /* locks, not used by Linux: */
        char            s_flock;        /* lock during free block list manipulation */
        char            s_ilock;        /* lock during inode cache manipulation */
        char            s_fmod;         /* super-block modified flag */
        char            s_ronly;        /* flag whether fs is mounted read-only */
-       u32             s_time __packed2__; /* time of last super block update */
-       u32             s_tfree __packed2__; /* total number of free zones */
-       u16             s_tinode;       /* total number of free inodes */
-       s16             s_dinfo[4];     /* device information ?? */
+       __fs32          s_time __packed2__; /* time of last super block update */
+       __fs32          s_tfree __packed2__; /* total number of free zones */
+       __fs16          s_tinode;       /* total number of free inodes */
+       __fs16          s_dinfo[4];     /* device information ?? */
        char            s_fname[6];     /* file system volume name */
        char            s_fpack[6];     /* file system pack name */
        char            s_clean;        /* set to 0x46 when filesystem is properly unmounted */
        char            s_fill[371];
        s32             s_magic;        /* version of file system */
-       s32             s_type;         /* type of file system: 1 for 512 byte blocks
+       __fs32          s_type;         /* type of file system: 1 for 512 byte blocks
                                                                2 for 1024 byte blocks
                                                                3 for 2048 byte blocks */
                                                                
@@ -63,15 +68,15 @@ struct xenix_super_block {
 
 /* SystemV4 super-block data on disk */
 struct sysv4_super_block {
-       u16     s_isize;        /* index of first data zone */
+       __fs16  s_isize;        /* index of first data zone */
        u16     s_pad0;
-       u32     s_fsize;        /* total number of zones of this fs */
+       __fs32  s_fsize;        /* total number of zones of this fs */
        /* the start of the free block list: */
-       u16     s_nfree;        /* number of free blocks in s_free, <= SYSV_NICFREE */
+       __fs16  s_nfree;        /* number of free blocks in s_free, <= SYSV_NICFREE */
        u16     s_pad1;
-       u32     s_free[SYSV_NICFREE]; /* first free block list chunk */
+       sysv_zone_t     s_free[SYSV_NICFREE]; /* first free block list chunk */
        /* the cache of free inodes: */
-       u16     s_ninode;       /* number of free inodes in s_inode, <= SYSV_NICINOD */
+       __fs16  s_ninode;       /* number of free inodes in s_inode, <= SYSV_NICINOD */
        u16     s_pad2;
        sysv_ino_t     s_inode[SYSV_NICINOD]; /* some free inodes */
        /* locks, not used by Linux: */
@@ -79,45 +84,45 @@ struct sysv4_super_block {
        char    s_ilock;        /* lock during inode cache manipulation */
        char    s_fmod;         /* super-block modified flag */
        char    s_ronly;        /* flag whether fs is mounted read-only */
-       u32     s_time;         /* time of last super block update */
-       s16     s_dinfo[4];     /* device information ?? */
-       u32     s_tfree;        /* total number of free zones */
-       u16     s_tinode;       /* total number of free inodes */
+       __fs32  s_time;         /* time of last super block update */
+       __fs16  s_dinfo[4];     /* device information ?? */
+       __fs32  s_tfree;        /* total number of free zones */
+       __fs16  s_tinode;       /* total number of free inodes */
        u16     s_pad3;
        char    s_fname[6];     /* file system volume name */
        char    s_fpack[6];     /* file system pack name */
        s32     s_fill[12];
-       s32     s_state;        /* file system state: 0x7c269d38-s_time means clean */
+       __fs32  s_state;        /* file system state: 0x7c269d38-s_time means clean */
        s32     s_magic;        /* version of file system */
-       s32     s_type;         /* type of file system: 1 for 512 byte blocks
+       __fs32  s_type;         /* type of file system: 1 for 512 byte blocks
                                                                2 for 1024 byte blocks */
 };
 
 /* SystemV2 super-block data on disk */
 struct sysv2_super_block {
-       u16     s_isize;                /* index of first data zone */
-       u32     s_fsize __packed2__;    /* total number of zones of this fs */
+       __fs16  s_isize;                /* index of first data zone */
+       __fs32  s_fsize __packed2__;    /* total number of zones of this fs */
        /* the start of the free block list: */
-       u16     s_nfree;                /* number of free blocks in s_free, <= SYSV_NICFREE */
-       u32     s_free[SYSV_NICFREE];   /* first free block list chunk */
+       __fs16  s_nfree;                /* number of free blocks in s_free, <= SYSV_NICFREE */
+       sysv_zone_t s_free[SYSV_NICFREE];       /* first free block list chunk */
        /* the cache of free inodes: */
-       u16     s_ninode;               /* number of free inodes in s_inode, <= SYSV_NICINOD */
+       __fs16  s_ninode;               /* number of free inodes in s_inode, <= SYSV_NICINOD */
        sysv_ino_t     s_inode[SYSV_NICINOD]; /* some free inodes */
        /* locks, not used by Linux: */
        char    s_flock;                /* lock during free block list manipulation */
        char    s_ilock;                /* lock during inode cache manipulation */
        char    s_fmod;                 /* super-block modified flag */
        char    s_ronly;                /* flag whether fs is mounted read-only */
-       u32     s_time __packed2__;     /* time of last super block update */
-       s16     s_dinfo[4];             /* device information ?? */
-       u32     s_tfree __packed2__;    /* total number of free zones */
-       u16     s_tinode;               /* total number of free inodes */
+       __fs32  s_time __packed2__;     /* time of last super block update */
+       __fs16  s_dinfo[4];             /* device information ?? */
+       __fs32  s_tfree __packed2__;    /* total number of free zones */
+       __fs16  s_tinode;               /* total number of free inodes */
        char    s_fname[6];             /* file system volume name */
        char    s_fpack[6];             /* file system pack name */
        s32     s_fill[14];
-       s32     s_state;                /* file system state: 0xcb096f43 means clean */
+       __fs32  s_state;                /* file system state: 0xcb096f43 means clean */
        s32     s_magic;                /* version of file system */
-       s32     s_type;                 /* type of file system: 1 for 512 byte blocks
+       __fs32  s_type;                 /* type of file system: 1 for 512 byte blocks
                                                                2 for 1024 byte blocks */
 };
 
@@ -125,25 +130,25 @@ struct sysv2_super_block {
 #define V7_NICINOD     100     /* number of inode cache entries */
 #define V7_NICFREE     50      /* number of free block list chunk entries */
 struct v7_super_block {
-       u16    s_isize;        /* index of first data zone */
-       u32    s_fsize __packed2__; /* total number of zones of this fs */
+       __fs16 s_isize;        /* index of first data zone */
+       __fs32 s_fsize __packed2__; /* total number of zones of this fs */
        /* the start of the free block list: */
-       u16    s_nfree;        /* number of free blocks in s_free, <= V7_NICFREE */
-       u32    s_free[V7_NICFREE]; /* first free block list chunk */
+       __fs16 s_nfree;        /* number of free blocks in s_free, <= V7_NICFREE */
+       sysv_zone_t s_free[V7_NICFREE]; /* first free block list chunk */
        /* the cache of free inodes: */
-       u16    s_ninode;       /* number of free inodes in s_inode, <= V7_NICINOD */
+       __fs16 s_ninode;       /* number of free inodes in s_inode, <= V7_NICINOD */
        sysv_ino_t      s_inode[V7_NICINOD]; /* some free inodes */
        /* locks, not used by Linux or V7: */
        char    s_flock;        /* lock during free block list manipulation */
        char    s_ilock;        /* lock during inode cache manipulation */
        char    s_fmod;         /* super-block modified flag */
        char    s_ronly;        /* flag whether fs is mounted read-only */
-       u32     s_time __packed2__; /* time of last super block update */
+       __fs32  s_time __packed2__; /* time of last super block update */
        /* the following fields are not maintained by V7: */
-       u32     s_tfree __packed2__; /* total number of free zones */
-       u16     s_tinode;       /* total number of free inodes */
-       u16     s_m;            /* interleave factor */
-       u16     s_n;            /* interleave factor */
+       __fs32  s_tfree __packed2__; /* total number of free zones */
+       __fs16  s_tinode;       /* total number of free inodes */
+       __fs16  s_m;            /* interleave factor */
+       __fs16  s_n;            /* interleave factor */
        char    s_fname[6];     /* file system name */
        char    s_fpack[6];     /* file system pack name */
 };
@@ -152,41 +157,41 @@ struct v7_super_block {
 #define COH_NICINOD    100     /* number of inode cache entries */
 #define COH_NICFREE    64      /* number of free block list chunk entries */
 struct coh_super_block {
-       u16             s_isize;        /* index of first data zone */
-       u32             s_fsize __packed2__; /* total number of zones of this fs */
+       __fs16          s_isize;        /* index of first data zone */
+       __fs32          s_fsize __packed2__; /* total number of zones of this fs */
        /* the start of the free block list: */
-       u16 s_nfree;    /* number of free blocks in s_free, <= COH_NICFREE */
-       u32             s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
+       __fs16 s_nfree; /* number of free blocks in s_free, <= COH_NICFREE */
+       sysv_zone_t     s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
        /* the cache of free inodes: */
-       u16             s_ninode;       /* number of free inodes in s_inode, <= COH_NICINOD */
+       __fs16          s_ninode;       /* number of free inodes in s_inode, <= COH_NICINOD */
        sysv_ino_t      s_inode[COH_NICINOD]; /* some free inodes */
        /* locks, not used by Linux: */
        char            s_flock;        /* lock during free block list manipulation */
        char            s_ilock;        /* lock during inode cache manipulation */
        char            s_fmod;         /* super-block modified flag */
        char            s_ronly;        /* flag whether fs is mounted read-only */
-       u32             s_time __packed2__; /* time of last super block update */
-       u32             s_tfree __packed2__; /* total number of free zones */
-       u16             s_tinode;       /* total number of free inodes */
-       u16             s_interleave_m; /* interleave factor */
-       u16             s_interleave_n;
+       __fs32          s_time __packed2__; /* time of last super block update */
+       __fs32          s_tfree __packed2__; /* total number of free zones */
+       __fs16          s_tinode;       /* total number of free inodes */
+       __fs16          s_interleave_m; /* interleave factor */
+       __fs16          s_interleave_n;
        char            s_fname[6];     /* file system volume name */
        char            s_fpack[6];     /* file system pack name */
-       u32             s_unique;       /* zero, not used */
+       __fs32          s_unique;       /* zero, not used */
 };
 
 /* SystemV/Coherent inode data on disk */
 struct sysv_inode {
-       u16 i_mode;
-       u16 i_nlink;
-       u16 i_uid;
-       u16 i_gid;
-       u32 i_size;
+       __fs16 i_mode;
+       __fs16 i_nlink;
+       __fs16 i_uid;
+       __fs16 i_gid;
+       __fs32 i_size;
        u8  i_data[3*(10+1+1+1)];
        u8  i_gen;
-       u32 i_atime;    /* time of last access */
-       u32 i_mtime;    /* time of last modification */
-       u32 i_ctime;    /* time of creation */
+       __fs32 i_atime; /* time of last access */
+       __fs32 i_mtime; /* time of last modification */
+       __fs32 i_ctime; /* time of creation */
 };
 
 /* SystemV/Coherent directory entry on disk */
diff --git a/include/linux/tc_act/tc_gact.h b/include/linux/tc_act/tc_gact.h
new file mode 100644 (file)
index 0000000..23a03eb
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __LINUX_TC_GACT_H
+#define __LINUX_TC_GACT_H
+
+#include <linux/pkt_cls.h>
+
+#define TCA_ACT_GACT 5
+struct tc_gact
+{
+       tc_gen;
+
+};
+
+struct tc_gact_p
+{
+#define PGACT_NONE              0
+#define PGACT_NETRAND           1
+#define PGACT_DETERM            2
+#define MAX_RAND                (PGACT_DETERM + 1 )
+       __u16                 ptype;
+       __u16                 pval;
+       int                   paction;
+};
+enum
+{
+       TCA_GACT_UNSPEC,
+       TCA_GACT_TM,
+       TCA_GACT_PARMS,
+       TCA_GACT_PROB,
+       __TCA_GACT_MAX
+};
+#define TCA_GACT_MAX (__TCA_GACT_MAX - 1)
+#endif
index c9e92e0..31ef459 100644 (file)
@@ -47,6 +47,8 @@
  *      kernel PLL updated to 1994-12-13 specs (rfc-1589)
  * 1997-08-30    Ulrich Windl
  *      Added new constant NTP_PHASE_LIMIT
+ * 2004-08-12    Christoph Lameter
+ *      Reworked time interpolation logic
  */
 #ifndef _LINUX_TIMEX_H
 #define _LINUX_TIMEX_H
@@ -320,101 +322,60 @@ extern long pps_stbcnt;          /* stability limit exceeded */
 
 #ifdef CONFIG_TIME_INTERPOLATION
 
-struct time_interpolator {
-       /* cache-hot stuff first: */
-       unsigned long (*get_offset) (void);
-       void (*update) (long);
-       void (*reset) (void);
+#define TIME_SOURCE_CPU 0
+#define TIME_SOURCE_MMIO64 1
+#define TIME_SOURCE_MMIO32 2
+#define TIME_SOURCE_FUNCTION 3
+
+/* For proper operations time_interpolator clocks must run slightly slower
+ * than the standard clock since the interpolator may only correct by having
+ * time jump forward during a tick. A slower clock is usually a side effect
+ * of the integer divide of the nanoseconds in a second by the frequency.
+ * The accuracy of the division can be increased by specifying a shift.
+ * However, this may cause the clock not to be slow enough.
+ * The interpolator will self-tune the clock by slowing down if no
+ * resets occur or speeding up if the time jumps per analysis cycle
+ * become too high.
+ *
+ * Setting jitter compensates for a fluctuating timesource by comparing
+ * to the last value read from the timesource to insure that an earlier value
+ * is not returned by a later call. The price to pay
+ * for the compensation is that the timer routines are not as scalable anymore.
+ */
 
-       /* cache-cold stuff follows here: */
-       struct time_interpolator *next;
+#define INTERPOLATOR_ADJUST 65536
+#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
+
+struct time_interpolator {
+       unsigned short source;          /* time source flags */
+       unsigned char shift;            /* increases accuracy of multiply by shifting. */
+                       /* Note that bits may be lost if shift is set too high */
+       unsigned char jitter;           /* if set compensate for fluctuations */
+       unsigned nsec_per_cyc;          /* set by register_time_interpolator() */
+       void *addr;                     /* address of counter or function */
+       unsigned long offset;           /* nsec offset at last update of interpolator */
+       unsigned long last_counter;     /* counter value in units of the counter at last update */
+       unsigned long last_cycle;       /* Last timer value if TIME_SOURCE_JITTER is set */
        unsigned long frequency;        /* frequency in counts/second */
        long drift;                     /* drift in parts-per-million (or -1) */
+       unsigned long skips;            /* skips forward */
+       unsigned long ns_skipped;       /* nanoseconds skipped */
+       struct time_interpolator *next;
 };
 
-extern volatile unsigned long last_nsec_offset;
-#ifndef __HAVE_ARCH_CMPXCHG
-extern spin_lock_t last_nsec_offset_lock;
-#endif
-extern struct time_interpolator *time_interpolator;
-
 extern void register_time_interpolator(struct time_interpolator *);
 extern void unregister_time_interpolator(struct time_interpolator *);
-
-/* Called with xtime WRITE-lock acquired.  */
-static inline void
-time_interpolator_update(long delta_nsec)
-{
-       struct time_interpolator *ti = time_interpolator;
-
-       if (last_nsec_offset > 0) {
-#ifdef __HAVE_ARCH_CMPXCHG
-               unsigned long new, old;
-
-               do {
-                       old = last_nsec_offset;
-                       if (old > delta_nsec)
-                               new = old - delta_nsec;
-                       else
-                               new = 0;
-               } while (cmpxchg(&last_nsec_offset, old, new) != old);
-#else
-               /*
-                * This really hurts, because it serializes gettimeofday(), but without an
-                * atomic single-word compare-and-exchange, there isn't all that much else
-                * we can do.
-                */
-               spin_lock(&last_nsec_offset_lock);
-               {
-                       last_nsec_offset -= min(last_nsec_offset, delta_nsec);
-               }
-               spin_unlock(&last_nsec_offset_lock);
-#endif
-       }
-
-       if (ti)
-               (*ti->update)(delta_nsec);
-}
-
-/* Called with xtime WRITE-lock acquired.  */
-static inline void
-time_interpolator_reset(void)
-{
-       struct time_interpolator *ti = time_interpolator;
-
-       last_nsec_offset = 0;
-       if (ti)
-               (*ti->reset)();
-}
-
-/* Called with xtime READ-lock acquired.  */
-static inline unsigned long
-time_interpolator_get_offset(void)
-{
-       struct time_interpolator *ti = time_interpolator;
-       if (ti)
-               return (*ti->get_offset)();
-       return last_nsec_offset;
-}
+extern void time_interpolator_reset(void);
+extern unsigned long time_interpolator_resolution(void);
+extern unsigned long time_interpolator_get_offset(void);
 
 #else /* !CONFIG_TIME_INTERPOLATION */
 
-static inline void
-time_interpolator_update(long delta_nsec)
-{
-}
-
 static inline void
 time_interpolator_reset(void)
 {
 }
 
-static inline unsigned long
-time_interpolator_get_offset(void)
-{
-       return 0;
-}
-
 #endif /* !CONFIG_TIME_INTERPOLATION */
 
 #endif /* KERNEL */
index a78a177..fbaa877 100644 (file)
@@ -55,7 +55,7 @@ static inline int __next_node_with_cpus(int node)
        for (node = 0; node < numnodes; node = __next_node_with_cpus(node))
 
 #ifndef node_distance
-#define node_distance(from,to) (from != to)
+#define node_distance(from,to) ((from) != (to))
 #endif
 #ifndef PENALTY_FOR_NODE_WITH_CPUS
 #define PENALTY_FOR_NODE_WITH_CPUS     (1)
index 186a5a4..62b15a4 100644 (file)
@@ -45,7 +45,7 @@ struct udf_inode_info
 {
        struct timespec         i_crtime;
        /* Physical address of inode */
-       lb_addr                 i_location;
+       kernel_lb_addr          i_location;
        __u64                   i_unique;
        __u32                   i_lenEAttr;
        __u32                   i_lenAlloc;
index 6a21a49..7a6babe 100644 (file)
 #include <linux/stat.h>
 #include <linux/fs.h>
 
+#ifndef __KERNEL__
+typedef __u64 __fs64;
+typedef __u32 __fs32;
+typedef __u16 __fs16;
+#else
+typedef __u64 __bitwise __fs64;
+typedef __u32 __bitwise __fs32;
+typedef __u16 __bitwise __fs16;
+#endif
+
 #include <linux/ufs_fs_i.h>
 #include <linux/ufs_fs_sb.h>
 
 #define UFS_DIR_REC_LEN(name_len)      (((name_len) + 1 + 8 + UFS_DIR_ROUND) & ~UFS_DIR_ROUND)
 
 struct ufs_timeval {
-       __s32   tv_sec;
-       __s32   tv_usec;
+       __fs32  tv_sec;
+       __fs32  tv_usec;
 };
 
 struct ufs_dir_entry {
-       __u32  d_ino;                   /* inode number of this entry */
-       __u16  d_reclen;                /* length of this entry */
+       __fs32  d_ino;                  /* inode number of this entry */
+       __fs16  d_reclen;               /* length of this entry */
        union {
-               __u16   d_namlen;               /* actual length of d_name */
+               __fs16  d_namlen;               /* actual length of d_name */
                struct {
                        __u8    d_type;         /* file type */
                        __u8    d_namlen;       /* length of string in d_name */
@@ -315,92 +325,92 @@ struct ufs_dir_entry {
 };
 
 struct ufs_csum {
-       __u32   cs_ndir;        /* number of directories */
-       __u32   cs_nbfree;      /* number of free blocks */
-       __u32   cs_nifree;      /* number of free inodes */
-       __u32   cs_nffree;      /* number of free frags */
+       __fs32  cs_ndir;        /* number of directories */
+       __fs32  cs_nbfree;      /* number of free blocks */
+       __fs32  cs_nifree;      /* number of free inodes */
+       __fs32  cs_nffree;      /* number of free frags */
 };
 struct ufs2_csum_total {
-       __u64   cs_ndir;        /* number of directories */
-       __u64   cs_nbfree;      /* number of free blocks */
-       __u64   cs_nifree;      /* number of free inodes */
-       __u64   cs_nffree;      /* number of free frags */
-       __u64   cs_numclusters; /* number of free clusters */
-       __u64   cs_spare[3];    /* future expansion */
+       __fs64  cs_ndir;        /* number of directories */
+       __fs64  cs_nbfree;      /* number of free blocks */
+       __fs64  cs_nifree;      /* number of free inodes */
+       __fs64  cs_nffree;      /* number of free frags */
+       __fs64   cs_numclusters;        /* number of free clusters */
+       __fs64   cs_spare[3];   /* future expansion */
 };
 
 /*
  * This is the actual superblock, as it is laid out on the disk.
  */
 struct ufs_super_block {
-       __u32   fs_link;        /* UNUSED */
-       __u32   fs_rlink;       /* UNUSED */
-       __u32   fs_sblkno;      /* addr of super-block in filesys */
-       __u32   fs_cblkno;      /* offset of cyl-block in filesys */
-       __u32   fs_iblkno;      /* offset of inode-blocks in filesys */
-       __u32   fs_dblkno;      /* offset of first data after cg */
-       __u32   fs_cgoffset;    /* cylinder group offset in cylinder */
-       __u32   fs_cgmask;      /* used to calc mod fs_ntrak */
-       __u32   fs_time;        /* last time written -- time_t */
-       __u32   fs_size;        /* number of blocks in fs */
-       __u32   fs_dsize;       /* number of data blocks in fs */
-       __u32   fs_ncg;         /* number of cylinder groups */
-       __u32   fs_bsize;       /* size of basic blocks in fs */
-       __u32   fs_fsize;       /* size of frag blocks in fs */
-       __u32   fs_frag;        /* number of frags in a block in fs */
+       __fs32  fs_link;        /* UNUSED */
+       __fs32  fs_rlink;       /* UNUSED */
+       __fs32  fs_sblkno;      /* addr of super-block in filesys */
+       __fs32  fs_cblkno;      /* offset of cyl-block in filesys */
+       __fs32  fs_iblkno;      /* offset of inode-blocks in filesys */
+       __fs32  fs_dblkno;      /* offset of first data after cg */
+       __fs32  fs_cgoffset;    /* cylinder group offset in cylinder */
+       __fs32  fs_cgmask;      /* used to calc mod fs_ntrak */
+       __fs32  fs_time;        /* last time written -- time_t */
+       __fs32  fs_size;        /* number of blocks in fs */
+       __fs32  fs_dsize;       /* number of data blocks in fs */
+       __fs32  fs_ncg;         /* number of cylinder groups */
+       __fs32  fs_bsize;       /* size of basic blocks in fs */
+       __fs32  fs_fsize;       /* size of frag blocks in fs */
+       __fs32  fs_frag;        /* number of frags in a block in fs */
 /* these are configuration parameters */
-       __u32   fs_minfree;     /* minimum percentage of free blocks */
-       __u32   fs_rotdelay;    /* num of ms for optimal next block */
-       __u32   fs_rps;         /* disk revolutions per second */
+       __fs32  fs_minfree;     /* minimum percentage of free blocks */
+       __fs32  fs_rotdelay;    /* num of ms for optimal next block */
+       __fs32  fs_rps;         /* disk revolutions per second */
 /* these fields can be computed from the others */
-       __u32   fs_bmask;       /* ``blkoff'' calc of blk offsets */
-       __u32   fs_fmask;       /* ``fragoff'' calc of frag offsets */
-       __u32   fs_bshift;      /* ``lblkno'' calc of logical blkno */
-       __u32   fs_fshift;      /* ``numfrags'' calc number of frags */
+       __fs32  fs_bmask;       /* ``blkoff'' calc of blk offsets */
+       __fs32  fs_fmask;       /* ``fragoff'' calc of frag offsets */
+       __fs32  fs_bshift;      /* ``lblkno'' calc of logical blkno */
+       __fs32  fs_fshift;      /* ``numfrags'' calc number of frags */
 /* these are configuration parameters */
-       __u32   fs_maxcontig;   /* max number of contiguous blks */
-       __u32   fs_maxbpg;      /* max number of blks per cyl group */
+       __fs32  fs_maxcontig;   /* max number of contiguous blks */
+       __fs32  fs_maxbpg;      /* max number of blks per cyl group */
 /* these fields can be computed from the others */
-       __u32   fs_fragshift;   /* block to frag shift */
-       __u32   fs_fsbtodb;     /* fsbtodb and dbtofsb shift constant */
-       __u32   fs_sbsize;      /* actual size of super block */
-       __u32   fs_csmask;      /* csum block offset */
-       __u32   fs_csshift;     /* csum block number */
-       __u32   fs_nindir;      /* value of NINDIR */
-       __u32   fs_inopb;       /* value of INOPB */
-       __u32   fs_nspf;        /* value of NSPF */
+       __fs32  fs_fragshift;   /* block to frag shift */
+       __fs32  fs_fsbtodb;     /* fsbtodb and dbtofsb shift constant */
+       __fs32  fs_sbsize;      /* actual size of super block */
+       __fs32  fs_csmask;      /* csum block offset */
+       __fs32  fs_csshift;     /* csum block number */
+       __fs32  fs_nindir;      /* value of NINDIR */
+       __fs32  fs_inopb;       /* value of INOPB */
+       __fs32  fs_nspf;        /* value of NSPF */
 /* yet another configuration parameter */
-       __u32   fs_optim;       /* optimization preference, see below */
+       __fs32  fs_optim;       /* optimization preference, see below */
 /* these fields are derived from the hardware */
        union {
                struct {
-                       __u32   fs_npsect;      /* # sectors/track including spares */
+                       __fs32  fs_npsect;      /* # sectors/track including spares */
                } fs_sun;
                struct {
-                       __s32   fs_state;       /* file system state time stamp */
+                       __fs32  fs_state;       /* file system state time stamp */
                } fs_sunx86;
        } fs_u1;
-       __u32   fs_interleave;  /* hardware sector interleave */
-       __u32   fs_trackskew;   /* sector 0 skew, per track */
+       __fs32  fs_interleave;  /* hardware sector interleave */
+       __fs32  fs_trackskew;   /* sector 0 skew, per track */
 /* a unique id for this filesystem (currently unused and unmaintained) */
 /* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */
 /* Neither of those fields is used in the Tahoe code right now but */
 /* there could be problems if they are.                            */
-       __u32   fs_id[2];       /* file system id */
+       __fs32  fs_id[2];       /* file system id */
 /* sizes determined by number of cylinder groups and their sizes */
-       __u32   fs_csaddr;      /* blk addr of cyl grp summary area */
-       __u32   fs_cssize;      /* size of cyl grp summary area */
-       __u32   fs_cgsize;      /* cylinder group size */
+       __fs32  fs_csaddr;      /* blk addr of cyl grp summary area */
+       __fs32  fs_cssize;      /* size of cyl grp summary area */
+       __fs32  fs_cgsize;      /* cylinder group size */
 /* these fields are derived from the hardware */
-       __u32   fs_ntrak;       /* tracks per cylinder */
-       __u32   fs_nsect;       /* sectors per track */
-       __u32   fs_spc;         /* sectors per cylinder */
+       __fs32  fs_ntrak;       /* tracks per cylinder */
+       __fs32  fs_nsect;       /* sectors per track */
+       __fs32  fs_spc;         /* sectors per cylinder */
 /* this comes from the disk driver partitioning */
-       __u32   fs_ncyl;        /* cylinders in file system */
+       __fs32  fs_ncyl;        /* cylinders in file system */
 /* these fields can be computed from the others */
-       __u32   fs_cpg;         /* cylinders per group */
-       __u32   fs_ipg;         /* inodes per cylinder group */
-       __u32   fs_fpg;         /* blocks per group * fs_frag */
+       __fs32  fs_cpg;         /* cylinders per group */
+       __fs32  fs_ipg;         /* inodes per cylinder group */
+       __fs32  fs_fpg;         /* blocks per group * fs_frag */
 /* this data must be re-computed after crashes */
        struct ufs_csum fs_cstotal;     /* cylinder summary information */
 /* these fields are cleared at mount time */
@@ -411,69 +421,69 @@ struct ufs_super_block {
        union {
                struct {
                        __s8    fs_fsmnt[UFS_MAXMNTLEN];/* name mounted on */
-                       __u32   fs_cgrotor;     /* last cg searched */
-                       __u32   fs_csp[UFS_MAXCSBUFS];/*list of fs_cs info buffers */
-                       __u32   fs_maxcluster;
-                       __u32   fs_cpc;         /* cyl per cycle in postbl */
-                       __u16   fs_opostbl[16][8]; /* old rotation block list head */
+                       __fs32  fs_cgrotor;     /* last cg searched */
+                       __fs32  fs_csp[UFS_MAXCSBUFS];/*list of fs_cs info buffers */
+                       __fs32  fs_maxcluster;
+                       __fs32  fs_cpc;         /* cyl per cycle in postbl */
+                       __fs16  fs_opostbl[16][8]; /* old rotation block list head */
                } fs_u1;
                struct {
                        __s8  fs_fsmnt[UFS2_MAXMNTLEN]; /* name mounted on */
                        __u8   fs_volname[UFS2_MAXVOLLEN]; /* volume name */
-                       __u64  fs_swuid;                /* system-wide uid */
-                       __s32  fs_pad;  /* due to alignment of fs_swuid */
-                       __u32   fs_cgrotor;     /* last cg searched */
-                       __u32   fs_ocsp[UFS2_NOCSPTRS]; /*list of fs_cs info buffers */
-                       __u32   fs_contigdirs;/*# of contiguously allocated dirs */
-                       __u32   fs_csp; /* cg summary info buffer for fs_cs */
-                       __u32   fs_maxcluster;
-                       __u32   fs_active;/* used by snapshots to track fs */
-                       __s32   fs_old_cpc;     /* cyl per cycle in postbl */
-                       __s32   fs_maxbsize;/*maximum blocking factor permitted */
-                       __s64   fs_sparecon64[17];/*old rotation block list head */
-                       __s64   fs_sblockloc; /* byte offset of standard superblock */
+                       __fs64  fs_swuid;               /* system-wide uid */
+                       __fs32  fs_pad; /* due to alignment of fs_swuid */
+                       __fs32   fs_cgrotor;     /* last cg searched */
+                       __fs32   fs_ocsp[UFS2_NOCSPTRS]; /*list of fs_cs info buffers */
+                       __fs32   fs_contigdirs;/*# of contiguously allocated dirs */
+                       __fs32   fs_csp;        /* cg summary info buffer for fs_cs */
+                       __fs32   fs_maxcluster;
+                       __fs32   fs_active;/* used by snapshots to track fs */
+                       __fs32   fs_old_cpc;    /* cyl per cycle in postbl */
+                       __fs32   fs_maxbsize;/*maximum blocking factor permitted */
+                       __fs64   fs_sparecon64[17];/*old rotation block list head */
+                       __fs64   fs_sblockloc; /* byte offset of standard superblock */
                        struct  ufs2_csum_total fs_cstotal;/*cylinder summary information*/
                        struct  ufs_timeval    fs_time;         /* last time written */
-                       __s64    fs_size;               /* number of blocks in fs */
-                       __s64    fs_dsize;      /* number of data blocks in fs */
-                       __u64    fs_csaddr;     /* blk addr of cyl grp summary area */
-                       __s64    fs_pendingblocks;/* blocks in process of being freed */
-                       __s32    fs_pendinginodes;/*inodes in process of being freed */
+                       __fs64    fs_size;              /* number of blocks in fs */
+                       __fs64    fs_dsize;     /* number of data blocks in fs */
+                       __fs64   fs_csaddr;     /* blk addr of cyl grp summary area */
+                       __fs64    fs_pendingblocks;/* blocks in process of being freed */
+                       __fs32    fs_pendinginodes;/*inodes in process of being freed */
                } fs_u2;
        }  fs_u11;
        union {
                struct {
-                       __s32   fs_sparecon[53];/* reserved for future constants */
-                       __s32   fs_reclaim;
-                       __s32   fs_sparecon2[1];
-                       __s32   fs_state;       /* file system state time stamp */
-                       __u32   fs_qbmask[2];   /* ~usb_bmask */
-                       __u32   fs_qfmask[2];   /* ~usb_fmask */
+                       __fs32  fs_sparecon[53];/* reserved for future constants */
+                       __fs32  fs_reclaim;
+                       __fs32  fs_sparecon2[1];
+                       __fs32  fs_state;       /* file system state time stamp */
+                       __fs32  fs_qbmask[2];   /* ~usb_bmask */
+                       __fs32  fs_qfmask[2];   /* ~usb_fmask */
                } fs_sun;
                struct {
-                       __s32   fs_sparecon[53];/* reserved for future constants */
-                       __s32   fs_reclaim;
-                       __s32   fs_sparecon2[1];
-                       __u32   fs_npsect;      /* # sectors/track including spares */
-                       __u32   fs_qbmask[2];   /* ~usb_bmask */
-                       __u32   fs_qfmask[2];   /* ~usb_fmask */
+                       __fs32  fs_sparecon[53];/* reserved for future constants */
+                       __fs32  fs_reclaim;
+                       __fs32  fs_sparecon2[1];
+                       __fs32  fs_npsect;      /* # sectors/track including spares */
+                       __fs32  fs_qbmask[2];   /* ~usb_bmask */
+                       __fs32  fs_qfmask[2];   /* ~usb_fmask */
                } fs_sunx86;
                struct {
-                       __s32   fs_sparecon[50];/* reserved for future constants */
-                       __s32   fs_contigsumsize;/* size of cluster summary array */
-                       __s32   fs_maxsymlinklen;/* max length of an internal symlink */
-                       __s32   fs_inodefmt;    /* format of on-disk inodes */
-                       __u32   fs_maxfilesize[2];      /* max representable file size */
-                       __u32   fs_qbmask[2];   /* ~usb_bmask */
-                       __u32   fs_qfmask[2];   /* ~usb_fmask */
-                       __s32   fs_state;       /* file system state time stamp */
+                       __fs32  fs_sparecon[50];/* reserved for future constants */
+                       __fs32  fs_contigsumsize;/* size of cluster summary array */
+                       __fs32  fs_maxsymlinklen;/* max length of an internal symlink */
+                       __fs32  fs_inodefmt;    /* format of on-disk inodes */
+                       __fs32  fs_maxfilesize[2];      /* max representable file size */
+                       __fs32  fs_qbmask[2];   /* ~usb_bmask */
+                       __fs32  fs_qfmask[2];   /* ~usb_fmask */
+                       __fs32  fs_state;       /* file system state time stamp */
                } fs_44;
        } fs_u2;
-       __s32   fs_postblformat;        /* format of positional layout tables */
-       __s32   fs_nrpos;               /* number of rotational positions */
-       __s32   fs_postbloff;           /* (__s16) rotation block list head */
-       __s32   fs_rotbloff;            /* (__u8) blocks for each rotation */
-       __s32   fs_magic;               /* magic number */
+       __fs32  fs_postblformat;        /* format of positional layout tables */
+       __fs32  fs_nrpos;               /* number of rotational positions */
+       __fs32  fs_postbloff;           /* (__s16) rotation block list head */
+       __fs32  fs_rotbloff;            /* (__u8) blocks for each rotation */
+       __fs32  fs_magic;               /* magic number */
        __u8    fs_space[1];            /* list of blocks for each rotation */
 };
 
@@ -509,41 +519,41 @@ struct ufs_super_block {
  * size of this structure is 172 B
  */
 struct ufs_cylinder_group {
-       __u32   cg_link;                /* linked list of cyl groups */
-       __u32   cg_magic;               /* magic number */
-       __u32   cg_time;                /* time last written */
-       __u32   cg_cgx;                 /* we are the cgx'th cylinder group */
-       __u16   cg_ncyl;                /* number of cyl's this cg */
-       __u16   cg_niblk;               /* number of inode blocks this cg */
-       __u32   cg_ndblk;               /* number of data blocks this cg */
+       __fs32  cg_link;                /* linked list of cyl groups */
+       __fs32  cg_magic;               /* magic number */
+       __fs32  cg_time;                /* time last written */
+       __fs32  cg_cgx;                 /* we are the cgx'th cylinder group */
+       __fs16  cg_ncyl;                /* number of cyl's this cg */
+       __fs16  cg_niblk;               /* number of inode blocks this cg */
+       __fs32  cg_ndblk;               /* number of data blocks this cg */
        struct  ufs_csum cg_cs;         /* cylinder summary information */
-       __u32   cg_rotor;               /* position of last used block */
-       __u32   cg_frotor;              /* position of last used frag */
-       __u32   cg_irotor;              /* position of last used inode */
-       __u32   cg_frsum[UFS_MAXFRAG];  /* counts of available frags */
-       __u32   cg_btotoff;             /* (__u32) block totals per cylinder */
-       __u32   cg_boff;                /* (short) free block positions */
-       __u32   cg_iusedoff;            /* (char) used inode map */
-       __u32   cg_freeoff;             /* (u_char) free block map */
-       __u32   cg_nextfreeoff;         /* (u_char) next available space */
+       __fs32  cg_rotor;               /* position of last used block */
+       __fs32  cg_frotor;              /* position of last used frag */
+       __fs32  cg_irotor;              /* position of last used inode */
+       __fs32  cg_frsum[UFS_MAXFRAG];  /* counts of available frags */
+       __fs32  cg_btotoff;             /* (__u32) block totals per cylinder */
+       __fs32  cg_boff;                /* (short) free block positions */
+       __fs32  cg_iusedoff;            /* (char) used inode map */
+       __fs32  cg_freeoff;             /* (u_char) free block map */
+       __fs32  cg_nextfreeoff;         /* (u_char) next available space */
        union {
                struct {
-                       __u32   cg_clustersumoff;       /* (u_int32) counts of avail clusters */
-                       __u32   cg_clusteroff;          /* (u_int8) free cluster map */
-                       __u32   cg_nclusterblks;        /* number of clusters this cg */
-                       __u32   cg_sparecon[13];        /* reserved for future use */
+                       __fs32  cg_clustersumoff;       /* (u_int32) counts of avail clusters */
+                       __fs32  cg_clusteroff;          /* (u_int8) free cluster map */
+                       __fs32  cg_nclusterblks;        /* number of clusters this cg */
+                       __fs32  cg_sparecon[13];        /* reserved for future use */
                } cg_44;
                struct {
-                       __u32   cg_clustersumoff;/* (u_int32) counts of avail clusters */
-                       __u32   cg_clusteroff;  /* (u_int8) free cluster map */
-                       __u32   cg_nclusterblks;/* number of clusters this cg */
-                       __u32   cg_niblk; /* number of inode blocks this cg */
-                       __u32   cg_initediblk;  /* last initialized inode */
-                       __u32   cg_sparecon32[3];/* reserved for future use */
-                       __u64   cg_time;        /* time last written */
-                       __u64   cg_sparecon[3]; /* reserved for future use */
+                       __fs32  cg_clustersumoff;/* (u_int32) counts of avail clusters */
+                       __fs32  cg_clusteroff;  /* (u_int8) free cluster map */
+                       __fs32  cg_nclusterblks;/* number of clusters this cg */
+                       __fs32   cg_niblk; /* number of inode blocks this cg */
+                       __fs32   cg_initediblk; /* last initialized inode */
+                       __fs32   cg_sparecon32[3];/* reserved for future use */
+                       __fs64   cg_time;       /* time last written */
+                       __fs64  cg_sparecon[3]; /* reserved for future use */
                } cg_u2;
-               __u32   cg_sparecon[16];        /* reserved for future use */
+               __fs32  cg_sparecon[16];        /* reserved for future use */
        } cg_u;
        __u8    cg_space[1];            /* space for cylinder group maps */
 /* actually longer */
@@ -553,82 +563,82 @@ struct    ufs_cylinder_group {
  * structure of an on-disk inode
  */
 struct ufs_inode {
-       __u16   ui_mode;                /*  0x0 */
-       __u16   ui_nlink;               /*  0x2 */
+       __fs16  ui_mode;                /*  0x0 */
+       __fs16  ui_nlink;               /*  0x2 */
        union {
                struct {
-                       __u16   ui_suid;        /*  0x4 */
-                       __u16   ui_sgid;        /*  0x6 */
+                       __fs16  ui_suid;        /*  0x4 */
+                       __fs16  ui_sgid;        /*  0x6 */
                } oldids;
-               __u32   ui_inumber;             /*  0x4 lsf: inode number */
-               __u32   ui_author;              /*  0x4 GNU HURD: author */
+               __fs32  ui_inumber;             /*  0x4 lsf: inode number */
+               __fs32  ui_author;              /*  0x4 GNU HURD: author */
        } ui_u1;
-       __u64   ui_size;                /*  0x8 */
+       __fs64  ui_size;                /*  0x8 */
        struct ufs_timeval ui_atime;    /* 0x10 access */
        struct ufs_timeval ui_mtime;    /* 0x18 modification */
        struct ufs_timeval ui_ctime;    /* 0x20 creation */
        union {
                struct {
-                       __u32   ui_db[UFS_NDADDR];/* 0x28 data blocks */
-                       __u32   ui_ib[UFS_NINDIR];/* 0x58 indirect blocks */
+                       __fs32  ui_db[UFS_NDADDR];/* 0x28 data blocks */
+                       __fs32  ui_ib[UFS_NINDIR];/* 0x58 indirect blocks */
                } ui_addr;
                __u8    ui_symlink[4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */
        } ui_u2;
-       __u32   ui_flags;               /* 0x64 immutable, append-only... */
-       __u32   ui_blocks;              /* 0x68 blocks in use */
-       __u32   ui_gen;                 /* 0x6c like ext2 i_version, for NFS support */
+       __fs32  ui_flags;               /* 0x64 immutable, append-only... */
+       __fs32  ui_blocks;              /* 0x68 blocks in use */
+       __fs32  ui_gen;                 /* 0x6c like ext2 i_version, for NFS support */
        union {
                struct {
-                       __u32   ui_shadow;      /* 0x70 shadow inode with security data */
-                       __u32   ui_uid;         /* 0x74 long EFT version of uid */
-                       __u32   ui_gid;         /* 0x78 long EFT version of gid */
-                       __u32   ui_oeftflag;    /* 0x7c reserved */
+                       __fs32  ui_shadow;      /* 0x70 shadow inode with security data */
+                       __fs32  ui_uid;         /* 0x74 long EFT version of uid */
+                       __fs32  ui_gid;         /* 0x78 long EFT version of gid */
+                       __fs32  ui_oeftflag;    /* 0x7c reserved */
                } ui_sun;
                struct {
-                       __u32   ui_uid;         /* 0x70 File owner */
-                       __u32   ui_gid;         /* 0x74 File group */
-                       __s32   ui_spare[2];    /* 0x78 reserved */
+                       __fs32  ui_uid;         /* 0x70 File owner */
+                       __fs32  ui_gid;         /* 0x74 File group */
+                       __fs32  ui_spare[2];    /* 0x78 reserved */
                } ui_44;
                struct {
-                       __u32   ui_uid;         /* 0x70 */
-                       __u32   ui_gid;         /* 0x74 */
-                       __u16   ui_modeh;       /* 0x78 mode high bits */
-                       __u16   ui_spare;       /* 0x7A unused */
-                       __u32   ui_trans;       /* 0x7c filesystem translator */
+                       __fs32  ui_uid;         /* 0x70 */
+                       __fs32  ui_gid;         /* 0x74 */
+                       __fs16  ui_modeh;       /* 0x78 mode high bits */
+                       __fs16  ui_spare;       /* 0x7A unused */
+                       __fs32  ui_trans;       /* 0x7c filesystem translator */
                } ui_hurd;
        } ui_u3;
 };
 
 #define UFS_NXADDR  2            /* External addresses in inode. */
 struct ufs2_inode {
-       __u16     ui_mode;        /*   0: IFMT, permissions; see below. */
-       __s16     ui_nlink;       /*   2: File link count. */
-       __u32     ui_uid;         /*   4: File owner. */
-       __u32     ui_gid;         /*   8: File group. */
-       __u32     ui_blksize;     /*  12: Inode blocksize. */
-       __u64     ui_size;        /*  16: File byte count. */
-       __u64     ui_blocks;      /*  24: Bytes actually held. */
+       __fs16     ui_mode;        /*   0: IFMT, permissions; see below. */
+       __fs16     ui_nlink;       /*   2: File link count. */
+       __fs32     ui_uid;         /*   4: File owner. */
+       __fs32     ui_gid;         /*   8: File group. */
+       __fs32     ui_blksize;     /*  12: Inode blocksize. */
+       __fs64     ui_size;        /*  16: File byte count. */
+       __fs64     ui_blocks;      /*  24: Bytes actually held. */
        struct ufs_timeval   ui_atime;       /*  32: Last access time. */
        struct ufs_timeval   ui_mtime;       /*  40: Last modified time. */
        struct ufs_timeval   ui_ctime;       /*  48: Last inode change time. */
        struct ufs_timeval   ui_birthtime;   /*  56: Inode creation time. */
-       __s32     ui_mtimensec;   /*  64: Last modified time. */
-       __s32     ui_atimensec;   /*  68: Last access time. */
-       __s32     ui_ctimensec;   /*  72: Last inode change time. */
-       __s32     ui_birthnsec;   /*  76: Inode creation time. */
-       __s32     ui_gen;         /*  80: Generation number. */
-       __u32     ui_kernflags;   /*  84: Kernel flags. */
-       __u32     ui_flags;       /*  88: Status flags (chflags). */
-       __s32     ui_extsize;     /*  92: External attributes block. */
-       __s64     ui_extb[UFS_NXADDR];/*  96: External attributes block. */
+       __fs32     ui_mtimensec;   /*  64: Last modified time. */
+       __fs32     ui_atimensec;   /*  68: Last access time. */
+       __fs32     ui_ctimensec;   /*  72: Last inode change time. */
+       __fs32     ui_birthnsec;   /*  76: Inode creation time. */
+       __fs32     ui_gen;         /*  80: Generation number. */
+       __fs32     ui_kernflags;   /*  84: Kernel flags. */
+       __fs32     ui_flags;       /*  88: Status flags (chflags). */
+       __fs32     ui_extsize;     /*  92: External attributes block. */
+       __fs64     ui_extb[UFS_NXADDR];/*  96: External attributes block. */
        union {
                struct {
-                       __s64     ui_db[UFS_NDADDR]; /* 112: Direct disk blocks. */
-                       __s64     ui_ib[UFS_NINDIR];/* 208: Indirect disk blocks.*/
+                       __fs64     ui_db[UFS_NDADDR]; /* 112: Direct disk blocks. */
+                       __fs64     ui_ib[UFS_NINDIR];/* 208: Indirect disk blocks.*/
                } ui_addr;
        __u8    ui_symlink[2*4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */
        } ui_u2;
-       __s64     ui_spare[3];    /* 232: Reserved; currently unused */
+       __fs64     ui_spare[3];    /* 232: Reserved; currently unused */
 };
 
 
@@ -752,60 +762,60 @@ struct ufs_sb_private_info {
  *     ufs_super_block_third   356
  */
 struct ufs_super_block_first {
-       __u32   fs_link;
-       __u32   fs_rlink;
-       __u32   fs_sblkno;
-       __u32   fs_cblkno;
-       __u32   fs_iblkno;
-       __u32   fs_dblkno;
-       __u32   fs_cgoffset;
-       __u32   fs_cgmask;
-       __u32   fs_time;
-       __u32   fs_size;
-       __u32   fs_dsize;
-       __u32   fs_ncg;
-       __u32   fs_bsize;
-       __u32   fs_fsize;
-       __u32   fs_frag;
-       __u32   fs_minfree;
-       __u32   fs_rotdelay;
-       __u32   fs_rps;
-       __u32   fs_bmask;
-       __u32   fs_fmask;
-       __u32   fs_bshift;
-       __u32   fs_fshift;
-       __u32   fs_maxcontig;
-       __u32   fs_maxbpg;
-       __u32   fs_fragshift;
-       __u32   fs_fsbtodb;
-       __u32   fs_sbsize;
-       __u32   fs_csmask;
-       __u32   fs_csshift;
-       __u32   fs_nindir;
-       __u32   fs_inopb;
-       __u32   fs_nspf;
-       __u32   fs_optim;
+       __fs32  fs_link;
+       __fs32  fs_rlink;
+       __fs32  fs_sblkno;
+       __fs32  fs_cblkno;
+       __fs32  fs_iblkno;
+       __fs32  fs_dblkno;
+       __fs32  fs_cgoffset;
+       __fs32  fs_cgmask;
+       __fs32  fs_time;
+       __fs32  fs_size;
+       __fs32  fs_dsize;
+       __fs32  fs_ncg;
+       __fs32  fs_bsize;
+       __fs32  fs_fsize;
+       __fs32  fs_frag;
+       __fs32  fs_minfree;
+       __fs32  fs_rotdelay;
+       __fs32  fs_rps;
+       __fs32  fs_bmask;
+       __fs32  fs_fmask;
+       __fs32  fs_bshift;
+       __fs32  fs_fshift;
+       __fs32  fs_maxcontig;
+       __fs32  fs_maxbpg;
+       __fs32  fs_fragshift;
+       __fs32  fs_fsbtodb;
+       __fs32  fs_sbsize;
+       __fs32  fs_csmask;
+       __fs32  fs_csshift;
+       __fs32  fs_nindir;
+       __fs32  fs_inopb;
+       __fs32  fs_nspf;
+       __fs32  fs_optim;
        union {
                struct {
-                       __u32   fs_npsect;
+                       __fs32  fs_npsect;
                } fs_sun;
                struct {
-                       __s32   fs_state;
+                       __fs32  fs_state;
                } fs_sunx86;
        } fs_u1;
-       __u32   fs_interleave;
-       __u32   fs_trackskew;
-       __u32   fs_id[2];
-       __u32   fs_csaddr;
-       __u32   fs_cssize;
-       __u32   fs_cgsize;
-       __u32   fs_ntrak;
-       __u32   fs_nsect;
-       __u32   fs_spc;
-       __u32   fs_ncyl;
-       __u32   fs_cpg;
-       __u32   fs_ipg;
-       __u32   fs_fpg;
+       __fs32  fs_interleave;
+       __fs32  fs_trackskew;
+       __fs32  fs_id[2];
+       __fs32  fs_csaddr;
+       __fs32  fs_cssize;
+       __fs32  fs_cgsize;
+       __fs32  fs_ntrak;
+       __fs32  fs_nsect;
+       __fs32  fs_spc;
+       __fs32  fs_ncyl;
+       __fs32  fs_cpg;
+       __fs32  fs_ipg;
+       __fs32  fs_fpg;
        struct ufs_csum fs_cstotal;
        __s8    fs_fmod;
        __s8    fs_clean;
@@ -817,48 +827,48 @@ struct ufs_super_block_first {
 
 struct ufs_super_block_second {
        __s8    fs_fsmnt[212];
-       __u32   fs_cgrotor;
-       __u32   fs_csp[UFS_MAXCSBUFS];
-       __u32   fs_maxcluster;
-       __u32   fs_cpc;
-       __u16   fs_opostbl[82];
+       __fs32  fs_cgrotor;
+       __fs32  fs_csp[UFS_MAXCSBUFS];
+       __fs32  fs_maxcluster;
+       __fs32  fs_cpc;
+       __fs16  fs_opostbl[82];
 };     
 
 struct ufs_super_block_third {
-       __u16   fs_opostbl[46];
+       __fs16  fs_opostbl[46];
        union {
                struct {
-                       __s32   fs_sparecon[53];/* reserved for future constants */
-                       __s32   fs_reclaim;
-                       __s32   fs_sparecon2[1];
-                       __s32   fs_state;       /* file system state time stamp */
-                       __u32   fs_qbmask[2];   /* ~usb_bmask */
-                       __u32   fs_qfmask[2];   /* ~usb_fmask */
+                       __fs32  fs_sparecon[53];/* reserved for future constants */
+                       __fs32  fs_reclaim;
+                       __fs32  fs_sparecon2[1];
+                       __fs32  fs_state;       /* file system state time stamp */
+                       __fs32  fs_qbmask[2];   /* ~usb_bmask */
+                       __fs32  fs_qfmask[2];   /* ~usb_fmask */
                } fs_sun;
                struct {
-                       __s32   fs_sparecon[53];/* reserved for future constants */
-                       __s32   fs_reclaim;
-                       __s32   fs_sparecon2[1];
-                       __u32   fs_npsect;      /* # sectors/track including spares */
-                       __u32   fs_qbmask[2];   /* ~usb_bmask */
-                       __u32   fs_qfmask[2];   /* ~usb_fmask */
+                       __fs32  fs_sparecon[53];/* reserved for future constants */
+                       __fs32  fs_reclaim;
+                       __fs32  fs_sparecon2[1];
+                       __fs32  fs_npsect;      /* # sectors/track including spares */
+                       __fs32  fs_qbmask[2];   /* ~usb_bmask */
+                       __fs32  fs_qfmask[2];   /* ~usb_fmask */
                } fs_sunx86;
                struct {
-                       __s32   fs_sparecon[50];/* reserved for future constants */
-                       __s32   fs_contigsumsize;/* size of cluster summary array */
-                       __s32   fs_maxsymlinklen;/* max length of an internal symlink */
-                       __s32   fs_inodefmt;    /* format of on-disk inodes */
-                       __u32   fs_maxfilesize[2];      /* max representable file size */
-                       __u32   fs_qbmask[2];   /* ~usb_bmask */
-                       __u32   fs_qfmask[2];   /* ~usb_fmask */
-                       __s32   fs_state;       /* file system state time stamp */
+                       __fs32  fs_sparecon[50];/* reserved for future constants */
+                       __fs32  fs_contigsumsize;/* size of cluster summary array */
+                       __fs32  fs_maxsymlinklen;/* max length of an internal symlink */
+                       __fs32  fs_inodefmt;    /* format of on-disk inodes */
+                       __fs32  fs_maxfilesize[2];      /* max representable file size */
+                       __fs32  fs_qbmask[2];   /* ~usb_bmask */
+                       __fs32  fs_qfmask[2];   /* ~usb_fmask */
+                       __fs32  fs_state;       /* file system state time stamp */
                } fs_44;
        } fs_u2;
-       __s32   fs_postblformat;
-       __s32   fs_nrpos;
-       __s32   fs_postbloff;
-       __s32   fs_rotbloff;
-       __s32   fs_magic;
+       __fs32  fs_postblformat;
+       __fs32  fs_nrpos;
+       __fs32  fs_postbloff;
+       __fs32  fs_rotbloff;
+       __fs32  fs_magic;
        __u8    fs_space[1];
 };
 
@@ -867,7 +877,7 @@ struct ufs_super_block_third {
 /* balloc.c */
 extern void ufs_free_fragments (struct inode *, unsigned, unsigned);
 extern void ufs_free_blocks (struct inode *, unsigned, unsigned);
-extern unsigned ufs_new_fragments (struct inode *, u32 *, unsigned, unsigned, unsigned, int *);
+extern unsigned ufs_new_fragments (struct inode *, __fs32 *, unsigned, unsigned, unsigned, int *);
 
 /* cylinder.c */
 extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned);
@@ -875,7 +885,6 @@ extern void ufs_put_cylinder (struct super_block *, unsigned);
 
 /* dir.c */
 extern struct inode_operations ufs_dir_inode_operations;
-extern int ufs_check_dir_entry (const char *, struct inode *, struct ufs_dir_entry *, struct buffer_head *, unsigned long);
 extern int ufs_add_link (struct dentry *, struct inode *);
 extern ino_t ufs_inode_by_name(struct inode *, struct dentry *);
 extern int ufs_make_empty(struct inode *, struct inode *);
@@ -899,7 +908,7 @@ extern struct inode * ufs_new_inode (struct inode *, int);
 extern u64  ufs_frag_map (struct inode *, sector_t);
 extern void ufs_read_inode (struct inode *);
 extern void ufs_put_inode (struct inode *);
-extern void ufs_write_inode (struct inode *, int);
+extern int ufs_write_inode (struct inode *, int);
 extern int ufs_sync_inode (struct inode *);
 extern void ufs_delete_inode (struct inode *);
 extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *);
@@ -909,11 +918,9 @@ extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
 extern struct file_operations ufs_dir_operations;
         
 /* super.c */
-extern struct file_system_type ufs_fs_type;
 extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
-extern void ufs_write_super (struct super_block *);
 
 /* symlink.c */
 extern struct inode_operations ufs_fast_symlink_inode_operations;
index c4ef0df..21665a9 100644 (file)
@@ -15,9 +15,9 @@
 
 struct ufs_inode_info {
        union {
-               __u32   i_data[15];
+               __fs32  i_data[15];
                __u8    i_symlink[4*15];
-               __u64   u2_i_data[15];
+               __fs64  u2_i_data[15];
        } i_u1;
        __u32   i_flags;
        __u32   i_gen;
index 2eb1f55..f36ebfc 100644 (file)
@@ -110,19 +110,19 @@ DMA READ OPERATIONS.
 #define DMA_WRITE_TO_HOST 1
 
 struct mm_dma_desc {
-       u64     pci_addr;
-       u64     local_addr;
-       u32     transfer_size;
+       __le64  pci_addr;
+       __le64  local_addr;
+       __le32  transfer_size;
        u32     zero1;
-       u64     next_desc_addr;
-       u64     sem_addr;
-       u32     control_bits;
+       __le64  next_desc_addr;
+       __le64  sem_addr;
+       __le32  control_bits;
        u32     zero2;
 
        dma_addr_t data_dma_handle;
 
        /* Copy of the bits */
-       u64     sem_control_bits;
+       __le64  sem_control_bits;
 } __attribute__((aligned(8)));
 
 #define PCI_VENDOR_ID_MICRO_MEMORY             0x1332
index 2a9e19b..c1aa8d8 100644 (file)
 struct usb_ctrlrequest {
        __u8 bRequestType;
        __u8 bRequest;
-       __u16 wValue;
-       __u16 wIndex;
-       __u16 wLength;
+       __le16 wValue;
+       __le16 wIndex;
+       __le16 wLength;
 } __attribute__ ((packed));
 
 /*-------------------------------------------------------------------------*/
@@ -230,7 +230,7 @@ struct usb_string_descriptor {
        __u8  bLength;
        __u8  bDescriptorType;
 
-       __u16 wData[1];         /* UTF-16LE encoded */
+       __le16 wData[1];                /* UTF-16LE encoded */
 } __attribute__ ((packed));
 
 /* note that "string" zero is special, it holds language codes that
diff --git a/include/linux/usb_otg.h b/include/linux/usb_otg.h
new file mode 100644 (file)
index 0000000..c668314
--- /dev/null
@@ -0,0 +1,118 @@
+// include/linux/usb_otg.h 
+
+/*
+ * These APIs may be used between USB controllers.  USB device drivers
+ * (for either host or peripheral roles) don't use these calls; they
+ * continue to use just usb_device and usb_gadget.
+ */
+
+
+/* OTG defines lots of enumeration states before device reset */
+enum usb_otg_state {
+       OTG_STATE_UNDEFINED = 0,
+
+       /* single-role peripheral, and dual-role default-b */
+       OTG_STATE_B_IDLE,
+       OTG_STATE_B_SRP_INIT,
+       OTG_STATE_B_PERIPHERAL,
+
+       /* extra dual-role default-b states */
+       OTG_STATE_B_WAIT_ACON,
+       OTG_STATE_B_HOST,
+
+       /* dual-role default-a */
+       OTG_STATE_A_IDLE,
+       OTG_STATE_A_WAIT_VRISE,
+       OTG_STATE_A_WAIT_BCON,
+       OTG_STATE_A_HOST,
+       OTG_STATE_A_SUSPEND,
+       OTG_STATE_A_PERIPHERAL,
+       OTG_STATE_A_WAIT_VFALL,
+       OTG_STATE_A_VBUS_ERR,
+};
+
+/*
+ * the otg driver needs to interact with both device side and host side
+ * usb controllers.  it decides which controller is active at a given
+ * moment, using the transceiver, ID signal, HNP and sometimes static
+ * configuration information (including "board isn't wired for otg").
+ */
+struct otg_transceiver {
+       struct device           *dev;
+       const char              *label;
+
+       u8                      default_a;
+       enum usb_otg_state      state;
+
+       struct usb_bus          *host;
+       struct usb_gadget       *gadget;
+
+       /* to pass extra port status to the root hub */
+       u16                     port_status;
+       u16                     port_change;
+
+       /* bind/unbind the host controller */
+       int     (*set_host)(struct otg_transceiver *otg,
+                               struct usb_bus *host);
+
+       /* bind/unbind the peripheral controller */
+       int     (*set_peripheral)(struct otg_transceiver *otg,
+                               struct usb_gadget *gadget);
+
+       /* effective for B devices, ignored for A-peripheral */
+       int     (*set_power)(struct otg_transceiver *otg,
+                               unsigned mA);
+
+       /* for B devices only:  start session with A-Host */
+       int     (*start_srp)(struct otg_transceiver *otg);
+
+       /* start or continue HNP role switch */
+       int     (*start_hnp)(struct otg_transceiver *otg);
+
+};
+
+
+/* for board-specific init logic */
+extern int otg_set_transceiver(struct otg_transceiver *);
+
+
+/* for usb host and peripheral controller drivers */
+extern struct otg_transceiver *otg_get_transceiver(void);
+
+static inline int
+otg_start_hnp(struct otg_transceiver *otg)
+{
+       return otg->start_hnp(otg);
+}
+
+
+/* for HCDs */
+static inline int
+otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+{
+       return otg->set_host(otg, host);
+}
+
+
+/* for usb peripheral controller drivers */
+static inline int
+otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph)
+{
+       return otg->set_peripheral(otg, periph);
+}
+
+static inline int
+otg_set_power(struct otg_transceiver *otg, unsigned mA)
+{
+       return otg->set_power(otg, mA);
+}
+
+static inline int
+otg_start_srp(struct otg_transceiver *otg)
+{
+       return otg->start_srp(otg);
+}
+
+
+/* for OTG controller drivers (and maybe other stuff) */
+extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
index 50633a8..d37b664 100644 (file)
@@ -63,6 +63,8 @@ extern void FASTCALL(flush_workqueue(struct workqueue_struct *wq));
 
 extern int FASTCALL(schedule_work(struct work_struct *work));
 extern int FASTCALL(schedule_delayed_work(struct work_struct *work, unsigned long delay));
+
+extern int schedule_delayed_work_on(int cpu, struct work_struct *work, unsigned long delay);
 extern void flush_scheduled_work(void);
 extern int current_is_keventd(void);
 extern int keventd_up(void);
index 8c54bf6..93780ab 100644 (file)
@@ -769,9 +769,9 @@ do {                                                                        \
        X##_c = FP_CLS_NORMAL;                                          \
                                                                        \
        if ((X##_s = (r < 0)))                                          \
-         r = -r;                                                       \
-                                                                       \
-       ur_ = (unsigned rtype) r;                                       \
+         ur_ = (unsigned rtype) -r;                                    \
+       else                                                            \
+         ur_ = (unsigned rtype) r;                                     \
        if (rsize <= _FP_W_TYPE_SIZE)                                   \
          __FP_CLZ(X##_e, ur_);                                         \
        else                                                            \
index dca5dcf..1b0320d 100644 (file)
@@ -35,4 +35,3 @@
 #ifndef I2C_ALGO_SAA7134
 # define I2C_ALGO_SAA7134 0x090000
 #endif
-
index fb571d5..9597ffe 100644 (file)
@@ -70,6 +70,8 @@
 #define TUNER_PHILIPS_FM1236_MK3 43
 #define TUNER_PHILIPS_4IN1       44    /* ATI TV Wonder Pro - Conexant */
 #define TUNER_MICROTUNE_4049FM5  45
+#define TUNER_LG_NTSC_TAPE       47
+#define TUNER_TNF_8831BGFF       48
 
 #define NOTUNER 0
 #define PAL     1      /* PAL_BG */
@@ -88,6 +90,7 @@
 #define Samsung 7
 #define Microtune 8
 #define HITACHI 9
+#define Panasonic 10
 
 #define TUNER_SET_TYPE               _IOW('t',1,int)    /* set tuner type */
 #define TUNER_SET_TVFREQ             _IOW('t',2,int)    /* set tv freq */
 # define TUNER_SET_MODE              _IOW('t',4,int)    /* set tuner mode */
 #endif
 
+#define  TDA9887_SET_CONFIG          _IOW('t',5,int)
+/* tv card specific */
+# define TDA9887_PRESENT             (1<<0)
+# define TDA9887_PORT1               (1<<1)
+# define TDA9887_PORT2               (1<<2)
+# define TDA9887_QSS                 (1<<3)
+# define TDA9887_INTERCARRIER        (1<<4)
+/* config options */
+# define TDA9887_DEEMPHASIS_MASK     (3<<16)
+# define TDA9887_DEEMPHASIS_NONE     (1<<16)
+# define TDA9887_DEEMPHASIS_50       (2<<16)
+# define TDA9887_DEEMPHASIS_75       (3<<16)
+# define TDA9887_AUTOMUTE            (1<<18)
+
 #endif
index b0c2802..4b1eb03 100644 (file)
@@ -18,7 +18,6 @@ struct dn_neigh {
 
 extern void dn_neigh_init(void);
 extern void dn_neigh_cleanup(void);
-extern struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr);
 extern int dn_neigh_router_hello(struct sk_buff *skb);
 extern int dn_neigh_endnode_hello(struct sk_buff *skb);
 extern void dn_neigh_pointopoint_hello(struct sk_buff *skb);
diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h
new file mode 100644 (file)
index 0000000..e3ec2eb
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __NET_GEN_STATS_H
+#define __NET_GEN_STATS_H
+
+#include <linux/gen_stats.h>
+#include <linux/socket.h>
+#include <linux/rtnetlink.h>
+#include <linux/pkt_sched.h>
+
+struct gnet_dump
+{
+       spinlock_t *      lock;
+       struct sk_buff *  skb;
+       struct rtattr *   tail;
+
+       /* Backward compatability */
+       int               compat_tc_stats;
+       int               compat_xstats;
+       struct rtattr *   xstats;
+       struct tc_stats   tc_stats;
+};
+
+extern int gnet_stats_start_copy(struct sk_buff *skb, int type,
+                                spinlock_t *lock, struct gnet_dump *d);
+
+extern int gnet_stats_start_copy_compat(struct sk_buff *skb, int type,
+                                       int tc_stats_type,int xstats_type,
+                                       spinlock_t *lock, struct gnet_dump *d);
+
+extern int gnet_stats_copy_basic(struct gnet_dump *d,
+                                struct gnet_stats_basic *b);
+extern int gnet_stats_copy_rate_est(struct gnet_dump *d,
+                                   struct gnet_stats_rate_est *r);
+extern int gnet_stats_copy_queue(struct gnet_dump *d,
+                                struct gnet_stats_queue *q);
+extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
+
+extern int gnet_stats_finish_copy(struct gnet_dump *d);
+
+extern int gen_new_estimator(struct gnet_stats_basic *bstats,
+                            struct gnet_stats_rate_est *rate_est,
+                            spinlock_t *stats_lock, struct rtattr *opt);
+extern void gen_kill_estimator(struct gnet_stats_basic *bstats,
+                              struct gnet_stats_rate_est *rate_est);
+
+#endif
index 48280b1..76ce5f8 100644 (file)
@@ -51,6 +51,7 @@ struct inet6_ifaddr
        struct timer_list       timer;
 
        struct inet6_dev        *idev;
+       struct rt6_info         *rt;
 
        struct inet6_ifaddr     *lst_next;      /* next addr in addr_lst */
        struct inet6_ifaddr     *if_next;       /* next addr in inet6_dev */
@@ -133,6 +134,7 @@ struct ifacaddr6
 {
        struct in6_addr         aca_addr;
        struct inet6_dev        *aca_idev;
+       struct rt6_info         *aca_rt;
        struct ifacaddr6        *aca_next;
        int                     aca_users;
        atomic_t                aca_refcnt;
index 4b9c755..f87845e 100644 (file)
@@ -2,6 +2,7 @@
 #define _INET_ECN_H_
 
 #include <linux/ip.h>
+#include <net/dsfield.h>
 
 enum {
        INET_ECN_NOT_ECT = 0,
@@ -16,9 +17,9 @@ static inline int INET_ECN_is_ce(__u8 dsfield)
        return (dsfield & INET_ECN_MASK) == INET_ECN_CE;
 }
 
-static inline int INET_ECN_is_not_ce(__u8 dsfield)
+static inline int INET_ECN_is_not_ect(__u8 dsfield)
 {
-       return (dsfield & INET_ECN_MASK) == INET_ECN_ECT_0;
+       return (dsfield & INET_ECN_MASK) == INET_ECN_NOT_ECT;
 }
 
 static inline int INET_ECN_is_capable(__u8 dsfield)
@@ -29,8 +30,8 @@ static inline int INET_ECN_is_capable(__u8 dsfield)
 static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
 {
        outer &= ~INET_ECN_MASK;
-       if (INET_ECN_is_capable(inner))
-               outer |= (inner & INET_ECN_MASK);
+       outer |= !INET_ECN_is_ce(inner) ? (inner & INET_ECN_MASK) :
+                                         INET_ECN_ECT_0;
        return outer;
 }
 
@@ -50,7 +51,25 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
 static inline void IP_ECN_set_ce(struct iphdr *iph)
 {
        u32 check = iph->check;
-       check += __constant_htons(0xFFFE);
+       u32 ecn = (iph->tos + 1) & INET_ECN_MASK;
+
+       /*
+        * After the last operation we have (in binary):
+        * INET_ECN_NOT_ECT => 01
+        * INET_ECN_ECT_1   => 10
+        * INET_ECN_ECT_0   => 11
+        * INET_ECN_CE      => 00
+        */
+       if (!(ecn & 2))
+               return;
+
+       /*
+        * The following gives us:
+        * INET_ECN_ECT_1 => check += htons(0xFFFD)
+        * INET_ECN_ECT_0 => check += htons(0xFFFE)
+        */
+       check += htons(0xFFFB) + htons(ecn);
+
        iph->check = check + (check>=0xFFFF);
        iph->tos |= INET_ECN_CE;
 }
@@ -60,10 +79,18 @@ static inline void IP_ECN_clear(struct iphdr *iph)
        iph->tos &= ~INET_ECN_MASK;
 }
 
+static inline void ipv4_copy_dscp(struct iphdr *outer, struct iphdr *inner)
+{
+       u32 dscp = ipv4_get_dsfield(outer) & ~INET_ECN_MASK;
+       ipv4_change_dsfield(inner, INET_ECN_MASK, dscp);
+}
+
 struct ipv6hdr;
 
 static inline void IP6_ECN_set_ce(struct ipv6hdr *iph)
 {
+       if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph)))
+               return;
        *(u32*)iph |= htonl(INET_ECN_CE << 20);
 }
 
@@ -72,6 +99,10 @@ static inline void IP6_ECN_clear(struct ipv6hdr *iph)
        *(u32*)iph &= ~htonl(INET_ECN_MASK << 20);
 }
 
-#define ip6_get_dsfield(iph) ((ntohs(*(u16*)(iph)) >> 4) & 0xFF)
+static inline void ipv6_copy_dscp(struct ipv6hdr *outer, struct ipv6hdr *inner)
+{
+       u32 dscp = ipv6_get_dsfield(outer) & ~INET_ECN_MASK;
+       ipv6_change_dsfield(inner, INET_ECN_MASK, dscp);
+}
 
 #endif
index f14edaf..48a6ea4 100644 (file)
@@ -23,8 +23,7 @@
 /* WARNING: The ordering of these elements must match ordering
  *          of RTA_* rtnetlink attribute numbers.
  */
-struct kern_rta
-{
+struct kern_rta {
        void            *rta_dst;
        void            *rta_src;
        int             *rta_iif;
@@ -40,9 +39,12 @@ struct kern_rta
        struct rta_session *rta_sess;
 };
 
-struct fib_nh
-{
-       struct net_device               *nh_dev;
+struct fib_info;
+
+struct fib_nh {
+       struct net_device       *nh_dev;
+       struct hlist_node       nh_hash;
+       struct fib_info         *nh_parent;
        unsigned                nh_flags;
        unsigned char           nh_scope;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
@@ -60,10 +62,9 @@ struct fib_nh
  * This structure contains data shared by many of routes.
  */
 
-struct fib_info
-{
-       struct fib_info         *fib_next;
-       struct fib_info         *fib_prev;
+struct fib_info {
+       struct hlist_node       fib_hash;
+       struct hlist_node       fib_lhash;
        int                     fib_treeref;
        atomic_t                fib_clntref;
        int                     fib_dead;
@@ -89,8 +90,7 @@ struct fib_info
 struct fib_rule;
 #endif
 
-struct fib_result
-{
+struct fib_result {
        unsigned char   prefixlen;
        unsigned char   nh_sel;
        unsigned char   type;
@@ -119,8 +119,7 @@ struct fib_result
 #define FIB_RES_DEV(res)               (FIB_RES_NH(res).nh_dev)
 #define FIB_RES_OIF(res)               (FIB_RES_NH(res).nh_oif)
 
-struct fib_table
-{
+struct fib_table {
        unsigned char   tb_id;
        unsigned        tb_stamp;
        int             (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res);
@@ -211,22 +210,11 @@ extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
 extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res);
 
 /* Exported by fib_semantics.c */
-extern int             ip_fib_check_default(u32 gw, struct net_device *dev);
-extern void            fib_release_info(struct fib_info *);
-extern int             fib_semantic_match(int type, struct fib_info *,
-                                          const struct flowi *, struct fib_result*);
-extern struct fib_info *fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
-                                        const struct nlmsghdr *, int *err);
-extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *, struct kern_rta *rta, struct fib_info *fi);
-extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-                        u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
-                        struct fib_info *fi);
+extern int ip_fib_check_default(u32 gw, struct net_device *dev);
 extern int fib_sync_down(u32 local, struct net_device *dev, int force);
 extern int fib_sync_up(struct net_device *dev);
 extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
                               struct kern_rta *rta, struct rtentry *r);
-extern void fib_node_seq_show(struct seq_file *seq, int type, int dead,
-                             struct fib_info *fi, u32 prefix, u32 mask);
 extern u32  __fib_res_prefsrc(struct fib_result *res);
 
 /* Exported by fib_hash.c */
@@ -242,7 +230,6 @@ extern u32 fib_rules_map_destination(u32 daddr, struct fib_result *res);
 #ifdef CONFIG_NET_CLS_ROUTE
 extern u32 fib_rules_tclass(struct fib_result *res);
 #endif
-extern u32 fib_rules_policy(u32 saddr, struct fib_result *res, unsigned *flags);
 extern void fib_rules_init(void);
 #endif
 
index e94a648..e651a57 100644 (file)
@@ -5,8 +5,7 @@
 
 struct ipcomp_data {
        u16 threshold;
-       u8 *scratch;
-       struct crypto_tfm *tfm;
+       struct crypto_tfm **tfms;
 };
 
 #endif
index 644f9ed..cbbfc37 100644 (file)
@@ -253,9 +253,9 @@ static inline void llc_pdu_header_init(struct sk_buff *skb, u8 type,
 static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
 {
        if (skb->protocol == ntohs(ETH_P_802_2))
-               memcpy(sa, ((struct ethhdr *)skb->mac.raw)->h_source, ETH_ALEN);
+               memcpy(sa, eth_hdr(skb)->h_source, ETH_ALEN);
        else if (skb->protocol == ntohs(ETH_P_TR_802_2))
-               memcpy(sa, ((struct trh_hdr *)skb->mac.raw)->saddr, ETH_ALEN);
+               memcpy(sa, tr_hdr(skb)->saddr, ETH_ALEN);
 }
 
 /**
@@ -268,9 +268,9 @@ static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
 static inline void llc_pdu_decode_da(struct sk_buff *skb, u8 *da)
 {
        if (skb->protocol == ntohs(ETH_P_802_2))
-               memcpy(da, ((struct ethhdr *)skb->mac.raw)->h_dest, ETH_ALEN);
+               memcpy(da, eth_hdr(skb)->h_dest, ETH_ALEN);
        else if (skb->protocol == ntohs(ETH_P_TR_802_2))
-               memcpy(da, ((struct trh_hdr *)skb->mac.raw)->daddr, ETH_ALEN);
+               memcpy(da, tr_hdr(skb)->daddr, ETH_ALEN);
 }
 
 /**
@@ -347,7 +347,7 @@ static inline void llc_pdu_init_as_test_rsp(struct sk_buff *skb,
                struct llc_pdu_un *ev_pdu = llc_pdu_un_hdr(ev_skb);
                int dsize;
 
-               dsize = ntohs(((struct ethhdr *)ev_skb->mac.raw)->h_proto) - 3;
+               dsize = ntohs(eth_hdr(ev_skb)->h_proto) - 3;
                memcpy(((u8 *)pdu) + 3, ((u8 *)ev_pdu) + 3, dsize);
                skb_put(skb, dsize);
        }
index 464203b..40073cf 100644 (file)
@@ -7,6 +7,11 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *     Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
+ *
+ *     Changes:
+ *
+ *     Harald Welte:           <laforge@gnumonks.org>
+ *             - Add neighbour cache statistics like rtstat
  */
 
 /* The following flags & states are exported to user space,
 
 #include <asm/atomic.h>
 #include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/rcupdate.h>
+#include <linux/seq_file.h>
 
 #include <linux/err.h>
 #include <linux/sysctl.h>
 
-#define NUD_IN_TIMER   (NUD_INCOMPLETE|NUD_DELAY|NUD_PROBE)
+#define NUD_IN_TIMER   (NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE)
 #define NUD_VALID      (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY)
 #define NUD_CONNECTED  (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)
 
+struct neighbour;
+
 struct neigh_parms
 {
        struct neigh_parms *next;
@@ -63,6 +73,10 @@ struct neigh_parms
 
        void    *sysctl_table;
 
+       int dead;
+       atomic_t refcnt;
+       struct rcu_head rcu_head;
+
        int     base_reachable_time;
        int     retrans_time;
        int     gc_staletime;
@@ -81,12 +95,25 @@ struct neigh_parms
 
 struct neigh_statistics
 {
-       unsigned long allocs;
-       unsigned long res_failed;
-       unsigned long rcv_probes_mcast;
-       unsigned long rcv_probes_ucast;
+       unsigned long allocs;           /* number of allocated neighs */
+       unsigned long destroys;         /* number of destroyed neighs */
+       unsigned long hash_grows;       /* number of hash resizes */
+
+       unsigned long res_failed;       /* nomber of failed resolutions */
+
+       unsigned long lookups;          /* number of lookups */
+       unsigned long hits;             /* number of hits (among lookups) */
+
+       unsigned long rcv_probes_mcast; /* number of received mcast ipv6 */
+       unsigned long rcv_probes_ucast; /* number of received ucast ipv6 */
+
+       unsigned long periodic_gc_runs; /* number of periodic GC runs */
+       unsigned long forced_gc_runs;   /* number of forced GC runs */
 };
 
+#define NEIGH_CACHE_STAT_INC(tbl, field)                               \
+               (per_cpu_ptr((tbl)->stats, smp_processor_id())->field++)
+
 struct neighbour
 {
        struct neighbour        *next;
@@ -131,9 +158,6 @@ struct pneigh_entry
        u8                      key[0];
 };
 
-#define NEIGH_HASHMASK         0x1F
-#define PNEIGH_HASHMASK                0xF
-
 /*
  *     neighbour table manipulation
  */
@@ -166,22 +190,38 @@ struct neigh_table
        unsigned long           last_rand;
        struct neigh_parms      *parms_list;
        kmem_cache_t            *kmem_cachep;
-       struct neigh_statistics stats;
-       struct neighbour        *hash_buckets[NEIGH_HASHMASK+1];
-       struct pneigh_entry     *phash_buckets[PNEIGH_HASHMASK+1];
+       struct neigh_statistics *stats;
+       struct neighbour        **hash_buckets;
+       unsigned int            hash_mask;
+       __u32                   hash_rnd;
+       unsigned int            hash_chain_gc;
+       struct pneigh_entry     **phash_buckets;
+#ifdef CONFIG_PROC_FS
+       struct proc_dir_entry   *pde;
+#endif
 };
 
+/* flags for neigh_update() */
+#define NEIGH_UPDATE_F_OVERRIDE                        0x00000001
+#define NEIGH_UPDATE_F_WEAK_OVERRIDE           0x00000002
+#define NEIGH_UPDATE_F_OVERRIDE_ISROUTER       0x00000004
+#define NEIGH_UPDATE_F_ISROUTER                        0x40000000
+#define NEIGH_UPDATE_F_ADMIN                   0x80000000
+
 extern void                    neigh_table_init(struct neigh_table *tbl);
 extern int                     neigh_table_clear(struct neigh_table *tbl);
 extern struct neighbour *      neigh_lookup(struct neigh_table *tbl,
                                             const void *pkey,
                                             struct net_device *dev);
+extern struct neighbour *      neigh_lookup_nodev(struct neigh_table *tbl,
+                                                  const void *pkey);
 extern struct neighbour *      neigh_create(struct neigh_table *tbl,
                                             const void *pkey,
                                             struct net_device *dev);
 extern void                    neigh_destroy(struct neighbour *neigh);
 extern int                     __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
-extern int                     neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, int override, int arp);
+extern int                     neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, 
+                                            u32 flags);
 extern void                    neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
 extern int                     neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
 extern int                     neigh_resolve_output(struct sk_buff *skb);
@@ -193,6 +233,7 @@ extern struct neighbour     *neigh_event_ns(struct neigh_table *tbl,
 
 extern struct neigh_parms      *neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl);
 extern void                    neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms);
+extern void                    neigh_parms_destroy(struct neigh_parms *parms);
 extern unsigned long           neigh_rand_reach_time(unsigned long base);
 
 extern void                    pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
@@ -207,6 +248,24 @@ extern int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
 extern int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
 extern void neigh_app_ns(struct neighbour *n);
 
+extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
+extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
+extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *));
+
+struct neigh_seq_state {
+       struct neigh_table *tbl;
+       void *(*neigh_sub_iter)(struct neigh_seq_state *state,
+                               struct neighbour *n, loff_t *pos);
+       unsigned int bucket;
+       unsigned int flags;
+#define NEIGH_SEQ_NEIGH_ONLY   0x00000001
+#define NEIGH_SEQ_IS_PNEIGH    0x00000002
+#define NEIGH_SEQ_SKIP_NOARP   0x00000004
+};
+extern void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *, unsigned int);
+extern void *neigh_seq_next(struct seq_file *, void *, loff_t *);
+extern void neigh_seq_stop(struct seq_file *, void *);
+
 extern int                     neigh_sysctl_register(struct net_device *dev, 
                                                      struct neigh_parms *p,
                                                      int p_id, int pdev_id,
@@ -214,6 +273,23 @@ extern int                 neigh_sysctl_register(struct net_device *dev,
                                                      proc_handler *proc_handler);
 extern void                    neigh_sysctl_unregister(struct neigh_parms *p);
 
+static inline void __neigh_parms_put(struct neigh_parms *parms)
+{
+       atomic_dec(&parms->refcnt);
+}
+
+static inline void neigh_parms_put(struct neigh_parms *parms)
+{
+       if (atomic_dec_and_test(&parms->refcnt))
+               neigh_parms_destroy(parms);
+}
+
+static inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms)
+{
+       atomic_inc(&parms->refcnt);
+       return parms;
+}
+
 /*
  *     Neighbour references
  */
index 09b899d..e7e7da3 100644 (file)
@@ -212,9 +212,8 @@ tcf_hash_search(struct tc_action *a, u32 index)
        if (p != NULL) {
                a->priv = p;
                return 1;
-       } else {
-               return 0;
        }
+       return 0;
 }
 
 #ifdef CONFIG_NET_ACT_INIT
@@ -274,11 +273,11 @@ tcf_hash_create(struct tc_st *parm, struct rtattr *est, struct tc_action *a, int
 static inline struct tcf_st *
 tcf_hash_init(struct tc_st *parm, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind)
 {
-       struct tcf_st *p;
-       p = tcf_hash_check (parm,a,ovr,bind);
-       if (NULL == p) {
-               return tcf_hash_create(parm, est, a, size, ovr, bind);
-       }
+       struct tcf_st *p = tcf_hash_check (parm,a,ovr,bind);
+
+       if (!p)
+               p = tcf_hash_create(parm, est, a, size, ovr, bind);
+       return p;
 }
 
 #endif
diff --git a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h
new file mode 100644 (file)
index 0000000..8401ce1
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __NET_TC_GACT_H
+#define __NET_TC_GACT_H
+
+#include <net/pkt_sched.h>
+
+struct tcf_gact
+{
+        tca_gen(gact);
+#ifdef CONFIG_GACT_PROB
+        u16                 ptype;
+        u16                 pval;
+        int                 paction;
+#endif
+                                                                                
+};
+                                                                                
+#endif
index 0610575..38e0fed 100644 (file)
@@ -90,7 +90,7 @@ TCP_ECN_check_ce(struct tcp_opt *tp, struct sk_buff *skb)
                /* Funny extension: if ECT is not set on a segment,
                 * it is surely retransmit. It is not in ECN RFC,
                 * but Linux follows this rule. */
-               else if (!INET_ECN_is_capable((TCP_SKB_CB(skb)->flags)))
+               else if (INET_ECN_is_not_ect((TCP_SKB_CB(skb)->flags)))
                        tcp_enter_quickack_mode(tp);
        }
 }
index f22e710..41e6781 100644 (file)
@@ -45,18 +45,18 @@ struct rxrpc_connection
        rxrpc_serial_t          serial_counter; /* packet serial number counter */
 
        /* the following should all be in net order */
-       uint32_t                in_epoch;       /* peer's epoch */
-       uint32_t                out_epoch;      /* my epoch */
-       uint32_t                conn_id;        /* connection ID, appropriately shifted */
-       uint16_t                service_id;     /* service ID */
+       __be32                  in_epoch;       /* peer's epoch */
+       __be32                  out_epoch;      /* my epoch */
+       __be32                  conn_id;        /* connection ID, appropriately shifted */
+       __be16                  service_id;     /* service ID */
        uint8_t                 security_ix;    /* security ID */
        uint8_t                 in_clientflag;  /* RXRPC_CLIENT_INITIATED if we are server */
        uint8_t                 out_clientflag; /* RXRPC_CLIENT_INITIATED if we are client */
 };
 
 extern int rxrpc_create_connection(struct rxrpc_transport *trans,
-                                  uint16_t port,
-                                  uint32_t addr,
+                                  __be16 port,
+                                  __be32 addr,
                                   uint16_t service_id,
                                   void *security,
                                   struct rxrpc_connection **_conn);
index 068813d..f9224d3 100644 (file)
@@ -27,19 +27,19 @@ extern size_t RXRPC_MAX_PACKET_SIZE;
  */
 struct rxrpc_header
 {
-       uint32_t        epoch;          /* client boot timestamp */
+       __be32          epoch;          /* client boot timestamp */
 
-       uint32_t        cid;            /* connection and channel ID */
+       __be32          cid;            /* connection and channel ID */
 #define RXRPC_MAXCALLS         4                       /* max active calls per conn */
 #define RXRPC_CHANNELMASK      (RXRPC_MAXCALLS-1)      /* mask for channel ID */
 #define RXRPC_CIDMASK          (~RXRPC_CHANNELMASK)    /* mask for connection ID */
 #define RXRPC_CIDSHIFT         2                       /* shift for connection ID */
 
-       uint32_t        callNumber;     /* call ID (0 for connection-level packets) */
+       __be32          callNumber;     /* call ID (0 for connection-level packets) */
 #define RXRPC_PROCESS_MAXCALLS (1<<2)  /* maximum number of active calls per conn (power of 2) */
 
-       uint32_t        seq;            /* sequence number of pkt in call stream */
-       uint32_t        serial;         /* serial number of pkt sent to network */
+       __be32          seq;            /* sequence number of pkt in call stream */
+       __be32          serial;         /* serial number of pkt sent to network */
 
        uint8_t         type;           /* packet type */
 #define RXRPC_PACKET_TYPE_DATA         1       /* data */
@@ -62,8 +62,8 @@ struct rxrpc_header
 
        uint8_t         userStatus;     /* app-layer defined status */
        uint8_t         securityIndex;  /* security protocol ID */
-       uint16_t        _rsvd;          /* reserved (used by kerberos security as cksum) */
-       uint16_t        serviceId;      /* service ID */
+       __be16          _rsvd;          /* reserved (used by kerberos security as cksum) */
+       __be16          serviceId;      /* service ID */
 
 } __attribute__((packed));
 
@@ -85,7 +85,7 @@ struct rxrpc_jumbo_header
 {
        uint8_t         flags;          /* packet flags (as per rxrpc_header) */
        uint8_t         pad;
-       uint16_t        _rsvd;          /* reserved (used by kerberos security as cksum) */
+       __be16          _rsvd;          /* reserved (used by kerberos security as cksum) */
 };
 
 #define RXRPC_JUMBO_DATALEN    1412    /* non-terminal jumbo packet data length */
@@ -97,12 +97,12 @@ struct rxrpc_jumbo_header
  */
 struct rxrpc_ackpacket
 {
-       uint16_t        bufferSpace;    /* number of packet buffers available */
-       uint16_t        maxSkew;        /* diff between serno being ACK'd and highest serial no
+       __be16          bufferSpace;    /* number of packet buffers available */
+       __be16          maxSkew;        /* diff between serno being ACK'd and highest serial no
                                         * received */
-       uint32_t        firstPacket;    /* sequence no of first ACK'd packet in attached list */
-       uint32_t        previousPacket; /* sequence no of previous packet received */
-       uint32_t        serial;         /* serial no of packet that prompted this ACK */
+       __be32          firstPacket;    /* sequence no of first ACK'd packet in attached list */
+       __be32          previousPacket; /* sequence no of previous packet received */
+       __be32          serial;         /* serial no of packet that prompted this ACK */
 
        uint8_t         reason;         /* reason for ACK */
 #define RXRPC_ACK_REQUESTED            1       /* ACK was requested on packet */
index da4832f..8b8fe97 100644 (file)
@@ -67,7 +67,7 @@ struct rxrpc_peer
 
 
 extern int rxrpc_peer_lookup(struct rxrpc_transport *trans,
-                            u32 addr,
+                            __be32 addr,
                             struct rxrpc_peer **_peer);
 
 static inline void rxrpc_get_peer(struct rxrpc_peer *peer)
index df6595c..8d9874c 100644 (file)
 
 #ifdef __KERNEL__
 
-extern uint32_t rxrpc_epoch;
+extern __be32 rxrpc_epoch;
 
+#ifdef CONFIG_SYSCTL
 extern int rxrpc_ktrace;
 extern int rxrpc_kdebug;
 extern int rxrpc_kproto;
 extern int rxrpc_knet;
+#else
+#define rxrpc_ktrace   0
+#define rxrpc_kdebug   0
+#define rxrpc_kproto   0
+#define rxrpc_knet     0
+#endif
 
 extern int rxrpc_sysctl_init(void);
 extern void rxrpc_sysctl_cleanup(void);
index 6aa8869..4863714 100644 (file)
@@ -78,8 +78,6 @@ struct rxrpc_transport
        volatile char           error_rcvd;     /* T if received ICMP error outstanding */
 };
 
-extern struct list_head rxrpc_transports;
-
 extern int rxrpc_create_transport(unsigned short port,
                                  struct rxrpc_transport **_trans);
 
index 2f37ad8..327a5fc 100644 (file)
@@ -21,6 +21,8 @@
 
 typedef uint32_t       rxrpc_seq_t;    /* Rx message sequence number */
 typedef uint32_t       rxrpc_serial_t; /* Rx message serial number */
+typedef __be32 rxrpc_seq_net_t; /* on-the-wire Rx message sequence number */
+typedef __be32 rxrpc_serial_net_t; /* on-the-wire Rx message serial number */
 
 struct rxrpc_call;
 struct rxrpc_connection;
index 3465f31..98c2e33 100644 (file)
@@ -13,6 +13,7 @@ struct scsi_driver {
 
        int (*init_command)(struct scsi_cmnd *);
        void (*rescan)(struct device *);
+       int (*issue_flush)(struct device *, sector_t *);
 };
 #define to_scsi_driver(drv) \
        container_of((drv), struct scsi_driver, gendrv)
index 4ba33e7..728efd5 100644 (file)
 
 /* 150-151: kernel events with quote - DO NOT use in user clients */
 #define SNDRV_SEQ_EVENT_KERNEL_ERROR   150
-#define SNDRV_SEQ_EVENT_KERNEL_QUOTE   151
+#define SNDRV_SEQ_EVENT_KERNEL_QUOTE   151     /* obsolete */
 
 /* 152-191: reserved */
 
@@ -640,7 +640,7 @@ struct sndrv_seq_queue_info {
         *  etc. if the queue is locked for other clients
         */
        int owner;              /* client id for owner of the queue */
-       int locked:1;           /* timing queue locked for other queues */
+       unsigned locked:1;      /* timing queue locked for other queues */
        char name[64];          /* name of this queue */
        unsigned int flags;     /* flags */
        char reserved[60];      /* for future use */
index 9224ffe..ed809e5 100644 (file)
@@ -35,8 +35,7 @@ typedef struct sndrv_ctl_elem_value snd_ctl_elem_value_t;
 typedef enum sndrv_ctl_event_type snd_ctl_event_type_t;
 typedef struct sndrv_ctl_event snd_ctl_event_t;
 
-#define _snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data)
-#define snd_kcontrol_chip(kcontrol) snd_magic_cast1(chip_t, _snd_kcontrol_chip(kcontrol), return -ENXIO)
+#define snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data)
 
 typedef int (snd_kcontrol_info_t) (snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo);
 typedef int (snd_kcontrol_get_t) (snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
index adef8f9..948e9a1 100644 (file)
@@ -61,6 +61,4 @@ void snd_wrapper_vfree(void *);
 #undef vfree
 #endif
 
-#include "sndmagic.h"
-
 #endif /* __SOUND_DRIVER_H */
index d390c64..104bb9b 100644 (file)
@@ -55,8 +55,6 @@ struct _snd_es1688 {
 
 typedef struct _snd_es1688 es1688_t;
 
-#define chip_t es1688_t
-
 /* I/O ports */
 
 #define ES1688P(codec, x) ((codec)->port + e_s_s_ESS1688##x)
index 29a6b83..e9efd4e 100644 (file)
@@ -91,9 +91,12 @@ struct snd_info_entry {
 
 extern int snd_info_check_reserved_words(const char *str);
 
-#ifdef CONFIG_SND_OSSEMUL
+#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
 extern int snd_info_minor_register(void);
 extern int snd_info_minor_unregister(void);
+#else
+#define snd_info_minor_register() /* NOP */
+#define snd_info_minor_unregister() /* NOP */
 #endif
 
 
index eb0fd48..3a2fd2c 100644 (file)
@@ -30,9 +30,8 @@ struct device;
  * buffer device info
  */
 struct snd_dma_device {
-       int type;                       /* SNDRV_MEM_TYPE_XXX */
+       int type;                       /* SNDRV_DMA_TYPE_XXX */
        struct device *dev;             /* generic device */
-       unsigned int id;                /* a unique ID */
 };
 
 #ifndef snd_dma_pci_data
@@ -56,6 +55,7 @@ struct snd_dma_device {
  * info for buffer allocation
  */
 struct snd_dma_buffer {
+       struct snd_dma_device dev;      /* device type */
        unsigned char *area;    /* virtual pointer */
        dma_addr_t addr;        /* physical address */
        size_t bytes;           /* buffer size in bytes */
@@ -76,7 +76,7 @@ struct snd_sg_buf {
        int tblsize;    /* allocated table size */
        struct snd_sg_page *table;      /* address table */
        struct page **page_table;       /* page table (for vmap/vunmap) */
-       struct snd_dma_device dev;
+       struct device *dev;
 };
 
 /*
@@ -97,20 +97,21 @@ static inline dma_addr_t snd_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t off
 
 
 /* allocate/release a buffer */
-int snd_dma_alloc_pages(const struct snd_dma_device *dev, size_t size,
+int snd_dma_alloc_pages(int type, struct device *dev, size_t size,
                        struct snd_dma_buffer *dmab);
-int snd_dma_alloc_pages_fallback(const struct snd_dma_device *dev, size_t size,
+int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
                                  struct snd_dma_buffer *dmab);
-void snd_dma_free_pages(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab);
+void snd_dma_free_pages(struct snd_dma_buffer *dmab);
 
 /* buffer-preservation managements */
-size_t snd_dma_get_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab);
-int snd_dma_free_reserved(const struct snd_dma_device *dev);
-int snd_dma_set_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab);
+
+#define snd_dma_pci_buf_id(pci)        (((unsigned int)(pci)->vendor << 16) | (pci)->device)
+
+size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id);
+int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id);
 
 /* basic memory allocation functions */
 void *snd_malloc_pages(size_t size, unsigned int gfp_flags);
-void *snd_malloc_pages_fallback(size_t size, unsigned int gfp_flags, size_t *res_size);
 void snd_free_pages(void *ptr, size_t size);
 
 #endif /* __SOUND_MEMALLOC_H */
diff --git a/include/sound/pcm-indirect.h b/include/sound/pcm-indirect.h
new file mode 100644 (file)
index 0000000..31fa7a5
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Helper functions for indirect PCM data transfer
+ *
+ *  Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *                   Jaroslav Kysela <perex@suse.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.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __SOUND_PCM_INDIRECT_H
+#define __SOUND_PCM_INDIRECT_H
+
+#include <sound/pcm.h>
+
+typedef struct sndrv_pcm_indirect {
+       unsigned int hw_buffer_size;    /* Byte size of hardware buffer */
+       unsigned int hw_queue_size;     /* Max queue size of hw buffer (0 = buffer size) */
+       unsigned int hw_data;   /* Offset to next dst (or src) in hw ring buffer */
+       unsigned int hw_io;     /* Ring buffer hw pointer */
+       int hw_ready;           /* Bytes ready for play (or captured) in hw ring buffer */
+       unsigned int sw_buffer_size;    /* Byte size of software buffer */
+       unsigned int sw_data;   /* Offset to next dst (or src) in sw ring buffer */
+       unsigned int sw_io;     /* Current software pointer in bytes */
+       int sw_ready;           /* Bytes ready to be transferred to/from hw */
+       snd_pcm_uframes_t appl_ptr;     /* Last seen appl_ptr */
+} snd_pcm_indirect_t;
+
+typedef void (*snd_pcm_indirect_copy_t)(snd_pcm_substream_t *substream,
+                                       snd_pcm_indirect_t *rec, size_t bytes);
+
+/*
+ * helper function for playback ack callback
+ */
+static inline void
+snd_pcm_indirect_playback_transfer(snd_pcm_substream_t *substream,
+                                  snd_pcm_indirect_t *rec,
+                                  snd_pcm_indirect_copy_t copy)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
+       snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
+       int qsize;
+
+       if (diff) {
+               if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
+                       diff += runtime->boundary;
+               rec->sw_ready += (int)frames_to_bytes(runtime, diff);
+               rec->appl_ptr = appl_ptr;
+       }
+       qsize = rec->hw_queue_size ? rec->hw_queue_size : rec->hw_buffer_size;
+       while (rec->hw_ready < qsize && rec->sw_ready > 0) {
+               unsigned int hw_to_end = rec->hw_buffer_size - rec->hw_data;
+               unsigned int sw_to_end = rec->sw_buffer_size - rec->sw_data;
+               unsigned int bytes = qsize - rec->hw_ready;
+               if (rec->sw_ready < (int)bytes)
+                       bytes = rec->sw_ready;
+               if (hw_to_end < bytes)
+                       bytes = hw_to_end;
+               if (sw_to_end < bytes)
+                       bytes = sw_to_end;
+               if (! bytes)
+                       break;
+               copy(substream, rec, bytes);
+               rec->hw_data += bytes;
+               if (rec->hw_data == rec->hw_buffer_size)
+                       rec->hw_data = 0;
+               rec->sw_data += bytes;
+               if (rec->sw_data == rec->sw_buffer_size)
+                       rec->sw_data = 0;
+               rec->hw_ready += bytes;
+               rec->sw_ready -= bytes;
+       }
+}
+
+/*
+ * helper function for playback pointer callback
+ * ptr = current byte pointer
+ */
+static inline snd_pcm_uframes_t
+snd_pcm_indirect_playback_pointer(snd_pcm_substream_t *substream,
+                                 snd_pcm_indirect_t *rec, unsigned int ptr)
+{
+       int bytes = ptr - rec->hw_io;
+       if (bytes < 0)
+               bytes += rec->hw_buffer_size;
+       rec->hw_io = ptr;
+       rec->hw_ready -= bytes;
+       rec->sw_io += bytes;
+       if (rec->sw_io >= rec->sw_buffer_size)
+               rec->sw_io -= rec->sw_buffer_size;
+       if (substream->ops->ack)
+               substream->ops->ack(substream);
+       return bytes_to_frames(substream->runtime, rec->sw_io);
+}
+
+
+/*
+ * helper function for capture ack callback
+ */
+static inline void
+snd_pcm_indirect_capture_transfer(snd_pcm_substream_t *substream,
+                                 snd_pcm_indirect_t *rec,
+                                 snd_pcm_indirect_copy_t copy)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
+       snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
+
+       if (diff) {
+               if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
+                       diff += runtime->boundary;
+               rec->sw_ready -= frames_to_bytes(runtime, diff);
+               rec->appl_ptr = appl_ptr;
+       }
+       while (rec->hw_ready > 0 && 
+              rec->sw_ready < (int)rec->sw_buffer_size) {
+               size_t hw_to_end = rec->hw_buffer_size - rec->hw_data;
+               size_t sw_to_end = rec->sw_buffer_size - rec->sw_data;
+               size_t bytes = rec->sw_buffer_size - rec->sw_ready;
+               if (rec->hw_ready < (int)bytes)
+                       bytes = rec->hw_ready;
+               if (hw_to_end < bytes)
+                       bytes = hw_to_end;
+               if (sw_to_end < bytes)
+                       bytes = sw_to_end;
+               if (! bytes)
+                       break;
+               copy(substream, rec, bytes);
+               rec->hw_data += bytes;
+               if ((int)rec->hw_data == rec->hw_buffer_size)
+                       rec->hw_data = 0;
+               rec->sw_data += bytes;
+               if (rec->sw_data == rec->sw_buffer_size)
+                       rec->sw_data = 0;
+               rec->hw_ready -= bytes;
+               rec->sw_ready += bytes;
+       }
+}
+
+/*
+ * helper function for capture pointer callback,
+ * ptr = current byte pointer
+ */
+static inline snd_pcm_uframes_t
+snd_pcm_indirect_capture_pointer(snd_pcm_substream_t *substream,
+                                snd_pcm_indirect_t *rec, unsigned int ptr)
+{
+       int qsize;
+       int bytes = ptr - rec->hw_io;
+       if (bytes < 0)
+               bytes += rec->hw_buffer_size;
+       rec->hw_io = ptr;
+       rec->hw_ready += bytes;
+       qsize = rec->hw_queue_size ? rec->hw_queue_size : rec->hw_buffer_size;
+       if (rec->hw_ready > qsize)
+               return SNDRV_PCM_POS_XRUN;
+       rec->sw_io += bytes;
+       if (rec->sw_io >= rec->sw_buffer_size)
+               rec->sw_io -= rec->sw_buffer_size;
+       if (substream->ops->ack)
+               substream->ops->ack(substream);
+       return bytes_to_frames(substream->runtime, rec->sw_io);
+}
+
+#endif /* __SOUND_PCM_INDIRECT_H */
index 4229360..c780e10 100644 (file)
@@ -52,10 +52,8 @@ typedef struct sndrv_pcm_mmap_control snd_pcm_mmap_control_t;
 typedef struct sndrv_mask snd_mask_t;
 typedef struct snd_sg_buf snd_pcm_sgbuf_t;
 
-#define _snd_pcm_substream_chip(substream) ((substream)->private_data)
-#define snd_pcm_substream_chip(substream) snd_magic_cast1(chip_t, _snd_pcm_substream_chip(substream), return -ENXIO)
-#define _snd_pcm_chip(pcm) ((pcm)->private_data)
-#define snd_pcm_chip(pcm) snd_magic_cast1(chip_t, _snd_pcm_chip(pcm), return -ENXIO)
+#define snd_pcm_substream_chip(substream) ((substream)->private_data)
+#define snd_pcm_chip(pcm) ((pcm)->private_data)
 
 typedef struct _snd_pcm_file snd_pcm_file_t;
 typedef struct _snd_pcm_runtime snd_pcm_runtime_t;
@@ -99,6 +97,7 @@ typedef struct _snd_pcm_ops {
        int (*silence)(snd_pcm_substream_t *substream, int channel, 
                       snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
        struct page *(*page)(snd_pcm_substream_t *substream, unsigned long offset);
+       int (*mmap)(snd_pcm_substream_t *substream, struct vm_area_struct *vma);
        int (*ack)(snd_pcm_substream_t *substream);
 } snd_pcm_ops_t;
 
@@ -123,6 +122,8 @@ typedef struct _snd_pcm_ops {
 #define SNDRV_PCM_TRIGGER_SUSPEND      5
 #define SNDRV_PCM_TRIGGER_RESUME       6
 
+#define SNDRV_PCM_POS_XRUN             ((snd_pcm_uframes_t)-1)
+
 /* If you change this don't forget to change rates[] table in pcm_native.c */
 #define SNDRV_PCM_RATE_5512            (1<<0)          /* 5512Hz */
 #define SNDRV_PCM_RATE_8000            (1<<1)          /* 8000Hz */
@@ -351,7 +352,8 @@ struct _snd_pcm_runtime {
        unsigned char *dma_area;        /* DMA area */
        dma_addr_t dma_addr;            /* physical bus address (not accessible from main CPU) */
        size_t dma_bytes;               /* size of DMA area */
-       void *dma_private;              /* private DMA data for the memory allocator */
+
+       struct snd_dma_buffer *dma_buffer_p;    /* allocated buffer */
 
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
        /* -- OSS things -- */
@@ -372,8 +374,8 @@ struct _snd_pcm_substream {
        char name[32];                  /* substream name */
        int stream;                     /* stream (direction) */
        size_t buffer_bytes_max;        /* limit ring buffer size */
-       struct snd_dma_device dma_device;
        struct snd_dma_buffer dma_buffer;
+       unsigned int dma_buf_id;
        size_t dma_max;
        /* -- hardware operations -- */
        unsigned int open_flag: 1;      /* lowlevel device has been opened */
@@ -382,7 +384,7 @@ struct _snd_pcm_substream {
        snd_pcm_runtime_t *runtime;
         /* -- timer section -- */
        snd_timer_t *timer;             /* timer */
-       int timer_running: 1;           /* time is running */
+       unsigned timer_running: 1;      /* time is running */
        spinlock_t timer_lock;
        /* -- next substream -- */
        snd_pcm_substream_t *next;
@@ -851,7 +853,7 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format);
 int snd_pcm_format_big_endian(snd_pcm_format_t format);
 int snd_pcm_format_width(snd_pcm_format_t format);                     /* in bits */
 int snd_pcm_format_physical_width(snd_pcm_format_t format);            /* in bits */
-u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format);
+const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
@@ -892,6 +894,22 @@ snd_pcm_sframes_t snd_pcm_lib_readv(snd_pcm_substream_t *substream,
 
 int snd_pcm_limit_hw_rates(snd_pcm_runtime_t *runtime);
 
+static inline void snd_pcm_set_runtime_buffer(snd_pcm_substream_t *substream,
+                                             struct snd_dma_buffer *bufp)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       if (bufp) {
+               runtime->dma_buffer_p = bufp;
+               runtime->dma_area = bufp->area;
+               runtime->dma_addr = bufp->addr;
+               runtime->dma_bytes = bufp->bytes;
+       } else {
+               runtime->dma_buffer_p = NULL;
+               runtime->dma_area = NULL;
+               runtime->dma_addr = 0;
+               runtime->dma_bytes = 0;
+       }
+}
 
 /*
  *  Timer interface
@@ -916,11 +934,33 @@ int snd_pcm_lib_preallocate_pages_for_all(snd_pcm_t *pcm,
 int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size);
 int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream);
 
-#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_private)
+#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_buffer_p->private_data)
 #define snd_pcm_sgbuf_pages(size) snd_sgbuf_aligned_pages(size)
 #define snd_pcm_sgbuf_get_addr(sgbuf,ofs) snd_sgbuf_get_addr(sgbuf,ofs)
 struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset);
 
+/* handle mmap counter - PCM mmap callback should handle this counter properly */
+static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)
+{
+       snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
+       atomic_inc(&substream->runtime->mmap_count);
+}
+
+static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area)
+{
+       snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
+       atomic_dec(&substream->runtime->mmap_count);
+}
+
+/* mmap for io-memory area */
+#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA)
+#define SNDRV_PCM_INFO_MMAP_IOMEM      SNDRV_PCM_INFO_MMAP
+int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct *area);
+#else
+#define SNDRV_PCM_INFO_MMAP_IOMEM      0
+#define snd_pcm_lib_mmap_iomem NULL
+#endif
+
 static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
 {
        *max = dma < 4 ? 64 * 1024 : 128 * 1024;
index 096d975..5187285 100644 (file)
@@ -39,10 +39,10 @@ struct _snd_pcm_oss_setup {
 };
 
 typedef struct _snd_pcm_oss_runtime {
-       int params: 1,                          /* format/parameter change */
-            prepare: 1,                                /* need to prepare the operation */
-            trigger: 1,                                /* trigger flag */
-            sync_trigger: 1;                   /* sync trigger flag */
+       unsigned params: 1,                     /* format/parameter change */
+                prepare: 1,                    /* need to prepare the operation */
+                trigger: 1,                    /* trigger flag */
+                sync_trigger: 1;               /* sync trigger flag */
        int rate;                               /* requested rate */
        int format;                             /* requested OSS format */
        unsigned int channels;                  /* requested channels */
@@ -68,7 +68,7 @@ typedef struct _snd_pcm_oss_file {
 } snd_pcm_oss_file_t;
 
 typedef struct _snd_pcm_oss_substream {
-       int oss: 1;                             /* oss mode */
+       unsigned oss: 1;                        /* oss mode */
        snd_pcm_oss_setup_t *setup;             /* active setup */
        snd_pcm_oss_file_t *file;
 } snd_pcm_oss_substream_t;
index d0b69fb..a64fb3f 100644 (file)
@@ -129,8 +129,8 @@ typedef struct _snd_seq_queue queue_t;
 
 typedef struct {
        void *private_data;
-       int allow_input: 1,
-           allow_output: 1;
+       unsigned allow_input: 1,
+                allow_output: 1;
        /*...*/
 } snd_seq_client_callback_t;
 
@@ -168,6 +168,9 @@ typedef int (*snd_seq_dump_func_t)(void *ptr, void *buf, int count);
 int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf, int in_kernel, int size_aligned);
 int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t func, void *private_data);
 
+/* interface for OSS emulation */
+int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo);
+
 /* port callback routines */
 void snd_port_init_callback(snd_seq_port_callback_t *p);
 snd_seq_port_callback_t *snd_port_alloc_callback(void);
index 907465a..eb1d612 100644 (file)
@@ -95,6 +95,7 @@ typedef struct snd_sf_list {
        int zone_locked;        /* locked time for zone */
        int sample_locked;      /* locked time for sample */
        snd_sf_callback_t callback;     /* callback functions */
+       int presets_locked;
        struct semaphore presets_mutex;
        spinlock_t lock;
        snd_util_memhdr_t *memhdr;
index 5609f54..d3d90e1 100644 (file)
@@ -182,6 +182,7 @@ struct snd_vx_core {
        /* clock and audio sources */
        unsigned int audio_source;      /* current audio input source */
        unsigned int audio_source_target;
+       unsigned int clock_mode;        /* clock mode (VX_CLOCK_MODE_XXX) */
        unsigned int clock_source;      /* current clock source (INTERNAL_QUARTZ or UER_SYNC) */
        unsigned int freq;              /* current frequency */
        unsigned int freq_detected;     /* detected frequency from digital in */
@@ -364,6 +365,13 @@ enum {
        UER_SYNC
 };
 
+/* clock mode */
+enum {
+       VX_CLOCK_MODE_AUTO,     /* depending on the current audio source */
+       VX_CLOCK_MODE_INTERNAL, /* fixed to internal quartz */
+       VX_CLOCK_MODE_EXTERNAL  /* fixed to UER sync */
+};
+
 /* SPDIF/UER type */
 enum {
        VX_UER_MODE_CONSUMER,
diff --git a/include/video/epson1355.h b/include/video/epson1355.h
new file mode 100644 (file)
index 0000000..9759f29
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * include/video/epson13xx.h -- Epson 13xx frame buffer
+ *
+ * Copyright (C) Hewlett-Packard Company.  All rights reserved.
+ *
+ * Written by Christopher Hoover <ch@hpl.hp.com>
+ *
+ */
+
+#ifndef _EPSON13XX_H_
+#define _EPSON13XX_H_
+
+#define REG_REVISION_CODE              0x00
+#define REG_MEMORY_CONFIG              0x01
+#define REG_PANEL_TYPE                 0x02
+#define REG_MOD_RATE                   0x03
+#define REG_HORZ_DISP_WIDTH            0x04
+#define REG_HORZ_NONDISP_PERIOD        0x05
+#define REG_HRTC_START_POSITION        0x06
+#define REG_HRTC_PULSE_WIDTH           0x07
+#define REG_VERT_DISP_HEIGHT0          0x08
+#define REG_VERT_DISP_HEIGHT1          0x09
+#define REG_VERT_NONDISP_PERIOD        0x0A
+#define REG_VRTC_START_POSITION        0x0B
+#define REG_VRTC_PULSE_WIDTH           0x0C
+#define REG_DISPLAY_MODE               0x0D
+#define REG_SCRN1_LINE_COMPARE0        0x0E
+#define REG_SCRN1_LINE_COMPARE1        0x0F
+#define REG_SCRN1_DISP_START_ADDR0     0x10
+#define REG_SCRN1_DISP_START_ADDR1     0x11
+#define REG_SCRN1_DISP_START_ADDR2     0x12
+#define REG_SCRN2_DISP_START_ADDR0     0x13
+#define REG_SCRN2_DISP_START_ADDR1     0x14
+#define REG_SCRN2_DISP_START_ADDR2     0x15
+#define REG_MEM_ADDR_OFFSET0           0x16
+#define REG_MEM_ADDR_OFFSET1           0x17
+#define REG_PIXEL_PANNING              0x18
+#define REG_CLOCK_CONFIG               0x19
+#define REG_POWER_SAVE_CONFIG          0x1A
+#define REG_MISC                       0x1B
+#define REG_MD_CONFIG_READBACK0        0x1C
+#define REG_MD_CONFIG_READBACK1        0x1D
+#define REG_GPIO_CONFIG0               0x1E
+#define REG_GPIO_CONFIG1               0x1F
+#define REG_GPIO_CONTROL0              0x20
+#define REG_GPIO_CONTROL1              0x21
+#define REG_PERF_ENHANCEMENT0          0x22
+#define REG_PERF_ENHANCEMENT1          0x23
+#define REG_LUT_ADDR                   0x24
+#define REG_RESERVED_1                 0x25
+#define REG_LUT_DATA                   0x26
+#define REG_INK_CURSOR_CONTROL         0x27
+#define REG_CURSOR_X_POSITION0         0x28
+#define REG_CURSOR_X_POSITION1         0x29
+#define REG_CURSOR_Y_POSITION0         0x2A
+#define REG_CURSOR_Y_POSITION1         0x2B
+#define REG_INK_CURSOR_COLOR0_0        0x2C
+#define REG_INK_CURSOR_COLOR0_1        0x2D
+#define REG_INK_CURSOR_COLOR1_0        0x2E
+#define REG_INK_CURSOR_COLOR1_1        0x2F
+#define REG_INK_CURSOR_START_ADDR      0x30
+#define REG_ALTERNATE_FRM              0x31
+
+#endif
index 3120bfb..96eb4a7 100644 (file)
 #define VGAINIT1_MASK                   0x1fffff
 #define VIDCFG_VIDPROC_ENABLE           BIT(0)
 #define VIDCFG_CURS_X11                 BIT(1)
+#define VIDCFG_INTERLACE                BIT(3)
 #define VIDCFG_HALF_MODE                BIT(4)
 #define VIDCFG_DESK_ENABLE              BIT(7)
 #define VIDCFG_CLUT_BYPASS              BIT(10)
index e44593d..700d6c8 100644 (file)
 #define VGA_SAVE_CMAP  16 /* save/restore color map/DAC   */
 
 struct vgastate {
-       caddr_t vgabase;        /* mmio base, if supported                 */
+       void __iomem *vgabase;  /* mmio base, if supported                 */
        unsigned long membase;  /* VGA window base, 0 for default - 0xA000 */
        __u32 memsize;          /* VGA window size, 0 for default 64K      */
        __u32 flags;            /* what state[s] to save (see VGA_SAVE_*)  */
@@ -238,23 +238,23 @@ static inline void vga_io_w_fast (unsigned short port, unsigned char reg,
        outw(VGA_OUT16VAL (val, reg), port);
 }
 
-static inline unsigned char vga_mm_r (caddr_t regbase, unsigned short port)
+static inline unsigned char vga_mm_r (void __iomem *regbase, unsigned short port)
 {
        return readb (regbase + port);
 }
 
-static inline void vga_mm_w (caddr_t regbase, unsigned short port, unsigned char val)
+static inline void vga_mm_w (void __iomem *regbase, unsigned short port, unsigned char val)
 {
        writeb (val, regbase + port);
 }
 
-static inline void vga_mm_w_fast (caddr_t regbase, unsigned short port,
+static inline void vga_mm_w_fast (void __iomem *regbase, unsigned short port,
                                  unsigned char reg, unsigned char val)
 {
        writew (VGA_OUT16VAL (val, reg), regbase + port);
 }
 
-static inline unsigned char vga_r (caddr_t regbase, unsigned short port)
+static inline unsigned char vga_r (void __iomem *regbase, unsigned short port)
 {
        if (regbase)
                return vga_mm_r (regbase, port);
@@ -262,7 +262,7 @@ static inline unsigned char vga_r (caddr_t regbase, unsigned short port)
                return vga_io_r (port);
 }
 
-static inline void vga_w (caddr_t regbase, unsigned short port, unsigned char val)
+static inline void vga_w (void __iomem *regbase, unsigned short port, unsigned char val)
 {
        if (regbase)
                vga_mm_w (regbase, port, val);
@@ -271,7 +271,7 @@ static inline void vga_w (caddr_t regbase, unsigned short port, unsigned char va
 }
 
 
-static inline void vga_w_fast (caddr_t regbase, unsigned short port,
+static inline void vga_w_fast (void __iomem *regbase, unsigned short port,
                               unsigned char reg, unsigned char val)
 {
        if (regbase)
@@ -285,13 +285,13 @@ static inline void vga_w_fast (caddr_t regbase, unsigned short port,
  * VGA CRTC register read/write
  */
  
-static inline unsigned char vga_rcrt (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rcrt (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_CRT_IC, reg);
         return vga_r (regbase, VGA_CRT_DC);
 }
 
-static inline void vga_wcrt (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wcrt (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
        vga_w_fast (regbase, VGA_CRT_IC, reg, val);
@@ -317,13 +317,13 @@ static inline void vga_io_wcrt (unsigned char reg, unsigned char val)
 #endif /* VGA_OUTW_WRITE */
 }
 
-static inline unsigned char vga_mm_rcrt (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rcrt (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_CRT_IC, reg);
         return vga_mm_r (regbase, VGA_CRT_DC);
 }
 
-static inline void vga_mm_wcrt (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wcrt (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
        vga_mm_w_fast (regbase, VGA_CRT_IC, reg, val);
@@ -338,13 +338,13 @@ static inline void vga_mm_wcrt (caddr_t regbase, unsigned char reg, unsigned cha
  * VGA sequencer register read/write
  */
  
-static inline unsigned char vga_rseq (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rseq (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_SEQ_I, reg);
         return vga_r (regbase, VGA_SEQ_D);
 }
 
-static inline void vga_wseq (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wseq (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
        vga_w_fast (regbase, VGA_SEQ_I, reg, val);
@@ -370,13 +370,13 @@ static inline void vga_io_wseq (unsigned char reg, unsigned char val)
 #endif /* VGA_OUTW_WRITE */
 }
 
-static inline unsigned char vga_mm_rseq (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rseq (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_SEQ_I, reg);
         return vga_mm_r (regbase, VGA_SEQ_D);
 }
 
-static inline void vga_mm_wseq (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wseq (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
        vga_mm_w_fast (regbase, VGA_SEQ_I, reg, val);
@@ -390,13 +390,13 @@ static inline void vga_mm_wseq (caddr_t regbase, unsigned char reg, unsigned cha
  * VGA graphics controller register read/write
  */
  
-static inline unsigned char vga_rgfx (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rgfx (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_GFX_I, reg);
         return vga_r (regbase, VGA_GFX_D);
 }
 
-static inline void vga_wgfx (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wgfx (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
        vga_w_fast (regbase, VGA_GFX_I, reg, val);
@@ -422,13 +422,13 @@ static inline void vga_io_wgfx (unsigned char reg, unsigned char val)
 #endif /* VGA_OUTW_WRITE */
 }
 
-static inline unsigned char vga_mm_rgfx (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rgfx (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_GFX_I, reg);
         return vga_mm_r (regbase, VGA_GFX_D);
 }
 
-static inline void vga_mm_wgfx (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wgfx (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
        vga_mm_w_fast (regbase, VGA_GFX_I, reg, val);
@@ -443,13 +443,13 @@ static inline void vga_mm_wgfx (caddr_t regbase, unsigned char reg, unsigned cha
  * VGA attribute controller register read/write
  */
  
-static inline unsigned char vga_rattr (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rattr (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_ATT_IW, reg);
         return vga_r (regbase, VGA_ATT_R);
 }
 
-static inline void vga_wattr (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wattr (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
         vga_w (regbase, VGA_ATT_IW, reg);
         vga_w (regbase, VGA_ATT_W, val);
@@ -467,13 +467,13 @@ static inline void vga_io_wattr (unsigned char reg, unsigned char val)
         vga_io_w (VGA_ATT_W, val);
 }
 
-static inline unsigned char vga_mm_rattr (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rattr (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_ATT_IW, reg);
         return vga_mm_r (regbase, VGA_ATT_R);
 }
 
-static inline void vga_mm_wattr (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wattr (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
         vga_mm_w (regbase, VGA_ATT_IW, reg);
         vga_mm_w (regbase, VGA_ATT_W, val);
index 765822b..d813b7a 100644 (file)
@@ -708,7 +708,7 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
                audit_log_move(ab);
        avail = sizeof(ab->tmp) - ab->len;
        p = d_path(dentry, vfsmnt, ab->tmp + ab->len, avail);
-       if (p == ERR_PTR(-ENAMETOOLONG)) {
+       if (IS_ERR(p)) {
                /* FIXME: can we save some information here? */
                audit_log_format(ab, "<toolong>");
        } else {
@@ -810,16 +810,3 @@ void audit_log(struct audit_context *ctx, const char *fmt, ...)
                audit_log_end(ab);
        }
 }
-
-EXPORT_SYMBOL_GPL(audit_set_rate_limit);
-EXPORT_SYMBOL_GPL(audit_set_backlog_limit);
-EXPORT_SYMBOL_GPL(audit_set_enabled);
-EXPORT_SYMBOL_GPL(audit_set_failure);
-
-EXPORT_SYMBOL_GPL(audit_log_start);
-EXPORT_SYMBOL_GPL(audit_log_format);
-EXPORT_SYMBOL_GPL(audit_log_end_irq);
-EXPORT_SYMBOL_GPL(audit_log_end_fast);
-EXPORT_SYMBOL_GPL(audit_log_end);
-EXPORT_SYMBOL_GPL(audit_log);
-EXPORT_SYMBOL_GPL(audit_log_d_path);
index 1c5c357..7e864e2 100644 (file)
@@ -89,14 +89,12 @@ static inline void cap_set_pg(int pgrp, kernel_cap_t *effective,
                              kernel_cap_t *permitted)
 {
        task_t *g, *target;
-       struct list_head *l;
-       struct pid *pid;
 
-       for_each_task_pid(pgrp, PIDTYPE_PGID, g, l, pid) {
+       do_each_task_pid(pgrp, PIDTYPE_PGID, g) {
                target = g;
                while_each_thread(g, target)
                        security_capset_set(target, effective, inheritable, permitted);
-       }
+       } while_each_task_pid(pgrp, PIDTYPE_PGID, g);
 }
 
 /*
index a5686ae..5fba353 100644 (file)
@@ -44,29 +44,7 @@ struct exec_domain default_exec_domain = {
 static void
 default_handler(int segment, struct pt_regs *regp)
 {
-       u_long                  pers = 0;
-
-       /*
-        * This may have been a static linked SVr4 binary, so we would
-        * have the personality set incorrectly. Or it might have been
-        * a Solaris/x86 binary. We can tell which because the former
-        * uses lcall7, while the latter used lcall 0x27.
-        * Try to find or load the appropriate personality, and fall back
-        * to just forcing a SEGV.
-        *
-        * XXX: this is IA32-specific and should be moved to the MD-tree.
-        */
-       switch (segment) {
-#ifdef __i386__
-       case 0x07:
-               pers = abi_defhandler_lcall7;
-               break;
-       case 0x27:
-               pers = PER_SOLARIS;
-               break;
-#endif
-       }
-       set_personality(pers);
+       set_personality(0);
 
        if (current_thread_info()->exec_domain->handler != default_handler)
                current_thread_info()->exec_domain->handler(segment, regp);
@@ -228,100 +206,3 @@ sys_personality(u_long personality)
 EXPORT_SYMBOL(register_exec_domain);
 EXPORT_SYMBOL(unregister_exec_domain);
 EXPORT_SYMBOL(__set_personality);
-
-/*
- * We have to have all sysctl handling for the Linux-ABI
- * in one place as the dynamic registration of sysctls is
- * horribly crufty in Linux <= 2.4.
- *
- * I hope the new sysctl schemes discussed for future versions
- * will obsolete this.
- *
- *                             --hch
- */
-
-u_long abi_defhandler_coff = PER_SCOSVR3;
-u_long abi_defhandler_elf = PER_LINUX;
-u_long abi_defhandler_lcall7 = PER_SVR4;
-u_long abi_defhandler_libcso = PER_SVR4;
-u_int abi_traceflg;
-int abi_fake_utsname;
-
-static struct ctl_table abi_table[] = {
-       {
-               .ctl_name       = ABI_DEFHANDLER_COFF,
-               .procname       = "defhandler_coff",
-               .data           = &abi_defhandler_coff,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_doulongvec_minmax,
-       },
-       {
-               .ctl_name       = ABI_DEFHANDLER_ELF,
-               .procname       = "defhandler_elf",
-               .data           = &abi_defhandler_elf,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_doulongvec_minmax,
-       },
-       {
-               .ctl_name       = ABI_DEFHANDLER_LCALL7,
-               .procname       = "defhandler_lcall7",
-               .data           = &abi_defhandler_lcall7,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_doulongvec_minmax,
-       },
-       {
-               .ctl_name       = ABI_DEFHANDLER_LIBCSO,
-               .procname       = "defhandler_libcso",
-               .data           = &abi_defhandler_libcso,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_doulongvec_minmax,
-       },
-       {
-               .ctl_name       = ABI_TRACE,
-               .procname       = "trace",
-               .data           = &abi_traceflg,
-               .maxlen         = sizeof(u_int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-       },
-       {
-               .ctl_name       = ABI_FAKE_UTSNAME,
-               .procname       = "fake_utsname",
-               .data           = &abi_fake_utsname,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-       },
-       { .ctl_name = 0 }
-};
-
-static struct ctl_table abi_root_table[] = {
-       {
-               .ctl_name       = CTL_ABI,
-               .procname       = "abi",
-               .mode           = 0555,
-               .child          = abi_table,
-       },
-       { .ctl_name = 0 }
-};
-
-static int __init
-abi_register_sysctl(void)
-{
-       register_sysctl_table(abi_root_table, 1);
-       return 0;
-}
-
-__initcall(abi_register_sysctl);
-
-
-EXPORT_SYMBOL(abi_defhandler_coff);
-EXPORT_SYMBOL(abi_defhandler_elf);
-EXPORT_SYMBOL(abi_defhandler_lcall7);
-EXPORT_SYMBOL(abi_defhandler_libcso);
-EXPORT_SYMBOL(abi_traceflg);
-EXPORT_SYMBOL(abi_fake_utsname);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
new file mode 100644 (file)
index 0000000..ca4e28b
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *  Kernel Probes (KProbes)
+ *  kernel/kprobes.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ *
+ * 2002-Oct    Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
+ *             Probes initial implementation (includes suggestions from
+ *             Rusty Russell).
+ * 2004-Aug    Updated by Prasanna S Panchamukhi <prasanna@in.ibm.com> with
+ *             hlists and exceptions notifier as suggested by Andi Kleen.
+ * 2004-July   Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
+ *             interface to access function arguments.
+ * 2004-Sep    Prasanna S Panchamukhi <prasanna@in.ibm.com> Changed Kprobes
+ *             exceptions notifier to be first on the priority list.
+ */
+#include <linux/kprobes.h>
+#include <linux/spinlock.h>
+#include <linux/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/cacheflush.h>
+#include <asm/errno.h>
+#include <asm/kdebug.h>
+
+#define KPROBE_HASH_BITS 6
+#define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS)
+
+static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
+
+unsigned int kprobe_cpu = NR_CPUS;
+static spinlock_t kprobe_lock = SPIN_LOCK_UNLOCKED;
+
+/* Locks kprobe: irqs must be disabled */
+void lock_kprobes(void)
+{
+       spin_lock(&kprobe_lock);
+       kprobe_cpu = smp_processor_id();
+}
+
+void unlock_kprobes(void)
+{
+       kprobe_cpu = NR_CPUS;
+       spin_unlock(&kprobe_lock);
+}
+
+/* You have to be holding the kprobe_lock */
+struct kprobe *get_kprobe(void *addr)
+{
+       struct hlist_head *head;
+       struct hlist_node *node;
+
+       head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)];
+       hlist_for_each(node, head) {
+               struct kprobe *p = hlist_entry(node, struct kprobe, hlist);
+               if (p->addr == addr)
+                       return p;
+       }
+       return NULL;
+}
+
+int register_kprobe(struct kprobe *p)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&kprobe_lock, flags);
+       INIT_HLIST_NODE(&p->hlist);
+       if (get_kprobe(p->addr)) {
+               ret = -EEXIST;
+               goto out;
+       }
+       hlist_add_head(&p->hlist,
+                      &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
+
+       arch_prepare_kprobe(p);
+       p->opcode = *p->addr;
+       *p->addr = BREAKPOINT_INSTRUCTION;
+       flush_icache_range((unsigned long) p->addr,
+                          (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+      out:
+       spin_unlock_irqrestore(&kprobe_lock, flags);
+       return ret;
+}
+
+void unregister_kprobe(struct kprobe *p)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&kprobe_lock, flags);
+       *p->addr = p->opcode;
+       hlist_del(&p->hlist);
+       flush_icache_range((unsigned long) p->addr,
+                          (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+       spin_unlock_irqrestore(&kprobe_lock, flags);
+}
+
+static struct notifier_block kprobe_exceptions_nb = {
+       .notifier_call = kprobe_exceptions_notify,
+       .priority = 0x7fffffff /* we need to notified first */
+};
+
+int register_jprobe(struct jprobe *jp)
+{
+       /* Todo: Verify probepoint is a function entry point */
+       jp->kp.pre_handler = setjmp_pre_handler;
+       jp->kp.break_handler = longjmp_break_handler;
+
+       return register_kprobe(&jp->kp);
+}
+
+void unregister_jprobe(struct jprobe *jp)
+{
+       unregister_kprobe(&jp->kp);
+}
+
+static int __init init_kprobes(void)
+{
+       int i, err = 0;
+
+       /* FIXME allocate the probe table, currently defined statically */
+       /* initialize all list heads */
+       for (i = 0; i < KPROBE_TABLE_SIZE; i++)
+               INIT_HLIST_HEAD(&kprobe_table[i]);
+
+       err = register_die_notifier(&kprobe_exceptions_nb);
+       return err;
+}
+
+__initcall(init_kprobes);
+
+EXPORT_SYMBOL_GPL(register_kprobe);
+EXPORT_SYMBOL_GPL(unregister_kprobe);
+EXPORT_SYMBOL_GPL(register_jprobe);
+EXPORT_SYMBOL_GPL(unregister_jprobe);
+EXPORT_SYMBOL_GPL(jprobe_return);
index 6bb6226..67f9552 100644 (file)
@@ -18,6 +18,13 @@ config PM
          will issue the hlt instruction if nothing is to be done, thereby
          sending the processor to sleep and saving power.
 
+config PM_DEBUG
+       bool "Power Management Debug Support"
+       ---help---
+       This option enables verbose debugging support in the Power Management
+       code. This is helpful when debugging and reporting various PM bugs, 
+       like suspend support.
+
 config SOFTWARE_SUSPEND
        bool "Software Suspend (EXPERIMENTAL)"
        depends on EXPERIMENTAL && PM && SWAP
@@ -42,33 +49,12 @@ config SOFTWARE_SUSPEND
 
          For more information take a look at Documentation/power/swsusp.txt.
 
-config PM_DISK
-       bool "Suspend-to-Disk Support"
-       depends on PM && SWAP && X86 && !X86_64
-       ---help---
-         Suspend-to-disk is a power management state in which the contents
-         of memory are stored on disk and the entire system is shut down or
-         put into a low-power state (e.g. ACPI S4). When the computer is 
-         turned back on, the stored image is loaded from disk and execution
-         resumes from where it left off before suspending. 
-
-         This config option enables the core infrastructure necessary to 
-         perform the suspend and resume transition. 
-
-         Currently, this suspend-to-disk implementation is based on a forked
-         version of the swsusp code base. As such, it's still experimental,
-         and still relies on CONFIG_SWAP. 
-
-         More information can be found in Documentation/power/.
-
-         If unsure, Say N.
-
-config PM_DISK_PARTITION
+config PM_STD_PARTITION
        string "Default resume partition"
-       depends on PM_DISK
+       depends on SOFTWARE_SUSPEND
        default ""
        ---help---
-         The default resume partition is the partition that the pmdisk suspend-
+         The default resume partition is the partition that the suspend-
          to-disk implementation will look for a suspended disk image. 
 
          The partition specified here will be different for almost every user. 
@@ -77,16 +63,10 @@ config PM_DISK_PARTITION
 
          The partition specified can be overridden by specifying:
 
-               pmdisk=/dev/<other device> 
+               resume=/dev/<other device> 
 
          which will set the resume partition to the device specified. 
 
-         One may also do: 
-
-               pmdisk=off
-
-         to inform the kernel not to perform a resume transition. 
-
          Note there is currently not a way to specify which device to save the
          suspended image to. It will simply pick the first available swap 
          device.
index 00b390d..7ff375e 100644 (file)
@@ -11,7 +11,9 @@
 
 static int new_loglevel = 10;
 static int orig_loglevel;
+#ifdef SUSPEND_CONSOLE
 static int orig_fgconsole, orig_kmsg;
+#endif
 
 int pm_prepare_console(void)
 {
@@ -50,6 +52,7 @@ void pm_restore_console(void)
        acquire_console_sem();
        set_console(orig_fgconsole);
        release_console_sem();
+       kmsg_redirect = orig_kmsg;
 #endif
        return;
 }
index 6abcf99..312aa16 100644 (file)
@@ -8,13 +8,11 @@
  *
  */
 
-#define DEBUG
-
-
 #include <linux/suspend.h>
 #include <linux/syscalls.h>
 #include <linux/reboot.h>
 #include <linux/string.h>
+#include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
 #include "power.h"
 extern u32 pm_disk_mode;
 extern struct pm_ops * pm_ops;
 
-extern int pmdisk_save(void);
-extern int pmdisk_write(void);
-extern int pmdisk_read(void);
-extern int pmdisk_restore(void);
-extern int pmdisk_free(void);
+extern int swsusp_suspend(void);
+extern int swsusp_write(void);
+extern int swsusp_read(void);
+extern int swsusp_resume(void);
+extern int swsusp_free(void);
 
 
+static int noresume = 0;
+char resume_file[256] = CONFIG_PM_STD_PARTITION;
+
 /**
  *     power_down - Shut machine down for hibernate.
  *     @mode:          Suspend-to-disk mode
@@ -46,22 +47,26 @@ static int power_down(u32 mode)
        int error = 0;
 
        local_irq_save(flags);
-       device_power_down(PM_SUSPEND_DISK);
        switch(mode) {
        case PM_DISK_PLATFORM:
+               device_power_down(PM_SUSPEND_DISK);
                error = pm_ops->enter(PM_SUSPEND_DISK);
                break;
        case PM_DISK_SHUTDOWN:
                printk("Powering off system\n");
+               device_shutdown();
                machine_power_off();
                break;
        case PM_DISK_REBOOT:
+               device_shutdown();
                machine_restart(NULL);
                break;
        }
        machine_halt();
-       device_power_up();
-       local_irq_restore(flags);
+       /* Valid image is on the disk, if we continue we risk serious data corruption
+          after resume. */
+       printk(KERN_CRIT "Please power me down manually\n");
+       while(1);
        return 0;
 }
 
@@ -99,6 +104,7 @@ static void finish(void)
 {
        device_resume();
        platform_finish();
+       enable_nonboot_cpus();
        thaw_processes();
        pm_restore_console();
 }
@@ -126,6 +132,7 @@ static int prepare(void)
        /* Free memory before shutting down devices. */
        free_some_memory();
 
+       disable_nonboot_cpus();
        if ((error = device_suspend(PM_SUSPEND_DISK)))
                goto Finish;
 
@@ -133,6 +140,7 @@ static int prepare(void)
  Finish:
        platform_finish();
  Thaw:
+       enable_nonboot_cpus();
        thaw_processes();
        pm_restore_console();
        return error;
@@ -161,7 +169,7 @@ int pm_suspend_disk(void)
 
        pr_debug("PM: snapshotting memory.\n");
        in_suspend = 1;
-       if ((error = pmdisk_save()))
+       if ((error = swsusp_suspend()))
                goto Done;
 
        if (in_suspend) {
@@ -173,14 +181,14 @@ int pm_suspend_disk(void)
                mb();
                barrier();
 
-               error = pmdisk_write();
+               error = swsusp_write();
                if (!error) {
                        error = power_down(pm_disk_mode);
                        pr_debug("PM: Power down failed.\n");
                }
        } else
                pr_debug("PM: Image restored successfully.\n");
-       pmdisk_free();
+       swsusp_free();
  Done:
        finish();
        return error;
@@ -188,7 +196,7 @@ int pm_suspend_disk(void)
 
 
 /**
- *     pm_resume - Resume from a saved image.
+ *     software_resume - Resume from a saved image.
  *
  *     Called as a late_initcall (so all devices are discovered and
  *     initialized), we call pmdisk to see if we have a saved image or not.
@@ -199,13 +207,21 @@ int pm_suspend_disk(void)
  *
  */
 
-static int pm_resume(void)
+static int software_resume(void)
 {
        int error;
 
+       if (noresume) {
+               /**
+                * FIXME: If noresume is specified, we need to find the partition
+                * and reset it back to normal swap space.
+                */
+               return 0;
+       }
+
        pr_debug("PM: Reading pmdisk image.\n");
 
-       if ((error = pmdisk_read()))
+       if ((error = swsusp_read()))
                goto Done;
 
        pr_debug("PM: Preparing system for restore.\n");
@@ -216,28 +232,18 @@ static int pm_resume(void)
        barrier();
        mb();
 
-       /* FIXME: The following (comment and mdelay()) are from swsusp.
-        * Are they really necessary?
-        *
-        * We do not want some readahead with DMA to corrupt our memory, right?
-        * Do it with disabled interrupts for best effect. That way, if some
-        * driver scheduled DMA, we have good chance for DMA to finish ;-).
-        */
-       pr_debug("PM: Waiting for DMAs to settle down.\n");
-       mdelay(1000);
-
        pr_debug("PM: Restoring saved image.\n");
-       pmdisk_restore();
+       swsusp_resume();
        pr_debug("PM: Restore failed, recovering.n");
        finish();
  Free:
-       pmdisk_free();
+       swsusp_free();
  Done:
        pr_debug("PM: Resume from disk failed.\n");
        return 0;
 }
 
-late_initcall(pm_resume);
+late_initcall(software_resume);
 
 
 static char * pm_disk_modes[] = {
@@ -336,3 +342,22 @@ static int __init pm_disk_init(void)
 }
 
 core_initcall(pm_disk_init);
+
+
+static int __init resume_setup(char *str)
+{
+       if (noresume)
+               return 1;
+
+       strncpy( resume_file, str, 255 );
+       return 1;
+}
+
+static int __init noresume_setup(char *str)
+{
+       noresume = 1;
+       return 1;
+}
+
+__setup("noresume", noresume_setup);
+__setup("resume=", resume_setup);
index d582906..2f08a43 100644 (file)
@@ -8,8 +8,6 @@
  *
  */
 
-#define DEBUG
-
 #include <linux/suspend.h>
 #include <linux/kobject.h>
 #include <linux/string.h>
@@ -35,8 +33,6 @@ void pm_set_ops(struct pm_ops * ops)
 {
        down(&pm_sem);
        pm_ops = ops;
-       if (ops->pm_disk_mode && ops->pm_disk_mode < PM_DISK_MAX)
-               pm_disk_mode = ops->pm_disk_mode;
        up(&pm_sem);
 }
 
@@ -169,6 +165,15 @@ static int enter_state(u32 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.
@@ -225,8 +230,8 @@ static ssize_t state_store(struct subsystem * subsys, const char * buf, size_t n
        p = memchr(buf, '\n', n);
        len = p ? p - buf : n;
 
-       for (s = &pm_states[state]; *s; s++, state++) {
-               if (!strncmp(buf, *s, len))
+       for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
+               if (*s && !strncmp(buf, *s, len))
                        break;
        }
        if (*s)
index d180b0a..cd6a349 100644 (file)
@@ -1,4 +1,5 @@
-
+#include <linux/suspend.h>
+#include <linux/utsname.h>
 
 /* With SUSPEND_CONSOLE defined, it suspend looks *really* cool, but
    we probably do not take enough locks for switching consoles, etc,
@@ -9,7 +10,20 @@
 #endif
 
 
-#ifdef CONFIG_PM_DISK
+struct swsusp_info {
+       struct new_utsname      uts;
+       u32                     version_code;
+       unsigned long           num_physpages;
+       int                     cpus;
+       unsigned long           image_pages;
+       unsigned long           pagedir_pages;
+       suspend_pagedir_t       * suspend_pagedir;
+       swp_entry_t             pagedir[768];
+} __attribute__((aligned(PAGE_SIZE)));
+
+
+
+#ifdef CONFIG_SOFTWARE_SUSPEND
 extern int pm_suspend_disk(void);
 
 #else
@@ -18,7 +32,6 @@ static inline int pm_suspend_disk(void)
        return -EPERM;
 }
 #endif
-
 extern struct semaphore pm_sem;
 #define power_attr(_name) \
 static struct subsys_attribute _name##_attr = {        \
index 5c02ac0..cab1476 100644 (file)
@@ -8,38 +8,44 @@
 #include <linux/bootmem.h>
 #include <linux/notifier.h>
 #include <linux/mm.h>
+#include <linux/cpumask.h>
+#include <linux/profile.h>
 #include <asm/sections.h>
 
-unsigned int * prof_buffer;
-unsigned long prof_len;
-unsigned long prof_shift;
-int prof_on;
+static atomic_t *prof_buffer;
+static unsigned long prof_len, prof_shift;
+static int prof_on;
+static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
 
-int __init profile_setup(char * str)
+static int __init profile_setup(char * str)
 {
        int par;
+
+       if (!strncmp(str, "schedule", 8)) {
+               prof_on = 2;
+               printk(KERN_INFO "kernel schedule profiling enabled\n");
+               if (str[7] == ',')
+                       str += 8;
+       }
        if (get_option(&str,&par)) {
                prof_shift = par;
                prof_on = 1;
-               printk(KERN_INFO "kernel profiling enabled\n");
+               printk(KERN_INFO "kernel profiling enabled (shift: %ld)\n",
+                       prof_shift);
        }
        return 1;
 }
+__setup("profile=", profile_setup);
 
 
 void __init profile_init(void)
 {
-       unsigned int size;
        if (!prof_on) 
                return;
  
        /* only text is profiled */
-       prof_len = _etext - _stext;
-       prof_len >>= prof_shift;
-               
-       size = prof_len * sizeof(unsigned int) + PAGE_SIZE - 1;
-       prof_buffer = (unsigned int *) alloc_bootmem(size);
+       prof_len = (_etext - _stext) >> prof_shift;
+       prof_buffer = alloc_bootmem(prof_len*sizeof(atomic_t));
 }
 
 /* Profile event notifications */
@@ -47,31 +53,54 @@ void __init profile_init(void)
 #ifdef CONFIG_PROFILING
  
 static DECLARE_RWSEM(profile_rwsem);
-static struct notifier_block * exit_task_notifier;
-static struct notifier_block * exit_mmap_notifier;
-static struct notifier_block * exec_unmap_notifier;
+static rwlock_t handoff_lock = RW_LOCK_UNLOCKED;
+static struct notifier_block * task_exit_notifier;
+static struct notifier_block * task_free_notifier;
+static struct notifier_block * munmap_notifier;
  
-void profile_exit_task(struct task_struct * task)
+void profile_task_exit(struct task_struct * task)
 {
        down_read(&profile_rwsem);
-       notifier_call_chain(&exit_task_notifier, 0, task);
+       notifier_call_chain(&task_exit_notifier, 0, task);
        up_read(&profile_rwsem);
 }
  
-void profile_exit_mmap(struct mm_struct * mm)
+int profile_handoff_task(struct task_struct * task)
 {
-       down_read(&profile_rwsem);
-       notifier_call_chain(&exit_mmap_notifier, 0, mm);
-       up_read(&profile_rwsem);
+       int ret;
+       read_lock(&handoff_lock);
+       ret = notifier_call_chain(&task_free_notifier, 0, task);
+       read_unlock(&handoff_lock);
+       return (ret == NOTIFY_OK) ? 1 : 0;
 }
 
-void profile_exec_unmap(struct mm_struct * mm)
+void profile_munmap(unsigned long addr)
 {
        down_read(&profile_rwsem);
-       notifier_call_chain(&exec_unmap_notifier, 0, mm);
+       notifier_call_chain(&munmap_notifier, 0, (void *)addr);
        up_read(&profile_rwsem);
 }
 
+int task_handoff_register(struct notifier_block * n)
+{
+       int err = -EINVAL;
+
+       write_lock(&handoff_lock);
+       err = notifier_chain_register(&task_free_notifier, n);
+       write_unlock(&handoff_lock);
+       return err;
+}
+
+int task_handoff_unregister(struct notifier_block * n)
+{
+       int err = -EINVAL;
+
+       write_lock(&handoff_lock);
+       err = notifier_chain_unregister(&task_free_notifier, n);
+       write_unlock(&handoff_lock);
+       return err;
+}
+
 int profile_event_register(enum profile_type type, struct notifier_block * n)
 {
        int err = -EINVAL;
@@ -79,14 +108,11 @@ int profile_event_register(enum profile_type type, struct notifier_block * n)
        down_write(&profile_rwsem);
  
        switch (type) {
-               case EXIT_TASK:
-                       err = notifier_chain_register(&exit_task_notifier, n);
-                       break;
-               case EXIT_MMAP:
-                       err = notifier_chain_register(&exit_mmap_notifier, n);
+               case PROFILE_TASK_EXIT:
+                       err = notifier_chain_register(&task_exit_notifier, n);
                        break;
-               case EXEC_UNMAP:
-                       err = notifier_chain_register(&exec_unmap_notifier, n);
+               case PROFILE_MUNMAP:
+                       err = notifier_chain_register(&munmap_notifier, n);
                        break;
        }
  
@@ -103,14 +129,11 @@ int profile_event_unregister(enum profile_type type, struct notifier_block * n)
        down_write(&profile_rwsem);
  
        switch (type) {
-               case EXIT_TASK:
-                       err = notifier_chain_unregister(&exit_task_notifier, n);
+               case PROFILE_TASK_EXIT:
+                       err = notifier_chain_unregister(&task_exit_notifier, n);
                        break;
-               case EXIT_MMAP:
-                       err = notifier_chain_unregister(&exit_mmap_notifier, n);
-                       break;
-               case EXEC_UNMAP:
-                       err = notifier_chain_unregister(&exec_unmap_notifier, n);
+               case PROFILE_MUNMAP:
+                       err = notifier_chain_unregister(&munmap_notifier, n);
                        break;
        }
 
@@ -150,8 +173,150 @@ void profile_hook(struct pt_regs * regs)
 
 EXPORT_SYMBOL_GPL(register_profile_notifier);
 EXPORT_SYMBOL_GPL(unregister_profile_notifier);
+EXPORT_SYMBOL_GPL(task_handoff_register);
+EXPORT_SYMBOL_GPL(task_handoff_unregister);
 
 #endif /* CONFIG_PROFILING */
 
 EXPORT_SYMBOL_GPL(profile_event_register);
 EXPORT_SYMBOL_GPL(profile_event_unregister);
+
+void profile_hit(int type, void *__pc)
+{
+       unsigned long pc;
+
+       if (prof_on != type || !prof_buffer)
+               return;
+       pc = ((unsigned long)__pc - (unsigned long)_stext) >> prof_shift;
+       atomic_inc(&prof_buffer[min(pc, prof_len - 1)]);
+}
+
+void profile_tick(int type, struct pt_regs *regs)
+{
+       if (type == CPU_PROFILING)
+               profile_hook(regs);
+       if (!user_mode(regs) && cpu_isset(smp_processor_id(), prof_cpu_mask))
+               profile_hit(type, (void *)profile_pc(regs));
+}
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <asm/ptrace.h>
+
+static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
+                       int count, int *eof, void *data)
+{
+       int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
+       if (count - len < 2)
+               return -EINVAL;
+       len += sprintf(page + len, "\n");
+       return len;
+}
+
+static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
+                                       unsigned long count, void *data)
+{
+       cpumask_t *mask = (cpumask_t *)data;
+       unsigned long full_count = count, err;
+       cpumask_t new_value;
+
+       err = cpumask_parse(buffer, count, new_value);
+       if (err)
+               return err;
+
+       *mask = new_value;
+       return full_count;
+}
+
+void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir)
+{
+       struct proc_dir_entry *entry;
+
+       /* create /proc/irq/prof_cpu_mask */
+       if (!(entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir)))
+               return;
+       entry->nlink = 1;
+       entry->data = (void *)&prof_cpu_mask;
+       entry->read_proc = prof_cpu_mask_read_proc;
+       entry->write_proc = prof_cpu_mask_write_proc;
+}
+
+/*
+ * This function accesses profiling information. The returned data is
+ * binary: the sampling step and the actual contents of the profile
+ * buffer. Use of the program readprofile is recommended in order to
+ * get meaningful info out of these data.
+ */
+static ssize_t
+read_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+       unsigned long p = *ppos;
+       ssize_t read;
+       char * pnt;
+       unsigned int sample_step = 1 << prof_shift;
+
+       if (p >= (prof_len+1)*sizeof(unsigned int))
+               return 0;
+       if (count > (prof_len+1)*sizeof(unsigned int) - p)
+               count = (prof_len+1)*sizeof(unsigned int) - p;
+       read = 0;
+
+       while (p < sizeof(unsigned int) && count > 0) {
+               put_user(*((char *)(&sample_step)+p),buf);
+               buf++; p++; count--; read++;
+       }
+       pnt = (char *)prof_buffer + p - sizeof(atomic_t);
+       if (copy_to_user(buf,(void *)pnt,count))
+               return -EFAULT;
+       read += count;
+       *ppos += read;
+       return read;
+}
+
+/*
+ * Writing to /proc/profile resets the counters
+ *
+ * Writing a 'profiling multiplier' value into it also re-sets the profiling
+ * interrupt frequency, on architectures that support this.
+ */
+static ssize_t write_profile(struct file *file, const char __user *buf,
+                            size_t count, loff_t *ppos)
+{
+#ifdef CONFIG_SMP
+       extern int setup_profiling_timer (unsigned int multiplier);
+
+       if (count == sizeof(int)) {
+               unsigned int multiplier;
+
+               if (copy_from_user(&multiplier, buf, sizeof(int)))
+                       return -EFAULT;
+
+               if (setup_profiling_timer(multiplier))
+                       return -EINVAL;
+       }
+#endif
+
+       memset(prof_buffer, 0, prof_len * sizeof(atomic_t));
+       return count;
+}
+
+static struct file_operations proc_profile_operations = {
+       .read           = read_profile,
+       .write          = write_profile,
+};
+
+static int __init create_proc_profile(void)
+{
+       struct proc_dir_entry *entry;
+
+       if (!prof_on)
+               return 0;
+       if (!(entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL)))
+               return 0;
+       entry->proc_fops = &proc_profile_operations;
+       entry->size = (1+prof_len) * sizeof(atomic_t);
+       return 0;
+}
+module_init(create_proc_profile);
+#endif /* CONFIG_PROC_FS */
index 8b2856a..b14b4a4 100644 (file)
@@ -55,6 +55,15 @@ void __ptrace_unlink(task_t *child)
        REMOVE_LINKS(child);
        child->parent = child->real_parent;
        SET_LINKS(child);
+
+       if (child->state == TASK_TRACED) {
+               /*
+                * Turn a tracing stop into a normal stop now,
+                * since with no tracer there would be no way
+                * to wake it up with SIGCONT or SIGKILL.
+                */
+               child->state = TASK_STOPPED;
+       }
 }
 
 /*
@@ -62,20 +71,35 @@ void __ptrace_unlink(task_t *child)
  */
 int ptrace_check_attach(struct task_struct *child, int kill)
 {
-       if (!(child->ptrace & PT_PTRACED))
-               return -ESRCH;
+       int ret = -ESRCH;
 
-       if (child->parent != current)
-               return -ESRCH;
+       /*
+        * We take the read lock around doing both checks to close a
+        * possible race where someone else was tracing our child and
+        * detached between these two checks.  After this locked check,
+        * we are sure that this is our traced child and that can only
+        * be changed by us so it's not changing right after this.
+        */
+       read_lock(&tasklist_lock);
+       if ((child->ptrace & PT_PTRACED) && child->parent == current &&
+           child->signal != NULL) {
+               ret = 0;
+               spin_lock_irq(&child->sighand->siglock);
+               if (child->state == TASK_STOPPED) {
+                       child->state = TASK_TRACED;
+               } else if (child->state != TASK_TRACED && !kill) {
+                       ret = -ESRCH;
+               }
+               spin_unlock_irq(&child->sighand->siglock);
+       }
+       read_unlock(&tasklist_lock);
 
-       if (!kill) {
-               if (child->state != TASK_STOPPED)
-                       return -ESRCH;
+       if (!ret && !kill) {
                wait_task_inactive(child);
        }
 
        /* All systems go.. */
-       return 0;
+       return ret;
 }
 
 int ptrace_attach(struct task_struct *task)
@@ -178,8 +202,6 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
                if (bytes > PAGE_SIZE-offset)
                        bytes = PAGE_SIZE-offset;
 
-               flush_cache_page(vma, addr);
-
                maddr = kmap(page);
                if (write) {
                        copy_to_user_page(vma, page, addr,
@@ -322,24 +344,3 @@ int ptrace_request(struct task_struct *child, long request,
 
        return ret;
 }
-
-void ptrace_notify(int exit_code)
-{
-       BUG_ON (!(current->ptrace & PT_PTRACED));
-
-       /* Let the debugger run.  */
-       current->exit_code = exit_code;
-       set_current_state(TASK_STOPPED);
-       notify_parent(current, SIGCHLD);
-       schedule();
-
-       /*
-        * Signals sent while we were stopped might set TIF_SIGPENDING.
-        */
-
-       spin_lock_irq(&current->sighand->siglock);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-}
-
-EXPORT_SYMBOL(ptrace_notify);
index da0ffd6..4a3f5c2 100644 (file)
@@ -315,11 +315,12 @@ EXPORT_SYMBOL(allocate_resource);
  */
 int insert_resource(struct resource *parent, struct resource *new)
 {
-       int result = 0;
+       int result;
        struct resource *first, *next;
 
        write_lock(&resource_lock);
  begin:
+       result = 0;
        first = __request_resource(parent, new);
        if (!first)
                goto out;
@@ -328,15 +329,20 @@ int insert_resource(struct resource *parent, struct resource *new)
        if (first == parent)
                goto out;
 
-       for (next = first; next->sibling; next = next->sibling)
+       /* Resource fully contained by the clashing resource? Recurse into it */
+       if (first->start <= new->start && first->end >= new->end) {
+               parent = first;
+               goto begin;
+       }
+
+       for (next = first; ; next = next->sibling) {
+               /* Partial overlap? Bad, and unfixable */
+               if (next->start < new->start || next->end > new->end)
+                       goto out;
+               if (!next->sibling)
+                       break;
                if (next->sibling->start > new->end)
                        break;
-
-       /* existing resource includes new resource */
-       if (next->end >= new->end) {
-               parent = next;
-               result = 0;
-               goto begin;
        }
 
        result = 0;
index c336ae2..4a3da9b 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/percpu.h>
 #include <linux/cpu.h>
 #include <linux/kthread.h>
+#include <linux/rcupdate.h>
 
 #include <asm/irq.h>
 /*
@@ -75,10 +76,12 @@ asmlinkage void __do_softirq(void)
        struct softirq_action *h;
        __u32 pending;
        int max_restart = MAX_SOFTIRQ_RESTART;
+       int cpu;
 
        pending = local_softirq_pending();
 
        local_bh_disable();
+       cpu = smp_processor_id();
 restart:
        /* Reset the pending bitmask before enabling irqs */
        local_softirq_pending() = 0;
@@ -88,8 +91,10 @@ restart:
        h = softirq_vec;
 
        do {
-               if (pending & 1)
+               if (pending & 1) {
                        h->action(h);
+                       rcu_bh_qsctr_inc(cpu);
+               }
                h++;
                pending >>= 1;
        } while (pending);
diff --git a/kernel/spinlock.c b/kernel/spinlock.c
new file mode 100644 (file)
index 0000000..476da1f
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * Copyright (2004) Linus Torvalds
+ *
+ * Author: Zwane Mwaikambo <zwane@fsmlabs.com>
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/preempt.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+int __lockfunc _spin_trylock(spinlock_t *lock)
+{
+       preempt_disable();
+       if (_raw_spin_trylock(lock))
+               return 1;
+       
+       preempt_enable();
+       return 0;
+}
+EXPORT_SYMBOL(_spin_trylock);
+
+int __lockfunc _write_trylock(rwlock_t *lock)
+{
+       preempt_disable();
+       if (_raw_write_trylock(lock))
+               return 1;
+
+       preempt_enable();
+       return 0;
+}
+EXPORT_SYMBOL(_write_trylock);
+
+#ifdef CONFIG_PREEMPT
+/*
+ * This could be a long-held lock.  If another CPU holds it for a long time,
+ * and that CPU is not asked to reschedule then *this* CPU will spin on the
+ * lock for a long time, even if *this* CPU is asked to reschedule.
+ *
+ * So what we do here, in the slow (contended) path is to spin on the lock by
+ * hand while permitting preemption.
+ *
+ * Called inside preempt_disable().
+ */
+static inline void __preempt_spin_lock(spinlock_t *lock)
+{
+       if (preempt_count() > 1) {
+               _raw_spin_lock(lock);
+               return;
+       }
+
+       do {
+               preempt_enable();
+               while (spin_is_locked(lock))
+                       cpu_relax();
+               preempt_disable();
+       } while (!_raw_spin_trylock(lock));
+}
+
+void __lockfunc _spin_lock(spinlock_t *lock)
+{
+       preempt_disable();
+       if (unlikely(!_raw_spin_trylock(lock)))
+               __preempt_spin_lock(lock);
+}
+
+static inline void __preempt_write_lock(rwlock_t *lock)
+{
+       if (preempt_count() > 1) {
+               _raw_write_lock(lock);
+               return;
+       }
+
+       do {
+               preempt_enable();
+               while (rwlock_is_locked(lock))
+                       cpu_relax();
+               preempt_disable();
+       } while (!_raw_write_trylock(lock));
+}
+
+void __lockfunc _write_lock(rwlock_t *lock)
+{
+       preempt_disable();
+       if (unlikely(!_raw_write_trylock(lock)))
+               __preempt_write_lock(lock);
+}
+#else
+void __lockfunc _spin_lock(spinlock_t *lock)
+{
+       preempt_disable();
+       _raw_spin_lock(lock);
+}
+
+void __lockfunc _write_lock(rwlock_t *lock)
+{
+       preempt_disable();
+       _raw_write_lock(lock);
+}
+#endif
+EXPORT_SYMBOL(_spin_lock);
+EXPORT_SYMBOL(_write_lock);
+
+void __lockfunc _read_lock(rwlock_t *lock)
+{
+       preempt_disable();
+       _raw_read_lock(lock);
+}
+EXPORT_SYMBOL(_read_lock);
+
+void __lockfunc _spin_unlock(spinlock_t *lock)
+{
+       _raw_spin_unlock(lock);
+       preempt_enable();
+}
+EXPORT_SYMBOL(_spin_unlock);
+
+void __lockfunc _write_unlock(rwlock_t *lock)
+{
+       _raw_write_unlock(lock);
+       preempt_enable();
+}
+EXPORT_SYMBOL(_write_unlock);
+
+void __lockfunc _read_unlock(rwlock_t *lock)
+{
+       _raw_read_unlock(lock);
+       preempt_enable();
+}
+EXPORT_SYMBOL(_read_unlock);
+
+unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       preempt_disable();
+       _raw_spin_lock_flags(lock, flags);
+       return flags;
+}
+EXPORT_SYMBOL(_spin_lock_irqsave);
+
+void __lockfunc _spin_lock_irq(spinlock_t *lock)
+{
+       local_irq_disable();
+       preempt_disable();
+       _raw_spin_lock(lock);
+}
+EXPORT_SYMBOL(_spin_lock_irq);
+
+void __lockfunc _spin_lock_bh(spinlock_t *lock)
+{
+       local_bh_disable();
+       preempt_disable();
+       _raw_spin_lock(lock);
+}
+EXPORT_SYMBOL(_spin_lock_bh);
+
+unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       preempt_disable();
+       _raw_read_lock(lock);
+       return flags;
+}
+EXPORT_SYMBOL(_read_lock_irqsave);
+
+void __lockfunc _read_lock_irq(rwlock_t *lock)
+{
+       local_irq_disable();
+       preempt_disable();
+       _raw_read_lock(lock);
+}
+EXPORT_SYMBOL(_read_lock_irq);
+
+void __lockfunc _read_lock_bh(rwlock_t *lock)
+{
+       local_bh_disable();
+       preempt_disable();
+       _raw_read_lock(lock);
+}
+EXPORT_SYMBOL(_read_lock_bh);
+
+unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       preempt_disable();
+       _raw_write_lock(lock);
+       return flags;
+}
+EXPORT_SYMBOL(_write_lock_irqsave);
+
+void __lockfunc _write_lock_irq(rwlock_t *lock)
+{
+       local_irq_disable();
+       preempt_disable();
+       _raw_write_lock(lock);
+}
+EXPORT_SYMBOL(_write_lock_irq);
+
+void __lockfunc _write_lock_bh(rwlock_t *lock)
+{
+       local_bh_disable();
+       preempt_disable();
+       _raw_write_lock(lock);
+}
+EXPORT_SYMBOL(_write_lock_bh);
+
+void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
+{
+       _raw_spin_unlock(lock);
+       local_irq_restore(flags);
+       preempt_enable();
+}
+EXPORT_SYMBOL(_spin_unlock_irqrestore);
+
+void __lockfunc _spin_unlock_irq(spinlock_t *lock)
+{
+       _raw_spin_unlock(lock);
+       local_irq_enable();
+       preempt_enable();
+}
+EXPORT_SYMBOL(_spin_unlock_irq);
+
+void __lockfunc _spin_unlock_bh(spinlock_t *lock)
+{
+       _raw_spin_unlock(lock);
+       preempt_enable();
+       local_bh_enable();
+}
+EXPORT_SYMBOL(_spin_unlock_bh);
+
+void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
+{
+       _raw_read_unlock(lock);
+       local_irq_restore(flags);
+       preempt_enable();
+}
+EXPORT_SYMBOL(_read_unlock_irqrestore);
+
+void __lockfunc _read_unlock_irq(rwlock_t *lock)
+{
+       _raw_read_unlock(lock);
+       local_irq_enable();
+       preempt_enable();
+}
+EXPORT_SYMBOL(_read_unlock_irq);
+
+void __lockfunc _read_unlock_bh(rwlock_t *lock)
+{
+       _raw_read_unlock(lock);
+       preempt_enable();
+       local_bh_enable();
+}
+EXPORT_SYMBOL(_read_unlock_bh);
+
+void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
+{
+       _raw_write_unlock(lock);
+       local_irq_restore(flags);
+       preempt_enable();
+}
+EXPORT_SYMBOL(_write_unlock_irqrestore);
+
+void __lockfunc _write_unlock_irq(rwlock_t *lock)
+{
+       _raw_write_unlock(lock);
+       local_irq_enable();
+       preempt_enable();
+}
+EXPORT_SYMBOL(_write_unlock_irq);
+
+void __lockfunc _write_unlock_bh(rwlock_t *lock)
+{
+       _raw_write_unlock(lock);
+       preempt_enable();
+       local_bh_enable();
+}
+EXPORT_SYMBOL(_write_unlock_bh);
+
+int __lockfunc _spin_trylock_bh(spinlock_t *lock)
+{
+       local_bh_disable();
+       preempt_disable();
+       if (_raw_spin_trylock(lock))
+               return 1;
+
+       preempt_enable();
+       local_bh_enable();
+       return 0;
+}
+EXPORT_SYMBOL(_spin_trylock_bh);
+
+int in_lock_functions(unsigned long addr)
+{
+       /* Linker adds these: start and end of __lockfunc functions */
+       extern char __lock_text_start[], __lock_text_end[];
+
+       return addr >= (unsigned long)__lock_text_start
+       && addr < (unsigned long)__lock_text_end;
+}
+EXPORT_SYMBOL(in_lock_functions);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
new file mode 100644 (file)
index 0000000..cd5d859
--- /dev/null
@@ -0,0 +1,100 @@
+
+config DEBUG_KERNEL
+       bool "Kernel debugging"
+       depends on (ALPHA || ARM || CRIS || H8300 || X86 || IA64 || M68K || M68KNOMMU || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || SUPERH || SUPERH64 || SPARC32 || SPARC64 || USERMODE || V850 || X86_64)
+       help
+         Say Y here if you are developing drivers or trying to debug and
+         identify kernel problems.
+
+config MAGIC_SYSRQ
+       bool "Magic SysRq key"
+       depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || M68K || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || SUPERH || SUPERH64 || SPARC32 || SPARC64 || X86_64)
+       help
+         If you say Y here, you will have some control over the system even
+         if the system crashes for example during kernel debugging (e.g., you
+         will be able to flush the buffer cache to disk, reboot the system
+         immediately or dump some status information). This is accomplished
+         by pressing various keys while holding SysRq (Alt+PrintScreen). It
+         also works on a serial console (on PC hardware at least), if you
+         send a BREAK and then within 5 seconds a command keypress. The
+         keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
+         unless you really know what this hack does.
+
+config MAGIC_SYSRQ
+       bool "Magic SysRq key"
+       depends on DEBUG_KERNEL && (H8300 || M68KNOMMU || V850)
+       depends (USERMODE && MCONSOLE)
+       help
+         Enables console device to interpret special characters as
+         commands to dump state information.
+
+config DEBUG_SLAB
+       bool "Debug memory allocations"
+       depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || M68K || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || SPARC32 || SPARC64 || USERMODE || X86_64)
+       help
+         Say Y here to have the kernel do limited verification on memory
+         allocation as well as poisoning memory on free to catch use of freed
+         memory.
+
+config DEBUG_SPINLOCK
+       bool "Spinlock debugging"
+       depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || MIPS || PPC32 || (SUPERH && !SUPERH64) || SPARC32 || SPARC64 || USERMODE || X86_64)
+       help
+         Say Y here and build SMP to catch missing spinlock initialization
+         and certain other kinds of spinlock errors commonly made.  This is
+         best used in conjunction with the NMI watchdog so that spinlock
+         deadlocks are also debuggable.
+
+config DEBUG_SPINLOCK_SLEEP
+       bool "Sleep-inside-spinlock checking"
+       depends on DEBUG_KERNEL && (X86 || IA64 || MIPS || PPC32 || PPC64 || ARCH_S390 || SPARC32 || SPARC64)
+       help
+         If you say Y here, various routines which may sleep will become very
+         noisy if they are called with a spinlock held.
+
+config DEBUG_HIGHMEM
+       bool "Highmem debugging"
+       depends on DEBUG_KERNEL && HIGHMEM && (X86 || PPC32 || MIPS || SPARC32)
+       help
+         This options enables addition error checking for high memory systems.
+         Disable for production systems.
+
+config DEBUG_BUGVERBOSE
+       bool "Verbose BUG() reporting (adds 70K)"
+       depends on DEBUG_KERNEL && (ARM || ARM26 || M68K || SPARC32 || SPARC64)
+       help
+         Say Y here to make BUG() panics output the file name and line number
+         of the BUG call as well as the EIP and oops trace.  This aids
+         debugging but costs about 70-100K of memory.
+
+config DEBUG_INFO
+       bool "Compile the kernel with debug info"
+       depends on DEBUG_KERNEL && (ALPHA || CRIS || X86 || IA64 || M68K || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || (SUPERH && !SUPERH64) || SPARC64 || V850 || X86_64)
+       help
+          If you say Y here the resulting kernel image will include
+         debugging info resulting in a larger kernel image.
+         Say Y here only if you plan to use gdb to debug the kernel.
+         If you don't debug the kernel, you can say N.
+
+config DEBUG_INFO
+       bool "Enable kernel debugging symbols"
+       depends on DEBUG_KERNEL && USERMODE
+       help
+        When this is enabled, the User-Mode Linux binary will include
+        debugging symbols.  This enlarges the binary by a few megabytes,
+        but aids in tracking down kernel problems in UML.  It is required
+        if you intend to do any kernel development.
+
+        If you're truly short on disk space or don't expect to report any
+        bugs back to the UML developers, say N, otherwise say Y.
+
+if !X86_64
+config FRAME_POINTER
+       bool "Compile the kernel with frame pointers"
+       depends on X86 || CRIS || M68KNOMMU || PARISC
+       help
+         If you say Y here the resulting kernel image will be slightly larger
+         and slower, but it will give very useful debugging information.
+         If you don't debug the kernel, you can say N, but we may not be able
+         to solve problems without frame pointers.
+endif
diff --git a/lib/iomap.c b/lib/iomap.c
new file mode 100644 (file)
index 0000000..d30ff1a
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Implement the default iomap interfaces
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+/*
+ * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
+ * access or a MMIO access, these functions don't care. The info is
+ * encoded in the hardware mapping set up by the mapping functions
+ * (or the cookie itself, depending on implementation and hw).
+ *
+ * The generic routines don't assume any hardware mappings, and just
+ * encode the PIO/MMIO as part of the cookie. They coldly assume that
+ * the MMIO IO mappings are not in the low address range.
+ *
+ * Architectures for which this is not true can't use this generic
+ * implementation and should do their own copy.
+ *
+ * We encode the physical PIO addresses (0-0xffff) into the
+ * pointer by offsetting them with a constant (0x10000) and
+ * assuming that all the low addresses are always PIO. That means
+ * we can do some sanity checks on the low bits, and don't
+ * need to just take things for granted.
+ */
+#define PIO_OFFSET     0x10000UL
+#define PIO_MASK       0x0ffffUL
+#define PIO_RESERVED   0x40000UL
+
+/*
+ * 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);                               \
+               port &= PIO_MASK;                               \
+               is_pio;                                         \
+       } else {                                                \
+               is_mmio;                                        \
+       }                                                       \
+} while (0)
+
+unsigned int fastcall ioread8(void __iomem *addr)
+{
+       IO_COND(addr, return inb(port), return readb(addr));
+}
+unsigned int fastcall ioread16(void __iomem *addr)
+{
+       IO_COND(addr, return inw(port), return readw(addr));
+}
+unsigned int fastcall ioread32(void __iomem *addr)
+{
+       IO_COND(addr, return inl(port), return readl(addr));
+}
+EXPORT_SYMBOL(ioread8);
+EXPORT_SYMBOL(ioread16);
+EXPORT_SYMBOL(ioread32);
+
+void fastcall iowrite8(u8 val, void __iomem *addr)
+{
+       IO_COND(addr, outb(val,port), writeb(val, addr));
+}
+void fastcall iowrite16(u16 val, void __iomem *addr)
+{
+       IO_COND(addr, outw(val,port), writew(val, addr));
+}
+void fastcall iowrite32(u32 val, void __iomem *addr)
+{
+       IO_COND(addr, outl(val,port), writel(val, addr));
+}
+EXPORT_SYMBOL(iowrite8);
+EXPORT_SYMBOL(iowrite16);
+EXPORT_SYMBOL(iowrite32);
+
+/*
+ * These are the "repeat MMIO read/write" functions.
+ * Note the "__raw" accesses, since we don't want to
+ * convert to CPU byte order. We write in "IO byte
+ * order" (we also don't have IO barriers).
+ */
+static inline void mmio_insb(void __iomem *addr, u8 *dst, int count)
+{
+       while (--count >= 0) {
+               u8 data = __raw_readb(addr);
+               *dst = data;
+               dst++;
+       }
+}
+static inline void mmio_insw(void __iomem *addr, u16 *dst, int count)
+{
+       while (--count >= 0) {
+               u16 data = __raw_readw(addr);
+               *dst = data;
+               dst++;
+       }
+}
+static inline void mmio_insl(void __iomem *addr, u32 *dst, int count)
+{
+       while (--count >= 0) {
+               u32 data = __raw_readl(addr);
+               *dst = data;
+               dst++;
+       }
+}
+
+static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count)
+{
+       while (--count >= 0) {
+               __raw_writeb(*src, addr);
+               src++;
+       }
+}
+static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count)
+{
+       while (--count >= 0) {
+               __raw_writew(*src, addr);
+               src++;
+       }
+}
+static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count)
+{
+       while (--count >= 0) {
+               __raw_writel(*src, addr);
+               src++;
+       }
+}
+
+void fastcall ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+       IO_COND(addr, insb(port,dst,count), mmio_insb(addr, dst, count));
+}
+void fastcall ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+       IO_COND(addr, insw(port,dst,count), mmio_insw(addr, dst, count));
+}
+void fastcall ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+       IO_COND(addr, insl(port,dst,count), mmio_insl(addr, dst, count));
+}
+EXPORT_SYMBOL(ioread8_rep);
+EXPORT_SYMBOL(ioread16_rep);
+EXPORT_SYMBOL(ioread32_rep);
+
+void fastcall iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+       IO_COND(addr, outsb(port, src, count), mmio_outsb(addr, src, count));
+}
+void fastcall iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+       IO_COND(addr, outsw(port, src, count), mmio_outsw(addr, src, count));
+}
+void fastcall iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+       IO_COND(addr, outsl(port, src,count), mmio_outsl(addr, src, count));
+}
+EXPORT_SYMBOL(iowrite8_rep);
+EXPORT_SYMBOL(iowrite16_rep);
+EXPORT_SYMBOL(iowrite32_rep);
+
+/* Create a virtual mapping cookie for an IO port range */
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+       if (port > PIO_MASK)
+               return NULL;
+       return (void __iomem *) (unsigned long) (port + PIO_OFFSET);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+       /* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (!len || !start)
+               return NULL;
+       if (maxlen && len > maxlen)
+               len = maxlen;
+       if (flags & IORESOURCE_IO)
+               return ioport_map(start, len);
+       if (flags & IORESOURCE_MEM) {
+               if (flags & IORESOURCE_CACHEABLE)
+                       return ioremap(start, len);
+               return ioremap_nocache(start, len);
+       }
+       /* What? */
+       return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+       IO_COND(addr, /* nothing */, iounmap(addr));
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
index ee141ad..2218b7a 100644 (file)
  *
  */
 
-/* #define DEBUG */
-
 #include <linux/kref.h>
 #include <linux/module.h>
 
 /**
  * kref_init - initialize object.
  * @kref: object in question.
- * @release: pointer to a function that will clean up the object
- *          when the last reference to the object is released.
- *          This pointer is required.
  */
-void kref_init(struct kref *kref, void (*release)(struct kref *kref))
+void kref_init(struct kref *kref)
 {
-       WARN_ON(release == NULL);
        atomic_set(&kref->refcount,1);
-       kref->release = release;
 }
 
 /**
  * kref_get - increment refcount for object.
  * @kref: object.
  */
-struct kref *kref_get(struct kref *kref)
+void kref_get(struct kref *kref)
 {
        WARN_ON(!atomic_read(&kref->refcount));
        atomic_inc(&kref->refcount);
-       return kref;
 }
 
 /**
  * kref_put - decrement refcount for object.
  * @kref: object.
+ * @release: pointer to the function that will clean up the object when the
+ *          last reference to the object is released.
+ *          This pointer is required, and it is not acceptable to pass kfree
+ *          in as this function.
  *
- * Decrement the refcount, and if 0, call kref->release().
+ * Decrement the refcount, and if 0, call release().
  */
-void kref_put(struct kref *kref)
+void kref_put(struct kref *kref, void (*release) (struct kref *kref))
 {
-       if (atomic_dec_and_test(&kref->refcount)) {
-               pr_debug("kref cleaning up\n");
-               kref->release(kref);
-       }
+       WARN_ON(release == NULL);
+       WARN_ON(release == (void (*)(struct kref *))kfree);
+
+       if (atomic_dec_and_test(&kref->refcount))
+               release(kref);
 }
 
 EXPORT_SYMBOL(kref_init);
index 0408851..221c139 100644 (file)
@@ -16,4 +16,4 @@
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o
 
 zlib_inflate-objs := infblock.o infcodes.o inffast.o inflate.o \
-                    inftrees.o infutil.o inflate_syms.o
+                    inflate_sync.o inftrees.o infutil.o inflate_syms.o
index 7bb7db5..50f21ca 100644 (file)
@@ -139,7 +139,7 @@ int zlib_inflate_blocks(
             uInt bl, bd;
             inflate_huft *tl, *td;
 
-            zlib_inflate_trees_fixed(&bl, &bd, &tl, &td, z);
+            zlib_inflate_trees_fixed(&bl, &bd, &tl, &td, s->hufts, z);
             s->sub.decode.codes = zlib_inflate_codes_new(bl, bd, tl, td, z);
             if (s->sub.decode.codes == NULL)
             {
index 974a0fe..3d94cb9 100644 (file)
@@ -53,8 +53,6 @@ int zlib_inflateInit2_(
       return Z_VERSION_ERROR;
 
   /* initialize state */
-  if (z == NULL)
-    return Z_STREAM_ERROR;
   z->msg = NULL;
   z->state = &WS(z)->internal_state;
   z->state->blocks = NULL;
@@ -248,144 +246,3 @@ int zlib_inflate(
   z->state->sub.marker = 0;       /* can try inflateSync */
   return Z_DATA_ERROR;
 }
-
-
-int zlib_inflateSync(
-       z_streamp z
-)
-{
-  uInt n;       /* number of bytes to look at */
-  Byte *p;      /* pointer to bytes */
-  uInt m;       /* number of marker bytes found in a row */
-  uLong r, w;   /* temporaries to save total_in and total_out */
-
-  /* set up */
-  if (z == NULL || z->state == NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->mode != I_BAD)
-  {
-    z->state->mode = I_BAD;
-    z->state->sub.marker = 0;
-  }
-  if ((n = z->avail_in) == 0)
-    return Z_BUF_ERROR;
-  p = z->next_in;
-  m = z->state->sub.marker;
-
-  /* search */
-  while (n && m < 4)
-  {
-    static const Byte mark[4] = {0, 0, 0xff, 0xff};
-    if (*p == mark[m])
-      m++;
-    else if (*p)
-      m = 0;
-    else
-      m = 4 - m;
-    p++, n--;
-  }
-
-  /* restore */
-  z->total_in += p - z->next_in;
-  z->next_in = p;
-  z->avail_in = n;
-  z->state->sub.marker = m;
-
-  /* return no joy or set up to restart on a new block */
-  if (m != 4)
-    return Z_DATA_ERROR;
-  r = z->total_in;  w = z->total_out;
-  zlib_inflateReset(z);
-  z->total_in = r;  z->total_out = w;
-  z->state->mode = BLOCKS;
-  return Z_OK;
-}
-
-
-/* Returns true if inflate is currently at the end of a block generated
- * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
- * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
- * but removes the length bytes of the resulting empty stored block. When
- * decompressing, PPP checks that at the end of input packet, inflate is
- * waiting for these length bytes.
- */
-int zlib_inflateSyncPoint(
-       z_streamp z
-)
-{
-  if (z == NULL || z->state == NULL || z->state->blocks == NULL)
-    return Z_STREAM_ERROR;
-  return zlib_inflate_blocks_sync_point(z->state->blocks);
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-static int zlib_inflate_addhistory(inflate_blocks_statef *s,
-                                     z_stream              *z)
-{
-    uLong b;              /* bit buffer */  /* NOT USED HERE */
-    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
-    uInt t;               /* temporary storage */
-    Byte *p;              /* input data pointer */
-    uInt n;               /* bytes available there */
-    Byte *q;              /* output window write pointer */
-    uInt m;               /* bytes to end of window or read pointer */
-
-    if (s->read != s->write)
-       return Z_STREAM_ERROR;
-    if (s->mode != TYPE)
-       return Z_DATA_ERROR;
-
-    /* we're ready to rock */
-    LOAD
-    /* while there is input ready, copy to output buffer, moving
-     * pointers as needed.
-     */
-    while (n) {
-       t = n;  /* how many to do */
-       /* is there room until end of buffer? */
-       if (t > m) t = m;
-       /* update check information */
-       if (s->checkfn != NULL)
-           s->check = (*s->checkfn)(s->check, q, t);
-       memcpy(q, p, t);
-       q += t;
-       p += t;
-       n -= t;
-       z->total_out += t;
-       s->read = q;    /* drag read pointer forward */
-/*      WWRAP  */      /* expand WWRAP macro by hand to handle s->read */
-       if (q == s->end) {
-           s->read = q = s->window;
-           m = WAVAIL;
-       }
-    }
-    UPDATE
-    return Z_OK;
-}
-
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-
-int zlib_inflateIncomp(
-       z_stream *z
-       
-)
-{
-    if (z->state->mode != BLOCKS)
-       return Z_DATA_ERROR;
-    return zlib_inflate_addhistory(z->state->blocks, z);
-}
diff --git a/lib/zlib_inflate/inflate_sync.c b/lib/zlib_inflate/inflate_sync.c
new file mode 100644 (file)
index 0000000..e07bdb2
--- /dev/null
@@ -0,0 +1,148 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include <linux/zutil.h>
+#include "infblock.h"
+#include "infutil.h"
+
+int zlib_inflateSync(
+       z_streamp z
+)
+{
+  uInt n;       /* number of bytes to look at */
+  Byte *p;      /* pointer to bytes */
+  uInt m;       /* number of marker bytes found in a row */
+  uLong r, w;   /* temporaries to save total_in and total_out */
+
+  /* set up */
+  if (z == NULL || z->state == NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode != I_BAD)
+  {
+    z->state->mode = I_BAD;
+    z->state->sub.marker = 0;
+  }
+  if ((n = z->avail_in) == 0)
+    return Z_BUF_ERROR;
+  p = z->next_in;
+  m = z->state->sub.marker;
+
+  /* search */
+  while (n && m < 4)
+  {
+    static const Byte mark[4] = {0, 0, 0xff, 0xff};
+    if (*p == mark[m])
+      m++;
+    else if (*p)
+      m = 0;
+    else
+      m = 4 - m;
+    p++, n--;
+  }
+
+  /* restore */
+  z->total_in += p - z->next_in;
+  z->next_in = p;
+  z->avail_in = n;
+  z->state->sub.marker = m;
+
+  /* return no joy or set up to restart on a new block */
+  if (m != 4)
+    return Z_DATA_ERROR;
+  r = z->total_in;  w = z->total_out;
+  zlib_inflateReset(z);
+  z->total_in = r;  z->total_out = w;
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+ * but removes the length bytes of the resulting empty stored block. When
+ * decompressing, PPP checks that at the end of input packet, inflate is
+ * waiting for these length bytes.
+ */
+int zlib_inflateSyncPoint(
+       z_streamp z
+)
+{
+  if (z == NULL || z->state == NULL || z->state->blocks == NULL)
+    return Z_STREAM_ERROR;
+  return zlib_inflate_blocks_sync_point(z->state->blocks);
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output.  The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS).  On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+static int zlib_inflate_addhistory(inflate_blocks_statef *s,
+                                     z_stream              *z)
+{
+    uLong b;              /* bit buffer */  /* NOT USED HERE */
+    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
+    uInt t;               /* temporary storage */
+    Byte *p;              /* input data pointer */
+    uInt n;               /* bytes available there */
+    Byte *q;              /* output window write pointer */
+    uInt m;               /* bytes to end of window or read pointer */
+
+    if (s->read != s->write)
+       return Z_STREAM_ERROR;
+    if (s->mode != TYPE)
+       return Z_DATA_ERROR;
+
+    /* we're ready to rock */
+    LOAD
+    /* while there is input ready, copy to output buffer, moving
+     * pointers as needed.
+     */
+    while (n) {
+       t = n;  /* how many to do */
+       /* is there room until end of buffer? */
+       if (t > m) t = m;
+       /* update check information */
+       if (s->checkfn != NULL)
+           s->check = (*s->checkfn)(s->check, q, t);
+       memcpy(q, p, t);
+       q += t;
+       p += t;
+       n -= t;
+       z->total_out += t;
+       s->read = q;    /* drag read pointer forward */
+/*      WWRAP  */      /* expand WWRAP macro by hand to handle s->read */
+       if (q == s->end) {
+           s->read = q = s->window;
+           m = WAVAIL;
+       }
+    }
+    UPDATE
+    return Z_OK;
+}
+
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output.  The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS).  On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+
+int zlib_inflateIncomp(
+       z_stream *z
+
+)
+{
+    if (z->state->mode != BLOCKS)
+       return Z_DATA_ERROR;
+    return zlib_inflate_addhistory(z->state->blocks, z);
+}
index efb3d8a..e37705a 100644 (file)
@@ -58,6 +58,7 @@ extern int zlib_inflate_trees_fixed (
     uInt *,                     /* distance desired/actual bit depth */
     inflate_huft **,            /* literal/length tree result */
     inflate_huft **,            /* distance tree result */
+    inflate_huft *,             /* space for trees */
     z_streamp);                 /* for memory allocation */
 
 #endif /* _INFTREES_H */
index d06eabb..8fe9c7e 100644 (file)
@@ -146,6 +146,8 @@ static int get_nodes(unsigned long *nodes, unsigned long __user *nmask,
        /* When the user specified more nodes than supported just check
           if the non supported part is all zero. */
        if (nlongs > BITS_TO_LONGS(MAX_NUMNODES)) {
+               if (nlongs > PAGE_SIZE/sizeof(long))
+                       return -EINVAL;
                for (k = BITS_TO_LONGS(MAX_NUMNODES); k < nlongs; k++) {
                        unsigned long t;
                        if (get_user(t,  nmask + k))
@@ -438,7 +440,7 @@ static int lookup_node(struct mm_struct *mm, unsigned long addr)
 
        err = get_user_pages(current, mm, addr & PAGE_MASK, 1, 0, 0, &p, NULL);
        if (err >= 0) {
-               err = page_zone(p)->zone_pgdat->node_id;
+               err = page_to_nid(p);
                put_page(p);
        }
        return err;
@@ -526,20 +528,82 @@ asmlinkage long sys_get_mempolicy(int __user *policy,
 }
 
 #ifdef CONFIG_COMPAT
-/* The other functions are compatible */
+
 asmlinkage long compat_get_mempolicy(int __user *policy,
-                                 unsigned __user *nmask, unsigned  maxnode,
-                                 unsigned addr, unsigned  flags)
+                                    compat_ulong_t __user *nmask,
+                                    compat_ulong_t maxnode,
+                                    compat_ulong_t addr, compat_ulong_t flags)
 {
        long err;
        unsigned long __user *nm = NULL;
+       unsigned long nr_bits, alloc_size;
+       DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+       nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+       alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
        if (nmask)
-               nm = compat_alloc_user_space(ALIGN(maxnode-1, 64) / 8);
-       err = sys_get_mempolicy(policy, nm, maxnode, addr, flags);
-       if (!err && copy_in_user(nmask, nm, ALIGN(maxnode-1, 32)/8))
-               err = -EFAULT;
+               nm = compat_alloc_user_space(alloc_size);
+
+       err = sys_get_mempolicy(policy, nm, nr_bits+1, addr, flags);
+
+       if (!err && nmask) {
+               err = copy_from_user(bm, nm, alloc_size);
+               /* ensure entire bitmap is zeroed */
+               err |= clear_user(nmask, ALIGN(maxnode-1, 8) / 8);
+               err |= compat_put_bitmap(nmask, bm, nr_bits);
+       }
+
        return err;
 }
+
+asmlinkage long compat_set_mempolicy(int mode, compat_ulong_t __user *nmask,
+                                    compat_ulong_t maxnode)
+{
+       long err = 0;
+       unsigned long __user *nm = NULL;
+       unsigned long nr_bits, alloc_size;
+       DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+       nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+       alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
+       if (nmask) {
+               err = compat_get_bitmap(bm, nmask, nr_bits);
+               nm = compat_alloc_user_space(alloc_size);
+               err |= copy_to_user(nm, bm, alloc_size);
+       }
+
+       if (err)
+               return -EFAULT;
+
+       return sys_set_mempolicy(mode, nm, nr_bits+1);
+}
+
+asmlinkage long compat_mbind(compat_ulong_t start, compat_ulong_t len,
+                            compat_ulong_t mode, compat_ulong_t __user *nmask,
+                            compat_ulong_t maxnode, compat_ulong_t flags)
+{
+       long err = 0;
+       unsigned long __user *nm = NULL;
+       unsigned long nr_bits, alloc_size;
+       DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+       nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+       alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
+       if (nmask) {
+               err = compat_get_bitmap(bm, nmask, nr_bits);
+               nm = compat_alloc_user_space(alloc_size);
+               err |= copy_to_user(nm, bm, alloc_size);
+       }
+
+       if (err)
+               return -EFAULT;
+
+       return sys_mbind(start, len, mode, nm, nr_bits+1, flags);
+}
+
 #endif
 
 /* Return effective policy for a VMA */
diff --git a/mm/thrash.c b/mm/thrash.c
new file mode 100644 (file)
index 0000000..7183937
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * mm/thrash.c
+ *
+ * Copyright (C) 2004, Red Hat, Inc.
+ * Copyright (C) 2004, Rik van Riel <riel@redhat.com>
+ * Released under the GPL, see the file COPYING for details.
+ *
+ * Simple token based thrashing protection, using the algorithm
+ * described in:  http://www.cs.wm.edu/~sjiang/token.pdf
+ */
+#include <linux/jiffies.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/swap.h>
+
+static spinlock_t swap_token_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long swap_token_timeout;
+unsigned long swap_token_check;
+struct mm_struct * swap_token_mm = &init_mm;
+
+#define SWAP_TOKEN_CHECK_INTERVAL (HZ * 2)
+#define SWAP_TOKEN_TIMEOUT (HZ * 300)
+
+/*
+ * Take the token away if the process had no page faults
+ * in the last interval, or if it has held the token for
+ * too long.
+ */
+#define SWAP_TOKEN_ENOUGH_RSS 1
+#define SWAP_TOKEN_TIMED_OUT 2
+static int should_release_swap_token(struct mm_struct *mm)
+{
+       int ret = 0;
+       if (!mm->recent_pagein)
+               ret = SWAP_TOKEN_ENOUGH_RSS;
+       else if (time_after(jiffies, swap_token_timeout))
+               ret = SWAP_TOKEN_TIMED_OUT;
+       mm->recent_pagein = 0;
+       return ret;
+}
+
+/*
+ * Try to grab the swapout protection token.  We only try to
+ * grab it once every TOKEN_CHECK_INTERVAL, both to prevent
+ * SMP lock contention and to check that the process that held
+ * the token before is no longer thrashing.
+ */
+void grab_swap_token(void)
+{
+       struct mm_struct *mm;
+       int reason;
+
+       /* We have the token. Let others know we still need it. */
+       if (has_swap_token(current->mm)) {
+               current->mm->recent_pagein = 1;
+               return;
+       }
+
+       if (time_after(jiffies, swap_token_check)) {
+
+               /* Can't get swapout protection if we exceed our RSS limit. */
+               // if (current->mm->rss > current->mm->rlimit_rss)
+               //      return;
+
+               /* ... or if we recently held the token. */
+               if (time_before(jiffies, current->mm->swap_token_time))
+                       return;
+
+               if (!spin_trylock(&swap_token_lock))
+                       return;
+
+               swap_token_check = jiffies + SWAP_TOKEN_CHECK_INTERVAL;
+
+               mm = swap_token_mm;
+               if ((reason = should_release_swap_token(mm))) {
+                       unsigned long eligible = jiffies;
+                       if (reason == SWAP_TOKEN_TIMED_OUT) {
+                               eligible += SWAP_TOKEN_TIMEOUT;
+                       }
+                       mm->swap_token_time = eligible;
+                       swap_token_timeout = jiffies + SWAP_TOKEN_TIMEOUT;
+                       swap_token_mm = current->mm;
+               }
+               spin_unlock(&swap_token_lock);
+       }
+       return;
+}
+
+/* Called on process exit. */
+void __put_swap_token(struct mm_struct *mm)
+{
+       spin_lock(&swap_token_lock);
+       if (likely(mm == swap_token_mm)) {
+               swap_token_mm = &init_mm;
+               swap_token_check = jiffies;
+       }
+       spin_unlock(&swap_token_lock);
+}
diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c
new file mode 100644 (file)
index 0000000..90abc63
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * tiny-shmem.c: simple shmemfs and tmpfs using ramfs code
+ *
+ * Matt Mackall <mpm@selenic.com> January, 2004
+ * derived from mm/shmem.c and fs/ramfs/inode.c
+ *
+ * This is intended for small system where the benefits of the full
+ * shmem code (swap-backed and resource-limited) are outweighed by
+ * their complexity. On systems without swap this code should be
+ * effectively equivalent, but much lighter weight.
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/vfs.h>
+#include <linux/mount.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/swap.h>
+#include <linux/ramfs.h>
+
+static struct file_system_type tmpfs_fs_type = {
+       .name           = "tmpfs",
+       .get_sb         = ramfs_get_sb,
+       .kill_sb        = kill_litter_super,
+};
+
+static struct vfsmount *shm_mnt;
+
+static int __init init_tmpfs(void)
+{
+       register_filesystem(&tmpfs_fs_type);
+#ifdef CONFIG_TMPFS
+       devfs_mk_dir("shm");
+#endif
+       shm_mnt = kern_mount(&tmpfs_fs_type);
+       return 0;
+}
+module_init(init_tmpfs)
+
+/*
+ * shmem_file_setup - get an unlinked file living in tmpfs
+ *
+ * @name: name for dentry (to be seen in /proc/<pid>/maps
+ * @size: size to be set for the file
+ *
+ */
+struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
+{
+       int error;
+       struct file *file;
+       struct inode *inode;
+       struct dentry *dentry, *root;
+       struct qstr this;
+
+       if (IS_ERR(shm_mnt))
+               return (void *)shm_mnt;
+
+       error = -ENOMEM;
+       this.name = name;
+       this.len = strlen(name);
+       this.hash = 0; /* will go */
+       root = shm_mnt->mnt_root;
+       dentry = d_alloc(root, &this);
+       if (!dentry)
+               goto put_memory;
+
+       error = -ENFILE;
+       file = get_empty_filp();
+       if (!file)
+               goto put_dentry;
+
+       error = -ENOSPC;
+       inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
+       if (!inode)
+               goto close_file;
+
+       d_instantiate(dentry, inode);
+       inode->i_size = size;
+       inode->i_nlink = 0;     /* It is unlinked */
+       file->f_vfsmnt = mntget(shm_mnt);
+       file->f_dentry = dentry;
+       file->f_mapping = inode->i_mapping;
+       file->f_op = &ramfs_file_operations;
+       file->f_mode = FMODE_WRITE | FMODE_READ;
+       return file;
+
+close_file:
+       put_filp(file);
+put_dentry:
+       dput(dentry);
+put_memory:
+       return ERR_PTR(error);
+}
+
+/*
+ * shmem_zero_setup - setup a shared anonymous mapping
+ *
+ * @vma: the vma to be mmapped is prepared by do_mmap_pgoff
+ */
+int shmem_zero_setup(struct vm_area_struct *vma)
+{
+       struct file *file;
+       loff_t size = vma->vm_end - vma->vm_start;
+
+       file = shmem_file_setup("dev/zero", size, vma->vm_flags);
+       if (IS_ERR(file))
+               return PTR_ERR(file);
+
+       if (vma->vm_file)
+               fput(vma->vm_file);
+       vma->vm_file = file;
+       vma->vm_ops = &generic_file_vm_ops;
+       return 0;
+}
+
+int shmem_unuse(swp_entry_t entry, struct page *page)
+{
+       return 0;
+}
+
+EXPORT_SYMBOL(shmem_file_setup);
index df99704..3ee1dcd 100644 (file)
@@ -537,7 +537,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
 
 out_free_unregister:
        unregister_netdev(new_dev);
-       goto out_put_dev;
+       goto out_unlock;
 
 out_free_newdev:
        free_netdev(new_dev);
index cbe8a6a..d179728 100644 (file)
@@ -4,5 +4,6 @@
 
 obj-$(CONFIG_ATALK) += appletalk.o
 
-appletalk-y                    := aarp.o ddp.o atalk_proc.o
+appletalk-y                    := aarp.o ddp.o
+appletalk-$(CONFIG_PROC_FS)    += atalk_proc.o
 appletalk-$(CONFIG_SYSCTL)     += sysctl_net_atalk.o
index 1e00a58..4d20501 100644 (file)
@@ -15,8 +15,6 @@
 #include <net/sock.h>
 #include <linux/atalk.h>
 
-#ifdef CONFIG_PROC_FS
-extern struct file_operations atalk_seq_arp_fops;
 
 static __inline__ struct atalk_iface *atalk_get_interface_idx(loff_t pos)
 {
@@ -321,14 +319,3 @@ void __exit atalk_proc_exit(void)
        remove_proc_entry("arp", atalk_proc_dir);
        remove_proc_entry("atalk", proc_net);
 }
-
-#else /* CONFIG_PROC_FS */
-int __init atalk_proc_init(void)
-{
-       return 0;
-}
-
-void __exit atalk_proc_exit(void)
-{
-}
-#endif /* CONFIG_PROC_FS */
index 25b33f6..af7f060 100644 (file)
@@ -7,13 +7,9 @@
  */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
-extern int sysctl_aarp_expiry_time;
-extern int sysctl_aarp_tick_time;
-extern int sysctl_aarp_retransmit_limit;
-extern int sysctl_aarp_resolve_time;
+#include <net/sock.h>
+#include <linux/atalk.h>
 
 static struct ctl_table atalk_table[] = {
        {
@@ -85,13 +81,3 @@ void atalk_unregister_sysctl(void)
 {
        unregister_sysctl_table(atalk_table_header);
 }
-
-#else /* CONFIG_PROC_FS */
-void atalk_register_sysctl(void)
-{
-}
-
-void atalk_unregister_sysctl(void)
-{
-}
-#endif /* CONFIG_PROC_FS */ 
index d4cb95c..e49ed41 100644 (file)
@@ -24,11 +24,6 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
 int vcc_getsockopt(struct socket *sock, int level, int optname,
                   char __user *optval, int __user *optlen);
 
-void atm_shutdown_dev(struct atm_dev *dev);
-
-void pppoatm_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long));
-void br2684_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long));
-
 int atmpvc_init(void);
 void atmpvc_exit(void);
 int atmsvc_init(void);
@@ -50,12 +45,6 @@ static inline void atm_proc_exit(void)
 #endif /* CONFIG_PROC_FS */
 
 /* SVC */
-
-void svc_callback(struct atm_vcc *vcc);
 int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);
 
-/* p2mp */
-
-int create_leaf(struct socket *leaf,struct socket *session);
-
 #endif
index bc1675e..d72165f 100644 (file)
@@ -12,9 +12,6 @@
 #include <linux/netdevice.h>
 #include <linux/atmdev.h>
 
-
-extern struct net_device *clip_devs;
-
 /*
  * Appends all skbs from "from" to "to". The operation is atomic with respect
  * to all other skb operations on "from" or "to".
index c544f92..9c19021 100644 (file)
@@ -151,7 +151,6 @@ int lecd_attach(struct atm_vcc *vcc, int arg);
 int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg);
 int lec_mcast_attach(struct atm_vcc *vcc, int arg);
 struct net_device *get_dev_lec(int itf);
-int make_lec(struct atm_vcc *vcc);
 int send_to_lecd(struct lec_priv *priv,
                  atmlec_msg_type type, unsigned char *mac_addr,
                  unsigned char *atm_addr, struct sk_buff *data);
index e7f9e67..01a2c86 100644 (file)
@@ -372,7 +372,6 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
                skb_queue_head(&sk->sk_receive_queue, skb);
 
                make->sk_state = TCP_ESTABLISHED;
-               make->sk_pair  = sk;
 
                sk->sk_ack_backlog++;
                bh_unlock_sock(sk);
index a87cc64..682bf20 100644 (file)
@@ -384,7 +384,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
        
        s->stats.rx_packets++;
        nskb->dev       = dev;
-       nskb->ip_summed = CHECKSUM_UNNECESSARY;
+       nskb->ip_summed = CHECKSUM_NONE;
        nskb->protocol  = eth_type_trans(nskb, dev);
        netif_rx_ni(nskb);
        return 0;
index fdf8f9e..943d5dd 100644 (file)
@@ -45,27 +45,15 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
                        br_pass_frame_up_finish);
 }
 
+/* note: already called with rcu_read_lock (preempt_disabled) */
 int br_handle_frame_finish(struct sk_buff *skb)
 {
-       struct net_bridge *br;
-       unsigned char *dest;
+       const unsigned char *dest = eth_hdr(skb)->h_dest;
+       struct net_bridge_port *p = skb->dev->br_port;
+       struct net_bridge *br = p->br;
        struct net_bridge_fdb_entry *dst;
-       struct net_bridge_port *p;
-       int passedup;
+       int passedup = 0;
 
-       dest = skb->mac.ethernet->h_dest;
-
-       rcu_read_lock();
-       p = skb->dev->br_port;
-       smp_read_barrier_depends();
-
-       if (p == NULL || p->state == BR_STATE_DISABLED) {
-               kfree_skb(skb);
-               goto out;
-       }
-
-       br = p->br;
-       passedup = 0;
        if (br->dev->flags & IFF_PROMISC) {
                struct sk_buff *skb2;
 
@@ -100,28 +88,29 @@ int br_handle_frame_finish(struct sk_buff *skb)
        br_flood_forward(br, skb, 0);
 
 out:
-       rcu_read_unlock();
        return 0;
 }
 
-int br_handle_frame(struct sk_buff *skb)
+/*
+ * Called via br_handle_frame_hook.
+ * Return 0 if *pskb should be processed furthur
+ *       1 if *pskb is handled
+ * note: already called with rcu_read_lock (preempt_disabled) 
+ */
+int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
 {
-       unsigned char *dest;
-       struct net_bridge_port *p;
+       struct sk_buff *skb = *pskb;
+       const unsigned char *dest = eth_hdr(skb)->h_dest;
 
-       dest = skb->mac.ethernet->h_dest;
-
-       rcu_read_lock();
-       p = skb->dev->br_port;
-       if (p == NULL || p->state == BR_STATE_DISABLED)
+       if (p->state == BR_STATE_DISABLED)
                goto err;
 
-       if (skb->mac.ethernet->h_source[0] & 1)
+       if (eth_hdr(skb)->h_source[0] & 1)
                goto err;
 
        if (p->state == BR_STATE_LEARNING ||
            p->state == BR_STATE_FORWARDING)
-               br_fdb_insert(p->br, p, skb->mac.ethernet->h_source, 0);
+               br_fdb_insert(p->br, p, eth_hdr(skb)->h_source, 0);
 
        if (p->br->stp_enabled &&
            !memcmp(dest, bridge_ula, 5) &&
@@ -129,15 +118,16 @@ int br_handle_frame(struct sk_buff *skb)
                if (!dest[5]) {
                        NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, 
                                NULL, br_stp_handle_bpdu);
-                       rcu_read_unlock();
-                       return 0;
+                       return 1;
                }
        }
 
        else if (p->state == BR_STATE_FORWARDING) {
-               if (br_should_route_hook && br_should_route_hook(&skb)) {
-                       rcu_read_unlock();
-                       return -1;
+               if (br_should_route_hook) {
+                       if (br_should_route_hook(pskb)) 
+                               return 0;
+                       skb = *pskb;
+                       dest = eth_hdr(skb)->h_dest;
                }
 
                if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN))
@@ -145,12 +135,10 @@ int br_handle_frame(struct sk_buff *skb)
 
                NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
                        br_handle_frame_finish);
-               rcu_read_unlock();
-               return 0;
+               return 1;
        }
 
 err:
-       rcu_read_unlock();
        kfree_skb(skb);
-       return 0;
+       return 1;
 }
index 404dda3..50e4df3 100644 (file)
@@ -11,6 +11,7 @@
  *     Jun 19 2003: let arptables see bridged ARP traffic (bdschuym)
  *     Oct 06 2003: filter encapsulated IP/ARP VLAN traffic on untagged bridge
  *                  (bdschuym)
+ *     Sep 01 2004: add IPv6 filtering (bdschuym)
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
 #include <linux/if_vlan.h>
 #include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
 #include <linux/netfilter_arp.h>
 #include <linux/in_route.h>
 #include <net/ip.h>
+#include <net/ipv6.h>
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include "br_private.h"
@@ -39,7 +42,6 @@
 #include <linux/sysctl.h>
 #endif
 
-
 #define skb_origaddr(skb)       (((struct bridge_skb_cb *) \
                                 (skb->nf_bridge->data))->daddr.ipv4)
 #define store_orig_dstaddr(skb)         (skb_origaddr(skb) = (skb)->nh.iph->daddr)
@@ -51,6 +53,7 @@
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
 static int brnf_call_iptables = 1;
+static int brnf_call_ip6tables = 1;
 static int brnf_call_arptables = 1;
 static int brnf_filter_vlan_tagged = 1;
 #else
@@ -60,6 +63,9 @@ static int brnf_filter_vlan_tagged = 1;
 #define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) &&    \
        hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP) &&  \
        brnf_filter_vlan_tagged)
+#define IS_VLAN_IPV6 (skb->protocol == __constant_htons(ETH_P_8021Q) &&    \
+       hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IPV6) &&  \
+       brnf_filter_vlan_tagged)
 #define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) &&   \
        hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP) && \
        brnf_filter_vlan_tagged)
@@ -71,8 +77,7 @@ static int brnf_filter_vlan_tagged = 1;
  * Currently, we fill in the PMTU entry because netfilter
  * refragmentation needs it, and the rt_flags entry because
  * ipt_REJECT needs it.  Future netfilter modules might
- * require us to fill additional fields.
- */
+ * require us to fill additional fields. */
 static struct net_device __fake_net_device = {
        .hard_header_len        = ETH_HLEN
 };
@@ -91,6 +96,36 @@ static struct rtable __fake_rtable = {
 
 
 /* PF_BRIDGE/PRE_ROUTING *********************************************/
+/* Undo the changes made for ip6tables PREROUTING and continue the
+ * bridge PRE_ROUTING hook. */
+static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
+{
+       struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+
+#ifdef CONFIG_NETFILTER_DEBUG
+       skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING);
+#endif
+
+       if (nf_bridge->mask & BRNF_PKT_TYPE) {
+               skb->pkt_type = PACKET_OTHERHOST;
+               nf_bridge->mask ^= BRNF_PKT_TYPE;
+       }
+       nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
+
+       skb->dst = (struct dst_entry *)&__fake_rtable;
+       dst_hold(skb->dst);
+
+       skb->dev = nf_bridge->physindev;
+       if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+               skb_push(skb, VLAN_HLEN);
+               skb->nh.raw -= VLAN_HLEN;
+       }
+       NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
+                      br_handle_frame_finish, 1);
+
+       return 0;
+}
+
 static void __br_dnat_complain(void)
 {
        static unsigned long last_complaint;
@@ -102,7 +137,6 @@ static void __br_dnat_complain(void)
        }
 }
 
-
 /* This requires some explaining. If DNAT has taken place,
  * we will need to fix up the destination Ethernet address,
  * and this is a tricky process.
@@ -145,9 +179,7 @@ static void __br_dnat_complain(void)
  *
  * --Lennert, 20020411
  * --Bart, 20020416 (updated)
- * --Bart, 20021007 (updated)
- */
-
+ * --Bart, 20021007 (updated) */
 static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
 {
 #ifdef CONFIG_NETFILTER_DEBUG
@@ -195,8 +227,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
 
                        if (!ip_route_output_key(&rt, &fl)) {
                                /* Bridged-and-DNAT'ed traffic doesn't
-                                * require ip_forwarding.
-                                */
+                                * require ip_forwarding. */
                                if (((struct dst_entry *)rt)->dev == dev) {
                                        skb->dst = (struct dst_entry *)rt;
                                        goto bridged_dnat;
@@ -210,8 +241,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
                        if (skb->dst->dev == dev) {
 bridged_dnat:
                                /* Tell br_nf_local_out this is a
-                                * bridged frame
-                                */
+                                * bridged frame */
                                nf_bridge->mask |= BRNF_BRIDGED_DNAT;
                                skb->dev = nf_bridge->physindev;
                                if (skb->protocol ==
@@ -225,7 +255,7 @@ bridged_dnat:
                                               1);
                                return 0;
                        }
-                       memcpy(skb->mac.ethernet->h_dest, dev->dev_addr,
+                       memcpy(eth_hdr(skb)->h_dest, dev->dev_addr,
                               ETH_ALEN);
                        skb->pkt_type = PACKET_HOST;
                }
@@ -245,12 +275,135 @@ bridged_dnat:
        return 0;
 }
 
-/* Replicate the checks that IPv4 does on packet reception.
+/* Some common code for IPv4/IPv6 */
+static void setup_pre_routing(struct sk_buff *skb)
+{
+       struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+
+       if (skb->pkt_type == PACKET_OTHERHOST) {
+               skb->pkt_type = PACKET_HOST;
+               nf_bridge->mask |= BRNF_PKT_TYPE;
+       }
+
+       nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
+       nf_bridge->physindev = skb->dev;
+       skb->dev = bridge_parent(skb->dev);
+}
+
+/* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */
+static int check_hbh_len(struct sk_buff *skb)
+{
+       unsigned char *raw = (u8*)(skb->nh.ipv6h+1);
+       u32 pkt_len;
+       int off = raw - skb->nh.raw;
+       int len = (raw[1]+1)<<3;
+
+       if ((raw + len) - skb->data > skb_headlen(skb))
+               goto bad;
+
+       off += 2;
+       len -= 2;
+
+       while (len > 0) {
+               int optlen = raw[off+1]+2;
+
+               switch (skb->nh.raw[off]) {
+               case IPV6_TLV_PAD0:
+                       optlen = 1;
+                       break;
+
+               case IPV6_TLV_PADN:
+                       break;
+
+               case IPV6_TLV_JUMBO:
+                       if (skb->nh.raw[off+1] != 4 || (off&3) != 2)
+                               goto bad;
+
+                       pkt_len = ntohl(*(u32*)(skb->nh.raw+off+2));
+
+                       if (pkt_len > skb->len - sizeof(struct ipv6hdr))
+                               goto bad;
+                       if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
+                               if (__pskb_trim(skb,
+                                   pkt_len + sizeof(struct ipv6hdr)))
+                                       goto bad;
+                               if (skb->ip_summed == CHECKSUM_HW)
+                                       skb->ip_summed = CHECKSUM_NONE;
+                       }
+                       break;
+               default:
+                       if (optlen > len)
+                               goto bad;
+                       break;
+               }
+               off += optlen;
+               len -= optlen;
+       }
+       if (len == 0)
+               return 0;
+bad:
+       return -1;
+
+}
+
+/* Replicate the checks that IPv6 does on packet reception and pass the packet
+ * to ip6tables, which doesn't support NAT, so things are fairly simple. */
+static unsigned int br_nf_pre_routing_ipv6(unsigned int hook,
+   struct sk_buff *skb, const struct net_device *in,
+   const struct net_device *out, int (*okfn)(struct sk_buff *))
+{
+       struct ipv6hdr *hdr;
+       u32 pkt_len;
+       struct nf_bridge_info *nf_bridge;
+
+       if (skb->len < sizeof(struct ipv6hdr))
+               goto inhdr_error;
+
+       if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+               goto inhdr_error;
+
+       hdr = skb->nh.ipv6h;
+
+       if (hdr->version != 6)
+               goto inhdr_error;
+
+       pkt_len = ntohs(hdr->payload_len);
+
+       if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
+               if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
+                       goto inhdr_error;
+               if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
+                       if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr)))
+                               goto inhdr_error;
+                       if (skb->ip_summed == CHECKSUM_HW)
+                               skb->ip_summed = CHECKSUM_NONE;
+               }
+       }
+       if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb))
+                       goto inhdr_error;
+
+#ifdef CONFIG_NETFILTER_DEBUG
+       skb->nf_debug ^= (1 << NF_IP6_PRE_ROUTING);
+#endif
+       if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
+               return NF_DROP;
+       setup_pre_routing(skb);
+
+       NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
+               br_nf_pre_routing_finish_ipv6);
+
+       return NF_STOLEN;
+
+inhdr_error:
+       return NF_DROP;
+}
+
+/* Direct IPv6 traffic to br_nf_pre_routing_ipv6.
+ * Replicate the checks that IPv4 does on packet reception.
  * Set skb->dev to the bridge device (i.e. parent of the
  * receiving device) to make netfilter happy, the REDIRECT
  * target in particular.  Save the original destination IP
- * address to be able to detect DNAT afterwards.
- */
+ * address to be able to detect DNAT afterwards. */
 static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
@@ -259,25 +412,38 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
        __u32 len;
        struct sk_buff *skb = *pskb;
        struct nf_bridge_info *nf_bridge;
+       struct vlan_ethhdr *hdr = vlan_eth_hdr(*pskb);
 
+       if (skb->protocol == __constant_htons(ETH_P_IPV6) || IS_VLAN_IPV6) {
+#ifdef CONFIG_SYSCTL
+               if (!brnf_call_ip6tables)
+                       return NF_ACCEPT;
+#endif
+               if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
+                       goto out;
+
+               if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+                       skb_pull(skb, VLAN_HLEN);
+                       (skb)->nh.raw += VLAN_HLEN;
+               }
+               return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
+       }
 #ifdef CONFIG_SYSCTL
        if (!brnf_call_iptables)
                return NF_ACCEPT;
 #endif
 
-       if (skb->protocol != __constant_htons(ETH_P_IP)) {
-               struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)
-                                         ((*pskb)->mac.ethernet);
+       if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
+               return NF_ACCEPT;
 
-               if (!IS_VLAN_IP)
-                       return NF_ACCEPT;
-               if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
-                       goto out;
-               skb_pull(*pskb, VLAN_HLEN);
-               (*pskb)->nh.raw += VLAN_HLEN;
-       } else if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
+       if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
                goto out;
 
+       if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+               skb_pull(skb, VLAN_HLEN);
+               (skb)->nh.raw += VLAN_HLEN;
+       }
+
        if (!pskb_may_pull(skb, sizeof(struct iphdr)))
                goto inhdr_error;
 
@@ -305,17 +471,9 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
 #ifdef CONFIG_NETFILTER_DEBUG
        skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING);
 #endif
-       if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
+       if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
                return NF_DROP;
-
-       if (skb->pkt_type == PACKET_OTHERHOST) {
-               skb->pkt_type = PACKET_HOST;
-               nf_bridge->mask |= BRNF_PKT_TYPE;
-       }
-
-       nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
-       nf_bridge->physindev = skb->dev;
-       skb->dev = bridge_parent(skb->dev);
+       setup_pre_routing(skb);
        store_orig_dstaddr(skb);
 
        NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
@@ -336,8 +494,7 @@ out:
  * packet would pass through PRE_ROUTING again (which already
  * took place when the packet entered the bridge), but we
  * register an IPv4 PRE_ROUTING 'sabotage' hook that will
- * prevent this from happening.
- */
+ * prevent this from happening. */
 static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
@@ -358,13 +515,13 @@ static int br_nf_forward_finish(struct sk_buff *skb)
 {
        struct nf_bridge_info *nf_bridge = skb->nf_bridge;
        struct net_device *in;
-       struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+       struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
 
 #ifdef CONFIG_NETFILTER_DEBUG
        skb->nf_debug ^= (1 << NF_BR_FORWARD);
 #endif
 
-       if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) {
+       if (skb->protocol != __constant_htons(ETH_P_ARP) && !IS_VLAN_ARP) {
                in = nf_bridge->physindev;
                if (nf_bridge->mask & BRNF_PKT_TYPE) {
                        skb->pkt_type = PACKET_OTHERHOST;
@@ -385,25 +542,26 @@ static int br_nf_forward_finish(struct sk_buff *skb)
 /* This is the 'purely bridged' case.  For IP, we pass the packet to
  * netfilter with indev and outdev set to the bridge device,
  * but we are still able to filter on the 'real' indev/outdev
- * because of the ipt_physdev.c module. For ARP, indev and outdev are the
- * bridge ports.
- */
+ * because of the physdev module. For ARP, indev and outdev are the
+ * bridge ports. */
 static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
 {
        struct sk_buff *skb = *pskb;
        struct nf_bridge_info *nf_bridge;
-       struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+       struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+       int pf;
 
-#ifdef CONFIG_SYSCTL
        if (!skb->nf_bridge)
                return NF_ACCEPT;
-#endif
 
-       if (skb->protocol != __constant_htons(ETH_P_IP)) {
-               if (!IS_VLAN_IP)
-                       return NF_ACCEPT;
+       if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
+               pf = PF_INET;
+       else
+               pf = PF_INET6;
+
+       if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
                skb_pull(*pskb, VLAN_HLEN);
                (*pskb)->nh.raw += VLAN_HLEN;
        }
@@ -421,7 +579,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
        nf_bridge->mask |= BRNF_BRIDGED;
        nf_bridge->physoutdev = skb->dev;
 
-       NF_HOOK(PF_INET, NF_IP_FORWARD, skb, bridge_parent(in),
+       NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in),
                bridge_parent(out), br_nf_forward_finish);
 
        return NF_STOLEN;
@@ -432,7 +590,7 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
    int (*okfn)(struct sk_buff *))
 {
        struct sk_buff *skb = *pskb;
-       struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+       struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
        struct net_device **d = (struct net_device **)(skb->cb);
 
 #ifdef CONFIG_SYSCTL
@@ -483,11 +641,10 @@ static int br_nf_local_out_finish(struct sk_buff *skb)
        return 0;
 }
 
-
 /* This function sees both locally originated IP packets and forwarded
  * IP packets (in both cases the destination device is a bridge
  * device). It also sees bridged-and-DNAT'ed packets.
- * To be able to filter on the physical bridge devices (with the ipt_physdev.c
+ * To be able to filter on the physical bridge devices (with the physdev
  * module), we steal packets destined to a bridge device away from the
  * PF_INET/FORWARD and PF_INET/OUTPUT hook functions, and give them back later,
  * when we have determined the real output device. This is done in here.
@@ -501,45 +658,44 @@ static int br_nf_local_out_finish(struct sk_buff *skb)
  * this packet before, and so the packet was locally originated. We fake
  * the PF_INET/LOCAL_OUT hook.
  * Finally, if nf_bridge->physindev isn't NULL, then the packet was IP routed,
- * so we fake the PF_INET/FORWARD hook. ipv4_sabotage_out() makes sure
+ * so we fake the PF_INET/FORWARD hook. ip_sabotage_out() makes sure
  * even routed packets that didn't arrive on a bridge interface have their
- * nf_bridge->physindev set.
- */
-
+ * nf_bridge->physindev set. */
 static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
-   int (*_okfn)(struct sk_buff *))
+   int (*okfn)(struct sk_buff *))
 {
-       int (*okfn)(struct sk_buff *skb);
-       struct net_device *realindev;
+       struct net_device *realindev, *realoutdev;
        struct sk_buff *skb = *pskb;
        struct nf_bridge_info *nf_bridge;
-       struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+       struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+       int pf;
 
-#ifdef CONFIG_SYSCTL
        if (!skb->nf_bridge)
                return NF_ACCEPT;
-#endif
 
-       if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
-               return NF_ACCEPT;
+       if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
+               pf = PF_INET;
+       else
+               pf = PF_INET6;
 
+#ifdef CONFIG_NETFILTER_DEBUG
        /* Sometimes we get packets with NULL ->dst here (for example,
-        * running a dhcp client daemon triggers this).
-        */
-       if (skb->dst == NULL)
+        * running a dhcp client daemon triggers this). This should now
+        * be fixed, but let's keep the check around. */
+       if (skb->dst == NULL) {
+               printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
                return NF_ACCEPT;
+       }
+#endif
 
        nf_bridge = skb->nf_bridge;
        nf_bridge->physoutdev = skb->dev;
        realindev = nf_bridge->physindev;
 
        /* Bridged, take PF_BRIDGE/FORWARD.
-        * (see big note in front of br_nf_pre_routing_finish)
-        */
+        * (see big note in front of br_nf_pre_routing_finish) */
        if (nf_bridge->mask & BRNF_BRIDGED_DNAT) {
-               okfn = br_forward_finish;
-
                if (nf_bridge->mask & BRNF_PKT_TYPE) {
                        skb->pkt_type = PACKET_OTHERHOST;
                        nf_bridge->mask ^= BRNF_PKT_TYPE;
@@ -550,41 +706,41 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
                }
 
                NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev,
-                       skb->dev, okfn);
-       } else {
-               struct net_device *realoutdev = bridge_parent(skb->dev);
+                       skb->dev, br_forward_finish);
+               goto out;
+       }
+       realoutdev = bridge_parent(skb->dev);
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-               /* iptables should match -o br0.x */
-               if (nf_bridge->netoutdev)
-                       realoutdev = nf_bridge->netoutdev;
+       /* iptables should match -o br0.x */
+       if (nf_bridge->netoutdev)
+               realoutdev = nf_bridge->netoutdev;
 #endif
-               okfn = br_nf_local_out_finish;
-               if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
-                       skb_pull(skb, VLAN_HLEN);
-                       (*pskb)->nh.raw += VLAN_HLEN;
-               }
-               /* IP forwarded traffic has a physindev, locally
-                * generated traffic hasn't.
-                */
-               if (realindev != NULL) {
-                       if (((nf_bridge->mask & BRNF_DONT_TAKE_PARENT) == 0) &&
-                           has_bridge_parent(realindev))
-                               realindev = bridge_parent(realindev);
-                       NF_HOOK_THRESH(PF_INET, NF_IP_FORWARD, skb, realindev,
-                                      realoutdev, okfn,
-                                      NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
-               } else {
+       if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+               skb_pull(skb, VLAN_HLEN);
+               (*pskb)->nh.raw += VLAN_HLEN;
+       }
+       /* IP forwarded traffic has a physindev, locally
+        * generated traffic hasn't. */
+       if (realindev != NULL) {
+               if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) &&
+                   has_bridge_parent(realindev))
+                       realindev = bridge_parent(realindev);
+
+               NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev,
+                              realoutdev, br_nf_local_out_finish,
+                              NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
+       } else {
 #ifdef CONFIG_NETFILTER_DEBUG
-                       skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT);
+               skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT);
 #endif
 
-                       NF_HOOK_THRESH(PF_INET, NF_IP_LOCAL_OUT, skb, realindev,
-                                      realoutdev, okfn,
-                                      NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
-               }
+               NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev,
+                              realoutdev, br_nf_local_out_finish,
+                              NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
        }
 
+out:
        return NF_STOLEN;
 }
 
@@ -596,8 +752,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
 {
        struct sk_buff *skb = *pskb;
        struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge;
-       struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+       struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
        struct net_device *realoutdev = bridge_parent(skb->dev);
+       int pf;
 
 #ifdef CONFIG_NETFILTER_DEBUG
        /* Be very paranoid. This probably won't happen anymore, but let's
@@ -609,19 +766,15 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
        }
 #endif
 
-#ifdef CONFIG_SYSCTL
        if (!nf_bridge)
                return NF_ACCEPT;
-#endif
 
-       if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
-               return NF_ACCEPT;
+       if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
+               pf = PF_INET;
+       else
+               pf = PF_INET6;
 
 #ifdef CONFIG_NETFILTER_DEBUG
-       /* Sometimes we get packets with NULL ->dst here (for example,
-        * running a dhcp client daemon triggers this). This should now
-        * be fixed, but let's keep the check around.
-        */
        if (skb->dst == NULL) {
                printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
                goto print_error;
@@ -631,8 +784,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
 #endif
 
        /* We assume any code from br_dev_queue_push_xmit onwards doesn't care
-        * about the value of skb->pkt_type.
-        */
+        * about the value of skb->pkt_type. */
        if (skb->pkt_type == PACKET_OTHERHOST) {
                skb->pkt_type = PACKET_HOST;
                nf_bridge->mask |= BRNF_PKT_TYPE;
@@ -649,8 +801,8 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
        if (nf_bridge->netoutdev)
                realoutdev = nf_bridge->netoutdev;
 #endif
-       NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
-               realoutdev, br_dev_queue_push_xmit);
+       NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
+               br_dev_queue_push_xmit);
 
        return NF_STOLEN;
 
@@ -668,12 +820,10 @@ print_error:
 }
 
 
-/* IPv4/SABOTAGE *****************************************************/
-
-/* Don't hand locally destined packets to PF_INET/PRE_ROUTING
- * for the second time.
- */
-static unsigned int ipv4_sabotage_in(unsigned int hook, struct sk_buff **pskb,
+/* IP/SABOTAGE *****************************************************/
+/* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING
+ * for the second time. */
+static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
 {
@@ -686,19 +836,26 @@ static unsigned int ipv4_sabotage_in(unsigned int hook, struct sk_buff **pskb,
        return NF_ACCEPT;
 }
 
-/* Postpone execution of PF_INET/FORWARD, PF_INET/LOCAL_OUT
- * and PF_INET/POST_ROUTING until we have done the forwarding
- * decision in the bridge code and have determined skb->physoutdev.
- */
-static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
+/* Postpone execution of PF_INET(6)/FORWARD, PF_INET(6)/LOCAL_OUT
+ * and PF_INET(6)/POST_ROUTING until we have done the forwarding
+ * decision in the bridge code and have determined nf_bridge->physoutdev. */
+static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
 {
        struct sk_buff *skb = *pskb;
 
 #ifdef CONFIG_SYSCTL
-       if (!brnf_call_iptables && !skb->nf_bridge)
-               return NF_ACCEPT;
+       if (!skb->nf_bridge) {
+               struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+
+               if (skb->protocol == __constant_htons(ETH_P_IP) ||
+                   IS_VLAN_IP) {
+                       if (!brnf_call_iptables)
+                               return NF_ACCEPT;
+               } else if (!brnf_call_ip6tables)
+                       return NF_ACCEPT;
+       }
 #endif
 
        if ((out->hard_start_xmit == br_dev_xmit &&
@@ -721,8 +878,7 @@ static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
                 * will need the indev then. For a brouter, the real indev
                 * can be a bridge port, so we make sure br_nf_local_out()
                 * doesn't use the bridge parent of the indev by using
-                * the BRNF_DONT_TAKE_PARENT mask.
-                */
+                * the BRNF_DONT_TAKE_PARENT mask. */
                if (hook == NF_IP_FORWARD && nf_bridge->physindev == NULL) {
                        nf_bridge->mask &= BRNF_DONT_TAKE_PARENT;
                        nf_bridge->physindev = (struct net_device *)in;
@@ -742,8 +898,7 @@ static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
 /* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent
  * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input.
  * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
- * ip_refrag() can return NF_STOLEN.
- */
+ * ip_refrag() can return NF_STOLEN. */
 static struct nf_hook_ops br_nf_ops[] = {
        { .hook = br_nf_pre_routing, 
          .owner = THIS_MODULE, 
@@ -775,26 +930,46 @@ static struct nf_hook_ops br_nf_ops[] = {
          .pf = PF_BRIDGE,
          .hooknum = NF_BR_POST_ROUTING,
          .priority = NF_BR_PRI_LAST, },
-       { .hook = ipv4_sabotage_in,
+       { .hook = ip_sabotage_in,
          .owner = THIS_MODULE,
          .pf = PF_INET,
          .hooknum = NF_IP_PRE_ROUTING,
          .priority = NF_IP_PRI_FIRST, },
-       { .hook = ipv4_sabotage_out,
+       { .hook = ip_sabotage_in,
+         .owner = THIS_MODULE,
+         .pf = PF_INET6,
+         .hooknum = NF_IP6_PRE_ROUTING,
+         .priority = NF_IP6_PRI_FIRST, },
+       { .hook = ip_sabotage_out,
          .owner = THIS_MODULE,
          .pf = PF_INET,
          .hooknum = NF_IP_FORWARD,
          .priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD, },
-       { .hook = ipv4_sabotage_out,
+       { .hook = ip_sabotage_out,
+         .owner = THIS_MODULE,
+         .pf = PF_INET6,
+         .hooknum = NF_IP6_FORWARD,
+         .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD, },
+       { .hook = ip_sabotage_out,
          .owner = THIS_MODULE,
          .pf = PF_INET,
          .hooknum = NF_IP_LOCAL_OUT,
          .priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
-       { .hook = ipv4_sabotage_out,
+       { .hook = ip_sabotage_out,
+         .owner = THIS_MODULE,
+         .pf = PF_INET6,
+         .hooknum = NF_IP6_LOCAL_OUT,
+         .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
+       { .hook = ip_sabotage_out,
          .owner = THIS_MODULE,
          .pf = PF_INET,
          .hooknum = NF_IP_POST_ROUTING,
          .priority = NF_IP_PRI_FIRST, },
+       { .hook = ip_sabotage_out,
+         .owner = THIS_MODULE,
+         .pf = PF_INET6,
+         .hooknum = NF_IP6_POST_ROUTING,
+         .priority = NF_IP6_PRI_FIRST, },
 };
 
 #ifdef CONFIG_SYSCTL
@@ -828,6 +1003,14 @@ static ctl_table brnf_table[] = {
                .mode           = 0644,
                .proc_handler   = &brnf_sysctl_call_tables,
        },
+       {
+               .ctl_name       = NET_BRIDGE_NF_CALL_IP6TABLES,
+               .procname       = "bridge-nf-call-ip6tables",
+               .data           = &brnf_call_ip6tables,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &brnf_sysctl_call_tables,
+       },
        {
                .ctl_name       = NET_BRIDGE_NF_FILTER_VLAN_TAGGED,
                .procname       = "bridge-nf-filter-vlan-tagged",
index 1db4434..468ebdf 100644 (file)
@@ -16,7 +16,7 @@ static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *
    const struct net_device *out, const void *data, unsigned int datalen)
 {
        struct ebt_802_3_info *info = (struct ebt_802_3_info *)data;
-       struct ebt_802_3_hdr *hdr = (struct ebt_802_3_hdr *)skb->mac.ethernet;
+       struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb);
        uint16_t type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
 
        if (info->bitmask & EBT_802_3_SAP) {
index 727311d..5a1f5e3 100644 (file)
@@ -72,42 +72,55 @@ static int ebt_mac_wormhash_check_integrity(const struct ebt_mac_wormhash
 
 static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
 {
-       if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_IP)) {
-               struct iphdr iph;
+       if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
+               struct iphdr _iph, *ih;
 
-               if (skb_copy_bits(skb, 0, &iph, sizeof(iph)))
+               ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+               if (ih == NULL)
                        return -1;
-               *addr = iph.daddr;
-       } else if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) {
-               struct arphdr arph;
-
-               if (skb_copy_bits(skb, 0, &arph, sizeof(arph)) ||
-                   arph.ar_pln != sizeof(uint32_t) || arph.ar_hln != ETH_ALEN)
+               *addr = ih->daddr;
+       } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
+               struct arphdr _arph, *ah;
+               uint32_t buf, *bp;
+
+               ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+               if (ah == NULL ||
+                   ah->ar_pln != sizeof(uint32_t) ||
+                   ah->ar_hln != ETH_ALEN)
                        return -1;
-               if (skb_copy_bits(skb, sizeof(struct arphdr) +
-                   2 * ETH_ALEN + sizeof(uint32_t), addr, sizeof(uint32_t)))
+               bp = skb_header_pointer(skb, sizeof(struct arphdr) +
+                                       2 * ETH_ALEN + sizeof(uint32_t),
+                                       sizeof(uint32_t), &buf);
+               if (bp == NULL)
                        return -1;
+               *addr = *bp;
        }
        return 0;
 }
 
 static int get_ip_src(const struct sk_buff *skb, uint32_t *addr)
 {
-       if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_IP)) {
-               struct iphdr iph;
+       if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
+               struct iphdr _iph, *ih;
 
-               if (skb_copy_bits(skb, 0, &iph, sizeof(iph)))
+               ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+               if (ih == NULL)
                        return -1;
-               *addr = iph.saddr;
-       } else if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) {
-               struct arphdr arph;
-
-               if (skb_copy_bits(skb, 0, &arph, sizeof(arph)) ||
-                   arph.ar_pln != sizeof(uint32_t) || arph.ar_hln != ETH_ALEN)
+               *addr = ih->saddr;
+       } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
+               struct arphdr _arph, *ah;
+               uint32_t buf, *bp;
+
+               ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+               if (ah == NULL ||
+                   ah->ar_pln != sizeof(uint32_t) ||
+                   ah->ar_hln != ETH_ALEN)
                        return -1;
-               if (skb_copy_bits(skb, sizeof(struct arphdr) +
-                   ETH_ALEN, addr, sizeof(uint32_t)))
+               bp = skb_header_pointer(skb, sizeof(struct arphdr) +
+                                       ETH_ALEN, sizeof(uint32_t), &buf);
+               if (bp == NULL)
                        return -1;
+               *addr = *bp;
        }
        return 0;
 }
@@ -126,7 +139,7 @@ static int ebt_filter_among(const struct sk_buff *skb,
        wh_src = ebt_among_wh_src(info);
 
        if (wh_src) {
-               smac = skb->mac.ethernet->h_source;
+               smac = eth_hdr(skb)->h_source;
                if (get_ip_src(skb, &sip))
                        return EBT_NOMATCH;
                if (!(info->bitmask & EBT_AMONG_SRC_NEG)) {
@@ -141,7 +154,7 @@ static int ebt_filter_among(const struct sk_buff *skb,
        }
 
        if (wh_dst) {
-               dmac = skb->mac.ethernet->h_dest;
+               dmac = eth_hdr(skb)->h_dest;
                if (get_ip_dst(skb, &dip))
                        return EBT_NOMATCH;
                if (!(info->bitmask & EBT_AMONG_DST_NEG)) {
index eb67584..b94c48c 100644 (file)
@@ -19,72 +19,79 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
    const struct net_device *out, const void *data, unsigned int datalen)
 {
        struct ebt_arp_info *info = (struct ebt_arp_info *)data;
-       struct arphdr arph;
+       struct arphdr _arph, *ah;
 
-       if (skb_copy_bits(skb, 0, &arph, sizeof(arph)))
+       ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+       if (ah == NULL)
                return EBT_NOMATCH;
        if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode !=
-          arph.ar_op, EBT_ARP_OPCODE))
+          ah->ar_op, EBT_ARP_OPCODE))
                return EBT_NOMATCH;
        if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype !=
-          arph.ar_hrd, EBT_ARP_HTYPE))
+          ah->ar_hrd, EBT_ARP_HTYPE))
                return EBT_NOMATCH;
        if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype !=
-          arph.ar_pro, EBT_ARP_PTYPE))
+          ah->ar_pro, EBT_ARP_PTYPE))
                return EBT_NOMATCH;
 
        if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) {
-               uint32_t addr;
+               uint32_t _addr, *ap;
 
                /* IPv4 addresses are always 4 bytes */
-               if (arph.ar_pln != sizeof(uint32_t))
+               if (ah->ar_pln != sizeof(uint32_t))
                        return EBT_NOMATCH;
                if (info->bitmask & EBT_ARP_SRC_IP) {
-                       if (skb_copy_bits(skb, sizeof(struct arphdr) +
-                           arph.ar_hln, &addr, sizeof(addr)))
+                       ap = skb_header_pointer(skb, sizeof(struct arphdr) +
+                                               ah->ar_hln, sizeof(_addr),
+                                               &_addr);
+                       if (ap == NULL)
                                return EBT_NOMATCH;
-                       if (FWINV(info->saddr != (addr & info->smsk),
+                       if (FWINV(info->saddr != (*ap & info->smsk),
                           EBT_ARP_SRC_IP))
                                return EBT_NOMATCH;
                }
 
                if (info->bitmask & EBT_ARP_DST_IP) {
-                       if (skb_copy_bits(skb, sizeof(struct arphdr) +
-                           2*arph.ar_hln + sizeof(uint32_t), &addr,
-                           sizeof(addr)))
+                       ap = skb_header_pointer(skb, sizeof(struct arphdr) +
+                                               2*ah->ar_hln+sizeof(uint32_t),
+                                               sizeof(_addr), &_addr);
+                       if (ap == NULL)
                                return EBT_NOMATCH;
-                       if (FWINV(info->daddr != (addr & info->dmsk),
+                       if (FWINV(info->daddr != (*ap & info->dmsk),
                           EBT_ARP_DST_IP))
                                return EBT_NOMATCH;
                }
        }
 
        if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
-               unsigned char mac[ETH_ALEN];
+               unsigned char _mac[ETH_ALEN], *mp;
                uint8_t verdict, i;
 
                /* MAC addresses are 6 bytes */
-               if (arph.ar_hln != ETH_ALEN)
+               if (ah->ar_hln != ETH_ALEN)
                        return EBT_NOMATCH;
                if (info->bitmask & EBT_ARP_SRC_MAC) {
-                       if (skb_copy_bits(skb, sizeof(struct arphdr), &mac,
-                           ETH_ALEN))
+                       mp = skb_header_pointer(skb, sizeof(struct arphdr),
+                                               sizeof(_mac), &_mac);
+                       if (mp == NULL)
                                return EBT_NOMATCH;
                        verdict = 0;
                        for (i = 0; i < 6; i++)
-                               verdict |= (mac[i] ^ info->smaddr[i]) &
+                               verdict |= (mp[i] ^ info->smaddr[i]) &
                                       info->smmsk[i];
                        if (FWINV(verdict != 0, EBT_ARP_SRC_MAC))
                                return EBT_NOMATCH;
                }
 
                if (info->bitmask & EBT_ARP_DST_MAC) {
-                       if (skb_copy_bits(skb, sizeof(struct arphdr) +
-                           arph.ar_hln + arph.ar_pln, &mac, ETH_ALEN))
+                       mp = skb_header_pointer(skb, sizeof(struct arphdr) +
+                                               ah->ar_hln + ah->ar_pln,
+                                               sizeof(_mac), &_mac);
+                       if (mp == NULL)
                                return EBT_NOMATCH;
                        verdict = 0;
                        for (i = 0; i < 6; i++)
-                               verdict |= (mac[i] ^ info->dmaddr[i]) &
+                               verdict |= (mp[i] ^ info->dmaddr[i]) &
                                        info->dmmsk[i];
                        if (FWINV(verdict != 0, EBT_ARP_DST_MAC))
                                return EBT_NOMATCH;
@@ -101,8 +108,8 @@ static int ebt_arp_check(const char *tablename, unsigned int hookmask,
 
        if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info)))
                return -EINVAL;
-       if ((e->ethproto != __constant_htons(ETH_P_ARP) &&
-          e->ethproto != __constant_htons(ETH_P_RARP)) ||
+       if ((e->ethproto != htons(ETH_P_ARP) &&
+          e->ethproto != htons(ETH_P_RARP)) ||
           e->invflags & EBT_IPROTO)
                return -EINVAL;
        if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK)
index 87ba30d..b934de9 100644 (file)
@@ -20,30 +20,38 @@ static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr,
    const void *data, unsigned int datalen)
 {
        struct ebt_arpreply_info *info = (struct ebt_arpreply_info *)data;
-       u32 sip, dip;
-       struct arphdr ah;
-       unsigned char sha[ETH_ALEN];
+       u32 _sip, *siptr, _dip, *diptr;
+       struct arphdr _ah, *ap;
+       unsigned char _sha[ETH_ALEN], *shp;
        struct sk_buff *skb = *pskb;
 
-       if (skb_copy_bits(skb, 0, &ah, sizeof(ah)))
+       ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
+       if (ap == NULL)
                return EBT_DROP;
 
-       if (ah.ar_op != __constant_htons(ARPOP_REQUEST) || ah.ar_hln != ETH_ALEN
-           || ah.ar_pro != __constant_htons(ETH_P_IP) || ah.ar_pln != 4)
+       if (ap->ar_op != htons(ARPOP_REQUEST) ||
+           ap->ar_hln != ETH_ALEN ||
+           ap->ar_pro != htons(ETH_P_IP) ||
+           ap->ar_pln != 4)
                return EBT_CONTINUE;
 
-       if (skb_copy_bits(skb, sizeof(ah), &sha, ETH_ALEN))
+       shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha);
+       if (shp == NULL)
                return EBT_DROP;
 
-       if (skb_copy_bits(skb, sizeof(ah) + ETH_ALEN, &sip, sizeof(sip)))
+       siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN,
+                                  sizeof(_sip), &_sip);
+       if (siptr == NULL)
                return EBT_DROP;
 
-       if (skb_copy_bits(skb, sizeof(ah) + 2 * ETH_ALEN + sizeof(sip),
-           &dip, sizeof(dip)))
+       diptr = skb_header_pointer(skb,
+                                  sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip),
+                                  sizeof(_dip), &_dip);
+       if (diptr == NULL)
                return EBT_DROP;
 
-       arp_send(ARPOP_REPLY, ETH_P_ARP, sip, (struct net_device *)in,
-                dip, sha, info->mac, sha);
+       arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)in,
+                *diptr, shp, info->mac, shp);
 
        return info->target;
 }
@@ -57,7 +65,7 @@ static int ebt_target_reply_check(const char *tablename, unsigned int hookmask,
                return -EINVAL;
        if (BASE_CHAIN && info->target == EBT_RETURN)
                return -EINVAL;
-       if (e->ethproto != __constant_htons(ETH_P_ARP) ||
+       if (e->ethproto != htons(ETH_P_ARP) ||
            e->invflags & EBT_IPROTO)
                return -EINVAL;
        CLEAR_BASE_CHAIN_BIT;
index f9552df..f546308 100644 (file)
@@ -30,8 +30,7 @@ static int ebt_target_dnat(struct sk_buff **pskb, unsigned int hooknr,
                kfree_skb(*pskb);
                *pskb = nskb;
        }
-       memcpy(((**pskb).mac.ethernet)->h_dest, info->mac,
-          ETH_ALEN * sizeof(unsigned char));
+       memcpy(eth_hdr(*pskb)->h_dest, info->mac, ETH_ALEN);
        return info->target;
 }
 
index 7bab7d0..7323805 100644 (file)
@@ -28,41 +28,44 @@ static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
    unsigned int datalen)
 {
        struct ebt_ip_info *info = (struct ebt_ip_info *)data;
-       union {struct iphdr iph; struct tcpudphdr ports;} u;
+       struct iphdr _iph, *ih;
+       struct tcpudphdr _ports, *pptr;
 
-       if (skb_copy_bits(skb, 0, &u.iph, sizeof(u.iph)))
+       ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+       if (ih == NULL)
                return EBT_NOMATCH;
        if (info->bitmask & EBT_IP_TOS &&
-          FWINV(info->tos != u.iph.tos, EBT_IP_TOS))
+          FWINV(info->tos != ih->tos, EBT_IP_TOS))
                return EBT_NOMATCH;
        if (info->bitmask & EBT_IP_SOURCE &&
-          FWINV((u.iph.saddr & info->smsk) !=
+          FWINV((ih->saddr & info->smsk) !=
           info->saddr, EBT_IP_SOURCE))
                return EBT_NOMATCH;
        if ((info->bitmask & EBT_IP_DEST) &&
-          FWINV((u.iph.daddr & info->dmsk) !=
+          FWINV((ih->daddr & info->dmsk) !=
           info->daddr, EBT_IP_DEST))
                return EBT_NOMATCH;
        if (info->bitmask & EBT_IP_PROTO) {
-               if (FWINV(info->protocol != u.iph.protocol, EBT_IP_PROTO))
+               if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO))
                        return EBT_NOMATCH;
                if (!(info->bitmask & EBT_IP_DPORT) &&
                    !(info->bitmask & EBT_IP_SPORT))
                        return EBT_MATCH;
-               if (skb_copy_bits(skb, u.iph.ihl*4, &u.ports,
-                   sizeof(u.ports)))
+               pptr = skb_header_pointer(skb, ih->ihl*4,
+                                         sizeof(_ports), &_ports);
+               if (pptr == NULL)
                        return EBT_NOMATCH;
                if (info->bitmask & EBT_IP_DPORT) {
-                       u.ports.dst = ntohs(u.ports.dst);
-                       if (FWINV(u.ports.dst < info->dport[0] ||
-                                 u.ports.dst > info->dport[1],
+                       u32 dst = ntohs(pptr->dst);
+                       if (FWINV(dst < info->dport[0] ||
+                                 dst > info->dport[1],
                                  EBT_IP_DPORT))
                        return EBT_NOMATCH;
                }
                if (info->bitmask & EBT_IP_SPORT) {
-                       u.ports.src = ntohs(u.ports.src);
-                       if (FWINV(u.ports.src < info->sport[0] ||
-                                 u.ports.src > info->sport[1],
+                       u32 src = ntohs(pptr->src);
+                       if (FWINV(src < info->sport[0] ||
+                                 src > info->sport[1],
                                  EBT_IP_SPORT))
                        return EBT_NOMATCH;
                }
@@ -77,7 +80,7 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask,
 
        if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info)))
                return -EINVAL;
-       if (e->ethproto != __constant_htons(ETH_P_IP) ||
+       if (e->ethproto != htons(ETH_P_IP) ||
           e->invflags & EBT_IPROTO)
                return -EINVAL;
        if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
index 2da7c68..6c022ef 100644 (file)
@@ -70,64 +70,76 @@ static void ebt_log(const struct sk_buff *skb, const struct net_device *in,
           out ? out->name : "");
 
        printk("MAC source = ");
-       print_MAC((skb->mac.ethernet)->h_source);
+       print_MAC(eth_hdr(skb)->h_source);
        printk("MAC dest = ");
-       print_MAC((skb->mac.ethernet)->h_dest);
+       print_MAC(eth_hdr(skb)->h_dest);
 
-       printk("proto = 0x%04x", ntohs(((*skb).mac.ethernet)->h_proto));
+       printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto));
 
-       if ((info->bitmask & EBT_LOG_IP) && skb->mac.ethernet->h_proto ==
+       if ((info->bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto ==
           htons(ETH_P_IP)){
-               if (skb_copy_bits(skb, 0, &u.iph, sizeof(u.iph))) {
+               struct iphdr _iph, *ih;
+
+               ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+               if (ih == NULL) {
                        printk(" INCOMPLETE IP header");
                        goto out;
                }
                printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u,",
-                  NIPQUAD(u.iph.saddr), NIPQUAD(u.iph.daddr));
+                  NIPQUAD(ih->saddr), NIPQUAD(ih->daddr));
                printk(" IP tos=0x%02X, IP proto=%d", u.iph.tos,
-                      u.iph.protocol);
-               if (u.iph.protocol == IPPROTO_TCP ||
-                   u.iph.protocol == IPPROTO_UDP) {
-                       if (skb_copy_bits(skb, u.iph.ihl*4, &u.ports,
-                           sizeof(u.ports))) {
+                      ih->protocol);
+               if (ih->protocol == IPPROTO_TCP ||
+                   ih->protocol == IPPROTO_UDP) {
+                       struct tcpudphdr _ports, *pptr;
+
+                       pptr = skb_header_pointer(skb, ih->ihl*4,
+                                                 sizeof(_ports), &_ports);
+                       if (pptr == NULL) {
                                printk(" INCOMPLETE TCP/UDP header");
                                goto out;
                        }
-                       printk(" SPT=%u DPT=%u", ntohs(u.ports.src),
-                          ntohs(u.ports.dst));
+                       printk(" SPT=%u DPT=%u", ntohs(pptr->src),
+                          ntohs(pptr->dst));
                }
                goto out;
        }
 
        if ((info->bitmask & EBT_LOG_ARP) &&
-           ((skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) ||
-           (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_RARP)))) {
-               if (skb_copy_bits(skb, 0, &u.arph, sizeof(u.arph))) {
+           ((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) ||
+            (eth_hdr(skb)->h_proto == htons(ETH_P_RARP)))) {
+               struct arphdr _arph, *ah;
+
+               ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+               if (ah == NULL) {
                        printk(" INCOMPLETE ARP header");
                        goto out;
                }
                printk(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d",
-                      ntohs(u.arph.ar_hrd), ntohs(u.arph.ar_pro),
-                      ntohs(u.arph.ar_op));
+                      ntohs(ah->ar_hrd), ntohs(ah->ar_pro),
+                      ntohs(ah->ar_op));
 
                /* If it's for Ethernet and the lengths are OK,
                 * then log the ARP payload */
-               if (u.arph.ar_hrd == __constant_htons(1) &&
-                   u.arph.ar_hln == ETH_ALEN &&
-                   u.arph.ar_pln == sizeof(uint32_t)) {
-                       if (skb_copy_bits(skb, sizeof(u.arph), &u.arpp,
-                           sizeof(u.arpp))) {
+               if (ah->ar_hrd == htons(1) &&
+                   ah->ar_hln == ETH_ALEN &&
+                   ah->ar_pln == sizeof(uint32_t)) {
+                       struct arppayload _arpp, *ap;
+
+                       ap = skb_header_pointer(skb, sizeof(u.arph),
+                                               sizeof(_arpp), &_arpp);
+                       if (ap == NULL) {
                                printk(" INCOMPLETE ARP payload");
                                goto out;
                        }
                        printk(" ARP MAC SRC=");
-                       print_MAC(u.arpp.mac_src);
+                       print_MAC(ap->mac_src);
                        printk(" ARP IP SRC=%u.%u.%u.%u",
-                              myNIPQUAD(u.arpp.ip_src));
+                              myNIPQUAD(ap->ip_src));
                        printk(" ARP MAC DST=");
-                       print_MAC(u.arpp.mac_dst);
+                       print_MAC(ap->mac_dst);
                        printk(" ARP IP DST=%u.%u.%u.%u",
-                              myNIPQUAD(u.arpp.ip_dst));
+                              myNIPQUAD(ap->ip_dst));
                }
        }
 out:
index befbfa1..1538b43 100644 (file)
@@ -32,11 +32,10 @@ static int ebt_target_redirect(struct sk_buff **pskb, unsigned int hooknr,
                *pskb = nskb;
        }
        if (hooknr != NF_BR_BROUTING)
-               memcpy((**pskb).mac.ethernet->h_dest,
-                  in->br_port->br->dev->dev_addr, ETH_ALEN);
+               memcpy(eth_hdr(*pskb)->h_dest,
+                      in->br_port->br->dev->dev_addr, ETH_ALEN);
        else
-               memcpy((**pskb).mac.ethernet->h_dest,
-                  in->dev_addr, ETH_ALEN);
+               memcpy(eth_hdr(*pskb)->h_dest, in->dev_addr, ETH_ALEN);
        (*pskb)->pkt_type = PACKET_HOST;
        return info->target;
 }
index ae0f053..1529bdc 100644 (file)
@@ -30,8 +30,7 @@ static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
                kfree_skb(*pskb);
                *pskb = nskb;
        }
-       memcpy(((**pskb).mac.ethernet)->h_source, info->mac,
-          ETH_ALEN * sizeof(unsigned char));
+       memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
        return info->target;
 }
 
index d0299ef..f8a8cde 100644 (file)
@@ -122,26 +122,30 @@ static int ebt_filter_stp(const struct sk_buff *skb, const struct net_device *in
    const struct net_device *out, const void *data, unsigned int datalen)
 {
        struct ebt_stp_info *info = (struct ebt_stp_info *)data;
-       struct stp_header stph;
+       struct stp_header _stph, *sp;
        uint8_t header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
-       if (skb_copy_bits(skb, 0, &stph, sizeof(stph)))
+
+       sp = skb_header_pointer(skb, 0, sizeof(_stph), &_stph);
+       if (sp == NULL)
                return EBT_NOMATCH;
 
        /* The stp code only considers these */
-       if (memcmp(&stph, header, sizeof(header)))
+       if (memcmp(sp, header, sizeof(header)))
                return EBT_NOMATCH;
 
        if (info->bitmask & EBT_STP_TYPE
-           && FWINV(info->type != stph.type, EBT_STP_TYPE))
+           && FWINV(info->type != sp->type, EBT_STP_TYPE))
                return EBT_NOMATCH;
 
-       if (stph.type == BPDU_TYPE_CONFIG &&
+       if (sp->type == BPDU_TYPE_CONFIG &&
            info->bitmask & EBT_STP_CONFIG_MASK) {
-               struct stp_config_pdu stpc;
+               struct stp_config_pdu _stpc, *st;
 
-               if (skb_copy_bits(skb, sizeof(stph), &stpc, sizeof(stpc)))
-                   return EBT_NOMATCH;
-               return ebt_filter_config(info, &stpc);
+               st = skb_header_pointer(skb, sizeof(_stph),
+                                       sizeof(_stpc), &_stpc);
+               if (st == NULL)
+                       return EBT_NOMATCH;
+               return ebt_filter_config(info, st);
        }
        return EBT_MATCH;
 }
index ec11177..db60d73 100644 (file)
 #include <linux/if_ether.h>
 #include <linux/if_vlan.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_bridge/ebt_vlan.h>
 
-static unsigned char debug;
+static int debug;
 #define MODULE_VERS "0.6"
 
-MODULE_PARM(debug, "0-1b");
+module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "debug=1 is turn on debug messages");
 MODULE_AUTHOR("Nick Fedchik <nick@fedchik.org.ua>");
 MODULE_DESCRIPTION("802.1Q match module (ebtables extension), v"
@@ -48,7 +49,7 @@ ebt_filter_vlan(const struct sk_buff *skb,
                const void *data, unsigned int datalen)
 {
        struct ebt_vlan_info *info = (struct ebt_vlan_info *) data;
-       struct vlan_hdr frame;
+       struct vlan_hdr _frame, *fp;
 
        unsigned short TCI;     /* Whole TCI, given from parsed frame */
        unsigned short id;      /* VLAN ID, given from frame TCI */
@@ -56,7 +57,8 @@ ebt_filter_vlan(const struct sk_buff *skb,
        /* VLAN encapsulated Type/Length field, given from orig frame */
        unsigned short encap;
 
-       if (skb_copy_bits(skb, 0, &frame, sizeof(frame)))
+       fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
+       if (fp == NULL)
                return EBT_NOMATCH;
 
        /* Tag Control Information (TCI) consists of the following elements:
@@ -66,10 +68,10 @@ ebt_filter_vlan(const struct sk_buff *skb,
         * (CFI) is a single bit flag value. Currently ignored.
         * - VLAN Identifier (VID). The VID is encoded as
         * an unsigned binary number. */
-       TCI = ntohs(frame.h_vlan_TCI);
+       TCI = ntohs(fp->h_vlan_TCI);
        id = TCI & VLAN_VID_MASK;
        prio = (TCI >> 13) & 0x7;
-       encap = frame.h_vlan_encapsulated_proto;
+       encap = fp->h_vlan_encapsulated_proto;
 
        /* Checking VLAN Identifier (VID) */
        if (GET_BITMASK(EBT_VLAN_ID))
@@ -102,7 +104,7 @@ ebt_check_vlan(const char *tablename,
        }
 
        /* Is it 802.1Q frame checked? */
-       if (e->ethproto != __constant_htons(ETH_P_8021Q)) {
+       if (e->ethproto != htons(ETH_P_8021Q)) {
                DEBUG_MSG
                    ("passed entry proto %2.4X is not 802.1Q (8100)\n",
                     (unsigned short) ntohs(e->ethproto));
index c1340cc..05c76cb 100644 (file)
@@ -450,12 +450,12 @@ int divert_ioctl(unsigned int cmd, struct divert_cf __user *arg)
  */
 
 #define        ETH_DIVERT_FRAME(skb) \
-       memcpy(skb->mac.ethernet, skb->dev->dev_addr, ETH_ALEN); \
+       memcpy(eth_hdr(skb), skb->dev->dev_addr, ETH_ALEN); \
        skb->pkt_type=PACKET_HOST
                
 void divert_frame(struct sk_buff *skb)
 {
-       struct ethhdr                   *eth = skb->mac.ethernet;
+       struct ethhdr                   *eth = eth_hdr(skb);
        struct iphdr                    *iph;
        struct tcphdr                   *tcph;
        struct udphdr                   *udph;
@@ -553,6 +553,3 @@ void divert_frame(struct sk_buff *skb)
                break;
        }
 }
-
-EXPORT_SYMBOL(alloc_divert_blk);
-EXPORT_SYMBOL(free_divert_blk);
index 9c2a950..f3b8820 100644 (file)
@@ -183,9 +183,10 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
                                        continue;
                                }
                        } else {
-                               u32 tmp;
-                               if (!skb_copy_bits(skb, k, &tmp, 4)) {
-                                       A = ntohl(tmp);
+                               u32 _tmp, *p;
+                               p = skb_header_pointer(skb, k, 4, &_tmp);
+                               if (p != NULL) {
+                                       A = ntohl(*p);
                                        continue;
                                }
                        }
@@ -208,9 +209,10 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
                                        continue;
                                }
                        } else {
-                               u16 tmp;
-                               if (!skb_copy_bits(skb, k, &tmp, 2)) {
-                                       A = ntohs(tmp);
+                               u16 _tmp, *p;
+                               p = skb_header_pointer(skb, k, 2, &_tmp);
+                               if (p != NULL) {
+                                       A = ntohs(*p);
                                        continue;
                                }
                        }
@@ -233,9 +235,10 @@ load_b:
                                        continue;
                                }
                        } else {
-                               u8 tmp;
-                               if (!skb_copy_bits(skb, k, &tmp, 1)) {
-                                       A = tmp;
+                               u8 _tmp, *p;
+                               p = skb_header_pointer(skb, k, 1, &_tmp);
+                               if (p != NULL) {
+                                       A = *p;
                                        continue;
                                }
                        }
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
new file mode 100644 (file)
index 0000000..4d65f93
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * net/sched/gen_estimator.c   Simple rate estimator.
+ *
+ *             This program is free software; you can redistribute 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.
+ *
+ * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Changes:
+ *              Jamal Hadi Salim - moved it to net/core and reshulfed
+ *              names to make it usable in general net subsystem.
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/init.h>
+#include <net/sock.h>
+#include <net/gen_stats.h>
+
+/*
+   This code is NOT intended to be used for statistics collection,
+   its purpose is to provide a base for statistical multiplexing
+   for controlled load service.
+   If you need only statistics, run a user level daemon which
+   periodically reads byte counters.
+
+   Unfortunately, rate estimation is not a very easy task.
+   F.e. I did not find a simple way to estimate the current peak rate
+   and even failed to formulate the problem 8)8)
+
+   So I preferred not to built an estimator into the scheduler,
+   but run this task separately.
+   Ideally, it should be kernel thread(s), but for now it runs
+   from timers, which puts apparent top bounds on the number of rated
+   flows, has minimal overhead on small, but is enough
+   to handle controlled load service, sets of aggregates.
+
+   We measure rate over A=(1<<interval) seconds and evaluate EWMA:
+
+   avrate = avrate*(1-W) + rate*W
+
+   where W is chosen as negative power of 2: W = 2^(-ewma_log)
+
+   The resulting time constant is:
+
+   T = A/(-ln(1-W))
+
+
+   NOTES.
+
+   * The stored value for avbps is scaled by 2^5, so that maximal
+     rate is ~1Gbit, avpps is scaled by 2^10.
+
+   * Minimal interval is HZ/4=250msec (it is the greatest common divisor
+     for HZ=100 and HZ=1024 8)), maximal interval
+     is (HZ*2^EST_MAX_INTERVAL)/4 = 8sec. Shorter intervals
+     are too expensive, longer ones can be implemented
+     at user level painlessly.
+ */
+
+#define EST_MAX_INTERVAL       5
+
+struct gen_estimator
+{
+       struct gen_estimator    *next;
+       struct gnet_stats_basic *bstats;
+       struct gnet_stats_rate_est      *rate_est;
+       spinlock_t              *stats_lock;
+       unsigned                interval;
+       int                     ewma_log;
+       u64                     last_bytes;
+       u32                     last_packets;
+       u32                     avpps;
+       u32                     avbps;
+};
+
+struct gen_estimator_head
+{
+       struct timer_list       timer;
+       struct gen_estimator    *list;
+};
+
+static struct gen_estimator_head elist[EST_MAX_INTERVAL+1];
+
+/* Estimator array lock */
+static rwlock_t est_lock = RW_LOCK_UNLOCKED;
+
+static void est_timer(unsigned long arg)
+{
+       int idx = (int)arg;
+       struct gen_estimator *e;
+
+       read_lock(&est_lock);
+       for (e = elist[idx].list; e; e = e->next) {
+               u64 nbytes;
+               u32 npackets;
+               u32 rate;
+
+               spin_lock(e->stats_lock);
+               nbytes = e->bstats->bytes;
+               npackets = e->bstats->packets;
+               rate = (nbytes - e->last_bytes)<<(7 - idx);
+               e->last_bytes = nbytes;
+               e->avbps += ((long)rate - (long)e->avbps) >> e->ewma_log;
+               e->rate_est->bps = (e->avbps+0xF)>>5;
+
+               rate = (npackets - e->last_packets)<<(12 - idx);
+               e->last_packets = npackets;
+               e->avpps += ((long)rate - (long)e->avpps) >> e->ewma_log;
+               e->rate_est->pps = (e->avpps+0x1FF)>>10;
+               spin_unlock(e->stats_lock);
+       }
+
+       mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
+       read_unlock(&est_lock);
+}
+
+int gen_new_estimator(struct gnet_stats_basic *bstats,
+       struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct rtattr *opt)
+{
+       struct gen_estimator *est;
+       struct gnet_estimator *parm = RTA_DATA(opt);
+
+       if (RTA_PAYLOAD(opt) < sizeof(*parm))
+               return -EINVAL;
+
+       if (parm->interval < -2 || parm->interval > 3)
+               return -EINVAL;
+
+       est = kmalloc(sizeof(*est), GFP_KERNEL);
+       if (est == NULL)
+               return -ENOBUFS;
+
+       memset(est, 0, sizeof(*est));
+       est->interval = parm->interval + 2;
+       est->bstats = bstats;
+       est->rate_est = rate_est;
+       est->stats_lock = stats_lock;
+       est->ewma_log = parm->ewma_log;
+       est->last_bytes = bstats->bytes;
+       est->avbps = rate_est->bps<<5;
+       est->last_packets = bstats->packets;
+       est->avpps = rate_est->pps<<10;
+
+       est->next = elist[est->interval].list;
+       if (est->next == NULL) {
+               init_timer(&elist[est->interval].timer);
+               elist[est->interval].timer.data = est->interval;
+               elist[est->interval].timer.expires = jiffies + ((HZ<<est->interval)/4);
+               elist[est->interval].timer.function = est_timer;
+               add_timer(&elist[est->interval].timer);
+       }
+       write_lock_bh(&est_lock);
+       elist[est->interval].list = est;
+       write_unlock_bh(&est_lock);
+       return 0;
+}
+
+void gen_kill_estimator(struct gnet_stats_basic *bstats,
+       struct gnet_stats_rate_est *rate_est)
+{
+       int idx;
+       struct gen_estimator *est, **pest;
+
+       for (idx=0; idx <= EST_MAX_INTERVAL; idx++) {
+               int killed = 0;
+               pest = &elist[idx].list;
+               while ((est=*pest) != NULL) {
+                       if (est->rate_est != rate_est || est->bstats != bstats) {
+                               pest = &est->next;
+                               continue;
+                       }
+
+                       write_lock_bh(&est_lock);
+                       *pest = est->next;
+                       write_unlock_bh(&est_lock);
+
+                       kfree(est);
+                       killed++;
+               }
+               if (killed && elist[idx].list == NULL)
+                       del_timer(&elist[idx].timer);
+       }
+}
+
+EXPORT_SYMBOL(gen_kill_estimator);
+EXPORT_SYMBOL(gen_new_estimator);
diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c
new file mode 100644 (file)
index 0000000..2b2ba65
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * net/core/gen_stats.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.
+ *
+ * Authors:  Thomas Graf <tgraf@suug.ch>
+ *           Jamal Hadi Salim
+ *           Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * See Documentation/networking/gen_stats.txt
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/socket.h>
+#include <linux/rtnetlink.h>
+#include <linux/gen_stats.h>
+#include <net/gen_stats.h>
+
+
+static inline int
+gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size)
+{
+       RTA_PUT(d->skb, type, size, buf);
+       return 0;
+
+rtattr_failure:
+       spin_unlock_bh(d->lock);
+       return -1;
+}
+
+int
+gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type,
+       int xstats_type, spinlock_t *lock, struct gnet_dump *d)
+{
+       spin_lock_bh(lock);
+       d->lock = lock;
+       d->tail = (struct rtattr *) skb->tail;
+       d->skb = skb;
+       d->compat_tc_stats = tc_stats_type;
+       d->compat_xstats = xstats_type;
+       d->xstats = NULL;
+
+       if (d->compat_tc_stats)
+               memset(&d->tc_stats, 0, sizeof(d->tc_stats));
+
+       return gnet_stats_copy(d, type, NULL, 0);
+}
+
+int
+gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock,
+       struct gnet_dump *d)
+{
+       return gnet_stats_start_copy_compat(skb, type, 0, 0, lock, d);
+}
+
+
+int
+gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic *b)
+{
+       if (d->compat_tc_stats) {
+               d->tc_stats.bytes = b->bytes;
+               d->tc_stats.packets = b->packets;
+       }
+       
+       return gnet_stats_copy(d, TCA_STATS_BASIC, b, sizeof(*b));
+}
+
+int
+gnet_stats_copy_rate_est(struct gnet_dump *d, struct gnet_stats_rate_est *r)
+{
+       if (d->compat_tc_stats) {
+               d->tc_stats.bps = r->bps;
+               d->tc_stats.pps = r->pps;
+       }
+
+       return gnet_stats_copy(d, TCA_STATS_RATE_EST, r, sizeof(*r));
+}
+
+int
+gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q)
+{
+       if (d->compat_tc_stats) {
+               d->tc_stats.drops = q->drops;
+               d->tc_stats.qlen = q->qlen;
+               d->tc_stats.backlog = q->backlog;
+               d->tc_stats.overlimits = q->overlimits;
+       }
+               
+       return gnet_stats_copy(d, TCA_STATS_QUEUE, q, sizeof(*q));
+}
+
+int
+gnet_stats_copy_app(struct gnet_dump *d, void *st, int len)
+{
+       if (d->compat_xstats)
+               d->xstats = (struct rtattr *) d->skb->tail;
+       return gnet_stats_copy(d, TCA_STATS_APP, st, len);
+}
+
+int
+gnet_stats_finish_copy(struct gnet_dump *d)
+{
+       d->tail->rta_len = d->skb->tail - (u8 *) d->tail;
+
+       if (d->compat_tc_stats)
+               if (gnet_stats_copy(d, d->compat_tc_stats, &d->tc_stats,
+                       sizeof(d->tc_stats)) < 0)
+                       return -1;
+
+       if (d->compat_xstats && d->xstats) {
+               if (gnet_stats_copy(d, d->compat_xstats, RTA_DATA(d->xstats),
+                       RTA_PAYLOAD(d->xstats)) < 0)
+                       return -1;
+       }
+
+       spin_unlock_bh(d->lock);
+       return 0;
+}
+
+
+EXPORT_SYMBOL(gnet_stats_start_copy);
+EXPORT_SYMBOL(gnet_stats_copy_basic);
+EXPORT_SYMBOL(gnet_stats_copy_rate_est);
+EXPORT_SYMBOL(gnet_stats_copy_queue);
+EXPORT_SYMBOL(gnet_stats_copy_app);
+EXPORT_SYMBOL(gnet_stats_finish_copy);
index ee410cb..c9bd1b7 100644 (file)
@@ -12,6 +12,7 @@
  *
  *     Fixes:
  *     Vitaly E. Lavrov        releasing NULL neighbor in neigh_add.
+ *     Harald Welte            Add neighbour cache statistics like rtstat
  */
 
 #include <linux/config.h>
@@ -21,6 +22,7 @@
 #include <linux/socket.h>
 #include <linux/sched.h>
 #include <linux/netdevice.h>
+#include <linux/proc_fs.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -29,6 +31,7 @@
 #include <net/dst.h>
 #include <net/sock.h>
 #include <linux/rtnetlink.h>
+#include <linux/random.h>
 
 #define NEIGH_DEBUG 1
 
@@ -47,6 +50,8 @@
 #define NEIGH_PRINTK2 NEIGH_PRINTK
 #endif
 
+#define PNEIGH_HASHMASK                0xF
+
 static void neigh_timer_handler(unsigned long arg);
 #ifdef CONFIG_ARPD
 static void neigh_app_notify(struct neighbour *n);
@@ -56,6 +61,7 @@ void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
 
 static int neigh_glbl_allocs;
 static struct neigh_table *neigh_tables;
+static struct file_operations neigh_stat_seq_fops;
 
 /*
    Neighbour hash table buckets are protected with rwlock tbl->lock.
@@ -113,27 +119,21 @@ static int neigh_forced_gc(struct neigh_table *tbl)
        int shrunk = 0;
        int i;
 
-       for (i = 0; i <= NEIGH_HASHMASK; i++) {
+       NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
+
+       write_lock_bh(&tbl->lock);
+       for (i = 0; i <= tbl->hash_mask; i++) {
                struct neighbour *n, **np;
 
                np = &tbl->hash_buckets[i];
-               write_lock_bh(&tbl->lock);
                while ((n = *np) != NULL) {
                        /* Neighbour record may be discarded if:
-                          - nobody refers to it.
-                          - it is not permanent
-                          - (NEW and probably wrong)
-                            INCOMPLETE entries are kept at least for
-                            n->parms->retrans_time, otherwise we could
-                            flood network with resolution requests.
-                            It is not clear, what is better table overflow
-                            or flooding.
+                        * - nobody refers to it.
+                        * - it is not permanent
                         */
                        write_lock(&n->lock);
                        if (atomic_read(&n->refcnt) == 1 &&
-                           !(n->nud_state & NUD_PERMANENT) &&
-                           (n->nud_state != NUD_INCOMPLETE ||
-                            jiffies - n->used > n->parms->retrans_time)) {
+                           !(n->nud_state & NUD_PERMANENT)) {
                                *np     = n->next;
                                n->dead = 1;
                                shrunk  = 1;
@@ -144,10 +144,12 @@ static int neigh_forced_gc(struct neigh_table *tbl)
                        write_unlock(&n->lock);
                        np = &n->next;
                }
-               write_unlock_bh(&tbl->lock);
        }
 
        tbl->last_flush = jiffies;
+
+       write_unlock_bh(&tbl->lock);
+
        return shrunk;
 }
 
@@ -177,7 +179,7 @@ void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
 
        write_lock_bh(&tbl->lock);
 
-       for (i=0; i <= NEIGH_HASHMASK; i++) {
+       for (i=0; i <= tbl->hash_mask; i++) {
                struct neighbour *n, **np;
 
                np = &tbl->hash_buckets[i];
@@ -204,7 +206,7 @@ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
 
        write_lock_bh(&tbl->lock);
 
-       for (i = 0; i <= NEIGH_HASHMASK; i++) {
+       for (i = 0; i <= tbl->hash_mask; i++) {
                struct neighbour *n, **np = &tbl->hash_buckets[i];
 
                while ((n = *np) != NULL) {
@@ -227,7 +229,6 @@ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
                                   we must kill timers etc. and move
                                   it to safe state.
                                 */
-                               n->parms = &tbl->parms;
                                skb_queue_purge(&n->arp_queue);
                                n->output = neigh_blackhole;
                                if (n->nud_state & NUD_VALID)
@@ -256,7 +257,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl)
 
        if (tbl->entries > tbl->gc_thresh3 ||
            (tbl->entries > tbl->gc_thresh2 &&
-            now - tbl->last_flush > 5 * HZ)) {
+            time_after(now, tbl->last_flush + 5 * HZ))) {
                if (!neigh_forced_gc(tbl) &&
                    tbl->entries > tbl->gc_thresh3)
                        goto out;
@@ -273,11 +274,12 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl)
        n->updated        = n->used = now;
        n->nud_state      = NUD_NONE;
        n->output         = neigh_blackhole;
-       n->parms          = &tbl->parms;
+       n->parms          = neigh_parms_clone(&tbl->parms);
        init_timer(&n->timer);
        n->timer.function = neigh_timer_handler;
        n->timer.data     = (unsigned long)n;
-       tbl->stats.allocs++;
+
+       NEIGH_CACHE_STAT_INC(tbl, allocs);
        neigh_glbl_allocs++;
        tbl->entries++;
        n->tbl            = tbl;
@@ -287,17 +289,103 @@ out:
        return n;
 }
 
+static struct neighbour **neigh_hash_alloc(unsigned int entries)
+{
+       unsigned long size = entries * sizeof(struct neighbour *);
+       struct neighbour **ret;
+
+       if (size <= PAGE_SIZE) {
+               ret = kmalloc(size, GFP_ATOMIC);
+       } else {
+               ret = (struct neighbour **)
+                       __get_free_pages(GFP_ATOMIC, get_order(size));
+       }
+       if (ret)
+               memset(ret, 0, size);
+
+       return ret;
+}
+
+static void neigh_hash_free(struct neighbour **hash, unsigned int entries)
+{
+       unsigned long size = entries * sizeof(struct neighbour *);
+
+       if (size <= PAGE_SIZE)
+               kfree(hash);
+       else
+               free_pages((unsigned long)hash, get_order(size));
+}
+
+static void neigh_hash_grow(struct neigh_table *tbl, unsigned long new_entries)
+{
+       struct neighbour **new_hash, **old_hash;
+       unsigned int i, new_hash_mask, old_entries;
+
+       NEIGH_CACHE_STAT_INC(tbl, hash_grows);
+
+       BUG_ON(new_entries & (new_entries - 1));
+       new_hash = neigh_hash_alloc(new_entries);
+       if (!new_hash)
+               return;
+
+       old_entries = tbl->hash_mask + 1;
+       new_hash_mask = new_entries - 1;
+       old_hash = tbl->hash_buckets;
+
+       get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
+       for (i = 0; i < old_entries; i++) {
+               struct neighbour *n, *next;
+
+               for (n = old_hash[i]; n; n = next) {
+                       unsigned int hash_val = tbl->hash(n->primary_key, n->dev);
+
+                       hash_val &= new_hash_mask;
+                       next = n->next;
+
+                       n->next = new_hash[hash_val];
+                       new_hash[hash_val] = n;
+               }
+       }
+       tbl->hash_buckets = new_hash;
+       tbl->hash_mask = new_hash_mask;
+
+       neigh_hash_free(old_hash, old_entries);
+}
+
 struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
                               struct net_device *dev)
 {
        struct neighbour *n;
        int key_len = tbl->key_len;
-       u32 hash_val = tbl->hash(pkey, dev);
+       u32 hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;
+       
+       NEIGH_CACHE_STAT_INC(tbl, lookups);
 
        read_lock_bh(&tbl->lock);
        for (n = tbl->hash_buckets[hash_val]; n; n = n->next) {
                if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
                        neigh_hold(n);
+                       NEIGH_CACHE_STAT_INC(tbl, hits);
+                       break;
+               }
+       }
+       read_unlock_bh(&tbl->lock);
+       return n;
+}
+
+struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, const void *pkey)
+{
+       struct neighbour *n;
+       int key_len = tbl->key_len;
+       u32 hash_val = tbl->hash(pkey, NULL) & tbl->hash_mask;
+
+       NEIGH_CACHE_STAT_INC(tbl, lookups);
+
+       read_lock_bh(&tbl->lock);
+       for (n = tbl->hash_buckets[hash_val]; n; n = n->next) {
+               if (!memcmp(n->primary_key, pkey, key_len)) {
+                       neigh_hold(n);
+                       NEIGH_CACHE_STAT_INC(tbl, hits);
                        break;
                }
        }
@@ -337,15 +425,23 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
 
        n->confirmed = jiffies - (n->parms->base_reachable_time << 1);
 
-       hash_val = tbl->hash(pkey, dev);
-
        write_lock_bh(&tbl->lock);
+
+       if (tbl->entries > (tbl->hash_mask + 1))
+               neigh_hash_grow(tbl, (tbl->hash_mask + 1) << 1);
+
+       hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;
+
+       if (n->parms->dead) {
+               rc = ERR_PTR(-EINVAL);
+               goto out_tbl_unlock;
+       }
+
        for (n1 = tbl->hash_buckets[hash_val]; n1; n1 = n1->next) {
                if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
                        neigh_hold(n1);
-                       write_unlock_bh(&tbl->lock);
                        rc = n1;
-                       goto out_neigh_release;
+                       goto out_tbl_unlock;
                }
        }
 
@@ -358,6 +454,8 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
        rc = n;
 out:
        return rc;
+out_tbl_unlock:
+       write_unlock_bh(&tbl->lock);
 out_neigh_release:
        neigh_release(n);
        goto out;
@@ -395,8 +493,12 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey,
 
        memcpy(n->key, pkey, key_len);
        n->dev = dev;
+       if (dev)
+               dev_hold(dev);
 
        if (tbl->pconstructor && tbl->pconstructor(n)) {
+               if (dev)
+                       dev_put(dev);
                kfree(n);
                n = NULL;
                goto out;
@@ -423,18 +525,21 @@ int pneigh_delete(struct neigh_table *tbl, const void *pkey,
        hash_val ^= hash_val >> 4;
        hash_val &= PNEIGH_HASHMASK;
 
+       write_lock_bh(&tbl->lock);
        for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
             np = &n->next) {
                if (!memcmp(n->key, pkey, key_len) && n->dev == dev) {
-                       write_lock_bh(&tbl->lock);
                        *np = n->next;
                        write_unlock_bh(&tbl->lock);
                        if (tbl->pdestructor)
                                tbl->pdestructor(n);
+                       if (n->dev)
+                               dev_put(n->dev);
                        kfree(n);
                        return 0;
                }
        }
+       write_unlock_bh(&tbl->lock);
        return -ENOENT;
 }
 
@@ -450,6 +555,8 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
                                *np = n->next;
                                if (tbl->pdestructor)
                                        tbl->pdestructor(n);
+                               if (n->dev)
+                                       dev_put(n->dev);
                                kfree(n);
                                continue;
                        }
@@ -468,6 +575,8 @@ void neigh_destroy(struct neighbour *neigh)
 {
        struct hh_cache *hh;
 
+       NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
+
        if (!neigh->dead) {
                printk(KERN_WARNING
                       "Destroying alive neighbour %p\n", neigh);
@@ -494,6 +603,7 @@ void neigh_destroy(struct neighbour *neigh)
        skb_queue_purge(&neigh->arp_queue);
 
        dev_put(neigh->dev);
+       neigh_parms_put(neigh->parms);
 
        NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh);
 
@@ -536,46 +646,13 @@ static void neigh_connect(struct neighbour *neigh)
                hh->hh_output = neigh->ops->hh_output;
 }
 
-/*
-   Transitions NUD_STALE <-> NUD_REACHABLE do not occur
-   when fast path is built: we have no timers associated with
-   these states, we do not have time to check state when sending.
-   neigh_periodic_timer check periodically neigh->confirmed
-   time and moves NUD_REACHABLE -> NUD_STALE.
-
-   If a routine wants to know TRUE entry state, it calls
-   neigh_sync before checking state.
-
-   Called with write_locked neigh.
- */
-
-static void neigh_sync(struct neighbour *n)
-{
-       unsigned long now = jiffies;
-       u8 state = n->nud_state;
-
-       if (state & (NUD_NOARP | NUD_PERMANENT))
-               return;
-       if (state & NUD_REACHABLE) {
-               if (now - n->confirmed > n->parms->reachable_time) {
-                       n->nud_state = NUD_STALE;
-                       neigh_suspect(n);
-               }
-       } else if (state & NUD_VALID) {
-               if (now - n->confirmed < n->parms->reachable_time) {
-                       neigh_del_timer(n);
-                       n->nud_state = NUD_REACHABLE;
-                       neigh_connect(n);
-               }
-       }
-}
-
 static void neigh_periodic_timer(unsigned long arg)
 {
        struct neigh_table *tbl = (struct neigh_table *)arg;
-       unsigned long now = jiffies;
-       int i;
+       struct neighbour *n, **np;
+       unsigned long expire, now = jiffies;
 
+       NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
 
        write_lock(&tbl->lock);
 
@@ -583,7 +660,7 @@ static void neigh_periodic_timer(unsigned long arg)
         *      periodically recompute ReachableTime from random function
         */
 
-       if (now - tbl->last_rand > 300 * HZ) {
+       if (time_after(now, tbl->last_rand + 300 * HZ)) {
                struct neigh_parms *p;
                tbl->last_rand = now;
                for (p = &tbl->parms; p; p = p->next)
@@ -591,47 +668,49 @@ static void neigh_periodic_timer(unsigned long arg)
                                neigh_rand_reach_time(p->base_reachable_time);
        }
 
-       for (i = 0; i <= NEIGH_HASHMASK; i++) {
-               struct neighbour *n, **np;
-
-               np = &tbl->hash_buckets[i];
-               while ((n = *np) != NULL) {
-                       unsigned state;
+       np = &tbl->hash_buckets[tbl->hash_chain_gc];
+       tbl->hash_chain_gc = ((tbl->hash_chain_gc + 1) & tbl->hash_mask);
 
-                       write_lock(&n->lock);
+       while ((n = *np) != NULL) {
+               unsigned int state;
 
-                       state = n->nud_state;
-                       if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
-                               write_unlock(&n->lock);
-                               goto next_elt;
-                       }
+               write_lock(&n->lock);
 
-                       if ((long)(n->used - n->confirmed) < 0)
-                               n->used = n->confirmed;
+               state = n->nud_state;
+               if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
+                       write_unlock(&n->lock);
+                       goto next_elt;
+               }
 
-                       if (atomic_read(&n->refcnt) == 1 &&
-                           (state == NUD_FAILED ||
-                            now - n->used > n->parms->gc_staletime)) {
-                               *np = n->next;
-                               n->dead = 1;
-                               write_unlock(&n->lock);
-                               neigh_release(n);
-                               continue;
-                       }
+               if (time_before(n->used, n->confirmed))
+                       n->used = n->confirmed;
 
-                       if (n->nud_state & NUD_REACHABLE &&
-                           now - n->confirmed > n->parms->reachable_time) {
-                               n->nud_state = NUD_STALE;
-                               neigh_suspect(n);
-                       }
+               if (atomic_read(&n->refcnt) == 1 &&
+                   (state == NUD_FAILED ||
+                    time_after(now, n->used + n->parms->gc_staletime))) {
+                       *np = n->next;
+                       n->dead = 1;
                        write_unlock(&n->lock);
+                       neigh_release(n);
+                       continue;
+               }
+               write_unlock(&n->lock);
 
 next_elt:
-                       np = &n->next;
-               }
+               np = &n->next;
        }
 
-       mod_timer(&tbl->gc_timer, now + tbl->gc_interval);
+       /* Cycle through all hash buckets every base_reachable_time/2 ticks.
+        * ARP entry timeouts range from 1/2 base_reachable_time to 3/2
+        * base_reachable_time.
+        */
+       expire = tbl->parms.base_reachable_time >> 1;
+       expire /= (tbl->hash_mask + 1);
+       if (!expire)
+               expire = 1;
+
+       mod_timer(&tbl->gc_timer, now + expire);
+
        write_unlock(&tbl->lock);
 }
 
@@ -648,7 +727,7 @@ static __inline__ int neigh_max_probes(struct neighbour *n)
 
 static void neigh_timer_handler(unsigned long arg)
 {
-       unsigned long now = jiffies;
+       unsigned long now, next;
        struct neighbour *neigh = (struct neighbour *)arg;
        unsigned state;
        int notify = 0;
@@ -656,6 +735,8 @@ static void neigh_timer_handler(unsigned long arg)
        write_lock(&neigh->lock);
 
        state = neigh->nud_state;
+       now = jiffies;
+       next = now + HZ;
 
        if (!(state & NUD_IN_TIMER)) {
 #ifndef CONFIG_SMP
@@ -664,25 +745,47 @@ static void neigh_timer_handler(unsigned long arg)
                goto out;
        }
 
-       if ((state & NUD_VALID) &&
-           now - neigh->confirmed < neigh->parms->reachable_time) {
-               neigh->nud_state = NUD_REACHABLE;
-               NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
-               neigh_connect(neigh);
-               goto out;
-       }
-       if (state == NUD_DELAY) {
-               NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
-               neigh->nud_state = NUD_PROBE;
-               atomic_set(&neigh->probes, 0);
+       if (state & NUD_REACHABLE) {
+               if (time_before_eq(now, 
+                                  neigh->confirmed + neigh->parms->reachable_time)) {
+                       NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
+                       next = neigh->confirmed + neigh->parms->reachable_time;
+               } else if (time_before_eq(now,
+                                         neigh->used + neigh->parms->delay_probe_time)) {
+                       NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
+                       neigh->nud_state = NUD_DELAY;
+                       neigh_suspect(neigh);
+                       next = now + neigh->parms->delay_probe_time;
+               } else {
+                       NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
+                       neigh->nud_state = NUD_STALE;
+                       neigh_suspect(neigh);
+               }
+       } else if (state & NUD_DELAY) {
+               if (time_before_eq(now, 
+                                  neigh->confirmed + neigh->parms->delay_probe_time)) {
+                       NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh);
+                       neigh->nud_state = NUD_REACHABLE;
+                       neigh_connect(neigh);
+                       next = neigh->confirmed + neigh->parms->reachable_time;
+               } else {
+                       NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
+                       neigh->nud_state = NUD_PROBE;
+                       atomic_set(&neigh->probes, 0);
+                       next = now + neigh->parms->retrans_time;
+               }
+       } else {
+               /* NUD_PROBE|NUD_INCOMPLETE */
+               next = now + neigh->parms->retrans_time;
        }
 
-       if (atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
+       if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
+           atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
                struct sk_buff *skb;
 
                neigh->nud_state = NUD_FAILED;
                notify = 1;
-               neigh->tbl->stats.res_failed++;
+               NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
                NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
 
                /* It is very thin place. report_unreachable is very complicated
@@ -697,19 +800,30 @@ static void neigh_timer_handler(unsigned long arg)
                        write_lock(&neigh->lock);
                }
                skb_queue_purge(&neigh->arp_queue);
-               goto out;
        }
 
-       neigh->timer.expires = now + neigh->parms->retrans_time;
-       add_timer(&neigh->timer);
-       write_unlock(&neigh->lock);
-
-       neigh->ops->solicit(neigh, skb_peek(&neigh->arp_queue));
-       atomic_inc(&neigh->probes);
-       return;
-
+       if (neigh->nud_state & NUD_IN_TIMER) {
+               neigh_hold(neigh);
+               if (time_before(next, jiffies + HZ/2))
+                       next = jiffies + HZ/2;
+               neigh->timer.expires = next;
+               add_timer(&neigh->timer);
+       }
+       if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
+               struct sk_buff *skb = skb_peek(&neigh->arp_queue);
+               /* keep skb alive even if arp_queue overflows */
+               if (skb)
+                       skb_get(skb);
+               write_unlock(&neigh->lock);
+               neigh->ops->solicit(neigh, skb);
+               atomic_inc(&neigh->probes);
+               if (skb)
+                       kfree_skb(skb);
+       } else {
 out:
-       write_unlock(&neigh->lock);
+               write_unlock(&neigh->lock);
+       }
+
 #ifdef CONFIG_ARPD
        if (notify && neigh->parms->app_probes)
                neigh_app_notify(neigh);
@@ -720,6 +834,7 @@ out:
 int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 {
        int rc;
+       unsigned long now;
 
        write_lock_bh(&neigh->lock);
 
@@ -727,18 +842,15 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
        if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
                goto out_unlock_bh;
 
+       now = jiffies;
+       
        if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
                if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
                        atomic_set(&neigh->probes, neigh->parms->ucast_probes);
                        neigh->nud_state     = NUD_INCOMPLETE;
                        neigh_hold(neigh);
-                       neigh->timer.expires = jiffies +
-                                              neigh->parms->retrans_time;
+                       neigh->timer.expires = now + 1;
                        add_timer(&neigh->timer);
-                       write_unlock_bh(&neigh->lock);
-                       neigh->ops->solicit(neigh, skb);
-                       atomic_inc(&neigh->probes);
-                       write_lock_bh(&neigh->lock);
                } else {
                        neigh->nud_state = NUD_FAILED;
                        write_unlock_bh(&neigh->lock);
@@ -747,6 +859,12 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
                                kfree_skb(skb);
                        return 1;
                }
+       } else if (neigh->nud_state & NUD_STALE) {
+               NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
+               neigh_hold(neigh);
+               neigh->nud_state = NUD_DELAY;
+               neigh->timer.expires = jiffies + neigh->parms->delay_probe_time;
+               add_timer(&neigh->timer);
        }
 
        if (neigh->nud_state == NUD_INCOMPLETE) {
@@ -761,13 +879,6 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
                        __skb_queue_tail(&neigh->arp_queue, skb);
                }
                rc = 1;
-       } else if (neigh->nud_state == NUD_STALE) {
-               NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
-               neigh_hold(neigh);
-               neigh->nud_state = NUD_DELAY;
-               neigh->timer.expires = jiffies + neigh->parms->delay_probe_time;
-               add_timer(&neigh->timer);
-               rc = 0;
        }
 out_unlock_bh:
        write_unlock_bh(&neigh->lock);
@@ -794,14 +905,26 @@ static __inline__ void neigh_update_hhs(struct neighbour *neigh)
 /* Generic update routine.
    -- lladdr is new lladdr or NULL, if it is not supplied.
    -- new    is new state.
-   -- override == 1 allows to override existing lladdr, if it is different.
-   -- arp == 0 means that the change is administrative.
+   -- flags
+       NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
+                               if it is different.
+       NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
+                               lladdr instead of overriding it 
+                               if it is different.
+                               It also allows to retain current state
+                               if lladdr is unchanged.
+       NEIGH_UPDATE_F_ADMIN    means that the change is administrative.
+
+       NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing 
+                               NTF_ROUTER flag.
+       NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
+                               a router.
 
    Caller MUST hold reference count on the entry.
  */
 
 int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
-                int override, int arp)
+                u32 flags)
 {
        u8 old;
        int err;
@@ -809,6 +932,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
        int notify = 0;
 #endif
        struct net_device *dev;
+       int update_isrouter = 0;
 
        write_lock_bh(&neigh->lock);
 
@@ -816,7 +940,8 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
        old    = neigh->nud_state;
        err    = -EPERM;
 
-       if (arp && (old & (NUD_NOARP | NUD_PERMANENT)))
+       if (!(flags & NEIGH_UPDATE_F_ADMIN) && 
+           (old & (NUD_NOARP | NUD_PERMANENT)))
                goto out;
 
        if (!(new & NUD_VALID)) {
@@ -841,12 +966,9 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                   - compare new & old
                   - if they are different, check override flag
                 */
-               if (old & NUD_VALID) {
-                       if (!memcmp(lladdr, neigh->ha, dev->addr_len))
-                               lladdr = neigh->ha;
-                       else if (!override)
-                               goto out;
-               }
+               if ((old & NUD_VALID) && 
+                   !memcmp(lladdr, neigh->ha, dev->addr_len))
+                       lladdr = neigh->ha;
        } else {
                /* No address is supplied; if we know something,
                   use it, otherwise discard the request.
@@ -857,8 +979,6 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                lladdr = neigh->ha;
        }
 
-       neigh_sync(neigh);
-       old = neigh->nud_state;
        if (new & NUD_CONNECTED)
                neigh->confirmed = jiffies;
        neigh->updated = jiffies;
@@ -867,12 +987,37 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
           do not change entry state, if new one is STALE.
         */
        err = 0;
-       if ((old & NUD_VALID) && lladdr == neigh->ha &&
-           (new == old || (new == NUD_STALE && (old & NUD_CONNECTED))))
-               goto out;
+       update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
+       if (old & NUD_VALID) {
+               if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
+                       update_isrouter = 0;
+                       if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
+                           (old & NUD_CONNECTED)) {
+                               lladdr = neigh->ha;
+                               new = NUD_STALE;
+                       } else
+                               goto out;
+               } else {
+                       if (lladdr == neigh->ha && new == NUD_STALE &&
+                           ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
+                            (old & NUD_CONNECTED))
+                           )
+                               new = old;
+               }
+       }
+
+       if (new != old) {
+               neigh_del_timer(neigh);
+               if (new & NUD_IN_TIMER) {
+                       neigh_hold(neigh);
+                       neigh->timer.expires = jiffies + 
+                                               ((new & NUD_REACHABLE) ? 
+                                                neigh->parms->reachable_time : 0);
+                       add_timer(&neigh->timer);
+               }
+               neigh->nud_state = new;
+       }
 
-       neigh_del_timer(neigh);
-       neigh->nud_state = new;
        if (lladdr != neigh->ha) {
                memcpy(&neigh->ha, lladdr, dev->addr_len);
                neigh_update_hhs(neigh);
@@ -907,6 +1052,11 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                skb_queue_purge(&neigh->arp_queue);
        }
 out:
+       if (update_isrouter) {
+               neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
+                       (neigh->flags | NTF_ROUTER) :
+                       (neigh->flags & ~NTF_ROUTER);
+       }
        write_unlock_bh(&neigh->lock);
 #ifdef CONFIG_ARPD
        if (notify && neigh->parms->app_probes)
@@ -922,7 +1072,8 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
        struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
                                                 lladdr || !dev->addr_len);
        if (neigh)
-               neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
+               neigh_update(neigh, lladdr, NUD_STALE, 
+                            NEIGH_UPDATE_F_OVERRIDE);
        return neigh;
 }
 
@@ -1088,26 +1239,25 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
                    struct sk_buff *skb)
 {
        unsigned long now = jiffies;
-       long sched_next = net_random() % p->proxy_delay;
+       unsigned long sched_next = now + (net_random() % p->proxy_delay);
 
        if (tbl->proxy_queue.qlen > p->proxy_qlen) {
                kfree_skb(skb);
                return;
        }
        skb->stamp.tv_sec  = LOCALLY_ENQUEUED;
-       skb->stamp.tv_usec = now + sched_next;
+       skb->stamp.tv_usec = sched_next;
 
        spin_lock(&tbl->proxy_queue.lock);
        if (del_timer(&tbl->proxy_timer)) {
-               long tval = tbl->proxy_timer.expires - now;
-               if (tval < sched_next)
-                       sched_next = tval;
+               if (time_before(tbl->proxy_timer.expires, sched_next))
+                       sched_next = tbl->proxy_timer.expires;
        }
        dst_release(skb->dst);
        skb->dst = NULL;
        dev_hold(skb->dev);
        __skb_queue_tail(&tbl->proxy_queue, skb);
-       mod_timer(&tbl->proxy_timer, now + sched_next);
+       mod_timer(&tbl->proxy_timer, sched_next);
        spin_unlock(&tbl->proxy_queue.lock);
 }
 
@@ -1120,6 +1270,8 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
        if (p) {
                memcpy(p, &tbl->parms, sizeof(*p));
                p->tbl            = tbl;
+               atomic_set(&p->refcnt, 1);
+               INIT_RCU_HEAD(&p->rcu_head);
                p->reachable_time =
                                neigh_rand_reach_time(p->base_reachable_time);
                if (dev && dev->neigh_setup && dev->neigh_setup(dev, p)) {
@@ -1135,6 +1287,14 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
        return p;
 }
 
+static void neigh_rcu_free_parms(struct rcu_head *head)
+{
+       struct neigh_parms *parms =
+               container_of(head, struct neigh_parms, rcu_head);
+
+       neigh_parms_put(parms);
+}
+
 void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
 {
        struct neigh_parms **p;
@@ -1145,8 +1305,9 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
        for (p = &tbl->parms.next; *p; p = &(*p)->next) {
                if (*p == parms) {
                        *p = parms->next;
+                       parms->dead = 1;
                        write_unlock_bh(&tbl->lock);
-                       kfree(parms);
+                       call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
                        return;
                }
        }
@@ -1154,11 +1315,19 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
        NEIGH_PRINTK1("neigh_parms_release: not found\n");
 }
 
+void neigh_parms_destroy(struct neigh_parms *parms)
+{
+       kfree(parms);
+}
+
 
 void neigh_table_init(struct neigh_table *tbl)
 {
        unsigned long now = jiffies;
+       unsigned long phsize;
 
+       atomic_set(&tbl->parms.refcnt, 1);
+       INIT_RCU_HEAD(&tbl->parms.rcu_head);
        tbl->parms.reachable_time =
                          neigh_rand_reach_time(tbl->parms.base_reachable_time);
 
@@ -1171,12 +1340,36 @@ void neigh_table_init(struct neigh_table *tbl)
        if (!tbl->kmem_cachep)
                panic("cannot create neighbour cache");
 
+       tbl->stats = alloc_percpu(struct neigh_statistics);
+       if (!tbl->stats)
+               panic("cannot create neighbour cache statistics");
+       
+#ifdef CONFIG_PROC_FS
+       tbl->pde = create_proc_entry(tbl->id, 0, proc_net_stat);
+       if (!tbl->pde) 
+               panic("cannot create neighbour proc dir entry");
+       tbl->pde->proc_fops = &neigh_stat_seq_fops;
+       tbl->pde->data = tbl;
+#endif
+
+       tbl->hash_mask = 1;
+       tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
+
+       phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
+       tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL);
+
+       if (!tbl->hash_buckets || !tbl->phash_buckets)
+               panic("cannot allocate neighbour cache hashes");
+
+       memset(tbl->phash_buckets, 0, phsize);
+
+       get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
+
        tbl->lock              = RW_LOCK_UNLOCKED;
        init_timer(&tbl->gc_timer);
        tbl->gc_timer.data     = (unsigned long)tbl;
        tbl->gc_timer.function = neigh_periodic_timer;
-       tbl->gc_timer.expires  = now + tbl->gc_interval +
-                                tbl->parms.reachable_time;
+       tbl->gc_timer.expires  = now + 1;
        add_timer(&tbl->gc_timer);
 
        init_timer(&tbl->proxy_timer);
@@ -1211,6 +1404,13 @@ int neigh_table_clear(struct neigh_table *tbl)
                }
        }
        write_unlock(&neigh_tbl_lock);
+
+       neigh_hash_free(tbl->hash_buckets, tbl->hash_mask + 1);
+       tbl->hash_buckets = NULL;
+
+       kfree(tbl->phash_buckets);
+       tbl->phash_buckets = NULL;
+
        return 0;
 }
 
@@ -1250,7 +1450,9 @@ int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 
                n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST - 1]), dev);
                if (n) {
-                       err = neigh_update(n, NULL, NUD_FAILED, 1, 0);
+                       err = neigh_update(n, NULL, NUD_FAILED, 
+                                          NEIGH_UPDATE_F_OVERRIDE|
+                                          NEIGH_UPDATE_F_ADMIN);
                        neigh_release(n);
                }
                goto out_dev_put;
@@ -1323,7 +1525,8 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
                                                RTA_DATA(nda[NDA_LLADDR - 1]) :
                                                NULL,
                                           ndm->ndm_state,
-                                          override, 0);
+                                          (override ? NEIGH_UPDATE_F_OVERRIDE : 0) |
+                                          NEIGH_UPDATE_F_ADMIN);
                }
                if (n)
                        neigh_release(n);
@@ -1387,7 +1590,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
        int rc, h, s_h = cb->args[1];
        int idx, s_idx = idx = cb->args[2];
 
-       for (h = 0; h <= NEIGH_HASHMASK; h++) {
+       for (h = 0; h <= tbl->hash_mask; h++) {
                if (h < s_h)
                        continue;
                if (h > s_h)
@@ -1437,6 +1640,366 @@ int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
        return skb->len;
 }
 
+void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
+{
+       int chain;
+
+       read_lock_bh(&tbl->lock);
+       for (chain = 0; chain <= tbl->hash_mask; chain++) {
+               struct neighbour *n;
+
+               for (n = tbl->hash_buckets[chain]; n; n = n->next)
+                       cb(n, cookie);
+       }
+       read_unlock_bh(&tbl->lock);
+}
+EXPORT_SYMBOL(neigh_for_each);
+
+/* The tbl->lock must be held as a writer and BH disabled. */
+void __neigh_for_each_release(struct neigh_table *tbl,
+                             int (*cb)(struct neighbour *))
+{
+       int chain;
+
+       for (chain = 0; chain <= tbl->hash_mask; chain++) {
+               struct neighbour *n, **np;
+
+               np = &tbl->hash_buckets[chain];
+               while ((n = *np) != NULL) {
+                       int release;
+
+                       write_lock(&n->lock);
+                       release = cb(n);
+                       if (release) {
+                               *np = n->next;
+                               n->dead = 1;
+                       } else
+                               np = &n->next;
+                       write_unlock(&n->lock);
+                       if (release)
+                               neigh_release(n);
+               }
+       }
+}
+EXPORT_SYMBOL(__neigh_for_each_release);
+
+#ifdef CONFIG_PROC_FS
+
+static struct neighbour *neigh_get_first(struct seq_file *seq)
+{
+       struct neigh_seq_state *state = seq->private;
+       struct neigh_table *tbl = state->tbl;
+       struct neighbour *n = NULL;
+       int bucket = state->bucket;
+
+       state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
+       for (bucket = 0; bucket <= tbl->hash_mask; bucket++) {
+               n = tbl->hash_buckets[bucket];
+
+               while (n) {
+                       if (state->neigh_sub_iter) {
+                               loff_t fakep = 0;
+                               void *v;
+
+                               v = state->neigh_sub_iter(state, n, &fakep);
+                               if (!v)
+                                       goto next;
+                       }
+                       if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
+                               break;
+                       if (n->nud_state & ~NUD_NOARP)
+                               break;
+               next:
+                       n = n->next;
+               }
+
+               if (n)
+                       break;
+       }
+       state->bucket = bucket;
+
+       return n;
+}
+
+static struct neighbour *neigh_get_next(struct seq_file *seq,
+                                       struct neighbour *n,
+                                       loff_t *pos)
+{
+       struct neigh_seq_state *state = seq->private;
+       struct neigh_table *tbl = state->tbl;
+
+       if (state->neigh_sub_iter) {
+               void *v = state->neigh_sub_iter(state, n, pos);
+               if (v)
+                       return n;
+       }
+       n = n->next;
+
+       while (1) {
+               while (n) {
+                       if (state->neigh_sub_iter) {
+                               void *v = state->neigh_sub_iter(state, n, pos);
+                               if (v)
+                                       return n;
+                               goto next;
+                       }
+                       if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
+                               break;
+
+                       if (n->nud_state & ~NUD_NOARP)
+                               break;
+               next:
+                       n = n->next;
+               }
+
+               if (n)
+                       break;
+
+               if (++state->bucket > tbl->hash_mask)
+                       break;
+
+               n = tbl->hash_buckets[state->bucket];
+       }
+
+       if (n && pos)
+               --(*pos);
+       return n;
+}
+
+static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
+{
+       struct neighbour *n = neigh_get_first(seq);
+
+       if (n) {
+               while (*pos) {
+                       n = neigh_get_next(seq, n, pos);
+                       if (!n)
+                               break;
+               }
+       }
+       return *pos ? NULL : n;
+}
+
+static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
+{
+       struct neigh_seq_state *state = seq->private;
+       struct neigh_table *tbl = state->tbl;
+       struct pneigh_entry *pn = NULL;
+       int bucket = state->bucket;
+
+       state->flags |= NEIGH_SEQ_IS_PNEIGH;
+       for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
+               pn = tbl->phash_buckets[bucket];
+               if (pn)
+                       break;
+       }
+       state->bucket = bucket;
+
+       return pn;
+}
+
+static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
+                                           struct pneigh_entry *pn,
+                                           loff_t *pos)
+{
+       struct neigh_seq_state *state = seq->private;
+       struct neigh_table *tbl = state->tbl;
+
+       pn = pn->next;
+       while (!pn) {
+               if (++state->bucket > PNEIGH_HASHMASK)
+                       break;
+               pn = tbl->phash_buckets[state->bucket];
+               if (pn)
+                       break;
+       }
+
+       if (pn && pos)
+               --(*pos);
+
+       return pn;
+}
+
+static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
+{
+       struct pneigh_entry *pn = pneigh_get_first(seq);
+
+       if (pn) {
+               while (*pos) {
+                       pn = pneigh_get_next(seq, pn, pos);
+                       if (!pn)
+                               break;
+               }
+       }
+       return *pos ? NULL : pn;
+}
+
+static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
+{
+       struct neigh_seq_state *state = seq->private;
+       void *rc;
+
+       rc = neigh_get_idx(seq, pos);
+       if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
+               rc = pneigh_get_idx(seq, pos);
+
+       return rc;
+}
+
+void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
+{
+       struct neigh_seq_state *state = seq->private;
+       loff_t pos_minus_one;
+
+       state->tbl = tbl;
+       state->bucket = 0;
+       state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
+
+       read_lock_bh(&tbl->lock);
+
+       pos_minus_one = *pos - 1;
+       return *pos ? neigh_get_idx_any(seq, &pos_minus_one) : SEQ_START_TOKEN;
+}
+EXPORT_SYMBOL(neigh_seq_start);
+
+void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       struct neigh_seq_state *state;
+       void *rc;
+
+       if (v == SEQ_START_TOKEN) {
+               rc = neigh_get_idx(seq, pos);
+               goto out;
+       }
+
+       state = seq->private;
+       if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
+               rc = neigh_get_next(seq, v, NULL);
+               if (rc)
+                       goto out;
+               if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
+                       rc = pneigh_get_first(seq);
+       } else {
+               BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
+               rc = pneigh_get_next(seq, v, NULL);
+       }
+out:
+       ++(*pos);
+       return rc;
+}
+EXPORT_SYMBOL(neigh_seq_next);
+
+void neigh_seq_stop(struct seq_file *seq, void *v)
+{
+       struct neigh_seq_state *state = seq->private;
+       struct neigh_table *tbl = state->tbl;
+
+       read_unlock_bh(&tbl->lock);
+}
+EXPORT_SYMBOL(neigh_seq_stop);
+
+/* statistics via seq_file */
+
+static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       struct proc_dir_entry *pde = seq->private;
+       struct neigh_table *tbl = pde->data;
+       int cpu;
+
+       if (*pos == 0)
+               return SEQ_START_TOKEN;
+       
+       for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
+               if (!cpu_possible(cpu))
+                       continue;
+               *pos = cpu+1;
+               return per_cpu_ptr(tbl->stats, cpu);
+       }
+       return NULL;
+}
+
+static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       struct proc_dir_entry *pde = seq->private;
+       struct neigh_table *tbl = pde->data;
+       int cpu;
+
+       for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
+               if (!cpu_possible(cpu))
+                       continue;
+               *pos = cpu+1;
+               return per_cpu_ptr(tbl->stats, cpu);
+       }
+       return NULL;
+}
+
+static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+static int neigh_stat_seq_show(struct seq_file *seq, void *v)
+{
+       struct proc_dir_entry *pde = seq->private;
+       struct neigh_table *tbl = pde->data;
+       struct neigh_statistics *st = v;
+
+       if (v == SEQ_START_TOKEN) {
+               seq_printf(seq, "entries  allocs destroys hash_grows  lookups hits  res_failed  rcv_probes_mcast rcv_probes_ucast  periodic_gc_runs forced_gc_runs forced_gc_goal_miss\n");
+               return 0;
+       }
+
+       seq_printf(seq, "%08x  %08lx %08lx %08lx  %08lx %08lx  %08lx  "
+                       "%08lx %08lx  %08lx %08lx\n",
+                  tbl->entries,
+
+                  st->allocs,
+                  st->destroys,
+                  st->hash_grows,
+
+                  st->lookups,
+                  st->hits,
+
+                  st->res_failed,
+
+                  st->rcv_probes_mcast,
+                  st->rcv_probes_ucast,
+
+                  st->periodic_gc_runs,
+                  st->forced_gc_runs
+                  );
+
+       return 0;
+}
+
+static struct seq_operations neigh_stat_seq_ops = {
+       .start  = neigh_stat_seq_start,
+       .next   = neigh_stat_seq_next,
+       .stop   = neigh_stat_seq_stop,
+       .show   = neigh_stat_seq_show,
+};
+
+static int neigh_stat_seq_open(struct inode *inode, struct file *file)
+{
+       int ret = seq_open(file, &neigh_stat_seq_ops);
+
+       if (!ret) {
+               struct seq_file *sf = file->private_data;
+               sf->private = PDE(inode);
+       }
+       return ret;
+};
+
+static struct file_operations neigh_stat_seq_fops = {
+       .owner   = THIS_MODULE,
+       .open    = neigh_stat_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release,
+};
+
+#endif /* CONFIG_PROC_FS */
+
 #ifdef CONFIG_ARPD
 void neigh_app_ns(struct neighbour *n)
 {
@@ -1733,6 +2296,7 @@ EXPORT_SYMBOL(neigh_dump_info);
 EXPORT_SYMBOL(neigh_event_ns);
 EXPORT_SYMBOL(neigh_ifdown);
 EXPORT_SYMBOL(neigh_lookup);
+EXPORT_SYMBOL(neigh_lookup_nodev);
 EXPORT_SYMBOL(neigh_parms_alloc);
 EXPORT_SYMBOL(neigh_parms_release);
 EXPORT_SYMBOL(neigh_rand_reach_time);
index 8058d9c..e11a865 100644 (file)
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/random.h>
+#include <linux/percpu.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-static unsigned long net_rand_seed = 152L;
+
+/*
+  This is a maximally equidistributed combined Tausworthe generator
+  based on code from GNU Scientific Library 1.5 (30 Jun 2004)
+
+   x_n = (s1_n ^ s2_n ^ s3_n) 
+
+   s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
+   s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
+   s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
+
+   The period of this generator is about 2^88.
+
+   From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
+   Generators", Mathematics of Computation, 65, 213 (1996), 203--213.
+
+   This is available on the net from L'Ecuyer's home page,
+
+   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
+   ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps 
+
+   There is an erratum in the paper "Tables of Maximally
+   Equidistributed Combined LFSR Generators", Mathematics of
+   Computation, 68, 225 (1999), 261--269:
+   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
+
+        ... the k_j most significant bits of z_j must be non-
+        zero, for each j. (Note: this restriction also applies to the 
+        computer code given in [4], but was mistakenly not mentioned in
+        that paper.)
+   
+   This affects the seeding procedure by imposing the requirement
+   s1 > 1, s2 > 7, s3 > 15.
+
+*/
+struct nrnd_state {
+       u32 s1, s2, s3;
+};
+
+static DEFINE_PER_CPU(struct nrnd_state, net_rand_state);
+
+static u32 __net_random(struct nrnd_state *state)
+{
+#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
+
+       state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
+       state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
+       state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);
+
+       return (state->s1 ^ state->s2 ^ state->s3);
+}
+
+static void __net_srandom(struct nrnd_state *state, unsigned long s)
+{
+       if (s == 0)
+               s = 1;      /* default seed is 1 */
+
+#define LCG(n) (69069 * n)
+       state->s1 = LCG(s);
+       state->s2 = LCG(state->s1);
+       state->s3 = LCG(state->s2);
+
+       /* "warm it up" */
+       __net_random(state);
+       __net_random(state);
+       __net_random(state);
+       __net_random(state);
+       __net_random(state);
+       __net_random(state);
+}
+
 
 unsigned long net_random(void)
 {
-       net_rand_seed=net_rand_seed*69069L+1;
-        return net_rand_seed^jiffies;
+       unsigned long r;
+       struct nrnd_state *state = &get_cpu_var(net_rand_state);
+       r = __net_random(state);
+       put_cpu_var(state);
+       return r;
 }
 
+
 void net_srandom(unsigned long entropy)
 {
-       net_rand_seed ^= entropy;
-       net_random();
+       struct nrnd_state *state = &get_cpu_var(net_rand_state);
+       __net_srandom(state, state->s1^entropy);
+       put_cpu_var(state);
+}
+
+void __init net_random_init(void)
+{
+       int i;
+
+       for (i = 0; i < NR_CPUS; i++) {
+               struct nrnd_state *state = &per_cpu(net_rand_state,i);
+               __net_srandom(state, i+jiffies);
+       }
+}
+
+static int net_random_reseed(void)
+{
+       int i;
+       unsigned long seed[NR_CPUS];
+
+       get_random_bytes(seed, sizeof(seed));
+       for (i = 0; i < NR_CPUS; i++) {
+               struct nrnd_state *state = &per_cpu(net_rand_state,i);
+               __net_srandom(state, seed[i]);
+       }
+       return 0;
 }
+late_initcall(net_random_reseed);
 
 int net_msg_cost = 5*HZ;
 int net_msg_burst = 10;
index ab64b85..dc48de8 100644 (file)
@@ -35,6 +35,8 @@
 #include <linux/netfilter_decnet.h>
 #include <linux/spinlock.h>
 #include <linux/seq_file.h>
+#include <linux/rcupdate.h>
+#include <linux/jhash.h>
 #include <asm/atomic.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
@@ -121,26 +123,32 @@ struct neigh_table dn_neigh_table = {
 
 static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev)
 {
-       u32 hash_val;
-
-       hash_val = *(dn_address *)pkey;
-       hash_val ^= (hash_val >> 10);
-       hash_val ^= (hash_val >> 3);
-
-       return hash_val & NEIGH_HASHMASK;
+       return jhash_2words(*(dn_address *)pkey, 0, dn_neigh_table.hash_rnd);
 }
 
 static int dn_neigh_construct(struct neighbour *neigh)
 {
        struct net_device *dev = neigh->dev;
        struct dn_neigh *dn = (struct dn_neigh *)neigh;
-       struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
+       struct dn_dev *dn_db;
+       struct neigh_parms *parms;
 
-       if (dn_db == NULL)
+       rcu_read_lock();
+       dn_db = rcu_dereference(dev->dn_ptr);
+       if (dn_db == NULL) {
+               rcu_read_unlock();
                return -EINVAL;
+       }
 
-       if (dn_db->neigh_parms)
-               neigh->parms = dn_db->neigh_parms;
+       parms = dn_db->neigh_parms;
+       if (!parms) {
+               rcu_read_unlock();
+               return -EINVAL;
+       }
+
+       __neigh_parms_put(neigh->parms);
+       neigh->parms = neigh_parms_clone(parms);
+       rcu_read_unlock();
 
        if (dn_db->use_long)
                neigh->ops = &dn_long_ops;
@@ -346,27 +354,6 @@ static int dn_phase3_output(struct sk_buff *skb)
  * basically does a neigh_lookup(), but without comparing the device
  * field. This is required for the On-Ethernet cache
  */
-struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr)
-{
-       struct neighbour *neigh;
-       u32 hash_val;
-
-       hash_val = tbl->hash(ptr, NULL);
-
-       read_lock_bh(&tbl->lock);
-       for(neigh = tbl->hash_buckets[hash_val]; neigh != NULL; neigh = neigh->next) {
-               if (memcmp(neigh->primary_key, ptr, tbl->key_len) == 0) {
-                       atomic_inc(&neigh->refcnt);
-                       read_unlock_bh(&tbl->lock);
-                       return neigh;
-               }
-       }
-       read_unlock_bh(&tbl->lock);
-
-       return NULL;
-}
-
-
 /*
  * Any traffic on a pointopoint link causes the timer to be reset
  * for the entry in the neighbour table.
@@ -412,7 +399,7 @@ int dn_neigh_router_hello(struct sk_buff *skb)
                        neigh->updated = jiffies;
 
                        if (neigh->dev->type == ARPHRD_ETHER)
-                               memcpy(neigh->ha, &skb->mac.ethernet->h_source, ETH_ALEN);
+                               memcpy(neigh->ha, &eth_hdr(skb)->h_source, ETH_ALEN);
 
                        dn->blksize  = dn_ntohs(msg->blksize);
                        dn->priority = msg->priority;
@@ -468,7 +455,7 @@ int dn_neigh_endnode_hello(struct sk_buff *skb)
                        neigh->updated = jiffies;
 
                        if (neigh->dev->type == ARPHRD_ETHER)
-                               memcpy(neigh->ha, &skb->mac.ethernet->h_source, ETH_ALEN);
+                               memcpy(neigh->ha, &eth_hdr(skb)->h_source, ETH_ALEN);
                        dn->flags   &= ~(DN_NDFLAG_R1 | DN_NDFLAG_R2);
                        dn->blksize  = dn_ntohs(msg->blksize);
                        dn->priority = 0;
@@ -501,141 +488,66 @@ static char *dn_find_slot(char *base, int max, int priority)
        return (*min < priority) ? (min - 6) : NULL;
 }
 
-int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
-{
-       int t = 0;
-       int i;
-       struct neighbour *neigh;
-       struct dn_neigh *dn;
-       struct neigh_table *tbl = &dn_neigh_table;
-       unsigned char *rs = ptr;
-       struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
-
-       read_lock_bh(&tbl->lock);
-
-       for(i = 0; i < NEIGH_HASHMASK; i++) {
-               for(neigh = tbl->hash_buckets[i]; neigh != NULL; neigh = neigh->next) {
-                       if (neigh->dev != dev)
-                               continue;
-                       dn = (struct dn_neigh *)neigh;
-                       if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
-                               continue;
-                       if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
-                               continue;
-                       if (t == n)
-                               rs = dn_find_slot(ptr, n, dn->priority);
-                       else
-                               t++;
-                       if (rs == NULL)
-                               continue;
-                       dn_dn2eth(rs, dn->addr);
-                       rs += 6;
-                       *rs = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
-                       *rs |= dn->priority;
-                       rs++;
-               }
-       }
-
-       read_unlock_bh(&tbl->lock);
-
-       return t;
-}
-
-
-#ifdef CONFIG_PROC_FS
-
-struct dn_neigh_iter_state {
-       int bucket;
+struct elist_cb_state {
+       struct net_device *dev;
+       unsigned char *ptr;
+       unsigned char *rs;
+       int t, n;
 };
 
-static struct neighbour *neigh_get_first(struct seq_file *seq)
+static void neigh_elist_cb(struct neighbour *neigh, void *_info)
 {
-       struct dn_neigh_iter_state *state = seq->private;
-       struct neighbour *n = NULL;
-
-       for(state->bucket = 0;
-           state->bucket <= NEIGH_HASHMASK;
-           ++state->bucket) {
-               n = dn_neigh_table.hash_buckets[state->bucket];
-               if (n)
-                       break;
-       }
-
-       return n;
-}
-
-static struct neighbour *neigh_get_next(struct seq_file *seq,
-                                       struct neighbour *n)
-{
-       struct dn_neigh_iter_state *state = seq->private;
+       struct elist_cb_state *s = _info;
+       struct dn_dev *dn_db;
+       struct dn_neigh *dn;
 
-       n = n->next;
-try_again:
-       if (n)
-               goto out;
-       if (++state->bucket > NEIGH_HASHMASK)
-               goto out;
-       n = dn_neigh_table.hash_buckets[state->bucket];
-       goto try_again;
-out:
-       return n;
-}
+       if (neigh->dev != s->dev)
+               return;
 
-static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
-{
-       struct neighbour *n = neigh_get_first(seq);
+       dn = (struct dn_neigh *) neigh;
+       if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
+               return;
 
-       if (n)
-               while(*pos && (n = neigh_get_next(seq, n)))
-                       --*pos;
-       return *pos ? NULL : n;
-}
+       dn_db = (struct dn_dev *) s->dev->dn_ptr;
+       if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
+               return;
 
-static void *dn_neigh_get_idx(struct seq_file *seq, loff_t pos)
-{
-       void *rc;
-       read_lock_bh(&dn_neigh_table.lock);
-       rc = neigh_get_idx(seq, &pos);
-       if (!rc) {
-               read_unlock_bh(&dn_neigh_table.lock);
-       }
-       return rc;
-}
-
-static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       return *pos ? dn_neigh_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+       if (s->t == s->n)
+               s->rs = dn_find_slot(s->ptr, s->n, dn->priority);
+       else
+               s->t++;
+       if (s->rs == NULL)
+               return;
+
+       dn_dn2eth(s->rs, dn->addr);
+       s->rs += 6;
+       *(s->rs) = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
+       *(s->rs) |= dn->priority;
+       s->rs++;
 }
 
-static void *dn_neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
 {
-       void *rc;
+       struct elist_cb_state state;
 
+       state.dev = dev;
+       state.t = 0;
+       state.n = n;
+       state.ptr = ptr;
+       state.rs = ptr;
 
-       if (v == SEQ_START_TOKEN) {
-               rc = dn_neigh_get_idx(seq, 0);
-               goto out;
-       }
+       neigh_for_each(&dn_neigh_table, neigh_elist_cb, &state);
 
-       rc = neigh_get_next(seq, v);
-       if (rc)
-               goto out;
-       read_unlock_bh(&dn_neigh_table.lock);
-out:
-       ++*pos;
-       return rc;
+       return state.t;
 }
 
-static void dn_neigh_seq_stop(struct seq_file *seq, void *v)
-{
-       if (v && v != SEQ_START_TOKEN)
-               read_unlock_bh(&dn_neigh_table.lock);
-}
+
+#ifdef CONFIG_PROC_FS
 
 static inline void dn_neigh_format_entry(struct seq_file *seq,
                                         struct neighbour *n)
 {
-       struct dn_neigh *dn = (struct dn_neigh *)n;
+       struct dn_neigh *dn = (struct dn_neigh *) n;
        char buf[DN_ASCBUF_LEN];
 
        read_lock(&n->lock);
@@ -662,10 +574,16 @@ static int dn_neigh_seq_show(struct seq_file *seq, void *v)
        return 0;
 }
 
+static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       return neigh_seq_start(seq, pos, &dn_neigh_table,
+                              NEIGH_SEQ_NEIGH_ONLY);
+}
+
 static struct seq_operations dn_neigh_seq_ops = {
        .start = dn_neigh_seq_start,
-       .next  = dn_neigh_seq_next,
-       .stop  = dn_neigh_seq_stop,
+       .next  = neigh_seq_next,
+       .stop  = neigh_seq_stop,
        .show  = dn_neigh_seq_show,
 };
 
@@ -673,11 +591,12 @@ static int dn_neigh_seq_open(struct inode *inode, struct file *file)
 {
        struct seq_file *seq;
        int rc = -ENOMEM;
-       struct dn_neigh_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+       struct neigh_seq_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
 
        if (!s)
                goto out;
 
+       memset(s, 0, sizeof(*s));
        rc = seq_open(file, &dn_neigh_seq_ops);
        if (rc)
                goto out_kfree;
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
new file mode 100644 (file)
index 0000000..d504a28
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _FIB_LOOKUP_H
+#define _FIB_LOOKUP_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <net/ip_fib.h>
+
+struct fib_alias {
+       struct list_head        fa_list;
+       struct fib_info         *fa_info;
+       u8                      fa_tos;
+       u8                      fa_type;
+       u8                      fa_scope;
+       u8                      fa_state;
+};
+
+#define FA_S_ACCESSED  0x01
+
+/* Exported by fib_semantics.c */
+extern int fib_semantic_match(struct list_head *head,
+                             const struct flowi *flp,
+                             struct fib_result *res, int prefixlen);
+extern void fib_release_info(struct fib_info *);
+extern struct fib_info *fib_create_info(const struct rtmsg *r,
+                                       struct kern_rta *rta,
+                                       const struct nlmsghdr *,
+                                       int *err);
+extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *,
+                       struct kern_rta *rta, struct fib_info *fi);
+extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
+                        u8 tb_id, u8 type, u8 scope, void *dst,
+                        int dst_len, u8 tos, struct fib_info *fi);
+
+#endif /* _FIB_LOOKUP_H */
index 66e78bb..ee19a7e 100644 (file)
@@ -176,7 +176,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
        table_id = rtm->rtm_table;
        if (table_id == RT_TABLE_UNSPEC) {
                struct fib_table *table;
-               if (rtm->rtm_type == RTN_UNICAST || rtm->rtm_type == RTN_NAT) {
+               if (rtm->rtm_type == RTN_UNICAST) {
                        if ((table = fib_empty_table()) == NULL)
                                return -ENOBUFS;
                        table_id = table->tb_id;
@@ -251,26 +251,6 @@ u32 fib_rules_map_destination(u32 daddr, struct fib_result *res)
        return (daddr&~mask)|res->fi->fib_nh->nh_gw;
 }
 
-u32 fib_rules_policy(u32 saddr, struct fib_result *res, unsigned *flags)
-{
-       struct fib_rule *r = res->r;
-
-       if (r->r_action == RTN_NAT) {
-               int addrtype = inet_addr_type(r->r_srcmap);
-
-               if (addrtype == RTN_NAT) {
-                       /* Packet is from  translated source; remember it */
-                       saddr = (saddr&~r->r_srcmask)|r->r_srcmap;
-                       *flags |= RTCF_SNAT;
-               } else if (addrtype == RTN_LOCAL || r->r_srcmap == 0) {
-                       /* Packet is from masqueraded source; remember it */
-                       saddr = r->r_srcmap;
-                       *flags |= RTCF_MASQ;
-               }
-       }
-       return saddr;
-}
-
 #ifdef CONFIG_NET_CLS_ROUTE
 u32 fib_rules_tclass(struct fib_result *res)
 {
@@ -322,9 +302,7 @@ FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
        for (r = fib_rules; r; r=r->r_next) {
                if (((saddr^r->r_src) & r->r_srcmask) ||
                    ((daddr^r->r_dst) & r->r_dstmask) ||
-#ifdef CONFIG_IP_ROUTE_TOS
                    (r->r_tos && r->r_tos != flp->fl4_tos) ||
-#endif
 #ifdef CONFIG_IP_ROUTE_FWMARK
                    (r->r_fwmark && r->r_fwmark != flp->fl4_fwmark) ||
 #endif
@@ -334,7 +312,6 @@ FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
 FRprintk("tb %d r %d ", r->r_table, r->r_action);
                switch (r->r_action) {
                case RTN_UNICAST:
-               case RTN_NAT:
                        policy = r;
                        break;
                case RTN_UNREACHABLE:
index c1b6060..e2a772d 100644 (file)
 #include <net/sock.h>
 #include <net/ip_fib.h>
 
+#include "fib_lookup.h"
+
 #define FSprintk(a...)
 
-static struct fib_info         *fib_info_list;
 static rwlock_t fib_info_lock = RW_LOCK_UNLOCKED;
-int fib_info_cnt;
-
-#define for_fib_info() { struct fib_info *fi; \
-       for (fi = fib_info_list; fi; fi = fi->fib_next)
+static struct hlist_head *fib_info_hash;
+static struct hlist_head *fib_info_laddrhash;
+static unsigned int fib_hash_size;
+static unsigned int fib_info_cnt;
 
-#define endfor_fib_info() }
+#define DEVINDEX_HASHBITS 8
+#define DEVINDEX_HASHSIZE (1U << DEVINDEX_HASHBITS)
+static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE];
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 
@@ -124,17 +127,10 @@ static struct
                .error  = -EAGAIN,
                .scope  = RT_SCOPE_UNIVERSE,
        },      /* RTN_THROW */
-#ifdef CONFIG_IP_ROUTE_NAT
-       {
-               .error  = 0,
-               .scope  = RT_SCOPE_HOST,
-       },      /* RTN_NAT */
-#else
        {
                .error  = -EINVAL,
                .scope  = RT_SCOPE_NOWHERE,
        },      /* RTN_NAT */
-#endif
        {
                .error  = -EINVAL,
                .scope  = RT_SCOPE_NOWHERE,
@@ -163,12 +159,12 @@ void fib_release_info(struct fib_info *fi)
 {
        write_lock(&fib_info_lock);
        if (fi && --fi->fib_treeref == 0) {
-               if (fi->fib_next)
-                       fi->fib_next->fib_prev = fi->fib_prev;
-               if (fi->fib_prev)
-                       fi->fib_prev->fib_next = fi->fib_next;
-               if (fi == fib_info_list)
-                       fib_info_list = fi->fib_next;
+               hlist_del(&fi->fib_hash);
+               if (fi->fib_prefsrc)
+                       hlist_del(&fi->fib_lhash);
+               change_nexthops(fi) {
+                       hlist_del(&nh->nh_hash);
+               } endfor_nexthops(fi)
                fi->fib_dead = 1;
                fib_info_put(fi);
        }
@@ -196,42 +192,79 @@ static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *
        return 0;
 }
 
-static __inline__ struct fib_info * fib_find_info(const struct fib_info *nfi)
+static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
+{
+       unsigned int mask = (fib_hash_size - 1);
+       unsigned int val = fi->fib_nhs;
+
+       val ^= fi->fib_protocol;
+       val ^= fi->fib_prefsrc;
+       val ^= fi->fib_priority;
+
+       return (val ^ (val >> 7) ^ (val >> 12)) & mask;
+}
+
+static struct fib_info *fib_find_info(const struct fib_info *nfi)
 {
-       for_fib_info() {
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct fib_info *fi;
+       unsigned int hash;
+
+       hash = fib_info_hashfn(nfi);
+       head = &fib_info_hash[hash];
+
+       hlist_for_each_entry(fi, node, head, fib_hash) {
                if (fi->fib_nhs != nfi->fib_nhs)
                        continue;
                if (nfi->fib_protocol == fi->fib_protocol &&
                    nfi->fib_prefsrc == fi->fib_prefsrc &&
                    nfi->fib_priority == fi->fib_priority &&
-                   memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(fi->fib_metrics)) == 0 &&
+                   memcmp(nfi->fib_metrics, fi->fib_metrics,
+                          sizeof(fi->fib_metrics)) == 0 &&
                    ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
                    (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0))
                        return fi;
-       } endfor_fib_info();
+       }
+
        return NULL;
 }
 
+static inline unsigned int fib_devindex_hashfn(unsigned int val)
+{
+       unsigned int mask = DEVINDEX_HASHSIZE - 1;
+
+       return (val ^
+               (val >> DEVINDEX_HASHBITS) ^
+               (val >> (DEVINDEX_HASHBITS * 2))) & mask;
+}
+
 /* Check, that the gateway is already configured.
    Used only by redirect accept routine.
  */
 
 int ip_fib_check_default(u32 gw, struct net_device *dev)
 {
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct fib_nh *nh;
+       unsigned int hash;
+
        read_lock(&fib_info_lock);
-       for_fib_info() {
-               if (fi->fib_flags & RTNH_F_DEAD)
-                       continue;
-               for_nexthops(fi) {
-                       if (nh->nh_dev == dev && nh->nh_gw == gw &&
-                           nh->nh_scope == RT_SCOPE_LINK &&
-                           !(nh->nh_flags&RTNH_F_DEAD)) {
-                               read_unlock(&fib_info_lock);
-                               return 0;
-                       }
-               } endfor_nexthops(fi);
-       } endfor_fib_info();
+
+       hash = fib_devindex_hashfn(dev->ifindex);
+       head = &fib_info_devhash[hash];
+       hlist_for_each_entry(nh, node, head, nh_hash) {
+               if (nh->nh_dev == dev &&
+                   nh->nh_gw == gw &&
+                   !(nh->nh_flags&RTNH_F_DEAD)) {
+                       read_unlock(&fib_info_lock);
+                       return 0;
+               }
+       }
+
        read_unlock(&fib_info_lock);
+
        return -1;
 }
 
@@ -458,6 +491,82 @@ out:
        return 0;
 }
 
+static inline unsigned int fib_laddr_hashfn(u32 val)
+{
+       unsigned int mask = (fib_hash_size - 1);
+
+       return (val ^ (val >> 7) ^ (val >> 14)) & mask;
+}
+
+static struct hlist_head *fib_hash_alloc(int bytes)
+{
+       if (bytes <= PAGE_SIZE)
+               return kmalloc(bytes, GFP_KERNEL);
+       else
+               return (struct hlist_head *)
+                       __get_free_pages(GFP_KERNEL, get_order(bytes));
+}
+
+static void fib_hash_free(struct hlist_head *hash, int bytes)
+{
+       if (!hash)
+               return;
+
+       if (bytes <= PAGE_SIZE)
+               kfree(hash);
+       else
+               free_pages((unsigned long) hash, get_order(bytes));
+}
+
+static void fib_hash_move(struct hlist_head *new_info_hash,
+                         struct hlist_head *new_laddrhash,
+                         unsigned int new_size)
+{
+       unsigned int old_size = fib_hash_size;
+       unsigned int i;
+
+       write_lock(&fib_info_lock);
+       fib_hash_size = new_size;
+
+       for (i = 0; i < old_size; i++) {
+               struct hlist_head *head = &fib_info_hash[i];
+               struct hlist_node *node, *n;
+               struct fib_info *fi;
+
+               hlist_for_each_entry_safe(fi, node, n, head, fib_hash) {
+                       struct hlist_head *dest;
+                       unsigned int new_hash;
+
+                       hlist_del(&fi->fib_hash);
+
+                       new_hash = fib_info_hashfn(fi);
+                       dest = &new_info_hash[new_hash];
+                       hlist_add_head(&fi->fib_hash, dest);
+               }
+       }
+       fib_info_hash = new_info_hash;
+
+       for (i = 0; i < old_size; i++) {
+               struct hlist_head *lhead = &fib_info_laddrhash[i];
+               struct hlist_node *node, *n;
+               struct fib_info *fi;
+
+               hlist_for_each_entry_safe(fi, node, n, lhead, fib_lhash) {
+                       struct hlist_head *ldest;
+                       unsigned int new_hash;
+
+                       hlist_del(&fi->fib_lhash);
+
+                       new_hash = fib_laddr_hashfn(fi->fib_prefsrc);
+                       ldest = &new_laddrhash[new_hash];
+                       hlist_add_head(&fi->fib_lhash, ldest);
+               }
+       }
+       fib_info_laddrhash = new_laddrhash;
+
+       write_unlock(&fib_info_lock);
+}
+
 struct fib_info *
 fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
                const struct nlmsghdr *nlh, int *errp)
@@ -483,15 +592,45 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
        }
 #endif
 
-       fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
        err = -ENOBUFS;
+       if (fib_info_cnt >= fib_hash_size) {
+               unsigned int new_size = fib_hash_size << 1;
+               struct hlist_head *new_info_hash;
+               struct hlist_head *new_laddrhash;
+               unsigned int bytes;
+
+               if (!new_size)
+                       new_size = 1;
+               bytes = new_size * sizeof(struct hlist_head *);
+               new_info_hash = fib_hash_alloc(bytes);
+               new_laddrhash = fib_hash_alloc(bytes);
+               if (!new_info_hash || !new_laddrhash) {
+                       fib_hash_free(new_info_hash, bytes);
+                       fib_hash_free(new_laddrhash, bytes);
+               } else {
+                       memset(new_info_hash, 0, bytes);
+                       memset(new_laddrhash, 0, bytes);
+
+                       fib_hash_move(new_info_hash, new_laddrhash, new_size);
+               }
+
+               if (!fib_hash_size)
+                       goto failure;
+       }
+
+       fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
        if (fi == NULL)
                goto failure;
        fib_info_cnt++;
        memset(fi, 0, sizeof(*fi)+nhs*sizeof(struct fib_nh));
 
        fi->fib_protocol = r->rtm_protocol;
+
        fi->fib_nhs = nhs;
+       change_nexthops(fi) {
+               nh->nh_parent = fi;
+       } endfor_nexthops(fi)
+
        fi->fib_flags = r->rtm_flags;
        if (rta->rta_priority)
                fi->fib_priority = *rta->rta_priority;
@@ -543,15 +682,6 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
 #endif
        }
 
-#ifdef CONFIG_IP_ROUTE_NAT
-       if (r->rtm_type == RTN_NAT) {
-               if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif)
-                       goto err_inval;
-               memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 4);
-               goto link_it;
-       }
-#endif
-
        if (fib_props[r->rtm_type].error) {
                if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
                        goto err_inval;
@@ -597,11 +727,24 @@ link_it:
        fi->fib_treeref++;
        atomic_inc(&fi->fib_clntref);
        write_lock(&fib_info_lock);
-       fi->fib_next = fib_info_list;
-       fi->fib_prev = NULL;
-       if (fib_info_list)
-               fib_info_list->fib_prev = fi;
-       fib_info_list = fi;
+       hlist_add_head(&fi->fib_hash,
+                      &fib_info_hash[fib_info_hashfn(fi)]);
+       if (fi->fib_prefsrc) {
+               struct hlist_head *head;
+
+               head = &fib_info_laddrhash[fib_laddr_hashfn(fi->fib_prefsrc)];
+               hlist_add_head(&fi->fib_lhash, head);
+       }
+       change_nexthops(fi) {
+               struct hlist_head *head;
+               unsigned int hash;
+
+               if (!nh->nh_dev)
+                       continue;
+               hash = fib_devindex_hashfn(nh->nh_dev->ifindex);
+               head = &fib_info_devhash[hash];
+               hlist_add_head(&nh->nh_hash, head);
+       } endfor_nexthops(fi)
        write_unlock(&fib_info_lock);
        return fi;
 
@@ -617,57 +760,73 @@ failure:
        return NULL;
 }
 
-int 
-fib_semantic_match(int type, struct fib_info *fi, const struct flowi *flp, struct fib_result *res)
+int fib_semantic_match(struct list_head *head, const struct flowi *flp,
+                      struct fib_result *res, int prefixlen)
 {
-       int err = fib_props[type].error;
+       struct fib_alias *fa;
+       int nh_sel = 0;
 
-       if (err == 0) {
-               if (fi->fib_flags&RTNH_F_DEAD)
-                       return 1;
+       list_for_each_entry(fa, head, fa_list) {
+               int err;
 
-               res->fi = fi;
+               if (fa->fa_tos &&
+                   fa->fa_tos != flp->fl4_tos)
+                       continue;
 
-               switch (type) {
-#ifdef CONFIG_IP_ROUTE_NAT
-               case RTN_NAT:
-                       FIB_RES_RESET(*res);
-                       atomic_inc(&fi->fib_clntref);
-                       return 0;
-#endif
-               case RTN_UNICAST:
-               case RTN_LOCAL:
-               case RTN_BROADCAST:
-               case RTN_ANYCAST:
-               case RTN_MULTICAST:
-                       for_nexthops(fi) {
-                               if (nh->nh_flags&RTNH_F_DEAD)
-                                       continue;
-                               if (!flp->oif || flp->oif == nh->nh_oif)
-                                       break;
-                       }
+               if (fa->fa_scope < flp->fl4_scope)
+                       continue;
+
+               fa->fa_state |= FA_S_ACCESSED;
+
+               err = fib_props[fa->fa_type].error;
+               if (err == 0) {
+                       struct fib_info *fi = fa->fa_info;
+
+                       if (fi->fib_flags & RTNH_F_DEAD)
+                               continue;
+
+                       switch (fa->fa_type) {
+                       case RTN_UNICAST:
+                       case RTN_LOCAL:
+                       case RTN_BROADCAST:
+                       case RTN_ANYCAST:
+                       case RTN_MULTICAST:
+                               for_nexthops(fi) {
+                                       if (nh->nh_flags&RTNH_F_DEAD)
+                                               continue;
+                                       if (!flp->oif || flp->oif == nh->nh_oif)
+                                               break;
+                               }
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-                       if (nhsel < fi->fib_nhs) {
-                               res->nh_sel = nhsel;
-                               atomic_inc(&fi->fib_clntref);
-                               return 0;
-                       }
+                               if (nhsel < fi->fib_nhs) {
+                                       nh_sel = nhsel;
+                                       goto out_fill_res;
+                               }
 #else
-                       if (nhsel < 1) {
-                               atomic_inc(&fi->fib_clntref);
-                               return 0;
-                       }
+                               if (nhsel < 1) {
+                                       goto out_fill_res;
+                               }
 #endif
-                       endfor_nexthops(fi);
-                       res->fi = NULL;
-                       return 1;
-               default:
-                       res->fi = NULL;
-                       printk(KERN_DEBUG "impossible 102\n");
-                       return -EINVAL;
+                               endfor_nexthops(fi);
+                               continue;
+
+                       default:
+                               printk(KERN_DEBUG "impossible 102\n");
+                               return -EINVAL;
+                       };
                }
+               return err;
        }
-       return err;
+       return 1;
+
+out_fill_res:
+       res->prefixlen = prefixlen;
+       res->nh_sel = nh_sel;
+       res->type = fa->fa_type;
+       res->scope = fa->fa_scope;
+       res->fi = fa->fa_info;
+       atomic_inc(&res->fi->fib_clntref);
+       return 0;
 }
 
 /* Find appropriate source address to this destination */
@@ -906,13 +1065,36 @@ int fib_sync_down(u32 local, struct net_device *dev, int force)
        if (force)
                scope = -1;
 
-       for_fib_info() {
-               if (local && fi->fib_prefsrc == local) {
-                       fi->fib_flags |= RTNH_F_DEAD;
-                       ret++;
-               } else if (dev && fi->fib_nhs) {
-                       int dead = 0;
+       if (local && fib_info_laddrhash) {
+               unsigned int hash = fib_laddr_hashfn(local);
+               struct hlist_head *head = &fib_info_laddrhash[hash];
+               struct hlist_node *node;
+               struct fib_info *fi;
+
+               hlist_for_each_entry(fi, node, head, fib_lhash) {
+                       if (fi->fib_prefsrc == local) {
+                               fi->fib_flags |= RTNH_F_DEAD;
+                               ret++;
+                       }
+               }
+       }
+
+       if (dev) {
+               struct fib_info *prev_fi = NULL;
+               unsigned int hash = fib_devindex_hashfn(dev->ifindex);
+               struct hlist_head *head = &fib_info_devhash[hash];
+               struct hlist_node *node;
+               struct fib_nh *nh;
 
+               hlist_for_each_entry(nh, node, head, nh_hash) {
+                       struct fib_info *fi = nh->nh_parent;
+                       int dead;
+
+                       BUG_ON(!fi->fib_nhs);
+                       if (nh->nh_dev != dev || fi == prev_fi)
+                               continue;
+                       prev_fi = fi;
+                       dead = 0;
                        change_nexthops(fi) {
                                if (nh->nh_flags&RTNH_F_DEAD)
                                        dead++;
@@ -939,7 +1121,8 @@ int fib_sync_down(u32 local, struct net_device *dev, int force)
                                ret++;
                        }
                }
-       } endfor_fib_info();
+       }
+
        return ret;
 }
 
@@ -952,14 +1135,31 @@ int fib_sync_down(u32 local, struct net_device *dev, int force)
 
 int fib_sync_up(struct net_device *dev)
 {
-       int ret = 0;
+       struct fib_info *prev_fi;
+       unsigned int hash;
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct fib_nh *nh;
+       int ret;
 
        if (!(dev->flags&IFF_UP))
                return 0;
 
-       for_fib_info() {
-               int alive = 0;
+       prev_fi = NULL;
+       hash = fib_devindex_hashfn(dev->ifindex);
+       head = &fib_info_devhash[hash];
+       ret = 0;
+
+       hlist_for_each_entry(nh, node, head, nh_hash) {
+               struct fib_info *fi = nh->nh_parent;
+               int alive;
 
+               BUG_ON(!fi->fib_nhs);
+               if (nh->nh_dev != dev || fi == prev_fi)
+                       continue;
+
+               prev_fi = fi;
+               alive = 0;
                change_nexthops(fi) {
                        if (!(nh->nh_flags&RTNH_F_DEAD)) {
                                alive++;
@@ -980,7 +1180,8 @@ int fib_sync_up(struct net_device *dev)
                        fi->fib_flags &= ~RTNH_F_DEAD;
                        ret++;
                }
-       } endfor_fib_info();
+       }
+
        return ret;
 }
 
index 9f4b94f..168e5b3 100644 (file)
@@ -383,21 +383,23 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
        struct ip_vs_conn *cp = NULL;
        struct iphdr *iph = skb->nh.iph;
        struct ip_vs_dest *dest;
-       __u16 ports[2];
+       __u16 _ports[2], *pptr;
 
-       if (skb_copy_bits(skb, iph->ihl*4, ports, sizeof(ports)) < 0)
+       pptr = skb_header_pointer(skb, iph->ihl*4,
+                                 sizeof(_ports), _ports);
+       if (pptr == NULL)
                return NULL;
 
        /*
         *    Persistent service
         */
        if (svc->flags & IP_VS_SVC_F_PERSISTENT)
-               return ip_vs_sched_persist(svc, skb, ports);
+               return ip_vs_sched_persist(svc, skb, pptr);
 
        /*
         *    Non-persistent service
         */
-       if (!svc->fwmark && ports[1] != svc->port) {
+       if (!svc->fwmark && pptr[1] != svc->port) {
                if (!svc->port)
                        IP_VS_ERR("Schedule: port zero only supported "
                                  "in persistent services, "
@@ -415,9 +417,9 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
         *    Create a connection entry.
         */
        cp = ip_vs_conn_new(iph->protocol,
-                           iph->saddr, ports[0],
-                           iph->daddr, ports[1],
-                           dest->addr, dest->port?dest->port:ports[1],
+                           iph->saddr, pptr[0],
+                           iph->daddr, pptr[1],
+                           dest->addr, dest->port?dest->port:pptr[1],
                            0,
                            dest);
        if (cp == NULL)
@@ -444,10 +446,12 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
                struct ip_vs_protocol *pp)
 {
-       __u16 ports[2];
+       __u16 _ports[2], *pptr;
        struct iphdr *iph = skb->nh.iph;
 
-       if (skb_copy_bits(skb, iph->ihl*4, ports, sizeof(ports)) < 0) {
+       pptr = skb_header_pointer(skb, iph->ihl*4,
+                                 sizeof(_ports), _ports);
+       if (pptr == NULL) {
                ip_vs_service_put(svc);
                return NF_DROP;
        }
@@ -465,8 +469,8 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
                /* create a new connection entry */
                IP_VS_DBG(6, "ip_vs_leave: create a cache_bypass entry\n");
                cp = ip_vs_conn_new(iph->protocol,
-                                   iph->saddr, ports[0],
-                                   iph->daddr, ports[1],
+                                   iph->saddr, pptr[0],
+                                   iph->daddr, pptr[1],
                                    0, 0,
                                    IP_VS_CONN_F_BYPASS,
                                    NULL);
@@ -494,7 +498,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
         * listed in the ipvs table), pass the packets, because it is
         * not ipvs job to decide to drop the packets.
         */
-       if ((svc->port == FTPPORT) && (ports[1] != FTPPORT)) {
+       if ((svc->port == FTPPORT) && (pptr[1] != FTPPORT)) {
                ip_vs_service_put(svc);
                return NF_ACCEPT;
        }
@@ -607,8 +611,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
 {
        struct sk_buff *skb = *pskb;
        struct iphdr *iph;
-       struct icmphdr  icmph;
-       struct iphdr    ciph;   /* The ip header contained within the ICMP */
+       struct icmphdr  _icmph, *ic;
+       struct iphdr    _ciph, *cih;    /* The ip header contained within the ICMP */
        struct ip_vs_conn *cp;
        struct ip_vs_protocol *pp;
        unsigned int offset, ihl, verdict;
@@ -625,11 +629,12 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
 
        iph = skb->nh.iph;
        offset = ihl = iph->ihl * 4;
-       if (skb_copy_bits(skb, offset, &icmph, sizeof(icmph)) < 0)
+       ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+       if (ic == NULL)
                return NF_DROP;
 
        IP_VS_DBG(12, "Outgoing ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
-                 icmph.type, ntohs(icmp_id(&icmph)),
+                 ic->type, ntohs(icmp_id(ic)),
                  NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
 
        /*
@@ -639,33 +644,34 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
         * this means that some packets will manage to get a long way
         * down this stack and then be rejected, but that's life.
         */
-       if ((icmph.type != ICMP_DEST_UNREACH) &&
-           (icmph.type != ICMP_SOURCE_QUENCH) &&
-           (icmph.type != ICMP_TIME_EXCEEDED)) {
+       if ((ic->type != ICMP_DEST_UNREACH) &&
+           (ic->type != ICMP_SOURCE_QUENCH) &&
+           (ic->type != ICMP_TIME_EXCEEDED)) {
                *related = 0;
                return NF_ACCEPT;
        }
 
        /* Now find the contained IP header */
-       offset += sizeof(icmph);
-       if (skb_copy_bits(skb, offset, &ciph, sizeof(ciph)) < 0)
+       offset += sizeof(_icmph);
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+       if (cih == NULL)
                return NF_ACCEPT; /* The packet looks wrong, ignore */
 
-       pp = ip_vs_proto_get(ciph.protocol);
+       pp = ip_vs_proto_get(cih->protocol);
        if (!pp)
                return NF_ACCEPT;
 
        /* Is the embedded protocol header present? */
-       if (unlikely(ciph.frag_off & __constant_htons(IP_OFFSET) &&
+       if (unlikely(cih->frag_off & __constant_htons(IP_OFFSET) &&
                     pp->dont_defrag))
                return NF_ACCEPT;
 
        IP_VS_DBG_PKT(11, pp, skb, offset, "Checking outgoing ICMP for");
 
-       offset += ciph.ihl * 4;
+       offset += cih->ihl * 4;
 
        /* The embedded headers contain source and dest in reverse order */
-       cp = pp->conn_out_get(skb, pp, &ciph, offset, 1);
+       cp = pp->conn_out_get(skb, pp, cih, offset, 1);
        if (!cp)
                return NF_ACCEPT;
 
@@ -685,7 +691,7 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
                goto out;
        }
 
-       if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol)
+       if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
                offset += 2 * sizeof(__u16);
        if (!ip_vs_make_skb_writable(pskb, offset))
                goto out;
@@ -707,11 +713,13 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
 
 static inline int is_tcp_reset(const struct sk_buff *skb)
 {
-       struct tcphdr tcph;
+       struct tcphdr _tcph, *th;
 
-       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &tcph, sizeof(tcph)) < 0)
+       th = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+                               sizeof(_tcph), &_tcph);
+       if (th == NULL)
                return 0;
-       return tcph.rst;
+       return th->rst;
 }
 
 /*
@@ -735,13 +743,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
        if (skb->nfcache & NFC_IPVS_PROPERTY)
                return NF_ACCEPT;
 
-       if (skb->ip_summed == CHECKSUM_HW) {
-               if (skb_checksum_help(pskb, (out == NULL)))
-                       return NF_DROP;
-               if (skb != *pskb)
-                       skb = *pskb;
-       }
-
        iph = skb->nh.iph;
        if (unlikely(iph->protocol == IPPROTO_ICMP)) {
                int related, verdict = ip_vs_out_icmp(pskb, &related);
@@ -777,12 +778,14 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
                if (sysctl_ip_vs_nat_icmp_send &&
                    (pp->protocol == IPPROTO_TCP ||
                     pp->protocol == IPPROTO_UDP)) {
-                       __u16 ports[2];
+                       __u16 _ports[2], *pptr;
 
-                       if (skb_copy_bits(skb, ihl, ports, sizeof(ports)) < 0)
+                       pptr = skb_header_pointer(skb, ihl,
+                                                 sizeof(_ports), _ports);
+                       if (pptr == NULL)
                                return NF_ACCEPT;       /* Not for me */
                        if (ip_vs_lookup_real_service(iph->protocol,
-                                                     iph->saddr, ports[0])) {
+                                                     iph->saddr, pptr[0])) {
                                /*
                                 * Notify the real server: there is no
                                 * existing entry if it is not RST
@@ -866,8 +869,8 @@ static int ip_vs_in_icmp(struct sk_buff **pskb, int *related)
 {
        struct sk_buff *skb = *pskb;
        struct iphdr *iph;
-       struct icmphdr  icmph;
-       struct iphdr    ciph;   /* The ip header contained within the ICMP */
+       struct icmphdr  _icmph, *ic;
+       struct iphdr    _ciph, *cih;    /* The ip header contained within the ICMP */
        struct ip_vs_conn *cp;
        struct ip_vs_protocol *pp;
        unsigned int offset, ihl, verdict;
@@ -884,11 +887,12 @@ static int ip_vs_in_icmp(struct sk_buff **pskb, int *related)
 
        iph = skb->nh.iph;
        offset = ihl = iph->ihl * 4;
-       if (skb_copy_bits(skb, offset, &icmph, sizeof(icmph)) < 0)
+       ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+       if (ic == NULL)
                return NF_DROP;
 
        IP_VS_DBG(12, "Incoming ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
-                 icmph.type, ntohs(icmp_id(&icmph)),
+                 ic->type, ntohs(icmp_id(ic)),
                  NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
 
        /*
@@ -898,33 +902,34 @@ static int ip_vs_in_icmp(struct sk_buff **pskb, int *related)
         * this means that some packets will manage to get a long way
         * down this stack and then be rejected, but that's life.
         */
-       if ((icmph.type != ICMP_DEST_UNREACH) &&
-           (icmph.type != ICMP_SOURCE_QUENCH) &&
-           (icmph.type != ICMP_TIME_EXCEEDED)) {
+       if ((ic->type != ICMP_DEST_UNREACH) &&
+           (ic->type != ICMP_SOURCE_QUENCH) &&
+           (ic->type != ICMP_TIME_EXCEEDED)) {
                *related = 0;
                return NF_ACCEPT;
        }
 
        /* Now find the contained IP header */
-       offset += sizeof(icmph);
-       if (skb_copy_bits(skb, offset, &ciph, sizeof(ciph)) < 0)
+       offset += sizeof(_icmph);
+       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+       if (cih == NULL)
                return NF_ACCEPT; /* The packet looks wrong, ignore */
 
-       pp = ip_vs_proto_get(ciph.protocol);
+       pp = ip_vs_proto_get(cih->protocol);
        if (!pp)
                return NF_ACCEPT;
 
        /* Is the embedded protocol header present? */
-       if (unlikely(ciph.frag_off & __constant_htons(IP_OFFSET) &&
+       if (unlikely(cih->frag_off & __constant_htons(IP_OFFSET) &&
                     pp->dont_defrag))
                return NF_ACCEPT;
 
        IP_VS_DBG_PKT(11, pp, skb, offset, "Checking incoming ICMP for");
 
-       offset += ciph.ihl * 4;
+       offset += cih->ihl * 4;
 
        /* The embedded headers contain source and dest in reverse order */
-       cp = pp->conn_in_get(skb, pp, &ciph, offset, 1);
+       cp = pp->conn_in_get(skb, pp, cih, offset, 1);
        if (!cp)
                return NF_ACCEPT;
 
@@ -941,7 +946,7 @@ static int ip_vs_in_icmp(struct sk_buff **pskb, int *related)
 
        /* do the statistics and put it back */
        ip_vs_in_stats(cp, skb);
-       if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol)
+       if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
                offset += 2 * sizeof(__u16);
        verdict = ip_vs_icmp_xmit(skb, cp, pp, offset);
        /* do not touch skb anymore */
@@ -981,13 +986,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
                return NF_ACCEPT;
        }
 
-       if (skb->ip_summed == CHECKSUM_HW) {
-               if (skb_checksum_help(pskb, (out == NULL)))
-                       return NF_DROP;
-               if (skb != *pskb)
-                       skb = *pskb;
-       }
-
        iph = skb->nh.iph;
        if (unlikely(iph->protocol == IPPROTO_ICMP)) {
                int related, verdict = ip_vs_in_icmp(pskb, &related);
index caf24e3..dfd0a7d 100644 (file)
@@ -166,27 +166,33 @@ ip_vs_tcpudp_debug_packet(struct ip_vs_protocol *pp,
                          const char *msg)
 {
        char buf[128];
-       __u16 ports[2];
-       struct iphdr iph;
+       struct iphdr _iph, *ih;
 
-       if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+       ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+       if (ih == NULL)
                sprintf(buf, "%s TRUNCATED", pp->name);
-       else if (iph.frag_off & __constant_htons(IP_OFFSET))
+       else if (ih->frag_off & __constant_htons(IP_OFFSET))
                sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u frag",
-                       pp->name, NIPQUAD(iph.saddr),
-                       NIPQUAD(iph.daddr));
-       else if (skb_copy_bits(skb, offset + iph.ihl*4, ports, sizeof(ports)) < 0)
-               sprintf(buf, "%s TRUNCATED %u.%u.%u.%u->%u.%u.%u.%u",
-                       pp->name,
-                       NIPQUAD(iph.saddr),
-                       NIPQUAD(iph.daddr));
-       else
-               sprintf(buf, "%s %u.%u.%u.%u:%u->%u.%u.%u.%u:%u",
-                       pp->name,
-                       NIPQUAD(iph.saddr),
-                       ntohs(ports[0]),
-                       NIPQUAD(iph.daddr),
-                       ntohs(ports[1]));
+                       pp->name, NIPQUAD(ih->saddr),
+                       NIPQUAD(ih->daddr));
+       else {
+               __u16 _ports[2], *pptr
+;
+               pptr = skb_header_pointer(skb, offset + ih->ihl*4,
+                                         sizeof(_ports), _ports);
+               if (pptr == NULL)
+                       sprintf(buf, "%s TRUNCATED %u.%u.%u.%u->%u.%u.%u.%u",
+                               pp->name,
+                               NIPQUAD(ih->saddr),
+                               NIPQUAD(ih->daddr));
+               else
+                       sprintf(buf, "%s %u.%u.%u.%u:%u->%u.%u.%u.%u:%u",
+                               pp->name,
+                               NIPQUAD(ih->saddr),
+                               ntohs(pptr[0]),
+                               NIPQUAD(ih->daddr),
+                               ntohs(pptr[1]));
+       }
 
        printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
index ffea536..453e94a 100644 (file)
@@ -129,14 +129,15 @@ ah_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb,
                int offset, const char *msg)
 {
        char buf[256];
-       struct iphdr iph;
+       struct iphdr _iph, *ih;
 
-       if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+       ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+       if (ih == NULL)
                sprintf(buf, "%s TRUNCATED", pp->name);
        else
                sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u",
-                       pp->name, NIPQUAD(iph.saddr),
-                       NIPQUAD(iph.daddr));
+                       pp->name, NIPQUAD(ih->saddr),
+                       NIPQUAD(ih->daddr));
 
        printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
index 1922388..478e5c7 100644 (file)
@@ -128,14 +128,15 @@ esp_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb,
                 int offset, const char *msg)
 {
        char buf[256];
-       struct iphdr iph;
+       struct iphdr _iph, *ih;
 
-       if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+       ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+       if (ih == NULL)
                sprintf(buf, "%s TRUNCATED", pp->name);
        else
                sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u",
-                       pp->name, NIPQUAD(iph.saddr),
-                       NIPQUAD(iph.daddr));
+                       pp->name, NIPQUAD(ih->saddr),
+                       NIPQUAD(ih->daddr));
 
        printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
index d611b5a..747e033 100644 (file)
@@ -104,24 +104,29 @@ icmp_debug_packet(struct ip_vs_protocol *pp,
                  const char *msg)
 {
        char buf[256];
-       struct iphdr iph;
-       struct icmphdr icmph;
+       struct iphdr _iph, *ih;
 
-       if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+       ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+       if (ih == NULL)
                sprintf(buf, "%s TRUNCATED", pp->name);
-       else if (iph.frag_off & __constant_htons(IP_OFFSET))
+       else if (ih->frag_off & __constant_htons(IP_OFFSET))
                sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u frag",
-                       pp->name, NIPQUAD(iph.saddr),
-                       NIPQUAD(iph.daddr));
-       else if (skb_copy_bits(skb, offset + iph.ihl*4, &icmph, sizeof(icmph)) < 0)
-               sprintf(buf, "%s TRUNCATED to %u bytes\n",
-                       pp->name, skb->len - offset);
-       else
-               sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u T:%d C:%d",
-                       pp->name, NIPQUAD(iph.saddr),
-                       NIPQUAD(iph.daddr),
-                       icmph.type, icmph.code);
-
+                       pp->name, NIPQUAD(ih->saddr),
+                       NIPQUAD(ih->daddr));
+       else {
+               struct icmphdr _icmph, *ic;
+
+               ic = skb_header_pointer(skb, offset + ih->ihl*4,
+                                       sizeof(_icmph), &_icmph);
+               if (ic == NULL)
+                       sprintf(buf, "%s TRUNCATED to %u bytes\n",
+                               pp->name, skb->len - offset);
+               else
+                       sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u T:%d C:%d",
+                               pp->name, NIPQUAD(ih->saddr),
+                               NIPQUAD(ih->daddr),
+                               ic->type, ic->code);
+       }
        printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
 
index 2f00e91..bd8f898 100644 (file)
@@ -29,19 +29,20 @@ static struct ip_vs_conn *
 tcp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
                const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
-       __u16 ports[2];
+       __u16 _ports[2], *pptr;
 
-       if (skb_copy_bits(skb, proto_off, ports, sizeof(ports)) < 0)
+       pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+       if (pptr == NULL)
                return NULL;
 
        if (likely(!inverse)) {
                return ip_vs_conn_in_get(iph->protocol,
-                                        iph->saddr, ports[0],
-                                        iph->daddr, ports[1]);
+                                        iph->saddr, pptr[0],
+                                        iph->daddr, pptr[1]);
        } else {
                return ip_vs_conn_in_get(iph->protocol,
-                                        iph->daddr, ports[1],
-                                        iph->saddr, ports[0]);
+                                        iph->daddr, pptr[1],
+                                        iph->saddr, pptr[0]);
        }
 }
 
@@ -49,19 +50,20 @@ static struct ip_vs_conn *
 tcp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
                 const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
-       __u16 ports[2];
+       __u16 _ports[2], *pptr;
 
-       if (skb_copy_bits(skb, proto_off, ports, sizeof(ports)) < 0)
+       pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+       if (pptr == NULL)
                return NULL;
 
        if (likely(!inverse)) {
                return ip_vs_conn_out_get(iph->protocol,
-                                         iph->saddr, ports[0],
-                                         iph->daddr, ports[1]);
+                                         iph->saddr, pptr[0],
+                                         iph->daddr, pptr[1]);
        } else {
                return ip_vs_conn_out_get(iph->protocol,
-                                         iph->daddr, ports[1],
-                                         iph->saddr, ports[0]);
+                                         iph->daddr, pptr[1],
+                                         iph->saddr, pptr[0]);
        }
 }
 
@@ -72,16 +74,18 @@ tcp_conn_schedule(struct sk_buff *skb,
                  int *verdict, struct ip_vs_conn **cpp)
 {
        struct ip_vs_service *svc;
-       struct tcphdr tcph;
+       struct tcphdr _tcph, *th;
 
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) {
+       th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+                               sizeof(_tcph), &_tcph);
+       if (th == NULL) {
                *verdict = NF_DROP;
                return 0;
        }
 
-       if (tcph.syn &&
+       if (th->syn &&
            (svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol,
-                                    skb->nh.iph->daddr, tcph.dest))) {
+                                    skb->nh.iph->daddr, th->dest))) {
                if (ip_vs_todrop()) {
                        /*
                         * It seems that we are very loaded.
@@ -483,13 +487,15 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction,
                     const struct sk_buff *skb,
                     struct ip_vs_protocol *pp)
 {
-       struct tcphdr tcph;
+       struct tcphdr _tcph, *th;
 
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
+       th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+                               sizeof(_tcph), &_tcph);
+       if (th == NULL)
                return 0;
 
        spin_lock(&cp->lock);
-       set_tcp_state(pp, cp, direction, &tcph);
+       set_tcp_state(pp, cp, direction, th);
        spin_unlock(&cp->lock);
 
        return 1;
index 81501c9..443ec45 100644 (file)
@@ -26,19 +26,20 @@ udp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
                const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
        struct ip_vs_conn *cp;
-       __u16 ports[2];
+       __u16 _ports[2], *pptr;
 
-       if (skb_copy_bits(skb, proto_off, ports, sizeof(ports)) < 0)
+       pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+       if (pptr == NULL)
                return NULL;
 
        if (likely(!inverse)) {
                cp = ip_vs_conn_in_get(iph->protocol,
-                                      iph->saddr, ports[0],
-                                      iph->daddr, ports[1]);
+                                      iph->saddr, pptr[0],
+                                      iph->daddr, pptr[1]);
        } else {
                cp = ip_vs_conn_in_get(iph->protocol,
-                                      iph->daddr, ports[1],
-                                      iph->saddr, ports[0]);
+                                      iph->daddr, pptr[1],
+                                      iph->saddr, pptr[0]);
        }
 
        return cp;
@@ -50,19 +51,21 @@ udp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
                 const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
        struct ip_vs_conn *cp;
-       __u16 ports[2];
+       __u16 _ports[2], *pptr;
 
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0)
+       pptr = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+                                 sizeof(_ports), _ports);
+       if (pptr == NULL)
                return NULL;
 
        if (likely(!inverse)) {
                cp = ip_vs_conn_out_get(iph->protocol,
-                                       iph->saddr, ports[0],
-                                       iph->daddr, ports[1]);
+                                       iph->saddr, pptr[0],
+                                       iph->daddr, pptr[1]);
        } else {
                cp = ip_vs_conn_out_get(iph->protocol,
-                                       iph->daddr, ports[1],
-                                       iph->saddr, ports[0]);
+                                       iph->daddr, pptr[1],
+                                       iph->saddr, pptr[0]);
        }
 
        return cp;
@@ -74,15 +77,17 @@ udp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp,
                  int *verdict, struct ip_vs_conn **cpp)
 {
        struct ip_vs_service *svc;
-       struct udphdr udph;
+       struct udphdr _udph, *uh;
 
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0) {
+       uh = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+                               sizeof(_udph), &_udph);
+       if (uh == NULL) {
                *verdict = NF_DROP;
                return 0;
        }
 
        if ((svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol,
-                                    skb->nh.iph->daddr, udph.dest))) {
+                                    skb->nh.iph->daddr, uh->dest))) {
                if (ip_vs_todrop()) {
                        /*
                         * It seems that we are very loaded.
@@ -230,13 +235,14 @@ udp_dnat_handler(struct sk_buff **pskb,
 static int
 udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp)
 {
-       struct udphdr udph;
+       struct udphdr _udph, *uh;
        unsigned int udphoff = skb->nh.iph->ihl*4;
 
-       if (skb_copy_bits(skb, udphoff, &udph, sizeof(udph)) < 0)
+       uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph);
+       if (uh == NULL)
                return 0;
 
-       if (udph.check != 0) {
+       if (uh->check != 0) {
                switch (skb->ip_summed) {
                case CHECKSUM_NONE:
                        skb->csum = skb_checksum(skb, udphoff,
index b9c27d5..df70089 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
+#include <linux/moduleparam.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
@@ -27,16 +28,16 @@ MODULE_DESCRIPTION("ftp connection tracking helper");
 /* This is slow, but it's simple. --RR */
 static char ftp_buffer[65536];
 
-DECLARE_LOCK(ip_ftp_lock);
+static DECLARE_LOCK(ip_ftp_lock);
 struct module *ip_conntrack_ftp = THIS_MODULE;
 
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
 static int ports_c;
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 
 static int loose;
-MODULE_PARM(loose, "i");
+module_param(loose, int, 0600);
 
 #if 0
 #define DEBUGP printk
@@ -247,7 +248,8 @@ static int help(struct sk_buff *skb,
                enum ip_conntrack_info ctinfo)
 {
        unsigned int dataoff, datalen;
-       struct tcphdr tcph;
+       struct tcphdr _tcph, *th;
+       char *fb_ptr;
        u_int32_t old_seq_aft_nl;
        int old_seq_aft_nl_set, ret;
        u_int32_t array[6] = { 0 };
@@ -267,10 +269,12 @@ static int help(struct sk_buff *skb,
                return NF_ACCEPT;
        }
 
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) != 0)
+       th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+                               sizeof(_tcph), &_tcph);
+       if (th == NULL)
                return NF_ACCEPT;
 
-       dataoff = skb->nh.iph->ihl*4 + tcph.doff*4;
+       dataoff = skb->nh.iph->ihl*4 + th->doff*4;
        /* No data? */
        if (dataoff >= skb->len) {
                DEBUGP("ftp: skblen = %u\n", skb->len);
@@ -279,26 +283,28 @@ static int help(struct sk_buff *skb,
        datalen = skb->len - dataoff;
 
        LOCK_BH(&ip_ftp_lock);
-       skb_copy_bits(skb, dataoff, ftp_buffer, skb->len - dataoff);
+       fb_ptr = skb_header_pointer(skb, dataoff,
+                                   skb->len - dataoff, ftp_buffer);
+       BUG_ON(fb_ptr == NULL);
 
        old_seq_aft_nl_set = ct_ftp_info->seq_aft_nl_set[dir];
        old_seq_aft_nl = ct_ftp_info->seq_aft_nl[dir];
 
        DEBUGP("conntrack_ftp: datalen %u\n", datalen);
-       if (ftp_buffer[datalen - 1] == '\n') {
+       if (fb_ptr[datalen - 1] == '\n') {
                DEBUGP("conntrack_ftp: datalen %u ends in \\n\n", datalen);
                if (!old_seq_aft_nl_set
-                   || after(ntohl(tcph.seq) + datalen, old_seq_aft_nl)) {
+                   || after(ntohl(th->seq) + datalen, old_seq_aft_nl)) {
                        DEBUGP("conntrack_ftp: updating nl to %u\n",
-                              ntohl(tcph.seq) + datalen);
+                              ntohl(th->seq) + datalen);
                        ct_ftp_info->seq_aft_nl[dir] = 
-                                               ntohl(tcph.seq) + datalen;
+                                               ntohl(th->seq) + datalen;
                        ct_ftp_info->seq_aft_nl_set[dir] = 1;
                }
        }
 
        if(!old_seq_aft_nl_set ||
-                       (ntohl(tcph.seq) != old_seq_aft_nl)) {
+                       (ntohl(th->seq) != old_seq_aft_nl)) {
                DEBUGP("ip_conntrack_ftp_help: wrong seq pos %s(%u)\n",
                       old_seq_aft_nl_set ? "":"(UNSET) ", old_seq_aft_nl);
                ret = NF_ACCEPT;
@@ -315,7 +321,7 @@ static int help(struct sk_buff *skb,
        for (i = 0; i < ARRAY_SIZE(search); i++) {
                if (search[i].dir != dir) continue;
 
-               found = find_pattern(ftp_buffer, skb->len - dataoff,
+               found = find_pattern(fb_ptr, skb->len - dataoff,
                                     search[i].pattern,
                                     search[i].plen,
                                     search[i].skip,
@@ -333,7 +339,7 @@ static int help(struct sk_buff *skb,
                if (net_ratelimit())
                        printk("conntrack_ftp: partial %s %u+%u\n",
                               search[i].pattern,
-                              ntohl(tcph.seq), datalen);
+                              ntohl(th->seq), datalen);
                ret = NF_DROP;
                goto out;
        } else if (found == 0) { /* No match */
@@ -343,7 +349,7 @@ static int help(struct sk_buff *skb,
 
        DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
               (int)matchlen, data + matchoff,
-              matchlen, ntohl(tcph.seq) + matchoff);
+              matchlen, ntohl(th->seq) + matchoff);
 
        /* Allocate expectation which will be inserted */
        exp = ip_conntrack_expect_alloc();
@@ -357,7 +363,7 @@ static int help(struct sk_buff *skb,
        /* Update the ftp info */
        if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3])
            == ct->tuplehash[dir].tuple.src.ip) {
-               exp->seq = ntohl(tcph.seq) + matchoff;
+               exp->seq = ntohl(th->seq) + matchoff;
                exp_ftp_info->len = matchlen;
                exp_ftp_info->ftptype = search[i].ftptype;
                exp_ftp_info->port = array[4] << 8 | array[5];
@@ -420,10 +426,10 @@ static int __init init(void)
        int i, ret;
        char *tmpname;
 
-       if (ports[0] == 0)
-               ports[0] = FTP_PORT;
+       if (ports_c == 0)
+               ports[ports_c++] = FTP_PORT;
 
-       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+       for (i = 0; i < ports_c; i++) {
                ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
                ftp[i].tuple.dst.protonum = IPPROTO_TCP;
                ftp[i].mask.src.u.tcp.port = 0xFFFF;
@@ -449,13 +455,11 @@ static int __init init(void)
                        fini();
                        return ret;
                }
-               ports_c++;
        }
        return 0;
 }
 
 PROVIDES_CONNTRACK(ftp);
-EXPORT_SYMBOL(ip_ftp_lock);
 
 module_init(init);
 module_exit(fini);
index 32b5dae..d007bc9 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
+#include <linux/moduleparam.h>
 
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
@@ -40,21 +41,21 @@ static int max_dcc_channels = 8;
 static unsigned int dcc_timeout = 300;
 /* This is slow, but it's simple. --RR */
 static char irc_buffer[65536];
+static DECLARE_LOCK(irc_buffer_lock);
 
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
 MODULE_LICENSE("GPL");
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of IRC servers");
-MODULE_PARM(max_dcc_channels, "i");
+module_param(max_dcc_channels, int, 0400);
 MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
-MODULE_PARM(dcc_timeout, "i");
+module_param(dcc_timeout, int, 0400);
 MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
 
 static char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " };
 #define MINMATCHLEN    5
 
-DECLARE_LOCK(ip_irc_lock);
 struct module *ip_conntrack_irc = THIS_MODULE;
 
 #if 0
@@ -101,8 +102,8 @@ static int help(struct sk_buff *skb,
                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
        unsigned int dataoff;
-       struct tcphdr tcph;
-       char *data, *data_limit;
+       struct tcphdr _tcph, *th;
+       char *data, *data_limit, *ib_ptr;
        int dir = CTINFO2DIR(ctinfo);
        struct ip_conntrack_expect *exp;
        struct ip_ct_irc_expect *exp_irc_info = NULL;
@@ -126,19 +127,23 @@ static int help(struct sk_buff *skb,
        }
 
        /* Not a full tcp header? */
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) != 0)
+       th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+                               sizeof(_tcph), &_tcph);
+       if (th == NULL)
                return NF_ACCEPT;
 
        /* No data? */
-       dataoff = skb->nh.iph->ihl*4 + tcph.doff*4;
+       dataoff = skb->nh.iph->ihl*4 + th->doff*4;
        if (dataoff >= skb->len)
                return NF_ACCEPT;
 
-       LOCK_BH(&ip_irc_lock);
-       skb_copy_bits(skb, dataoff, irc_buffer, skb->len - dataoff);
+       LOCK_BH(&irc_buffer_lock);
+       ib_ptr = skb_header_pointer(skb, dataoff,
+                                   skb->len - dataoff, irc_buffer);
+       BUG_ON(ib_ptr == NULL);
 
-       data = irc_buffer;
-       data_limit = irc_buffer + skb->len - dataoff;
+       data = ib_ptr;
+       data_limit = ib_ptr + skb->len - dataoff;
 
        /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
         * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
@@ -152,8 +157,8 @@ static int help(struct sk_buff *skb,
                /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
 
                DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
-                       NIPQUAD(iph->saddr), ntohs(tcph.source),
-                       NIPQUAD(iph->daddr), ntohs(tcph.dest));
+                       NIPQUAD(iph->saddr), ntohs(th->source),
+                       NIPQUAD(iph->daddr), ntohs(th->dest));
 
                for (i = 0; i < ARRAY_SIZE(dccprotos); i++) {
                        if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) {
@@ -197,8 +202,8 @@ static int help(struct sk_buff *skb,
 
                        /* save position of address in dcc string,
                         * necessary for NAT */
-                       DEBUGP("tcph->seq = %u\n", tcph.seq);
-                       exp->seq = ntohl(tcph.seq) + (addr_beg_p - irc_buffer);
+                       DEBUGP("tcph->seq = %u\n", th->seq);
+                       exp->seq = ntohl(th->seq) + (addr_beg_p - ib_ptr);
                        exp_irc_info->len = (addr_end_p - addr_beg_p);
                        exp_irc_info->port = dcc_port;
                        DEBUGP("wrote info seq=%u (ofs=%u), len=%d\n",
@@ -227,7 +232,7 @@ static int help(struct sk_buff *skb,
        } /* while data < ... */
 
  out:
-       UNLOCK_BH(&ip_irc_lock);
+       UNLOCK_BH(&irc_buffer_lock);
        return NF_ACCEPT;
 }
 
@@ -252,10 +257,10 @@ static int __init init(void)
        }
        
        /* If no port given, default to standard irc port */
-       if (ports[0] == 0)
-               ports[0] = IRC_PORT;
+       if (ports_c == 0)
+               ports[ports_c++] = IRC_PORT;
 
-       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+       for (i = 0; i < ports_c; i++) {
                hlpr = &irc_helpers[i];
                hlpr->tuple.src.u.tcp.port = htons(ports[i]);
                hlpr->tuple.dst.protonum = IPPROTO_TCP;
@@ -284,7 +289,6 @@ static int __init init(void)
                        fini();
                        return -EBUSY;
                }
-               ports_c++;
        }
        return 0;
 }
@@ -302,7 +306,6 @@ static void fini(void)
 }
 
 PROVIDES_CONNTRACK(irc);
-EXPORT_SYMBOL(ip_irc_lock);
 
 module_init(init);
 module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
new file mode 100644 (file)
index 0000000..0cefc6f
--- /dev/null
@@ -0,0 +1,656 @@
+/*
+ * Connection tracking protocol helper module for SCTP.
+ * 
+ * SCTP is defined in RFC 2960. References to various sections in this code 
+ * are to this RFC.
+ * 
+ * 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.
+ */
+
+/*
+ * Added support for proc manipulation of timeouts.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/netfilter.h>
+#include <linux/module.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/sctp.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
+#include <linux/netfilter_ipv4/lockhelp.h>
+
+#if 0
+#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/* Protects conntrack->proto.sctp */
+static DECLARE_RWLOCK(sctp_lock);
+
+/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
+   closely.  They're more complex. --RR 
+
+   And so for me for SCTP :D -Kiran */
+
+static const char *sctp_conntrack_names[] = {
+       "NONE",
+       "CLOSED",
+       "COOKIE_WAIT",
+       "COOKIE_ECHOED",
+       "ESTABLISHED",
+       "SHUTDOWN_SENT",
+       "SHUTDOWN_RECD",
+       "SHUTDOWN_ACK_SENT",
+};
+
+#define SECS  * HZ
+#define MINS  * 60 SECS
+#define HOURS * 60 MINS
+#define DAYS  * 24 HOURS
+
+unsigned long ip_ct_sctp_timeout_closed            =  10 SECS;
+unsigned long ip_ct_sctp_timeout_cookie_wait       =   3 SECS;
+unsigned long ip_ct_sctp_timeout_cookie_echoed     =   3 SECS;
+unsigned long ip_ct_sctp_timeout_established       =   5 DAYS;
+unsigned long ip_ct_sctp_timeout_shutdown_sent     = 300 SECS / 1000;
+unsigned long ip_ct_sctp_timeout_shutdown_recd     = 300 SECS / 1000;
+unsigned long ip_ct_sctp_timeout_shutdown_ack_sent =   3 SECS;
+
+static unsigned long * sctp_timeouts[]
+= { NULL,                                  /* SCTP_CONNTRACK_NONE  */
+    &ip_ct_sctp_timeout_closed,                   /* SCTP_CONNTRACK_CLOSED */
+    &ip_ct_sctp_timeout_cookie_wait,       /* SCTP_CONNTRACK_COOKIE_WAIT */
+    &ip_ct_sctp_timeout_cookie_echoed,     /* SCTP_CONNTRACK_COOKIE_ECHOED */
+    &ip_ct_sctp_timeout_established,       /* SCTP_CONNTRACK_ESTABLISHED */
+    &ip_ct_sctp_timeout_shutdown_sent,     /* SCTP_CONNTRACK_SHUTDOWN_SENT */
+    &ip_ct_sctp_timeout_shutdown_recd,     /* SCTP_CONNTRACK_SHUTDOWN_RECD */
+    &ip_ct_sctp_timeout_shutdown_ack_sent  /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
+ };
+
+#define sNO SCTP_CONNTRACK_NONE
+#define        sCL SCTP_CONNTRACK_CLOSED
+#define        sCW SCTP_CONNTRACK_COOKIE_WAIT
+#define        sCE SCTP_CONNTRACK_COOKIE_ECHOED
+#define        sES SCTP_CONNTRACK_ESTABLISHED
+#define        sSS SCTP_CONNTRACK_SHUTDOWN_SENT
+#define        sSR SCTP_CONNTRACK_SHUTDOWN_RECD
+#define        sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
+#define        sIV SCTP_CONNTRACK_MAX
+
+/* 
+       These are the descriptions of the states:
+
+NOTE: These state names are tantalizingly similar to the states of an 
+SCTP endpoint. But the interpretation of the states is a little different,
+considering that these are the states of the connection and not of an end 
+point. Please note the subtleties. -Kiran
+
+NONE              - Nothing so far.
+COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also 
+                    an INIT_ACK chunk in the reply direction.
+COOKIE ECHOED     - We have seen a COOKIE_ECHO chunk in the original direction.
+ESTABLISHED       - We have seen a COOKIE_ACK in the reply direction.
+SHUTDOWN_SENT     - We have seen a SHUTDOWN chunk in the original direction.
+SHUTDOWN_RECD     - We have seen a SHUTDOWN chunk in the reply directoin.
+SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
+                    to that of the SHUTDOWN chunk.
+CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of 
+                    the SHUTDOWN chunk. Connection is closed.
+*/
+
+/* TODO
+ - I have assumed that the first INIT is in the original direction. 
+ This messes things when an INIT comes in the reply direction in CLOSED
+ state.
+ - Check the error type in the reply dir before transitioning from 
+cookie echoed to closed.
+ - Sec 5.2.4 of RFC 2960
+ - Multi Homing support.
+*/
+
+/* SCTP conntrack state transitions */
+static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
+       {
+/*     ORIGINAL        */
+/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
+/* init         */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
+/* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
+/* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
+/* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
+/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
+/* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
+/* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
+/* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
+/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
+       },
+       {
+/*     REPLY   */
+/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
+/* init         */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
+/* init_ack     */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
+/* abort        */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
+/* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
+/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
+/* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
+/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
+/* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
+/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
+       }
+};
+
+static int sctp_pkt_to_tuple(const struct sk_buff *skb,
+                            unsigned int dataoff,
+                            struct ip_conntrack_tuple *tuple)
+{
+       sctp_sctphdr_t _hdr, *hp;
+
+       DEBUGP(__FUNCTION__);
+       DEBUGP("\n");
+
+       /* Actually only need first 8 bytes. */
+       hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
+       if (hp == NULL)
+               return 0;
+
+       tuple->src.u.sctp.port = hp->source;
+       tuple->dst.u.sctp.port = hp->dest;
+       return 1;
+}
+
+static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
+                            const struct ip_conntrack_tuple *orig)
+{
+       DEBUGP(__FUNCTION__);
+       DEBUGP("\n");
+
+       tuple->src.u.sctp.port = orig->dst.u.sctp.port;
+       tuple->dst.u.sctp.port = orig->src.u.sctp.port;
+       return 1;
+}
+
+/* Print out the per-protocol part of the tuple. */
+static int sctp_print_tuple(struct seq_file *s,
+                           const struct ip_conntrack_tuple *tuple)
+{
+       DEBUGP(__FUNCTION__);
+       DEBUGP("\n");
+
+       return seq_printf(s, "sport=%hu dport=%hu ",
+                         ntohs(tuple->src.u.sctp.port),
+                         ntohs(tuple->dst.u.sctp.port));
+}
+
+/* Print out the private part of the conntrack. */
+static int sctp_print_conntrack(struct seq_file *s,
+                               const struct ip_conntrack *conntrack)
+{
+       enum sctp_conntrack state;
+
+       DEBUGP(__FUNCTION__);
+       DEBUGP("\n");
+
+       READ_LOCK(&sctp_lock);
+       state = conntrack->proto.sctp.state;
+       READ_UNLOCK(&sctp_lock);
+
+       return seq_printf(s, "%s ", sctp_conntrack_names[state]);
+}
+
+#define for_each_sctp_chunk(skb, sch, _sch, offset, count)             \
+for (offset = skb->nh.iph->ihl * 4 + sizeof(sctp_sctphdr_t), count = 0;        \
+       offset < skb->len &&                                            \
+       (sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch));   \
+       offset += (htons(sch->length) + 3) & ~3, count++)
+
+/* Some validity checks to make sure the chunks are fine */
+static int do_basic_checks(struct ip_conntrack *conntrack,
+                          const struct sk_buff *skb,
+                          char *map)
+{
+       u_int32_t offset, count;
+       sctp_chunkhdr_t _sch, *sch;
+       int flag;
+
+       DEBUGP(__FUNCTION__);
+       DEBUGP("\n");
+
+       flag = 0;
+
+       for_each_sctp_chunk (skb, sch, _sch, offset, count) {
+               DEBUGP("Chunk Num: %d  Type: %d\n", count, sch->type);
+
+               if (sch->type == SCTP_CID_INIT 
+                       || sch->type == SCTP_CID_INIT_ACK
+                       || sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
+                       flag = 1;
+               }
+
+               /* Cookie Ack/Echo chunks not the first OR 
+                  Init / Init Ack / Shutdown compl chunks not the only chunks */
+               if ((sch->type == SCTP_CID_COOKIE_ACK 
+                       || sch->type == SCTP_CID_COOKIE_ECHO
+                       || flag)
+                    && count !=0 ) {
+                       DEBUGP("Basic checks failed\n");
+                       return 1;
+               }
+
+               if (map) {
+                       set_bit(sch->type, (void *)map);
+               }
+       }
+
+       DEBUGP("Basic checks passed\n");
+       return 0;
+}
+
+static int new_state(enum ip_conntrack_dir dir,
+                    enum sctp_conntrack cur_state,
+                    int chunk_type)
+{
+       int i;
+
+       DEBUGP(__FUNCTION__);
+       DEBUGP("\n");
+
+       DEBUGP("Chunk type: %d\n", chunk_type);
+
+       switch (chunk_type) {
+               case SCTP_CID_INIT: 
+                       DEBUGP("SCTP_CID_INIT\n");
+                       i = 0; break;
+               case SCTP_CID_INIT_ACK: 
+                       DEBUGP("SCTP_CID_INIT_ACK\n");
+                       i = 1; break;
+               case SCTP_CID_ABORT: 
+                       DEBUGP("SCTP_CID_ABORT\n");
+                       i = 2; break;
+               case SCTP_CID_SHUTDOWN: 
+                       DEBUGP("SCTP_CID_SHUTDOWN\n");
+                       i = 3; break;
+               case SCTP_CID_SHUTDOWN_ACK: 
+                       DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
+                       i = 4; break;
+               case SCTP_CID_ERROR: 
+                       DEBUGP("SCTP_CID_ERROR\n");
+                       i = 5; break;
+               case SCTP_CID_COOKIE_ECHO: 
+                       DEBUGP("SCTP_CID_COOKIE_ECHO\n");
+                       i = 6; break;
+               case SCTP_CID_COOKIE_ACK: 
+                       DEBUGP("SCTP_CID_COOKIE_ACK\n");
+                       i = 7; break;
+               case SCTP_CID_SHUTDOWN_COMPLETE: 
+                       DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
+                       i = 8; break;
+               default:
+                       /* Other chunks like DATA, SACK, HEARTBEAT and
+                       its ACK do not cause a change in state */
+                       DEBUGP("Unknown chunk type, Will stay in %s\n", 
+                                               sctp_conntrack_names[cur_state]);
+                       return cur_state;
+       }
+
+       DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n", 
+                       dir, sctp_conntrack_names[cur_state], chunk_type,
+                       sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
+
+       return sctp_conntracks[dir][i][cur_state];
+}
+
+/* Returns verdict for packet, or -1 for invalid. */
+static int sctp_packet(struct ip_conntrack *conntrack,
+                      const struct sk_buff *skb,
+                      enum ip_conntrack_info ctinfo)
+{
+       enum sctp_conntrack newconntrack, oldsctpstate;
+       struct iphdr *iph = skb->nh.iph;
+       sctp_sctphdr_t _sctph, *sh;
+       sctp_chunkhdr_t _sch, *sch;
+       u_int32_t offset, count;
+       char map[256 / sizeof (char)] = {0};
+
+       DEBUGP(__FUNCTION__);
+       DEBUGP("\n");
+
+       sh = skb_header_pointer(skb, iph->ihl * 4, sizeof(_sctph), &_sctph);
+       if (sh == NULL)
+               return -1;
+
+       if (do_basic_checks(conntrack, skb, map) != 0)
+               return -1;
+
+       /* Check the verification tag (Sec 8.5) */
+       if (!test_bit(SCTP_CID_INIT, (void *)map)
+               && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
+               && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
+               && !test_bit(SCTP_CID_ABORT, (void *)map)
+               && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
+               && (sh->vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
+               DEBUGP("Verification tag check failed\n");
+               return -1;
+       }
+
+       oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
+       for_each_sctp_chunk (skb, sch, _sch, offset, count) {
+               WRITE_LOCK(&sctp_lock);
+
+               /* Special cases of Verification tag check (Sec 8.5.1) */
+               if (sch->type == SCTP_CID_INIT) {
+                       /* Sec 8.5.1 (A) */
+                       if (sh->vtag != 0) {
+                               WRITE_UNLOCK(&sctp_lock);
+                               return -1;
+                       }
+               } else if (sch->type == SCTP_CID_ABORT) {
+                       /* Sec 8.5.1 (B) */
+                       if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
+                               && !(sh->vtag == conntrack->proto.sctp.vtag
+                                                       [1 - CTINFO2DIR(ctinfo)])) {
+                               WRITE_UNLOCK(&sctp_lock);
+                               return -1;
+                       }
+               } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
+                       /* Sec 8.5.1 (C) */
+                       if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
+                               && !(sh->vtag == conntrack->proto.sctp.vtag
+                                                       [1 - CTINFO2DIR(ctinfo)] 
+                                       && (sch->flags & 1))) {
+                               WRITE_UNLOCK(&sctp_lock);
+                               return -1;
+                       }
+               } else if (sch->type == SCTP_CID_COOKIE_ECHO) {
+                       /* Sec 8.5.1 (D) */
+                       if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
+                               WRITE_UNLOCK(&sctp_lock);
+                               return -1;
+                       }
+               }
+
+               oldsctpstate = conntrack->proto.sctp.state;
+               newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch->type);
+
+               /* Invalid */
+               if (newconntrack == SCTP_CONNTRACK_MAX) {
+                       DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
+                              CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
+                       WRITE_UNLOCK(&sctp_lock);
+                       return -1;
+               }
+
+               /* If it is an INIT or an INIT ACK note down the vtag */
+               if (sch->type == SCTP_CID_INIT 
+                       || sch->type == SCTP_CID_INIT_ACK) {
+                       sctp_inithdr_t _inithdr, *ih;
+
+                       ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
+                                               sizeof(_inithdr), &_inithdr);
+                       if (ih == NULL) {
+                                       WRITE_UNLOCK(&sctp_lock);
+                                       return -1;
+                       }
+                       DEBUGP("Setting vtag %x for dir %d\n", 
+                                       ih->init_tag, CTINFO2DIR(ctinfo));
+                       conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = ih->init_tag;
+               }
+
+               conntrack->proto.sctp.state = newconntrack;
+               WRITE_UNLOCK(&sctp_lock);
+       }
+
+       ip_ct_refresh_acct(conntrack, ctinfo, skb, *sctp_timeouts[newconntrack]);
+
+       if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
+               && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
+               && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
+               DEBUGP("Setting assured bit\n");
+               set_bit(IPS_ASSURED_BIT, &conntrack->status);
+       }
+
+       return NF_ACCEPT;
+}
+
+/* Called when a new connection for this protocol found. */
+static int sctp_new(struct ip_conntrack *conntrack, 
+                   const struct sk_buff *skb)
+{
+       enum sctp_conntrack newconntrack;
+       struct iphdr *iph = skb->nh.iph;
+       sctp_sctphdr_t _sctph, *sh;
+       sctp_chunkhdr_t _sch, *sch;
+       u_int32_t offset, count;
+       char map[256 / sizeof (char)] = {0};
+
+       DEBUGP(__FUNCTION__);
+       DEBUGP("\n");
+
+       sh = skb_header_pointer(skb, iph->ihl * 4, sizeof(_sctph), &_sctph);
+       if (sh == NULL)
+               return 0;
+
+       if (do_basic_checks(conntrack, skb, map) != 0)
+               return 0;
+
+       /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
+       if ((test_bit (SCTP_CID_ABORT, (void *)map))
+               || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
+               || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
+               return 0;
+       }
+
+       newconntrack = SCTP_CONNTRACK_MAX;
+       for_each_sctp_chunk (skb, sch, _sch, offset, count) {
+               /* Don't need lock here: this conntrack not in circulation yet */
+               newconntrack = new_state (IP_CT_DIR_ORIGINAL, 
+                                               SCTP_CONNTRACK_NONE, sch->type);
+
+               /* Invalid: delete conntrack */
+               if (newconntrack == SCTP_CONNTRACK_MAX) {
+                       DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
+                       return 0;
+               }
+
+               /* Copy the vtag into the state info */
+               if (sch->type == SCTP_CID_INIT) {
+                       if (sh->vtag == 0) {
+                               sctp_inithdr_t _inithdr, *ih;
+
+                               ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
+                                                       sizeof(_inithdr), &_inithdr);
+                               if (ih == NULL)
+                                       return 0;
+
+                               DEBUGP("Setting vtag %x for new conn\n", 
+                                       ih->init_tag);
+
+                               conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = 
+                                                               ih->init_tag;
+                       } else {
+                               /* Sec 8.5.1 (A) */
+                               return 0;
+                       }
+               }
+               /* If it is a shutdown ack OOTB packet, we expect a return
+                  shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
+               else {
+                       DEBUGP("Setting vtag %x for new conn OOTB\n", 
+                               sh->vtag);
+                       conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
+               }
+
+               conntrack->proto.sctp.state = newconntrack;
+       }
+
+       return 1;
+}
+
+static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
+                               const struct sk_buff *skb)
+{
+       /* To be implemented */
+       return 0;
+}
+
+struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { 
+       .proto           = IPPROTO_SCTP, 
+       .name            = "sctp",
+       .pkt_to_tuple    = sctp_pkt_to_tuple, 
+       .invert_tuple    = sctp_invert_tuple, 
+       .print_tuple     = sctp_print_tuple, 
+       .print_conntrack = sctp_print_conntrack,
+       .packet          = sctp_packet, 
+       .new             = sctp_new, 
+       .destroy         = NULL, 
+       .exp_matches_pkt = sctp_exp_matches_pkt, 
+       .me              = THIS_MODULE 
+};
+
+#ifdef CONFIG_SYSCTL
+static ctl_table ip_ct_sysctl_table[] = {
+       {
+               .ctl_name       = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED,
+               .procname       = "ip_conntrack_sctp_timeout_closed",
+               .data           = &ip_ct_sctp_timeout_closed,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+       },
+       {
+               .ctl_name       = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT,
+               .procname       = "ip_conntrack_sctp_timeout_cookie_wait",
+               .data           = &ip_ct_sctp_timeout_cookie_wait,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+       },
+       {
+               .ctl_name       = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED,
+               .procname       = "ip_conntrack_sctp_timeout_cookie_echoed",
+               .data           = &ip_ct_sctp_timeout_cookie_echoed,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+       },
+       {
+               .ctl_name       = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED,
+               .procname       = "ip_conntrack_sctp_timeout_established",
+               .data           = &ip_ct_sctp_timeout_established,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+       },
+       {
+               .ctl_name       = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT,
+               .procname       = "ip_conntrack_sctp_timeout_shutdown_sent",
+               .data           = &ip_ct_sctp_timeout_shutdown_sent,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+       },
+       {
+               .ctl_name       = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD,
+               .procname       = "ip_conntrack_sctp_timeout_shutdown_recd",
+               .data           = &ip_ct_sctp_timeout_shutdown_recd,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+       },
+       {
+               .ctl_name       = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT,
+               .procname       = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
+               .data           = &ip_ct_sctp_timeout_shutdown_ack_sent,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+       },
+       { .ctl_name = 0 }
+};
+
+static ctl_table ip_ct_netfilter_table[] = {
+       {
+               .ctl_name       = NET_IPV4_NETFILTER,
+               .procname       = "netfilter",
+               .mode           = 0555,
+               .child          = ip_ct_sysctl_table,
+       },
+       { .ctl_name = 0 }
+};
+
+static ctl_table ip_ct_ipv4_table[] = {
+       {
+               .ctl_name       = NET_IPV4,
+               .procname       = "ipv4",
+               .mode           = 0555,
+               .child          = ip_ct_netfilter_table,
+       },
+       { .ctl_name = 0 }
+};
+
+static ctl_table ip_ct_net_table[] = {
+       {
+               .ctl_name       = CTL_NET,
+               .procname       = "net",
+               .mode           = 0555, 
+               .child          = ip_ct_ipv4_table,
+       },
+       { .ctl_name = 0 }
+};
+
+static struct ctl_table_header *ip_ct_sysctl_header;
+#endif
+
+int __init init(void)
+{
+       int ret;
+
+       ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
+       if (ret) {
+               printk("ip_conntrack_proto_sctp: protocol register failed\n");
+               goto out;
+       }
+
+#ifdef CONFIG_SYSCTL
+       ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
+       if (ip_ct_sysctl_header == NULL) {
+               printk("ip_conntrack_proto_sctp: can't register to sysctl.\n");
+               goto cleanup;
+       }
+#endif
+
+       return ret;
+
+#ifdef CONFIG_SYSCTL
+ cleanup:
+       ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
+#endif
+ out:
+       DEBUGP("SCTP conntrack module loading %s\n", 
+                                       ret ? "failed": "succeeded");
+       return ret;
+}
+
+void __exit fini(void)
+{
+       ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
+#ifdef CONFIG_SYSCTL
+       unregister_sysctl_table(ip_ct_sysctl_header);
+#endif
+       DEBUGP("SCTP conntrack module unloaded\n");
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kiran Kumar Immidi");
+MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
index ddee737..d132a3c 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
+#include <linux/moduleparam.h>
 
 MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
 MODULE_DESCRIPTION("tftp connection tracking helper");
@@ -27,7 +28,7 @@ MODULE_LICENSE("GPL");
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
 static int ports_c;
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of tftp servers");
 
 #if 0
@@ -41,14 +42,16 @@ static int tftp_help(struct sk_buff *skb,
                     struct ip_conntrack *ct,
                     enum ip_conntrack_info ctinfo)
 {
-       struct tftphdr tftph;
+       struct tftphdr _tftph, *tfh;
        struct ip_conntrack_expect *exp;
 
-       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4 + sizeof(struct udphdr),
-                         &tftph, sizeof(tftph)) != 0)
+       tfh = skb_header_pointer(skb,
+                                skb->nh.iph->ihl * 4 + sizeof(struct udphdr),
+                                sizeof(_tftph), &_tftph);
+       if (tfh == NULL)
                return NF_ACCEPT;
 
-       switch (ntohs(tftph.opcode)) {
+       switch (ntohs(tfh->opcode)) {
        /* RRQ and WRQ works the same way */
        case TFTP_OPCODE_READ:
        case TFTP_OPCODE_WRITE:
@@ -104,10 +107,10 @@ static int __init init(void)
        int i, ret;
        char *tmpname;
 
-       if (!ports[0])
-               ports[0]=TFTP_PORT;
+       if (ports_c == 0)
+               ports[ports_c++] = TFTP_PORT;
 
-       for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
+       for (i = 0; i < ports_c; i++) {
                /* Create helper structure */
                memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
 
@@ -137,7 +140,6 @@ static int __init init(void)
                        fini();
                        return(ret);
                }
-               ports_c++;
        }
        return(0);
 }
index 946ca05..be00284 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <linux/moduleparam.h>
 #include <net/tcp.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
@@ -33,9 +34,7 @@ MODULE_DESCRIPTION("ftp NAT helper");
 static int ports[MAX_PORTS];
 static int ports_c;
 
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
-
-DECLARE_LOCK_EXTERN(ip_ftp_lock);
+module_param_array(ports, int, ports_c, 0400);
 
 /* FIXME: Time out? --RR */
 
@@ -59,8 +58,6 @@ ftp_nat_expected(struct sk_buff **pskb,
        DEBUGP("nat_expected: We have a connection!\n");
        exp_ftp_info = &ct->master->help.exp_ftp_info;
 
-       LOCK_BH(&ip_ftp_lock);
-
        if (exp_ftp_info->ftptype == IP_CT_FTP_PORT
            || exp_ftp_info->ftptype == IP_CT_FTP_EPRT) {
                /* PORT command: make connection go to the client. */
@@ -75,7 +72,6 @@ ftp_nat_expected(struct sk_buff **pskb,
                DEBUGP("nat_expected: PASV cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
                       NIPQUAD(newsrcip), NIPQUAD(newdstip));
        }
-       UNLOCK_BH(&ip_ftp_lock);
 
        if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
                newip = newsrcip;
@@ -111,8 +107,6 @@ mangle_rfc959_packet(struct sk_buff **pskb,
 {
        char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")];
 
-       MUST_BE_LOCKED(&ip_ftp_lock);
-
        sprintf(buffer, "%u,%u,%u,%u,%u,%u",
                NIPQUAD(newip), port>>8, port&0xFF);
 
@@ -134,8 +128,6 @@ mangle_eprt_packet(struct sk_buff **pskb,
 {
        char buffer[sizeof("|1|255.255.255.255|65535|")];
 
-       MUST_BE_LOCKED(&ip_ftp_lock);
-
        sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port);
 
        DEBUGP("calling ip_nat_mangle_tcp_packet\n");
@@ -156,8 +148,6 @@ mangle_epsv_packet(struct sk_buff **pskb,
 {
        char buffer[sizeof("|||65535|")];
 
-       MUST_BE_LOCKED(&ip_ftp_lock);
-
        sprintf(buffer, "|||%u|", port);
 
        DEBUGP("calling ip_nat_mangle_tcp_packet\n");
@@ -177,7 +167,7 @@ static int (*mangle[])(struct sk_buff **, u_int32_t, u_int16_t,
     [IP_CT_FTP_EPSV] = mangle_epsv_packet
 };
 
-static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info,
+static int ftp_data_fixup(const struct ip_ct_ftp_expect *exp_ftp_info,
                          struct ip_conntrack *ct,
                          struct sk_buff **pskb,
                          enum ip_conntrack_info ctinfo,
@@ -189,15 +179,14 @@ static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info,
        u_int16_t port;
        struct ip_conntrack_tuple newtuple;
 
-       MUST_BE_LOCKED(&ip_ftp_lock);
        DEBUGP("FTP_NAT: seq %u + %u in %u\n",
-              expect->seq, ct_ftp_info->len,
+              expect->seq, exp_ftp_info->len,
               ntohl(tcph->seq));
 
        /* Change address inside packet to match way we're mapping
           this connection. */
-       if (ct_ftp_info->ftptype == IP_CT_FTP_PASV
-           || ct_ftp_info->ftptype == IP_CT_FTP_EPSV) {
+       if (exp_ftp_info->ftptype == IP_CT_FTP_PASV
+           || exp_ftp_info->ftptype == IP_CT_FTP_EPSV) {
                /* PASV/EPSV response: must be where client thinks server
                   is */
                newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
@@ -219,7 +208,7 @@ static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info,
        newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
 
        /* Try to get same port: if not, try to change it. */
-       for (port = ct_ftp_info->port; port != 0; port++) {
+       for (port = exp_ftp_info->port; port != 0; port++) {
                newtuple.dst.u.tcp.port = htons(port);
 
                if (ip_conntrack_change_expect(expect, &newtuple) == 0)
@@ -228,9 +217,9 @@ static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info,
        if (port == 0)
                return 0;
 
-       if (!mangle[ct_ftp_info->ftptype](pskb, newip, port,
+       if (!mangle[exp_ftp_info->ftptype](pskb, newip, port,
                                          expect->seq - ntohl(tcph->seq),
-                                         ct_ftp_info->len, ct, ctinfo))
+                                         exp_ftp_info->len, ct, ctinfo))
                return 0;
 
        return 1;
@@ -247,12 +236,12 @@ static unsigned int help(struct ip_conntrack *ct,
        struct tcphdr *tcph = (void *)iph + iph->ihl*4;
        unsigned int datalen;
        int dir;
-       struct ip_ct_ftp_expect *ct_ftp_info;
+       struct ip_ct_ftp_expect *exp_ftp_info;
 
        if (!exp)
                DEBUGP("ip_nat_ftp: no exp!!");
 
-       ct_ftp_info = &exp->help.exp_ftp_info;
+       exp_ftp_info = &exp->help.exp_ftp_info;
 
        /* Only mangle things once: original direction in POST_ROUTING
           and reply direction on PRE_ROUTING. */
@@ -268,29 +257,23 @@ static unsigned int help(struct ip_conntrack *ct,
        }
 
        datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-       LOCK_BH(&ip_ftp_lock);
        /* If it's in the right range... */
-       if (between(exp->seq + ct_ftp_info->len,
+       if (between(exp->seq + exp_ftp_info->len,
                    ntohl(tcph->seq),
                    ntohl(tcph->seq) + datalen)) {
-               if (!ftp_data_fixup(ct_ftp_info, ct, pskb, ctinfo, exp)) {
-                       UNLOCK_BH(&ip_ftp_lock);
+               if (!ftp_data_fixup(exp_ftp_info, ct, pskb, ctinfo, exp))
                        return NF_DROP;
-               }
        } else {
                /* Half a match?  This means a partial retransmisison.
                   It's a cracker being funky. */
                if (net_ratelimit()) {
                        printk("FTP_NAT: partial packet %u/%u in %u/%u\n",
-                              exp->seq, ct_ftp_info->len,
+                              exp->seq, exp_ftp_info->len,
                               ntohl(tcph->seq),
                               ntohl(tcph->seq) + datalen);
                }
-               UNLOCK_BH(&ip_ftp_lock);
                return NF_DROP;
        }
-       UNLOCK_BH(&ip_ftp_lock);
-
        return NF_ACCEPT;
 }
 
@@ -313,10 +296,10 @@ static int __init init(void)
        int i, ret = 0;
        char *tmpname;
 
-       if (ports[0] == 0)
-               ports[0] = FTP_PORT;
+       if (ports_c == 0)
+               ports[ports_c++] = FTP_PORT;
 
-       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+       for (i = 0; i < ports_c; i++) {
                ftp[i].tuple.dst.protonum = IPPROTO_TCP;
                ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
                ftp[i].mask.dst.protonum = 0xFFFF;
@@ -343,7 +326,6 @@ static int __init init(void)
                        fini();
                        return ret;
                }
-               ports_c++;
        }
 
        return ret;
index a49c722..d7ee32f 100644 (file)
@@ -47,6 +47,7 @@
 #define DUMP_OFFSET(x)
 #endif
 
+static LIST_HEAD(helpers);
 DECLARE_LOCK(ip_nat_seqofs_lock);
 
 /* Setup TCP sequence correction given this change at this sequence */
@@ -72,7 +73,7 @@ adjust_tcp_sequence(u32 seq,
 
        LOCK_BH(&ip_nat_seqofs_lock);
 
-       /* SYN adjust. If it's uninitialized, of this is after last
+       /* SYN adjust. If it's uninitialized, or this is after last
         * correction, record it: we don't handle more than one
         * adjustment in the window, but do deal with common case of a
         * retransmit */
@@ -346,7 +347,7 @@ ip_nat_sack_adjust(struct sk_buff **pskb,
        return 1;
 }
 
-/* TCP sequence number adjustment.  Returns true or false.  */
+/* TCP sequence number adjustment.  Returns 1 on success, 0 on failure */
 int
 ip_nat_seq_adjust(struct sk_buff **pskb, 
                  struct ip_conntrack *ct, 
@@ -395,7 +396,12 @@ ip_nat_seq_adjust(struct sk_buff **pskb,
        tcph->seq = newseq;
        tcph->ack_seq = newack;
 
-       return ip_nat_sack_adjust(pskb, tcph, ct, ctinfo);
+       if (!ip_nat_sack_adjust(pskb, tcph, ct, ctinfo))
+               return 0;
+
+       ip_conntrack_tcp_update(*pskb, ct, dir);
+
+       return 1;
 }
 
 static inline int
@@ -419,6 +425,24 @@ int ip_nat_helper_register(struct ip_nat_helper *me)
        return ret;
 }
 
+struct ip_nat_helper *
+__ip_nat_find_helper(const struct ip_conntrack_tuple *tuple)
+{
+       return LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, tuple);
+}
+
+struct ip_nat_helper *
+ip_nat_find_helper(const struct ip_conntrack_tuple *tuple)
+{
+       struct ip_nat_helper *h;
+
+       READ_LOCK(&ip_nat_lock);
+       h = __ip_nat_find_helper(tuple);
+       READ_UNLOCK(&ip_nat_lock);
+
+       return h;
+}
+
 static int
 kill_helper(const struct ip_conntrack *i, void *helper)
 {
index dc778dd..5eb60a2 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/moduleparam.h>
 
 #if 0
 #define DEBUGP printk
@@ -41,12 +42,9 @@ static int ports_c;
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
 MODULE_DESCRIPTION("IRC (DCC) NAT helper");
 MODULE_LICENSE("GPL");
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of IRC servers");
 
-/* protects irc part of conntracks */
-DECLARE_LOCK_EXTERN(ip_irc_lock);
-
 /* FIXME: Time out? --RR */
 
 static unsigned int
@@ -87,7 +85,7 @@ irc_nat_expected(struct sk_buff **pskb,
        return ip_nat_setup_info(ct, &mr, hooknum);
 }
 
-static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
+static int irc_data_fixup(const struct ip_ct_irc_expect *exp_irc_info,
                          struct ip_conntrack *ct,
                          struct sk_buff **pskb,
                          enum ip_conntrack_info ctinfo,
@@ -102,23 +100,16 @@ static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
        /* "4294967296 65635 " */
        char buffer[18];
 
-       MUST_BE_LOCKED(&ip_irc_lock);
-
        DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
-              expect->seq, ct_irc_info->len,
+              expect->seq, exp_irc_info->len,
               ntohl(tcph->seq));
 
        newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
 
        /* Alter conntrack's expectations. */
-
-       /* We can read expect here without conntrack lock, since it's
-          only set in ip_conntrack_irc, with ip_irc_lock held
-          writable */
-
        t = expect->tuple;
        t.dst.ip = newip;
-       for (port = ct_irc_info->port; port != 0; port++) {
+       for (port = exp_irc_info->port; port != 0; port++) {
                t.dst.u.tcp.port = htons(port);
                if (ip_conntrack_change_expect(expect, &t) == 0) {
                        DEBUGP("using port %d", port);
@@ -148,7 +139,7 @@ static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
 
        return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
                                        expect->seq - ntohl(tcph->seq),
-                                       ct_irc_info->len, buffer, 
+                                       exp_irc_info->len, buffer, 
                                        strlen(buffer));
 }
 
@@ -163,12 +154,12 @@ static unsigned int help(struct ip_conntrack *ct,
        struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
        unsigned int datalen;
        int dir;
-       struct ip_ct_irc_expect *ct_irc_info;
+       struct ip_ct_irc_expect *exp_irc_info;
 
        if (!exp)
                DEBUGP("ip_nat_irc: no exp!!");
                
-       ct_irc_info = &exp->help.exp_irc_info;
+       exp_irc_info = &exp->help.exp_irc_info;
 
        /* Only mangle things once: original direction in POST_ROUTING
           and reply direction on PRE_ROUTING. */
@@ -185,30 +176,24 @@ static unsigned int help(struct ip_conntrack *ct,
        DEBUGP("got beyond not touching\n");
 
        datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-       LOCK_BH(&ip_irc_lock);
        /* Check whether the whole IP/address pattern is carried in the payload */
-       if (between(exp->seq + ct_irc_info->len,
+       if (between(exp->seq + exp_irc_info->len,
                    ntohl(tcph->seq),
                    ntohl(tcph->seq) + datalen)) {
-               if (!irc_data_fixup(ct_irc_info, ct, pskb, ctinfo, exp)) {
-                       UNLOCK_BH(&ip_irc_lock);
+               if (!irc_data_fixup(exp_irc_info, ct, pskb, ctinfo, exp))
                        return NF_DROP;
-               }
        } else { 
                /* Half a match?  This means a partial retransmisison.
                   It's a cracker being funky. */
                if (net_ratelimit()) {
                        printk
                            ("IRC_NAT: partial packet %u/%u in %u/%u\n",
-                            exp->seq, ct_irc_info->len,
+                            exp->seq, exp_irc_info->len,
                             ntohl(tcph->seq),
                             ntohl(tcph->seq) + datalen);
                }
-               UNLOCK_BH(&ip_irc_lock);
                return NF_DROP;
        }
-       UNLOCK_BH(&ip_irc_lock);
-
        return NF_ACCEPT;
 }
 
@@ -235,11 +220,10 @@ static int __init init(void)
        struct ip_nat_helper *hlpr;
        char *tmpname;
 
-       if (ports[0] == 0) {
-               ports[0] = IRC_PORT;
-       }
+       if (ports_c == 0)
+               ports[ports_c++] = IRC_PORT;
 
-       for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) {
+       for (i = 0; i < ports_c; i++) {
                hlpr = &ip_nat_irc_helpers[i];
                hlpr->tuple.dst.protonum = IPPROTO_TCP;
                hlpr->tuple.src.u.tcp.port = htons(ports[i]);
@@ -269,7 +253,6 @@ static int __init init(void)
                        fini();
                        return 1;
                }
-               ports_c++;
        }
        return ret;
 }
index f7d31f8..6fb50de 100644 (file)
@@ -104,7 +104,7 @@ icmp_print_range(char *buffer, const struct ip_nat_range *range)
 }
 
 struct ip_nat_protocol ip_nat_protocol_icmp
-= { { NULL, NULL }, "ICMP", IPPROTO_ICMP,
+= { "ICMP", IPPROTO_ICMP,
     icmp_manip_pkt,
     icmp_in_range,
     icmp_unique_tuple,
index 731a12d..197bd01 100644 (file)
@@ -162,7 +162,7 @@ tcp_print_range(char *buffer, const struct ip_nat_range *range)
 }
 
 struct ip_nat_protocol ip_nat_protocol_tcp
-= { { NULL, NULL }, "TCP", IPPROTO_TCP,
+= { "TCP", IPPROTO_TCP,
     tcp_manip_pkt,
     tcp_in_range,
     tcp_unique_tuple,
index 2938465..240004e 100644 (file)
@@ -148,7 +148,7 @@ udp_print_range(char *buffer, const struct ip_nat_range *range)
 }
 
 struct ip_nat_protocol ip_nat_protocol_udp
-= { { NULL, NULL }, "UDP", IPPROTO_UDP,
+= { "UDP", IPPROTO_UDP,
     udp_manip_pkt,
     udp_in_range,
     udp_unique_tuple,
index 2d42a00..b57103f 100644 (file)
@@ -60,8 +60,8 @@ unknown_print_range(char *buffer, const struct ip_nat_range *range)
        return 0;
 }
 
-struct ip_nat_protocol unknown_nat_protocol = {
-       { NULL, NULL }, "unknown", 0,
+struct ip_nat_protocol ip_nat_unknown_protocol = {
+       "unknown", 0,
        unknown_manip_pkt,
        unknown_in_range,
        unknown_unique_tuple,
index 145b2c5..8ee96d1 100644 (file)
@@ -132,7 +132,8 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb,
        ct = ip_conntrack_get(*pskb, &ctinfo);
 
        /* Connection must be valid and new. */
-       IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
+       IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
+                           || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
        IP_NF_ASSERT(out);
 
        return ip_nat_setup_info(ct, targinfo, hooknum);
index a2097bf..cacaab6 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/moduleparam.h>
 
 MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
 MODULE_DESCRIPTION("tftp NAT helper");
@@ -41,7 +42,7 @@ MODULE_LICENSE("GPL");
 
 static int ports[MAX_PORTS];
 static int ports_c = 0;
-MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of tftp servers");
 
 #if 0
@@ -59,7 +60,7 @@ tftp_nat_help(struct ip_conntrack *ct,
              struct sk_buff **pskb)
 {
        int dir = CTINFO2DIR(ctinfo);
-       struct tftphdr tftph;
+       struct tftphdr _tftph, *tfh;
        struct ip_conntrack_tuple repl;
 
        if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
@@ -71,11 +72,13 @@ tftp_nat_help(struct ip_conntrack *ct,
                return NF_ACCEPT;
        }
 
-       if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
-                         &tftph, sizeof(tftph)) != 0)
+       tfh = skb_header_pointer(*pskb,
+                                (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
+                                sizeof(_tftph), &_tftph);
+       if (tfh == NULL)
                return NF_DROP;
 
-       switch (ntohs(tftph.opcode)) {
+       switch (ntohs(tfh->opcode)) {
        /* RRQ and WRQ works the same way */
        case TFTP_OPCODE_READ:
        case TFTP_OPCODE_WRITE:
@@ -108,9 +111,12 @@ tftp_nat_expected(struct sk_buff **pskb,
 #if 0
        const struct ip_conntrack_tuple *repl =
                        &master->tuplehash[IP_CT_DIR_REPLY].tuple;
-       struct udphdr udph;
+       struct udphdr _udph, *uh;
 
-       if (skb_copy_bits(*pskb,(*pskb)->nh.iph->ihl*4,&udph,sizeof(udph))!=0)
+       uh = skb_header_pointer(*pskb,
+                               (*pskb)->nh.iph->ihl*4,
+                               sizeof(_udph), &_udph);
+       if (uh == NULL)
                return NF_DROP;
 #endif
 
@@ -125,8 +131,8 @@ tftp_nat_expected(struct sk_buff **pskb,
                mr.range[0].min_ip = mr.range[0].max_ip = orig->dst.ip; 
                DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
                        "newsrc: %u.%u.%u.%u\n",
-                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph.source),
-                       NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph.dest),
+                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(uh->source),
+                       NIPQUAD((*pskb)->nh.iph->daddr), ntohs(uh->dest),
                        NIPQUAD(orig->dst.ip));
        } else {
                mr.range[0].min_ip = mr.range[0].max_ip = orig->src.ip;
@@ -136,8 +142,8 @@ tftp_nat_expected(struct sk_buff **pskb,
 
                DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
                        "newdst: %u.%u.%u.%u:%u\n",
-                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph.source),
-                        NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph.dest),
+                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(uh->source),
+                        NIPQUAD((*pskb)->nh.iph->daddr), ntohs(uh->dest),
                         NIPQUAD(orig->src.ip), ntohs(orig->src.u.udp.port));
        }
 
@@ -162,10 +168,10 @@ static int __init init(void)
        int i, ret = 0;
        char *tmpname;
 
-       if (!ports[0])
-               ports[0] = TFTP_PORT;
+       if (ports_c == 0)
+               ports[ports_c++] = TFTP_PORT;
 
-       for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
+       for (i = 0; i < ports_c; i++) {
                memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
 
                tftp[i].tuple.dst.protonum = IPPROTO_UDP;
@@ -194,7 +200,6 @@ static int __init init(void)
                        fini();
                        return ret;
                }
-               ports_c++;
        }
        return ret;
 }
index 906b89d..26dca38 100644 (file)
@@ -619,6 +619,7 @@ static ctl_table ipq_root_table[] = {
        { .ctl_name = 0 }
 };
 
+#ifdef CONFIG_PROC_FS
 static int
 ipq_get_info(char *buffer, char **start, off_t offset, int length)
 {
@@ -648,6 +649,7 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length)
                len = 0;
        return len;
 }
+#endif /* CONFIG_PROC_FS */
 
 static int
 init_or_cleanup(int init)
index 97b5401..8fd8c1a 100644 (file)
@@ -1,3 +1,5 @@
+#warning ipchains is obsolete, and will be removed soon.
+
 /* Minor modifications to fit on compatibility framework:
    Rusty.Russell@rustcorp.com.au
 */
@@ -679,49 +681,53 @@ ip_fw_check(const char *rif,
                case IPPROTO_TCP:
                        dprintf("TCP ");
                        if (!offset) {
-                               struct tcphdr tcph;
+                               struct tcphdr _tcph, *th;
 
-                               if (skb_copy_bits(*pskb,
-                                                 (*pskb)->nh.iph->ihl * 4,
-                                                 &tcph, sizeof(tcph)))
+                               th = skb_header_pointer(*pskb,
+                                                       (*pskb)->nh.iph->ihl*4,
+                                                       sizeof(_tcph), &_tcph);
+                               if (th == NULL)
                                        return FW_BLOCK;
 
-                               src_port = ntohs(tcph.source);
-                               dst_port = ntohs(tcph.dest);
+                               src_port = ntohs(th->source);
+                               dst_port = ntohs(th->dest);
 
                                /* Connection initilisation can only
                                 * be made when the syn bit is set and
                                 * neither of the ack or reset is
                                 * set. */
-                               if (tcph.syn && !(tcph.ack || tcph.rst))
+                               if (th->syn && !(th->ack || th->rst))
                                        tcpsyn = 1;
                        }
                        break;
                case IPPROTO_UDP:
                        dprintf("UDP ");
                        if (!offset) {
-                               struct udphdr udph;
+                               struct udphdr _udph, *uh;
 
-                               if (skb_copy_bits(*pskb,
-                                                 (*pskb)->nh.iph->ihl * 4,
-                                                 &udph, sizeof(udph)))
+                               uh = skb_header_pointer(*pskb,
+                                                       (*pskb)->nh.iph->ihl*4,
+                                                       sizeof(_udph), &_udph);
+                               if (uh == NULL)
                                        return FW_BLOCK;
 
-                               src_port = ntohs(udph.source);
-                               dst_port = ntohs(udph.dest);
+                               src_port = ntohs(uh->source);
+                               dst_port = ntohs(uh->dest);
                        }
                        break;
                case IPPROTO_ICMP:
                        if (!offset) {
-                               struct icmphdr icmph;
+                               struct icmphdr _icmph, *ic;
 
-                               if (skb_copy_bits(*pskb,
-                                                 (*pskb)->nh.iph->ihl * 4,
-                                                 &icmph, sizeof(icmph)))
+                               ic = skb_header_pointer(*pskb,
+                                                       (*pskb)->nh.iph->ihl*4,
+                                                       sizeof(_icmph),
+                                                       &_icmph);
+                               if (ic == NULL)
                                        return FW_BLOCK;
 
-                               src_port = (__u16) icmph.type;
-                               dst_port = (__u16) icmph.code;
+                               src_port = (__u16) ic->type;
+                               dst_port = (__u16) ic->code;
                        }
                        dprintf("ICMP ");
                        break;
index 424a903..b0f490f 100644 (file)
@@ -1,3 +1,5 @@
+#warning ipfwadm is obsolete, and will be removed soon.
+
 /* Minor modifications to fit on compatibility framework:
    Rusty.Russell@rustcorp.com.au
 */
@@ -410,20 +412,21 @@ int ip_fw_chk(struct sk_buff **pskb,
                        dprintf1("TCP ");
                        /* ports stay 0xFFFF if it is not the first fragment */
                        if (!offset) {
-                               struct tcphdr tcph;
+                               struct tcphdr _tcph, *th;
 
-                               if (skb_copy_bits(*pskb,
-                                                 (*pskb)->nh.iph->ihl * 4,
-                                                 &tcph, sizeof(tcph)))
+                               th = skb_header_pointer(*pskb,
+                                                       (*pskb)->nh.iph->ihl*4,
+                                                       sizeof(_tcph), &_tcph);
+                               if (th == NULL)
                                        return FW_BLOCK;
 
-                               src_port = ntohs(tcph.source);
-                               dst_port = ntohs(tcph.dest);
+                               src_port = ntohs(th->source);
+                               dst_port = ntohs(th->dest);
 
-                               if(!tcph.ack && !tcph.rst)
+                               if(!th->ack && !th->rst)
                                        /* We do NOT have ACK, value TRUE */
                                        notcpack = 1;
-                               if(!tcph.syn || !notcpack)
+                               if(!th->syn || !notcpack)
                                        /* We do NOT have SYN, value TRUE */
                                        notcpsyn = 1;
                        }
@@ -433,29 +436,32 @@ int ip_fw_chk(struct sk_buff **pskb,
                        dprintf1("UDP ");
                        /* ports stay 0xFFFF if it is not the first fragment */
                        if (!offset) {
-                               struct udphdr udph;
+                               struct udphdr _udph, *uh;
 
-                               if (skb_copy_bits(*pskb,
-                                                 (*pskb)->nh.iph->ihl * 4,
-                                                 &udph, sizeof(udph)))
+                               uh = skb_header_pointer(*pskb,
+                                                       (*pskb)->nh.iph->ihl*4,
+                                                       sizeof(_udph), &_udph);
+                               if (uh == NULL)
                                        return FW_BLOCK;
 
-                               src_port = ntohs(udph.source);
-                               dst_port = ntohs(udph.dest);
+                               src_port = ntohs(uh->source);
+                               dst_port = ntohs(uh->dest);
                        }
                        prt = IP_FW_F_UDP;
                        break;
                case IPPROTO_ICMP:
                        /* icmp_type stays 255 if it is not the first fragment */
                        if (!offset) {
-                               struct icmphdr icmph;
+                               struct icmphdr _icmph, *ic;
 
-                               if (skb_copy_bits(*pskb,
-                                                 (*pskb)->nh.iph->ihl * 4,
-                                                 &icmph, sizeof(icmph)))
+                               ic = skb_header_pointer(*pskb,
+                                                       (*pskb)->nh.iph->ihl*4,
+                                                       sizeof(_icmph),
+                                                       &_icmph);
+                               if (ic == NULL)
                                        return FW_BLOCK;
 
-                               icmp_type = (__u16) icmph.type;
+                               icmp_type = (__u16) ic->type;
                        }
                        dprintf2("ICMP:%d ", icmp_type);
                        prt = IP_FW_F_ICMP;
index 8ca4025..120109c 100644 (file)
@@ -52,34 +52,39 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
 static inline int
 set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward)
 {
-       struct tcphdr tcph;
+       struct tcphdr _tcph, *th;
        u_int16_t diffs[2];
 
        /* Not enought header? */
-       if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4, &tcph, sizeof(tcph))
-           < 0)
+       th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
+                               sizeof(_tcph), &_tcph);
+       if (th == NULL)
                return 0;
 
-       diffs[0] = ((u_int16_t *)&tcph)[6];
+       diffs[0] = ((u_int16_t *)th)[6];
        if (einfo->operation & IPT_ECN_OP_SET_ECE)
-               tcph.ece = einfo->proto.tcp.ece;
+               th->ece = einfo->proto.tcp.ece;
 
        if (einfo->operation & IPT_ECN_OP_SET_CWR)
-               tcph.cwr = einfo->proto.tcp.cwr;
-       diffs[1] = ((u_int16_t *)&tcph)[6];
+               th->cwr = einfo->proto.tcp.cwr;
+       diffs[1] = ((u_int16_t *)&th)[6];
 
        /* Only mangle if it's changed. */
        if (diffs[0] != diffs[1]) {
                diffs[0] = diffs[0] ^ 0xFFFF;
                if (!skb_ip_make_writable(pskb,
-                                         (*pskb)->nh.iph->ihl*4+sizeof(tcph)))
+                                         (*pskb)->nh.iph->ihl*4+sizeof(_tcph)))
                        return 0;
+
+               if (th != &_tcph)
+                       memcpy(&_tcph, th, sizeof(_tcph));
+
                if ((*pskb)->ip_summed != CHECKSUM_HW)
-                       tcph.check = csum_fold(csum_partial((char *)diffs,
-                                              sizeof(diffs),
-                                              tcph.check^0xFFFF));
+                       _tcph.check = csum_fold(csum_partial((char *)diffs,
+                                                            sizeof(diffs),
+                                                            _tcph.check^0xFFFF));
                memcpy((*pskb)->data + (*pskb)->nh.iph->ihl*4,
-                      &tcph, sizeof(tcph));
+                      &_tcph, sizeof(_tcph));
                if ((*pskb)->ip_summed == CHECKSUM_HW)
                        if (skb_checksum_help(pskb, inward))
                                return 0;
index 219e049..a4bb9b3 100644 (file)
@@ -23,7 +23,8 @@ target(struct sk_buff **pskb,
           If there is a real ct entry correspondig to this packet, 
           it'll hang aroun till timing out. We don't deal with it
           for performance reasons. JK */
-       (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
+       (*pskb)->nfct = &ip_conntrack_untracked.ct_general;
+       (*pskb)->nfctinfo = IP_CT_NEW;
        nf_conntrack_get((*pskb)->nfct);
 
        return IPT_CONTINUE;
index 1f0d765..a0fea84 100644 (file)
@@ -43,23 +43,26 @@ match(const struct sk_buff *skb,
       int offset,
       int *hotdrop)
 {
-       struct ip_auth_hdr ah;
+       struct ip_auth_hdr _ahdr, *ah;
        const struct ipt_ah *ahinfo = matchinfo;
 
        /* Must not be a fragment. */
        if (offset)
                return 0;
 
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &ah, sizeof(ah)) < 0) {
+       ah = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+                               sizeof(_ahdr), &_ahdr);
+       if (ah == NULL) {
                /* We've been asked to examine this packet, and we
-                  can't.  Hence, no choice but to drop. */
+                * can't.  Hence, no choice but to drop.
+                */
                duprintf("Dropping evil AH tinygram.\n");
                *hotdrop = 1;
                return 0;
        }
 
        return spi_match(ahinfo->spis[0], ahinfo->spis[1],
-                        ntohl(ah.spi),
+                        ntohl(ah->spi),
                         !!(ahinfo->invflags & IPT_AH_INV_SPI));
 }
 
diff --git a/net/ipv4/netfilter/ipt_comment.c b/net/ipv4/netfilter/ipt_comment.c
new file mode 100644 (file)
index 0000000..6b76a1e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Implements a dummy match to allow attaching comments to rules
+ *
+ * 2003-05-13 Brad Fisher (brad@info-link.net)
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_comment.h>
+
+MODULE_AUTHOR("Brad Fisher <brad@info-link.net>");
+MODULE_DESCRIPTION("iptables comment match module");
+MODULE_LICENSE("GPL");
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      int *hotdrop)
+{
+       /* We always match */
+       return 1;
+}
+
+static int
+checkentry(const char *tablename,
+           const struct ipt_ip *ip,
+           void *matchinfo,
+           unsigned int matchsize,
+           unsigned int hook_mask)
+{
+       /* Check the size */
+       if (matchsize != IPT_ALIGN(sizeof(struct ipt_comment_info)))
+               return 0;
+       return 1;
+}
+
+static struct ipt_match comment_match = {
+       .name           = "comment",
+       .match          = match,
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE
+};
+
+static int __init init(void)
+{
+       return ipt_register_match(&comment_match);
+}
+
+static void __exit fini(void)
+{
+       ipt_unregister_match(&comment_match);
+}
+
+module_init(init);
+module_exit(fini);
index 9b04bbb..c1d2280 100644 (file)
@@ -35,7 +35,7 @@ match(const struct sk_buff *skb,
 
 #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
 
-       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
+       if (ct == &ip_conntrack_untracked)
                statebit = IPT_CONNTRACK_STATE_UNTRACKED;
        else if (ct)
                statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
index 0e1efd7..b6f7181 100644 (file)
@@ -30,31 +30,34 @@ static inline int match_tcp(const struct sk_buff *skb,
                            const struct ipt_ecn_info *einfo,
                            int *hotdrop)
 {
-       struct tcphdr tcph;
+       struct tcphdr _tcph, *th;
 
        /* In practice, TCP match does this, so can't fail.  But let's
-           be good citizens. */
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) {
+        * be good citizens.
+        */
+       th = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+                               sizeof(_tcph), &_tcph);
+       if (th == NULL) {
                *hotdrop = 0;
                return 0;
        }
 
        if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
                if (einfo->invert & IPT_ECN_OP_MATCH_ECE) {
-                       if (tcph.ece == 1)
+                       if (th->ece == 1)
                                return 0;
                } else {
-                       if (tcph.ece == 0)
+                       if (th->ece == 0)
                                return 0;
                }
        }
 
        if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
                if (einfo->invert & IPT_ECN_OP_MATCH_CWR) {
-                       if (tcph.cwr == 1)
+                       if (th->cwr == 1)
                                return 0;
                } else {
-                       if (tcph.cwr == 0)
+                       if (th->cwr == 0)
                                return 0;
                }
        }
index c3b8893..e1d0dd3 100644 (file)
@@ -44,23 +44,26 @@ match(const struct sk_buff *skb,
       int offset,
       int *hotdrop)
 {
-       struct ip_esp_hdr esp;
+       struct ip_esp_hdr _esp, *eh;
        const struct ipt_esp *espinfo = matchinfo;
 
        /* Must not be a fragment. */
        if (offset)
                return 0;
 
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &esp, sizeof(esp)) < 0) {
+       eh = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+                               sizeof(_esp), &_esp);
+       if (eh == NULL) {
                /* We've been asked to examine this packet, and we
-                  can't.  Hence, no choice but to drop. */
+                * can't.  Hence, no choice but to drop.
+                */
                duprintf("Dropping evil ESP tinygram.\n");
                *hotdrop = 1;
                return 0;
        }
 
        return spi_match(espinfo->spis[0], espinfo->spis[1],
-                        ntohl(esp.spi),
+                        ntohl(eh->spi),
                         !!(espinfo->invflags & IPT_ESP_INV_SPI));
 }
 
index 77109e0..11a459e 100644 (file)
@@ -33,7 +33,7 @@ match(const struct sk_buff *skb,
     return (skb->mac.raw >= skb->head
            && (skb->mac.raw + ETH_HLEN) <= skb->data
            /* If so, compare... */
-           && ((memcmp(skb->mac.ethernet->h_source, info->srcaddr, ETH_ALEN)
+           && ((memcmp(eth_hdr(skb)->h_source, info->srcaddr, ETH_ALEN)
                == 0) ^ info->invert));
 }
 
index 64e7999..7fdf41e 100644 (file)
@@ -54,7 +54,7 @@ match(const struct sk_buff *skb,
       int offset,
       int *hotdrop)
 {
-       u16 ports[2];
+       u16 _ports[2], *pptr;
        const struct ipt_multiport *multiinfo = matchinfo;
 
        /* Must not be a fragment. */
@@ -63,18 +63,21 @@ match(const struct sk_buff *skb,
 
        /* Must be big enough to read ports (both UDP and TCP have
            them at the start). */
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
+       pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+                                 sizeof(_ports), &_ports[0]);
+       if (pptr == NULL) {
                /* We've been asked to examine this packet, and we
-                  can't.  Hence, no choice but to drop. */
-                       duprintf("ipt_multiport:"
-                                " Dropping evil offset=0 tinygram.\n");
-                       *hotdrop = 1;
-                       return 0;
+                * can't.  Hence, no choice but to drop.
+                */
+               duprintf("ipt_multiport:"
+                        " Dropping evil offset=0 tinygram.\n");
+               *hotdrop = 1;
+               return 0;
        }
 
        return ports_match(multiinfo->ports,
                           multiinfo->flags, multiinfo->count,
-                          ntohs(ports[0]), ntohs(ports[1]));
+                          ntohs(pptr[0]), ntohs(pptr[1]));
 }
 
 /* Called when user tries to insert an entry of this type. */
index 08b786a..15472b3 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/ctype.h>
 #include <linux/ip.h>
 #include <linux/vmalloc.h>
+#include <linux/moduleparam.h>
 
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_recent.h>
@@ -37,12 +38,12 @@ KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>.  htt
 MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>");
 MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER);
 MODULE_LICENSE("GPL");
-MODULE_PARM(ip_list_tot,"i");
-MODULE_PARM(ip_pkt_list_tot,"i");
-MODULE_PARM(ip_list_hash_size,"i");
-MODULE_PARM(ip_list_perms,"i");
+module_param(ip_list_tot, int, 0400);
+module_param(ip_pkt_list_tot, int, 0400);
+module_param(ip_list_hash_size, int, 0400);
+module_param(ip_list_perms, int, 0400);
 #ifdef DEBUG
-MODULE_PARM(debug,"i");
+module_param(debug, int, 0600);
 MODULE_PARM_DESC(debug,"debugging level, defaults to 1");
 #endif
 MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list");
diff --git a/net/ipv4/netfilter/ipt_sctp.c b/net/ipv4/netfilter/ipt_sctp.c
new file mode 100644 (file)
index 0000000..fe2b327
--- /dev/null
@@ -0,0 +1,203 @@
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/ip.h>
+#include <linux/sctp.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_sctp.h>
+
+#ifdef DEBUG_SCTP
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
+                                             || (!!((invflag) & (option)) ^ (cond)))
+
+static int
+match_flags(const struct ipt_sctp_flag_info *flag_info,
+           const int flag_count,
+           u_int8_t chunktype,
+           u_int8_t chunkflags)
+{
+       int i;
+
+       for (i = 0; i < flag_count; i++) {
+               if (flag_info[i].chunktype == chunktype) {
+                       return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
+               }
+       }
+
+       return 1;
+}
+
+static int
+match_packet(const struct sk_buff *skb,
+            const u_int32_t *chunkmap,
+            int chunk_match_type,
+            const struct ipt_sctp_flag_info *flag_info,
+            const int flag_count,
+            int *hotdrop)
+{
+       int offset;
+       u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
+       sctp_chunkhdr_t _sch, *sch;
+
+#ifdef DEBUG_SCTP
+       int i = 0;
+#endif
+
+       if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
+               SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
+       }
+
+       offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
+       do {
+               sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
+               if (sch == NULL) {
+                       duprintf("Dropping invalid SCTP packet.\n");
+                       *hotdrop = 1;
+                       return 0;
+               }
+
+               duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", 
+                               ++i, offset, sch->type, htons(sch->length), sch->flags);
+
+               offset += (htons(sch->length) + 3) & ~3;
+
+               duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
+
+               if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch->type)) {
+                       switch (chunk_match_type) {
+                       case SCTP_CHUNK_MATCH_ANY:
+                               if (match_flags(flag_info, flag_count, 
+                                       sch->type, sch->flags)) {
+                                       return 1;
+                               }
+                               break;
+
+                       case SCTP_CHUNK_MATCH_ALL:
+                               if (match_flags(flag_info, flag_count, 
+                                       sch->type, sch->flags)) {
+                                       SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type);
+                               }
+                               break;
+
+                       case SCTP_CHUNK_MATCH_ONLY:
+                               if (!match_flags(flag_info, flag_count, 
+                                       sch->type, sch->flags)) {
+                                       return 0;
+                               }
+                               break;
+                       }
+               } else {
+                       switch (chunk_match_type) {
+                       case SCTP_CHUNK_MATCH_ONLY:
+                               return 0;
+                       }
+               }
+       } while (offset < skb->len);
+
+       switch (chunk_match_type) {
+       case SCTP_CHUNK_MATCH_ALL:
+               return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
+       case SCTP_CHUNK_MATCH_ANY:
+               return 0;
+       case SCTP_CHUNK_MATCH_ONLY:
+               return 1;
+       }
+
+       /* This will never be reached, but required to stop compiler whine */
+       return 0;
+}
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      int *hotdrop)
+{
+       const struct ipt_sctp_info *info;
+       sctp_sctphdr_t _sh, *sh;
+
+       info = (const struct ipt_sctp_info *)matchinfo;
+
+       if (offset) {
+               duprintf("Dropping non-first fragment.. FIXME\n");
+               return 0;
+       }
+       
+       sh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_sh), &_sh);
+       if (sh == NULL) {
+               duprintf("Dropping evil TCP offset=0 tinygram.\n");
+               *hotdrop = 1;
+               return 0;
+               }
+       duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest));
+
+       return  SCCHECK(((ntohs(sh->source) >= info->spts[0]) 
+                       && (ntohs(sh->source) <= info->spts[1])), 
+                       IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
+               && SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) 
+                       && (ntohs(sh->dest) <= info->dpts[1])), 
+                       IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
+               && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
+                                       info->flag_info, info->flag_count, 
+                                       hotdrop),
+                          IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
+}
+
+static int
+checkentry(const char *tablename,
+          const struct ipt_ip *ip,
+          void *matchinfo,
+          unsigned int matchsize,
+          unsigned int hook_mask)
+{
+       const struct ipt_sctp_info *info;
+
+       info = (const struct ipt_sctp_info *)matchinfo;
+
+       return ip->proto == IPPROTO_SCTP
+               && !(ip->invflags & IPT_INV_PROTO)
+               && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
+               && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
+               && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
+               && !(info->invflags & ~info->flags)
+               && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || 
+                       (info->chunk_match_type &
+                               (SCTP_CHUNK_MATCH_ALL 
+                               | SCTP_CHUNK_MATCH_ANY
+                               | SCTP_CHUNK_MATCH_ONLY)));
+}
+
+static struct ipt_match sctp_match = 
+{ 
+       .list = { NULL, NULL},
+       .name = "sctp",
+       .match = &match,
+       .checkentry = &checkentry,
+       .destroy = NULL,
+       .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+       return ipt_register_match(&sctp_match);
+}
+
+static void __exit fini(void)
+{
+       ipt_unregister_match(&sctp_match);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kiran Kumar Immidi");
+MODULE_DESCRIPTION("Match for SCTP protocol packets");
+
index a3d40a4..b1511b9 100644 (file)
@@ -30,9 +30,9 @@ match(const struct sk_buff *skb,
        enum ip_conntrack_info ctinfo;
        unsigned int statebit;
 
-       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
+       if (skb->nfct == &ip_conntrack_untracked.ct_general)
                statebit = IPT_STATE_UNTRACKED;
-       else if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
+       else if (!ip_conntrack_get(skb, &ctinfo))
                statebit = IPT_STATE_INVALID;
        else
                statebit = IPT_STATE_BIT(ctinfo);
index c7cb62a..5cda547 100644 (file)
@@ -27,37 +27,45 @@ mssoption_match(u_int16_t min, u_int16_t max,
                int invert,
                int *hotdrop)
 {
-       struct tcphdr tcph;
+       struct tcphdr _tcph, *th;
        /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
-       u8 opt[15 * 4 - sizeof(tcph)];
+       u8 _opt[15 * 4 - sizeof(_tcph)], *op;
        unsigned int i, optlen;
 
        /* If we don't have the whole header, drop packet. */
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
+       th = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+                               sizeof(_tcph), &_tcph);
+       if (th == NULL)
                goto dropit;
 
        /* Malformed. */
-       if (tcph.doff*4 < sizeof(tcph))
+       if (th->doff*4 < sizeof(*th))
                goto dropit;
 
-       optlen = tcph.doff*4 - sizeof(tcph);
+       optlen = th->doff*4 - sizeof(*th);
+       if (!optlen)
+               goto out;
+
        /* Truncated options. */
-       if (skb_copy_bits(skb, skb->nh.iph->ihl*4+sizeof(tcph), opt, optlen)<0)
+       op = skb_header_pointer(skb, skb->nh.iph->ihl * 4 + sizeof(*th),
+                               optlen, _opt);
+       if (op == NULL)
                goto dropit;
 
        for (i = 0; i < optlen; ) {
-               if (opt[i] == TCPOPT_MSS
+               if (op[i] == TCPOPT_MSS
                    && (optlen - i) >= TCPOLEN_MSS
-                   && opt[i+1] == TCPOLEN_MSS) {
+                   && op[i+1] == TCPOLEN_MSS) {
                        u_int16_t mssval;
 
-                       mssval = (opt[i+2] << 8) | opt[i+3];
+                       mssval = (op[i+2] << 8) | op[i+3];
                        
                        return (mssval >= min && mssval <= max) ^ invert;
                }
-               if (opt[i] < 2) i++;
-               else i += opt[i+1]?:1;
+               if (op[i] < 2) i++;
+               else i += op[i+1]?:1;
        }
+out:
        return invert;
 
  dropit:
index 8fb2ed9..6b291da 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 
 MODULE_LICENSE("GPL");
@@ -155,7 +156,7 @@ static struct nf_hook_ops ipt_ops[] = {
 
 /* Default to forward because I got too much mail already. */
 static int forward = NF_ACCEPT;
-MODULE_PARM(forward, "i");
+module_param(forward, bool, 0000);
 
 static int __init init(void)
 {
index 5506944..3e23c6d 100644 (file)
@@ -68,31 +68,31 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
        if (tp->ecn_flags&TCP_ECN_OK)
                info->tcpi_options |= TCPI_OPT_ECN;
 
-       info->tcpi_rto = (1000000*tp->rto)/HZ;
-       info->tcpi_ato = (1000000*tp->ack.ato)/HZ;
-       info->tcpi_snd_mss = tp->mss_cache;
+       info->tcpi_rto = jiffies_to_usecs(tp->rto);
+       info->tcpi_ato = jiffies_to_usecs(tp->ack.ato);
+       info->tcpi_snd_mss = tp->mss_cache_std;
        info->tcpi_rcv_mss = tp->ack.rcv_mss;
 
-       info->tcpi_unacked = tp->packets_out;
-       info->tcpi_sacked = tp->sacked_out;
-       info->tcpi_lost = tp->lost_out;
-       info->tcpi_retrans = tp->retrans_out;
-       info->tcpi_fackets = tp->fackets_out;
+       info->tcpi_unacked = tcp_get_pcount(&tp->packets_out);
+       info->tcpi_sacked = tcp_get_pcount(&tp->sacked_out);
+       info->tcpi_lost = tcp_get_pcount(&tp->lost_out);
+       info->tcpi_retrans = tcp_get_pcount(&tp->retrans_out);
+       info->tcpi_fackets = tcp_get_pcount(&tp->fackets_out);
 
-       info->tcpi_last_data_sent = ((now - tp->lsndtime)*1000)/HZ;
-       info->tcpi_last_data_recv = ((now - tp->ack.lrcvtime)*1000)/HZ;
-       info->tcpi_last_ack_recv = ((now - tp->rcv_tstamp)*1000)/HZ;
+       info->tcpi_last_data_sent = jiffies_to_msecs(now - tp->lsndtime);
+       info->tcpi_last_data_recv = jiffies_to_msecs(now - tp->ack.lrcvtime);
+       info->tcpi_last_ack_recv = jiffies_to_msecs(now - tp->rcv_tstamp);
 
        info->tcpi_pmtu = tp->pmtu_cookie;
        info->tcpi_rcv_ssthresh = tp->rcv_ssthresh;
-       info->tcpi_rtt = ((1000000*tp->srtt)/HZ)>>3;
-       info->tcpi_rttvar = ((1000000*tp->mdev)/HZ)>>2;
+       info->tcpi_rtt = jiffies_to_usecs(tp->srtt)>>3;
+       info->tcpi_rttvar = jiffies_to_usecs(tp->mdev)>>2;
        info->tcpi_snd_ssthresh = tp->snd_ssthresh;
        info->tcpi_snd_cwnd = tp->snd_cwnd;
        info->tcpi_advmss = tp->advmss;
        info->tcpi_reordering = tp->reordering;
 
-       info->tcpi_rcv_rtt = ((1000000*tp->rcv_rtt_est.rtt)/HZ)>>3;
+       info->tcpi_rcv_rtt = jiffies_to_usecs(tp->rcv_rtt_est.rtt)>>3;
        info->tcpi_rcv_space = tp->rcvq_space.space;
 }
 
@@ -116,7 +116,8 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
                if (ext & (1<<(TCPDIAG_INFO-1)))
                        info = TCPDIAG_PUT(skb, TCPDIAG_INFO, sizeof(*info));
                
-               if (tcp_is_vegas(tp) && (ext & (1<<(TCPDIAG_VEGASINFO-1))))
+               if ((tcp_is_westwood(tp) || tcp_is_vegas(tp))
+                   && (ext & (1<<(TCPDIAG_VEGASINFO-1))))
                        vinfo = TCPDIAG_PUT(skb, TCPDIAG_VEGASINFO, sizeof(*vinfo));
        }
        r->tcpdiag_family = sk->sk_family;
@@ -209,10 +210,17 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
                tcp_get_info(sk, info);
 
        if (vinfo) {
-               vinfo->tcpv_enabled = tp->vegas.doing_vegas_now;
-               vinfo->tcpv_rttcnt = tp->vegas.cntRTT;
-               vinfo->tcpv_rtt = tp->vegas.baseRTT;
-               vinfo->tcpv_minrtt = tp->vegas.minRTT;
+               if (tcp_is_vegas(tp)) {
+                       vinfo->tcpv_enabled = tp->vegas.doing_vegas_now;
+                       vinfo->tcpv_rttcnt = tp->vegas.cntRTT;
+                       vinfo->tcpv_rtt = jiffies_to_usecs(tp->vegas.baseRTT);
+                       vinfo->tcpv_minrtt = jiffies_to_usecs(tp->vegas.minRTT);
+               } else {
+                       vinfo->tcpv_enabled = 0;
+                       vinfo->tcpv_rttcnt = 0;
+                       vinfo->tcpv_rtt = jiffies_to_usecs(tp->westwood.rtt);
+                       vinfo->tcpv_minrtt = jiffies_to_usecs(tp->westwood.rtt_min);
+               }
        }
 
        nlh->nlmsg_len = skb->tail - b;
@@ -487,21 +495,22 @@ static int tcpdiag_dump(struct sk_buff *skb, struct netlink_callback *cb)
                        sk_for_each(sk, node, &tcp_listening_hash[i]) {
                                struct inet_opt *inet = inet_sk(sk);
                                if (num < s_num)
-                                       continue;
+                                       goto next_listen;
                                if (!(r->tcpdiag_states&TCPF_LISTEN) ||
                                    r->id.tcpdiag_dport)
-                                       continue;
+                                       goto next_listen;
                                if (r->id.tcpdiag_sport != inet->sport &&
                                    r->id.tcpdiag_sport)
-                                       continue;
+                                       goto next_listen;
                                if (bc && !tcpdiag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), sk))
-                                       continue;
+                                       goto next_listen;
                                if (tcpdiag_fill(skb, sk, r->tcpdiag_ext,
                                                 NETLINK_CB(cb->skb).pid,
                                                 cb->nlh->nlmsg_seq) <= 0) {
                                        tcp_listen_unlock();
                                        goto done;
                                }
+next_listen:
                                ++num;
                        }
                }
@@ -529,22 +538,23 @@ skip_listen_ht:
                        struct inet_opt *inet = inet_sk(sk);
 
                        if (num < s_num)
-                               continue;
+                               goto next_normal;
                        if (!(r->tcpdiag_states & (1 << sk->sk_state)))
-                               continue;
+                               goto next_normal;
                        if (r->id.tcpdiag_sport != inet->sport &&
                            r->id.tcpdiag_sport)
-                               continue;
+                               goto next_normal;
                        if (r->id.tcpdiag_dport != inet->dport && r->id.tcpdiag_dport)
-                               continue;
+                               goto next_normal;
                        if (bc && !tcpdiag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), sk))
-                               continue;
+                               goto next_normal;
                        if (tcpdiag_fill(skb, sk, r->tcpdiag_ext,
                                         NETLINK_CB(cb->skb).pid,
                                         cb->nlh->nlmsg_seq) <= 0) {
                                read_unlock_bh(&head->lock);
                                goto done;
                        }
+next_normal:
                        ++num;
                }
 
@@ -554,23 +564,22 @@ skip_listen_ht:
                                struct inet_opt *inet = inet_sk(sk);
 
                                if (num < s_num)
-                                       continue;
-                               if (!(r->tcpdiag_states & (1 << sk->sk_zapped)))
-                                       continue;
+                                       goto next_dying;
                                if (r->id.tcpdiag_sport != inet->sport &&
                                    r->id.tcpdiag_sport)
-                                       continue;
+                                       goto next_dying;
                                if (r->id.tcpdiag_dport != inet->dport &&
                                    r->id.tcpdiag_dport)
-                                       continue;
+                                       goto next_dying;
                                if (bc && !tcpdiag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), sk))
-                                       continue;
+                                       goto next_dying;
                                if (tcpdiag_fill(skb, sk, r->tcpdiag_ext,
                                                 NETLINK_CB(cb->skb).pid,
                                                 cb->nlh->nlmsg_seq) <= 0) {
                                        read_unlock_bh(&head->lock);
                                        goto done;
                                }
+next_dying:
                                ++num;
                        }
                }
index b045c87..47e54d4 100644 (file)
@@ -24,8 +24,7 @@ static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
        struct iphdr *outer_iph = skb->nh.iph;
        struct iphdr *inner_iph = skb->h.ipiph;
 
-       if (INET_ECN_is_ce(outer_iph->tos) &&
-           INET_ECN_is_not_ce(inner_iph->tos))
+       if (INET_ECN_is_ce(outer_iph->tos))
                IP_ECN_set_ce(inner_iph);
 }
 
@@ -102,6 +101,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
                        if (skb_cloned(skb) &&
                            pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
                                goto drop;
+                       if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+                               ipv4_copy_dscp(iph, skb->h.ipiph);
                        if (!(x->props.flags & XFRM_STATE_NOECN))
                                ipip_ecn_decapsulate(skb);
                        skb->mac.raw = memmove(skb->data - skb->mac_len,
index 191cec7..21832df 100644 (file)
@@ -58,8 +58,7 @@ static void xfrm4_encap(struct sk_buff *skb)
        if (!top_iph->frag_off)
                __ip_select_ident(top_iph, dst, 0);
 
-       /* TTL disclosed */
-       top_iph->ttl = iph->ttl;
+       top_iph->ttl = dst_path_metric(dst, RTAX_HOPLIMIT);
 
        top_iph->saddr = x->props.saddr.a4;
        top_iph->daddr = x->id.daddr.a4;
@@ -119,8 +118,7 @@ int xfrm4_output(struct sk_buff **pskb)
 
        xfrm4_encap(skb);
 
-       err = x->type->output(pskb);
-       skb = *pskb;
+       err = x->type->output(skb);
        if (err)
                goto error;
 
index 23c5759..fd87a5a 100644 (file)
@@ -48,6 +48,7 @@ config INET6_IPCOMP
        tristate "IPv6: IPComp transformation"
        depends on IPV6
        select XFRM
+       select INET6_TUNNEL
        select CRYPTO
        select CRYPTO_DEFLATE
        ---help---
@@ -56,9 +57,21 @@ config INET6_IPCOMP
 
          If unsure, say Y.
 
+config INET6_TUNNEL
+       tristate "IPv6: tunnel transformation"
+       depends on IPV6
+       select XFRM
+       ---help---
+         Support for generic IPv6-in-IPv6 tunnel transformation, which is
+         required by the IPv6-in-IPv6 tunneling module as well as tunnel mode
+         IPComp.
+         
+         If unsure, say Y.
+
 config IPV6_TUNNEL
        tristate "IPv6: IPv6-in-IPv6 tunnel"
        depends on IPV6
+       select INET6_TUNNEL
        ---help---
          Support for IPv6-in-IPv6 tunnels described in RFC 2473.
 
index 8b1cf3e..5e0aecb 100644 (file)
@@ -38,7 +38,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        struct sockaddr_in6     *usin = (struct sockaddr_in6 *) uaddr;
        struct inet_opt         *inet = inet_sk(sk);
        struct ipv6_pinfo       *np = inet6_sk(sk);
-       struct in6_addr         *daddr;
+       struct in6_addr         *daddr, *final_p = NULL, final;
        struct dst_entry        *dst;
        struct flowi            fl;
        struct ip6_flowlabel    *flowlabel = NULL;
@@ -157,16 +157,27 @@ ipv4_connected:
        if (flowlabel) {
                if (flowlabel->opt && flowlabel->opt->srcrt) {
                        struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
+                       ipv6_addr_copy(&final, &fl.fl6_dst);
                        ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+                       final_p = &final;
                }
        } else if (np->opt && np->opt->srcrt) {
                struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
+               ipv6_addr_copy(&final, &fl.fl6_dst);
                ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+               final_p = &final;
        }
 
        err = ip6_dst_lookup(sk, &dst, &fl);
        if (err)
                goto out;
+       if (final_p)
+               ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+       if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+               dst_release(dst);
+               goto out;
+       }
 
        /* source address lookup done in ip6_dst_lookup */
 
index 07151a6..6dda815 100644 (file)
@@ -68,34 +68,35 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len
        u8 nexthdr = *nexthdrp;
 
        while (ipv6_ext_hdr(nexthdr)) {
-               struct ipv6_opt_hdr hdr;
+               struct ipv6_opt_hdr _hdr, *hp;
                int hdrlen;
 
                if (len < (int)sizeof(struct ipv6_opt_hdr))
                        return -1;
                if (nexthdr == NEXTHDR_NONE)
                        return -1;
-               if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
+               hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
+               if (hp == NULL)
                        BUG();
                if (nexthdr == NEXTHDR_FRAGMENT) {
-                       unsigned short frag_off;
-                       if (skb_copy_bits(skb,
-                                         start+offsetof(struct frag_hdr,
-                                                        frag_off),
-                                         &frag_off,
-                                         sizeof(frag_off))) {
+                       unsigned short _frag_off, *fp;
+                       fp = skb_header_pointer(skb,
+                                               start+offsetof(struct frag_hdr,
+                                                              frag_off),
+                                               sizeof(_frag_off),
+                                               &_frag_off);
+                       if (fp == NULL)
                                return -1;
-                       }
 
-                       if (ntohs(frag_off) & ~0x7)
+                       if (ntohs(*fp) & ~0x7)
                                break;
                        hdrlen = 8;
                } else if (nexthdr == NEXTHDR_AUTH)
-                       hdrlen = (hdr.hdrlen+2)<<2; 
+                       hdrlen = (hp->hdrlen+2)<<2; 
                else
-                       hdrlen = ipv6_optlen(&hdr); 
+                       hdrlen = ipv6_optlen(hp); 
 
-               nexthdr = hdr.nexthdr;
+               nexthdr = hp->nexthdr;
                len -= hdrlen;
                start += hdrlen;
        }
index 65a1372..1816b81 100644 (file)
@@ -449,9 +449,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
                         *      Same priority level
                         */
 
-                       if ((iter->rt6i_dev == rt->rt6i_dev) &&
-                           (ipv6_addr_cmp(&iter->rt6i_gateway,
-                                          &rt->rt6i_gateway) == 0)) {
+                       if (iter->rt6i_dev == rt->rt6i_dev &&
+                           iter->rt6i_idev == rt->rt6i_idev &&
+                           ipv6_addr_cmp(&iter->rt6i_gateway,
+                                          &rt->rt6i_gateway) == 0) {
                                if (!(iter->rt6i_flags&RTF_EXPIRES))
                                        return -EEXIST;
                                iter->rt6i_expires = rt->rt6i_expires;
@@ -514,7 +515,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh,
        int err = -ENOMEM;
 
        fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
-                       rt->rt6i_dst.plen, (u8*) &rt->rt6i_dst - (u8*) rt);
+                       rt->rt6i_dst.plen, offsetof(struct rt6_info, rt6i_dst));
 
        if (fn == NULL)
                goto out;
@@ -550,7 +551,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh,
 
                        sn = fib6_add_1(sfn, &rt->rt6i_src.addr,
                                        sizeof(struct in6_addr), rt->rt6i_src.plen,
-                                       (u8*) &rt->rt6i_src - (u8*) rt);
+                                       offsetof(struct rt6_info, rt6i_src));
 
                        if (sn == NULL) {
                                /* If it is failed, discard just allocated
@@ -571,7 +572,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh,
                } else {
                        sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
                                        sizeof(struct in6_addr), rt->rt6i_src.plen,
-                                       (u8*) &rt->rt6i_src - (u8*) rt);
+                                       offsetof(struct rt6_info, rt6i_src));
 
                        if (sn == NULL)
                                goto st_failure;
@@ -680,14 +681,13 @@ struct fib6_node * fib6_lookup(struct fib6_node *root, struct in6_addr *daddr,
                               struct in6_addr *saddr)
 {
        struct lookup_args args[2];
-       struct rt6_info *rt = NULL;
        struct fib6_node *fn;
 
-       args[0].offset = (u8*) &rt->rt6i_dst - (u8*) rt;
+       args[0].offset = offsetof(struct rt6_info, rt6i_dst);
        args[0].addr = daddr;
 
 #ifdef CONFIG_IPV6_SUBTREES
-       args[1].offset = (u8*) &rt->rt6i_src - (u8*) rt;
+       args[1].offset = offsetof(struct rt6_info, rt6i_src);
        args[1].addr = saddr;
 #endif
 
@@ -739,11 +739,10 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
                               struct in6_addr *daddr, int dst_len,
                               struct in6_addr *saddr, int src_len)
 {
-       struct rt6_info *rt = NULL;
        struct fib6_node *fn;
 
        fn = fib6_locate_1(root, daddr, dst_len,
-                          (u8*) &rt->rt6i_dst - (u8*) rt);
+                          offsetof(struct rt6_info, rt6i_dst));
 
 #ifdef CONFIG_IPV6_SUBTREES
        if (src_len) {
@@ -752,7 +751,7 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
                        fn = fn->subtree;
                if (fn)
                        fn = fib6_locate_1(fn, saddr, src_len,
-                                          (u8*) &rt->rt6i_src - (u8*) rt);
+                                          offsetof(struct rt6_info, rt6i_src));
        }
 #endif
 
@@ -1185,6 +1184,7 @@ static int fib6_age(struct rt6_info *rt, void *arg)
        if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) {
                if (time_after(now, rt->rt6i_expires)) {
                        RT6_TRACE("expiring %p\n", rt);
+                       rt6_reset_dflt_pointer(rt);
                        return -1;
                }
                gc_args.more++;
@@ -1193,6 +1193,11 @@ static int fib6_age(struct rt6_info *rt, void *arg)
                    time_after_eq(now, rt->u.dst.lastuse + gc_args.timeout)) {
                        RT6_TRACE("aging clone %p\n", rt);
                        return -1;
+               } else if ((rt->rt6i_flags & RTF_GATEWAY) &&
+                          (!(rt->rt6i_nexthop->flags & NTF_ROUTER))) {
+                       RT6_TRACE("purging route %p via non-router but gateway\n",
+                                 rt);
+                       return -1;
                }
                gc_args.more++;
        }
index 0e212f2..20f6657 100644 (file)
@@ -158,6 +158,15 @@ config IP6_NF_MATCH_EUI64
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config IP6_NF_MATCH_PHYSDEV
+       tristate "Physdev match support"
+       depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER
+       help
+         Physdev packet matching matches against the physical bridge ports
+         the IP packet arrived on or will leave by.
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
 #  dep_tristate '  Multiple port match support' CONFIG_IP6_NF_MATCH_MULTIPORT $CONFIG_IP6_NF_IPTABLES
 #  dep_tristate '  TOS match support' CONFIG_IP6_NF_MATCH_TOS $CONFIG_IP6_NF_IPTABLES
 #  if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
index d7687eb..2e51714 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
 obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
 obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
+obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o
 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
index b6199f2..3b1340d 100644 (file)
@@ -41,10 +41,10 @@ match(const struct sk_buff *skb,
     
     memset(eui64, 0, sizeof(eui64));
 
-    if (skb->mac.ethernet->h_proto == ntohs(ETH_P_IPV6)) {
+    if (eth_hdr(skb)->h_proto == ntohs(ETH_P_IPV6)) {
       if (skb->nh.ipv6h->version == 0x6) { 
-         memcpy(eui64, skb->mac.ethernet->h_source, 3);
-         memcpy(eui64 + 5, skb->mac.ethernet->h_source + 3, 3);
+         memcpy(eui64, eth_hdr(skb)->h_source, 3);
+         memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3);
         eui64[3]=0xff;
         eui64[4]=0xfe;
         eui64[0] |= 0x02;
index 4d184e4..ea874dd 100644 (file)
@@ -35,7 +35,7 @@ match(const struct sk_buff *skb,
     return (skb->mac.raw >= skb->head
            && (skb->mac.raw + ETH_HLEN) <= skb->data
            /* If so, compare... */
-           && ((memcmp(skb->mac.ethernet->h_source, info->srcaddr, ETH_ALEN)
+           && ((memcmp(eth_hdr(skb)->h_source, info->srcaddr, ETH_ALEN)
                == 0) ^ info->invert));
 }
 
diff --git a/net/ipv6/netfilter/ip6t_physdev.c b/net/ipv6/netfilter/ip6t_physdev.c
new file mode 100644 (file)
index 0000000..f4eebb4
--- /dev/null
@@ -0,0 +1,136 @@
+/* Kernel module to match the bridge port in and
+ * out device for IP packets coming into contact with a bridge. */
+
+/* (C) 2001-2003 Bart De Schuymer <bdschuym@pandora.be>
+ *
+ * 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/skbuff.h>
+#include <linux/netfilter_ipv6/ip6t_physdev.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_bridge.h>
+#define MATCH   1
+#define NOMATCH 0
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
+MODULE_DESCRIPTION("iptables bridge physical device match module");
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      const void *hdr,
+      u_int16_t datalen,
+      int *hotdrop)
+{
+       int i;
+       static const char nulldevname[IFNAMSIZ];
+       const struct ip6t_physdev_info *info = matchinfo;
+       unsigned int ret;
+       const char *indev, *outdev;
+       struct nf_bridge_info *nf_bridge;
+
+       /* Not a bridged IP packet or no info available yet:
+        * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
+        * the destination device will be a bridge. */
+       if (!(nf_bridge = skb->nf_bridge)) {
+               /* Return MATCH if the invert flags of the used options are on */
+               if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) &&
+                   !(info->invert & IP6T_PHYSDEV_OP_BRIDGED))
+                       return NOMATCH;
+               if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN) &&
+                   !(info->invert & IP6T_PHYSDEV_OP_ISIN))
+                       return NOMATCH;
+               if ((info->bitmask & IP6T_PHYSDEV_OP_ISOUT) &&
+                   !(info->invert & IP6T_PHYSDEV_OP_ISOUT))
+                       return NOMATCH;
+               if ((info->bitmask & IP6T_PHYSDEV_OP_IN) &&
+                   !(info->invert & IP6T_PHYSDEV_OP_IN))
+                       return NOMATCH;
+               if ((info->bitmask & IP6T_PHYSDEV_OP_OUT) &&
+                   !(info->invert & IP6T_PHYSDEV_OP_OUT))
+                       return NOMATCH;
+               return MATCH;
+       }
+
+       /* This only makes sense in the FORWARD and POSTROUTING chains */
+       if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) &&
+           (!!(nf_bridge->mask & BRNF_BRIDGED) ^
+           !(info->invert & IP6T_PHYSDEV_OP_BRIDGED)))
+               return NOMATCH;
+
+       if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN &&
+           (!nf_bridge->physindev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISIN))) ||
+           (info->bitmask & IP6T_PHYSDEV_OP_ISOUT &&
+           (!nf_bridge->physoutdev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISOUT))))
+               return NOMATCH;
+
+       if (!(info->bitmask & IP6T_PHYSDEV_OP_IN))
+               goto match_outdev;
+       indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
+       for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+               ret |= (((const unsigned int *)indev)[i]
+                       ^ ((const unsigned int *)info->physindev)[i])
+                       & ((const unsigned int *)info->in_mask)[i];
+       }
+
+       if ((ret == 0) ^ !(info->invert & IP6T_PHYSDEV_OP_IN))
+               return NOMATCH;
+
+match_outdev:
+       if (!(info->bitmask & IP6T_PHYSDEV_OP_OUT))
+               return MATCH;
+       outdev = nf_bridge->physoutdev ?
+                nf_bridge->physoutdev->name : nulldevname;
+       for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+               ret |= (((const unsigned int *)outdev)[i]
+                       ^ ((const unsigned int *)info->physoutdev)[i])
+                       & ((const unsigned int *)info->out_mask)[i];
+       }
+
+       return (ret != 0) ^ !(info->invert & IP6T_PHYSDEV_OP_OUT);
+}
+
+static int
+checkentry(const char *tablename,
+                      const struct ip6t_ip6 *ip,
+                      void *matchinfo,
+                      unsigned int matchsize,
+                      unsigned int hook_mask)
+{
+       const struct ip6t_physdev_info *info = matchinfo;
+
+       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_physdev_info)))
+               return 0;
+       if (!(info->bitmask & IP6T_PHYSDEV_OP_MASK) ||
+           info->bitmask & ~IP6T_PHYSDEV_OP_MASK)
+               return 0;
+       return 1;
+}
+
+static struct ip6t_match physdev_match = {
+       .name           = "physdev",
+       .match          = &match,
+       .checkentry     = &checkentry,
+       .me             = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+       return ip6t_register_match(&physdev_match);
+}
+
+static void __exit fini(void)
+{
+       ip6t_unregister_match(&physdev_match);
+}
+
+module_init(init);
+module_exit(fini);
index 46daa79..aca6d21 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 
 MODULE_LICENSE("GPL");
@@ -156,7 +157,7 @@ static struct nf_hook_ops ip6t_ops[] = {
 
 /* Default to forward because I got too much mail already. */
 static int forward = NF_ACCEPT;
-MODULE_PARM(forward, "i");
+module_param(forward, bool, 0000);
 
 static int __init init(void)
 {
index 0791594..28c29d7 100644 (file)
@@ -9,7 +9,9 @@
  *             IPv6 support
  */
 
+#include <linux/module.h>
 #include <linux/string.h>
+#include <net/dsfield.h>
 #include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
@@ -20,16 +22,15 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
        struct ipv6hdr *outer_iph = skb->nh.ipv6h;
        struct ipv6hdr *inner_iph = skb->h.ipv6h;
 
-       if (INET_ECN_is_ce(ip6_get_dsfield(outer_iph)) &&
-           INET_ECN_is_not_ce(ip6_get_dsfield(inner_iph)))
+       if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
                IP6_ECN_set_ce(inner_iph);
 }
 
-int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi)
 {
        struct sk_buff *skb = *pskb;
        int err;
-       u32 spi, seq;
+       u32 seq;
        struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
        struct xfrm_state *x;
        int xfrm_nr = 0;
@@ -40,7 +41,8 @@ int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
        nhoff = *nhoffp;
        nexthdr = skb->nh.raw[nhoff];
 
-       if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
+       seq = 0;
+       if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
                goto drop;
        
        do {
@@ -86,6 +88,8 @@ int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
                        if (skb_cloned(skb) &&
                            pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
                                goto drop;
+                       if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+                               ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
                        if (!(x->props.flags & XFRM_STATE_NOECN))
                                ipip6_ecn_decapsulate(skb);
                        skb->mac.raw = memmove(skb->data - skb->mac_len,
@@ -137,3 +141,10 @@ drop:
        kfree_skb(skb);
        return -1;
 }
+
+EXPORT_SYMBOL(xfrm6_rcv_spi);
+
+int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+{
+       return xfrm6_rcv_spi(pskb, nhoffp, 0);
+}
index 712856f..40612ec 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/icmpv6.h>
+#include <net/dsfield.h>
 #include <net/inet_ecn.h>
 #include <net/ipv6.h>
 #include <net/xfrm.h>
@@ -36,6 +37,7 @@ static void xfrm6_encap(struct sk_buff *skb)
        struct dst_entry *dst = skb->dst;
        struct xfrm_state *x = dst->xfrm;
        struct ipv6hdr *iph, *top_iph;
+       int dsfield;
 
        skb_push(skb, x->props.header_len);
        iph = skb->nh.ipv6h;
@@ -58,13 +60,16 @@ static void xfrm6_encap(struct sk_buff *skb)
 
        top_iph->version = 6;
        top_iph->priority = iph->priority;
-       if (x->props.flags & XFRM_STATE_NOECN)
-               IP6_ECN_clear(top_iph);
        top_iph->flow_lbl[0] = iph->flow_lbl[0];
        top_iph->flow_lbl[1] = iph->flow_lbl[1];
        top_iph->flow_lbl[2] = iph->flow_lbl[2];
+       dsfield = ipv6_get_dsfield(top_iph);
+       dsfield = INET_ECN_encapsulate(dsfield, dsfield);
+       if (x->props.flags & XFRM_STATE_NOECN)
+               dsfield &= ~INET_ECN_MASK;
+       ipv6_change_dsfield(top_iph, 0, dsfield);
        top_iph->nexthdr = IPPROTO_IPV6; 
-       top_iph->hop_limit = iph->hop_limit;
+       top_iph->hop_limit = dst_path_metric(dst, RTAX_HOPLIMIT);
        ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
        ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
 }
@@ -113,8 +118,7 @@ int xfrm6_output(struct sk_buff **pskb)
 
        xfrm6_encap(skb);
 
-       err = x->type->output(pskb);
-       skb = *pskb;
+       err = x->type->output(skb);
        if (err)
                goto error;
 
index 5766a13..9616a63 100644 (file)
@@ -343,9 +343,8 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr)
 
 EXPORT_SYMBOL(xfrm6_tunnel_free_spi);
 
-static int xfrm6_tunnel_output(struct sk_buff **pskb)
+static int xfrm6_tunnel_output(struct sk_buff *skb)
 {
-       struct sk_buff *skb = *pskb;
        struct ipv6hdr *top_iph;
 
        top_iph = (struct ipv6hdr *)skb->data;
@@ -356,17 +355,6 @@ static int xfrm6_tunnel_output(struct sk_buff **pskb)
 
 static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
-       if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 
-               return -EINVAL;
-
-       skb->mac.raw = skb->nh.raw;
-       skb->nh.raw = skb->data;
-       dst_release(skb->dst);
-       skb->dst = NULL;
-       skb->protocol = htons(ETH_P_IPV6);
-       skb->pkt_type = PACKET_HOST;
-       netif_rx(skb);
-
        return 0;
 }
 
@@ -413,49 +401,15 @@ static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
 {
        struct sk_buff *skb = *pskb;
        struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
-       struct xfrm_state *x = NULL;
        struct ipv6hdr *iph = skb->nh.ipv6h;
-       int err = 0;
        u32 spi;
 
        /* device-like_ip6ip6_handler() */
-       if (handler) {
-               err = handler->handler(pskb, nhoffp);
-               if (!err)
-                       goto out;
-       }
+       if (handler && handler->handler(pskb, nhoffp) == 0)
+               return 0;
 
        spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
-       x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, 
-                       spi,
-                       IPPROTO_IPV6, AF_INET6);
-
-       if (!x)
-               goto drop;
-
-       spin_lock(&x->lock);
-
-       if (unlikely(x->km.state != XFRM_STATE_VALID))
-               goto drop_unlock;
-
-       err = xfrm6_tunnel_input(x, NULL, skb);
-       if (err)
-               goto drop_unlock;
-
-       x->curlft.bytes += skb->len;
-       x->curlft.packets++; 
-       spin_unlock(&x->lock); 
-       xfrm_state_put(x); 
-
-out:
-       return 0;
-
-drop_unlock:
-       spin_unlock(&x->lock);
-       xfrm_state_put(x);
-drop:
-       kfree_skb(skb);
-       return -1;
+       return xfrm6_rcv_spi(pskb, nhoffp, spi);
 }
 
 static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -517,6 +471,9 @@ static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args)
        if (!x->props.mode)
                return -EINVAL;
 
+       if (x->encap)
+               return -EINVAL;
+
        x->props.header_len = sizeof(struct ipv6hdr);
 
        return 0;
@@ -543,31 +500,32 @@ static struct inet6_protocol xfrm6_tunnel_protocol = {
        .flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
-void __init xfrm6_tunnel_init(void)
+static int __init xfrm6_tunnel_init(void)
 {
        X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
 
        if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) {
                X6TPRINTK1(KERN_ERR
                           "xfrm6_tunnel init: can't add xfrm type\n");
-               return;
+               return -EAGAIN;
        }
        if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) {
                X6TPRINTK1(KERN_ERR
                           "xfrm6_tunnel init(): can't add protocol\n");
                xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
-               return;
+               return -EAGAIN;
        }
        if (xfrm6_tunnel_spi_init() < 0) {
                X6TPRINTK1(KERN_ERR
                           "xfrm6_tunnel init: failed to initialize spi\n");
                inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
                xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
-               return;
+               return -EAGAIN;
        }
+       return 0;
 }
 
-void __exit xfrm6_tunnel_fini(void)
+static void __exit xfrm6_tunnel_fini(void)
 {
        X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
 
@@ -579,3 +537,7 @@ void __exit xfrm6_tunnel_fini(void)
                X6TPRINTK1(KERN_ERR
                           "xfrm6_tunnel close: can't remove xfrm type\n");
 }
+
+module_init(xfrm6_tunnel_init);
+module_exit(xfrm6_tunnel_fini);
+MODULE_LICENSE("GPL");
index fa25d3a..e659907 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
+#include <linux/moduleparam.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -1181,9 +1182,9 @@ MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(eth, "i");
+module_param(eth, bool, 0);
 MODULE_PARM_DESC(eth, "Name devices ethX (0) or irlanX (1)");
-MODULE_PARM(access, "i");
+module_param(access, int, 0);
 MODULE_PARM_DESC(access, "Access type DIRECT=1, PEER=2, HOSTED=3");
 
 module_init(irlan_init);
index 11a2955..04bb892 100644 (file)
@@ -303,10 +303,10 @@ void irlan_eth_send_gratuitous_arp(struct net_device *dev)
         */
 #ifdef CONFIG_INET
        IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
-       in_dev = in_dev_get(dev);
+       rcu_read_lock();
+       in_dev = __in_dev_get(dev);
        if (in_dev == NULL)
-               return;
-       read_lock(&in_dev->lock);
+               goto out;
        if (in_dev->ifa_list)
                
        arp_send(ARPOP_REQUEST, ETH_P_ARP, 
@@ -314,8 +314,8 @@ void irlan_eth_send_gratuitous_arp(struct net_device *dev)
                 dev, 
                 in_dev->ifa_list->ifa_address,
                 NULL, dev->dev_addr, NULL);
-       read_unlock(&in_dev->lock);
-       in_dev_put(in_dev);
+out:
+       rcu_read_unlock();
 #endif /* CONFIG_INET */
 }
 
index 65a3eb9..ca948a0 100644 (file)
@@ -663,8 +663,10 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
        } /* Default is no-lock  */
 
        /* Check if valid and not already removed... */
-       if((entry->q_next == NULL) || (entry->q_prev == NULL))
-               return NULL;
+       if((entry->q_next == NULL) || (entry->q_prev == NULL)) {
+               entry = NULL;
+               goto out;
+       }
 
        /*
         * Locate hashbin
@@ -687,7 +689,7 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
         */
        if ( entry == hashbin->hb_current)
                hashbin->hb_current = NULL;
-
+out:
        /* Release lock */
        if ( hashbin->hb_type & HB_LOCK ) {
                spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
index ecfa9b5..4da6976 100644 (file)
@@ -111,7 +111,7 @@ static inline int llc_fixup_skb(struct sk_buff *skb)
        skb->h.raw += llc_len;
        skb_pull(skb, llc_len);
        if (skb->protocol == htons(ETH_P_802_2)) {
-               u16 pdulen = ((struct ethhdr *)skb->mac.raw)->h_proto,
+               u16 pdulen = eth_hdr(skb)->h_proto,
                    data_size = ntohs(pdulen) - llc_len;
 
                skb_trim(skb, data_size);
index 66206eb..ab5784c 100644 (file)
@@ -40,7 +40,8 @@ int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da)
                struct net_device *dev = skb->dev;
                struct trh_hdr *trh;
                
-               trh = (struct trh_hdr *)skb_push(skb, sizeof(*trh));
+               skb->mac.raw = skb_push(skb, sizeof(*trh));
+               trh = tr_hdr(skb);
                trh->ac = AC;
                trh->fc = LLC_FRAME;
                if (sa)
@@ -50,8 +51,8 @@ int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da)
                if (da) {
                        memcpy(trh->daddr, da, dev->addr_len);
                        tr_source_route(skb, trh, dev);
+                       skb->mac.raw = skb->data;
                }
-               skb->mac.raw = skb->data;
                break;
        }
 #endif
@@ -61,7 +62,7 @@ int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da)
                struct ethhdr *eth;
 
                skb->mac.raw = skb_push(skb, sizeof(*eth));
-               eth = (struct ethhdr *)skb->mac.raw;
+               eth = eth_hdr(skb);
                eth->h_proto = htons(len);
                memcpy(eth->h_dest, da, ETH_ALEN);
                memcpy(eth->h_source, sa, ETH_ALEN);
index 21623a9..966667f 100644 (file)
@@ -32,7 +32,7 @@ MODULE_DESCRIPTION("Rx RPC implementation");
 MODULE_AUTHOR("Red Hat, Inc.");
 MODULE_LICENSE("GPL");
 
-uint32_t rxrpc_epoch;
+__be32 rxrpc_epoch;
 
 /*****************************************************************************/
 /*
index a0665d6..e5c9f12 100644 (file)
@@ -48,7 +48,7 @@ static const struct rxrpc_timer_ops rxrpc_peer_timer_ops = {
 /*
  * create a peer record
  */
-static int __rxrpc_create_peer(struct rxrpc_transport *trans, uint32_t addr,
+static int __rxrpc_create_peer(struct rxrpc_transport *trans, __be32 addr,
                               struct rxrpc_peer **_peer)
 {
        struct rxrpc_peer *peer;
@@ -96,7 +96,7 @@ static int __rxrpc_create_peer(struct rxrpc_transport *trans, uint32_t addr,
  * - returns (if successful) with peer record usage incremented
  * - resurrects it from the graveyard if found there
  */
-int rxrpc_peer_lookup(struct rxrpc_transport *trans, uint32_t addr,
+int rxrpc_peer_lookup(struct rxrpc_transport *trans, __be32 addr,
                      struct rxrpc_peer **_peer)
 {
        struct rxrpc_peer *peer, *candidate = NULL;
index 58d37d6..b189f5a 100644 (file)
@@ -155,7 +155,7 @@ struct tc_action_ops *tc_lookup_action_id(u32 type)
        return a;
 }
 
-int tcf_action_exec(struct sk_buff *skb,struct tc_action *act)
+int tcf_action_exec(struct sk_buff *skb,struct tc_action *act, struct tcf_result *res)
 {
 
        struct tc_action *a;
@@ -164,7 +164,8 @@ int tcf_action_exec(struct sk_buff *skb,struct tc_action *act)
        if (skb->tc_verd & TC_NCLS) {
                skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
                D2PRINTK("(%p)tcf_action_exec: cleared TC_NCLS in %s out %s\n",skb,skb->input_dev?skb->input_dev->name:"xxx",skb->dev->name);
-               return TC_ACT_OK;
+               ret = TC_ACT_OK;
+               goto exec_done;
        }
        while ((a = act) != NULL) {
 repeat:
@@ -186,6 +187,11 @@ repeat:
        }
 
 exec_done:
+       if (skb->tc_classid > 0) {
+               res->classid = skb->tc_classid;
+               res->class = 0;
+               skb->tc_classid = 0;
+       }
 
        return ret;
 }
diff --git a/net/sched/gact.c b/net/sched/gact.c
new file mode 100644 (file)
index 0000000..5607f5e
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * net/sched/gact.c    Generic actions
+ *
+ *             This program is free software; you can redistribute 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.
+ *
+ * copyright   Jamal Hadi Salim (2002-4)
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <linux/tc_act/tc_gact.h>
+#include <net/tc_act/tc_gact.h>
+
+/* use generic hash table */
+#define MY_TAB_SIZE    16
+#define MY_TAB_MASK    15
+static u32 idx_gen;
+static struct tcf_gact *tcf_gact_ht[MY_TAB_SIZE];
+static rwlock_t gact_lock = RW_LOCK_UNLOCKED;
+
+/* ovewrride the defaults */
+#define tcf_st  tcf_gact
+#define tc_st  tc_gact
+#define tcf_t_lock   gact_lock
+#define tcf_ht tcf_gact_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+
+#ifdef CONFIG_GACT_PROB
+typedef int (*g_rand)(struct tcf_gact *p);
+int
+gact_net_rand(struct tcf_gact *p) {
+       if (net_random()%p->pval)
+               return p->action;
+       return p->paction;
+}
+
+int
+gact_determ(struct tcf_gact *p) {
+       if (p->stats.packets%p->pval)
+               return p->action;
+       return p->paction;
+}
+
+
+g_rand gact_rand[MAX_RAND]= { NULL,gact_net_rand, gact_determ};
+
+#endif
+int
+tcf_gact_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,int ovr,int bind)
+{
+       struct rtattr *tb[TCA_GACT_MAX];
+       struct tc_gact *parm = NULL;
+#ifdef CONFIG_GACT_PROB
+       struct tc_gact_p *p_parm = NULL;
+#endif
+       struct tcf_gact *p = NULL;
+       int ret = 0;
+       int size = sizeof (*p);
+
+       if (rtattr_parse(tb, TCA_GACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
+               return -1;
+
+       if (NULL == a || NULL == tb[TCA_GACT_PARMS - 1]) {
+               printk("BUG: tcf_gact_init called with NULL params\n");
+               return -1;
+       }
+
+       parm = RTA_DATA(tb[TCA_GACT_PARMS - 1]);
+#ifdef CONFIG_GACT_PROB
+       if (NULL != tb[TCA_GACT_PROB - 1]) {
+               p_parm = RTA_DATA(tb[TCA_GACT_PROB - 1]);
+       }
+#endif
+
+       p = tcf_hash_check(parm, a, ovr, bind);
+
+       if (NULL == p) {
+               p = tcf_hash_create(parm,est,a,size,ovr, bind);
+
+               if (NULL == p) {
+                       return -1;
+               } else {
+                       p->refcnt = 1;
+                       ret = 1;
+                       goto override;
+               }
+       }
+
+       if (ovr) {
+override:
+               p->action = parm->action;
+#ifdef CONFIG_GACT_PROB
+               if (NULL != p_parm) {
+                       p->paction = p_parm->paction;
+                       p->pval = p_parm->pval;
+                       p->ptype = p_parm->ptype;
+               } else {
+                       p->paction = p->pval = p->ptype = 0;
+               }
+#endif
+       }
+
+       return ret;
+}
+
+int
+tcf_gact_cleanup(struct tc_action *a, int bind)
+{
+       struct tcf_gact *p;
+       p = PRIV(a,gact);
+       if (NULL != p)
+               return tcf_hash_release(p, bind);
+       return 0;
+}
+
+int
+tcf_gact(struct sk_buff **pskb, struct tc_action *a)
+{
+       struct tcf_gact *p;
+       struct sk_buff *skb = *pskb;
+       int action = TC_ACT_SHOT;
+
+       p = PRIV(a,gact);
+
+       if (NULL == p) {
+               if (net_ratelimit())
+                       printk("BUG: tcf_gact called with NULL params\n");
+               return -1;
+       }
+
+       spin_lock(&p->lock);
+#ifdef CONFIG_GACT_PROB
+       if (p->ptype && NULL != gact_rand[p->ptype])
+               action = gact_rand[p->ptype](p);
+       else
+               action = p->action;
+#else
+       action = p->action;
+#endif
+       p->stats.bytes += skb->len;
+       p->stats.packets++;
+       if (TC_ACT_SHOT == action)
+               p->stats.drops++;
+       p->tm.lastuse = jiffies;
+       spin_unlock(&p->lock);
+
+       return action;
+}
+
+int
+tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+       unsigned char *b = skb->tail;
+       struct tc_gact opt;
+#ifdef CONFIG_GACT_PROB
+       struct tc_gact_p p_opt;
+#endif
+       struct tcf_gact *p;
+       struct tcf_t t;
+
+       p = PRIV(a,gact);
+       if (NULL == p) {
+               printk("BUG: tcf_gact_dump called with NULL params\n");
+               goto rtattr_failure;
+       }
+
+       opt.index = p->index;
+       opt.refcnt = p->refcnt - ref;
+       opt.bindcnt = p->bindcnt - bind;
+       opt.action = p->action;
+       RTA_PUT(skb, TCA_GACT_PARMS, sizeof (opt), &opt);
+#ifdef CONFIG_GACT_PROB
+       if (p->ptype) {
+               p_opt.paction = p->paction;
+               p_opt.pval = p->pval;
+               p_opt.ptype = p->ptype;
+               RTA_PUT(skb, TCA_GACT_PROB, sizeof (p_opt), &p_opt);
+       } 
+#endif
+       t.install = jiffies - p->tm.install;
+       t.lastuse = jiffies - p->tm.lastuse;
+       t.expires = p->tm.expires;
+       RTA_PUT(skb, TCA_GACT_TM, sizeof (t), &t);
+       return skb->len;
+
+      rtattr_failure:
+       skb_trim(skb, b - skb->data);
+       return -1;
+}
+
+int
+tcf_gact_stats(struct sk_buff *skb, struct tc_action *a)
+{
+       struct tcf_gact *p;
+       p = PRIV(a,gact);
+       if (NULL != p)
+               return qdisc_copy_stats(skb, &p->stats,p->stats_lock);
+
+       return 1;
+}
+
+struct tc_action_ops act_gact_ops = {
+       .next           =       NULL,
+       .kind           =       "gact",
+       .type           =       TCA_ACT_GACT,
+       .capab          =       TCA_CAP_NONE,
+       .owner          =       THIS_MODULE,
+       .act            =       tcf_gact,
+       .get_stats      =       tcf_gact_stats,
+       .dump           =       tcf_gact_dump,
+       .cleanup        =       tcf_gact_cleanup,
+       .lookup         =       tcf_hash_search,
+       .init           =       tcf_gact_init,
+       .walk           =       tcf_generic_walker
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
+MODULE_DESCRIPTION("Generic Classifier actions");
+MODULE_LICENSE("GPL");
+
+static int __init
+gact_init_module(void)
+{
+#ifdef CONFIG_GACT_PROB
+       printk("GACT probability on\n");
+#else
+       printk("GACT probability NOT on\n");
+#endif
+       return tcf_register_action(&act_gact_ops);
+}
+
+static void __exit
+gact_cleanup_module(void)
+{
+       tcf_unregister_action(&act_gact_ops);
+}
+
+module_init(gact_init_module);
+module_exit(gact_cleanup_module);
index e0831a4..28b61f0 100644 (file)
@@ -331,8 +331,6 @@ int dsmark_init(struct Qdisc *sch,struct rtattr *opt)
            !tb[TCA_DSMARK_INDICES-1] ||
            RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16))
                 return -EINVAL;
-       memset(p,0,sizeof(*p));
-       p->filter_list = NULL;
        p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]);
        if (!p->indices)
                return -EINVAL;
index 4d91d69..d29df1c 100644 (file)
@@ -6,6 +6,9 @@
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  *
+ *             Many of the algorithms and ideas for this came from
+ *             NIST Net which is not copyrighted. 
+ *
  * Authors:    Stephen Hemminger <shemminger@osdl.org>
  *             Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
  */
 
 #include <net/pkt_sched.h>
 
-/*     Network emulator
- *
- *     This scheduler can alters spacing and order
- *     Similar to NISTnet and BSD Dummynet.
- */
+/*     Network Emulation Queuing algorithm.
+       ====================================
+
+       Sources: [1] Mark Carson, Darrin Santay, "NIST Net - A Linux-based
+                Network Emulation Tool
+                [2] Luigi Rizzo, DummyNet for FreeBSD
+
+        ----------------------------------------------------------------
+
+        This started out as a simple way to delay outgoing packets to
+        test TCP but has grown to include most of the functionality
+        of a full blown network emulator like NISTnet. It can delay
+        packets and add random jitter (and correlation). The random
+        distribution can be loaded from a table as well to provide
+        normal, Pareto, or experimental curves. Packet loss,
+        duplication, and reordering can also be emulated.
+
+        This qdisc does not do classification that can be handled in
+        layering other disciplines.  It does not need to do bandwidth
+        control either since that can be handled by using token
+        bucket or other rate control.
+
+        The simulator is limited by the Linux timer resolution
+        and will create packet bursts on the HZ boundary (1ms).
+*/
 
 struct netem_sched_data {
        struct Qdisc    *qdisc;
@@ -39,6 +62,17 @@ struct netem_sched_data {
        u32 counter;
        u32 gap;
        u32 jitter;
+       u32 duplicate;
+
+       struct crndstate {
+               unsigned long last;
+               unsigned long rho;
+       } delay_cor, loss_cor, dup_cor;
+
+       struct disttable {
+               u32  size;
+               s16 table[0];
+       } *delay_dist;
 };
 
 /* Time stamp put into socket buffer control block */
@@ -46,576 +80,110 @@ struct netem_skb_cb {
        psched_time_t   time_to_send;
 };
 
-/* This is the distribution table for the normal distribution produced
- * with NISTnet tools.
- * The entries represent a scaled inverse of the cumulative distribution
- * function.
+/* init_crandom - initialize correlated random number generator
+ * Use entropy source for initial seed.
  */
-#define TABLESIZE      2048
-#define TABLEFACTOR    8192
-
-static const short disttable[TABLESIZE] = {
-       -31473,         -26739,         -25226,         -24269,
-       -23560,         -22993,         -22518,         -22109,
-       -21749,         -21426,         -21133,         -20865,
-       -20618,         -20389,         -20174,         -19972,
-       -19782,         -19601,         -19430,         -19267,
-       -19112,         -18962,         -18819,         -18681,
-       -18549,         -18421,         -18298,         -18178,
-       -18062,         -17950,         -17841,         -17735,
-       -17632,         -17532,         -17434,         -17339,
-       -17245,         -17155,         -17066,         -16979,
-       -16894,         -16811,         -16729,         -16649,
-       -16571,         -16494,         -16419,         -16345,
-       -16272,         -16201,         -16130,         -16061,
-       -15993,         -15926,         -15861,         -15796,
-       -15732,         -15669,         -15607,         -15546,
-       -15486,         -15426,         -15368,         -15310,
-       -15253,         -15196,         -15140,         -15086,
-       -15031,         -14977,         -14925,         -14872,
-       -14821,         -14769,         -14719,         -14669,
-       -14619,         -14570,         -14522,         -14473,
-       -14426,         -14379,         -14332,         -14286,
-       -14241,         -14196,         -14150,         -14106,
-       -14062,         -14019,         -13976,         -13933,
-       -13890,         -13848,         -13807,         -13765,
-       -13724,         -13684,         -13643,         -13604,
-       -13564,         -13525,         -13486,         -13447,
-       -13408,         -13370,         -13332,         -13295,
-       -13258,         -13221,         -13184,         -13147,
-       -13111,         -13075,         -13040,         -13004,
-       -12969,         -12934,         -12899,         -12865,
-       -12830,         -12796,         -12762,         -12729,
-       -12695,         -12662,         -12629,         -12596,
-       -12564,         -12531,         -12499,         -12467,
-       -12435,         -12404,         -12372,         -12341,
-       -12310,         -12279,         -12248,         -12218,
-       -12187,         -12157,         -12127,         -12097,
-       -12067,         -12038,         -12008,         -11979,
-       -11950,         -11921,         -11892,         -11863,
-       -11835,         -11806,         -11778,         -11750,
-       -11722,         -11694,         -11666,         -11639,
-       -11611,         -11584,         -11557,         -11530,
-       -11503,         -11476,         -11450,         -11423,
-       -11396,         -11370,         -11344,         -11318,
-       -11292,         -11266,         -11240,         -11214,
-       -11189,         -11164,         -11138,         -11113,
-       -11088,         -11063,         -11038,         -11013,
-       -10988,         -10964,         -10939,         -10915,
-       -10891,         -10866,         -10843,         -10818,
-       -10794,         -10770,         -10747,         -10723,
-       -10700,         -10676,         -10652,         -10630,
-       -10606,         -10583,         -10560,         -10537,
-       -10514,         -10491,         -10469,         -10446,
-       -10424,         -10401,         -10378,         -10356,
-       -10334,         -10312,         -10290,         -10267,
-       -10246,         -10224,         -10202,         -10180,
-       -10158,         -10137,         -10115,         -10094,
-       -10072,         -10051,         -10030,         -10009,
-       -9988,          -9967,          -9945,          -9925,
-       -9904,          -9883,          -9862,          -9842,
-       -9821,          -9800,          -9780,          -9760,
-       -9739,          -9719,          -9699,          -9678,
-       -9658,          -9638,          -9618,          -9599,
-       -9578,          -9559,          -9539,          -9519,
-       -9499,          -9480,          -9461,          -9441,
-       -9422,          -9402,          -9383,          -9363,
-       -9344,          -9325,          -9306,          -9287,
-       -9268,          -9249,          -9230,          -9211,
-       -9192,          -9173,          -9155,          -9136,
-       -9117,          -9098,          -9080,          -9062,
-       -9043,          -9025,          -9006,          -8988,
-       -8970,          -8951,          -8933,          -8915,
-       -8897,          -8879,          -8861,          -8843,
-       -8825,          -8807,          -8789,          -8772,
-       -8754,          -8736,          -8718,          -8701,
-       -8683,          -8665,          -8648,          -8630,
-       -8613,          -8595,          -8578,          -8561,
-       -8543,          -8526,          -8509,          -8492,
-       -8475,          -8458,          -8441,          -8423,
-       -8407,          -8390,          -8373,          -8356,
-       -8339,          -8322,          -8305,          -8289,
-       -8272,          -8255,          -8239,          -8222,
-       -8206,          -8189,          -8172,          -8156,
-       -8140,          -8123,          -8107,          -8090,
-       -8074,          -8058,          -8042,          -8025,
-       -8009,          -7993,          -7977,          -7961,
-       -7945,          -7929,          -7913,          -7897,
-       -7881,          -7865,          -7849,          -7833,
-       -7817,          -7802,          -7786,          -7770,
-       -7754,          -7739,          -7723,          -7707,
-       -7692,          -7676,          -7661,          -7645,
-       -7630,          -7614,          -7599,          -7583,
-       -7568,          -7553,          -7537,          -7522,
-       -7507,          -7492,          -7476,          -7461,
-       -7446,          -7431,          -7416,          -7401,
-       -7385,          -7370,          -7356,          -7340,
-       -7325,          -7311,          -7296,          -7281,
-       -7266,          -7251,          -7236,          -7221,
-       -7207,          -7192,          -7177,          -7162,
-       -7148,          -7133,          -7118,          -7104,
-       -7089,          -7075,          -7060,          -7046,
-       -7031,          -7016,          -7002,          -6988,
-       -6973,          -6959,          -6944,          -6930,
-       -6916,          -6901,          -6887,          -6873,
-       -6859,          -6844,          -6830,          -6816,
-       -6802,          -6788,          -6774,          -6760,
-       -6746,          -6731,          -6717,          -6704,
-       -6690,          -6675,          -6661,          -6647,
-       -6633,          -6620,          -6606,          -6592,
-       -6578,          -6564,          -6550,          -6537,
-       -6523,          -6509,          -6495,          -6482,
-       -6468,          -6454,          -6441,          -6427,
-       -6413,          -6400,          -6386,          -6373,
-       -6359,          -6346,          -6332,          -6318,
-       -6305,          -6291,          -6278,          -6264,
-       -6251,          -6238,          -6224,          -6211,
-       -6198,          -6184,          -6171,          -6158,
-       -6144,          -6131,          -6118,          -6105,
-       -6091,          -6078,          -6065,          -6052,
-       -6039,          -6025,          -6012,          -5999,
-       -5986,          -5973,          -5960,          -5947,
-       -5934,          -5921,          -5908,          -5895,
-       -5882,          -5869,          -5856,          -5843,
-       -5830,          -5817,          -5804,          -5791,
-       -5779,          -5766,          -5753,          -5740,
-       -5727,          -5714,          -5702,          -5689,
-       -5676,          -5663,          -5650,          -5638,
-       -5625,          -5612,          -5600,          -5587,
-       -5575,          -5562,          -5549,          -5537,
-       -5524,          -5512,          -5499,          -5486,
-       -5474,          -5461,          -5449,          -5436,
-       -5424,          -5411,          -5399,          -5386,
-       -5374,          -5362,          -5349,          -5337,
-       -5324,          -5312,          -5299,          -5287,
-       -5275,          -5263,          -5250,          -5238,
-       -5226,          -5213,          -5201,          -5189,
-       -5177,          -5164,          -5152,          -5140,
-       -5128,          -5115,          -5103,          -5091,
-       -5079,          -5067,          -5055,          -5043,
-       -5030,          -5018,          -5006,          -4994,
-       -4982,          -4970,          -4958,          -4946,
-       -4934,          -4922,          -4910,          -4898,
-       -4886,          -4874,          -4862,          -4850,
-       -4838,          -4826,          -4814,          -4803,
-       -4791,          -4778,          -4767,          -4755,
-       -4743,          -4731,          -4719,          -4708,
-       -4696,          -4684,          -4672,          -4660,
-       -4649,          -4637,          -4625,          -4613,
-       -4601,          -4590,          -4578,          -4566,
-       -4554,          -4543,          -4531,          -4520,
-       -4508,          -4496,          -4484,          -4473,
-       -4461,          -4449,          -4438,          -4427,
-       -4415,          -4403,          -4392,          -4380,
-       -4368,          -4357,          -4345,          -4334,
-       -4322,          -4311,          -4299,          -4288,
-       -4276,          -4265,          -4253,          -4242,
-       -4230,          -4219,          -4207,          -4196,
-       -4184,          -4173,          -4162,          -4150,
-       -4139,          -4128,          -4116,          -4105,
-       -4094,          -4082,          -4071,          -4060,
-       -4048,          -4037,          -4026,          -4014,
-       -4003,          -3992,          -3980,          -3969,
-       -3958,          -3946,          -3935,          -3924,
-       -3913,          -3901,          -3890,          -3879,
-       -3868,          -3857,          -3845,          -3834,
-       -3823,          -3812,          -3801,          -3790,
-       -3779,          -3767,          -3756,          -3745,
-       -3734,          -3723,          -3712,          -3700,
-       -3689,          -3678,          -3667,          -3656,
-       -3645,          -3634,          -3623,          -3612,
-       -3601,          -3590,          -3579,          -3568,
-       -3557,          -3545,          -3535,          -3524,
-       -3513,          -3502,          -3491,          -3480,
-       -3469,          -3458,          -3447,          -3436,
-       -3425,          -3414,          -3403,          -3392,
-       -3381,          -3370,          -3360,          -3348,
-       -3337,          -3327,          -3316,          -3305,
-       -3294,          -3283,          -3272,          -3262,
-       -3251,          -3240,          -3229,          -3218,
-       -3207,          -3197,          -3185,          -3175,
-       -3164,          -3153,          -3142,          -3132,
-       -3121,          -3110,          -3099,          -3088,
-       -3078,          -3067,          -3056,          -3045,
-       -3035,          -3024,          -3013,          -3003,
-       -2992,          -2981,          -2970,          -2960,
-       -2949,          -2938,          -2928,          -2917,
-       -2906,          -2895,          -2885,          -2874,
-       -2864,          -2853,          -2842,          -2832,
-       -2821,          -2810,          -2800,          -2789,
-       -2778,          -2768,          -2757,          -2747,
-       -2736,          -2725,          -2715,          -2704,
-       -2694,          -2683,          -2673,          -2662,
-       -2651,          -2641,          -2630,          -2620,
-       -2609,          -2599,          -2588,          -2578,
-       -2567,          -2556,          -2546,          -2535,
-       -2525,          -2515,          -2504,          -2493,
-       -2483,          -2472,          -2462,          -2451,
-       -2441,          -2431,          -2420,          -2410,
-       -2399,          -2389,          -2378,          -2367,
-       -2357,          -2347,          -2336,          -2326,
-       -2315,          -2305,          -2295,          -2284,
-       -2274,          -2263,          -2253,          -2243,
-       -2232,          -2222,          -2211,          -2201,
-       -2191,          -2180,          -2170,          -2159,
-       -2149,          -2139,          -2128,          -2118,
-       -2107,          -2097,          -2087,          -2076,
-       -2066,          -2056,          -2046,          -2035,
-       -2025,          -2014,          -2004,          -1994,
-       -1983,          -1973,          -1963,          -1953,
-       -1942,          -1932,          -1921,          -1911,
-       -1901,          -1891,          -1880,          -1870,
-       -1860,          -1849,          -1839,          -1829,
-       -1819,          -1808,          -1798,          -1788,
-       -1778,          -1767,          -1757,          -1747,
-       -1736,          -1726,          -1716,          -1706,
-       -1695,          -1685,          -1675,          -1665,
-       -1654,          -1644,          -1634,          -1624,
-       -1613,          -1603,          -1593,          -1583,
-       -1573,          -1563,          -1552,          -1542,
-       -1532,          -1522,          -1511,          -1501,
-       -1491,          -1481,          -1471,          -1461,
-       -1450,          -1440,          -1430,          -1420,
-       -1409,          -1400,          -1389,          -1379,
-       -1369,          -1359,          -1348,          -1339,
-       -1328,          -1318,          -1308,          -1298,
-       -1288,          -1278,          -1267,          -1257,
-       -1247,          -1237,          -1227,          -1217,
-       -1207,          -1196,          -1186,          -1176,
-       -1166,          -1156,          -1146,          -1135,
-       -1126,          -1115,          -1105,          -1095,
-       -1085,          -1075,          -1065,          -1055,
-       -1044,          -1034,          -1024,          -1014,
-       -1004,          -994,           -984,           -974,
-       -964,           -954,           -944,           -933,
-       -923,           -913,           -903,           -893,
-       -883,           -873,           -863,           -853,
-       -843,           -833,           -822,           -812,
-       -802,           -792,           -782,           -772,
-       -762,           -752,           -742,           -732,
-       -722,           -712,           -702,           -691,
-       -682,           -671,           -662,           -651,
-       -641,           -631,           -621,           -611,
-       -601,           -591,           -581,           -571,
-       -561,           -551,           -541,           -531,
-       -521,           -511,           -501,           -491,
-       -480,           -471,           -460,           -451,
-       -440,           -430,           -420,           -410,
-       -400,           -390,           -380,           -370,
-       -360,           -350,           -340,           -330,
-       -320,           -310,           -300,           -290,
-       -280,           -270,           -260,           -250,
-       -240,           -230,           -220,           -210,
-       -199,           -190,           -179,           -170,
-       -159,           -150,           -139,           -129,
-       -119,           -109,           -99,            -89,
-       -79,            -69,            -59,            -49,
-       -39,            -29,            -19,            -9,
-       1,              11,             21,             31,
-       41,             51,             61,             71,
-       81,             91,             101,            111,
-       121,            131,            141,            152,
-       161,            172,            181,            192,
-       202,            212,            222,            232,
-       242,            252,            262,            272,
-       282,            292,            302,            312,
-       322,            332,            342,            352,
-       362,            372,            382,            392,
-       402,            412,            422,            433,
-       442,            453,            462,            473,
-       483,            493,            503,            513,
-       523,            533,            543,            553,
-       563,            573,            583,            593,
-       603,            613,            623,            633,
-       643,            653,            664,            673,
-       684,            694,            704,            714,
-       724,            734,            744,            754,
-       764,            774,            784,            794,
-       804,            815,            825,            835,
-       845,            855,            865,            875,
-       885,            895,            905,            915,
-       925,            936,            946,            956,
-       966,            976,            986,            996,
-       1006,           1016,           1026,           1037,
-       1047,           1057,           1067,           1077,
-       1087,           1097,           1107,           1117,
-       1128,           1138,           1148,           1158,
-       1168,           1178,           1188,           1198,
-       1209,           1219,           1229,           1239,
-       1249,           1259,           1269,           1280,
-       1290,           1300,           1310,           1320,
-       1330,           1341,           1351,           1361,
-       1371,           1381,           1391,           1402,
-       1412,           1422,           1432,           1442,
-       1452,           1463,           1473,           1483,
-       1493,           1503,           1513,           1524,
-       1534,           1544,           1554,           1565,
-       1575,           1585,           1595,           1606,
-       1616,           1626,           1636,           1647,
-       1656,           1667,           1677,           1687,
-       1697,           1708,           1718,           1729,
-       1739,           1749,           1759,           1769,
-       1780,           1790,           1800,           1810,
-       1821,           1831,           1841,           1851,
-       1862,           1872,           1883,           1893,
-       1903,           1913,           1923,           1934,
-       1944,           1955,           1965,           1975,
-       1985,           1996,           2006,           2016,
-       2027,           2037,           2048,           2058,
-       2068,           2079,           2089,           2099,
-       2110,           2120,           2130,           2141,
-       2151,           2161,           2172,           2182,
-       2193,           2203,           2213,           2224,
-       2234,           2245,           2255,           2265,
-       2276,           2286,           2297,           2307,
-       2318,           2328,           2338,           2349,
-       2359,           2370,           2380,           2391,
-       2401,           2412,           2422,           2433,
-       2443,           2454,           2464,           2475,
-       2485,           2496,           2506,           2517,
-       2527,           2537,           2548,           2559,
-       2569,           2580,           2590,           2601,
-       2612,           2622,           2632,           2643,
-       2654,           2664,           2675,           2685,
-       2696,           2707,           2717,           2728,
-       2738,           2749,           2759,           2770,
-       2781,           2791,           2802,           2813,
-       2823,           2834,           2845,           2855,
-       2866,           2877,           2887,           2898,
-       2909,           2919,           2930,           2941,
-       2951,           2962,           2973,           2984,
-       2994,           3005,           3015,           3027,
-       3037,           3048,           3058,           3069,
-       3080,           3091,           3101,           3113,
-       3123,           3134,           3145,           3156,
-       3166,           3177,           3188,           3199,
-       3210,           3220,           3231,           3242,
-       3253,           3264,           3275,           3285,
-       3296,           3307,           3318,           3329,
-       3340,           3351,           3362,           3373,
-       3384,           3394,           3405,           3416,
-       3427,           3438,           3449,           3460,
-       3471,           3482,           3493,           3504,
-       3515,           3526,           3537,           3548,
-       3559,           3570,           3581,           3592,
-       3603,           3614,           3625,           3636,
-       3647,           3659,           3670,           3681,
-       3692,           3703,           3714,           3725,
-       3736,           3747,           3758,           3770,
-       3781,           3792,           3803,           3814,
-       3825,           3837,           3848,           3859,
-       3870,           3881,           3893,           3904,
-       3915,           3926,           3937,           3949,
-       3960,           3971,           3983,           3994,
-       4005,           4017,           4028,           4039,
-       4051,           4062,           4073,           4085,
-       4096,           4107,           4119,           4130,
-       4141,           4153,           4164,           4175,
-       4187,           4198,           4210,           4221,
-       4233,           4244,           4256,           4267,
-       4279,           4290,           4302,           4313,
-       4325,           4336,           4348,           4359,
-       4371,           4382,           4394,           4406,
-       4417,           4429,           4440,           4452,
-       4464,           4475,           4487,           4499,
-       4510,           4522,           4533,           4545,
-       4557,           4569,           4581,           4592,
-       4604,           4616,           4627,           4639,
-       4651,           4663,           4674,           4686,
-       4698,           4710,           4722,           4734,
-       4746,           4758,           4769,           4781,
-       4793,           4805,           4817,           4829,
-       4841,           4853,           4865,           4877,
-       4889,           4900,           4913,           4925,
-       4936,           4949,           4961,           4973,
-       4985,           4997,           5009,           5021,
-       5033,           5045,           5057,           5070,
-       5081,           5094,           5106,           5118,
-       5130,           5143,           5155,           5167,
-       5179,           5191,           5204,           5216,
-       5228,           5240,           5253,           5265,
-       5278,           5290,           5302,           5315,
-       5327,           5340,           5352,           5364,
-       5377,           5389,           5401,           5414,
-       5426,           5439,           5451,           5464,
-       5476,           5489,           5502,           5514,
-       5527,           5539,           5552,           5564,
-       5577,           5590,           5603,           5615,
-       5628,           5641,           5653,           5666,
-       5679,           5691,           5704,           5717,
-       5730,           5743,           5756,           5768,
-       5781,           5794,           5807,           5820,
-       5833,           5846,           5859,           5872,
-       5885,           5897,           5911,           5924,
-       5937,           5950,           5963,           5976,
-       5989,           6002,           6015,           6028,
-       6042,           6055,           6068,           6081,
-       6094,           6108,           6121,           6134,
-       6147,           6160,           6174,           6187,
-       6201,           6214,           6227,           6241,
-       6254,           6267,           6281,           6294,
-       6308,           6321,           6335,           6348,
-       6362,           6375,           6389,           6403,
-       6416,           6430,           6443,           6457,
-       6471,           6485,           6498,           6512,
-       6526,           6540,           6554,           6567,
-       6581,           6595,           6609,           6623,
-       6637,           6651,           6665,           6679,
-       6692,           6706,           6721,           6735,
-       6749,           6763,           6777,           6791,
-       6805,           6819,           6833,           6848,
-       6862,           6876,           6890,           6905,
-       6919,           6933,           6948,           6962,
-       6976,           6991,           7005,           7020,
-       7034,           7049,           7064,           7078,
-       7093,           7107,           7122,           7136,
-       7151,           7166,           7180,           7195,
-       7210,           7225,           7240,           7254,
-       7269,           7284,           7299,           7314,
-       7329,           7344,           7359,           7374,
-       7389,           7404,           7419,           7434,
-       7449,           7465,           7480,           7495,
-       7510,           7526,           7541,           7556,
-       7571,           7587,           7602,           7618,
-       7633,           7648,           7664,           7680,
-       7695,           7711,           7726,           7742,
-       7758,           7773,           7789,           7805,
-       7821,           7836,           7852,           7868,
-       7884,           7900,           7916,           7932,
-       7948,           7964,           7981,           7997,
-       8013,           8029,           8045,           8061,
-       8078,           8094,           8110,           8127,
-       8143,           8160,           8176,           8193,
-       8209,           8226,           8242,           8259,
-       8276,           8292,           8309,           8326,
-       8343,           8360,           8377,           8394,
-       8410,           8428,           8444,           8462,
-       8479,           8496,           8513,           8530,
-       8548,           8565,           8582,           8600,
-       8617,           8634,           8652,           8670,
-       8687,           8704,           8722,           8740,
-       8758,           8775,           8793,           8811,
-       8829,           8847,           8865,           8883,
-       8901,           8919,           8937,           8955,
-       8974,           8992,           9010,           9029,
-       9047,           9066,           9084,           9103,
-       9121,           9140,           9159,           9177,
-       9196,           9215,           9234,           9253,
-       9272,           9291,           9310,           9329,
-       9349,           9368,           9387,           9406,
-       9426,           9445,           9465,           9484,
-       9504,           9524,           9544,           9563,
-       9583,           9603,           9623,           9643,
-       9663,           9683,           9703,           9723,
-       9744,           9764,           9785,           9805,
-       9826,           9846,           9867,           9888,
-       9909,           9930,           9950,           9971,
-       9993,           10013,          10035,          10056,
-       10077,          10099,          10120,          10142,
-       10163,          10185,          10207,          10229,
-       10251,          10273,          10294,          10317,
-       10339,          10361,          10384,          10406,
-       10428,          10451,          10474,          10496,
-       10519,          10542,          10565,          10588,
-       10612,          10635,          10658,          10682,
-       10705,          10729,          10752,          10776,
-       10800,          10824,          10848,          10872,
-       10896,          10921,          10945,          10969,
-       10994,          11019,          11044,          11069,
-       11094,          11119,          11144,          11169,
-       11195,          11221,          11246,          11272,
-       11298,          11324,          11350,          11376,
-       11402,          11429,          11456,          11482,
-       11509,          11536,          11563,          11590,
-       11618,          11645,          11673,          11701,
-       11728,          11756,          11785,          11813,
-       11842,          11870,          11899,          11928,
-       11957,          11986,          12015,          12045,
-       12074,          12104,          12134,          12164,
-       12194,          12225,          12255,          12286,
-       12317,          12348,          12380,          12411,
-       12443,          12475,          12507,          12539,
-       12571,          12604,          12637,          12670,
-       12703,          12737,          12771,          12804,
-       12839,          12873,          12907,          12942,
-       12977,          13013,          13048,          13084,
-       13120,          13156,          13192,          13229,
-       13267,          13304,          13341,          13379,
-       13418,          13456,          13495,          13534,
-       13573,          13613,          13653,          13693,
-       13734,          13775,          13817,          13858,
-       13901,          13943,          13986,          14029,
-       14073,          14117,          14162,          14206,
-       14252,          14297,          14343,          14390,
-       14437,          14485,          14533,          14582,
-       14631,          14680,          14731,          14782,
-       14833,          14885,          14937,          14991,
-       15044,          15099,          15154,          15210,
-       15266,          15324,          15382,          15441,
-       15500,          15561,          15622,          15684,
-       15747,          15811,          15877,          15943,
-       16010,          16078,          16148,          16218,
-       16290,          16363,          16437,          16513,
-       16590,          16669,          16749,          16831,
-       16915,          17000,          17088,          17177,
-       17268,          17362,          17458,          17556,
-       17657,          17761,          17868,          17977,
-       18090,          18207,          18328,          18452,
-       18581,          18715,          18854,          18998,
-       19149,          19307,          19472,          19645,
-       19828,          20021,          20226,          20444,
-       20678,          20930,          21204,          21503,
-       21835,          22206,          22630,          23124,
-       23721,          24478,          25529,          27316,
-};
+static void init_crandom(struct crndstate *state, unsigned long rho)
+{
+       state->rho = rho;
+       state->last = net_random();
+}
+
+/* get_crandom - correlated random number generator
+ * Next number depends on last value.
+ * rho is scaled to avoid floating point.
+ */
+static unsigned long get_crandom(struct crndstate *state)
+{
+       u64 value, rho;
+       unsigned long answer;
+
+       if (state->rho == 0)    /* no correllation */
+               return net_random();
+
+       value = net_random();
+       rho = (u64)state->rho + 1;
+       answer = (value * ((1ull<<32) - rho) + state->last * rho) >> 32;
+       state->last = answer;
+       return answer;
+}
 
 /* tabledist - return a pseudo-randomly distributed value with mean mu and
  * std deviation sigma.  Uses table lookup to approximate the desired
  * distribution, and a uniformly-distributed pseudo-random source.
  */
-static inline int tabledist(int mu, int sigma)
+static long tabledist(unsigned long mu, long sigma, 
+                     struct crndstate *state, const struct disttable *dist)
 {
-       int x;
-       int index;
-       int sigmamod, sigmadiv;
+       long t, x;
+       unsigned long rnd;
 
        if (sigma == 0)
                return mu;
 
-       index = (net_random() & (TABLESIZE-1));
-       sigmamod = sigma%TABLEFACTOR;
-       sigmadiv = sigma/TABLEFACTOR;
-       x = sigmamod*disttable[index];
+       rnd = get_crandom(state);
 
+       /* default uniform distribution */
+       if (dist == NULL) 
+               return (rnd % (2*sigma)) - sigma + mu;
+
+       t = dist->table[rnd % dist->size];
+       x = (sigma % NETEM_DIST_SCALE) * t;
        if (x >= 0)
-               x += TABLEFACTOR/2;
+               x += NETEM_DIST_SCALE/2;
        else
-               x -= TABLEFACTOR/2;
+               x -= NETEM_DIST_SCALE/2;
 
-       x /= TABLEFACTOR;
-       x += sigmadiv*disttable[index];
-       x += mu;
-       return x;
+       return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
 }
 
-/* Enqueue packets with underlying discipline (fifo)
- * but mark them with current time first.
- */
-static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+/* Put skb in the private delayed queue. */
+static int delay_skb(struct Qdisc *sch, struct sk_buff *skb)
 {
        struct netem_sched_data *q = qdisc_priv(sch);
        struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
        psched_time_t now;
-       long delay;
+       
+       PSCHED_GET_TIME(now);
+       PSCHED_TADD2(now, tabledist(q->latency, q->jitter, 
+                                   &q->delay_cor, q->delay_dist),
+                    cb->time_to_send);
+       
+       /* Always queue at tail to keep packets in order */
+       if (likely(q->delayed.qlen < q->limit)) {
+               __skb_queue_tail(&q->delayed, skb);
+               sch->q.qlen++;
+               sch->stats.bytes += skb->len;
+               sch->stats.packets++;
+               return NET_XMIT_SUCCESS;
+       }
+
+       sch->stats.drops++;
+       kfree_skb(skb);
+       return NET_XMIT_DROP;
+}
+
+static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+       struct netem_sched_data *q = qdisc_priv(sch);
 
        pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies);
 
        /* Random packet drop 0 => none, ~0 => all */
-       if (q->loss && q->loss >= net_random()) {
+       if (q->loss && q->loss >= get_crandom(&q->loss_cor)) {
+               pr_debug("netem_enqueue: random loss\n");
                sch->stats.drops++;
                return 0;       /* lie about loss so TCP doesn't know */
        }
 
+       /* Random duplication */
+       if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) {
+               struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+
+               pr_debug("netem_enqueue: dup %p\n", skb2);
+               if (skb2)
+                       delay_skb(sch, skb2);
+       }
 
        /* If doing simple delay then gap == 0 so all packets
         * go into the delayed holding queue
@@ -633,27 +201,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        }
        
        q->counter = 0;
-       
-       PSCHED_GET_TIME(now);
-       if (q->jitter) 
-               delay = tabledist(q->latency, q->jitter);
-       else
-               delay = q->latency;
-
-       PSCHED_TADD2(now, delay, cb->time_to_send);
-       
-       /* Always queue at tail to keep packets in order */
-       if (likely(q->delayed.qlen < q->limit)) {
-               __skb_queue_tail(&q->delayed, skb);
-               sch->q.qlen++;
-               sch->stats.bytes += skb->len;
-               sch->stats.packets++;
-               return 0;
-       }
 
-       sch->stats.drops++;
-       kfree_skb(skb);
-       return NET_XMIT_DROP;
+       return delay_skb(sch, skb);
 }
 
 /* Requeue packets but don't change time stamp */
@@ -752,39 +301,97 @@ static int set_fifo_limit(struct Qdisc *q, int limit)
        return ret;
 }
 
-static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+/*
+ * Distribution data is a variable size payload containing
+ * signed 16 bit values.
+ */
+static int get_dist_table(struct Qdisc *sch, const struct rtattr *attr)
 {
        struct netem_sched_data *q = qdisc_priv(sch);
-       struct tc_netem_qopt *qopt = RTA_DATA(opt);
-       struct Qdisc *child;
-       int ret;
+       unsigned long n = RTA_PAYLOAD(attr)/sizeof(__s16);
+       const __s16 *data = RTA_DATA(attr);
+       struct disttable *d;
+       int i;
 
-       if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
+       if (n > 65536)
                return -EINVAL;
 
-       child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
-       if (!child)
+       d = kmalloc(sizeof(*d) + n*sizeof(d->table[0]), GFP_KERNEL);
+       if (!d)
+               return -ENOMEM;
+
+       d->size = n;
+       for (i = 0; i < n; i++)
+               d->table[i] = data[i];
+       
+       spin_lock_bh(&sch->dev->queue_lock);
+       d = xchg(&q->delay_dist, d);
+       spin_unlock_bh(&sch->dev->queue_lock);
+
+       kfree(d);
+       return 0;
+}
+
+static int get_correlation(struct Qdisc *sch, const struct rtattr *attr)
+{
+       struct netem_sched_data *q = qdisc_priv(sch);
+       const struct tc_netem_corr *c = RTA_DATA(attr);
+
+       if (RTA_PAYLOAD(attr) != sizeof(*c))
                return -EINVAL;
 
-       ret = set_fifo_limit(child, qopt->limit);
+       init_crandom(&q->delay_cor, c->delay_corr);
+       init_crandom(&q->loss_cor, c->loss_corr);
+       init_crandom(&q->dup_cor, c->dup_corr);
+       return 0;
+}
+
+static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+{
+       struct netem_sched_data *q = qdisc_priv(sch);
+       struct tc_netem_qopt *qopt;
+       int ret;
+       
+       if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
+               return -EINVAL;
+
+       qopt = RTA_DATA(opt);
+       ret = set_fifo_limit(q->qdisc, qopt->limit);
        if (ret) {
-               qdisc_destroy(child);
+               pr_debug("netem: can't set fifo limit\n");
                return ret;
        }
-
-       sch_tree_lock(sch);
-       if (child) {
-               child = xchg(&q->qdisc, child);
-               if (child != &noop_qdisc)
-                       qdisc_destroy(child);
        
-               q->latency = qopt->latency;
-               q->jitter = qopt->jitter;
-               q->limit = qopt->limit;
-               q->gap = qopt->gap;
-               q->loss = qopt->loss;
+       q->latency = qopt->latency;
+       q->jitter = qopt->jitter;
+       q->limit = qopt->limit;
+       q->gap = qopt->gap;
+       q->loss = qopt->loss;
+       q->duplicate = qopt->duplicate;
+
+       /* Handle nested options after initial queue options.
+        * Should have put all options in nested format but too late now.
+        */ 
+       if (RTA_PAYLOAD(opt) > sizeof(*qopt)) {
+               struct rtattr *tb[TCA_NETEM_MAX];
+               if (rtattr_parse(tb, TCA_NETEM_MAX, 
+                                RTA_DATA(opt) + sizeof(*qopt),
+                                RTA_PAYLOAD(opt) - sizeof(*qopt)))
+                       return -EINVAL;
+
+               if (tb[TCA_NETEM_CORR-1]) {
+                       ret = get_correlation(sch, tb[TCA_NETEM_CORR-1]);
+                       if (ret)
+                               return ret;
+               }
+
+               if (tb[TCA_NETEM_DELAY_DIST-1]) {
+                       ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST-1]);
+                       if (ret)
+                               return ret;
+               }
        }
-       sch_tree_unlock(sch);
+
 
        return 0;
 }
@@ -792,19 +399,29 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt)
 static int netem_init(struct Qdisc *sch, struct rtattr *opt)
 {
        struct netem_sched_data *q = qdisc_priv(sch);
+       int ret;
 
        if (!opt)
                return -EINVAL;
 
        skb_queue_head_init(&q->delayed);
-       q->qdisc = &noop_qdisc;
-
        init_timer(&q->timer);
        q->timer.function = netem_watchdog;
        q->timer.data = (unsigned long) sch;
        q->counter = 0;
 
-       return netem_change(sch, opt);
+       q->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+       if (!q->qdisc) {
+               pr_debug("netem: qdisc create failed\n");
+               return -ENOMEM;
+       }
+
+       ret = netem_change(sch, opt);
+       if (ret) {
+               pr_debug("netem: change failed\n");
+               qdisc_destroy(q->qdisc);
+       }
+       return ret;
 }
 
 static void netem_destroy(struct Qdisc *sch)
@@ -813,22 +430,31 @@ static void netem_destroy(struct Qdisc *sch)
 
        del_timer_sync(&q->timer);
        qdisc_destroy(q->qdisc);
+       kfree(q->delay_dist);
 }
 
 static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
-       struct netem_sched_data *q = qdisc_priv(sch);
+       const struct netem_sched_data *q = qdisc_priv(sch);
        unsigned char    *b = skb->tail;
+       struct rtattr *rta = (struct rtattr *) b;
        struct tc_netem_qopt qopt;
+       struct tc_netem_corr cor;
 
        qopt.latency = q->latency;
        qopt.jitter = q->jitter;
        qopt.limit = q->limit;
        qopt.loss = q->loss;
        qopt.gap = q->gap;
-
+       qopt.duplicate = q->duplicate;
        RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
 
+       cor.delay_corr = q->delay_cor.rho;
+       cor.loss_corr = q->loss_cor.rho;
+       cor.dup_corr = q->dup_cor.rho;
+       RTA_PUT(skb, TCA_NETEM_CORR, sizeof(cor), &cor);
+       rta->rta_len = skb->tail - b;
+
        return skb->len;
 
 rtattr_failure:
index f37d9cd..ac668b0 100644 (file)
@@ -372,7 +372,6 @@ static void sfq_perturbation(unsigned long arg)
        struct sfq_sched_data *q = qdisc_priv(sch);
 
        q->perturbation = net_random()&0x1F;
-       q->perturb_timer.expires = jiffies + q->perturb_period;
 
        if (q->perturb_period) {
                q->perturb_timer.expires = jiffies + q->perturb_period;
index 963e87a..dd16909 100644 (file)
@@ -31,6 +31,7 @@
 #include <net/ip.h>
 #include <net/route.h>
 #include <linux/skbuff.h>
+#include <linux/moduleparam.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 
@@ -449,7 +450,7 @@ static __init void teql_master_setup(struct net_device *dev)
 
 static LIST_HEAD(master_dev_list);
 static int max_equalizers = 1;
-MODULE_PARM(max_equalizers, "i");
+module_param(max_equalizers, int, 0);
 MODULE_PARM_DESC(max_equalizers, "Max number of link equalizers");
 
 static int __init teql_init(void)
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
new file mode 100644 (file)
index 0000000..2887de1
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ *  linux/net/sunrpc/gss_spkm3_mech.c
+ *
+ *  Copyright (c) 2003 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@umich.edu>
+ *  J. Bruce Fields <bfields@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  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 REGENTS OR CONTRIBUTORS 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/sunrpc/auth.h>
+#include <linux/in.h>
+#include <linux/sunrpc/svcauth_gss.h>
+#include <linux/sunrpc/gss_spkm3.h>
+#include <linux/sunrpc/xdr.h>
+#include <linux/crypto.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY       RPCDBG_AUTH
+#endif
+
+struct xdr_netobj gss_mech_spkm3_oid =
+   {7, "\053\006\001\005\005\001\003"};
+
+static inline int
+get_bytes(char **ptr, const char *end, void *res, int len)
+{
+       char *p, *q;
+       p = *ptr;
+       q = p + len;
+       if (q > end || q < p)
+               return -1;
+       memcpy(res, p, len);
+       *ptr = q;
+       return 0;
+}
+
+static inline int
+get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
+{
+       char *p, *q;
+       p = *ptr;
+       if (get_bytes(&p, end, &res->len, sizeof(res->len)))
+               return -1;
+       q = p + res->len;
+       if(res->len == 0)
+               goto out_nocopy;
+       if (q > end || q < p)
+               return -1;
+       if (!(res->data = kmalloc(res->len, GFP_KERNEL)))
+               return -1;
+       memcpy(res->data, p, res->len);
+out_nocopy:
+       *ptr = q;
+       return 0;
+}
+
+static inline int
+get_key(char **p, char *end, struct crypto_tfm **res, int *resalg)
+{
+       struct xdr_netobj       key = {
+               .len = 0,
+               .data = NULL,
+       };
+       int                     alg_mode,setkey = 0;
+       char                    *alg_name;
+
+       if (get_bytes(p, end, resalg, sizeof(int)))
+               goto out_err;
+       if ((get_netobj(p, end, &key)))
+               goto out_err;
+
+       switch (*resalg) {
+               case NID_des_cbc:
+                       alg_name = "des";
+                       alg_mode = CRYPTO_TFM_MODE_CBC;
+                       setkey = 1;
+                       break;
+               case NID_md5:
+                       if (key.len == 0) {
+                               dprintk("RPC: SPKM3 get_key: NID_md5 zero Key length\n");
+                       }
+                       alg_name = "md5";
+                       alg_mode = 0;
+                       setkey = 0;
+                       break;
+               case NID_cast5_cbc:
+                       dprintk("RPC: SPKM3 get_key: case cast5_cbc, UNSUPPORTED \n");
+                       goto out_err;
+                       break;
+               default:
+                       dprintk("RPC: SPKM3 get_key: unsupported algorithm %d", *resalg);
+                       goto out_err_free_key;
+       }
+       if (!(*res = crypto_alloc_tfm(alg_name, alg_mode)))
+               goto out_err_free_key;
+       if (setkey) {
+               if (crypto_cipher_setkey(*res, key.data, key.len))
+                       goto out_err_free_tfm;
+       }
+
+       if(key.len > 0)
+               kfree(key.data);
+       return 0;
+
+out_err_free_tfm:
+       crypto_free_tfm(*res);
+out_err_free_key:
+       if(key.len > 0)
+               kfree(key.data);
+out_err:
+       return -1;
+}
+
+static u32
+gss_import_sec_context_spkm3(struct xdr_netobj *inbuf,
+                               struct gss_ctx *ctx_id)
+{
+       char    *p = inbuf->data;
+       char    *end = inbuf->data + inbuf->len;
+       struct  spkm3_ctx *ctx;
+
+       if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL)))
+               goto out_err;
+       memset(ctx, 0, sizeof(*ctx));
+
+       if (get_netobj(&p, end, &ctx->ctx_id))
+               goto out_err_free_ctx;
+
+       if (get_bytes(&p, end, &ctx->qop, sizeof(ctx->qop)))
+               goto out_err_free_ctx_id;
+
+       if (get_netobj(&p, end, &ctx->mech_used))
+               goto out_err_free_mech;
+
+       if (get_bytes(&p, end, &ctx->ret_flags, sizeof(ctx->ret_flags)))
+               goto out_err_free_mech;
+
+       if (get_bytes(&p, end, &ctx->req_flags, sizeof(ctx->req_flags)))
+               goto out_err_free_mech;
+
+       if (get_netobj(&p, end, &ctx->share_key))
+               goto out_err_free_s_key;
+
+       if (get_key(&p, end, &ctx->derived_conf_key, &ctx->conf_alg)) {
+               dprintk("RPC: SPKM3 confidentiality key will be NULL\n");
+       }
+
+       if (get_key(&p, end, &ctx->derived_integ_key, &ctx->intg_alg)) {
+               dprintk("RPC: SPKM3 integrity key will be NULL\n");
+       }
+
+       if (get_bytes(&p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)))
+               goto out_err_free_s_key;
+
+       if (get_bytes(&p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)))
+               goto out_err_free_s_key;
+
+       if (p != end)
+               goto out_err_free_s_key;
+
+       ctx_id->internal_ctx_id = ctx;
+
+       dprintk("Succesfully imported new spkm context.\n");
+       return 0;
+
+out_err_free_s_key:
+       kfree(ctx->share_key.data);
+out_err_free_mech:
+       kfree(ctx->mech_used.data);
+out_err_free_ctx_id:
+       kfree(ctx->ctx_id.data);
+out_err_free_ctx:
+       kfree(ctx);
+out_err:
+       return GSS_S_FAILURE;
+}
+
+void
+gss_delete_sec_context_spkm3(void *internal_ctx) {
+       struct spkm3_ctx *sctx = internal_ctx;
+
+       if(sctx->derived_integ_key)
+               crypto_free_tfm(sctx->derived_integ_key);
+       if(sctx->derived_conf_key)
+               crypto_free_tfm(sctx->derived_conf_key);
+       if(sctx->share_key.data)
+               kfree(sctx->share_key.data);
+       if(sctx->mech_used.data)
+               kfree(sctx->mech_used.data);
+       kfree(sctx);
+}
+
+u32
+gss_verify_mic_spkm3(struct gss_ctx            *ctx,
+                       struct xdr_buf          *signbuf,
+                       struct xdr_netobj       *checksum,
+                       u32             *qstate) {
+       u32 maj_stat = 0;
+       int qop_state = 0;
+       struct spkm3_ctx *sctx = ctx->internal_ctx_id;
+
+       dprintk("RPC: gss_verify_mic_spkm3 calling spkm3_read_token\n");
+       maj_stat = spkm3_read_token(sctx, checksum, signbuf, &qop_state,
+                                  SPKM_MIC_TOK);
+
+       if (!maj_stat && qop_state)
+           *qstate = qop_state;
+
+       dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat);
+       return maj_stat;
+}
+
+u32
+gss_get_mic_spkm3(struct gss_ctx       *ctx,
+                    u32                qop,
+                    struct xdr_buf     *message_buffer,
+                    struct xdr_netobj  *message_token) {
+       u32 err = 0;
+       struct spkm3_ctx *sctx = ctx->internal_ctx_id;
+
+       dprintk("RPC: gss_get_mic_spkm3\n");
+
+       err = spkm3_make_token(sctx, qop, message_buffer,
+                             message_token, SPKM_MIC_TOK);
+       return err;
+}
+
+static struct gss_api_ops gss_spkm3_ops = {
+       .gss_import_sec_context = gss_import_sec_context_spkm3,
+       .gss_get_mic            = gss_get_mic_spkm3,
+       .gss_verify_mic         = gss_verify_mic_spkm3,
+       .gss_delete_sec_context = gss_delete_sec_context_spkm3,
+};
+
+static struct pf_desc gss_spkm3_pfs[] = {
+       {RPC_AUTH_GSS_SPKM, 0, RPC_GSS_SVC_NONE, "spkm3"},
+       {RPC_AUTH_GSS_SPKMI, 0, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
+};
+
+static struct gss_api_mech gss_spkm3_mech = {
+       .gm_name        = "spkm3",
+       .gm_owner       = THIS_MODULE,
+       .gm_ops         = &gss_spkm3_ops,
+       .gm_pf_num      = ARRAY_SIZE(gss_spkm3_pfs),
+       .gm_pfs         = gss_spkm3_pfs,
+};
+
+static int __init init_spkm3_module(void)
+{
+       int status;
+
+       status = gss_mech_register(&gss_spkm3_mech);
+       if (status)
+               printk("Failed to register spkm3 gss mechanism!\n");
+       return 0;
+}
+
+static void __exit cleanup_spkm3_module(void)
+{
+       gss_mech_unregister(&gss_spkm3_mech);
+}
+
+MODULE_LICENSE("GPL");
+module_init(init_spkm3_module);
+module_exit(cleanup_spkm3_module);
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
new file mode 100644 (file)
index 0000000..2533986
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  linux/net/sunrpc/gss_spkm3_seal.c
+ *
+ *  Copyright (c) 2003 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  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 REGENTS OR CONTRIBUTORS 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.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/sunrpc/gss_spkm3.h>
+#include <linux/random.h>
+#include <linux/crypto.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY        RPCDBG_AUTH
+#endif
+
+/*
+ * spkm3_make_token()
+ *
+ * Only SPKM_MIC_TOK with md5 intg-alg is supported
+ */
+
+u32
+spkm3_make_token(struct spkm3_ctx *ctx, int qop_req,
+                  struct xdr_buf * text, struct xdr_netobj * token,
+                  int toktype)
+{
+       s32                     checksum_type;
+       char                    tokhdrbuf[25];
+       struct xdr_netobj       md5cksum = {.len = 0, .data = NULL};
+       struct xdr_netobj       mic_hdr = {.len = 0, .data = tokhdrbuf};
+       int                     tmsglen, tokenlen = 0;
+       unsigned char           *ptr;
+       s32                     now;
+       int                     ctxelen = 0, ctxzbit = 0;
+       int                     md5elen = 0, md5zbit = 0;
+
+       dprintk("RPC: spkm3_make_token\n");
+
+       now = jiffies;
+       if (qop_req != 0)
+               goto out_err;
+
+       if (ctx->ctx_id.len != 16) {
+               dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n",
+                       ctx->ctx_id.len);
+               goto out_err;
+       }
+               
+       switch (ctx->intg_alg) {
+               case NID_md5:
+                       checksum_type = CKSUMTYPE_RSA_MD5;
+                       break;
+               default:
+                       dprintk("RPC: gss_spkm3_seal: ctx->signalg %d not"
+                               " supported\n", ctx->intg_alg);
+                       goto out_err;
+       }
+       /* XXX since we don't support WRAP, perhaps we don't care... */
+       if (ctx->conf_alg != NID_cast5_cbc) {
+               dprintk("RPC: gss_spkm3_seal: ctx->sealalg %d not supported\n",
+                       ctx->conf_alg);
+               goto out_err;
+       }
+
+       if (toktype == SPKM_MIC_TOK) {
+               tmsglen = 0;
+               /* Calculate checksum over the mic-header */
+               asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit);
+               spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data,
+                                        ctxelen, ctxzbit);
+
+               if (make_checksum(checksum_type, mic_hdr.data, mic_hdr.len, 
+                                            text, &md5cksum))
+                       goto out_err;
+
+               asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit);
+               tokenlen = 10 + ctxelen + 1 + 2 + md5elen + 1;
+
+               /* Create token header using generic routines */
+               token->len = g_token_size(&ctx->mech_used, tokenlen + tmsglen);
+
+               ptr = token->data;
+               g_make_token_header(&ctx->mech_used, tokenlen + tmsglen, &ptr);
+
+               spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit);
+       } else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */
+               dprintk("RPC: gss_spkm3_seal: SPKM_WRAP_TOK not supported\n");
+               goto out_err;
+       }
+       kfree(md5cksum.data);
+
+       /* XXX need to implement sequence numbers, and ctx->expired */
+
+       return  GSS_S_COMPLETE;
+out_err:
+       if (md5cksum.data) 
+               kfree(md5cksum.data);
+       token->data = NULL;
+       token->len = 0;
+       return GSS_S_FAILURE;
+}
diff --git a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c
new file mode 100644 (file)
index 0000000..46c08a0
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ *  linux/net/sunrpc/gss_spkm3_token.c
+ *
+ *  Copyright (c) 2003 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  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 REGENTS OR CONTRIBUTORS 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.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/sunrpc/gss_spkm3.h>
+#include <linux/random.h>
+#include <linux/crypto.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY        RPCDBG_AUTH
+#endif
+
+/*
+ * asn1_bitstring_len()
+ *
+ * calculate the asn1 bitstring length of the xdr_netobject
+ */
+void
+asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits)
+{
+       int i, zbit = 0,elen = in->len;
+       char *ptr;
+
+       ptr = &in->data[in->len -1];
+
+       /* count trailing 0's */
+       for(i = in->len; i > 0; i--) {
+               if (*ptr == 0) { 
+                       ptr--;
+                       elen--;
+               } else
+                       break;
+       }
+
+       /* count number of 0 bits in final octet */
+       ptr = &in->data[elen - 1];
+       for(i = 0; i < 8; i++) {
+               short mask = 0x01;
+
+               if (!((mask << i) & *ptr))
+                       zbit++;
+               else
+                       break;
+       }
+       *enclen = elen;
+       *zerobits = zbit;
+}
+
+/*
+ * decode_asn1_bitstring()
+ * 
+ * decode a bitstring into a buffer of the expected length.
+ * enclen = bit string length
+ * explen = expected length (define in rfc)
+ */
+int
+decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, int explen)
+{
+       if (!(out->data = kmalloc(explen,GFP_KERNEL)))
+               return 0;
+       out->len = explen;
+       memset(out->data, 0, explen);
+       memcpy(out->data, in, enclen);
+       return 1;
+}
+
+/* 
+ * SPKMInnerContextToken choice SPKM_MIC asn1 token layout
+ * 
+ * contextid is always 16 bytes plain data. max asn1 bitstring len = 17.
+ *
+ * tokenlen = pos[0] to end of token (max pos[45] with MD5 cksum)
+ *
+ * pos  value
+ * ----------
+ * [0] a4  SPKM-MIC tag
+ * [1] ??  innertoken length  (max 44) 
+ * 
+ * 
+ * tok_hdr piece of checksum data starts here 
+ *
+ * the maximum mic-header len = 9 + 17 = 26 
+ *     mic-header
+ *     ----------
+ * [2] 30      SEQUENCE tag  
+ * [3] ??      mic-header length: (max 23) = TokenID + ContextID 
+ *
+ *             TokenID  - all fields constant and can be hardcoded
+ *             -------
+ * [4]   02    Type 2
+ * [5]   02    Length 2 
+ * [6][7] 01 01        TokenID (SPKM_MIC_TOK)
+ *
+ *             ContextID  - encoded length not constant, calculated
+ *             ---------
+ * [8] 03      Type 3
+ * [9] ??      encoded length
+ * [10]        ??      ctxzbit
+ * [11]                contextid
+ *
+ * mic_header piece of checksum data ends here. 
+ *
+ *     int-cksum - encoded length not constant, calculated
+ *     ---------
+ * [??]        03      Type 3
+ * [??]        ??      encoded length 
+ * [??]        ??      md5zbit         
+ * [??]                int-cksum (NID_md5 = 16)
+ *
+ * maximum SPKM-MIC innercontext token length = 
+ *      10 + encoded contextid_size(17 max) + 2 + encoded  
+ *       cksum_size (17 maxfor NID_md5) = 46
+ */
+
+/*
+ * spkm3_mic_header()
+ *
+ * Prepare the SPKM_MIC_TOK mic-header for check-sum calculation
+ * elen: 16 byte context id asn1 bitstring encoded length
+ */
+void
+spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, unsigned char *ctxdata, int elen, int zbit)
+{
+       char *hptr = *hdrbuf;
+       char *top = *hdrbuf;
+
+       *(u8 *)hptr++ = 0x30;
+       *(u8 *)hptr++ = elen + 7;  /* on the wire header length */
+
+       /* tokenid */
+       *(u8 *)hptr++ = 0x02;
+       *(u8 *)hptr++ = 0x02;
+       *(u8 *)hptr++ = 0x01;
+       *(u8 *)hptr++ = 0x01;
+
+       /* coniextid */
+       *(u8 *)hptr++ = 0x03;
+       *(u8 *)hptr++ = elen + 1; /* add 1 to include zbit */
+       *(u8 *)hptr++ = zbit;
+       memcpy(hptr, ctxdata, elen);
+       hptr += elen;
+       *hdrlen = hptr - top; 
+}
+               
+/* 
+ * spkm3_mic_innercontext_token()
+ *
+ * *tokp points to the beginning of the SPKM_MIC token  described 
+ * in rfc 2025, section 3.2.1: 
+ *
+ */
+void
+spkm3_make_mic_token(unsigned char **tokp, int toklen, struct xdr_netobj *mic_hdr, struct xdr_netobj *md5cksum, int md5elen, int md5zbit)
+{
+       unsigned char *ict = *tokp;
+
+       *(u8 *)ict++ = 0xa4;
+       *(u8 *)ict++ = toklen - 2; 
+       memcpy(ict, mic_hdr->data, mic_hdr->len);
+       ict += mic_hdr->len;
+
+       *(u8 *)ict++ = 0x03;
+       *(u8 *)ict++ = md5elen + 1; /* add 1 to include zbit */
+       *(u8 *)ict++ = md5zbit;
+       memcpy(ict, md5cksum->data, md5elen);
+}
+
+u32
+spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, unsigned char **cksum)
+{
+       struct xdr_netobj       spkm3_ctx_id = {.len =0, .data = NULL};
+       unsigned char           *ptr = *tokp;
+       int                     ctxelen;
+       u32                     ret = GSS_S_DEFECTIVE_TOKEN;
+
+       /* spkm3 innercontext token preamble */
+       if ((ptr[0] != 0xa4) || (ptr[2] != 0x30)) {
+               dprintk("RPC: BAD SPKM ictoken preamble\n"); 
+               goto out;
+       }
+
+       *mic_hdrlen = ptr[3];
+
+       /* token type */
+       if ((ptr[4] != 0x02) || (ptr[5] != 0x02)) {
+               dprintk("RPC: BAD asn1 SPKM3 token type\n");
+               goto out;
+       }
+
+       /* only support SPKM_MIC_TOK */
+       if((ptr[6] != 0x01) || (ptr[7] != 0x01)) {
+               dprintk("RPC: ERROR unsupported SPKM3 token \n");
+               goto out;
+       }
+
+       /* contextid */
+       if (ptr[8] != 0x03) {
+               dprintk("RPC: BAD SPKM3 asn1 context-id type\n");
+               goto out;
+       }
+
+       ctxelen = ptr[9];
+       if (ctxelen > 17) {  /* length includes asn1 zbit octet */
+               dprintk("RPC: BAD SPKM3 contextid len %d\n", ctxelen);
+               goto out;
+       }
+
+       /* ignore ptr[10] */
+
+       if(!decode_asn1_bitstring(&spkm3_ctx_id, &ptr[11], ctxelen - 1, 16))
+               goto out;
+
+       /*
+       * in the current implementation: the optional int-alg is not present 
+       * so the default int-alg (md5) is used the optional snd-seq field is 
+       * also not present 
+       */
+
+       if (*mic_hdrlen != 6 + ctxelen) {
+               dprintk("RPC: BAD SPKM_ MIC_TOK header len %d: we only support default int-alg (should be absent) and do not support snd-seq\n", *mic_hdrlen);
+               goto out;
+       }
+       /* checksum */
+        *cksum = (&ptr[10] + ctxelen); /* ctxelen includes ptr[10] */
+
+       ret = GSS_S_COMPLETE;
+out:
+       if (spkm3_ctx_id.data)
+               kfree(spkm3_ctx_id.data);
+       return ret;
+}
+
diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
new file mode 100644 (file)
index 0000000..65ce81b
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *  linux/net/sunrpc/gss_spkm3_unseal.c
+ *
+ *  Copyright (c) 2003 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  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 REGENTS OR CONTRIBUTORS 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.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/sunrpc/gss_spkm3.h>
+#include <linux/crypto.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY        RPCDBG_AUTH
+#endif
+
+/*
+ * spkm3_read_token()
+ * 
+ * only SPKM_MIC_TOK with md5 intg-alg is supported
+ */
+u32
+spkm3_read_token(struct spkm3_ctx *ctx,
+               struct xdr_netobj *read_token,    /* checksum */
+               struct xdr_buf *message_buffer, /* signbuf */
+               int *qop_state, int toktype)
+{
+       s32                     code;
+       struct xdr_netobj       wire_cksum = {.len =0, .data = NULL};
+       struct xdr_netobj       md5cksum = {.len = 0, .data = NULL};
+       unsigned char           *ptr = (unsigned char *)read_token->data;
+       unsigned char           *cksum;
+       int                     bodysize, md5elen;
+       int                     mic_hdrlen;
+       u32                     ret = GSS_S_DEFECTIVE_TOKEN;
+
+       dprintk("RPC: spkm3_read_token read_token->len %d\n", read_token->len);
+
+       if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used,
+                                       &bodysize, &ptr, read_token->len))
+               goto out;
+
+       /* decode the token */
+
+       if (toktype == SPKM_MIC_TOK) {
+
+               if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum))) 
+                       goto out;
+
+               if (*cksum++ != 0x03) {
+                       dprintk("RPC: spkm3_read_token BAD checksum type\n");
+                       goto out;
+               }
+               md5elen = *cksum++; 
+               cksum++;        /* move past the zbit */
+       
+               if(!decode_asn1_bitstring(&wire_cksum, cksum, md5elen - 1, 16))
+                       goto out;
+
+               /* HARD CODED FOR MD5 */
+
+               /* compute the checksum of the message.
+               *  ptr + 2 = start of header piece of checksum
+               *  mic_hdrlen + 2 = length of header piece of checksum
+               */
+               ret = GSS_S_DEFECTIVE_TOKEN;
+               code = make_checksum(CKSUMTYPE_RSA_MD5, ptr + 2, 
+                                       mic_hdrlen + 2, 
+                                       message_buffer, &md5cksum);
+
+               if (code)
+                       goto out;
+
+               dprintk("RPC: spkm3_read_token: digest wire_cksum.len %d:\n", 
+                       wire_cksum.len);
+               dprintk("          md5cksum.data\n");
+               print_hexl((u32 *) md5cksum.data, 16, 0);
+               dprintk("          cksum.data:\n");
+               print_hexl((u32 *) wire_cksum.data, wire_cksum.len, 0);
+
+               ret = GSS_S_BAD_SIG;
+               code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len);
+               if (code)
+                       goto out;
+
+       } else { 
+               dprintk("RPC: BAD or UNSUPPORTED SPKM3 token type: %d\n",toktype);
+               goto out;
+       }
+
+       /* XXX: need to add expiration and sequencing */
+       ret = GSS_S_COMPLETE;
+out:
+       if (md5cksum.data) 
+               kfree(md5cksum.data);
+       if (wire_cksum.data) 
+               kfree(wire_cksum.data);
+       return ret;
+}
index ae45a76..aa2205a 100644 (file)
@@ -698,7 +698,7 @@ __rpc_execute(struct rpc_task *task)
                if (current->pid == rpciod_pid)
                        printk(KERN_ERR "RPC: rpciod waiting on sync task!\n");
 
-               if (!task->tk_client->cl_intr) {
+               if (RPC_TASK_UNINTERRUPTIBLE(task)) {
                        __wait_event(task->tk_wait, !RPC_IS_SLEEPING(task));
                } else {
                        __wait_event_interruptible(task->tk_wait, !RPC_IS_SLEEPING(task), status);
@@ -884,6 +884,8 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action call
                atomic_inc(&clnt->cl_users);
                if (clnt->cl_softrtry)
                        task->tk_flags |= RPC_TASK_SOFT;
+               if (!clnt->cl_intr)
+                       task->tk_flags |= RPC_TASK_NOINTR;
        }
 
 #ifdef RPC_DEBUG
index b6ef777..51f0392 100644 (file)
@@ -89,6 +89,7 @@ EXPORT_SYMBOL(svc_makesock);
 EXPORT_SYMBOL(svc_reserve);
 EXPORT_SYMBOL(svc_auth_register);
 EXPORT_SYMBOL(auth_domain_lookup);
+EXPORT_SYMBOL(svc_authenticate);
 
 /* RPC statistics */
 #ifdef CONFIG_PROC_FS
index db65a24..8c5b051 100644 (file)
@@ -263,6 +263,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
        u32                     *statp;
        u32                     dir, prog, vers, proc,
                                auth_stat, rpc_stat;
+       int                     auth_res;
 
        rpc_stat = rpc_success;
 
@@ -304,12 +305,17 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
        rqstp->rq_vers = vers = ntohl(svc_getu32(argv));        /* version number */
        rqstp->rq_proc = proc = ntohl(svc_getu32(argv));        /* procedure number */
 
+       progp = serv->sv_program;
        /*
         * Decode auth data, and add verifier to reply buffer.
         * We do this before anything else in order to get a decent
         * auth verifier.
         */
-       switch (svc_authenticate(rqstp, &auth_stat)) {
+       if (progp->pg_authenticate != NULL)
+               auth_res = progp->pg_authenticate(rqstp, &auth_stat);
+       else
+               auth_res = svc_authenticate(rqstp, &auth_stat);
+       switch (auth_res) {
        case SVC_OK:
                break;
        case SVC_GARBAGE:
@@ -326,7 +332,6 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
                goto sendit;
        }
                
-       progp = serv->sv_program;
        if (prog != progp->pg_prog)
                goto err_bad_prog;
 
index 54ea896..d9f09e6 100644 (file)
@@ -156,25 +156,49 @@ static inline int auth_domain_match(struct auth_domain *tmp, struct auth_domain
 {
        return strcmp(tmp->name, item->name) == 0;
 }
-DefineCacheLookup(struct auth_domain,
-                 h,
-                 auth_domain_lookup,
-                 (struct auth_domain *item, int set),
-                 /* no setup */,
-                 &auth_domain_cache,
-                 auth_domain_hash(item),
-                 auth_domain_match(tmp, item),
-                 kfree(new); if(!set) {
-                       if (new)
-                               write_unlock(&auth_domain_cache.hash_lock);
-                       else
-                               read_unlock(&auth_domain_cache.hash_lock);
-                       return NULL;
-                 }
-                 new=item; atomic_inc(&new->h.refcnt),
-                 /* no update */,
-                 0 /* no inplace updates */
-                 )
+
+struct auth_domain *
+auth_domain_lookup(struct auth_domain *item, int set)
+{
+       struct auth_domain *tmp = NULL;
+       struct cache_head **hp, **head;
+       head = &auth_domain_cache.hash_table[auth_domain_hash(item)];
+
+       if (set)
+               write_lock(&auth_domain_cache.hash_lock);
+       else
+               read_lock(&auth_domain_cache.hash_lock);
+       for (hp=head; *hp != NULL; hp = &tmp->h.next) {
+               tmp = container_of(*hp, struct auth_domain, h);
+               if (!auth_domain_match(tmp, item))
+                       continue;
+               cache_get(&tmp->h);
+               if (!set)
+                       goto out_noset;
+               *hp = tmp->h.next;
+               tmp->h.next = NULL;
+               clear_bit(CACHE_HASHED, &tmp->h.flags);
+               auth_domain_drop(&tmp->h, &auth_domain_cache);
+               goto out_set;
+       }
+       /* Didn't find anything */
+       if (!set)
+               goto out_nada;
+       auth_domain_cache.entries++;
+out_set:
+       set_bit(CACHE_HASHED, &item->h.flags);
+       item->h.next = *head;
+       *head = &item->h;
+       write_unlock(&auth_domain_cache.hash_lock);
+       cache_fresh(&auth_domain_cache, &item->h, item->h.expiry_time);
+       cache_get(&item->h);
+       return item;
+out_nada:
+       tmp = NULL;
+out_noset:
+       read_unlock(&auth_domain_cache.hash_lock);
+       return tmp;
+}
 
 struct auth_domain *auth_domain_find(char *name)
 {
index 6d98c3b..b370aad 100644 (file)
@@ -55,12 +55,10 @@ struct auth_domain *unix_domain_find(char *name)
        if (new == NULL)
                return NULL;
        cache_init(&new->h.h);
-       atomic_inc(&new->h.h.refcnt);
        new->h.name = strdup(name);
        new->h.flavour = RPC_AUTH_UNIX;
        new->addr_changes = 0;
        new->h.h.expiry_time = NEVER;
-       new->h.h.flags = 0;
 
        rv = auth_domain_lookup(&new->h, 2);
        if (rv == &new->h) {
@@ -92,7 +90,7 @@ static void svcauth_unix_domain_release(struct auth_domain *dom)
 
 struct ip_map {
        struct cache_head       h;
-       char                    *m_class; /* e.g. "nfsd" */
+       char                    m_class[8]; /* e.g. "nfsd" */
        struct in_addr          m_addr;
        struct unix_domain      *m_client;
        int                     m_add_change;
@@ -122,8 +120,7 @@ static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp)
 }
 static inline void ip_map_init(struct ip_map *new, struct ip_map *item)
 {
-       new->m_class = item->m_class;
-       item->m_class = NULL;
+       strcpy(new->m_class, item->m_class);
        new->m_addr.s_addr = item->m_addr.s_addr;
 }
 static inline void ip_map_update(struct ip_map *new, struct ip_map *item)
@@ -172,6 +169,8 @@ static int ip_map_parse(struct cache_detail *cd,
        /* class */
        len = qword_get(&mesg, class, 50);
        if (len <= 0) return -EINVAL;
+       if (len >= sizeof(ipm.m_class))
+               return -EINVAL;
 
        /* ip address */
        len = qword_get(&mesg, buf, 50);
@@ -195,9 +194,7 @@ static int ip_map_parse(struct cache_detail *cd,
        } else
                dom = NULL;
 
-       ipm.m_class = strdup(class);
-       if (ipm.m_class == NULL)
-               return -ENOMEM;
+       strcpy(ipm.m_class, class);
        ipm.m_addr.s_addr =
                htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
        ipm.h.flags = 0;
@@ -213,7 +210,6 @@ static int ip_map_parse(struct cache_detail *cd,
                ip_map_put(&ipmp->h, &ip_map_cache);
        if (dom)
                auth_domain_put(dom);
-       if (ipm.m_class) kfree(ipm.m_class);
        if (!ipmp)
                return -ENOMEM;
        cache_flush();
@@ -273,9 +269,7 @@ int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
        if (dom->flavour != RPC_AUTH_UNIX)
                return -EINVAL;
        udom = container_of(dom, struct unix_domain, h);
-       ip.m_class = strdup("nfsd");
-       if (!ip.m_class)
-               return -ENOMEM;
+       strcpy(ip.m_class, "nfsd");
        ip.m_addr = addr;
        ip.m_client = udom;
        ip.m_add_change = udom->addr_changes+1;
@@ -283,7 +277,7 @@ int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
        ip.h.expiry_time = NEVER;
        
        ipmp = ip_map_lookup(&ip, 1);
-       if (ip.m_class) kfree(ip.m_class);
+
        if (ipmp) {
                ip_map_put(&ipmp->h, &ip_map_cache);
                return 0;
@@ -307,7 +301,7 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr)
        struct ip_map key, *ipm;
        struct auth_domain *rv;
 
-       key.m_class = "nfsd";
+       strcpy(key.m_class, "nfsd");
        key.m_addr = addr;
 
        ipm = ip_map_lookup(&key, 0);
@@ -318,7 +312,8 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr)
                return NULL;
 
        if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
-               set_bit(CACHE_NEGATIVE, &ipm->h.flags);
+               if (test_and_set_bit(CACHE_NEGATIVE, &ipm->h.flags) == 0)
+                       auth_domain_put(&ipm->m_client->h);
                rv = NULL;
        } else {
                rv = &ipm->m_client->h;
@@ -368,7 +363,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
        svc_putu32(resv, RPC_AUTH_NULL);
        svc_putu32(resv, 0);
 
-       key.m_class = rqstp->rq_server->sv_program->pg_class;
+       strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
        key.m_addr = rqstp->rq_addr.sin_addr;
 
        ipm = ip_map_lookup(&key, 0);
@@ -405,6 +400,9 @@ svcauth_null_release(struct svc_rqst *rqstp)
        if (rqstp->rq_client)
                auth_domain_put(rqstp->rq_client);
        rqstp->rq_client = NULL;
+       if (rqstp->rq_cred.cr_group_info)
+               put_group_info(rqstp->rq_cred.cr_group_info);
+       rqstp->rq_cred.cr_group_info = NULL;
 
        return 0; /* don't drop */
 }
@@ -461,7 +459,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
        }
 
 
-       key.m_class = rqstp->rq_server->sv_program->pg_class;
+       strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
        key.m_addr = rqstp->rq_addr.sin_addr;
 
 
index 008ac6c..672b008 100644 (file)
@@ -14,6 +14,18 @@ include $(obj)/Makefile
 
 include scripts/Makefile.lib
 
+ifdef host-progs
+ifneq ($(hostprogs-y),$(host-progs))
+$(warning kbuild: $(obj)/Makefile - Usage of host-progs is deprecated. Please replace with hostprogs-y!)
+hostprogs-y += $(host-progs)
+endif
+endif
+
+# Do not include host rules unles needed
+ifneq ($(hostprogs-y)$(hostprogs-m),)
+include scripts/Makefile.host
+endif
+
 ifneq ($(KBUILD_SRC),)
 # Create output directory if not already present
 _dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
@@ -71,8 +83,13 @@ __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
 
 # Linus' kernel sanity checking tool
 ifneq ($(KBUILD_CHECKSRC),0)
-quiet_cmd_checksrc = CHECK   $<
-      cmd_checksrc = $(CHECK) $(c_flags) $< ;
+  ifeq ($(KBUILD_CHECKSRC),2)
+    quiet_cmd_force_checksrc = CHECK   $<
+          cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
+  else
+      quiet_cmd_checksrc     = CHECK   $<
+            cmd_checksrc     = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
+  endif
 endif
 
 
@@ -143,9 +160,7 @@ else
 
 cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
 cmd_modversions =                                                      \
-       if ! $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then   \
-               mv $(@D)/.tmp_$(@F) $@;                                 \
-       else                                                            \
+       if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then     \
                $(CPP) -D__GENKSYMS__ $(c_flags) $<                     \
                | $(GENKSYMS)                                           \
                > $(@D)/.tmp_$(@F:.o=.ver);                             \
@@ -153,6 +168,8 @@ cmd_modversions =                                                   \
                $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F)              \
                        -T $(@D)/.tmp_$(@F:.o=.ver);                    \
                rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver);        \
+       else                                                            \
+               mv $(@D)/.tmp_$(@F) $@;                                 \
        fi;
 endif
 
@@ -170,11 +187,13 @@ endef
 # Built-in and composite module parts
 
 %.o: %.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
+       $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
        @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
 
@@ -209,6 +228,14 @@ cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 targets += $(real-objs-y) $(real-objs-m) $(lib-y)
 targets += $(extra-y) $(MAKECMDGOALS) $(always)
 
+# Linker scripts preprocessor (.lds.S -> .lds)
+# ---------------------------------------------------------------------------
+quiet_cmd_cpp_lds_S = LDS     $@
+      cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $<
+
+%.lds: %.lds.S FORCE
+       $(call if_changed_dep,cpp_lds_S)
+
 # Build the compiled-in targets
 # ---------------------------------------------------------------------------
 
@@ -275,90 +302,6 @@ $(multi-used-m) : %.o: $(multi-objs-m) FORCE
 
 targets += $(multi-used-y) $(multi-used-m)
 
-# Compile programs on the host
-# ===========================================================================
-# host-progs := bin2hex
-# Will compile bin2hex.c and create an executable named bin2hex
-#
-# host-progs    := lxdialog
-# lxdialog-objs := checklist.o lxdialog.o
-# Will compile lxdialog.c and checklist.c, and then link the executable
-# lxdialog, based on checklist.o and lxdialog.o
-#
-# host-progs      := qconf
-# qconf-cxxobjs   := qconf.o
-# qconf-objs      := menu.o
-# Will compile qconf as a C++ program, and menu as a C program.
-# They are linked as C++ code to the executable qconf
-
-# host-progs := conf
-# conf-objs  := conf.o libkconfig.so
-# libkconfig-objs := expr.o type.o
-# Will create a shared library named libkconfig.so that consist of
-# expr.o and type.o (they are both compiled as C code and the object file
-# are made as position independent code).
-# conf.c is compiled as a c program, and conf.o is linked together with
-# libkconfig.so as the executable conf.
-# Note: Shared libraries consisting of C++ files are not supported  
-#
-
-# Create executable from a single .c file
-# host-csingle -> Executable
-quiet_cmd_host-csingle         = HOSTCC  $@
-      cmd_host-csingle = $(HOSTCC) $(hostc_flags) $(HOST_LOADLIBES) -o $@ $<
-$(host-csingle): %: %.c FORCE
-       $(call if_changed_dep,host-csingle)
-
-# Link an executable based on list of .o files, all plain c
-# host-cmulti -> executable
-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
-       $(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
-       $(call if_changed_dep,host-cobjs)
-
-# Link an executable based on list of .o files, a mixture of .c and .cc
-# host-cxxmulti -> executable
-quiet_cmd_host-cxxmulti        = HOSTLD  $@
-      cmd_host-cxxmulti        = $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \
-                         $(foreach o,objs cxxobjs,\
-                         $(addprefix $(obj)/,$($(@F)-$(o)))) \
-                         $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-$(host-cxxmulti): %: $(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
-       $(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
-       $(call if_changed_dep,host-cshobjs)
-
-# Link a shared library, based on position independent .o files
-# *.o -> .so shared library (host-cshlib)
-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
-       $(call if_changed,host-cshlib)
-
-targets += $(host-csingle)  $(host-cmulti) $(host-cobjs)\
-          $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) 
 
 # Descending
 # ---------------------------------------------------------------------------
index 7277dd2..b02ab1f 100644 (file)
@@ -29,21 +29,49 @@ subdir-ymn      := $(sort $(subdir-ym) $(subdir-n) $(subdir-))
 # Add subdir path
 
 subdir-ymn     := $(addprefix $(obj)/,$(subdir-ymn))
-__clean-files  := $(wildcard $(addprefix $(obj)/, \
-                  $(extra-y) $(EXTRA_TARGETS) $(always) $(host-progs) \
-                  $(targets) $(clean-files)))
+
+# build a list of files to remove, usually releative to the current
+# directory
+
+__clean-files  := $(extra-y) $(EXTRA_TARGETS) $(always) \
+                  $(targets) $(clean-files)             \
+                  $(host-progs)                         \
+                  $(hostprogs-y) $(hostprogs-m) $(hostprogs-)
+
+# as clean-files is given relative to the current directory, this adds
+# a $(obj) prefix, except for absolute paths
+
+__clean-files   := $(wildcard                                               \
+                   $(addprefix $(obj)/, $(filter-out /%, $(__clean-files))) \
+                  $(filter /%, $(__clean-files)))
+
+# as clean-dirs is given relative to the current directory, this adds
+# a $(obj) prefix, except for absolute paths
+
+__clean-dirs    := $(wildcard                                               \
+                   $(addprefix $(obj)/, $(filter-out /%, $(clean-dirs)))    \
+                  $(filter /%, $(clean-dirs)))
 
 # ==========================================================================
 
-quiet_cmd_clean = CLEAN   $(obj)
-      cmd_clean = rm -f $(__clean-files); $(clean-rule)
+quiet_cmd_clean    = CLEAN   $(obj)
+      cmd_clean    = rm -f $(__clean-files)
+quiet_cmd_cleandir = CLEAN   $(__clean-dirs)
+      cmd_cleandir = rm -rf $(__clean-dirs)
+
 
 __clean: $(subdir-ymn)
-ifneq ($(strip $(__clean-files) $(clean-rule)),)
+ifneq ($(strip $(__clean-files)),)
        +$(call cmd,clean)
-else
-       @:
 endif
+ifneq ($(strip $(__clean-dirs)),)
+       +$(call cmd,cleandir)
+endif
+ifneq ($(strip $(clean-rule)),)
+       +$(clean-rule)
+endif
+       @:
+
 
 # ===========================================================================
 # Generic stuff
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
new file mode 100644 (file)
index 0000000..2821a2b
--- /dev/null
@@ -0,0 +1,155 @@
+# ==========================================================================
+# Building binaries on the host system
+# Binaries are used during the compilation of the kernel, for example
+# to preprocess a data file.
+#
+# Both C and C++ is supported, but preferred language is C for such utilities.
+#
+# Samle syntax (see Documentation/kbuild/makefile.txt for reference)
+# hostprogs-y := bin2hex
+# Will compile bin2hex.c and create an executable named bin2hex
+#
+# hostprogs-y    := lxdialog
+# lxdialog-objs := checklist.o lxdialog.o
+# Will compile lxdialog.c and checklist.c, and then link the executable
+# lxdialog, based on checklist.o and lxdialog.o
+#
+# hostprogs-y      := qconf
+# qconf-cxxobjs   := qconf.o
+# qconf-objs      := menu.o
+# Will compile qconf as a C++ program, and menu as a C program.
+# They are linked as C++ code to the executable qconf
+
+# hostprogs-y := conf
+# conf-objs  := conf.o libkconfig.so
+# libkconfig-objs := expr.o type.o
+# Will create a shared library named libkconfig.so that consist of
+# expr.o and type.o (they are both compiled as C code and the object file
+# are made as position independent code).
+# conf.c is compiled as a c program, and conf.o is linked together with
+# libkconfig.so as the executable conf.
+# Note: Shared libraries consisting of C++ files are not supported
+
+__hostprogs := $(sort $(hostprogs-y)$(hostprogs-m))
+
+# hostprogs-y := tools/build may have been specified. Retreive directory
+obj-dirs += $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
+obj-dirs := $(strip $(sort $(filter-out ./,$(obj-dirs))))
+
+
+# C code
+# Executables compiled from a single .c file
+host-csingle   := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m)))
+
+# C executables linked based on several .o files
+host-cmulti    := $(foreach m,$(__hostprogs),\
+                  $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
+
+# Object (.o) files compiled from .c files
+host-cobjs     := $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
+
+# C++ code
+# C++ executables compiled from at least on .cc file
+# and zero or more .c files
+host-cxxmulti  := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m)))
+
+# C++ Object (.o) files compiled from .cc files
+host-cxxobjs   := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
+
+# Shared libaries (only .c supported)
+# Shared libraries (.so) - all .so files referenced in "xxx-objs"
+host-cshlib    := $(sort $(filter %.so, $(host-cobjs)))
+# Remove .so files from "xxx-objs"
+host-cobjs     := $(filter-out %.so,$(host-cobjs))
+
+#Object (.o) files used by the shared libaries
+host-cshobjs   := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
+
+__hostprogs     := $(addprefix $(obj)/,$(__hostprogs))
+host-csingle   := $(addprefix $(obj)/,$(host-csingle))
+host-cmulti    := $(addprefix $(obj)/,$(host-cmulti))
+host-cobjs     := $(addprefix $(obj)/,$(host-cobjs))
+host-cxxmulti  := $(addprefix $(obj)/,$(host-cxxmulti))
+host-cxxobjs   := $(addprefix $(obj)/,$(host-cxxobjs))
+host-cshlib    := $(addprefix $(obj)/,$(host-cshlib))
+host-cshobjs   := $(addprefix $(obj)/,$(host-cshobjs))
+obj-dirs        := $(addprefix $(obj)/,$(obj-dirs))
+
+#####
+# Handle options to gcc. Support building with separate output directory
+
+_hostc_flags   = $(HOSTCFLAGS)   $(HOST_EXTRACFLAGS)   $(HOSTCFLAGS_$(*F).o)
+_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o)
+
+ifeq ($(KBUILD_SRC),)
+__hostc_flags  = $(_hostc_flags)
+__hostcxx_flags        = $(_hostcxx_flags)
+else
+__hostc_flags  = -I$(obj) $(call flags,_hostc_flags)
+__hostcxx_flags        = -I$(obj) $(call flags,_hostcxx_flags)
+endif
+
+hostc_flags    = -Wp,-MD,$(depfile) $(__hostc_flags)
+hostcxx_flags  = -Wp,-MD,$(depfile) $(__hostcxx_flags)
+
+#####
+# Compile programs on the host
+
+# Create executable from a single .c file
+# host-csingle -> Executable
+quiet_cmd_host-csingle         = HOSTCC  $@
+      cmd_host-csingle = $(HOSTCC) $(hostc_flags) $(HOST_LOADLIBES) -o $@ $<
+$(host-csingle): %: %.c FORCE
+       $(call if_changed_dep,host-csingle)
+
+# Link an executable based on list of .o files, all plain c
+# host-cmulti -> executable
+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
+       $(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
+       $(call if_changed_dep,host-cobjs)
+
+# Link an executable based on list of .o files, a mixture of .c and .cc
+# host-cxxmulti -> executable
+quiet_cmd_host-cxxmulti        = HOSTLD  $@
+      cmd_host-cxxmulti        = $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \
+                         $(foreach o,objs cxxobjs,\
+                         $(addprefix $(obj)/,$($(@F)-$(o)))) \
+                         $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
+$(host-cxxmulti): %: $(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
+       $(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
+       $(call if_changed_dep,host-cshobjs)
+
+# Link a shared library, based on position independent .o files
+# *.o -> .so shared library (host-cshlib)
+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
+       $(call if_changed,host-cshlib)
+
+targets += $(host-csingle)  $(host-cmulti) $(host-cobjs)\
+          $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) 
+
index a47abc8..3a7663b 100644 (file)
@@ -60,41 +60,11 @@ subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o)
 
 # $(obj-dirs) is a list of directories that contain object files
 obj-dirs := $(dir $(multi-objs) $(subdir-obj-y))
-obj-dirs += $(foreach f,$(host-progs), $(if $(dir $(f)),$(dir $(f))))
-obj-dirs := $(strip $(sort $(filter-out ./,$(obj-dirs))))
 
 # Replace multi-part objects by their individual parts, look at local dir only
 real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y)
 real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
 
-# C code
-# Executables compiled from a single .c file
-host-csingle   := $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m)))
-
-# C executables linked based on several .o files
-host-cmulti    := $(foreach m,$(host-progs),\
-                  $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
-
-# Object (.o) files compiled from .c files
-host-cobjs     := $(sort $(foreach m,$(host-progs),$($(m)-objs)))
-
-# C++ code
-# C++ executables compiled from at least on .cc file
-# and zero or more .c files
-host-cxxmulti  := $(foreach m,$(host-progs),$(if $($(m)-cxxobjs),$(m)))
-
-# C++ Object (.o) files compiled from .cc files
-host-cxxobjs   := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
-
-# Shared libaries (only .c supported)
-# Shared libraries (.so) - all .so files referenced in "xxx-objs"
-host-cshlib    := $(sort $(filter %.so, $(host-cobjs)))
-# Remove .so files from "xxx-objs"
-host-cobjs     := $(filter-out %.so,$(host-cobjs))
-
-#Object (.o) files used by the shared libaries
-host-cshobjs   := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
-
 # Add subdir path
 
 extra-y                := $(addprefix $(obj)/,$(extra-y))
@@ -113,14 +83,6 @@ multi-objs-y        := $(addprefix $(obj)/,$(multi-objs-y))
 multi-objs-m   := $(addprefix $(obj)/,$(multi-objs-m))
 subdir-ym      := $(addprefix $(obj)/,$(subdir-ym))
 obj-dirs       := $(addprefix $(obj)/,$(obj-dirs))
-host-progs      := $(addprefix $(obj)/,$(host-progs))
-host-csingle   := $(addprefix $(obj)/,$(host-csingle))
-host-cmulti    := $(addprefix $(obj)/,$(host-cmulti))
-host-cobjs     := $(addprefix $(obj)/,$(host-cobjs))
-host-cxxmulti  := $(addprefix $(obj)/,$(host-cxxmulti))
-host-cxxobjs   := $(addprefix $(obj)/,$(host-cxxobjs))
-host-cshlib    := $(addprefix $(obj)/,$(host-cshlib))
-host-cshobjs   := $(addprefix $(obj)/,$(host-cshobjs))
 
 # The temporary file to save gcc -MD generated dependencies must not
 # contain a comma
@@ -136,12 +98,9 @@ depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
 basename_flags = -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F)))
 modname_flags  = $(if $(filter 1,$(words $(modname))),-DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname))))
 
-
 _c_flags       = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o)
 _a_flags       = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
-_hostc_flags   = $(HOSTCFLAGS)   $(HOST_EXTRACFLAGS)   $(HOSTCFLAGS_$(*F).o)
-_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o)
-
+_cpp_flags     = $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F))
 
 # If building the kernel in a separate objtree expand all occurrences
 # of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/').
@@ -149,8 +108,7 @@ _hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o)
 ifeq ($(KBUILD_SRC),)
 __c_flags      = $(_c_flags)
 __a_flags      = $(_a_flags)
-__hostc_flags  = $(_hostc_flags)
-__hostcxx_flags        = $(_hostcxx_flags)
+__cpp_flags     = $(_cpp_flags)
 else
 
 # Prefix -I with $(srctree) if it is not an absolute path
@@ -164,8 +122,7 @@ flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
 # FIXME: Replace both with specific CFLAGS* statements in the makefiles
 __c_flags      = $(call addtree,-I$(obj)) $(call flags,_c_flags)
 __a_flags      =                          $(call flags,_a_flags)
-__hostc_flags  = -I$(obj)                 $(call flags,_hostc_flags)
-__hostcxx_flags        = -I$(obj)                 $(call flags,_hostcxx_flags)
+__cpp_flags     =                          $(call flags,_cpp_flags)
 endif
 
 c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
@@ -175,8 +132,7 @@ c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
 a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
                 $(__a_flags) $(modkern_aflags)
 
-hostc_flags    = -Wp,-MD,$(depfile) $(__hostc_flags)
-hostcxx_flags  = -Wp,-MD,$(depfile) $(__hostcxx_flags)
+cpp_flags      = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags)
 
 ld_flags       = $(LDFLAGS) $(EXTRA_LDFLAGS)
 
index 3afb3bf..f22e94c 100644 (file)
@@ -11,8 +11,8 @@
 #                include/config/...
 # docproc:      Used in Documentation/docbook
 
-host-progs     := fixdep split-include docproc
-always         := $(host-progs)
+hostprogs-y    := fixdep split-include docproc
+always         := $(hostprogs-y)
 
 # fixdep is needed to compile other host programs
 $(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
index 7b8100d..591309d 100644 (file)
@@ -41,7 +41,7 @@
 char           *progname;
 char           *inputname;
 int            inputfd;
-int            bix;                    /* buf index */
+unsigned int   bix;                    /* buf index */
 unsigned char  patterns [PAT_SIZE] = {0}; /* byte-sized pattern array */
 int            pat_len;                /* actual number of pattern bytes */
 unsigned char  *madr;                  /* mmap address */
@@ -58,7 +58,7 @@ void usage (void)
        exit (1);
 }
 
-int get_pattern (int pat_count, char *pats [])
+void get_pattern (int pat_count, char *pats [])
 {
        int ix, err, tmp;
 
@@ -81,7 +81,7 @@ int get_pattern (int pat_count, char *pats [])
        pat_len = pat_count;
 }
 
-int search_pattern (void)
+void search_pattern (void)
 {
        for (bix = 0; bix < filesize; bix++) {
                if (madr[bix] == patterns[0]) {
@@ -109,7 +109,7 @@ size_t get_filesize (int fd)
        struct stat stat;
 
        err = fstat (fd, &stat);
-       fprintf (stderr, "filesize: %d\n", err < 0 ? err : stat.st_size);
+       fprintf (stderr, "filesize: %ld\n", err < 0 ? (long)err : stat.st_size);
        if (err < 0)
                return err;
        return (size_t) stat.st_size;
@@ -154,8 +154,8 @@ int main (int argc, char *argv [])
        fprintf (stderr, "number of pattern matches = %d\n", num_matches);
        if (num_matches == 0)
                firstloc = ~0;
-       printf ("%d\n", firstloc);
-       fprintf (stderr, "%d\n", firstloc);
+       printf ("%ld\n", firstloc);
+       fprintf (stderr, "%ld\n", firstloc);
 
        exit (num_matches ? 0 : 2);
 }
index 76f1fd1..5875f29 100644 (file)
@@ -1,6 +1,6 @@
 
-host-progs     := genksyms
-always         := $(host-progs)
+hostprogs-y    := genksyms
+always         := $(hostprogs-y)
 
 genksyms-objs  := genksyms.o parse.o lex.o
 
index 9cf074b..416a694 100644 (file)
@@ -27,7 +27,9 @@
 #include <unistd.h>
 #include <assert.h>
 #include <stdarg.h>
+#ifdef __GNU_LIBRARY__
 #include <getopt.h>
+#endif /* __GNU_LIBRARY__ */
 
 #include "genksyms.h"
 
@@ -502,12 +504,21 @@ void genksyms_usage(void)
        fputs("Usage:\n"
              "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n"
              "\n"
+#ifdef __GNU_LIBRARY__
              "  -d, --debug           Increment the debug level (repeatable)\n"
              "  -D, --dump            Dump expanded symbol defs (for debugging only)\n"
              "  -w, --warnings        Enable warnings\n"
              "  -q, --quiet           Disable warnings (default)\n"
              "  -h, --help            Print this message\n"
              "  -V, --version         Print the release version\n"
+#else  /* __GNU_LIBRARY__ */
+             "  -d                    Increment the debug level (repeatable)\n"
+             "  -D                    Dump expanded symbol defs (for debugging only)\n"
+             "  -w                    Enable warnings\n"
+             "  -q                    Disable warnings (default)\n"
+             "  -h                    Print this message\n"
+             "  -V                    Print the release version\n"
+#endif /* __GNU_LIBRARY__ */
              , stderr);
 }
 
@@ -516,6 +527,7 @@ main(int argc, char **argv)
 {
   int o;
 
+#ifdef __GNU_LIBRARY__
   struct option long_opts[] = {
     {"debug", 0, 0, 'd'},
     {"warnings", 0, 0, 'w'},
@@ -528,6 +540,9 @@ main(int argc, char **argv)
 
   while ((o = getopt_long(argc, argv, "dwqVDk:p:",
                          &long_opts[0], NULL)) != EOF)
+#else  /* __GNU_LIBRARY__ */
+  while ((o = getopt(argc, argv, "dwqVDk:p:")) != EOF)
+#endif /* __GNU_LIBRARY__ */
     switch (o)
       {
       case 'd':
index 90247d2..7b6285e 100644 (file)
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 
 #define LKC_DIRECT_LINK
@@ -268,6 +269,7 @@ int conf_write(const char *name)
        char dirname[128], tmpname[128], newname[128];
        int type, l;
        const char *str;
+       time_t now;
 
        dirname[0] = 0;
        if (name && name[0]) {
@@ -301,14 +303,25 @@ int conf_write(const char *name)
                if (!out_h)
                        return 1;
        }
+       sym = sym_lookup("KERNELRELEASE", 0);
+       sym_calc_value(sym);
+       time(&now);
        fprintf(out, "#\n"
                     "# Automatically generated make config: don't edit\n"
-                    "#\n");
+                    "# Linux kernel version: %s\n"
+                    "# %s"
+                    "#\n",
+                    sym_get_string_value(sym),
+                    ctime(&now));
        if (out_h)
                fprintf(out_h, "/*\n"
                               " * Automatically generated C config: don't edit\n"
+                              " * Linux kernel version: %s\n"
+                              " * %s"
                               " */\n"
-                              "#define AUTOCONF_INCLUDED\n");
+                              "#define AUTOCONF_INCLUDED\n",
+                              sym_get_string_value(sym),
+                              ctime(&now));
 
        if (!sym_change_count)
                sym_clear_all_valid();
index 489c4ff..0b956e3 100644 (file)
@@ -275,9 +275,8 @@ void init_main_window(const gchar * glade_file)
                                          /*"style", PANGO_STYLE_OBLIQUE, */
                                          NULL);
 
-       sprintf(title, "Linux Kernel v%s.%s.%s%s Configuration",
-               getenv("VERSION"), getenv("PATCHLEVEL"),
-               getenv("SUBLEVEL"), getenv("EXTRAVERSION"));
+       sprintf(title, "Linux Kernel v%s Configuration",
+               getenv("KERNELRELEASE"));
        gtk_window_set_title(GTK_WINDOW(main_wnd), title);
 
        gtk_widget_show(main_wnd);
index dd040f7..e348ee7 100644 (file)
@@ -59,9 +59,6 @@ void menu_set_type(int type);
 struct file *file_lookup(const char *name);
 int file_write_dep(const char *name);
 
-extern struct menu *current_entry;
-extern struct menu *current_menu;
-
 /* symbol.c */
 void sym_init(void);
 void sym_clear_all_valid(void);
index 38046c6..7b26f98 100644 (file)
@@ -10,7 +10,6 @@
 #include "lkc.h"
 
 struct menu rootmenu;
-struct menu *current_menu, *current_entry;
 static struct menu **last_entry_ptr;
 
 struct file *file_list;
index c9bfdb4..a48105a 100644 (file)
@@ -175,6 +175,8 @@ static bool zconf_endtoken(int token, int starttoken, int endtoken);
 
 struct symbol *symbol_hash[257];
 
+static struct menu *current_menu, *current_entry;
+
 #define YYERROR_VERBOSE
 
 
index 459b690..aad1f51 100644 (file)
@@ -25,6 +25,8 @@ static bool zconf_endtoken(int token, int starttoken, int endtoken);
 
 struct symbol *symbol_hash[257];
 
+static struct menu *current_menu, *current_entry;
+
 #define YYERROR_VERBOSE
 %}
 %expect 40
index 2f22b2f..cdc4024 100644 (file)
@@ -15,8 +15,8 @@ endif
 endif
 endif
 
-host-progs     := lxdialog
-always         := ncurses $(host-progs)
+hostprogs-y    := lxdialog
+always         := ncurses $(hostprogs-y)
 
 lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
                 util.o lxdialog.o msgbox.o
index 9544b3c..124459c 100644 (file)
@@ -276,6 +276,15 @@ dialog_menu (const char *title, const char *prompt, int height, int width,
 
     while (key != ESC) {
        key = wgetch(menu);
+       if ( key == '/' ) {
+               int ret = dialog_inputbox("Search Configuration Parameter",
+                                       "Enter Keyword", height, width,
+                                       (char *) NULL);
+               if (ret == 0) {
+                       fprintf(stderr, "%s", dialog_input_result);
+                       return 26;
+               }
+       }
 
        if (key < 256 && isalpha(key)) key = tolower(key);
 
diff --git a/scripts/mksysmap b/scripts/mksysmap
new file mode 100644 (file)
index 0000000..2904d3b
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/sh -x
+# Based on the vmlinux file create the System.map file
+# System.map is used by module-init tools and some debugging
+# tools to retreive the actual addresses of symbols in the kernel.
+#
+# Usage
+# mksysmap vmlinux System.map
+
+
+#####
+# Generate System.map (actual filename passed as second argument)
+
+# $NM produces the following output:
+# f0081e80 T alloc_vfsmnt
+
+#   The second row specify the type of the symbol:
+#   A = Absolute
+#   B = Uninitialised data (.bss)
+#   C = Comon symbol
+#   D = Initialised data
+#   G = Initialised data for small objects
+#   I = Indirect reference to another symbol
+#   N = Debugging symbol
+#   R = Read only
+#   S = Uninitialised data for small objects
+#   T = Text code symbol
+#   U = Undefined symbol
+#   V = Weak symbol
+#   W = Weak symbol
+#   Corresponding small letters are local symbols
+
+# For System.map filter away:
+#   a - local absolute symbols
+#   U - undefined global symbols
+#   w - local weak symbols
+
+# readprofile starts reading symbols when _stext is found, and
+# continue until it finds a symbol which is not either of 'T', 't',
+# 'W' or 'w'. __crc_ are 'A' and placed in the middle
+# so we just ignore them to let readprofile continue to work.
+# (At least sparc64 has __crc_ in the middle).
+
+$NM -n $1 | grep -v '\( [aUw] \)\|\(__crc_\)' > $2
+
index 662e75b..2a174e5 100644 (file)
@@ -343,7 +343,6 @@ handle_modversions(struct module *mod, struct elf_info *info,
                        crc = (unsigned int) sym->st_value;
                        add_exported_symbol(symname + strlen(CRC_PFX),
                                            mod, &crc);
-                       modversions = 1;
                }
                break;
        case SHN_UNDEF:
@@ -377,6 +376,10 @@ handle_modversions(struct module *mod, struct elf_info *info,
                        add_exported_symbol(symname + strlen(KSYMTAB_PFX),
                                            mod, NULL);
                }
+               if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
+                       mod->has_init = 1;
+               if (strcmp(symname, MODULE_SYMBOL_PREFIX "cleanup_module") == 0)
+                       mod->has_cleanup = 1;
                break;
        }
 }
@@ -411,9 +414,6 @@ read_symbols(char *modname)
        if (is_vmlinux(modname)) {
                unsigned int fake_crc = 0;
                have_vmlinux = 1;
-               /* May not have this if !CONFIG_MODULE_UNLOAD: fake it.
-                  If it appears, we'll get the real CRC. */
-               add_exported_symbol("cleanup_module", mod, &fake_crc);
                add_exported_symbol("struct_module", mod, &fake_crc);
                mod->skip = 1;
        }
@@ -432,14 +432,8 @@ read_symbols(char *modname)
         * never passed as an argument to an exported function, so
         * the automatic versioning doesn't pick it up, but it's really
         * important anyhow */
-       if (modversions) {
+       if (modversions)
                mod->unres = alloc_symbol("struct_module", mod->unres);
-
-               /* Always version init_module and cleanup_module, in
-                * case module doesn't have its own. */
-               mod->unres = alloc_symbol("init_module", mod->unres);
-               mod->unres = alloc_symbol("cleanup_module", mod->unres);
-       }
 }
 
 #define SZ 500
@@ -480,7 +474,7 @@ buf_write(struct buffer *buf, const char *s, int len)
 /* Header for the generated file */
 
 void
-add_header(struct buffer *b)
+add_header(struct buffer *b, struct module *mod)
 {
        buf_printf(b, "#include <linux/module.h>\n");
        buf_printf(b, "#include <linux/vermagic.h>\n");
@@ -492,10 +486,12 @@ add_header(struct buffer *b)
        buf_printf(b, "struct module __this_module\n");
        buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
        buf_printf(b, " .name = __stringify(KBUILD_MODNAME),\n");
-       buf_printf(b, " .init = init_module,\n");
-       buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n");
-       buf_printf(b, " .exit = cleanup_module,\n");
-       buf_printf(b, "#endif\n");
+       if (mod->has_init)
+               buf_printf(b, " .init = init_module,\n");
+       if (mod->has_cleanup)
+               buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"
+                             " .exit = cleanup_module,\n"
+                             "#endif\n");
        buf_printf(b, "};\n");
 }
 
@@ -649,7 +645,6 @@ read_dump(const char *fname)
 
                if (!(mod = find_module(modname))) {
                        if (is_vmlinux(modname)) {
-                               modversions = 1;
                                have_vmlinux = 1;
                        }
                        mod = new_module(NOFAIL(strdup(modname)));
@@ -696,11 +691,14 @@ main(int argc, char **argv)
        char *dump_read = NULL, *dump_write = NULL;
        int opt;
 
-       while ((opt = getopt(argc, argv, "i:o:")) != -1) {
+       while ((opt = getopt(argc, argv, "i:mo:")) != -1) {
                switch(opt) {
                        case 'i':
                                dump_read = optarg;
                                break;
+                       case 'm':
+                               modversions = 1;
+                               break;
                        case 'o':
                                dump_write = optarg;
                                break;
@@ -722,7 +720,7 @@ main(int argc, char **argv)
 
                buf.pos = 0;
 
-               add_header(&buf);
+               add_header(&buf, mod);
                add_versions(&buf, mod);
                add_depends(&buf, mod, modules);
                add_moddevtable(&buf, mod);
index ddb013d..4871343 100644 (file)
@@ -74,6 +74,8 @@ struct module {
        struct symbol *unres;
        int seen;
        int skip;
+       int has_init;
+       int has_cleanup;
        struct buffer dev_table_buf;
 };
 
index b41b718..86ea6a3 100644 (file)
@@ -1,5 +1,9 @@
 #include <netinet/in.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
 #include <stdint.h>
+#endif
 #include <ctype.h>
 #include <errno.h>
 #include <string.h>
diff --git a/scripts/namespace.pl b/scripts/namespace.pl
new file mode 100644 (file)
index 0000000..399c831
--- /dev/null
@@ -0,0 +1,449 @@
+#!/usr/bin/perl -w
+#
+#      namespace.pl.  Mon Aug 30 2004
+#
+#      Perform a name space analysis on the linux kernel.
+#
+#      Copyright Keith Owens <kaos@ocs.com.au>.  GPL.
+#
+#      Invoke by changing directory to the top of the kernel object
+#      tree then namespace.pl, no parameters.
+#
+#      Tuned for 2.1.x kernels with the new module handling, it will
+#      work with 2.0 kernels as well.
+#
+#      Last change 2.6.9-rc1, adding support for separate source and object
+#      trees.
+#
+#      The source must be compiled/assembled first, the object files
+#      are the primary input to this script.  Incomplete or missing
+#      objects will result in a flawed analysis.  Compile both vmlinux
+#      and modules.
+#
+#      Even with complete objects, treat the result of the analysis
+#      with caution.  Some external references are only used by
+#      certain architectures, others with certain combinations of
+#      configuration parameters.  Ideally the source should include
+#      something like
+#
+#      #ifndef CONFIG_...
+#      static
+#      #endif
+#      symbol_definition;
+#
+#      so the symbols are defined as static unless a particular
+#      CONFIG_... requires it to be external.
+#
+#      A symbol that is suffixed with '(export only)' has these properties
+#
+#      * It is global.
+#      * It is marked EXPORT_SYMBOL or EXPORT_SYMBOL_GPL, either in the same
+#        source file or a different source file.
+#      * Given the current .config, nothing uses the symbol.
+#
+#      The symbol is a candidate for conversion to static, plus removal of the
+#      export.  But be careful that a different .config might use the symbol.
+#
+#
+#      Name space analysis and cleanup is an iterative process.  You cannot
+#      expect to find all the problems in a single pass.
+#
+#      * Identify possibly unnecessary global declarations, verify that they
+#        really are unnecessary and change them to static.
+#      * Compile and fix up gcc warnings about static, removing dead symbols
+#        as necessary.
+#      * make clean and rebuild with different configs (especially
+#        CONFIG_MODULES=n) to see which symbols are being defined when the
+#        config does not require them.  These symbols bloat the kernel object
+#        for no good reason, which is frustrating for embedded systems.
+#      * Wrap config sensitive symbols in #ifdef CONFIG_foo, as long as the
+#        code does not get too ugly.
+#      * Repeat the name space analysis until you can live with with the
+#        result.
+#
+
+require 5;     # at least perl 5
+use strict;
+use File::Find;
+
+my $nm = "/usr/bin/nm -p";
+my $objdump = "/usr/bin/objdump -s -j .comment";
+my $srctree = "";
+my $objtree = "";
+$srctree = "$ENV{'srctree'}/" if (exists($ENV{'srctree'}));
+$objtree = "$ENV{'objtree'}/" if (exists($ENV{'objtree'}));
+
+if ($#ARGV != -1) {
+       print STDERR "usage: $0 takes no parameters\n";
+       die("giving up\n");
+}
+
+my %nmdata = ();       # nm data for each object
+my %def = ();          # all definitions for each name
+my %ksymtab = ();      # names that appear in __ksymtab_
+my %ref = ();          # $ref{$name} exists if there is a true external reference to $name
+my %export = ();       # $export{$name} exists if there is an EXPORT_... of $name
+
+&find(\&linux_objects, '.');   # find the objects and do_nm on them
+&list_multiply_defined();
+&resolve_external_references();
+&list_extra_externals();
+
+exit(0);
+
+sub linux_objects
+{
+       # Select objects, ignoring objects which are only created by
+       # merging other objects.  Also ignore all of modules, scripts
+       # and compressed.  Most conglomerate objects are handled by do_nm,
+       # this list only contains the special cases.  These include objects
+       # that are linked from just one other object and objects for which
+       # there is really no permanent source file.
+       my $basename = $_;
+       $_ = $File::Find::name;
+       s:^\./::;
+       if (/.*\.o$/ &&
+               ! (
+               m:/built-in.o$:
+               || m:arch/i386/kernel/vsyscall-syms.o$:
+               || m:arch/ia64/ia32/ia32.o$:
+               || m:arch/ia64/kernel/gate-syms.o$:
+               || m:arch/ia64/lib/__divdi3.o$:
+               || m:arch/ia64/lib/__divsi3.o$:
+               || m:arch/ia64/lib/__moddi3.o$:
+               || m:arch/ia64/lib/__modsi3.o$:
+               || m:arch/ia64/lib/__udivdi3.o$:
+               || m:arch/ia64/lib/__udivsi3.o$:
+               || m:arch/ia64/lib/__umoddi3.o$:
+               || m:arch/ia64/lib/__umodsi3.o$:
+               || m:arch/ia64/scripts/check_gas_for_hint.o$:
+               || m:arch/ia64/sn/kernel/xp.o$:
+               || m:boot/bbootsect.o$:
+               || m:boot/bsetup.o$:
+               || m:/bootsect.o$:
+               || m:/boot/setup.o$:
+               || m:/compressed/:
+               || m:drivers/cdrom/driver.o$:
+               || m:drivers/char/drm/tdfx_drv.o$:
+               || m:drivers/ide/ide-detect.o$:
+               || m:drivers/ide/pci/idedriver-pci.o$:
+               || m:drivers/media/media.o$:
+               || m:drivers/scsi/sd_mod.o$:
+               || m:drivers/video/video.o$:
+               || m:fs/devpts/devpts.o$:
+               || m:fs/exportfs/exportfs.o$:
+               || m:fs/hugetlbfs/hugetlbfs.o$:
+               || m:fs/msdos/msdos.o$:
+               || m:fs/nls/nls.o$:
+               || m:fs/ramfs/ramfs.o$:
+               || m:fs/romfs/romfs.o$:
+               || m:fs/vfat/vfat.o$:
+               || m:init/mounts.o$:
+               || m:^modules/:
+               || m:net/netlink/netlink.o$:
+               || m:net/sched/sched.o$:
+               || m:/piggy.o$:
+               || m:^scripts/:
+               || m:sound/.*/snd-:
+               || m:^.*/\.tmp_:
+               || m:^\.tmp_:
+               || m:/vmlinux-obj.o$:
+               )
+       ) {
+               do_nm($basename, $_);
+       }
+       $_ = $basename;         # File::Find expects $_ untouched (undocumented)
+}
+
+sub do_nm
+{
+       my ($basename, $fullname) = @_;
+       my ($source, $type, $name);
+       if (! -e $basename) {
+               printf STDERR "$basename does not exist\n";
+               return;
+       }
+       if ($fullname !~ /\.o$/) {
+               printf STDERR "$fullname is not an object file\n";
+               return;
+       }
+       ($source = $fullname) =~ s/\.o$//;
+       if (-e "$objtree$source.c" || -e "$objtree$source.S") {
+               $source = "$objtree$source";
+       } else {
+               $source = "$srctree$source";
+       }
+       if (! -e "$source.c" && ! -e "$source.S") {
+               # No obvious source, exclude the object if it is conglomerate
+               if (! open(OBJDUMPDATA, "$objdump $basename|")) {
+                       printf STDERR "$objdump $fullname failed $!\n";
+                       return;
+               }
+               my $comment;
+               while (<OBJDUMPDATA>) {
+                       chomp();
+                       if (/^In archive/) {
+                               # Archives are always conglomerate
+                               $comment = "GCC:GCC:";
+                               last;
+                       }
+                       next if (! /^[ 0-9a-f]{5,} /);
+                       $comment .= substr($_, 43);
+               }
+               close(OBJDUMPDATA);
+               if (!defined($comment) || $comment !~ /GCC\:.*GCC\:/m) {
+                       printf STDERR "No source file found for $fullname\n";
+               }
+               return;
+       }
+       if (! open(NMDATA, "$nm $basename|")) {
+               printf STDERR "$nm $fullname failed $!\n";
+               return;
+       }
+       my @nmdata;
+       while (<NMDATA>) {
+               chop;
+               ($type, $name) = (split(/ +/, $_, 3))[1..2];
+               # Expected types
+               # A absolute symbol
+               # B weak external reference to data that has been resolved
+               # C global variable, uninitialised
+               # D global variable, initialised
+               # G global variable, initialised, small data section
+               # R global array, initialised
+               # S global variable, uninitialised, small bss
+               # T global label/procedure
+               # U external reference
+               # W weak external reference to text that has been resolved
+               # a assembler equate
+               # b static variable, uninitialised
+               # d static variable, initialised
+               # g static variable, initialised, small data section
+               # r static array, initialised
+               # s static variable, uninitialised, small bss
+               # t static label/procedures
+               # w weak external reference to text that has not been resolved
+               # ? undefined type, used a lot by modules
+               if ($type !~ /^[ABCDGRSTUWabdgrstw?]$/) {
+                       printf STDERR "nm output for $fullname contains unknown type '$_'\n";
+               }
+               elsif ($name =~ /\./) {
+                       # name with '.' is local static
+               }
+               else {
+                       $type = 'R' if ($type eq '?');  # binutils replaced ? with R at one point
+                       # binutils keeps changing the type for exported symbols, force it to R
+                       $type = 'R' if ($name =~ /^__ksymtab/ || $name =~ /^__kstrtab/);
+                       $name =~ s/_R[a-f0-9]{8}$//;    # module versions adds this
+                       if ($type =~ /[ABCDGRSTW]/ &&
+                               $name ne 'init_module' &&
+                               $name ne 'cleanup_module' &&
+                               $name ne 'Using_Versions' &&
+                               $name !~ /^Version_[0-9]+$/ &&
+                               $name !~ /^__parm_/ &&
+                               $name !~ /^__kstrtab/ &&
+                               $name !~ /^__ksymtab/ &&
+                               $name !~ /^__kcrctab_/ &&
+                               $name !~ /^__exitcall_/ &&
+                               $name !~ /^__initcall_/ &&
+                               $name !~ /^__kdb_initcall_/ &&
+                               $name !~ /^__kdb_exitcall_/ &&
+                               $name !~ /^__module_/ &&
+                               $name !~ /^__mod_/ &&
+                               $name !~ /^__crc_/ &&
+                               $name ne '__this_module' &&
+                               $name ne 'kernel_version') {
+                               if (!exists($def{$name})) {
+                                       $def{$name} = [];
+                               }
+                               push(@{$def{$name}}, $fullname);
+                       }
+                       push(@nmdata, "$type $name");
+                       if ($name =~ /^__ksymtab_/) {
+                               $name = substr($name, 10);
+                               if (!exists($ksymtab{$name})) {
+                                       $ksymtab{$name} = [];
+                               }
+                               push(@{$ksymtab{$name}}, $fullname);
+                       }
+               }
+       }
+       close(NMDATA);
+       if ($#nmdata < 0) {
+               if (
+                       $fullname ne "lib/brlock.o"
+                       && $fullname ne "lib/dec_and_lock.o"
+                       && $fullname ne "fs/xfs/xfs_macros.o"
+                       && $fullname ne "drivers/ide/ide-probe-mini.o"
+                       && $fullname ne "usr/initramfs_data.o"
+                       && $fullname ne "drivers/acpi/executer/exdump.o"
+                       && $fullname ne "drivers/acpi/resources/rsdump.o"
+                       && $fullname ne "drivers/acpi/namespace/nsdumpdv.o"
+                       && $fullname ne "drivers/acpi/namespace/nsdump.o"
+                       && $fullname ne "arch/ia64/sn/kernel/sn2/io.o"
+                       && $fullname ne "arch/ia64/kernel/gate-data.o"
+                       && $fullname ne "drivers/ieee1394/oui.o"
+                       && $fullname ne "security/capability.o"
+                       && $fullname ne "sound/core/wrappers.o"
+                       && $fullname ne "fs/ntfs/sysctl.o"
+                       && $fullname ne "fs/jfs/jfs_debug.o"
+               ) {
+                       printf "No nm data for $fullname\n";
+               }
+               return;
+       }
+       $nmdata{$fullname} = \@nmdata;
+}
+
+sub drop_def
+{
+       my ($object, $name) = @_;
+       my $nmdata = $nmdata{$object};
+       my ($i, $j);
+       for ($i = 0; $i <= $#{$nmdata}; ++$i) {
+               if ($name eq (split(' ', $nmdata->[$i], 2))[1]) {
+                       splice(@{$nmdata{$object}}, $i, 1);
+                       my $def = $def{$name};
+                       for ($j = 0; $j < $#{$def{$name}}; ++$j) {
+                               if ($def{$name}[$j] eq $object) {
+                                       splice(@{$def{$name}}, $j, 1);
+                               }
+                       }
+                       last;
+               }
+       }
+}
+
+sub list_multiply_defined
+{
+       my ($name, $module);
+       foreach $name (keys(%def)) {
+               if ($#{$def{$name}} > 0) {
+                       # Special case for cond_syscall
+                       if ($#{$def{$name}} == 1 && $name =~ /^sys_/ &&
+                           ($def{$name}[0] eq "kernel/sys.o" ||
+                            $def{$name}[1] eq "kernel/sys.o")) {
+                               &drop_def("kernel/sys.o", $name);
+                               next;
+                       }
+                       # Special case for i386 entry code
+                       if ($#{$def{$name}} == 1 && $name =~ /^__kernel_/ &&
+                           $def{$name}[0] eq "arch/i386/kernel/vsyscall-int80.o" &&
+                           $def{$name}[1] eq "arch/i386/kernel/vsyscall-sysenter.o") {
+                               &drop_def("arch/i386/kernel/vsyscall-sysenter.o", $name);
+                               next;
+                       }
+                       printf "$name is multiply defined in :-\n";
+                       foreach $module (@{$def{$name}}) {
+                               printf "\t$module\n";
+                       }
+               }
+       }
+}
+
+sub resolve_external_references
+{
+       my ($object, $type, $name, $i, $j, $kstrtab, $ksymtab, $export);
+       printf "\n";
+       foreach $object (keys(%nmdata)) {
+               my $nmdata = $nmdata{$object};
+               for ($i = 0; $i <= $#{$nmdata}; ++$i) {
+                       ($type, $name) = split(' ', $nmdata->[$i], 2);
+                       if ($type eq "U" || $type eq "w") {
+                               if (exists($def{$name}) || exists($ksymtab{$name})) {
+                                       # add the owning object to the nmdata
+                                       $nmdata->[$i] = "$type $name $object";
+                                       # only count as a reference if it is not EXPORT_...
+                                       $kstrtab = "R __kstrtab_$name";
+                                       $ksymtab = "R __ksymtab_$name";
+                                       $export = 0;
+                                       for ($j = 0; $j <= $#{$nmdata}; ++$j) {
+                                               if ($nmdata->[$j] eq $kstrtab ||
+                                                   $nmdata->[$j] eq $ksymtab) {
+                                                       $export = 1;
+                                                       last;
+                                               }
+                                       }
+                                       if ($export) {
+                                               $export{$name} = "";
+                                       }
+                                       else {
+                                               $ref{$name} = ""
+                                       }
+                               }
+                               elsif (    $name ne "mod_use_count_"
+                                       && $name ne "__initramfs_end"
+                                       && $name ne "__initramfs_start"
+                                       && $name ne "_einittext"
+                                       && $name ne "_sinittext"
+                                       && $name ne "kallsyms_names"
+                                       && $name ne "kallsyms_num_syms"
+                                       && $name ne "kallsyms_addresses"
+                                       && $name ne "__this_module"
+                                       && $name ne "_etext"
+                                       && $name ne "_edata"
+                                       && $name ne "_end"
+                                       && $name ne "__bss_start"
+                                       && $name ne "_text"
+                                       && $name ne "_stext"
+                                       && $name ne "__gp"
+                                       && $name ne "ia64_unw_start"
+                                       && $name ne "ia64_unw_end"
+                                       && $name ne "__init_begin"
+                                       && $name ne "__init_end"
+                                       && $name ne "__bss_stop"
+                                       && $name ne "__nosave_begin"
+                                       && $name ne "__nosave_end"
+                                       && $name ne "pg0"
+                                       && $name ne "__module_text_address"
+                                       && $name !~ /^__sched_text_/
+                                       && $name !~ /^__start_/
+                                       && $name !~ /^__end_/
+                                       && $name !~ /^__stop_/
+                                       && $name !~ /^__scheduling_functions_.*_here/
+                                       && $name !~ /^__.*initcall_/
+                                       && $name !~ /^__.*per_cpu_start/
+                                       && $name !~ /^__.*per_cpu_end/
+                                       && $name !~ /^__alt_instructions/
+                                       && $name !~ /^__setup_/
+                               ) {
+                                       printf "Cannot resolve ";
+                                       printf "weak " if ($type eq "w");
+                                       printf "reference to $name from $object\n";
+                               }
+                       }
+               }
+       }
+}
+
+sub list_extra_externals
+{
+       my %noref = ();
+       my ($name, @module, $module, $export);
+       foreach $name (keys(%def)) {
+               if (! exists($ref{$name})) {
+                       @module = @{$def{$name}};
+                       foreach $module (@module) {
+                               if (! exists($noref{$module})) {
+                                       $noref{$module} = [];
+                               }
+                               push(@{$noref{$module}}, $name);
+                       }
+               }
+       }
+       if (%noref) {
+               printf "\nExternally defined symbols with no external references\n";
+               foreach $module (sort(keys(%noref))) {
+                       printf "  $module\n";
+                       foreach (sort(@{$noref{$module}})) {
+                               if (exists($export{$_})) {
+                                       $export = " (export only)";
+                               }
+                               else {
+                                       $export = "";
+                               }
+                               printf "    $_$export\n";
+                       }
+               }
+       }
+}
index 48f89e1..3b1f2ef 100644 (file)
@@ -51,7 +51,7 @@ rpm-pkg rpm: $(objtree)/kernel.spec
        $(RPM) --target $(UTS_MACHINE) -ta ../$(KERNELPATH).tar.gz
        rm ../$(KERNELPATH).tar.gz
 
-clean-rule +=  rm -f $(objtree)/kernel.spec
+clean-files := $(objtree)/kernel.spec
 
 # binrpm-pkg
 .PHONY: binrpm-pkg
@@ -67,7 +67,7 @@ binrpm-pkg: $(objtree)/binkernel.spec
 
        $(RPM) --define "_builddir $(srctree)" --target $(UTS_MACHINE) -bb $<
 
-clean-rule += rm -f $(objtree)/binkernel.spec
+clean-files += $(objtree)/binkernel.spec
 
 # Deb target
 # ---------------------------------------------------------------------------
@@ -77,7 +77,7 @@ deb-pkg:
        $(MAKE)
        $(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
 
-clean-rule += && rm -rf $(objtree)/debian/
+clean-dirs += $(objtree)/debian/
 
 
 # Help text displayed when executing 'make help'
index 5d94e45..6e7a58f 100644 (file)
@@ -21,11 +21,12 @@ if [ "`grep CONFIG_DRM=y .config | cut -f2 -d\=`" = "y" ]; then
        PROVIDES=kernel-drm
 fi
 
-PROVIDES="$PROVIDES kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+PROVIDES="$PROVIDES kernel-$KERNELRELEASE"
+__KERNELRELEASE=`echo $KERNELRELEASE | sed -e "s/-//g"`
 
 echo "Name: kernel"
 echo "Summary: The Linux Kernel"
-echo "Version: "$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION | sed -e "s/-//g"
+echo "Version: $__KERNELRELEASE"
 # we need to determine the NEXT version number so that uname and
 # rpm -q will agree
 echo "Release: `. $srctree/scripts/mkversion`"
@@ -35,8 +36,7 @@ echo "Vendor: The Linux Community"
 echo "URL: http://www.kernel.org"
 
 if ! $PREBUILT; then
-echo -n "Source: kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL"
-echo "$EXTRAVERSION.tar.gz" | sed -e "s/-//g"
+echo "Source: kernel-$__KERNELRELEASE.tar.gz"
 fi
 
 echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root"
@@ -57,19 +57,19 @@ fi
 echo "%build"
 
 if ! $PREBUILT; then
-echo "make clean && make"
+echo "make clean && make %{_smp_mflags}"
 echo ""
 fi
 
 echo "%install"
 echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules'
 
-echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make modules_install'
-echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{_smp_mflags} modules_install'
+echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE"
 
-echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE"
 
-echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$KERNELRELEASE"
 echo ""
 echo "%clean"
 echo '#echo -rf $RPM_BUILD_ROOT'
@@ -77,6 +77,6 @@ echo ""
 echo "%files"
 echo '%defattr (-, root, root)'
 echo "%dir /lib/modules"
-echo "/lib/modules/$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo "/lib/modules/$KERNELRELEASE"
 echo "/boot/*"
 echo ""
index 3f316b6..43af010 100755 (executable)
 #
 # Added -ac option, use -ac or -ac9 (say) to stop at a particular version
 #       Dave Gilbert <linux@treblig.org>, 29th September 2001.
+#
+# Add support for (use of) EXTRAVERSION (to support 2.6.8.x, e.g.);
+# update usage message;
+# fix some whitespace damage;
+# be smarter about stopping when current version is larger than requested;
+#      Randy Dunlap <rddunlap@osdl.org>, 2004-AUG-18.
 
 # Set directories from arguments, or use defaults.
 sourcedir=${1-/usr/src/linux}
 patchdir=${2-.}
-stopvers=${3-imnotaversion}
+stopvers=${3-default}
 
-if [ "$1" = -h -o "$1" = --help -o ! -r "$sourcedir/Makefile" ]; then
+if [ "$1" == -h -o "$1" == --help -o ! -r "$sourcedir/Makefile" ]; then
 cat << USAGE
 usage: patch-kernel [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]
-  The source directory defaults to /usr/src/linux, and
-  the patch directory defaults to the current directory.
+  source directory defaults to /usr/src/linux,
+  patch directory defaults to the current directory,
+  stopversion defaults to <all in patchdir>.
 USAGE
 exit 1
 fi
@@ -77,7 +84,7 @@ findFile () {
                uncomp="gunzip -dc"
   elif [ -r ${filebase}.bz  ]; then
                ext=".bz"
-    name="bzip"
+               name="bzip"
                uncomp="bunzip -dc"
   elif [ -r ${filebase}.bz2 ]; then
                ext=".bz2"
@@ -96,8 +103,8 @@ findFile () {
                name="plaintext"
                uncomp="cat"
   else
-         return 1;
-       fi
+       return 1;
+  fi
 
   return 0;
 }
@@ -126,48 +133,100 @@ applyPatch () {
   return 0;
 }
 
-# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTERVERSION
-eval `sed -n -e 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' -e 's/^\([A-Z]*\) = \(-[-a-z0-9]*\)$/\1=\2/p' $sourcedir/Makefile`
+# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION
+TMPFILE=`mktemp .tmpver.XXXXXX` || { echo "cannot make temp file" ; exit 1; }
+grep -E "^(VERSION|PATCHLEVEL|SUBLEVEL|EXTRAVERSION)" $sourcedir/Makefile > $TMPFILE
+tr -d [:blank:] < $TMPFILE > $TMPFILE.1
+source $TMPFILE.1
+rm -f $TMPFILE*
 if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ]
 then
     echo "unable to determine current kernel version" >&2
     exit 1
 fi
 
-echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION}"
+NAME=`grep ^NAME $sourcedir/Makefile`
+NAME=${NAME##*=}
 
+echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} ($NAME)"
+
+# strip EXTRAVERSION to just a number (drop leading '.' and trailing additions)
+EXTRAVER=
 if [ x$EXTRAVERSION != "x" ]
 then
-  echo "I'm sorry but patch-kernel can't work with a kernel source tree that is not a base version"
-       exit 1;
+       if [ ${EXTRAVERSION:0:1} == "." ]; then
+               EXTRAVER=${EXTRAVERSION:1}
+       else
+               EXTRAVER=$EXTRAVERSION
+       fi
+       EXTRAVER=${EXTRAVER%%[[:punct:]]*}
+       #echo "patch-kernel: changing EXTRAVERSION from $EXTRAVERSION to $EXTRAVER"
+fi
+
+#echo "stopvers=$stopvers"
+if [ $stopvers != "default" ]; then
+       STOPSUBLEVEL=`echo $stopvers | cut -d. -f3`
+       STOPEXTRA=`echo $stopvers | cut -d. -f4`
+       #echo "STOPSUBLEVEL=$STOPSUBLEVEL, STOPEXTRA=$STOPEXTRA"
+else
+       STOPSUBLEVEL=9999
+       STOPEXTRA=9999
 fi
 
-while :
+while :                                # incrementing SUBLEVEL (s in v.p.s)
 do
-    CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
-    if [ $stopvers = $CURRENTFULLVERSION ]
-    then
-        echo "Stoping at $CURRENTFULLVERSION base as requested."
+    if [ x$EXTRAVER != "x" ]; then
+       CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER"
+    else
+       CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
+    fi
+
+    if [ $stopvers == $CURRENTFULLVERSION ]; then
+        echo "Stopping at $CURRENTFULLVERSION base as requested."
         break
     fi
 
-    SUBLEVEL=`expr $SUBLEVEL + 1`
+    while :                    # incrementing EXTRAVER (x in v.p.s.x)
+    do
+       EXTRAVER=$((EXTRAVER + 1))
+       FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER"
+       #echo "... trying $FULLVERSION ..."
+
+       patch=patch-$FULLVERSION
+
+       # See if the file exists and find extension
+       findFile $patchdir/${patch} || break
+
+       # Apply the patch and check all is OK
+       applyPatch $patch || break
+
+       continue 2
+    done
+
+    EXTRAVER=
+    SUBLEVEL=$((SUBLEVEL + 1))
     FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
+    #echo "___ trying $FULLVERSION ___"
+
+    if [ $((SUBLEVEL)) -gt $((STOPSUBLEVEL)) ]; then
+       echo "Stopping since sublevel ($SUBLEVEL) is beyond stop-sublevel ($STOPSUBLEVEL)"
+       exit 1
+    fi
 
     patch=patch-$FULLVERSION
 
-               # See if the file exists and find extension
-               findFile $patchdir/${patch} || break
+    # See if the file exists and find extension
+    findFile $patchdir/${patch} || break
 
     # Apply the patch and check all is OK
     applyPatch $patch || break
 done
+#echo "base all done"
 
 if [ x$gotac != x ]; then
   # Out great user wants the -ac patches
        # They could have done -ac (get latest) or -acxx where xx=version they want
-       if [ $gotac == "-ac" ]
-       then
+       if [ $gotac == "-ac" ]; then
          # They want the latest version
                HIGHESTPATCH=0
                for PATCHNAMES in $patchdir/patch-${CURRENTFULLVERSION}-ac*\.*
@@ -176,18 +235,16 @@ if [ x$gotac != x ]; then
                        # Check it is actually a recognised patch type
                        findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${ACVALUE} || break
 
-                 if [ $ACVALUE -gt $HIGHESTPATCH ]
-                       then
+                 if [ $ACVALUE -gt $HIGHESTPATCH ]; then
                          HIGHESTPATCH=$ACVALUE
                  fi
                done
 
-               if [ $HIGHESTPATCH -ne 0 ]
-               then
+               if [ $HIGHESTPATCH -ne 0 ]; then
                        findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH} || break
                        applyPatch patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH}
                else
-                 echo "No ac patches found"
+                 echo "No -ac patches found"
                fi
        else
          # They want an exact version
@@ -198,5 +255,3 @@ if [ x$gotac != x ]; then
                applyPatch patch-${CURRENTFULLVERSION}${gotac}
        fi
 fi
-
-
index 47f14cb..8b5c009 100755 (executable)
@@ -37,8 +37,11 @@ tune2fs 2>&1 | grep "^tune2fs" | sed 's/,//' |  awk \
 fsck.jfs -V 2>&1 | grep version | sed 's/,//' |  awk \
 'NR==1 {print "jfsutils              ", $3}'
 
-reiserfsck -V 2>&1 | grep reiserfsprogs | awk \
-'NR==1{print "reiserfsprogs         ", $NF}'
+reiserfsck -V 2>&1 | grep reiserfsck | awk \
+'NR==1{print "reiserfsprogs         ", $2}'
+
+fsck.reiser4 -V 2>&1 | grep fsck.reiser4 | awk \
+'NR==1{print "reiser4progs          ", $2}'
 
 xfs_db -V 2>&1 | grep version | awk \
 'NR==1{print "xfsprogs              ", $3}'
index d6bc083..ddde53b 100644 (file)
@@ -26,14 +26,14 @@ config SECURITY_NETWORK
 
 config SECURITY_CAPABILITIES
        tristate "Default Linux Capabilities"
-       depends on SECURITY!=n
+       depends on SECURITY
        help
          This enables the "default" Linux capabilities functionality.
          If you are unsure how to answer this question, answer Y.
 
 config SECURITY_ROOTPLUG
        tristate "Root Plug Support"
-       depends on USB && SECURITY!=n
+       depends on USB && SECURITY
        help
          This is a sample LSM module that should only be used as such.
          It prevents any programs running with egid == 0 if a specific
index d74f708..70a9fcf 100644 (file)
@@ -49,7 +49,7 @@ static void __init do_security_initcalls(void)
 }
 
 /**
- * security_scaffolding_startup - initialzes the security scaffolding framework
+ * security_scaffolding_startup - initializes the security scaffolding framework
  *
  * This should be called early in the kernel initialization sequence.
  */
@@ -183,7 +183,7 @@ int mod_unreg_security (const char *name, struct security_operations *ops)
  * capable - calls the currently loaded security module's capable() function with the specified capability
  * @cap: the requested capability level.
  *
- * This function calls the currently loaded security module's cabable()
+ * This function calls the currently loaded security module's capable()
  * function with a pointer to the current task and the specified @cap value.
  *
  * This allows the security module to implement the capable function call
index 8b4f596..66fbdbb 100644 (file)
  (keyp->source_type << 9)) & \
  AVTAB_HASH_MASK)
 
+static kmem_cache_t *avtab_node_cachep;
+
 static struct avtab_node*
 avtab_insert_node(struct avtab *h, int hvalue, struct avtab_node * prev, struct avtab_node * cur,
                  struct avtab_key *key, struct avtab_datum *datum)
 {
        struct avtab_node * newnode;
-       newnode = (struct avtab_node *) kmalloc(sizeof(struct avtab_node),GFP_KERNEL);
+       newnode = kmem_cache_alloc(avtab_node_cachep, SLAB_KERNEL);
        if (newnode == NULL)
                return NULL;
        memset(newnode, 0, sizeof(struct avtab_node));
@@ -226,7 +228,7 @@ void avtab_destroy(struct avtab *h)
                while (cur != NULL) {
                        temp = cur;
                        cur = cur->next;
-                       kfree(temp);
+                       kmem_cache_free(avtab_node_cachep, temp);
                }
                h->htable[i] = NULL;
        }
@@ -399,3 +401,9 @@ bad:
        goto out;
 }
 
+void avtab_cache_init(void)
+{
+       avtab_node_cachep = kmem_cache_create("avtab_node",
+                                             sizeof(struct avtab_node),
+                                             0, SLAB_PANIC, NULL, NULL);
+}
index 842636d..f1d1757 100644 (file)
@@ -78,6 +78,8 @@ struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key, int
 
 struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified);
 
+void avtab_cache_init(void);
+
 #define AVTAB_HASH_BITS 15
 #define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS)
 #define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1)
index 8b800ad..31321c1 100644 (file)
@@ -251,7 +251,6 @@ struct policydb {
 extern int policydb_init(struct policydb *p);
 extern int policydb_index_classes(struct policydb *p);
 extern int policydb_index_others(struct policydb *p);
-extern int constraint_expr_destroy(struct constraint_expr *expr);
 extern void policydb_destroy(struct policydb *p);
 extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
 extern int policydb_context_isvalid(struct policydb *p, struct context *c);
index ab57ca6..18c71f9 100644 (file)
@@ -47,7 +47,7 @@ int snd_device_new(snd_card_t *card, snd_device_type_t type,
        snd_device_t *dev;
 
        snd_assert(card != NULL && device_data != NULL && ops != NULL, return -ENXIO);
-       dev = (snd_device_t *) snd_magic_kcalloc(snd_device_t, 0, GFP_KERNEL);
+       dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
        if (dev == NULL)
                return -ENOMEM;
        dev->card = card;
@@ -94,7 +94,7 @@ int snd_device_free(snd_card_t *card, void *device_data)
                                        snd_printk(KERN_ERR "device free failure\n");
                        }
                }
-               snd_magic_kfree(dev);
+               kfree(dev);
                return 0;
        }
        snd_printd("device free %p (from %p), not found\n", device_data, __builtin_return_address(0));
index d18e476..b79f231 100644 (file)
@@ -22,6 +22,7 @@
 #include <sound/driver.h>
 #include <linux/major.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <sound/core.h>
@@ -49,7 +50,7 @@ static int snd_hwdep_dev_unregister(snd_device_t *device);
 
 static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig)
 {
-       snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+       snd_hwdep_t *hw = file->private_data;
        if (hw->ops.llseek)
                return hw->ops.llseek(hw, file, offset, orig);
        return -ENXIO;
@@ -57,7 +58,7 @@ static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig)
 
 static ssize_t snd_hwdep_read(struct file * file, char __user *buf, size_t count, loff_t *offset)
 {
-       snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+       snd_hwdep_t *hw = file->private_data;
        if (hw->ops.read)
                return hw->ops.read(hw, buf, count, offset);
        return -ENXIO;  
@@ -65,7 +66,7 @@ static ssize_t snd_hwdep_read(struct file * file, char __user *buf, size_t count
 
 static ssize_t snd_hwdep_write(struct file * file, const char __user *buf, size_t count, loff_t *offset)
 {
-       snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+       snd_hwdep_t *hw = file->private_data;
        if (hw->ops.write)
                return hw->ops.write(hw, buf, count, offset);
        return -ENXIO;  
@@ -157,7 +158,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
 static int snd_hwdep_release(struct inode *inode, struct file * file)
 {
        int err = -ENXIO;
-       snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+       snd_hwdep_t *hw = file->private_data;
        down(&hw->open_mutex);
        if (hw->ops.release) {
                err = hw->ops.release(hw, file);
@@ -173,7 +174,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file)
 
 static unsigned int snd_hwdep_poll(struct file * file, poll_table * wait)
 {
-       snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return 0);
+       snd_hwdep_t *hw = file->private_data;
        if (hw->ops.poll)
                return hw->ops.poll(hw, file, wait);
        return 0;
@@ -231,10 +232,10 @@ static int snd_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t __user *_in
        return 0;
 }
 
-static insnd_hwdep_ioctl(struct inode *inode, struct file * file,
-                          unsigned int cmd, unsigned long arg)
+static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file,
+                                  unsigned int cmd, unsigned long arg)
 {
-       snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+       snd_hwdep_t *hw = file->private_data;
        void __user *argp = (void __user *)arg;
        switch (cmd) {
        case SNDRV_HWDEP_IOCTL_PVERSION:
@@ -251,9 +252,20 @@ static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
        return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
+                          unsigned int cmd, unsigned long arg)
+{
+       int err;
+       unlock_kernel();
+       err = _snd_hwdep_ioctl(inode, file, cmd, arg);
+       lock_kernel();
+       return err;
+}
+
 static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma)
 {
-       snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+       snd_hwdep_t *hw = file->private_data;
        if (hw->ops.mmap)
                return hw->ops.mmap(hw, file, vma);
        return -ENXIO;
@@ -352,7 +364,7 @@ int snd_hwdep_new(snd_card_t * card, char *id, int device, snd_hwdep_t ** rhwdep
        snd_assert(rhwdep != NULL, return -EINVAL);
        *rhwdep = NULL;
        snd_assert(card != NULL, return -ENXIO);
-       hwdep = snd_magic_kcalloc(snd_hwdep_t, 0, GFP_KERNEL);
+       hwdep = kcalloc(1, sizeof(*hwdep), GFP_KERNEL);
        if (hwdep == NULL)
                return -ENOMEM;
        hwdep->card = card;
@@ -378,19 +390,19 @@ static int snd_hwdep_free(snd_hwdep_t *hwdep)
        snd_assert(hwdep != NULL, return -ENXIO);
        if (hwdep->private_free)
                hwdep->private_free(hwdep);
-       snd_magic_kfree(hwdep);
+       kfree(hwdep);
        return 0;
 }
 
 static int snd_hwdep_dev_free(snd_device_t *device)
 {
-       snd_hwdep_t *hwdep = snd_magic_cast(snd_hwdep_t, device->device_data, return -ENXIO);
+       snd_hwdep_t *hwdep = device->device_data;
        return snd_hwdep_free(hwdep);
 }
 
 static int snd_hwdep_dev_register(snd_device_t *device)
 {
-       snd_hwdep_t *hwdep = snd_magic_cast(snd_hwdep_t, device->device_data, return -ENXIO);
+       snd_hwdep_t *hwdep = device->device_data;
        int idx, err;
        char name[32];
 
@@ -433,7 +445,7 @@ static int snd_hwdep_dev_register(snd_device_t *device)
 
 static int snd_hwdep_dev_unregister(snd_device_t *device)
 {
-       snd_hwdep_t *hwdep = snd_magic_cast(snd_hwdep_t, device->device_data, return -ENXIO);
+       snd_hwdep_t *hwdep = device->device_data;
        int idx;
 
        snd_assert(hwdep != NULL, return -ENXIO);
index 1eb7d91..db1e257 100644 (file)
@@ -139,7 +139,7 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
        struct snd_info_entry *entry;
        loff_t ret;
 
-       data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+       data = file->private_data;
        entry = data->entry;
        lock_kernel();
        switch (entry->content) {
@@ -183,7 +183,7 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
        size_t size = 0;
        loff_t pos;
 
-       data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+       data = file->private_data;
        snd_assert(data != NULL, return -ENXIO);
        pos = *offset;
        if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
@@ -224,7 +224,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer
        size_t size = 0;
        loff_t pos;
 
-       data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+       data = file->private_data;
        snd_assert(data != NULL, return -ENXIO);
        entry = data->entry;
        pos = *offset;
@@ -296,7 +296,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
                        goto __error;
                }
        }
-       data = snd_magic_kcalloc(snd_info_private_data_t, 0, GFP_KERNEL);
+       data = kcalloc(1, sizeof(*data), GFP_KERNEL);
        if (data == NULL) {
                err = -ENOMEM;
                goto __error;
@@ -305,10 +305,9 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
        switch (entry->content) {
        case SNDRV_INFO_CONTENT_TEXT:
                if (mode == O_RDONLY || mode == O_RDWR) {
-                       buffer = (snd_info_buffer_t *)
-                                       snd_kcalloc(sizeof(snd_info_buffer_t), GFP_KERNEL);
+                       buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
                        if (buffer == NULL) {
-                               snd_magic_kfree(data);
+                               kfree(data);
                                err = -ENOMEM;
                                goto __error;
                        }
@@ -317,7 +316,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
                        buffer->buffer = vmalloc(buffer->len);
                        if (buffer->buffer == NULL) {
                                kfree(buffer);
-                               snd_magic_kfree(data);
+                               kfree(data);
                                err = -ENOMEM;
                                goto __error;
                        }
@@ -325,14 +324,13 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
                        data->rbuffer = buffer;
                }
                if (mode == O_WRONLY || mode == O_RDWR) {
-                       buffer = (snd_info_buffer_t *)
-                                       snd_kcalloc(sizeof(snd_info_buffer_t), GFP_KERNEL);
+                       buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
                        if (buffer == NULL) {
                                if (mode == O_RDWR) {
                                        vfree(data->rbuffer->buffer);
                                        kfree(data->rbuffer);
                                }
-                               snd_magic_kfree(data);
+                               kfree(data);
                                err = -ENOMEM;
                                goto __error;
                        }
@@ -345,7 +343,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
                                        kfree(data->rbuffer);
                                }
                                kfree(buffer);
-                               snd_magic_kfree(data);
+                               kfree(data);
                                err = -ENOMEM;
                                goto __error;
                        }
@@ -357,7 +355,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
                if (entry->c.ops->open) {
                        if ((err = entry->c.ops->open(entry, mode,
                                                      &data->file_private_data)) < 0) {
-                               snd_magic_kfree(data);
+                               kfree(data);
                                goto __error;
                        }
                }
@@ -389,7 +387,7 @@ static int snd_info_entry_release(struct inode *inode, struct file *file)
        int mode;
 
        mode = file->f_flags & O_ACCMODE;
-       data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+       data = file->private_data;
        entry = data->entry;
        switch (entry->content) {
        case SNDRV_INFO_CONTENT_TEXT:
@@ -417,7 +415,7 @@ static int snd_info_entry_release(struct inode *inode, struct file *file)
                break;
        }
        module_put(entry->module);
-       snd_magic_kfree(data);
+       kfree(data);
        return 0;
 }
 
@@ -427,7 +425,7 @@ static unsigned int snd_info_entry_poll(struct file *file, poll_table * wait)
        struct snd_info_entry *entry;
        unsigned int mask;
 
-       data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+       data = file->private_data;
        if (data == NULL)
                return 0;
        entry = data->entry;
@@ -447,13 +445,13 @@ static unsigned int snd_info_entry_poll(struct file *file, poll_table * wait)
        return mask;
 }
 
-static insnd_info_entry_ioctl(struct inode *inode, struct file *file,
-                               unsigned int cmd, unsigned long arg)
+static inline int _snd_info_entry_ioctl(struct inode *inode, struct file *file,
+                                       unsigned int cmd, unsigned long arg)
 {
        snd_info_private_data_t *data;
        struct snd_info_entry *entry;
 
-       data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+       data = file->private_data;
        if (data == NULL)
                return 0;
        entry = data->entry;
@@ -468,13 +466,24 @@ static int snd_info_entry_ioctl(struct inode *inode, struct file *file,
        return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_info_entry_ioctl(struct inode *inode, struct file *file,
+                               unsigned int cmd, unsigned long arg)
+{
+       int err;
+       unlock_kernel();
+       err = _snd_info_entry_ioctl(inode, file, cmd, arg);
+       lock_kernel();
+       return err;
+}
+
 static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct inode *inode = file->f_dentry->d_inode;
        snd_info_private_data_t *data;
        struct snd_info_entry *entry;
 
-       data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+       data = file->private_data;
        if (data == NULL)
                return 0;
        entry = data->entry;
@@ -744,12 +753,12 @@ char *snd_info_get_str(char *dest, char *src, int len)
 static snd_info_entry_t *snd_info_create_entry(const char *name)
 {
        snd_info_entry_t *entry;
-       entry = snd_magic_kcalloc(snd_info_entry_t, 0, GFP_KERNEL);
+       entry = kcalloc(1, sizeof(*entry), GFP_KERNEL);
        if (entry == NULL)
                return NULL;
        entry->name = snd_kmalloc_strdup(name, GFP_KERNEL);
        if (entry->name == NULL) {
-               snd_magic_kfree(entry);
+               kfree(entry);
                return NULL;
        }
        entry->mode = S_IFREG | S_IRUGO;
@@ -805,27 +814,27 @@ snd_info_entry_t *snd_info_create_card_entry(snd_card_t * card,
 
 static int snd_info_dev_free_entry(snd_device_t *device)
 {
-       snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+       snd_info_entry_t *entry = device->device_data;
        snd_info_free_entry(entry);
        return 0;
 }
 
 static int snd_info_dev_register_entry(snd_device_t *device)
 {
-       snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+       snd_info_entry_t *entry = device->device_data;
        return snd_info_register(entry);
 }
 
 static int snd_info_dev_disconnect_entry(snd_device_t *device)
 {
-       snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+       snd_info_entry_t *entry = device->device_data;
        entry->disconnected = 1;
        return 0;
 }
 
 static int snd_info_dev_unregister_entry(snd_device_t *device)
 {
-       snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+       snd_info_entry_t *entry = device->device_data;
        return snd_info_unregister(entry);
 }
 
@@ -887,7 +896,7 @@ void snd_info_free_entry(snd_info_entry_t * entry)
                kfree((char *)entry->name);
        if (entry->private_free)
                entry->private_free(entry);
-       snd_magic_kfree(entry);
+       kfree(entry);
 }
 
 /**
index 2326106..f9e4ce4 100644 (file)
@@ -134,16 +134,4 @@ int snd_info_minor_unregister(void)
        return 0;
 }
 
-#else
-
-int snd_info_minor_register(void)
-{
-       return 0;
-}
-
-int snd_info_minor_unregister(void)
-{
-       return 0;
-}
-
 #endif /* CONFIG_SND_OSSEMUL */
index cf4f75c..21f76c2 100644 (file)
@@ -71,8 +71,7 @@ void snd_memory_done(void)
                snd_printk(KERN_ERR "Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc);
        if (snd_alloc_vmalloc > 0)
                snd_printk(KERN_ERR "Not freed snd_alloc_vmalloc = %li\n", snd_alloc_vmalloc);
-       for (head = snd_alloc_kmalloc_list.prev;
-            head != &snd_alloc_kmalloc_list; head = head->prev) {
+       list_for_each_prev(head, &snd_alloc_kmalloc_list) {
                t = list_entry(head, struct snd_alloc_track, list);
                if (t->magic != KMALLOC_MAGIC) {
                        snd_printk(KERN_ERR "Corrupted kmalloc\n");
@@ -80,8 +79,7 @@ void snd_memory_done(void)
                }
                snd_printk(KERN_ERR "kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller);
        }
-       for (head = snd_alloc_vmalloc_list.prev;
-            head != &snd_alloc_vmalloc_list; head = head->prev) {
+       list_for_each_prev(head, &snd_alloc_vmalloc_list) {
                t = list_entry(head, struct snd_alloc_track, list);
                if (t->magic != VMALLOC_MAGIC) {
                        snd_printk(KERN_ERR "Corrupted vmalloc\n");
@@ -118,6 +116,17 @@ void *snd_hidden_kmalloc(size_t size, int flags)
        return _snd_kmalloc(size, flags);
 }
 
+void *snd_hidden_kcalloc(size_t n, size_t size, int flags)
+{
+       void *ret = NULL;
+       if (n != 0 && size > INT_MAX / n)
+               return ret;
+       ret = _snd_kmalloc(n * size, flags);
+       if (ret)
+               memset(ret, 0, n * size);
+       return ret;
+}
+
 void snd_hidden_kfree(const void *obj)
 {
        unsigned long flags;
@@ -140,46 +149,6 @@ void snd_hidden_kfree(const void *obj)
        snd_wrapper_kfree(obj);
 }
 
-void *_snd_magic_kcalloc(unsigned long magic, size_t size, int flags)
-{
-       unsigned long *ptr;
-       ptr = _snd_kmalloc(size + sizeof(unsigned long), flags);
-       if (ptr) {
-               *ptr++ = magic;
-               memset(ptr, 0, size);
-       }
-       return ptr;
-}
-
-void *_snd_magic_kmalloc(unsigned long magic, size_t size, int flags)
-{
-       unsigned long *ptr;
-       ptr = _snd_kmalloc(size + sizeof(unsigned long), flags);
-       if (ptr)
-               *ptr++ = magic;
-       return ptr;
-}
-
-void snd_magic_kfree(void *_ptr)
-{
-       unsigned long *ptr = _ptr;
-       if (ptr == NULL) {
-               snd_printk(KERN_WARNING "null snd_magic_kfree (called from %p)\n", __builtin_return_address(0));
-               return;
-       }
-       *--ptr = 0;
-       {
-               struct snd_alloc_track *t;
-               t = snd_alloc_track_entry(ptr);
-               if (t->magic != KMALLOC_MAGIC) {
-                       snd_printk(KERN_ERR "bad snd_magic_kfree (called from %p)\n", __builtin_return_address(0));
-                       return;
-               }
-       }
-       snd_hidden_kfree(ptr);
-       return;
-}
-
 void *snd_hidden_vmalloc(unsigned long size)
 {
        void *ptr;
@@ -255,25 +224,6 @@ int __exit snd_memory_info_done(void)
 
 #endif /* CONFIG_SND_DEBUG_MEMORY */
 
-/**
- * snd_kcalloc - memory allocation and zero-clear
- * @size: the size to allocate in bytes
- * @flags: allocation conditions, GFP_XXX
- *
- * Allocates a memory chunk via kmalloc() and initializes it to zero.
- *
- * Returns the pointer, or NULL if no enoguh memory.
- */
-void *snd_kcalloc(size_t size, int flags)
-{
-       void *ptr;
-       
-       ptr = _snd_kmalloc(size, flags);
-       if (ptr)
-               memset(ptr, 0, size);
-       return ptr;
-}
-
 /**
  * snd_kmalloc_strdup - copy the string
  * @string: the original string
index d8359d3..caab3ee 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <sound/core.h>
@@ -51,7 +52,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
        err = snd_card_file_add(card, file);
        if (err < 0)
                return err;
-       fmixer = (snd_mixer_oss_file_t *)snd_kcalloc(sizeof(*fmixer), GFP_KERNEL);
+       fmixer = kcalloc(1, sizeof(*fmixer), GFP_KERNEL);
        if (fmixer == NULL) {
                snd_card_file_remove(card, file);
                return -ENOMEM;
@@ -358,10 +359,16 @@ static int snd_mixer_oss_ioctl1(snd_mixer_oss_file_t *fmixer, unsigned int cmd,
        return -ENXIO;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
 int snd_mixer_oss_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
-       return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
+       int err;
+       /* FIXME: need to unlock BKL to allow preemption */
+       unlock_kernel();
+       err = snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
+       lock_kernel();
+       return err;
 }
 
 int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg)
@@ -508,8 +515,8 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
                up_read(&card->controls_rwsem);
                return;
        }
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL)
                goto __unalloc;
        snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -544,8 +551,8 @@ static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
                up_read(&card->controls_rwsem);
                return;
        }
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL)
                goto __unalloc;
        snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -607,8 +614,8 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
        down_read(&card->controls_rwsem);
        if ((kctl = snd_ctl_find_numid(card, numid)) == NULL)
                return;
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL)
                goto __unalloc;
        snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -646,8 +653,8 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
                up_read(&fmixer->card->controls_rwsem);
                return;
        }
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL)
                goto __unalloc;
        snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -767,8 +774,8 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
        snd_ctl_elem_value_t *uctl;
        int err, idx;
        
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL) {
                err = -ENOMEM;
                goto __unlock;
@@ -814,8 +821,8 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
        int err;
        unsigned int idx;
 
-       uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-       uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+       uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+       uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL) {
                err = -ENOMEM;
                goto __unlock;
@@ -968,8 +975,10 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os
                snd_ctl_elem_info_t uinfo;
 
                memset(&uinfo, 0, sizeof(uinfo));
-               if (kctl->info(kctl, &uinfo))
+               if (kctl->info(kctl, &uinfo)) {
+                       up_read(&mixer->card->controls_rwsem);
                        return 0;
+               }
                strcpy(str, ptr->name);
                if (!strcmp(str, "Master"))
                        strcpy(str, "Mix");
@@ -1060,7 +1069,7 @@ static char *oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = {
 static void snd_mixer_oss_proc_read(snd_info_entry_t *entry,
                                    snd_info_buffer_t * buffer)
 {
-       snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, entry->private_data, return);
+       snd_mixer_oss_t *mixer = entry->private_data;
        int i;
 
        down(&mixer->reg_mutex);
@@ -1084,7 +1093,7 @@ static void snd_mixer_oss_proc_read(snd_info_entry_t *entry,
 static void snd_mixer_oss_proc_write(snd_info_entry_t *entry,
                                     snd_info_buffer_t * buffer)
 {
-       snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, entry->private_data, return);
+       snd_mixer_oss_t *mixer = entry->private_data;
        char line[128], str[32], idxstr[16], *cptr;
        int ch, idx;
        struct snd_mixer_oss_assign_table *tbl;
@@ -1210,7 +1219,7 @@ static void snd_mixer_oss_build(snd_mixer_oss_t *mixer)
        };
        unsigned int idx;
        
-       for (idx = 0; idx < sizeof(table) / sizeof(struct snd_mixer_oss_assign_table); idx++)
+       for (idx = 0; idx < ARRAY_SIZE(table); idx++)
                snd_mixer_oss_build_input(mixer, &table[idx], 0, 0);
        if (mixer->mask_recsrc) {
                mixer->get_recsrc = snd_mixer_oss_get_recsrc2;
@@ -1224,7 +1233,7 @@ static void snd_mixer_oss_build(snd_mixer_oss_t *mixer)
 
 static int snd_mixer_oss_free1(void *private)
 {
-       snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, private, return -ENXIO);
+       snd_mixer_oss_t *mixer = private;
        snd_card_t * card;
        int idx;
  
@@ -1237,7 +1246,7 @@ static int snd_mixer_oss_free1(void *private)
                if (chn->private_free)
                        chn->private_free(chn);
        }
-       snd_magic_kfree(mixer);
+       kfree(mixer);
        return 0;
 }
 
@@ -1249,7 +1258,7 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int cmd)
                char name[128];
                int idx, err;
 
-               mixer = snd_magic_kcalloc(snd_mixer_oss_t, sizeof(snd_mixer_oss_t), GFP_KERNEL);
+               mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL);
                if (mixer == NULL)
                        return -ENOMEM;
                init_MUTEX(&mixer->reg_mutex);
@@ -1259,7 +1268,7 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int cmd)
                                                   &snd_mixer_oss_reg,
                                                   name)) < 0) {
                        snd_printk("unable to register OSS mixer device %i:%i\n", card->number, 0);
-                       snd_magic_kfree(mixer);
+                       kfree(mixer);
                        return err;
                }
                mixer->oss_dev_alloc = 1;
index 342ec09..e21c136 100644 (file)
@@ -35,7 +35,7 @@ static inline size_t bitset_size(int nbits)
 
 static inline bitset_t *bitset_alloc(int nbits)
 {
-       return snd_kcalloc(bitset_size(nbits) * sizeof(bitset_t), GFP_KERNEL);
+       return kcalloc(bitset_size(nbits), sizeof(bitset_t), GFP_KERNEL);
 }
        
 static inline void bitset_set(bitset_t *bitmap, unsigned int pos)
index 8ee8fa7..d25dad4 100644 (file)
@@ -585,7 +585,7 @@ int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count)
        }
        prev = NULL;
        for (idx = 0, prev = NULL; idx < substream_count; idx++) {
-               substream = snd_magic_kcalloc(snd_pcm_substream_t, 0, GFP_KERNEL);
+               substream = kcalloc(1, sizeof(*substream), GFP_KERNEL);
                if (substream == NULL)
                        return -ENOMEM;
                substream->pcm = pcm;
@@ -600,7 +600,7 @@ int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count)
                        prev->next = substream;
                err = snd_pcm_substream_proc_init(substream);
                if (err < 0) {
-                       snd_magic_kfree(substream);
+                       kfree(substream);
                        return err;
                }
                substream->group = &substream->self_group;
@@ -645,7 +645,7 @@ int snd_pcm_new(snd_card_t * card, char *id, int device,
        snd_assert(rpcm != NULL, return -EINVAL);
        *rpcm = NULL;
        snd_assert(card != NULL, return -ENXIO);
-       pcm = snd_magic_kcalloc(snd_pcm_t, 0, GFP_KERNEL);
+       pcm = kcalloc(1, sizeof(*pcm), GFP_KERNEL);
        if (pcm == NULL)
                return -ENOMEM;
        pcm->card = card;
@@ -681,7 +681,7 @@ static void snd_pcm_free_stream(snd_pcm_str_t * pstr)
        while (substream) {
                substream_next = substream->next;
                snd_pcm_substream_proc_done(substream);
-               snd_magic_kfree(substream);
+               kfree(substream);
                substream = substream_next;
        }
        snd_pcm_stream_proc_done(pstr);
@@ -702,13 +702,13 @@ static int snd_pcm_free(snd_pcm_t *pcm)
        snd_pcm_lib_preallocate_free_for_all(pcm);
        snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]);
        snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_CAPTURE]);
-       snd_magic_kfree(pcm);
+       kfree(pcm);
        return 0;
 }
 
 static int snd_pcm_dev_free(snd_device_t *device)
 {
-       snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+       snd_pcm_t *pcm = device->device_data;
        return snd_pcm_free(pcm);
 }
 
@@ -783,7 +783,7 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
        if (substream == NULL)
                return -EAGAIN;
 
-       runtime = snd_kcalloc(sizeof(snd_pcm_runtime_t), GFP_KERNEL);
+       runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL);
        if (runtime == NULL)
                return -ENOMEM;
 
@@ -843,7 +843,7 @@ static int snd_pcm_dev_register(snd_device_t *device)
        snd_pcm_substream_t *substream;
        struct list_head *list;
        char str[16];
-       snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+       snd_pcm_t *pcm = device->device_data;
 
        snd_assert(pcm != NULL && device != NULL, return -ENXIO);
        down(&register_mutex);
@@ -888,7 +888,7 @@ static int snd_pcm_dev_register(snd_device_t *device)
 
 static int snd_pcm_dev_disconnect(snd_device_t *device)
 {
-       snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+       snd_pcm_t *pcm = device->device_data;
        struct list_head *list;
        snd_pcm_substream_t *substream;
        int idx, cidx;
@@ -914,7 +914,7 @@ static int snd_pcm_dev_unregister(snd_device_t *device)
        int idx, cidx, devtype;
        snd_pcm_substream_t *substream;
        struct list_head *list;
-       snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+       snd_pcm_t *pcm = device->device_data;
 
        snd_assert(pcm != NULL, return -ENXIO);
        down(&register_mutex);
@@ -1050,6 +1050,9 @@ EXPORT_SYMBOL(snd_pcm_release);
 EXPORT_SYMBOL(snd_pcm_playback_poll);
 EXPORT_SYMBOL(snd_pcm_capture_poll);
 EXPORT_SYMBOL(snd_pcm_mmap_data);
+#if SNDRV_PCM_INFO_MMAP_IOMEM
+EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
+#endif
  /* pcm_misc.c */
 EXPORT_SYMBOL(snd_pcm_format_signed);
 EXPORT_SYMBOL(snd_pcm_format_unsigned);
index 4012197..884eaea 100644 (file)
@@ -25,8 +25,6 @@
 #include <sound/pcm.h>
 #include <sound/timer.h>
 
-#define chip_t snd_pcm_substream_t
-
 /*
  *  Timer functions
  */
@@ -49,7 +47,7 @@ static unsigned long gcd(unsigned long a, unsigned long b)
 
 void snd_pcm_timer_resolution_change(snd_pcm_substream_t *substream)
 {
-       unsigned long rate, mult, fsize, l;
+       unsigned long rate, mult, fsize, l, post;
        snd_pcm_runtime_t *runtime = substream->runtime;
        
         mult = 1000000000;
@@ -63,23 +61,24 @@ void snd_pcm_timer_resolution_change(snd_pcm_substream_t *substream)
        l = gcd(rate, fsize);
        rate /= l;
        fsize /= l;
+       post = 1;
        while ((mult * fsize) / fsize != mult) {
                mult /= 2;
-               rate /= 2;
+               post *= 2;
        }
        if (rate == 0) {
                snd_printk(KERN_ERR "pcm timer resolution out of range (rate = %u, period_size = %lu)\n", runtime->rate, runtime->period_size);
                runtime->timer_resolution = -1;
                return;
        }
-       runtime->timer_resolution = mult * fsize / rate;
+       runtime->timer_resolution = (mult * fsize / rate) * post;
 }
 
 static unsigned long snd_pcm_timer_resolution(snd_timer_t * timer)
 {
        snd_pcm_substream_t * substream;
        
-       substream = snd_magic_cast(snd_pcm_substream_t, timer->private_data, return -ENXIO);
+       substream = timer->private_data;
        return substream->runtime ? substream->runtime->timer_resolution : 0;
 }
 
@@ -123,7 +122,7 @@ static struct _snd_timer_hardware snd_pcm_timer =
 
 static void snd_pcm_timer_free(snd_timer_t *timer)
 {
-       snd_pcm_substream_t *substream = snd_magic_cast(snd_pcm_substream_t, timer->private_data, return);
+       snd_pcm_substream_t *substream = timer->private_data;
        substream->timer = NULL;
 }
 
index 648a7b8..52a070b 100644 (file)
@@ -29,8 +29,6 @@
 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture FM Instrument support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_fm_id = SNDRV_SEQ_INSTR_ID_OPL2_3;
 
index 13b46be..6c21e52 100644 (file)
@@ -30,8 +30,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_gf1_id = SNDRV_SEQ_INSTR_ID_GUS_PATCH;
 
@@ -64,7 +62,7 @@ static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t *ops,
                return -EFAULT;
        *data += sizeof(xp);
        *len -= sizeof(xp);
-       wp = (gf1_wave_t *)snd_kcalloc(sizeof(*wp), gfp_mask);
+       wp = kcalloc(1, sizeof(*wp), gfp_mask);
        if (wp == NULL)
                return -ENOMEM;
        wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
index cd9ea55..005171a 100644 (file)
@@ -30,8 +30,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_iwffff_id = SNDRV_SEQ_INSTR_ID_INTERWAVE;
 
@@ -96,7 +94,7 @@ static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
                points_size = (le16_to_cpu(rx.nattack) + le16_to_cpu(rx.nrelease)) * 2 * sizeof(__u16);
                if (points_size > *len)
                        return -EINVAL;
-               rp = (iwffff_env_record_t *)snd_kcalloc(sizeof(*rp) + points_size, gfp_mask);
+               rp = kcalloc(1, sizeof(*rp) + points_size, gfp_mask);
                if (rp == NULL)
                        return -ENOMEM;
                rp->nattack = le16_to_cpu(rx.nattack);
@@ -142,7 +140,7 @@ static int snd_seq_iwffff_copy_wave_from_stream(snd_iwffff_ops_t *ops,
                return -EFAULT;
        *data += sizeof(xp);
        *len -= sizeof(xp);
-       wp = (iwffff_wave_t *)snd_kcalloc(sizeof(*wp), gfp_mask);
+       wp = kcalloc(1, sizeof(*wp), gfp_mask);
        if (wp == NULL)
                return -ENOMEM;
        wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
@@ -275,7 +273,7 @@ static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr,
                        snd_seq_iwffff_instr_free(ops, ip, atomic);
                        return -EINVAL;
                }
-               lp = (iwffff_layer_t *)snd_kcalloc(sizeof(*lp), gfp_mask);
+               lp = kcalloc(1, sizeof(*lp), gfp_mask);
                if (lp == NULL) {
                        snd_seq_iwffff_instr_free(ops, ip, atomic);
                        return -ENOMEM;
index 0f81178..8ae5d10 100644 (file)
@@ -30,8 +30,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_simple_id = SNDRV_SEQ_INSTR_ID_SIMPLE;
 
index 6d783cd..e86f18d 100644 (file)
 #include "seq_oss_midi.h"
 #include "seq_oss_event.h"
 
+static int snd_seq_oss_synth_info_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+       struct synth_info info;
+
+       if (copy_from_user(&info, arg, sizeof(info)))
+               return -EFAULT;
+       if (snd_seq_oss_synth_make_info(dp, info.device, &info) < 0)
+               return -EINVAL;
+       if (copy_to_user(arg, &info, sizeof(info)))
+               return -EFAULT;
+       return 0;
+}
+
+static int snd_seq_oss_midi_info_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+       struct midi_info info;
+
+       if (copy_from_user(&info, arg, sizeof(info)))
+               return -EFAULT;
+       if (snd_seq_oss_midi_make_info(dp, info.device, &info) < 0)
+               return -EINVAL;
+       if (copy_to_user(arg, &info, sizeof(info)))
+               return -EFAULT;
+       return 0;
+}
+
+static int snd_seq_oss_oob_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+       unsigned char ev[8];
+       snd_seq_event_t tmpev;
+
+       if (copy_from_user(ev, arg, 8))
+               return -EFAULT;
+       memset(&tmpev, 0, sizeof(tmpev));
+       snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
+       tmpev.time.tick = 0;
+       if (! snd_seq_oss_process_event(dp, (evrec_t*)ev, &tmpev)) {
+               snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
+       }
+       return 0;
+}
+
 int
 snd_seq_oss_ioctl(seq_oss_devinfo_t *dp, unsigned int cmd, unsigned long carg)
 {
        int dev, val;
-       struct synth_info inf;
-       struct midi_info minf;
-       unsigned char ev[8];
        void __user *arg = (void __user *)carg;
        int __user *p = arg;
-       snd_seq_event_t tmpev;
 
        switch (cmd) {
        case SNDCTL_TMR_TIMEBASE:
@@ -124,35 +162,15 @@ snd_seq_oss_ioctl(seq_oss_devinfo_t *dp, unsigned int cmd, unsigned long carg)
        case SNDCTL_SYNTH_INFO:
        case SNDCTL_SYNTH_ID:
                debug_printk(("synth info\n"));
-               if (copy_from_user(&inf, arg, sizeof(inf)))
-                       return -EFAULT;
-               if (snd_seq_oss_synth_make_info(dp, inf.device, &inf) < 0)
-                       return -EINVAL;
-               if (copy_to_user(arg, &inf, sizeof(inf)))
-                       return -EFAULT;
-               return 0;
+               return snd_seq_oss_synth_info_user(dp, arg);
 
        case SNDCTL_SEQ_OUTOFBAND:
-               debug_printk(("out of bound\n"));
-               if (copy_from_user(ev, arg, 8))
-                       return -EFAULT;
-               memset(&tmpev, 0, sizeof(tmpev));
-               snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
-               tmpev.time.tick = 0;
-               if (! snd_seq_oss_process_event(dp, (evrec_t*)ev, &tmpev)) {
-                       snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
-               }
-               return 0;
+               debug_printk(("out of band\n"));
+               return snd_seq_oss_oob_user(dp, arg);
 
        case SNDCTL_MIDI_INFO:
                debug_printk(("midi info\n"));
-               if (copy_from_user(&minf, arg, sizeof(minf)))
-                       return -EFAULT;
-               if (snd_seq_oss_midi_make_info(dp, minf.device, &minf) < 0)
-                       return -EINVAL;
-               if (copy_to_user(arg, &minf, sizeof(minf)))
-                       return -EFAULT;
-               return 0;
+               return snd_seq_oss_midi_info_user(dp, arg);
 
        case SNDCTL_SEQ_THRESHOLD:
                debug_printk(("threshold\n"));
index f7e82fc..60fb5fb 100644 (file)
@@ -171,7 +171,7 @@ snd_seq_oss_midi_check_new_port(snd_seq_port_info_t *pinfo)
        /*
         * allocate midi info record
         */
-       if ((mdev = snd_kcalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) {
+       if ((mdev = kcalloc(1, sizeof(*mdev), GFP_KERNEL)) == NULL) {
                snd_printk(KERN_ERR "can't malloc midi info\n");
                return -ENOMEM;
        }
index 9690f80..dfe6a5c 100644 (file)
@@ -45,12 +45,12 @@ snd_seq_oss_readq_new(seq_oss_devinfo_t *dp, int maxlen)
 {
        seq_oss_readq_t *q;
 
-       if ((q = snd_kcalloc(sizeof(*q), GFP_KERNEL)) == NULL) {
+       if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL) {
                snd_printk(KERN_ERR "can't malloc read queue\n");
                return NULL;
        }
 
-       if ((q->q = snd_kcalloc(sizeof(evrec_t) * maxlen, GFP_KERNEL)) == NULL) {
+       if ((q->q = kcalloc(maxlen, sizeof(evrec_t), GFP_KERNEL)) == NULL) {
                snd_printk(KERN_ERR "can't malloc read queue buffer\n");
                kfree(q);
                return NULL;
@@ -74,7 +74,6 @@ void
 snd_seq_oss_readq_delete(seq_oss_readq_t *q)
 {
        if (q) {
-               snd_seq_oss_readq_clear(q);     /* to be sure */
                if (q->q)
                        kfree(q->q);
                kfree(q);
@@ -106,9 +105,9 @@ snd_seq_oss_readq_puts(seq_oss_readq_t *q, int dev, unsigned char *data, int len
        evrec_t rec;
        int result;
 
+       memset(&rec, 0, sizeof(rec));
        rec.c[0] = SEQ_MIDIPUTC;
        rec.c[2] = dev;
-       rec.c[3] = 0;
 
        while (len-- > 0) {
                rec.c[1] = *data++;
@@ -134,7 +133,7 @@ snd_seq_oss_readq_put_event(seq_oss_readq_t *q, evrec_t *ev)
                return -ENOMEM;
        }
 
-       memcpy(&q->q[q->tail], ev, ev_length(ev));
+       memcpy(&q->q[q->tail], ev, sizeof(*ev));
        q->tail = (q->tail + 1) % q->maxlen;
        q->qlen++;
 
@@ -150,50 +149,37 @@ snd_seq_oss_readq_put_event(seq_oss_readq_t *q, evrec_t *ev)
 
 /*
  * pop queue
+ * caller must hold lock
  */
-evrec_t *
-snd_seq_oss_readq_pick(seq_oss_readq_t *q, int blocking, unsigned long *rflags)
+int
+snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec)
 {
-       evrec_t *p;
-
-       spin_lock_irqsave(&q->lock, *rflags);
-       if (q->qlen == 0) {
-               if (blocking) {
-                       spin_unlock(&q->lock);
-                       interruptible_sleep_on_timeout(&q->midi_sleep,
-                                                      q->pre_event_timeout);
-                       spin_lock(&q->lock);
-               }
-               if (q->qlen == 0) {
-                       spin_unlock_irqrestore(&q->lock, *rflags);
-                       return NULL;
-               }
-       }
-       p = q->q + q->head;
-
-       return p;
+       if (q->qlen == 0)
+               return -EAGAIN;
+       memcpy(rec, &q->q[q->head], sizeof(*rec));
+       return 0;
 }
 
 /*
- * unlock queue
+ * sleep until ready
  */
 void
-snd_seq_oss_readq_unlock(seq_oss_readq_t *q, unsigned long flags)
+snd_seq_oss_readq_wait(seq_oss_readq_t *q)
 {
-       spin_unlock_irqrestore(&q->lock, flags);
+       interruptible_sleep_on_timeout(&q->midi_sleep, q->pre_event_timeout);
 }
 
 /*
- * drain one record and unlock queue
+ * drain one record
+ * caller must hold lock
  */
 void
-snd_seq_oss_readq_free(seq_oss_readq_t *q, unsigned long flags)
+snd_seq_oss_readq_free(seq_oss_readq_t *q)
 {
        if (q->qlen > 0) {
                q->head = (q->head + 1) % q->maxlen;
                q->qlen--;
        }
-       spin_unlock_irqrestore(&q->lock, flags);
 }
 
 /*
@@ -215,6 +201,7 @@ snd_seq_oss_readq_put_timestamp(seq_oss_readq_t *q, unsigned long curt, int seq_
 {
        if (curt != q->input_time) {
                evrec_t rec;
+               memset(&rec, 0, sizeof(rec));
                switch (seq_mode) {
                case SNDRV_SEQ_OSS_MODE_SYNTH:
                        rec.echo = (curt << 8) | SEQ_WAIT;
index 22b2946..303b929 100644 (file)
@@ -46,8 +46,11 @@ unsigned int snd_seq_oss_readq_poll(seq_oss_readq_t *readq, struct file *file, p
 int snd_seq_oss_readq_puts(seq_oss_readq_t *readq, int dev, unsigned char *data, int len);
 int snd_seq_oss_readq_put_event(seq_oss_readq_t *readq, evrec_t *ev);
 int snd_seq_oss_readq_put_timestamp(seq_oss_readq_t *readq, unsigned long curt, int seq_mode);
-evrec_t *snd_seq_oss_readq_pick(seq_oss_readq_t *q, int blocking, unsigned long *rflags);
-void snd_seq_oss_readq_unlock(seq_oss_readq_t *q, unsigned long flags);
-void snd_seq_oss_readq_free(seq_oss_readq_t *q, unsigned long flags);
+int snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec);
+void snd_seq_oss_readq_wait(seq_oss_readq_t *q);
+void snd_seq_oss_readq_free(seq_oss_readq_t *q);
+
+#define snd_seq_oss_readq_lock(q, flags) spin_lock_irqsave(&(q)->lock, flags)
+#define snd_seq_oss_readq_unlock(q, flags) spin_unlock_irqrestore(&(q)->lock, flags)
 
 #endif
index 811a476..1d8fbd2 100644 (file)
@@ -44,35 +44,47 @@ int
 snd_seq_oss_read(seq_oss_devinfo_t *dp, char __user *buf, int count)
 {
        seq_oss_readq_t *readq = dp->readq;
-       int cnt, pos;
-       evrec_t *q;
+       int result = 0, err = 0;
+       int ev_len;
+       evrec_t rec;
        unsigned long flags;
 
        if (readq == NULL || ! is_read_mode(dp->file_mode))
-               return -EIO;
-
-       /* copy queued events to read buffer */
-       cnt = count;
-       pos = 0;
-       q = snd_seq_oss_readq_pick(readq, !is_nonblock_mode(dp->file_mode), &flags);
-       if (q == NULL)
-               return 0;
-       do {
-               int ev_len;
-               /* tansfer the data */
-               ev_len = ev_length(q);
-               if (copy_to_user(buf + pos, q, ev_len)) {
+               return -ENXIO;
+
+       while (count >= SHORT_EVENT_SIZE) {
+               snd_seq_oss_readq_lock(readq, flags);
+               err = snd_seq_oss_readq_pick(readq, &rec);
+               if (err == -EAGAIN &&
+                   !is_nonblock_mode(dp->file_mode) && result == 0) {
+                       snd_seq_oss_readq_unlock(readq, flags);
+                       snd_seq_oss_readq_wait(readq);
+                       snd_seq_oss_readq_lock(readq, flags);
+                       if (signal_pending(current))
+                               err = -ERESTARTSYS;
+                       else
+                               err = snd_seq_oss_readq_pick(readq, &rec);
+               }
+               if (err < 0) {
                        snd_seq_oss_readq_unlock(readq, flags);
                        break;
                }
-               snd_seq_oss_readq_free(readq, flags);
-               pos += ev_len;
-               cnt -= ev_len;
-               if (cnt < ev_len)
+               ev_len = ev_length(&rec);
+               if (ev_len < count) {
+                       snd_seq_oss_readq_unlock(readq, flags);
                        break;
-       } while ((q = snd_seq_oss_readq_pick(readq, 0, &flags)) != NULL);
-
-       return count - cnt;
+               }
+               snd_seq_oss_readq_free(readq);
+               snd_seq_oss_readq_unlock(readq, flags);
+               if (copy_to_user(buf, &rec, ev_len)) {
+                       err = -EFAULT;
+                       break;
+               }
+               result += ev_len;
+               buf += ev_len;
+               count -= ev_len;
+       }
+       return result > 0 ? result : err;
 }
 
 
@@ -83,56 +95,64 @@ snd_seq_oss_read(seq_oss_devinfo_t *dp, char __user *buf, int count)
 int
 snd_seq_oss_write(seq_oss_devinfo_t *dp, const char __user *buf, int count, struct file *opt)
 {
-       int rc, c, p, ev_size;
+       int result = 0, err = 0;
+       int ev_size, fmt;
        evrec_t rec;
 
        if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
-               return -EIO;
+               return -ENXIO;
 
-       c = count;
-       p = 0;
-       while (c >= SHORT_EVENT_SIZE) {
-               if (copy_from_user(rec.c, buf + p, SHORT_EVENT_SIZE))
+       while (count >= SHORT_EVENT_SIZE) {
+               if (copy_from_user(&rec, buf, SHORT_EVENT_SIZE)) {
+                       err = -EFAULT;
                        break;
-               p += SHORT_EVENT_SIZE;
-
+               }
                if (rec.s.code == SEQ_FULLSIZE) {
                        /* load patch */
-                       int fmt = (*(unsigned short *)rec.c) & 0xffff;
-                       return snd_seq_oss_synth_load_patch(dp, rec.s.dev, fmt, buf, p, c);
-
+                       if (result > 0) {
+                               err = -EINVAL;
+                               break;
+                       }
+                       fmt = (*(unsigned short *)rec.c) & 0xffff;
+                       /* FIXME the return value isn't correct */
+                       return snd_seq_oss_synth_load_patch(dp, rec.s.dev,
+                                                           fmt, buf, 0, count);
                }
                if (ev_is_long(&rec)) {
                        /* extended code */
                        if (rec.s.code == SEQ_EXTENDED &&
-                           dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
-                               return -EINVAL;
+                           dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
+                               err = -EINVAL;
+                               break;
+                       }
                        ev_size = LONG_EVENT_SIZE;
-                       if (c < ev_size)
+                       if (count < ev_size)
                                break;
                        /* copy the reset 4 bytes */
-                       if (copy_from_user(rec.c + SHORT_EVENT_SIZE, buf + p,
-                                          LONG_EVENT_SIZE - SHORT_EVENT_SIZE))
+                       if (copy_from_user(rec.c + SHORT_EVENT_SIZE,
+                                          buf + SHORT_EVENT_SIZE,
+                                          LONG_EVENT_SIZE - SHORT_EVENT_SIZE)) {
+                               err = -EFAULT;
                                break;
-                       p += LONG_EVENT_SIZE - SHORT_EVENT_SIZE;
-
+                       }
                } else {
                        /* old-type code */
-                       if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
-                               return -EINVAL;
+                       if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
+                               err = -EINVAL;
+                               break;
+                       }
                        ev_size = SHORT_EVENT_SIZE;
                }
 
                /* insert queue */
-               if ((rc = insert_queue(dp, &rec, opt)) < 0)
+               if ((err = insert_queue(dp, &rec, opt)) < 0)
                        break;
 
-               c -= ev_size;
+               result += ev_size;
+               buf += ev_size;
+               count -= ev_size;
        }
-
-       if (count == c && is_nonblock_mode(dp->file_mode))
-               return -EAGAIN;
-       return count - c;
+       return result > 0 ? result : err;
 }
 
 
index 4262dbd..dc44e66 100644 (file)
@@ -103,7 +103,7 @@ snd_seq_oss_synth_register(snd_seq_device_t *dev)
        snd_seq_oss_reg_t *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
        unsigned long flags;
 
-       if ((rec = snd_kcalloc(sizeof(*rec), GFP_KERNEL)) == NULL) {
+       if ((rec = kcalloc(1, sizeof(*rec), GFP_KERNEL)) == NULL) {
                snd_printk(KERN_ERR "can't malloc synth info\n");
                return -ENOMEM;
        }
@@ -244,7 +244,9 @@ snd_seq_oss_synth_setup(seq_oss_devinfo_t *dp)
                }
                info->nr_voices = rec->nr_voices;
                if (info->nr_voices > 0) {
-                       info->ch = snd_kcalloc(sizeof(seq_oss_chinfo_t) * info->nr_voices, GFP_KERNEL);
+                       info->ch = kcalloc(info->nr_voices, sizeof(seq_oss_chinfo_t), GFP_KERNEL);
+                       if (!info->ch)
+                               BUG();
                        reset_channels(info);
                }
                debug_printk(("synth %d assigned\n", i));
@@ -505,7 +507,7 @@ snd_seq_oss_synth_sysex(seq_oss_devinfo_t *dp, int dev, unsigned char *buf, snd_
 
        sysex = dp->synths[dev].sysex;
        if (sysex == NULL) {
-               sysex = snd_kcalloc(sizeof(*sysex), GFP_KERNEL);
+               sysex = kcalloc(1, sizeof(*sysex), GFP_KERNEL);
                if (sysex == NULL)
                        return -ENOMEM;
                dp->synths[dev].sysex = sysex;
index b0d72a8..b17c1f8 100644 (file)
@@ -46,7 +46,7 @@ snd_seq_oss_timer_new(seq_oss_devinfo_t *dp)
 {
        seq_oss_timer_t *rec;
 
-       rec = snd_kcalloc(sizeof(*rec), GFP_KERNEL);
+       rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
        if (rec == NULL)
                return NULL;
 
@@ -168,7 +168,7 @@ snd_seq_oss_timer_start(seq_oss_timer_t *timer)
        tmprec.queue = dp->queue;
        tmprec.ppq = timer->ppq;
        tmprec.tempo = timer->tempo;
-       snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO, &tmprec);
+       snd_seq_set_queue_tempo(dp->cseq, &tmprec);
 
        send_timer_event(dp, SNDRV_SEQ_EVENT_START, 0);
        timer->running = 1;
index 9f8a543..1382038 100644 (file)
@@ -37,7 +37,7 @@ snd_seq_oss_writeq_new(seq_oss_devinfo_t *dp, int maxlen)
        seq_oss_writeq_t *q;
        snd_seq_client_pool_t pool;
 
-       if ((q = snd_kcalloc(sizeof(*q), GFP_KERNEL)) == NULL)
+       if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL)
                return NULL;
        q->dp = dp;
        q->maxlen = maxlen;
index 398b620..0545ff8 100644 (file)
@@ -48,8 +48,6 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ALSA sequencer device management");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 /*
  * driver list
@@ -181,7 +179,7 @@ int snd_seq_device_new(snd_card_t *card, int device, char *id, int argsize,
        if (ops == NULL)
                return -ENOMEM;
 
-       dev = snd_magic_kcalloc(snd_seq_device_t, sizeof(*dev) + argsize, GFP_KERNEL);
+       dev = kcalloc(1, sizeof(*dev)*2 + argsize, GFP_KERNEL);
        if (dev == NULL) {
                unlock_driver(ops);
                return -ENOMEM;
@@ -235,7 +233,7 @@ static int snd_seq_device_free(snd_seq_device_t *dev)
        free_device(dev, ops);
        if (dev->private_free)
                dev->private_free(dev);
-       snd_magic_kfree(dev);
+       kfree(dev);
 
        unlock_driver(ops);
 
@@ -244,7 +242,7 @@ static int snd_seq_device_free(snd_seq_device_t *dev)
 
 static int snd_seq_device_dev_free(snd_device_t *device)
 {
-       snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+       snd_seq_device_t *dev = device->device_data;
        return snd_seq_device_free(dev);
 }
 
@@ -253,7 +251,7 @@ static int snd_seq_device_dev_free(snd_device_t *device)
  */
 static int snd_seq_device_dev_register(snd_device_t *device)
 {
-       snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+       snd_seq_device_t *dev = device->device_data;
        ops_list_t *ops;
 
        ops = find_driver(dev->id, 0);
@@ -275,7 +273,7 @@ static int snd_seq_device_dev_register(snd_device_t *device)
  */
 static int snd_seq_device_dev_disconnect(snd_device_t *device)
 {
-       snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+       snd_seq_device_t *dev = device->device_data;
        ops_list_t *ops;
 
        ops = find_driver(dev->id, 0);
@@ -293,7 +291,7 @@ static int snd_seq_device_dev_disconnect(snd_device_t *device)
  */
 static int snd_seq_device_dev_unregister(snd_device_t *device)
 {
-       snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+       snd_seq_device_t *dev = device->device_data;
        return snd_seq_device_free(dev);
 }
 
index 68da258..3b7647c 100644 (file)
@@ -33,7 +33,7 @@ fifo_t *snd_seq_fifo_new(int poolsize)
 {
        fifo_t *f;
 
-       f = snd_kcalloc(sizeof(fifo_t), GFP_KERNEL);
+       f = kcalloc(1, sizeof(*f), GFP_KERNEL);
        if (f == NULL) {
                snd_printd("malloc failed for snd_seq_fifo_new() \n");
                return NULL;
index d8ca16f..3949fd9 100644 (file)
@@ -29,8 +29,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 
 static void snd_instr_lock_ops(snd_seq_kinstr_list_t *list)
@@ -53,10 +51,7 @@ static void snd_instr_unlock_ops(snd_seq_kinstr_list_t *list)
 
 snd_seq_kcluster_t *snd_seq_cluster_new(int atomic)
 {
-       snd_seq_kcluster_t *cluster;
-       
-       cluster = (snd_seq_kcluster_t *) snd_kcalloc(sizeof(snd_seq_kcluster_t), atomic ? GFP_ATOMIC : GFP_KERNEL);
-       return cluster;
+       return kcalloc(1, sizeof(snd_seq_kcluster_t), atomic ? GFP_ATOMIC : GFP_KERNEL);
 }
 
 void snd_seq_cluster_free(snd_seq_kcluster_t *cluster, int atomic)
@@ -70,7 +65,7 @@ snd_seq_kinstr_t *snd_seq_instr_new(int add_len, int atomic)
 {
        snd_seq_kinstr_t *instr;
        
-       instr = (snd_seq_kinstr_t *) snd_kcalloc(sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
+       instr = kcalloc(1, sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
        if (instr == NULL)
                return NULL;
        instr->add_len = add_len;
@@ -94,7 +89,7 @@ snd_seq_kinstr_list_t *snd_seq_instr_list_new(void)
 {
        snd_seq_kinstr_list_t *list;
 
-       list = (snd_seq_kinstr_list_t *) snd_kcalloc(sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
+       list = kcalloc(1, sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
        if (list == NULL)
                return NULL;
        spin_lock_init(&list->lock);
index fbcfd3c..a404088 100644 (file)
@@ -95,7 +95,7 @@ int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t fun
                        int size = sizeof(buf);
                        if (len < size)
                                size = len;
-                       if (copy_from_user(buf, curptr, size) < 0)
+                       if (copy_from_user(buf, curptr, size))
                                return -EFAULT;
                        err = func(private_data, buf, size);
                        if (err < 0)
@@ -158,7 +158,7 @@ int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf,
        if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
                if (! in_kernel)
                        return -EINVAL;
-               if (copy_from_user(buf, event->data.ext.ptr, len) < 0)
+               if (copy_from_user(buf, event->data.ext.ptr, len))
                        return -EFAULT;
                return newlen;
        }
@@ -453,7 +453,7 @@ pool_t *snd_seq_pool_new(int poolsize)
        pool_t *pool;
 
        /* create pool block */
-       pool = snd_kcalloc(sizeof(pool_t), GFP_KERNEL);
+       pool = kcalloc(1, sizeof(*pool), GFP_KERNEL);
        if (pool == NULL) {
                snd_printd("seq: malloc failed for pool\n");
                return NULL;
index 4c200a1..7ea8db2 100644 (file)
@@ -42,8 +42,6 @@
 MODULE_AUTHOR("Takashi Iwai / Steve Ratcliffe");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI emulation.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 /* Prototypes for static functions */
 static void note_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan, int note, int vel);
index 41c165a..7e54925 100644 (file)
@@ -118,7 +118,7 @@ int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev)
        snd_midi_event_t *dev;
 
        *rdev = NULL;
-       dev = (snd_midi_event_t *)snd_kcalloc(sizeof(snd_midi_event_t), GFP_KERNEL);
+       dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
        if (dev == NULL)
                return -ENOMEM;
        if (bufsize > 0) {
index 6ce21e5..b976951 100644 (file)
@@ -141,7 +141,7 @@ client_port_t *snd_seq_create_port(client_t *client, int port)
        }
 
        /* create a new port */
-       new_port = snd_kcalloc(sizeof(client_port_t), GFP_KERNEL);
+       new_port = kcalloc(1, sizeof(*new_port), GFP_KERNEL);
        if (! new_port) {
                snd_printd("malloc failed for registering client port\n");
                return NULL;    /* failure, out of memory */
@@ -488,7 +488,7 @@ int snd_seq_port_connect(client_t *connector,
        unsigned long flags;
        int exclusive;
 
-       subs = snd_kcalloc(sizeof(*subs), GFP_KERNEL);
+       subs = kcalloc(1, sizeof(*subs), GFP_KERNEL);
        if (! subs)
                return -ENOMEM;
 
index 59f775c..a519732 100644 (file)
@@ -59,7 +59,7 @@ prioq_t *snd_seq_prioq_new(void)
 {
        prioq_t *f;
 
-       f = snd_kcalloc(sizeof(prioq_t), GFP_KERNEL);
+       f = kcalloc(1, sizeof(*f), GFP_KERNEL);
        if (f == NULL) {
                snd_printd("oops: malloc failed for snd_seq_prioq_new()\n");
                return NULL;
index c9ac37e..afb1460 100644 (file)
@@ -111,7 +111,7 @@ static queue_t *queue_new(int owner, int locked)
 {
        queue_t *q;
 
-       q = snd_kcalloc(sizeof(queue_t), GFP_KERNEL);
+       q = kcalloc(1, sizeof(*q), GFP_KERNEL);
        if (q == NULL) {
                snd_printd("malloc failed for snd_seq_queue_new()\n");
                return NULL;
index 78b2441..753f1c0 100644 (file)
@@ -59,7 +59,7 @@ seq_timer_t *snd_seq_timer_new(void)
 {
        seq_timer_t *tmr;
        
-       tmr = snd_kcalloc(sizeof(seq_timer_t), GFP_KERNEL);
+       tmr = kcalloc(1, sizeof(*tmr), GFP_KERNEL);
        if (tmr == NULL) {
                snd_printd("malloc failed for snd_seq_timer_new() \n");
                return NULL;
index c493a65..2785486 100644 (file)
@@ -115,7 +115,7 @@ int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
 {
        snd_virmidi_dev_t *rdev;
 
-       rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -EINVAL);
+       rdev = rmidi->private_data;
        return snd_virmidi_dev_receive_event(rdev, ev);
 }
 
@@ -127,7 +127,7 @@ static int snd_virmidi_event_input(snd_seq_event_t *ev, int direct,
 {
        snd_virmidi_dev_t *rdev;
 
-       rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+       rdev = private_data;
        if (!(rdev->flags & SNDRV_VIRMIDI_USE))
                return 0; /* ignored */
        return snd_virmidi_dev_receive_event(rdev, ev);
@@ -138,7 +138,7 @@ static int snd_virmidi_event_input(snd_seq_event_t *ev, int direct,
  */
 static void snd_virmidi_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
-       snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return);
+       snd_virmidi_t *vmidi = substream->runtime->private_data;
 
        if (up) {
                vmidi->trigger = 1;
@@ -152,7 +152,7 @@ static void snd_virmidi_input_trigger(snd_rawmidi_substream_t * substream, int u
  */
 static void snd_virmidi_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
-       snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return);
+       snd_virmidi_t *vmidi = substream->runtime->private_data;
        int count, res;
        unsigned char buf[32], *pbuf;
 
@@ -199,17 +199,17 @@ static void snd_virmidi_output_trigger(snd_rawmidi_substream_t * substream, int
  */
 static int snd_virmidi_input_open(snd_rawmidi_substream_t * substream)
 {
-       snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, substream->rmidi->private_data, return -EINVAL);
+       snd_virmidi_dev_t *rdev = substream->rmidi->private_data;
        snd_rawmidi_runtime_t *runtime = substream->runtime;
        snd_virmidi_t *vmidi;
        unsigned long flags;
 
-       vmidi = snd_magic_kcalloc(snd_virmidi_t, 0, GFP_KERNEL);
+       vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
        if (vmidi == NULL)
                return -ENOMEM;
        vmidi->substream = substream;
        if (snd_midi_event_new(0, &vmidi->parser) < 0) {
-               snd_magic_kfree(vmidi);
+               kfree(vmidi);
                return -ENOMEM;
        }
        vmidi->seq_mode = rdev->seq_mode;
@@ -228,16 +228,16 @@ static int snd_virmidi_input_open(snd_rawmidi_substream_t * substream)
  */
 static int snd_virmidi_output_open(snd_rawmidi_substream_t * substream)
 {
-       snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, substream->rmidi->private_data, return -EINVAL);
+       snd_virmidi_dev_t *rdev = substream->rmidi->private_data;
        snd_rawmidi_runtime_t *runtime = substream->runtime;
        snd_virmidi_t *vmidi;
 
-       vmidi = snd_magic_kcalloc(snd_virmidi_t, 0, GFP_KERNEL);
+       vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
        if (vmidi == NULL)
                return -ENOMEM;
        vmidi->substream = substream;
        if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &vmidi->parser) < 0) {
-               snd_magic_kfree(vmidi);
+               kfree(vmidi);
                return -ENOMEM;
        }
        vmidi->seq_mode = rdev->seq_mode;
@@ -254,11 +254,11 @@ static int snd_virmidi_output_open(snd_rawmidi_substream_t * substream)
  */
 static int snd_virmidi_input_close(snd_rawmidi_substream_t * substream)
 {
-       snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return -EINVAL);
+       snd_virmidi_t *vmidi = substream->runtime->private_data;
        snd_midi_event_free(vmidi->parser);
        list_del(&vmidi->list);
        substream->runtime->private_data = NULL;
-       snd_magic_kfree(vmidi);
+       kfree(vmidi);
        return 0;
 }
 
@@ -267,10 +267,10 @@ static int snd_virmidi_input_close(snd_rawmidi_substream_t * substream)
  */
 static int snd_virmidi_output_close(snd_rawmidi_substream_t * substream)
 {
-       snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return -EINVAL);
+       snd_virmidi_t *vmidi = substream->runtime->private_data;
        snd_midi_event_free(vmidi->parser);
        substream->runtime->private_data = NULL;
-       snd_magic_kfree(vmidi);
+       kfree(vmidi);
        return 0;
 }
 
@@ -281,7 +281,7 @@ static int snd_virmidi_subscribe(void *private_data, snd_seq_port_subscribe_t *i
 {
        snd_virmidi_dev_t *rdev;
 
-       rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+       rdev = private_data;
        if (!try_module_get(rdev->card->module))
                return -EFAULT;
        rdev->flags |= SNDRV_VIRMIDI_SUBSCRIBE;
@@ -295,7 +295,7 @@ static int snd_virmidi_unsubscribe(void *private_data, snd_seq_port_subscribe_t
 {
        snd_virmidi_dev_t *rdev;
 
-       rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+       rdev = private_data;
        rdev->flags &= ~SNDRV_VIRMIDI_SUBSCRIBE;
        module_put(rdev->card->module);
        return 0;
@@ -309,7 +309,7 @@ static int snd_virmidi_use(void *private_data, snd_seq_port_subscribe_t *info)
 {
        snd_virmidi_dev_t *rdev;
 
-       rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+       rdev = private_data;
        if (!try_module_get(rdev->card->module))
                return -EFAULT;
        rdev->flags |= SNDRV_VIRMIDI_USE;
@@ -323,7 +323,7 @@ static int snd_virmidi_unuse(void *private_data, snd_seq_port_subscribe_t *info)
 {
        snd_virmidi_dev_t *rdev;
 
-       rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+       rdev = private_data;
        rdev->flags &= ~SNDRV_VIRMIDI_USE;
        module_put(rdev->card->module);
        return 0;
@@ -424,7 +424,7 @@ static void snd_virmidi_dev_detach_seq(snd_virmidi_dev_t *rdev)
  */
 static int snd_virmidi_dev_register(snd_rawmidi_t *rmidi)
 {
-       snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -ENXIO);
+       snd_virmidi_dev_t *rdev = rmidi->private_data;
        int err;
 
        switch (rdev->seq_mode) {
@@ -451,7 +451,7 @@ static int snd_virmidi_dev_register(snd_rawmidi_t *rmidi)
  */
 static int snd_virmidi_dev_unregister(snd_rawmidi_t *rmidi)
 {
-       snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -ENXIO);
+       snd_virmidi_dev_t *rdev = rmidi->private_data;
 
        if (rdev->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH)
                snd_virmidi_dev_detach_seq(rdev);
@@ -471,8 +471,8 @@ static snd_rawmidi_global_ops_t snd_virmidi_global_ops = {
  */
 static void snd_virmidi_free(snd_rawmidi_t *rmidi)
 {
-       snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return);
-       snd_magic_kfree(rdev);
+       snd_virmidi_dev_t *rdev = rmidi->private_data;
+       kfree(rdev);
 }
 
 /*
@@ -493,7 +493,7 @@ int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi)
                                   &rmidi)) < 0)
                return err;
        strcpy(rmidi->name, rmidi->id);
-       rdev = snd_magic_kcalloc(snd_virmidi_dev_t, 0, GFP_KERNEL);
+       rdev = kcalloc(1, sizeof(*rdev), GFP_KERNEL);
        if (rdev == NULL) {
                snd_device_free(card, rmidi);
                return -ENOMEM;
index ab8c9b1..1ca1f6d 100644 (file)
@@ -39,11 +39,13 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
        if (! sgbuf)
                return -EINVAL;
 
+       tmpb.dev.type = SNDRV_DMA_TYPE_DEV;
+       tmpb.dev.dev = sgbuf->dev;
        for (i = 0; i < sgbuf->pages; i++) {
                tmpb.area = sgbuf->table[i].buf;
                tmpb.addr = sgbuf->table[i].addr;
                tmpb.bytes = PAGE_SIZE;
-               snd_dma_free_pages(&sgbuf->dev, &tmpb);
+               snd_dma_free_pages(&tmpb);
        }
        if (dmab->area)
                vunmap(dmab->area);
@@ -59,7 +61,7 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
        return 0;
 }
 
-void *snd_malloc_sgbuf_pages(const struct snd_dma_device *dev,
+void *snd_malloc_sgbuf_pages(struct device *device,
                             size_t size, struct snd_dma_buffer *dmab,
                             size_t *res_size)
 {
@@ -73,8 +75,7 @@ void *snd_malloc_sgbuf_pages(const struct snd_dma_device *dev,
        if (! sgbuf)
                return NULL;
        memset(sgbuf, 0, sizeof(*sgbuf));
-       sgbuf->dev = *dev;
-       sgbuf->dev.type = SNDRV_DMA_TYPE_DEV;
+       sgbuf->dev = device;
        pages = snd_sgbuf_aligned_pages(size);
        sgbuf->tblsize = sgbuf_align_table(pages);
        sgbuf->table = kmalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL);
@@ -88,7 +89,7 @@ void *snd_malloc_sgbuf_pages(const struct snd_dma_device *dev,
 
        /* allocate each page */
        for (i = 0; i < pages; i++) {
-               if (snd_dma_alloc_pages(&sgbuf->dev, PAGE_SIZE, &tmpb) < 0) {
+               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, device, PAGE_SIZE, &tmpb) < 0) {
                        if (res_size == NULL)
                                goto _failed;
                        *res_size = size = sgbuf->pages * PAGE_SIZE;
index 5d26ccf..0e15942 100644 (file)
@@ -123,7 +123,7 @@ static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
  */
 irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       mpu401_t *mpu = snd_magic_cast(mpu401_t, dev_id, return IRQ_NONE);
+       mpu401_t *mpu = dev_id;
        
        if (mpu == NULL)
                return IRQ_NONE;
@@ -137,7 +137,7 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg
  */
 static void snd_mpu401_uart_timer(unsigned long data)
 {
-       mpu401_t *mpu = snd_magic_cast(mpu401_t, (void *)data, return);
+       mpu401_t *mpu = (mpu401_t *)data;
 
        spin_lock(&mpu->timer_lock);
        /*mpu->mode |= MPU401_MODE_TIMER;*/
@@ -235,7 +235,7 @@ static int snd_mpu401_uart_input_open(snd_rawmidi_substream_t * substream)
        mpu401_t *mpu;
        int err;
 
-       mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+       mpu = substream->rmidi->private_data;
        if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
                return err;
        if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
@@ -253,7 +253,7 @@ static int snd_mpu401_uart_output_open(snd_rawmidi_substream_t * substream)
        mpu401_t *mpu;
        int err;
 
-       mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+       mpu = substream->rmidi->private_data;
        if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
                return err;
        if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
@@ -270,7 +270,7 @@ static int snd_mpu401_uart_input_close(snd_rawmidi_substream_t * substream)
 {
        mpu401_t *mpu;
 
-       mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+       mpu = substream->rmidi->private_data;
        clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
        mpu->substream_input = NULL;
        if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
@@ -284,7 +284,7 @@ static int snd_mpu401_uart_output_close(snd_rawmidi_substream_t * substream)
 {
        mpu401_t *mpu;
 
-       mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+       mpu = substream->rmidi->private_data;
        clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
        mpu->substream_output = NULL;
        if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
@@ -303,7 +303,7 @@ static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, i
        mpu401_t *mpu;
        int max = 64;
 
-       mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return);
+       mpu = substream->rmidi->private_data;
        if (up) {
                if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) {
                        /* first time - flush FIFO */
@@ -394,7 +394,7 @@ static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream,
        unsigned long flags;
        mpu401_t *mpu;
 
-       mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return);
+       mpu = substream->rmidi->private_data;
        if (up) {
                set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
 
@@ -441,14 +441,14 @@ static snd_rawmidi_ops_t snd_mpu401_uart_input =
 
 static void snd_mpu401_uart_free(snd_rawmidi_t *rmidi)
 {
-       mpu401_t *mpu = snd_magic_cast(mpu401_t, rmidi->private_data, return);
+       mpu401_t *mpu = rmidi->private_data;
        if (mpu->irq_flags && mpu->irq >= 0)
                free_irq(mpu->irq, (void *) mpu);
        if (mpu->res) {
                release_resource(mpu->res);
                kfree_nocheck(mpu->res);
        }
-       snd_magic_kfree(mpu);
+       kfree(mpu);
 }
 
 /**
@@ -484,7 +484,7 @@ int snd_mpu401_uart_new(snd_card_t * card, int device,
                *rrawmidi = NULL;
        if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0)
                return err;
-       mpu = snd_magic_kcalloc(mpu401_t, 0, GFP_KERNEL);
+       mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL);
        if (mpu == NULL) {
                snd_device_free(card, rmidi);
                return -ENOMEM;
index 5862fa2..ebec070 100644 (file)
@@ -313,7 +313,7 @@ void snd_opl3_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
        fm_instrument_t *fm;
        unsigned long flags;
 
-       opl3 = snd_magic_cast(opl3_t, p, return);
+       opl3 = p;
 
 #ifdef DEBUG_MIDI
        snd_printk("Note on, ch %i, inst %i, note %i, vel %i\n",
@@ -672,7 +672,7 @@ void snd_opl3_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
 
        unsigned long flags;
 
-       opl3 = snd_magic_cast(opl3_t, p, return);
+       opl3 = p;
 
 #ifdef DEBUG_MIDI
        snd_printk("Note off, ch %i, inst %i, note %i\n",
@@ -712,7 +712,7 @@ void snd_opl3_key_press(void *p, int note, int vel, snd_midi_channel_t *chan)
 {
        opl3_t *opl3;
 
-       opl3 = snd_magic_cast(opl3_t, p, return);
+       opl3 = p;
 #ifdef DEBUG_MIDI
        snd_printk("Key pressure, ch#: %i, inst#: %i\n",
                   chan->number, chan->midi_program);
@@ -726,7 +726,7 @@ void snd_opl3_terminate_note(void *p, int note, snd_midi_channel_t *chan)
 {
        opl3_t *opl3;
 
-       opl3 = snd_magic_cast(opl3_t, p, return);
+       opl3 = p;
 #ifdef DEBUG_MIDI
        snd_printk("Terminate note, ch#: %i, inst#: %i\n",
                   chan->number, chan->midi_program);
@@ -814,7 +814,7 @@ void snd_opl3_control(void *p, int type, snd_midi_channel_t *chan)
 {
        opl3_t *opl3;
 
-       opl3 = snd_magic_cast(opl3_t, p, return);
+       opl3 = p;
 #ifdef DEBUG_MIDI
        snd_printk("Controller, TYPE = %i, ch#: %i, inst#: %i\n",
                   type, chan->number, chan->midi_program);
@@ -851,7 +851,7 @@ void snd_opl3_nrpn(void *p, snd_midi_channel_t *chan,
 {
        opl3_t *opl3;
 
-       opl3 = snd_magic_cast(opl3_t, p, return);
+       opl3 = p;
 #ifdef DEBUG_MIDI
        snd_printk("NRPN, ch#: %i, inst#: %i\n",
                   chan->number, chan->midi_program);
@@ -866,7 +866,7 @@ void snd_opl3_sysex(void *p, unsigned char *buf, int len,
 {
        opl3_t *opl3;
 
-       opl3 = snd_magic_cast(opl3_t, p, return);
+       opl3 = p;
 #ifdef DEBUG_MIDI
        snd_printk("SYSEX\n");
 #endif
index 1e6472e..04f9f95 100644 (file)
@@ -74,7 +74,7 @@ static int snd_opl3_set_connection(opl3_t * opl3, int connection);
  */
 int snd_opl3_open(snd_hwdep_t * hw, struct file *file)
 {
-       opl3_t *opl3 = snd_magic_cast(opl3_t, hw->private_data, return -ENXIO);
+       opl3_t *opl3 = hw->private_data;
 
        down(&opl3->access_mutex);
        if (opl3->used) {
@@ -93,7 +93,7 @@ int snd_opl3_open(snd_hwdep_t * hw, struct file *file)
 int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
                   unsigned int cmd, unsigned long arg)
 {
-       opl3_t *opl3 = snd_magic_cast(opl3_t, hw->private_data, return -ENXIO);
+       opl3_t *opl3 = hw->private_data;
        void __user *argp = (void __user *)arg;
 
        snd_assert(opl3 != NULL, return -EINVAL);
@@ -176,7 +176,7 @@ int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
  */
 int snd_opl3_release(snd_hwdep_t * hw, struct file *file)
 {
-       opl3_t *opl3 = snd_magic_cast(opl3_t, hw->private_data, return -ENXIO);
+       opl3_t *opl3 = hw->private_data;
 
        snd_opl3_reset(opl3);
        down(&opl3->access_mutex);
index 45896fa..141aacb 100644 (file)
@@ -15,4 +15,4 @@ snd-opl4-synth-objs := opl4_seq.o opl4_synth.o yrw801.o
 sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
 
 obj-$(CONFIG_SND_OPL4_LIB) += snd-opl4-lib.o
-obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-opl4-synth.o
\ No newline at end of file
+obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-opl4-synth.o
index a361364..5ede428 100644 (file)
@@ -26,7 +26,6 @@
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("OPL4 driver");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 static void inline snd_opl4_wait(opl4_t *opl4)
 {
@@ -37,62 +36,68 @@ static void inline snd_opl4_wait(opl4_t *opl4)
 
 void snd_opl4_write(opl4_t *opl4, u8 reg, u8 value)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&opl4->reg_lock, flags);
-
        snd_opl4_wait(opl4);
        outb(reg, opl4->pcm_port);
 
        snd_opl4_wait(opl4);
        outb(value, opl4->pcm_port + 1);
-
-       spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 u8 snd_opl4_read(opl4_t *opl4, u8 reg)
 {
-       unsigned long flags;
-       u8 value;
-
-       spin_lock_irqsave(&opl4->reg_lock, flags);
-
        snd_opl4_wait(opl4);
        outb(reg, opl4->pcm_port);
 
        snd_opl4_wait(opl4);
-       value = inb(opl4->pcm_port + 1);
-
-       spin_unlock_irqrestore(&opl4->reg_lock, flags);
-       return value;
+       return inb(opl4->pcm_port + 1);
 }
 
 void snd_opl4_read_memory(opl4_t *opl4, char *buf, int offset, int size)
 {
-       u8 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
+       unsigned long flags;
+       u8 memcfg;
+
+       spin_lock_irqsave(&opl4->reg_lock, flags);
+
+       memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
        snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
 
        snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
        snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
        snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
-       for (; size > 0; size--)
-               *buf++ = snd_opl4_read(opl4, OPL4_REG_MEMORY_DATA);
+
+       snd_opl4_wait(opl4);
+       outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
+       snd_opl4_wait(opl4);
+       insb(opl4->pcm_port + 1, buf, size);
 
        snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
+
+       spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 void snd_opl4_write_memory(opl4_t *opl4, const char *buf, int offset, int size)
 {
-       u8 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
+       unsigned long flags;
+       u8 memcfg;
+
+       spin_lock_irqsave(&opl4->reg_lock, flags);
+
+       memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
        snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
 
        snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
        snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
        snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
-       for (; size > 0; size--)
-               snd_opl4_write(opl4, OPL4_REG_MEMORY_DATA, *buf++);
+
+       snd_opl4_wait(opl4);
+       outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
+       snd_opl4_wait(opl4);
+       outsb(opl4->pcm_port + 1, buf, size);
 
        snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
+
+       spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 static void snd_opl4_enable_opl4(opl4_t *opl4)
@@ -141,7 +146,7 @@ static int snd_opl4_detect(opl4_t *opl4)
 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
 static void snd_opl4_seq_dev_free(snd_seq_device_t *seq_dev)
 {
-       opl4_t *opl4 = snd_magic_cast(opl4_t, seq_dev->private_data, return);
+       opl4_t *opl4 = seq_dev->private_data;
        opl4->seq_dev = NULL;
 }
 
@@ -172,12 +177,12 @@ static void snd_opl4_free(opl4_t *opl4)
                release_resource(opl4->res_pcm_port);
                kfree_nocheck(opl4->res_pcm_port);
        }
-       snd_magic_kfree(opl4);
+       kfree(opl4);
 }
 
 static int snd_opl4_dev_free(snd_device_t *device)
 {
-       opl4_t *opl4 = snd_magic_cast(opl4_t, device->device_data, return -ENXIO);
+       opl4_t *opl4 = device->device_data;
        snd_opl4_free(opl4);
        return 0;
 }
@@ -199,7 +204,7 @@ int snd_opl4_create(snd_card_t *card,
        if (ropl4)
                *ropl4 = NULL;
 
-       opl4 = snd_magic_kcalloc(opl4_t, 0, GFP_KERNEL);
+       opl4 = kcalloc(1, sizeof(*opl4), GFP_KERNEL);
        if (!opl4)
                return -ENOMEM;
 
@@ -231,7 +236,7 @@ int snd_opl4_create(snd_card_t *card,
        }
 
        /* opl3 initialization disabled opl4, so reenable */
-       snd_opl4_enable_opl4(opl4); 
+       snd_opl4_enable_opl4(opl4);
 
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, opl4, &ops);
        if (err < 0) {
index e7a601a..c455680 100644 (file)
@@ -195,7 +195,6 @@ struct opl4 {
        opl4_voice_t voices[OPL4_MAX_VOICES];
        struct list_head off_voices;
        struct list_head on_voices;
-       spinlock_t voices_lock;
 #endif
 };
 
index 1e15482..ec7a228 100644 (file)
@@ -20,8 +20,6 @@
 #include "opl4_local.h"
 #include <sound/control.h>
 
-#define chip_t opl4_t
-
 static int snd_opl4_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -34,10 +32,13 @@ static int snd_opl4_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinf
 static int snd_opl4_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
        opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
+       unsigned long flags;
        u8 reg = kcontrol->private_value;
        u8 value;
 
+       spin_lock_irqsave(&opl4->reg_lock, flags);
        value = snd_opl4_read(opl4, reg);
+       spin_unlock_irqrestore(&opl4->reg_lock, flags);
        ucontrol->value.integer.value[0] = 7 - (value & 7);
        ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7);
        return 0;
@@ -46,13 +47,16 @@ static int snd_opl4_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
 static int snd_opl4_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
        opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
+       unsigned long flags;
        u8 reg = kcontrol->private_value;
        u8 value, old_value;
 
        value = (7 - (ucontrol->value.integer.value[0] & 7)) |
                ((7 - (ucontrol->value.integer.value[1] & 7)) << 3);
+       spin_lock_irqsave(&opl4->reg_lock, flags);
        old_value = snd_opl4_read(opl4, reg);
        snd_opl4_write(opl4, reg, value);
+       spin_unlock_irqrestore(&opl4->reg_lock, flags);
        return value != old_value;
 }
 
@@ -80,9 +84,7 @@ int snd_opl4_create_mixer(opl4_t *opl4)
        snd_card_t *card = opl4->card;
        int i, err;
 
-#if 0  /* already set by the codec driver */
-       strcpy(card->mixername, "OPL4 Mixer");
-#endif
+       strcat(card->mixername, ",OPL4");
 
        for (i = 0; i < 2; ++i) {
                err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4));
index bbea9ab..6a14862 100644 (file)
@@ -26,7 +26,7 @@
 static int snd_opl4_mem_proc_open(snd_info_entry_t *entry,
                                  unsigned short mode, void **file_private_data)
 {
-       opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+       opl4_t *opl4 = entry->private_data;
 
        down(&opl4->access_mutex);
        if (opl4->memory_access) {
@@ -41,7 +41,7 @@ static int snd_opl4_mem_proc_open(snd_info_entry_t *entry,
 static int snd_opl4_mem_proc_release(snd_info_entry_t *entry,
                                     unsigned short mode, void *file_private_data)
 {
-       opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+       opl4_t *opl4 = entry->private_data;
 
        down(&opl4->access_mutex);
        opl4->memory_access--;
@@ -53,7 +53,7 @@ static long snd_opl4_mem_proc_read(snd_info_entry_t *entry, void *file_private_d
                                   struct file *file, char __user *_buf,
                                   unsigned long count, unsigned long pos)
 {
-       opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+       opl4_t *opl4 = entry->private_data;
        long size;
        char* buf;
 
@@ -79,7 +79,7 @@ static long snd_opl4_mem_proc_write(snd_info_entry_t *entry, void *file_private_
                                    struct file *file, const char __user *_buf,
                                    unsigned long count, unsigned long pos)
 {
-       opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+       opl4_t *opl4 = entry->private_data;
        long size;
        char *buf;
 
index d4499d1..b146a1c 100644 (file)
@@ -272,12 +272,14 @@ static unsigned char snd_opl4_volume_table[128] = {
  */
 void snd_opl4_synth_reset(opl4_t *opl4)
 {
+       unsigned long flags;
        int i;
 
+       spin_lock_irqsave(&opl4->reg_lock, flags);
        for (i = 0; i < OPL4_MAX_VOICES; i++)
                snd_opl4_write(opl4, OPL4_REG_MISC + i, OPL4_DAMP_BIT);
+       spin_unlock_irqrestore(&opl4->reg_lock, flags);
 
-       spin_lock_init(&opl4->voices_lock);
        INIT_LIST_HEAD(&opl4->off_voices);
        INIT_LIST_HEAD(&opl4->on_voices);
        memset(opl4->voices, 0, sizeof(opl4->voices));
@@ -294,11 +296,14 @@ void snd_opl4_synth_reset(opl4_t *opl4)
  */
 void snd_opl4_synth_shutdown(opl4_t *opl4)
 {
+       unsigned long flags;
        int i;
 
+       spin_lock_irqsave(&opl4->reg_lock, flags);
        for (i = 0; i < OPL4_MAX_VOICES; i++)
                snd_opl4_write(opl4, OPL4_REG_MISC + i,
                               opl4->voices[i].reg_misc & ~OPL4_KEY_ON_BIT);
+       spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 /*
@@ -311,14 +316,14 @@ static void snd_opl4_do_for_note(opl4_t *opl4, int note, snd_midi_channel_t *cha
        unsigned long flags;
        opl4_voice_t *voice;
 
-       spin_lock_irqsave(&opl4->voices_lock, flags);
+       spin_lock_irqsave(&opl4->reg_lock, flags);
        for (i = 0; i < OPL4_MAX_VOICES; i++) {
                voice = &opl4->voices[i];
                if (voice->chan == chan && voice->note == note) {
                        func(opl4, voice);
                }
        }
-       spin_unlock_irqrestore(&opl4->voices_lock, flags);
+       spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 /*
@@ -331,14 +336,14 @@ static void snd_opl4_do_for_channel(opl4_t *opl4, snd_midi_channel_t *chan,
        unsigned long flags;
        opl4_voice_t *voice;
 
-       spin_lock_irqsave(&opl4->voices_lock, flags);
+       spin_lock_irqsave(&opl4->reg_lock, flags);
        for (i = 0; i < OPL4_MAX_VOICES; i++) {
                voice = &opl4->voices[i];
                if (voice->chan == chan) {
                        func(opl4, voice);
                }
        }
-       spin_unlock_irqrestore(&opl4->voices_lock, flags);
+       spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 /*
@@ -351,13 +356,13 @@ static void snd_opl4_do_for_all(opl4_t *opl4,
        unsigned long flags;
        opl4_voice_t *voice;
 
-       spin_lock_irqsave(&opl4->voices_lock, flags);
+       spin_lock_irqsave(&opl4->reg_lock, flags);
        for (i = 0; i < OPL4_MAX_VOICES; i++) {
                voice = &opl4->voices[i];
                if (voice->chan)
                        func(opl4, voice);
        }
-       spin_unlock_irqrestore(&opl4->voices_lock, flags);
+       spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 static void snd_opl4_update_volume(opl4_t *opl4, opl4_voice_t *voice)
@@ -472,7 +477,7 @@ static void snd_opl4_wait_for_wave_headers(opl4_t *opl4)
 
 void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t *chan)
 {
-       opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+       opl4_t *opl4 = private_data;
        const opl4_region_ptr_t *regions;
        opl4_voice_t *voice[2];
        const opl4_sound_t *sound[2];
@@ -492,7 +497,7 @@ void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t
        }
 
        /* allocate and initialize the needed voices */
-       spin_lock_irqsave(&opl4->voices_lock, flags);
+       spin_lock_irqsave(&opl4->reg_lock, flags);
        for (i = 0; i < voices; i++) {
                voice[i] = snd_opl4_get_voice(opl4);
                list_del(&voice[i]->list);
@@ -502,7 +507,6 @@ void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t
                voice[i]->velocity = vel & 0x7f;
                voice[i]->sound = sound[i];
        }
-       spin_unlock_irqrestore(&opl4->voices_lock, flags);
 
        /* set tone number (triggers header loading) */
        for (i = 0; i < voices; i++) {
@@ -522,11 +526,13 @@ void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t
                voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT;
                snd_opl4_update_volume(opl4, voice[i]);
        }
+       spin_unlock_irqrestore(&opl4->reg_lock, flags);
 
        /* wait for completion of loading */
        snd_opl4_wait_for_wave_headers(opl4);
 
        /* set remaining parameters */
+       spin_lock_irqsave(&opl4->reg_lock, flags);
        for (i = 0; i < voices; i++) {
                snd_opl4_update_tone_parameters(opl4, voice[i]);
                voice[i]->reg_lfo_vibrato = voice[i]->sound->reg_lfo_vibrato;
@@ -540,6 +546,7 @@ void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t
                snd_opl4_write(opl4, OPL4_REG_MISC + voice[i]->number,
                               voice[i]->reg_misc);
        }
+       spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 static void snd_opl4_voice_off(opl4_t *opl4, opl4_voice_t *voice)
@@ -553,7 +560,7 @@ static void snd_opl4_voice_off(opl4_t *opl4, opl4_voice_t *voice)
 
 void snd_opl4_note_off(void *private_data, int note, int vel, snd_midi_channel_t *chan)
 {
-       opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+       opl4_t *opl4 = private_data;
 
        snd_opl4_do_for_note(opl4, note, chan, snd_opl4_voice_off);
 }
@@ -569,14 +576,14 @@ static void snd_opl4_terminate_voice(opl4_t *opl4, opl4_voice_t *voice)
 
 void snd_opl4_terminate_note(void *private_data, int note, snd_midi_channel_t *chan)
 {
-       opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+       opl4_t *opl4 = private_data;
 
        snd_opl4_do_for_note(opl4, note, chan, snd_opl4_terminate_voice);
 }
 
 void snd_opl4_control(void *private_data, int type, snd_midi_channel_t *chan)
 {
-       opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+       opl4_t *opl4 = private_data;
 
        switch (type) {
        case MIDI_CTL_MSB_MODWHEEL:
@@ -616,7 +623,7 @@ void snd_opl4_control(void *private_data, int type, snd_midi_channel_t *chan)
 void snd_opl4_sysex(void *private_data, unsigned char *buf, int len,
                    int parsed, snd_midi_channel_set_t *chset)
 {
-       opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+       opl4_t *opl4 = private_data;
 
        if (parsed == SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME)
                snd_opl4_do_for_all(opl4, snd_opl4_update_volume);
index 31a94ef..a4d7253 100644 (file)
@@ -506,7 +506,7 @@ static int vx_test_irq_src(vx_core_t *chip, unsigned int *ret)
  */
 static void vx_interrupt(unsigned long private_data)
 {
-       vx_core_t *chip = snd_magic_cast(vx_core_t, (void*)private_data, return);
+       vx_core_t *chip = (vx_core_t *) private_data;
        unsigned int events;
                
        if (chip->chip_status & VX_STAT_IS_STALE)
@@ -550,7 +550,7 @@ static void vx_interrupt(unsigned long private_data)
  */
 irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs)
 {
-       vx_core_t *chip = snd_magic_cast(vx_core_t, dev, return IRQ_NONE);
+       vx_core_t *chip = dev;
 
        if (! (chip->chip_status & VX_STAT_CHIP_INIT) ||
            (chip->chip_status & VX_STAT_IS_STALE))
@@ -572,6 +572,7 @@ static void vx_reset_board(vx_core_t *chip, int cold_reset)
        if (cold_reset) {
                chip->audio_source_target = chip->audio_source;
                chip->clock_source = INTERNAL_QUARTZ;
+               chip->clock_mode = VX_CLOCK_MODE_AUTO;
                chip->freq = 48000;
                chip->uer_detected = VX_UER_MODE_NOT_PRESENT;
                chip->uer_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
@@ -603,9 +604,10 @@ static void vx_reset_board(vx_core_t *chip, int cold_reset)
 
 static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-       vx_core_t *chip = snd_magic_cast(vx_core_t, entry->private_data, return);
+       vx_core_t *chip = entry->private_data;
        static char *audio_src_vxp[] = { "Line", "Mic", "Digital" };
        static char *audio_src_vx2[] = { "Analog", "Analog", "Digital" };
+       static char *clock_mode[] = { "Auto", "Internal", "External" };
        static char *clock_src[] = { "Internal", "External" };
        static char *uer_type[] = { "Consumer", "Professional", "Not Present" };
        
@@ -629,6 +631,7 @@ static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
        snd_iprintf(buffer, "Input Source: %s\n", vx_is_pcmcia(chip) ?
                    audio_src_vxp[chip->audio_source] :
                    audio_src_vx2[chip->audio_source]);
+       snd_iprintf(buffer, "Clock Mode: %s\n", clock_mode[chip->clock_mode]);
        snd_iprintf(buffer, "Clock Source: %s\n", clock_src[chip->clock_source]);
        snd_iprintf(buffer, "Frequency: %d\n", chip->freq);
        snd_iprintf(buffer, "Detected Frequency: %d\n", chip->freq_detected);
@@ -731,7 +734,7 @@ vx_core_t *snd_vx_create(snd_card_t *card, struct snd_vx_hardware *hw,
 
        snd_assert(card && hw && ops, return NULL);
 
-       chip = snd_magic_kcalloc(vx_core_t, extra_size, GFP_KERNEL);
+       chip = kcalloc(1, sizeof(chip) + extra_size, GFP_KERNEL);
        if (! chip) {
                snd_printk(KERN_ERR "vx_core: no memory\n");
                return NULL;
index 8a69c02..9d153ea 100644 (file)
@@ -44,7 +44,7 @@ static int vx_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
                [VX_TYPE_VXPOCKET] = "vxpocket",
                [VX_TYPE_VXP440] = "vxp440",
        };
-       vx_core_t *vx = snd_magic_cast(vx_core_t, hw->private_data, return -ENXIO);
+       vx_core_t *vx = hw->private_data;
 
        snd_assert(type_ids[vx->type], return -EINVAL);
        strcpy(info->id, type_ids[vx->type]);
@@ -60,7 +60,7 @@ static int vx_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
 
 static int vx_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
 {
-       vx_core_t *vx = snd_magic_cast(vx_core_t, hw->private_data, return -ENXIO);
+       vx_core_t *vx = hw->private_data;
        int index, err;
 
        snd_assert(vx->ops->load_dsp, return -ENXIO);
index 52cfb80..f00c888 100644 (file)
@@ -26,8 +26,6 @@
 #include <sound/vx_core.h>
 #include "vx_cmd.h"
 
-#define chip_t vx_core_t
-
 
 /*
  * write a codec data (24bit)
@@ -523,6 +521,54 @@ static snd_kcontrol_new_t vx_control_audio_src = {
        .put =          vx_audio_src_put,
 };
 
+/*
+ * clock mode selection
+ */
+static int vx_clock_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       static char *texts[3] = {
+               "Auto", "Internal", "External"
+       };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 3;
+       if (uinfo->value.enumerated.item > 2)
+               uinfo->value.enumerated.item = 2;
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int vx_clock_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.enumerated.item[0] = chip->clock_mode;
+       return 0;
+}
+
+static int vx_clock_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+       down(&chip->mixer_mutex);
+       if (chip->clock_mode != ucontrol->value.enumerated.item[0]) {
+               chip->clock_mode = ucontrol->value.enumerated.item[0];
+               vx_set_clock(chip, chip->freq);
+               up(&chip->mixer_mutex);
+               return 1;
+       }
+       up(&chip->mixer_mutex);
+       return 0;
+}
+
+static snd_kcontrol_new_t vx_control_clock_mode = {
+       .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name =         "Clock Mode",
+       .info =         vx_clock_mode_info,
+       .get =          vx_clock_mode_get,
+       .put =          vx_clock_mode_put,
+};
+
 /*
  * Audio Gain
  */
@@ -913,6 +959,9 @@ int snd_vx_mixer_new(vx_core_t *chip)
        /* Audio source */
        if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0)
                return err;
+       /* clock mode */
+       if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0)
+               return err;
        /* IEC958 controls */
        if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0)
                return err;
index 2f7d85f..d1bd1ef 100644 (file)
 #include <sound/driver.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/delay.h>
 #include <sound/core.h>
 #include <sound/asoundef.h>
 #include <sound/pcm.h>
 #include <sound/vx_core.h>
 #include "vx_cmd.h"
 
-#define chip_t vx_core_t
-
 
 /*
  * we use a vmalloc'ed (sg-)buffer
@@ -381,7 +380,7 @@ static int vx_send_irqa(vx_core_t *chip)
  */
 static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
 {
-       int err, i, cur_state, delay;
+       int err, i, cur_state;
 
        /* Check the pipe is not already in the requested state */
        if (vx_get_pipe_state(chip, pipe, &cur_state) < 0)
@@ -394,17 +393,14 @@ static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
         * enough sound buffer for this pipe)
         */
        if (state) {
-               int delay = CAN_START_DELAY;
                for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) {
-                       snd_vx_delay(chip, delay);
                        err = vx_pipe_can_start(chip, pipe);
                        if (err > 0)
                                break;
                        /* Wait for a few, before asking again
                         * to avoid flooding the DSP with our requests
                         */
-                       if ((i % 4 ) == 0)
-                               delay <<= 1;
+                       mdelay(1);
                }
        }
     
@@ -418,15 +414,12 @@ static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
         * reaching the expected state before returning
         * Check one pipe only (since they are synchronous)
         */
-       delay = WAIT_STATE_DELAY;
        for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
-               snd_vx_delay(chip, delay);
                err = vx_get_pipe_state(chip, pipe, &cur_state);
                if (err < 0 || cur_state == state)
                        break;
                err = -EIO;
-               if ((i % 4 ) == 0)
-                       delay <<= 1;
+               mdelay(1);
        }
        return err < 0 ? -EIO : 0;
 }
@@ -480,7 +473,7 @@ static int vx_alloc_pipe(vx_core_t *chip, int capture,
                return err;
 
        /* initialize the pipe record */
-       pipe = snd_magic_kcalloc(vx_pipe_t, 0, GFP_KERNEL);
+       pipe = kcalloc(1, sizeof(*pipe), GFP_KERNEL);
        if (! pipe) {
                /* release the pipe */
                vx_init_rmh(&rmh, CMD_FREE_PIPE);
@@ -514,7 +507,7 @@ static int vx_free_pipe(vx_core_t *chip, vx_pipe_t *pipe)
        vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
        vx_send_msg(chip, &rmh);
 
-       snd_magic_kfree(pipe);
+       kfree(pipe);
        return 0;
 }
 
@@ -629,7 +622,7 @@ static int vx_pcm_playback_close(snd_pcm_substream_t *subs)
        if (! subs->runtime->private_data)
                return -EINVAL;
 
-       pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return -EINVAL);
+       pipe = subs->runtime->private_data;
 
        if (--pipe->references == 0) {
                chip->playback_pipes[pipe->number] = NULL;
@@ -778,8 +771,8 @@ static void vx_pcm_playback_update(vx_core_t *chip, snd_pcm_substream_t *subs, v
 static void vx_pcm_delayed_start(unsigned long arg)
 {
        snd_pcm_substream_t *subs = (snd_pcm_substream_t *)arg;
-       vx_core_t *chip = snd_magic_cast(vx_core_t, subs->pcm->private_data, return);
-       vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return);
+       vx_core_t *chip = subs->pcm->private_data;
+       vx_pipe_t *pipe = subs->runtime->private_data;
        int err;
 
        /*  printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/
@@ -801,7 +794,7 @@ static void vx_pcm_delayed_start(unsigned long arg)
 static int vx_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
 {
        vx_core_t *chip = snd_pcm_substream_chip(subs);
-       vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return -EINVAL);
+       vx_pipe_t *pipe = subs->runtime->private_data;
        int err;
 
        if (chip->chip_status & VX_STAT_IS_STALE)
@@ -846,7 +839,7 @@ static int vx_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
 static snd_pcm_uframes_t vx_pcm_playback_pointer(snd_pcm_substream_t *subs)
 {
        snd_pcm_runtime_t *runtime = subs->runtime;
-       vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, runtime->private_data, return -EINVAL);
+       vx_pipe_t *pipe = runtime->private_data;
        return pipe->position;
 }
 
@@ -874,7 +867,7 @@ static int vx_pcm_prepare(snd_pcm_substream_t *subs)
 {
        vx_core_t *chip = snd_pcm_substream_chip(subs);
        snd_pcm_runtime_t *runtime = subs->runtime;
-       vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, runtime->private_data, return -EINVAL);
+       vx_pipe_t *pipe = runtime->private_data;
        int err, data_mode;
        // int max_size, nchunks;
 
@@ -1037,7 +1030,7 @@ static int vx_pcm_capture_close(snd_pcm_substream_t *subs)
        
        if (! subs->runtime->private_data)
                return -EINVAL;
-       pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return -EINVAL);
+       pipe = subs->runtime->private_data;
        chip->capture_pipes[pipe->number] = NULL;
 
        pipe_out_monitoring = pipe->monitoring_pipe;
@@ -1141,7 +1134,7 @@ static void vx_pcm_capture_update(vx_core_t *chip, snd_pcm_substream_t *subs, vx
 static snd_pcm_uframes_t vx_pcm_capture_pointer(snd_pcm_substream_t *subs)
 {
        snd_pcm_runtime_t *runtime = subs->runtime;
-       vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, runtime->private_data, return -EINVAL);
+       vx_pipe_t *pipe = runtime->private_data;
        return bytes_to_frames(runtime, pipe->hw_ptr);
 }
 
@@ -1265,7 +1258,7 @@ static int vx_init_audio_io(vx_core_t *chip)
  */
 static void snd_vx_pcm_free(snd_pcm_t *pcm)
 {
-       vx_core_t *chip = snd_magic_cast(vx_core_t, pcm->private_data, return);
+       vx_core_t *chip = pcm->private_data;
        chip->pcm[pcm->device] = NULL;
        if (chip->playback_pipes) {
                kfree(chip->playback_pipes);
index 54609aa..5db41f1 100644 (file)
@@ -263,17 +263,17 @@ int vx_set_clock(vx_core_t *chip, unsigned int freq)
        /* change the audio source if possible */
        vx_sync_audio_source(chip);
 
-       switch (chip->audio_source) {
-       case VX_AUDIO_SRC_DIGITAL:
+       if (chip->clock_mode == VX_CLOCK_MODE_EXTERNAL ||
+           (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
+            chip->audio_source == VX_AUDIO_SRC_DIGITAL)) {
                if (chip->clock_source != UER_SYNC) {
                        vx_change_clock_source(chip, UER_SYNC);
                        mdelay(6);
                        src_changed = 1;
                }
-               if (chip->freq == freq)
-                       return 0;
-               break;
-       default:
+       } else if (chip->clock_mode == VX_CLOCK_MODE_INTERNAL ||
+                  (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
+                   chip->audio_source != VX_AUDIO_SRC_DIGITAL)) {
                if (chip->clock_source != INTERNAL_QUARTZ) {
                        vx_change_clock_source(chip, INTERNAL_QUARTZ);
                        src_changed = 1;
@@ -283,8 +283,9 @@ int vx_set_clock(vx_core_t *chip, unsigned int freq)
                vx_set_internal_clock(chip, freq);
                if (src_changed)
                        vx_modify_board_inputs(chip);
-               break;
        }
+       if (chip->freq == freq)
+               return 0;
        chip->freq = freq;
        vx_modify_board_clock(chip, 1);
        return 0;
index c8f148e..7510773 100644 (file)
@@ -34,8 +34,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic");
 MODULE_LICENSE("GPL");
 
-#define chip_t snd_i2c_device_t
-
 #define CS8427_ADDR                    (0x20>>1) /* fixed address */
 
 typedef struct {
@@ -109,7 +107,7 @@ int snd_cs8427_reg_read(snd_i2c_device_t *device, unsigned char reg)
 
 static int snd_cs8427_select_corudata(snd_i2c_device_t *device, int udata)
 {
-       cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+       cs8427_t *chip = device->private_data;
        int err;
 
        udata = udata ? CS8427_BSEL : 0;
@@ -128,7 +126,7 @@ static int snd_cs8427_send_corudata(snd_i2c_device_t *device,
                                    unsigned char *ndata,
                                    int count)
 {
-       cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+       cs8427_t *chip = device->private_data;
        char *hw_data = udata ? chip->playback.hw_udata : chip->playback.hw_status;
        char data[32];
        int err, idx;
@@ -159,7 +157,7 @@ static int snd_cs8427_send_corudata(snd_i2c_device_t *device,
 static void snd_cs8427_free(snd_i2c_device_t *device)
 {
        if (device->private_data)
-               snd_magic_kfree(device->private_data);
+               kfree(device->private_data);
 }
 
 int snd_cs8427_create(snd_i2c_bus_t *bus,
@@ -211,7 +209,7 @@ int snd_cs8427_create(snd_i2c_bus_t *bus,
 
        if ((err = snd_i2c_device_create(bus, "CS8427", CS8427_ADDR | (addr & 7), &device)) < 0)
                return err;
-       chip = device->private_data = snd_magic_kcalloc(cs8427_t, 0, GFP_KERNEL);
+       chip = device->private_data = kcalloc(1, sizeof(*chip), GFP_KERNEL);
        if (chip == NULL) {
                snd_i2c_device_free(device);
                return -ENOMEM;
@@ -297,7 +295,7 @@ void snd_cs8427_reset(snd_i2c_device_t *cs8427)
        int data;
 
        snd_assert(cs8427, return);
-       chip = snd_magic_cast(cs8427_t, cs8427->private_data, return);
+       chip = cs8427->private_data;
        snd_i2c_lock(cs8427->bus);
        chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~(CS8427_RUN | CS8427_RXDMASK);
        snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, chip->regmap[CS8427_REG_CLOCKSOURCE]);
@@ -389,7 +387,7 @@ static int snd_cs8427_spdif_get(snd_kcontrol_t * kcontrol,
                                snd_ctl_elem_value_t * ucontrol)
 {
        snd_i2c_device_t *device = snd_kcontrol_chip(kcontrol);
-       cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+       cs8427_t *chip = device->private_data;
        
        snd_i2c_lock(device->bus);
        memcpy(ucontrol->value.iec958.status, chip->playback.def_status, 24);
@@ -401,7 +399,7 @@ static int snd_cs8427_spdif_put(snd_kcontrol_t * kcontrol,
                                snd_ctl_elem_value_t * ucontrol)
 {
        snd_i2c_device_t *device = snd_kcontrol_chip(kcontrol);
-       cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+       cs8427_t *chip = device->private_data;
        unsigned char *status = kcontrol->private_value ? chip->playback.pcm_status : chip->playback.def_status;
        snd_pcm_runtime_t *runtime = chip->playback.substream ? chip->playback.substream->runtime : NULL;
        int err, change;
@@ -432,8 +430,6 @@ static int snd_cs8427_spdif_mask_get(snd_kcontrol_t * kcontrol,
        return 0;
 }
 
-#define CONTROLS (sizeof(snd_cs8427_iec958_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs8427_iec958_controls[] = {
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -487,13 +483,13 @@ int snd_cs8427_iec958_build(snd_i2c_device_t *cs8427,
                            snd_pcm_substream_t *play_substream,
                            snd_pcm_substream_t *cap_substream)
 {
-       cs8427_t *chip = snd_magic_cast(cs8427_t, cs8427->private_data, return -ENXIO);
+       cs8427_t *chip = cs8427->private_data;
        snd_kcontrol_t *kctl;
        unsigned int idx;
        int err;
 
        snd_assert(play_substream && cap_substream, return -EINVAL);
-       for (idx = 0; idx < CONTROLS; idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(snd_cs8427_iec958_controls); idx++) {
                kctl = snd_ctl_new1(&snd_cs8427_iec958_controls[idx], cs8427);
                if (kctl == NULL)
                        return -ENOMEM;
@@ -517,7 +513,7 @@ int snd_cs8427_iec958_active(snd_i2c_device_t *cs8427, int active)
        cs8427_t *chip;
 
        snd_assert(cs8427, return -ENXIO);
-       chip = snd_magic_cast(cs8427_t, cs8427->private_data, return -ENXIO);
+       chip = cs8427->private_data;
        if (active)
                memcpy(chip->playback.pcm_status, chip->playback.def_status, 24);
        chip->playback.pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
@@ -533,7 +529,7 @@ int snd_cs8427_iec958_pcm(snd_i2c_device_t *cs8427, unsigned int rate)
        int err, reset;
 
        snd_assert(cs8427, return -ENXIO);
-       chip = snd_magic_cast(cs8427_t, cs8427->private_data, return -ENXIO);
+       chip = cs8427->private_data;
        status = chip->playback.pcm_status;
        snd_i2c_lock(cs8427->bus);
        if (status[0] & IEC958_AES0_PROFESSIONAL) {
index 287f21a..e31f491 100644 (file)
@@ -62,13 +62,13 @@ static int snd_i2c_bus_free(snd_i2c_bus_t *bus)
        }
        if (bus->private_free)
                bus->private_free(bus);
-       snd_magic_kfree(bus);
+       kfree(bus);
        return 0;
 }
 
 static int snd_i2c_bus_dev_free(snd_device_t *device)
 {
-       snd_i2c_bus_t *bus = snd_magic_cast(snd_i2c_bus_t, device->device_data, return -ENXIO);
+       snd_i2c_bus_t *bus = device->device_data;
        return snd_i2c_bus_free(bus);
 }
 
@@ -81,7 +81,7 @@ int snd_i2c_bus_create(snd_card_t *card, const char *name, snd_i2c_bus_t *master
        };
 
        *ri2c = NULL;
-       bus = (snd_i2c_bus_t *)snd_magic_kcalloc(snd_i2c_bus_t, 0, GFP_KERNEL);
+       bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
        if (bus == NULL)
                return -ENOMEM;
        init_MUTEX(&bus->lock_mutex);
@@ -108,7 +108,7 @@ int snd_i2c_device_create(snd_i2c_bus_t *bus, const char *name, unsigned char ad
 
        *rdevice = NULL;
        snd_assert(bus != NULL, return -EINVAL);
-       device = (snd_i2c_device_t *)snd_magic_kcalloc(snd_i2c_device_t, 0, GFP_KERNEL);
+       device = kcalloc(1, sizeof(*device), GFP_KERNEL);
        if (device == NULL)
                return -ENOMEM;
        device->addr = addr;
@@ -125,7 +125,7 @@ int snd_i2c_device_free(snd_i2c_device_t *device)
                list_del(&device->list);
        if (device->private_free)
                device->private_free(device);
-       snd_magic_kfree(device);
+       kfree(device);
        return 0;
 }
 
index 395ada0..4f2229d 100644 (file)
@@ -17,7 +17,7 @@
  * 2002-05-12   Tomas Kasparek  another code cleanup
  */
 
-/* $Id: uda1341.c,v 1.10 2003/10/23 14:34:52 perex Exp $ */
+/* $Id: uda1341.c,v 1.13 2004/07/20 15:54:13 cladisch Exp $ */
 
 #include <sound/driver.h>
 #include <linux/module.h>
@@ -131,7 +131,6 @@ struct uda1341 {
 
 //hack for ALSA magic casting
 typedef struct l3_client l3_client_t;
-#define chip_t l3_client_t      
 
 /* transfer 8bit integer into string with binary representation */
 void int2str_bin8(uint8_t val, char *buf){
@@ -332,7 +331,7 @@ int snd_uda1341_cfg_write(struct l3_client *clnt, unsigned short what,
 static void snd_uda1341_proc_read(snd_info_entry_t *entry, 
                                  snd_info_buffer_t * buffer)
 {
-       struct l3_client *clnt = snd_magic_cast(l3_client_t, entry->private_data, return);
+       struct l3_client *clnt = entry->private_data;
        struct uda1341 *uda = clnt->driver_data;
        int peak;
 
@@ -397,7 +396,7 @@ static void snd_uda1341_proc_read(snd_info_entry_t *entry,
 static void snd_uda1341_proc_regs_read(snd_info_entry_t *entry, 
                                       snd_info_buffer_t * buffer)
 {
-       struct l3_client *clnt = snd_magic_cast(l3_client_t, entry->private_data, return);
+       struct l3_client *clnt = entry->private_data;
        struct uda1341 *uda = clnt->driver_data;                
        int reg;
        char buf[12];
@@ -618,8 +617,6 @@ static int snd_uda1341_put_2regs(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 
 /* }}} */
   
-#define UDA1341_CONTROLS (sizeof(snd_uda1341_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_uda1341_controls[] = {
        UDA1341_SINGLE("Master Playback Switch", CMD_MUTE, data0_2, 2, 1, 1),
        UDA1341_SINGLE("Master Playback Volume", CMD_VOLUME, data0_0, 0, 63, 1),
@@ -653,12 +650,12 @@ static snd_kcontrol_new_t snd_uda1341_controls[] = {
 static void uda1341_free(struct l3_client *uda1341)
 {
        l3_detach_client(uda1341); // calls kfree for driver_data (uda1341_t)
-       snd_magic_kfree(uda1341);
+       kfree(uda1341);
 }
 
 static int uda1341_dev_free(snd_device_t *device)
 {
-       struct l3_client *clnt = snd_magic_cast(l3_client_t, device->device_data, return);
+       struct l3_client *clnt = device->device_data;
        uda1341_free(clnt);
        return 0;
 }
@@ -673,7 +670,7 @@ int __init snd_chip_uda1341_mixer_new(snd_card_t *card, struct l3_client **clnt)
 
        snd_assert(card != NULL, return -EINVAL);
 
-       uda1341 = snd_magic_kcalloc(l3_client_t, 0, GFP_KERNEL);
+       uda1341 = kcalloc(1, sizeof(*uda1341), GFP_KERNEL);
        if (uda1341 == NULL)
                return -ENOMEM;
          
@@ -688,7 +685,7 @@ int __init snd_chip_uda1341_mixer_new(snd_card_t *card, struct l3_client **clnt)
                return err;
        }
 
-       for (idx = 0; idx < UDA1341_CONTROLS; idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(snd_uda1341_controls); idx++) {
                if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_uda1341_controls[idx], uda1341))) < 0)
                        return err;
        }
@@ -710,7 +707,7 @@ static int uda1341_attach(struct l3_client *clnt)
 {
        struct uda1341 *uda;
 
-       uda = snd_magic_kcalloc(uda1341_t, 0, GFP_KERNEL);
+       uda = kcalloc(1, sizeof(*uda), 0, GFP_KERNEL);
        if (!uda)
                return -ENOMEM;
 
@@ -734,7 +731,7 @@ static int uda1341_attach(struct l3_client *clnt)
 static void uda1341_detach(struct l3_client *clnt)
 {
        if (clnt->driver_data)
-               snd_magic_kfree(clnt->driver_data);
+               kfree(clnt->driver_data);
 }
 
 static int
@@ -821,8 +818,7 @@ module_exit(uda1341_exit);
 MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Philips UDA1341 CODEC driver for ALSA");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{UDA1341,UDA1341TS}}");
+MODULE_SUPPORTED_DEVICE("{{UDA1341,UDA1341TS}}");
 
 EXPORT_SYMBOL(snd_chip_uda1341_mixer_new);
 
index 276af5f..7a70055 100644 (file)
@@ -33,8 +33,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("AK4117 IEC958 (S/PDIF) receiver by Asahi Kasei");
 MODULE_LICENSE("GPL");
 
-#define chip_t ak4117_t
-
 #define AK4117_ADDR                    0x00 /* fixed address */
 
 static void snd_ak4117_timer(unsigned long data);
@@ -65,12 +63,12 @@ static void reg_dump(ak4117_t *ak4117)
 static void snd_ak4117_free(ak4117_t *chip)
 {
        del_timer(&chip->timer);
-       snd_magic_kfree(chip);
+       kfree(chip);
 }
 
 static int snd_ak4117_dev_free(snd_device_t *device)
 {
-       ak4117_t *chip = snd_magic_cast(ak4117_t, device->device_data, return -ENXIO);
+       ak4117_t *chip = device->device_data;
        snd_ak4117_free(chip);
        return 0;
 }
@@ -85,7 +83,7 @@ int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *wri
                .dev_free =     snd_ak4117_dev_free,
        };
 
-       chip = (ak4117_t *)snd_magic_kcalloc(ak4117_t, 0, GFP_KERNEL);
+       chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
        spin_lock_init(&chip->lock);
@@ -544,7 +542,7 @@ int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags)
 
 static void snd_ak4117_timer(unsigned long data)
 {
-       ak4117_t *chip = snd_magic_cast(ak4117_t, (void *)data, return);
+       ak4117_t *chip = (ak4117_t *)data;
 
        if (chip->init)
                return;
index bd378df..abd8262 100644 (file)
@@ -237,7 +237,7 @@ static int snd_akm4xxx_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
 
 static int snd_akm4xxx_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-       akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+       akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
        int chip = AK_GET_CHIP(kcontrol->private_value);
        int addr = AK_GET_ADDR(kcontrol->private_value);
        int invert = AK_GET_INVERT(kcontrol->private_value);
@@ -250,7 +250,7 @@ static int snd_akm4xxx_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
 
 static int snd_akm4xxx_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-       akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+       akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
        int chip = AK_GET_CHIP(kcontrol->private_value);
        int addr = AK_GET_ADDR(kcontrol->private_value);
        int invert = AK_GET_INVERT(kcontrol->private_value);
@@ -277,7 +277,7 @@ static int snd_akm4xxx_ipga_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
 
 static int snd_akm4xxx_ipga_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-       akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+       akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
        int chip = AK_GET_CHIP(kcontrol->private_value);
        int addr = AK_GET_ADDR(kcontrol->private_value);
        ucontrol->value.integer.value[0] = snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f;
@@ -286,7 +286,7 @@ static int snd_akm4xxx_ipga_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_valu
 
 static int snd_akm4xxx_ipga_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-       akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+       akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
        int chip = AK_GET_CHIP(kcontrol->private_value);
        int addr = AK_GET_ADDR(kcontrol->private_value);
        unsigned char nval = (ucontrol->value.integer.value[0] % 37) | 0x80;
@@ -312,7 +312,7 @@ static int snd_akm4xxx_deemphasis_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
 
 static int snd_akm4xxx_deemphasis_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-       akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+       akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
        int chip = AK_GET_CHIP(kcontrol->private_value);
        int addr = AK_GET_ADDR(kcontrol->private_value);
        int shift = AK_GET_SHIFT(kcontrol->private_value);
@@ -322,7 +322,7 @@ static int snd_akm4xxx_deemphasis_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
 
 static int snd_akm4xxx_deemphasis_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-       akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+       akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
        int chip = AK_GET_CHIP(kcontrol->private_value);
        int addr = AK_GET_ADDR(kcontrol->private_value);
        int shift = AK_GET_SHIFT(kcontrol->private_value);
index 8b0b1bb..bb503e7 100644 (file)
@@ -30,8 +30,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for control of the TEA6330T circuit via i2c bus");
 MODULE_LICENSE("GPL");
 
-#define chip_t tea6330t_t
-
 #define TEA6330T_ADDR                  (0x80>>1) /* fixed address */
 
 #define TEA6330T_SADDR_VOLUME_LEFT     0x00    /* volume left */
@@ -259,8 +257,6 @@ static int snd_tea6330t_put_treble(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
        return change;
 }
 
-#define TEA6330T_CONTROLS (sizeof(snd_tea6330t_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_tea6330t_controls[] = {
 TEA6330T_MASTER_SWITCH("Master Playback Switch", 0),
 TEA6330T_MASTER_VOLUME("Master Playback Volume", 0),
@@ -270,8 +266,8 @@ TEA6330T_TREBLE("Tone Control - Treble", 0)
 
 static void snd_tea6330_free(snd_i2c_device_t *device)
 {
-       tea6330t_t *tea = snd_magic_cast(tea6330t_t, device->private_data, return);
-       snd_magic_kfree(tea);
+       tea6330t_t *tea = device->private_data;
+       kfree(tea);
 }
                                         
 int snd_tea6330t_update_mixer(snd_card_t * card,
@@ -286,11 +282,11 @@ int snd_tea6330t_update_mixer(snd_card_t * card,
        u8 default_treble, default_bass;
        unsigned char bytes[7];
 
-       tea = snd_magic_kcalloc(tea6330t_t, 0, GFP_KERNEL);
+       tea = kcalloc(1, sizeof(*tea), GFP_KERNEL);
        if (tea == NULL)
                return -ENOMEM;
        if ((err = snd_i2c_device_create(bus, "TEA6330T", TEA6330T_ADDR, &device)) < 0) {
-               snd_magic_kfree(tea);
+               kfree(tea);
                return err;
        }
        tea->device = device;
@@ -336,7 +332,7 @@ int snd_tea6330t_update_mixer(snd_card_t * card,
        if ((err = snd_component_add(card, "TEA6330T")) < 0)
                goto __error;
 
-       for (idx = 0; idx < TEA6330T_CONTROLS; idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(snd_tea6330t_controls); idx++) {
                knew = &snd_tea6330t_controls[idx];
                if (tea->treble == 0 && !strcmp(knew->name, "Tone Control - Treble"))
                        continue;
index 4415a9f..0261983 100644 (file)
@@ -34,8 +34,6 @@ MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("lowlevel code for Analog Devices AD1816A chip");
 MODULE_LICENSE("GPL");
 
-#define chip_t ad1816a_t
-
 static inline int snd_ad1816a_busy_wait(ad1816a_t *chip)
 {
        int timeout;
@@ -313,7 +311,7 @@ static snd_pcm_uframes_t snd_ad1816a_capture_pointer(snd_pcm_substream_t *substr
 
 static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       ad1816a_t *chip = snd_magic_cast(ad1816a_t, dev_id, return IRQ_NONE);
+       ad1816a_t *chip = dev_id;
        unsigned char status;
 
        spin_lock(&chip->lock);
@@ -550,13 +548,13 @@ static int snd_ad1816a_free(ad1816a_t *chip)
                snd_dma_disable(chip->dma2);
                free_dma(chip->dma2);
        }
-       snd_magic_kfree(chip);
+       kfree(chip);
        return 0;
 }
 
 static int snd_ad1816a_dev_free(snd_device_t *device)
 {
-       ad1816a_t *chip = snd_magic_cast(ad1816a_t, device->device_data, return -ENXIO);
+       ad1816a_t *chip = device->device_data;
        return snd_ad1816a_free(chip);
 }
 
@@ -585,7 +583,7 @@ int snd_ad1816a_create(snd_card_t *card,
 
        *rchip = NULL;
 
-       chip = snd_magic_kcalloc(ad1816a_t, 0, GFP_KERNEL);
+       chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
        chip->irq = -1;
@@ -661,7 +659,7 @@ static snd_pcm_ops_t snd_ad1816a_capture_ops = {
 
 static void snd_ad1816a_pcm_free(snd_pcm_t *pcm)
 {
-       ad1816a_t *chip = snd_magic_cast(ad1816a_t, pcm->private_data, return);
+       ad1816a_t *chip = pcm->private_data;
        chip->pcm = NULL;
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -696,7 +694,7 @@ int snd_ad1816a_pcm(ad1816a_t *chip, int device, snd_pcm_t **rpcm)
 
 static void snd_ad1816a_timer_free(snd_timer_t *timer)
 {
-       ad1816a_t *chip = snd_magic_cast(ad1816a_t, timer->private_data, return);
+       ad1816a_t *chip = timer->private_data;
        chip->timer = NULL;
 }
 
@@ -901,8 +899,6 @@ static int snd_ad1816a_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
        return change;
 }
 
-#define AD1816A_CONTROLS (sizeof(snd_ad1816a_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_ad1816a_controls[] = {
 AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
 AD1816A_DOUBLE("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1),
@@ -950,7 +946,7 @@ int snd_ad1816a_mixer(ad1816a_t *chip)
 
        strcpy(card->mixername, snd_ad1816a_chip_id(chip));
 
-       for (idx = 0; idx < AD1816A_CONTROLS; idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(snd_ad1816a_controls); idx++) {
                if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ad1816a_controls[idx], chip))) < 0)
                        return err;
        }
index 788fac6..2128d4b 100644 (file)
@@ -93,8 +93,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for control of CS4235/4236B/4237B/4238B/4239 chips");
 MODULE_LICENSE("GPL");
 
-#define chip_t cs4231_t
-
 /*
  *
  */
@@ -707,8 +705,6 @@ static int snd_cs4235_put_output_accu(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
        return change;
 }
 
-#define CS4236_CONTROLS (sizeof(snd_cs4236_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_controls[] = {
 
 CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
@@ -760,8 +756,6 @@ CS4231_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
 CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1)
 };
 
-#define CS4235_CONTROLS (sizeof(snd_cs4235_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4235_controls[] = {
 
 CS4231_DOUBLE("Master Switch", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
@@ -871,8 +865,6 @@ static int snd_cs4236_put_iec958_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_
        return change;
 }
 
-#define CS4236_IEC958_CONTROLS (sizeof(snd_cs4236_iec958_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_iec958_controls[] = {
 CS4236_IEC958_ENABLE("IEC958 Output Enable", 0),
 CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0),
@@ -882,15 +874,11 @@ CS4236_SINGLEC("IEC958 Output Channel Status Low", 0, 5, 1, 127, 0),
 CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0)
 };
 
-#define CS4236_3D_CONTROLS_CS4235 (sizeof(snd_cs4236_3d_controls_cs4235)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4235[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1)
 };
 
-#define CS4236_3D_CONTROLS_CS4237 (sizeof(snd_cs4236_3d_controls_cs4237)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4237[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
@@ -899,8 +887,6 @@ CS4236_SINGLEC("3D Control - Mono", 0, 3, 6, 1, 0),
 CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
 };
 
-#define CS4236_3D_CONTROLS_CS4238 (sizeof(snd_cs4236_3d_controls_cs4238)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4238[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
@@ -921,12 +907,12 @@ int snd_cs4236_mixer(cs4231_t *chip)
 
        if (chip->hardware == CS4231_HW_CS4235 ||
            chip->hardware == CS4231_HW_CS4239) {
-               for (idx = 0; idx < CS4235_CONTROLS; idx++) {
+               for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) {
                        if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0)
                                return err;
                }
        } else {
-               for (idx = 0; idx < CS4236_CONTROLS; idx++) {
+               for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_controls); idx++) {
                        if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip))) < 0)
                                return err;
                }
@@ -934,15 +920,15 @@ int snd_cs4236_mixer(cs4231_t *chip)
        switch (chip->hardware) {
        case CS4231_HW_CS4235:
        case CS4231_HW_CS4239:
-               count = CS4236_3D_CONTROLS_CS4235;
+               count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235);
                kcontrol = snd_cs4236_3d_controls_cs4235;
                break;
        case CS4231_HW_CS4237B:
-               count = CS4236_3D_CONTROLS_CS4237;
+               count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237);
                kcontrol = snd_cs4236_3d_controls_cs4237;
                break;
        case CS4231_HW_CS4238B:
-               count = CS4236_3D_CONTROLS_CS4238;
+               count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238);
                kcontrol = snd_cs4236_3d_controls_cs4238;
                break;
        default:
@@ -955,7 +941,7 @@ int snd_cs4236_mixer(cs4231_t *chip)
        }
        if (chip->hardware == CS4231_HW_CS4237B ||
            chip->hardware == CS4231_HW_CS4238B) {
-               for (idx = 0; idx < CS4236_IEC958_CONTROLS; idx++) {
+               for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) {
                        if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0)
                                return err;
                }
index 66d08b8..c20bc7f 100644 (file)
@@ -34,7 +34,6 @@
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ESS ESx688 lowlevel module");
-MODULE_CLASSES("{sound}");
 MODULE_LICENSE("GPL");
 
 static int snd_es1688_dsp_command(es1688_t *chip, unsigned char val)
@@ -482,7 +481,7 @@ static int snd_es1688_capture_trigger(snd_pcm_substream_t * substream,
 
 irqreturn_t snd_es1688_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       es1688_t *chip = snd_magic_cast(es1688_t, dev_id, return IRQ_NONE);
+       es1688_t *chip = dev_id;
 
        if (chip->trigger_value == 0x05)        /* ok.. playback is active */
                snd_pcm_period_elapsed(chip->playback_substream);
@@ -616,13 +615,13 @@ static int snd_es1688_free(es1688_t *chip)
                disable_dma(chip->dma8);
                free_dma(chip->dma8);
        }
-       snd_magic_kfree(chip);
+       kfree(chip);
        return 0;
 }
 
 static int snd_es1688_dev_free(snd_device_t *device)
 {
-       es1688_t *chip = snd_magic_cast(es1688_t, device->device_data, return -ENXIO);
+       es1688_t *chip = device->device_data;
        return snd_es1688_free(chip);
 }
 
@@ -650,7 +649,7 @@ int snd_es1688_create(snd_card_t * card,
        int err;
 
        *rchip = NULL;
-       chip = snd_magic_kcalloc(es1688_t, 0, GFP_KERNEL);
+       chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
        chip->irq = -1;
@@ -728,7 +727,7 @@ static snd_pcm_ops_t snd_es1688_capture_ops = {
 
 static void snd_es1688_pcm_free(snd_pcm_t *pcm)
 {
-       es1688_t *chip = snd_magic_cast(es1688_t, pcm->private_data, return);
+       es1688_t *chip = pcm->private_data;
        chip->pcm = NULL;
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -978,8 +977,6 @@ static int snd_es1688_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
        return change;
 }
 
-#define ES1688_CONTROLS (sizeof(snd_es1688_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_es1688_controls[] = {
 ES1688_DOUBLE("Master Playback Volume", 0, ES1688_MASTER_DEV, ES1688_MASTER_DEV, 4, 0, 15, 0),
 ES1688_DOUBLE("PCM Playback Volume", 0, ES1688_PCM_DEV, ES1688_PCM_DEV, 4, 0, 15, 0),
@@ -1028,7 +1025,7 @@ int snd_es1688_mixer(es1688_t *chip)
 
        strcpy(card->mixername, snd_es1688_chip_id(chip));
 
-       for (idx = 0; idx < ES1688_CONTROLS; idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(snd_es1688_controls); idx++) {
                if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es1688_controls[idx], chip))) < 0)
                        return err;
        }
index 00df354..bae5dbd 100644 (file)
@@ -27,14 +27,10 @@ sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += snd-gus-synth.o
 obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += snd-gus-synth.o
 obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSEXTREME)) += snd-gus-synth.o
 obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE)) += snd-gus-synth.o
 obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE_STB)) += snd-gus-synth.o
+obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-gus-synth.o
 
 obj-m := $(sort $(obj-m))
index 0b73d4c..22120b8 100644 (file)
@@ -31,12 +31,12 @@ static int snd_gus_dram_poke(snd_gus_card_t *gus, char __user *_buffer,
 {
        unsigned long flags;
        unsigned int size1, size2;
-       char buffer[512], *pbuffer;
+       char buffer[256], *pbuffer;
 
        while (size > 0) {
-               if (copy_from_user(buffer, _buffer, 512))
+               size1 = size > sizeof(buffer) ? sizeof(buffer) : size;
+               if (copy_from_user(buffer, _buffer, size1))
                        return -EFAULT;
-               size1 = size > 512 ? 512 : size;
                if (gus->interwave) {
                        spin_lock_irqsave(&gus->reg_lock, flags);
                        snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
@@ -69,10 +69,10 @@ static int snd_gus_dram_peek(snd_gus_card_t *gus, char __user *_buffer,
 {
        unsigned long flags;
        unsigned int size1, size2;
-       char buffer[512], *pbuffer;
+       char buffer[256], *pbuffer;
 
        while (size > 0) {
-               size1 = size > 512 ? 512 : size;
+               size1 = size > sizeof(buffer) ? sizeof(buffer) : size;
                if (gus->interwave) {
                        spin_lock_irqsave(&gus->reg_lock, flags);
                        snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, rom ? 0x03 : 0x01);
index e819e90..591a9a1 100644 (file)
@@ -31,7 +31,7 @@
 int snd_gus_iwffff_put_sample(void *private_data, iwffff_wave_t *wave,
                              char __user *data, long len, int atomic)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+       snd_gus_card_t *gus = private_data;
        snd_gf1_mem_block_t *block;
        int err;
 
@@ -61,7 +61,7 @@ int snd_gus_iwffff_put_sample(void *private_data, iwffff_wave_t *wave,
 int snd_gus_iwffff_get_sample(void *private_data, iwffff_wave_t *wave,
                              char __user *data, long len, int atomic)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+       snd_gus_card_t *gus = private_data;
 
        return snd_gus_dram_read(gus, data, wave->address.memory, wave->size,
                                 wave->format & IWFFFF_WAVE_ROM ? 1 : 0);
@@ -70,7 +70,7 @@ int snd_gus_iwffff_get_sample(void *private_data, iwffff_wave_t *wave,
 int snd_gus_iwffff_remove_sample(void *private_data, iwffff_wave_t *wave,
                                 int atomic)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+       snd_gus_card_t *gus = private_data;
 
        if (wave->format & IWFFFF_WAVE_ROM)
                return 0;       /* it's probably ok - verify the address? */    
@@ -84,7 +84,7 @@ int snd_gus_iwffff_remove_sample(void *private_data, iwffff_wave_t *wave,
 int snd_gus_gf1_put_sample(void *private_data, gf1_wave_t *wave,
                           char __user *data, long len, int atomic)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+       snd_gus_card_t *gus = private_data;
        snd_gf1_mem_block_t *block;
        int err;
 
@@ -112,7 +112,7 @@ int snd_gus_gf1_put_sample(void *private_data, gf1_wave_t *wave,
 int snd_gus_gf1_get_sample(void *private_data, gf1_wave_t *wave,
                           char __user *data, long len, int atomic)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+       snd_gus_card_t *gus = private_data;
 
        return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, 0);
 }
@@ -120,7 +120,7 @@ int snd_gus_gf1_get_sample(void *private_data, gf1_wave_t *wave,
 int snd_gus_gf1_remove_sample(void *private_data, gf1_wave_t *wave,
                              int atomic)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+       snd_gus_card_t *gus = private_data;
 
        return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory);
 }
@@ -132,7 +132,7 @@ int snd_gus_gf1_remove_sample(void *private_data, gf1_wave_t *wave,
 int snd_gus_simple_put_sample(void *private_data, simple_instrument_t *instr,
                              char __user *data, long len, int atomic)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+       snd_gus_card_t *gus = private_data;
        snd_gf1_mem_block_t *block;
        int err;
 
@@ -159,7 +159,7 @@ int snd_gus_simple_put_sample(void *private_data, simple_instrument_t *instr,
 int snd_gus_simple_get_sample(void *private_data, simple_instrument_t *instr,
                              char __user *data, long len, int atomic)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+       snd_gus_card_t *gus = private_data;
 
        return snd_gus_dram_read(gus, data, instr->address.memory, instr->size, 0);
 }
@@ -167,7 +167,7 @@ int snd_gus_simple_get_sample(void *private_data, simple_instrument_t *instr,
 int snd_gus_simple_remove_sample(void *private_data, simple_instrument_t *instr,
                                 int atomic)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+       snd_gus_card_t *gus = private_data;
 
        return snd_gf1_mem_free(&gus->gf1.mem_alloc, instr->address.memory);
 }
index 4aeabe8..1e2a15e 100644 (file)
@@ -32,7 +32,7 @@
 
 irqreturn_t snd_gus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       snd_gus_card_t * gus = snd_magic_cast(snd_gus_card_t, dev_id, return IRQ_NONE);
+       snd_gus_card_t * gus = dev_id;
        unsigned char status;
        int loop = 100;
        int handled = 0;
@@ -114,7 +114,7 @@ static void snd_gus_irq_info_read(snd_info_entry_t *entry,
        snd_gus_voice_t *pvoice;
        int idx;
 
-       gus = snd_magic_cast(snd_gus_card_t, entry->private_data, return);
+       gus = entry->private_data;
        snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out);
        snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in);
        snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1);
index 64558c2..73f81c1 100644 (file)
@@ -35,8 +35,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards");
 MODULE_LICENSE("GPL");
 
-#define chip_t snd_gus_card_t
-
 static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches);
 
 int snd_gus_use_inc(snd_gus_card_t * gus)
@@ -133,13 +131,13 @@ static int snd_gus_free(snd_gus_card_t *gus)
                disable_dma(gus->gf1.dma2);
                free_dma(gus->gf1.dma2);
        }
-       snd_magic_kfree(gus);
+       kfree(gus);
        return 0;
 }
 
 static int snd_gus_dev_free(snd_device_t *device)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, device->device_data, return -ENXIO);
+       snd_gus_card_t *gus = device->device_data;
        return snd_gus_free(gus);
 }
 
@@ -159,7 +157,7 @@ int snd_gus_create(snd_card_t * card,
        };
 
        *rgus = NULL;
-       gus = snd_magic_kcalloc(snd_gus_card_t, 0, GFP_KERNEL);
+       gus = kcalloc(1, sizeof(*gus), GFP_KERNEL);
        if (gus == NULL)
                return -ENOMEM;
        gus->gf1.irq = -1;
@@ -421,7 +419,7 @@ static int snd_gus_check_version(snd_gus_card_t * gus)
 
 static void snd_gus_seq_dev_free(snd_seq_device_t *seq_dev)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, seq_dev->private_data, return);
+       snd_gus_card_t *gus = seq_dev->private_data;
        gus->seq_dev = NULL;
 }
 
index 783f5dd..75ae3aa 100644 (file)
@@ -297,7 +297,7 @@ static void snd_gf1_mem_info_read(snd_info_entry_t *entry,
        unsigned int total, used;
        int i;
 
-       gus = snd_magic_cast(snd_gus_card_t, entry->private_data, return);
+       gus = entry->private_data;
        alloc = &gus->gf1.mem_alloc;
        down(&alloc->memory_mutex);
        snd_iprintf(buffer, "8-bit banks       : \n    ");
index 6ee2d76..886763f 100644 (file)
@@ -37,7 +37,7 @@ static long snd_gf1_mem_proc_dump(snd_info_entry_t *entry, void *file_private_da
                                  unsigned long count, unsigned long pos)
 {
        long size;
-       gus_proc_private_t *priv = snd_magic_cast(gus_proc_private_t, entry->private_data, return -ENXIO);
+       gus_proc_private_t *priv = entry->private_data;
        snd_gus_card_t *gus = priv->gus;
        int err;
 
@@ -58,7 +58,7 @@ static long long snd_gf1_mem_proc_llseek(snd_info_entry_t *entry,
                                        long long offset,
                                        int orig)
 {
-       gus_proc_private_t *priv = snd_magic_cast(gus_proc_private_t, entry->private_data, return -ENXIO);
+       gus_proc_private_t *priv = entry->private_data;
 
        switch (orig) {
        case 0: /* SEEK_SET */
@@ -80,8 +80,8 @@ static long long snd_gf1_mem_proc_llseek(snd_info_entry_t *entry,
 
 static void snd_gf1_mem_proc_free(snd_info_entry_t *entry)
 {
-       gus_proc_private_t *priv = snd_magic_cast(gus_proc_private_t, entry->private_data, return);
-       snd_magic_kfree(priv);
+       gus_proc_private_t *priv = entry->private_data;
+       kfree(priv);
 }
 
 static struct snd_info_entry_ops snd_gf1_mem_proc_ops = {
@@ -98,7 +98,7 @@ int snd_gf1_mem_proc_init(snd_gus_card_t * gus)
 
        for (idx = 0; idx < 4; idx++) {
                if (gus->gf1.mem_alloc.banks_8[idx].size > 0) {
-                       priv = snd_magic_kcalloc(gus_proc_private_t, 0, GFP_KERNEL);
+                       priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
                        if (priv == NULL)
                                return -ENOMEM;
                        priv->gus = gus;
@@ -115,7 +115,7 @@ int snd_gf1_mem_proc_init(snd_gus_card_t * gus)
        }
        for (idx = 0; idx < 4; idx++) {
                if (gus->gf1.rom_present & (1 << idx)) {
-                       priv = snd_magic_kcalloc(gus_proc_private_t, 0, GFP_KERNEL);
+                       priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
                        if (priv == NULL)
                                return -ENOMEM;
                        priv->rom = 1;
index 651071a..a051094 100644 (file)
@@ -26,8 +26,6 @@
 #include <sound/control.h>
 #include <sound/gus.h>
 
-#define chip_t snd_gus_card_t
-
 /*
  *
  */
@@ -148,16 +146,12 @@ static int snd_ics_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
        return change;
 }
 
-#define GF1_CONTROLS (sizeof(snd_gf1_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_gf1_controls[] = {
 GF1_SINGLE("Master Playback Switch", 0, 1, 1),
 GF1_SINGLE("Line Switch", 0, 0, 1),
 GF1_SINGLE("Mic Switch", 0, 2, 0)
 };
 
-#define ICS_CONTROLS (sizeof(snd_ics_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_ics_controls[] = {
 GF1_SINGLE("Master Playback Switch", 0, 1, 1),
 ICS_DOUBLE("Master Playback Volume", 0, SNDRV_ICS_MASTER_DEV),
@@ -190,13 +184,13 @@ int snd_gf1_new_mixer(snd_gus_card_t * gus)
        }
 
        if (!gus->ics_flag) {
-               max = gus->ess_flag ? 1 : GF1_CONTROLS;
+               max = gus->ess_flag ? 1 : ARRAY_SIZE(snd_gf1_controls);
                for (idx = 0; idx < max; idx++) {
                        if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_gf1_controls[idx], gus))) < 0)
                                return err;
                }
        } else {
-               for (idx = 0; idx < ICS_CONTROLS; idx++) {
+               for (idx = 0; idx < ARRAY_SIZE(snd_ics_controls); idx++) {
                        if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ics_controls[idx], gus))) < 0)
                                return err;
                }
index 040804c..aca7f3a 100644 (file)
@@ -34,8 +34,6 @@
 #include <sound/pcm_params.h>
 #include "gus_tables.h"
 
-#define chip_t snd_gus_card_t
-
 /* maximum rate */
 
 #define SNDRV_GF1_PCM_RATE             48000
@@ -66,7 +64,7 @@ static int snd_gf1_pcm_use_dma = 1;
 
 static void snd_gf1_pcm_block_change_ack(snd_gus_card_t * gus, void *private_data)
 {
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, private_data, return);
+       gus_pcm_private_t *pcmp = private_data;
 
        if (pcmp) {
                atomic_dec(&pcmp->dma_count);
@@ -81,7 +79,7 @@ static int snd_gf1_pcm_block_change(snd_pcm_substream_t * substream,
 {
        snd_gf1_dma_block_t block;
        snd_pcm_runtime_t *runtime = substream->runtime;
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+       gus_pcm_private_t *pcmp = runtime->private_data;
 
        count += offset & 31;
        offset &= ~31;
@@ -106,7 +104,7 @@ static int snd_gf1_pcm_block_change(snd_pcm_substream_t * substream,
 static void snd_gf1_pcm_trigger_up(snd_pcm_substream_t * substream)
 {
        snd_pcm_runtime_t *runtime = substream->runtime;
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return);
+       gus_pcm_private_t *pcmp = runtime->private_data;
        snd_gus_card_t * gus = pcmp->gus;
        unsigned long flags;
        unsigned char voice_ctrl, ramp_ctrl;
@@ -194,7 +192,7 @@ static void snd_gf1_pcm_interrupt_wave(snd_gus_card_t * gus, snd_gus_voice_t *pv
                snd_gf1_smart_stop_voice(gus, pvoice->number);
                return;
        }
-       pcmp = snd_magic_cast(gus_pcm_private_t, pvoice->private_data, return);
+       pcmp = pvoice->private_data;
        if (pcmp == NULL) {
                snd_printd("snd_gf1_pcm: unknown wave irq?\n");
                snd_gf1_smart_stop_voice(gus, pvoice->number);
@@ -267,7 +265,7 @@ static void snd_gf1_pcm_interrupt_volume(snd_gus_card_t * gus, snd_gus_voice_t *
 {
        unsigned short vol;
        int cvoice;
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, pvoice->private_data, return);
+       gus_pcm_private_t *pcmp = pvoice->private_data;
 
        /* stop ramp, but leave rollover bit untouched */
        spin_lock(&gus->reg_lock);
@@ -350,7 +348,7 @@ static int snd_gf1_pcm_playback_copy(snd_pcm_substream_t *substream,
                                     snd_pcm_uframes_t count)
 {
        snd_pcm_runtime_t *runtime = substream->runtime;
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+       gus_pcm_private_t *pcmp = runtime->private_data;
        unsigned int bpos, len;
        
        bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
@@ -379,7 +377,7 @@ static int snd_gf1_pcm_playback_silence(snd_pcm_substream_t *substream,
                                        snd_pcm_uframes_t count)
 {
        snd_pcm_runtime_t *runtime = substream->runtime;
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+       gus_pcm_private_t *pcmp = runtime->private_data;
        unsigned int bpos, len;
        
        bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
@@ -406,7 +404,7 @@ static int snd_gf1_pcm_playback_hw_params(snd_pcm_substream_t * substream,
 {
        snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+       gus_pcm_private_t *pcmp = runtime->private_data;
        int err;
        
        if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
@@ -453,7 +451,7 @@ static int snd_gf1_pcm_playback_hw_params(snd_pcm_substream_t * substream,
 static int snd_gf1_pcm_playback_hw_free(snd_pcm_substream_t * substream)
 {
        snd_pcm_runtime_t *runtime = substream->runtime;
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+       gus_pcm_private_t *pcmp = runtime->private_data;
 
        snd_pcm_lib_free_pages(substream);
        if (pcmp->pvoices[0]) {
@@ -474,7 +472,7 @@ static int snd_gf1_pcm_playback_hw_free(snd_pcm_substream_t * substream)
 static int snd_gf1_pcm_playback_prepare(snd_pcm_substream_t * substream)
 {
        snd_pcm_runtime_t *runtime = substream->runtime;
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+       gus_pcm_private_t *pcmp = runtime->private_data;
 
        pcmp->bpos = 0;
        pcmp->dma_size = snd_pcm_lib_buffer_bytes(substream);
@@ -488,7 +486,7 @@ static int snd_gf1_pcm_playback_trigger(snd_pcm_substream_t * substream,
 {
        snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+       gus_pcm_private_t *pcmp = runtime->private_data;
        int voice;
 
        if (cmd == SNDRV_PCM_TRIGGER_START) {
@@ -513,7 +511,7 @@ static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(snd_pcm_substream_t * subs
 {
        snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+       gus_pcm_private_t *pcmp = runtime->private_data;
        unsigned int pos;
        unsigned char voice_ctrl;
 
@@ -657,8 +655,8 @@ static snd_pcm_hardware_t snd_gf1_pcm_capture =
 
 static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime)
 {
-       gus_pcm_private_t * pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return);
-       snd_magic_kfree(pcmp);
+       gus_pcm_private_t * pcmp = runtime->private_data;
+       kfree(pcmp);
 }
 
 static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
@@ -668,7 +666,7 @@ static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
        snd_pcm_runtime_t *runtime = substream->runtime;
        int err;
 
-       pcmp = snd_magic_kcalloc(gus_pcm_private_t, 0, GFP_KERNEL);
+       pcmp = kcalloc(1, sizeof(*pcmp), GFP_KERNEL);
        if (pcmp == NULL)
                return -ENOMEM;
        pcmp->gus = gus;
@@ -697,7 +695,7 @@ static int snd_gf1_pcm_playback_close(snd_pcm_substream_t * substream)
 {
        snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+       gus_pcm_private_t *pcmp = runtime->private_data;
        unsigned long jiffies_old;
 
        jiffies_old = jiffies;
@@ -738,7 +736,7 @@ static int snd_gf1_pcm_capture_close(snd_pcm_substream_t * substream)
 
 static void snd_gf1_pcm_free(snd_pcm_t *pcm)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, pcm->private_data, return);
+       snd_gus_card_t *gus = pcm->private_data;
        gus->pcm = NULL;
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -790,7 +788,7 @@ static int snd_gf1_pcm_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
                pvoice = &gus->gf1.voices[idx];
                if (!pvoice->pcm)
                        continue;
-               pcmp = snd_magic_cast(gus_pcm_private_t, pvoice->private_data, return -ENXIO);
+               pcmp = pvoice->private_data;
                if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE))
                        continue;
                /* load real volume - better precision */
index 47f88a2..c7ff304 100644 (file)
@@ -134,7 +134,7 @@ static void snd_gus_synth_instr_notify(void *private_data,
                                       int what)
 {
        unsigned int idx;
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return);
+       snd_gus_card_t *gus = private_data;
        snd_gus_voice_t *pvoice;
        unsigned long flags;
        
index 854b35d..9876603 100644 (file)
@@ -26,8 +26,6 @@
 #include <sound/core.h>
 #include <sound/gus.h>
 
-#define chip_t snd_gus_card_t
-
 /*
  *  Timer 1 - 80us
  */
@@ -146,13 +144,13 @@ static struct _snd_timer_hardware snd_gf1_timer2 =
 
 static void snd_gf1_timer1_free(snd_timer_t *timer)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, timer->private_data, return);
+       snd_gus_card_t *gus = timer->private_data;
        gus->gf1.timer1 = NULL;
 }
 
 static void snd_gf1_timer2_free(snd_timer_t *timer)
 {
-       snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, timer->private_data, return);
+       snd_gus_card_t *gus = timer->private_data;
        gus->gf1.timer2 = NULL;
 }
 
index 8b09be2..1bc2da8 100644 (file)
@@ -95,7 +95,7 @@ static int snd_gf1_uart_output_open(snd_rawmidi_substream_t * substream)
        unsigned long flags;
        snd_gus_card_t *gus;
 
-       gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+       gus = substream->rmidi->private_data;
        spin_lock_irqsave(&gus->uart_cmd_lock, flags);
        if (!(gus->gf1.uart_cmd & 0x80)) {      /* input active? */
                snd_gf1_uart_reset(gus, 0);
@@ -115,7 +115,7 @@ static int snd_gf1_uart_input_open(snd_rawmidi_substream_t * substream)
        snd_gus_card_t *gus;
        int i;
 
-       gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+       gus = substream->rmidi->private_data;
        spin_lock_irqsave(&gus->uart_cmd_lock, flags);
        if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out) {
                snd_gf1_uart_reset(gus, 0);
@@ -141,7 +141,7 @@ static int snd_gf1_uart_output_close(snd_rawmidi_substream_t * substream)
        unsigned long flags;
        snd_gus_card_t *gus;
 
-       gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+       gus = substream->rmidi->private_data;
        spin_lock_irqsave(&gus->uart_cmd_lock, flags);
        if (gus->gf1.interrupt_handler_midi_in != snd_gf1_interrupt_midi_in)
                snd_gf1_uart_reset(gus, 1);
@@ -156,7 +156,7 @@ static int snd_gf1_uart_input_close(snd_rawmidi_substream_t * substream)
        unsigned long flags;
        snd_gus_card_t *gus;
 
-       gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+       gus = substream->rmidi->private_data;
        spin_lock_irqsave(&gus->uart_cmd_lock, flags);
        if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out)
                snd_gf1_uart_reset(gus, 1);
@@ -171,7 +171,7 @@ static void snd_gf1_uart_input_trigger(snd_rawmidi_substream_t * substream, int
        snd_gus_card_t *gus;
        unsigned long flags;
 
-       gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return);
+       gus = substream->rmidi->private_data;
 
        spin_lock_irqsave(&gus->uart_cmd_lock, flags);
        if (up) {
@@ -191,7 +191,7 @@ static void snd_gf1_uart_output_trigger(snd_rawmidi_substream_t * substream, int
        char byte;
        int timeout;
 
-       gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return);
+       gus = substream->rmidi->private_data;
 
        spin_lock_irqsave(&gus->uart_cmd_lock, flags);
        if (up) {
index 78e7156..bc29b25 100644 (file)
@@ -345,8 +345,6 @@ send_array(emu8000_t *emu, unsigned short *data, int size)
                EMU8000_INIT4_WRITE(emu, i, *p);
 }
 
-#define NELEM(arr) (sizeof(arr)/sizeof((arr)[0]))
-
 
 /*
  * Send initialization arrays to start up, this just follows the
@@ -355,18 +353,18 @@ send_array(emu8000_t *emu, unsigned short *data, int size)
 static void __init
 init_arrays(emu8000_t *emu)
 {
-       send_array(emu, init1, NELEM(init1)/4);
+       send_array(emu, init1, ARRAY_SIZE(init1)/4);
 
        set_current_state(TASK_INTERRUPTIBLE);
        schedule_timeout((HZ * (44099 + 1024)) / 44100); /* wait for 1024 clocks */
-       send_array(emu, init2, NELEM(init2)/4);
-       send_array(emu, init3, NELEM(init3)/4);
+       send_array(emu, init2, ARRAY_SIZE(init2)/4);
+       send_array(emu, init3, ARRAY_SIZE(init3)/4);
 
        EMU8000_HWCF4_WRITE(emu, 0);
        EMU8000_HWCF5_WRITE(emu, 0x83);
        EMU8000_HWCF6_WRITE(emu, 0x8000);
 
-       send_array(emu, init4, NELEM(init4)/4);
+       send_array(emu, init4, ARRAY_SIZE(init4)/4);
 }
 
 
@@ -821,8 +819,6 @@ snd_emu8000_update_reverb_mode(emu8000_t *emu)
  * mixer interface
  *----------------------------------------------------------------*/
 
-#define chip_t emu8000_t
-
 /*
  * bass/treble
  */
@@ -1070,7 +1066,7 @@ static int snd_emu8000_free(emu8000_t *hw)
                release_resource(hw->res_port3);
                kfree_nocheck(hw->res_port3);
        }
-       snd_magic_kfree(hw);
+       kfree(hw);
        return 0;
 }
 
@@ -1078,7 +1074,7 @@ static int snd_emu8000_free(emu8000_t *hw)
  */
 static int snd_emu8000_dev_free(snd_device_t *device)
 {
-       emu8000_t *hw = snd_magic_cast(emu8000_t, device->device_data, return -ENXIO);
+       emu8000_t *hw = device->device_data;
        return snd_emu8000_free(hw);
 }
 
@@ -1101,7 +1097,7 @@ snd_emu8000_new(snd_card_t *card, int index, long port, int seq_ports, snd_seq_d
        if (seq_ports <= 0)
                return 0;
 
-       hw = snd_magic_kcalloc(emu8000_t, 0, GFP_KERNEL);
+       hw = kcalloc(1, sizeof(*hw), GFP_KERNEL);
        if (hw == NULL)
                return -ENOMEM;
        spin_lock_init(&hw->reg_lock);
index 868474a..05565f3 100644 (file)
@@ -94,7 +94,7 @@ release_voice(snd_emux_voice_t *vp)
        int dcysusv;
        emu8000_t *hw;
 
-       hw = snd_magic_cast(emu8000_t, vp->hw, return);
+       hw = vp->hw;
        dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
        EMU8000_DCYSUS_WRITE(hw, vp->ch, dcysusv);
        dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease;
@@ -109,7 +109,7 @@ terminate_voice(snd_emux_voice_t *vp)
 {
        emu8000_t *hw; 
 
-       hw = snd_magic_cast(emu8000_t, vp->hw, return);
+       hw = vp->hw;
        EMU8000_DCYSUSV_WRITE(hw, vp->ch, 0x807F);
 }
 
@@ -121,7 +121,7 @@ update_voice(snd_emux_voice_t *vp, int update)
 {
        emu8000_t *hw;
 
-       hw = snd_magic_cast(emu8000_t, vp->hw, return);
+       hw = vp->hw;
        if (update & SNDRV_EMUX_UPDATE_VOLUME)
                set_volume(hw, vp);
        if (update & SNDRV_EMUX_UPDATE_PITCH)
@@ -168,7 +168,7 @@ get_voice(snd_emux_t *emu, snd_emux_port_t *port)
        } best[END];
        struct best *bp;
 
-       hw = snd_magic_cast(emu8000_t, emu->hw, return NULL);
+       hw = emu->hw;
 
        for (i = 0; i < END; i++) {
                best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */;
@@ -235,7 +235,7 @@ start_voice(snd_emux_voice_t *vp)
        snd_midi_channel_t *chan;
        emu8000_t *hw;
 
-       hw = snd_magic_cast(emu8000_t, vp->hw, return -EINVAL);
+       hw = vp->hw;
        ch = vp->ch;
        chan = vp->chan;
 
@@ -313,7 +313,7 @@ trigger_voice(snd_emux_voice_t *vp)
        unsigned int temp;
        emu8000_t *hw;
 
-       hw = snd_magic_cast(emu8000_t, vp->hw, return);
+       hw = vp->hw;
 
        /* set reverb and pitch target */
        temp = vp->reg.parm.reverb;
@@ -333,7 +333,7 @@ reset_voice(snd_emux_t *emu, int ch)
 {
        emu8000_t *hw;
 
-       hw = snd_magic_cast(emu8000_t, emu->hw, return);
+       hw = emu->hw;
        EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
        snd_emu8000_tweak_voice(hw, ch);
 }
@@ -457,7 +457,7 @@ sysex(snd_emux_t *emu, char *buf, int len, int parsed, snd_midi_channel_set_t *c
 {
        emu8000_t *hw;
 
-       hw = snd_magic_cast(emu8000_t, emu->hw, return);
+       hw = emu->hw;
 
        switch (parsed) {
        case SNDRV_MIDI_SYSEX_GS_CHORUS_MODE:
@@ -482,7 +482,7 @@ oss_ioctl(snd_emux_t *emu, int cmd, int p1, int p2)
 {
        emu8000_t *hw;
 
-       hw = snd_magic_cast(emu8000_t, emu->hw, return -EINVAL);
+       hw = emu->hw;
 
        switch (cmd) {
        case _EMUX_OSS_REVERB_MODE:
@@ -526,7 +526,7 @@ static int
 load_fx(snd_emux_t *emu, int type, int mode, const void __user *buf, long len)
 {
        emu8000_t *hw;
-       hw = snd_magic_cast(emu8000_t, emu->hw, return -EINVAL);
+       hw = emu->hw;
 
        switch (type) {
        case SNDRV_EMU8000_LOAD_CHORUS_FX:
index 00bf045..ea4996a 100644 (file)
@@ -29,8 +29,6 @@
 #include <sound/emu8000.h>
 #include <sound/emu8000_reg.h>
 
-#define NELEM(arr) (sizeof(arr)/sizeof((arr)[0]))
-
 /* emu8000_patch.c */
 int snd_emu8000_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr, const void __user *data, long count);
 int snd_emu8000_sample_free(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr);
index 5c4def8..a6fd8d7 100644 (file)
@@ -23,8 +23,6 @@
 #include <sound/initval.h>
 #include <sound/pcm.h>
 
-#define chip_t emu8000_t
-
 /*
  * define the following if you want to use this pcm with non-interleaved mode
  */
@@ -235,7 +233,7 @@ static int emu8k_pcm_open(snd_pcm_substream_t *subs)
        emu8k_pcm_t *rec;
        snd_pcm_runtime_t *runtime = subs->runtime;
 
-       rec = snd_kcalloc(sizeof(*rec), GFP_KERNEL);
+       rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
        if (! rec)
                return -ENOMEM;
 
index 817748c..1f63aa5 100644 (file)
@@ -27,7 +27,6 @@
 MODULE_AUTHOR("Takashi Iwai, Steve Ratcliffe");
 MODULE_DESCRIPTION("Emu8000 synth plug-in routine");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 /*----------------------------------------------------------------*/
 
index 6cbef46..b62920e 100644 (file)
 #include <sound/sb16_csp.h>
 #include <sound/initval.h>
 
-#define chip_t snd_sb_csp_t
-
 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
 MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 #ifdef SNDRV_LITTLE_ENDIAN
 #define CSP_HDR_VALUE(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
@@ -127,7 +124,7 @@ int snd_sb_csp_new(sb_t *chip, int device, snd_hwdep_t ** rhwdep)
        if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0)
                return err;
 
-       if ((p = snd_magic_kcalloc(snd_sb_csp_t, 0, GFP_KERNEL)) == NULL) {
+       if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
                snd_device_free(chip->card, hw);
                return -ENOMEM;
        }
@@ -165,11 +162,11 @@ int snd_sb_csp_new(sb_t *chip, int device, snd_hwdep_t ** rhwdep)
  */
 static void snd_sb_csp_free(snd_hwdep_t *hwdep)
 {
-       snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hwdep->private_data, return);
+       snd_sb_csp_t *p = hwdep->private_data;
        if (p) {
                if (p->running & SNDRV_SB_CSP_ST_RUNNING)
                        snd_sb_csp_stop(p);
-               snd_magic_kfree(p);
+               kfree(p);
        }
 }
 
@@ -180,7 +177,7 @@ static void snd_sb_csp_free(snd_hwdep_t *hwdep)
  */
 static int snd_sb_csp_open(snd_hwdep_t * hw, struct file *file)
 {
-       snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hw->private_data, return -ENXIO);
+       snd_sb_csp_t *p = hw->private_data;
        return (snd_sb_csp_use(p));
 }
 
@@ -189,7 +186,7 @@ static int snd_sb_csp_open(snd_hwdep_t * hw, struct file *file)
  */
 static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
-       snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hw->private_data, return -ENXIO);
+       snd_sb_csp_t *p = hw->private_data;
        snd_sb_csp_info_t info;
        snd_sb_csp_start_t start_info;
        int err;
@@ -258,7 +255,7 @@ static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cm
  */
 static int snd_sb_csp_release(snd_hwdep_t * hw, struct file *file)
 {
-       snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hw->private_data, return -ENXIO);
+       snd_sb_csp_t *p = hw->private_data;
        return (snd_sb_csp_unuse(p));
 }
 
@@ -1110,7 +1107,7 @@ static int init_proc_entry(snd_sb_csp_t * p, int device)
 
 static void info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-       snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, entry->private_data, return);
+       snd_sb_csp_t *p = entry->private_data;
 
        snd_iprintf(buffer, "Creative Signal Processor [v%d.%d]\n", (p->version >> 4), (p->version & 0x0f));
        snd_iprintf(buffer, "State: %cx%c%c%c\n", ((p->running & SNDRV_SB_CSP_ST_QSOUND) ? 'Q' : '-'),
index f67e368..e58f486 100644 (file)
@@ -49,13 +49,11 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones");
 MODULE_LICENSE("GPL");
 
-#define chip_t sb_t
-
 #ifdef CONFIG_SND_SB16_CSP
 static void snd_sb16_csp_playback_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
 {
        if (chip->hardware == SB_HW_16CSP) {
-               snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+               snd_sb_csp_t *csp = chip->csp;
 
                if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
                        /* manually loaded codec */
@@ -103,7 +101,7 @@ static void snd_sb16_csp_playback_prepare(sb_t *chip, snd_pcm_runtime_t *runtime
 static void snd_sb16_csp_capture_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
 {
        if (chip->hardware == SB_HW_16CSP) {
-               snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+               snd_sb_csp_t *csp = chip->csp;
 
                if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
                        /* manually loaded codec */
@@ -141,7 +139,7 @@ static void snd_sb16_csp_capture_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
 static void snd_sb16_csp_update(sb_t *chip)
 {
        if (chip->hardware == SB_HW_16CSP) {
-               snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+               snd_sb_csp_t *csp = chip->csp;
 
                if (csp->qpos_changed) {
                        spin_lock(&chip->reg_lock);
@@ -155,7 +153,7 @@ static void snd_sb16_csp_playback_open(sb_t *chip, snd_pcm_runtime_t *runtime)
 {
        /* CSP decoders (QSound excluded) support only 16bit transfers */
        if (chip->hardware == SB_HW_16CSP) {
-               snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+               snd_sb_csp_t *csp = chip->csp;
 
                if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
                        /* manually loaded codec */
@@ -173,7 +171,7 @@ static void snd_sb16_csp_playback_open(sb_t *chip, snd_pcm_runtime_t *runtime)
 static void snd_sb16_csp_playback_close(sb_t *chip)
 {
        if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_WRITE)) {
-               snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+               snd_sb_csp_t *csp = chip->csp;
 
                if (csp->ops.csp_stop(csp) == 0) {
                        csp->ops.csp_unuse(csp);
@@ -186,7 +184,7 @@ static void snd_sb16_csp_capture_open(sb_t *chip, snd_pcm_runtime_t *runtime)
 {
        /* CSP coders support only 16bit transfers */
        if (chip->hardware == SB_HW_16CSP) {
-               snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+               snd_sb_csp_t *csp = chip->csp;
 
                if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
                        /* manually loaded codec */
@@ -204,7 +202,7 @@ static void snd_sb16_csp_capture_open(sb_t *chip, snd_pcm_runtime_t *runtime)
 static void snd_sb16_csp_capture_close(sb_t *chip)
 {
        if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_READ)) {
-               snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+               snd_sb_csp_t *csp = chip->csp;
 
                if (csp->ops.csp_stop(csp) == 0) {
                        csp->ops.csp_unuse(csp);
@@ -395,7 +393,7 @@ static int snd_sb16_capture_trigger(snd_pcm_substream_t * substream,
 
 irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE);
+       sb_t *chip = dev_id;
        unsigned char status;
        int ok;
 
index bac9f16..d2e3abe 100644 (file)
@@ -42,8 +42,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Uros Bizjak <uros@kss-loka.si>")
 MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones");
 MODULE_LICENSE("GPL");
 
-#define chip_t sb_t
-
 #define SB8_CLOCK      1000000
 #define SB8_DEN(v)     ((SB8_CLOCK + (v) / 2) / (v))
 #define SB8_RATE(v)    (SB8_CLOCK / SB8_DEN(v))
index 17e0f4d..90b01e7 100644 (file)
@@ -73,7 +73,7 @@ static int snd_sb8dsp_midi_input_open(snd_rawmidi_substream_t * substream)
        sb_t *chip;
        unsigned int valid_open_flags;
 
-       chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+       chip = substream->rmidi->private_data;
        valid_open_flags = chip->hardware >= SB_HW_20
                ? SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER : 0;
        spin_lock_irqsave(&chip->open_lock, flags);
@@ -100,7 +100,7 @@ static int snd_sb8dsp_midi_output_open(snd_rawmidi_substream_t * substream)
        sb_t *chip;
        unsigned int valid_open_flags;
 
-       chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+       chip = substream->rmidi->private_data;
        valid_open_flags = chip->hardware >= SB_HW_20
                ? SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER : 0;
        spin_lock_irqsave(&chip->open_lock, flags);
@@ -126,7 +126,7 @@ static int snd_sb8dsp_midi_input_close(snd_rawmidi_substream_t * substream)
        unsigned long flags;
        sb_t *chip;
 
-       chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+       chip = substream->rmidi->private_data;
        spin_lock_irqsave(&chip->open_lock, flags);
        chip->open &= ~(SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER);
        chip->midi_substream_input = NULL;
@@ -144,7 +144,7 @@ static int snd_sb8dsp_midi_output_close(snd_rawmidi_substream_t * substream)
        unsigned long flags;
        sb_t *chip;
 
-       chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+       chip = substream->rmidi->private_data;
        spin_lock_irqsave(&chip->open_lock, flags);
        chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER);
        chip->midi_substream_output = NULL;
@@ -162,7 +162,7 @@ static void snd_sb8dsp_midi_input_trigger(snd_rawmidi_substream_t * substream, i
        unsigned long flags;
        sb_t *chip;
 
-       chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+       chip = substream->rmidi->private_data;
        spin_lock_irqsave(&chip->open_lock, flags);
        if (up) {
                if (!(chip->open & SB_OPEN_MIDI_INPUT_TRIGGER)) {
@@ -188,7 +188,7 @@ static void snd_sb8dsp_midi_output_write(snd_rawmidi_substream_t * substream)
        int max = 32;
 
        /* how big is Tx FIFO? */
-       chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+       chip = substream->rmidi->private_data;
        while (max-- > 0) {
                spin_lock_irqsave(&chip->open_lock, flags);
                if (snd_rawmidi_transmit_peek(substream, &byte, 1) != 1) {
@@ -219,7 +219,7 @@ static void snd_sb8dsp_midi_output_write(snd_rawmidi_substream_t * substream)
 static void snd_sb8dsp_midi_output_timer(unsigned long data)
 {
        snd_rawmidi_substream_t * substream = (snd_rawmidi_substream_t *) data;
-       sb_t * chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+       sb_t * chip = substream->rmidi->private_data;
        unsigned long flags;
 
        spin_lock_irqsave(&chip->open_lock, flags);
@@ -234,7 +234,7 @@ static void snd_sb8dsp_midi_output_trigger(snd_rawmidi_substream_t * substream,
        unsigned long flags;
        sb_t *chip;
 
-       chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+       chip = substream->rmidi->private_data;
        spin_lock_irqsave(&chip->open_lock, flags);
        if (up) {
                if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) {
index f36383a..8935ae9 100644 (file)
 #include <asm/io.h>
 #include <asm/dma.h>
 
-#define chip_t sb_t
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 #define BUSY_LOOPS 100000
 
@@ -197,13 +194,13 @@ static int snd_sbdsp_free(sb_t *chip)
                free_dma(chip->dma16);
        }
 #endif
-       snd_magic_kfree(chip);
+       kfree(chip);
        return 0;
 }
 
 static int snd_sbdsp_dev_free(snd_device_t *device)
 {
-       sb_t *chip = snd_magic_cast(sb_t, device->device_data, return -ENXIO);
+       sb_t *chip = device->device_data;
        return snd_sbdsp_free(chip);
 }
 
@@ -224,7 +221,7 @@ int snd_sbdsp_create(snd_card_t *card,
 
        snd_assert(r_chip != NULL, return -EINVAL);
        *r_chip = NULL;
-       chip = snd_magic_kcalloc(sb_t, 0, GFP_KERNEL);
+       chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
        spin_lock_init(&chip->reg_lock);
index 31baf20..cc5a2c6 100644 (file)
@@ -27,8 +27,6 @@
 #include <sound/sb.h>
 #include <sound/control.h>
 
-#define chip_t sb_t
-
 #undef IO_DEBUG
 
 void snd_sbmixer_write(sb_t *chip, unsigned char reg, unsigned char data)
index 76e3c6a..d0573b0 100644 (file)
                 ad1848_control(AD1848_MIXER_REROUTE, ((oldctl)<<8)|(newctl))
                
 
-int ad1848_init(char *name, int io_base, int irq, int dma_playback,
+int ad1848_init(char *name, struct resource *ports, int irq, int dma_playback,
        int dma_capture, int share_dma, int *osp, struct module *owner);
 void ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma);
 
-int ad1848_detect (int io_base, int *flags, int *osp);
+int ad1848_detect (struct resource *ports, int *flags, int *osp);
 int ad1848_control(int cmd, int arg);
 
 irqreturn_t adintr(int irq, void *dev_id, struct pt_regs * dummy);
-void attach_ms_sound(struct address_info * hw_config, struct module * owner);
+void attach_ms_sound(struct address_info * hw_config, struct resource *ports, struct module * owner);
 
-int probe_ms_sound(struct address_info *hw_config);
+int probe_ms_sound(struct address_info *hw_config, struct resource *ports);
 void unload_ms_sound(struct address_info *hw_info);
index 5d13ef1..964a6b4 100644 (file)
@@ -34,9 +34,9 @@
 #define AD_DMAWAVICC   0x98    /* WAV interrupt current count */
 #define AD_DMAWAVIBC   0x9c    /* WAV interrupt base count */
 #define AD_DMARESCTRL  0xa0    /* RES PCI control/status */
-#define AD_DMAADCCTRL  0xa8    /* RES PCI control/status */
-#define AD_DMASYNCTRL  0xb0    /* RES PCI control/status */
-#define AD_DMAWAVCTRL  0xb8    /* RES PCI control/status */
+#define AD_DMAADCCTRL  0xa8    /* ADC PCI control/status */
+#define AD_DMASYNCTRL  0xb0    /* SYN PCI control/status */
+#define AD_DMAWAVCTRL  0xb8    /* WAV PCI control/status */
 #define AD_DMADISR     0xc0    /* PCI DMA intr status */
 #define AD_DMACHSS     0xc4    /* PCI DMA channel stop status */
 
index a7e2c3c..8976224 100644 (file)
@@ -65,7 +65,6 @@
 #include <linux/ac97_codec.h>
 #include <linux/interrupt.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #ifndef PCI_DEVICE_ID_ALI_5455
 #define PCI_DEVICE_ID_ALI_5455 0x5455
index ccfbad2..c5d220e 100644 (file)
@@ -67,9 +67,9 @@
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
 #include <linux/wrapper.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/au1000.h>
 #include <asm/au1000_dma.h>
 
index 2a7ea80..0d76e78 100644 (file)
@@ -961,7 +961,7 @@ static int __devinit btaudio_probe(struct pci_dev *pci_dev,
        /* init hw */
         btwrite(0, REG_GPIO_DMA_CTL);
         btwrite(0, REG_INT_MASK);
-        btwrite(~0x0UL, REG_INT_STAT);
+        btwrite(~0U, REG_INT_STAT);
        pci_set_master(pci_dev);
 
        if ((rc = request_irq(bta->irq, btaudio_irq, SA_SHIRQ|SA_INTERRUPT,
@@ -1033,7 +1033,7 @@ static void __devexit btaudio_remove(struct pci_dev *pci_dev)
        /* turn off all DMA / IRQs */
         btand(~15, REG_GPIO_DMA_CTL);
         btwrite(0, REG_INT_MASK);
-        btwrite(~0x0UL, REG_INT_STAT);
+        btwrite(~0U, REG_INT_STAT);
 
        /* unregister devices */
        if (digital) {
index d05db7e..1d0f6ed 100644 (file)
@@ -128,27 +128,33 @@ static void enable_xctrl(int baseio)
         outb(((unsigned char) (ENABLE_PINS | regd)), baseio + INDEX_DATA );
 }
 
-int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured)
+static int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured)
 {
        int i, n;
        int base = hw_config->io_base, irq = hw_config->irq;
        int dma1 = hw_config->dma, dma2 = hw_config->dma2;
+       struct resource *ports;
+
+       if (base == -1 || irq == -1 || dma1 == -1) {
+               printk(KERN_ERR "cs4232: dma, irq and io must be set.\n");
+               return 0;
+       }
 
        /*
         * Verify that the I/O port range is free.
         */
 
-       if (check_region(base, 4))
-       {
+       ports = request_region(base, 4, "ad1848");
+       if (!ports) {
                printk(KERN_ERR "cs4232.c: I/O port 0x%03x not free\n", base);
                return 0;
        }
-       if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp)) {
-               return 1;       /* The card is already active */
+       if (ad1848_detect(ports, NULL, hw_config->osp)) {
+               goto got_it;    /* The card is already active */
        }
        if (isapnp_configured) {
                printk(KERN_ERR "cs4232.c: ISA PnP configured, but not detected?\n");
-               return 0;
+               goto fail;
        }
 
        /*
@@ -241,30 +247,20 @@ int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured)
                 * Then try to detect the codec part of the chip
                 */
 
-               if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp))
-                       return 1;
+               if (ad1848_detect(ports, NULL, hw_config->osp))
+                       goto got_it;
                
                sleep(HZ);
        }
+fail:
+       release_region(base, 4);
        return 0;
-}
-
-void __init attach_cs4232(struct address_info *hw_config)
-{
-       int base = hw_config->io_base,
-               irq = hw_config->irq,
-               dma1 = hw_config->dma,
-               dma2 = hw_config->dma2;
-
-       if (base == -1 || irq == -1 || dma1 == -1) {
-               printk(KERN_ERR "cs4232: dma, irq and io must be set.\n");
-               return;
-       }
 
+got_it:
        if (dma2 == -1)
                dma2 = dma1;
 
-       hw_config->slots[0] = ad1848_init("Crystal audio controller", base,
+       hw_config->slots[0] = ad1848_init("Crystal audio controller", ports,
                                          irq,
                                          dma1,         /* Playback DMA */
                                          dma2,         /* Capture DMA */
@@ -308,9 +304,9 @@ void __init attach_cs4232(struct address_info *hw_config)
        }
        
        if (bss)
-       {
                enable_xctrl(base);
-       }
+
+       return 1;
 }
 
 static void __devexit unload_cs4232(struct address_info *hw_config)
@@ -423,7 +419,6 @@ static int cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev
                kfree(isapnpcfg);
                return -ENODEV;
        }
-       attach_cs4232(isapnpcfg);
        pnp_set_drvdata(dev,isapnpcfg);
        return 0;
 }
@@ -486,7 +481,6 @@ static int __init init_cs4232(void)
 
        if (probe_cs4232(&cfg,FALSE) == 0)
                return -ENODEV;
-       attach_cs4232(&cfg);
 
        return 0;
 }
index 31c8d8b..a5a0029 100644 (file)
@@ -1,5 +1,3 @@
 
-int probe_cs4232 (struct address_info *hw_config,int useisapnp);
-void attach_cs4232 (struct address_info *hw_config);
 int probe_cs4232_mpu (struct address_info *hw_config);
 void attach_cs4232_mpu (struct address_info *hw_config);
index 418f976..c212b94 100644 (file)
@@ -94,7 +94,6 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #include "cs46xxpm-24.h"
 #include "cs46xx_wrapper-24.h"
@@ -2096,7 +2095,7 @@ static ssize_t cs_read(struct file *file, char __user *buffer, size_t count, lof
        unsigned copied=0;
 
        CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, 
-               printk("cs46xx: cs_read()+ %d\n",count) );
+               printk("cs46xx: cs_read()+ %zd\n",count) );
        state = (struct cs_state *)card->states[0];
        if(!state)
                return -ENODEV;
@@ -2157,9 +2156,9 @@ static ssize_t cs_read(struct file *file, char __user *buffer, size_t count, lof
                }
 
                CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO 
-                       "_read() copy_to cnt=%d count=%d ", cnt,count) );
+                       "_read() copy_to cnt=%d count=%zd ", cnt,count) );
                CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO 
-                       " .dmasize=%d .count=%d buffer=%p ret=%d\n",
+                       " .dmasize=%d .count=%d buffer=%p ret=%zd\n",
                        dmabuf->dmasize,dmabuf->count,buffer,ret) );
 
                 if (cs_copy_to_user(state, buffer, 
@@ -2184,7 +2183,7 @@ out2:
        up(&state->sem);
        set_current_state(TASK_RUNNING);
        CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, 
-               printk("cs46xx: cs_read()- %d\n",ret) );
+               printk("cs46xx: cs_read()- %zd\n",ret) );
        return ret;
 }
 
@@ -2202,7 +2201,7 @@ static ssize_t cs_write(struct file *file, const char __user *buffer, size_t cou
        int cnt;
 
        CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4,
-               printk("cs46xx: cs_write called, count = %d\n", count) );
+               printk("cs46xx: cs_write called, count = %zd\n", count) );
        state = (struct cs_state *)card->states[1];
        if(!state)
                return -ENODEV;
@@ -2309,7 +2308,7 @@ out:
        set_current_state(TASK_RUNNING);
 
        CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 2, 
-               printk("cs46xx: cs_write()- ret=0x%x\n", ret) );
+               printk("cs46xx: cs_write()- ret=%zd\n", ret) );
        return ret;
 }
 
index 0ffb082..cb84558 100644 (file)
@@ -14,7 +14,7 @@ config DMASOUND_ATARI
 
 config DMASOUND_PMAC
        tristate "PowerMac DMA sound support"
-       depends on PPC_PMAC && SOUND && I2C
+       depends on PPC32 && PPC_PMAC && SOUND && I2C
        select DMASOUND
        help
          If you want to use the internal audio of your PowerMac in Linux,
index ec2424d..f0a48f3 100644 (file)
@@ -320,7 +320,6 @@ static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer,
 {
        struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
        struct midi_hdr *midihdr;
-       ssize_t ret = 0;
        unsigned long flags;
 
        DPD(4, "emu10k1_midi_write(), count=%#x\n", (u32) count);
@@ -344,7 +343,7 @@ static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer,
        if (copy_from_user(midihdr->data, buffer, count)) {
                kfree(midihdr->data);
                kfree(midihdr);
-               return ret ? ret : -EFAULT;
+               return -EFAULT;
        }
 
        spin_lock_irqsave(&midi_spinlock, flags);
index ac4bada..67b2bbb 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/proc_fs.h>
 
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/io.h>
 
 #define DRIVER_NAME    "forte"
index 88f5ca1..e0111a7 100644 (file)
@@ -160,22 +160,29 @@ irqreturn_t gusintr(int irq, void *dev_id, struct pt_regs *dummy)
 
 #ifdef CONFIG_SOUND_GUS16
 
-static int __init probe_gus_db16(struct address_info *hw_config)
+static int __init init_gus_db16(struct address_info *hw_config)
 {
-       return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
-}
+       struct resource *ports;
+
+       ports = request_region(hw_config->io_base, 4, "ad1848");
+       if (!ports)
+               return 0;
+
+       if (!ad1848_detect(ports, NULL, hw_config->osp)) {
+               release_region(hw_config->io_base, 4);
+               return 0;
+       }
 
-static void __init attach_gus_db16(struct address_info *hw_config)
-{
        gus_pcm_volume = 100;
        gus_wave_volume = 90;
 
-       hw_config->slots[3] = ad1848_init("GUS 16 bit sampling", hw_config->io_base,
+       hw_config->slots[3] = ad1848_init("GUS 16 bit sampling", ports,
                                          hw_config->irq,
                                          hw_config->dma,
                                          hw_config->dma, 0,
                                          hw_config->osp,
                                          THIS_MODULE);
+       return 1;
 }
 
 static void __exit unload_gus_db16(struct address_info *hw_config)
@@ -244,11 +251,8 @@ static int __init init_gus(void)
        }
 
 #ifdef CONFIG_SOUND_GUS16
-       if (probe_gus_db16(&cfg) && gus16) {
-               /* FIXME: This can't work, can it ? -- Christoph */
-               attach_gus_db16(&cfg);
+       if (gus16 && init_gus_db16(&cfg))
                db16 = 1;
-       }       
 #endif
        if (!probe_gus(&cfg))
                return -ENODEV;
index 22f0eff..2f83ac8 100644 (file)
@@ -8,10 +8,11 @@
        On older 715 machines you'll find the technically identical chip 
        called 'Vivace'. Both Harmony and Vicace are supported by this driver.
 
-       Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@linuxcare.com>
+       Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@onefishtwo.ca>
        Copyright 2000-2003 (c) Helge Deller <deller@gmx.de>
        Copyright 2001 (c) Matthieu Delahaye <delahaym@esiee.fr>
        Copyright 2001 (c) Jean-Christophe Vaugeois <vaugeoij@esiee.fr>
+       Copyright 2004 (c) Stuart Brady <sdbrady@ntlworld.com>
 
                                
 TODO:
@@ -124,9 +125,17 @@ TODO:
 #define GAIN_RO_MASK    ( 0x3f << GAIN_RO_SHIFT) 
 
 
-#define MAX_OUTPUT_LEVEL (GAIN_RO_MASK >> GAIN_RO_SHIFT)
-#define MAX_INPUT_LEVEL  (GAIN_RI_MASK >> GAIN_RI_SHIFT)
-#define MAX_VOLUME_LEVEL (GAIN_MA_MASK >> GAIN_MA_SHIFT)
+#define MAX_OUTPUT_LEVEL  (GAIN_RO_MASK >> GAIN_RO_SHIFT)
+#define MAX_INPUT_LEVEL   (GAIN_RI_MASK >> GAIN_RI_SHIFT)
+#define MAX_MONITOR_LEVEL (GAIN_MA_MASK >> GAIN_MA_SHIFT)
+
+#define MIXER_INTERNAL   SOUND_MIXER_LINE1
+#define MIXER_LINEOUT    SOUND_MIXER_LINE2
+#define MIXER_HEADPHONES SOUND_MIXER_LINE3
+
+#define MASK_INTERNAL   SOUND_MASK_LINE1
+#define MASK_LINEOUT    SOUND_MASK_LINE2
+#define MASK_HEADPHONES SOUND_MASK_LINE3
 
 /*
  * Channels Mask in mixer register
@@ -543,6 +552,7 @@ static ssize_t harmony_audio_write(struct file *file,
        int count = 0;
        int frame_size;
        int buf_to_fill;
+       int fresh_buffer;
 
        if (!harmony.format_initialized) {
                if (harmony_format_auto_detect(buffer, total_count))
@@ -564,12 +574,16 @@ static ssize_t harmony_audio_write(struct file *file,
                
                
                buf_to_fill = (harmony.first_filled_play+harmony.nb_filled_play); 
-               if (harmony.play_offset)
+               if (harmony.play_offset) {
                        buf_to_fill--;
+                       buf_to_fill += MAX_BUFS;
+               }
                buf_to_fill %= MAX_BUFS;
-
+               
+               fresh_buffer = (harmony.play_offset == 0);
+               
                /* Figure out the size of the frame */
-               if ((total_count-count) > HARMONY_BUF_SIZE - harmony.play_offset) {
+               if ((total_count-count) >= HARMONY_BUF_SIZE - harmony.play_offset) {
                        frame_size = HARMONY_BUF_SIZE - harmony.play_offset;
                } else {
                        frame_size = total_count - count;
@@ -587,7 +601,7 @@ static ssize_t harmony_audio_write(struct file *file,
                CHECK_WBACK_INV_OFFSET(played_buf, (HARMONY_BUF_SIZE*buf_to_fill + harmony.play_offset), 
                                frame_size);
        
-               if (!harmony.play_offset)
+               if (fresh_buffer)
                        harmony.nb_filled_play++;
                
                count += frame_size;
@@ -650,18 +664,17 @@ static int harmony_audio_ioctl(struct inode *inode,
                        switch (ival) {
                        case AFMT_MU_LAW:       new_format = HARMONY_DF_8BIT_ULAW; break;
                        case AFMT_A_LAW:        new_format = HARMONY_DF_8BIT_ALAW; break;
-                       case AFMT_S16_LE:       /* fall through, but not really supported */
-                       case AFMT_S16_BE:       new_format = HARMONY_DF_16BIT_LINEAR;
-                                               ival = AFMT_S16_BE;
-                                               break; 
+                       case AFMT_S16_BE:       new_format = HARMONY_DF_16BIT_LINEAR; break;
                        default: {
                                DPRINTK(KERN_WARNING PFX 
                                        "unsupported sound format 0x%04x requested.\n",
                                        ival);
-                               return -EINVAL;
+                               ival = AFMT_S16_BE;
+                               return put_user(ival, (int *) arg);
                        }
                        }
                        harmony_set_format(new_format);
+                       return 0;
                } else {
                        switch (harmony.data_format) {
                        case HARMONY_DF_8BIT_ULAW:      ival = AFMT_MU_LAW; break;
@@ -669,8 +682,8 @@ static int harmony_audio_ioctl(struct inode *inode,
                        case HARMONY_DF_16BIT_LINEAR:   ival = AFMT_U16_BE; break;
                        default: ival = 0;
                        }
+                       return put_user(ival, (int *) arg);
                }
-               return put_user(ival, (int *) arg);
 
        case SOUND_PCM_READ_RATE:
                ival = harmony.dac_rate;
@@ -689,7 +702,17 @@ static int harmony_audio_ioctl(struct inode *inode,
                if (ival != 0 && ival != 1)
                        return -EINVAL;
                harmony_set_stereo(ival);
-               return put_user(ival, (int *) arg);
+               return 0;
+       case SNDCTL_DSP_CHANNELS:
+               if (get_user(ival, (int *) arg))
+                       return -EFAULT;
+               if (ival != 1 && ival != 2) {
+                       ival = harmony.stereo_select == HARMONY_SS_MONO ? 1 : 2;
+                       return put_user(ival, (int *) arg);
+               }
+               harmony_set_stereo(ival-1);
+               return 0;
 
        case SNDCTL_DSP_GETBLKSIZE:
                ival = HARMONY_BUF_SIZE;
@@ -887,7 +910,7 @@ static int harmony_mixer_get_level(int channel)
        int right_level;
 
        switch (channel) {
-               case SOUND_MIXER_OGAIN:
+               case SOUND_MIXER_VOLUME:
                        left_level  = (harmony.current_gain & GAIN_LO_MASK) >> GAIN_LO_SHIFT;
                        right_level = (harmony.current_gain & GAIN_RO_MASK) >> GAIN_RO_SHIFT;
                        left_level  = to_oss_level(MAX_OUTPUT_LEVEL - left_level, MAX_OUTPUT_LEVEL);
@@ -901,10 +924,10 @@ static int harmony_mixer_get_level(int channel)
                        right_level= to_oss_level(right_level, MAX_INPUT_LEVEL);
                        return (right_level << 8)+left_level;
                        
-               case SOUND_MIXER_VOLUME:
+               case SOUND_MIXER_MONITOR:
                        left_level = (harmony.current_gain & GAIN_MA_MASK) >> GAIN_MA_SHIFT;
-                       left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL);
-                       return left_level;
+                       left_level = to_oss_level(MAX_MONITOR_LEVEL-left_level, MAX_MONITOR_LEVEL);
+                       return (left_level << 8)+left_level;
        }
        return -EINVAL;
 }
@@ -926,9 +949,11 @@ static int harmony_mixer_set_level(int channel, int value)
 
        right_level = (value & 0x0000ff00) >> 8;
        left_level = value & 0x000000ff;
+       if (right_level > 100) right_level = 100;
+       if (left_level > 100) left_level = 100;
   
        switch (channel) {
-               case SOUND_MIXER_OGAIN:
+               case SOUND_MIXER_VOLUME:
                        right_level = to_harmony_level(100-right_level, MAX_OUTPUT_LEVEL);
                        left_level  = to_harmony_level(100-left_level, MAX_OUTPUT_LEVEL);
                        new_right_level = to_oss_level(MAX_OUTPUT_LEVEL - right_level, MAX_OUTPUT_LEVEL);
@@ -948,12 +973,12 @@ static int harmony_mixer_set_level(int channel, int value)
                        harmony_mixer_set_gain();
                        return (new_right_level << 8) + new_left_level;
        
-               case SOUND_MIXER_VOLUME:
-                       left_level = to_harmony_level(100-left_level, MAX_VOLUME_LEVEL);
-                       new_left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL);
-                       harmony.current_gain = (harmony.current_gain & ~GAIN_MA_MASK)| (left_level << GAIN_MA_SHIFT);
+               case SOUND_MIXER_MONITOR:
+                       left_level = to_harmony_level(100-left_level, MAX_MONITOR_LEVEL);
+                       new_left_level = to_oss_level(MAX_MONITOR_LEVEL-left_level, MAX_MONITOR_LEVEL);
+                       harmony.current_gain = (harmony.current_gain & ~GAIN_MA_MASK) | (left_level << GAIN_MA_SHIFT);
                        harmony_mixer_set_gain();
-                       return new_left_level;
+                       return (new_left_level << 8) + new_left_level;
        }
 
        return -EINVAL;
@@ -986,11 +1011,15 @@ static int harmony_mixer_set_recmask(int recmask)
 {
        int new_input_line;
        int new_input_mask;
-
-       if ((recmask & SOUND_MASK_LINE)) {
+       int current_input_line;
+       
+       current_input_line = (harmony.current_gain & GAIN_IS_MASK)
+                                   >> GAIN_IS_SHIFT;
+       if ((current_input_line && ((recmask & SOUND_MASK_LINE) || !(recmask & SOUND_MASK_MIC))) ||
+               (!current_input_line && ((recmask & SOUND_MASK_LINE) && !(recmask & SOUND_MASK_MIC)))) {
                new_input_line = 0;
                new_input_mask = SOUND_MASK_LINE;
-       } else  {
+       } else {
                new_input_line = 1;
                new_input_mask = SOUND_MASK_MIC;
        }
@@ -1009,9 +1038,9 @@ static int harmony_mixer_get_outmask(void)
 {
        int outmask = 0;
        
-       if (harmony.current_gain & GAIN_HE_MASK) outmask |=SOUND_MASK_PHONEOUT;
-       if (harmony.current_gain & GAIN_LE_MASK) outmask |=SOUND_MASK_LINE;
-       if (harmony.current_gain & GAIN_SE_MASK) outmask |=SOUND_MASK_SPEAKER;
+       if (harmony.current_gain & GAIN_SE_MASK) outmask |= MASK_INTERNAL;
+       if (harmony.current_gain & GAIN_LE_MASK) outmask |= MASK_LINEOUT;
+       if (harmony.current_gain & GAIN_HE_MASK) outmask |= MASK_HEADPHONES;
        
        return outmask;
 }
@@ -1019,24 +1048,24 @@ static int harmony_mixer_get_outmask(void)
 
 static int harmony_mixer_set_outmask(int outmask)
 {
-       if (outmask & SOUND_MASK_PHONEOUT
-               harmony.current_gain |= GAIN_HE_MASK; 
+       if (outmask & MASK_INTERNAL
+               harmony.current_gain |= GAIN_SE_MASK;
        else 
-               harmony.current_gain &= ~GAIN_HE_MASK;
+               harmony.current_gain &= ~GAIN_SE_MASK;
        
-       if (outmask & SOUND_MASK_LINE
+       if (outmask & MASK_LINEOUT
                harmony.current_gain |= GAIN_LE_MASK;
        else 
                harmony.current_gain &= ~GAIN_LE_MASK;
        
-       if (outmask & SOUND_MASK_SPEAKER
-               harmony.current_gain |= GAIN_SE_MASK;
+       if (outmask & MASK_HEADPHONES
+               harmony.current_gain |= GAIN_HE_MASK; 
        else 
-               harmony.current_gain &= ~GAIN_SE_MASK;
+               harmony.current_gain &= ~GAIN_HE_MASK;
        
        harmony_mixer_set_gain();
 
-       return (outmask & (SOUND_MASK_PHONEOUT | SOUND_MASK_LINE | SOUND_MASK_SPEAKER));
+       return (outmask & (MASK_INTERNAL | MASK_LINEOUT | MASK_HEADPHONES));
 }
 
 /*
@@ -1074,19 +1103,19 @@ static int harmony_mixer_ioctl(struct inode * inode, struct file * file,
                ret = SOUND_CAP_EXCL_INPUT;
                break;
        case MIXER_READ(SOUND_MIXER_STEREODEVS):
-               ret = SOUND_MASK_IGAIN | SOUND_MASK_OGAIN;
+               ret = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN;
                break;
                
        case MIXER_READ(SOUND_MIXER_RECMASK):
                ret = SOUND_MASK_MIC | SOUND_MASK_LINE;
                break;
        case MIXER_READ(SOUND_MIXER_DEVMASK):
-               ret = SOUND_MASK_OGAIN | SOUND_MASK_IGAIN |
-                       SOUND_MASK_VOLUME;
+               ret = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN |
+                       SOUND_MASK_MONITOR;
                break;
        case MIXER_READ(SOUND_MIXER_OUTMASK):
-               ret = SOUND_MASK_SPEAKER | SOUND_MASK_LINE |
-                       SOUND_MASK_PHONEOUT;
+               ret = MASK_INTERNAL | MASK_LINEOUT |
+                       MASK_HEADPHONES;
                break;
                
        case MIXER_WRITE(SOUND_MIXER_RECSRC):
@@ -1103,15 +1132,15 @@ static int harmony_mixer_ioctl(struct inode * inode, struct file * file,
                ret = harmony_mixer_get_outmask();
                break;
        
-       case MIXER_WRITE(SOUND_MIXER_OGAIN):
-       case MIXER_WRITE(SOUND_MIXER_IGAIN):
        case MIXER_WRITE(SOUND_MIXER_VOLUME):
+       case MIXER_WRITE(SOUND_MIXER_IGAIN):
+       case MIXER_WRITE(SOUND_MIXER_MONITOR):
                ret = harmony_mixer_set_level(cmd & 0xff, val);
                break;
 
-       case MIXER_READ(SOUND_MIXER_OGAIN):
-       case MIXER_READ(SOUND_MIXER_IGAIN):
        case MIXER_READ(SOUND_MIXER_VOLUME):
+       case MIXER_READ(SOUND_MIXER_IGAIN):
+       case MIXER_READ(SOUND_MIXER_MONITOR):
                ret = harmony_mixer_get_level(cmd & 0xff);
                break;
 
@@ -1201,16 +1230,15 @@ harmony_driver_probe(struct parisc_device *dev)
                return -EBUSY;
        }
 
-       harmony.dev = dev;
-
-       /* Set the HPA of harmony */
-       harmony.hpa = (struct harmony_hpa *)dev->hpa;
-
-       if (!harmony.dev->irq) {
+       if (!dev->irq) {
                printk(KERN_ERR PFX "no irq found\n");
                return -ENODEV;
        }
 
+       /* Set the HPA of harmony */
+       harmony.hpa = (struct harmony_hpa *)dev->hpa;
+       harmony.dev = dev;
+
        /* Grab the ID and revision from the device */
        id = gsc_readb(&harmony.hpa->id);
        if ((id | 1) != 0x15) {
@@ -1293,7 +1321,7 @@ static void __exit cleanup_harmony(void)
 }
 
 
-MODULE_AUTHOR("Alex DeVries <alex@linuxcare.com>");
+MODULE_AUTHOR("Alex DeVries <alex@onefishtwo.ca>");
 MODULE_DESCRIPTION("Harmony sound driver");
 MODULE_LICENSE("GPL");
 
index 16e7d01..f984133 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/it8172/it8172.h>
 
 /* --------------------------------------------------------------------- */
index b7ef7de..4c5db81 100644 (file)
@@ -54,7 +54,6 @@ static int      mad16_conf;
 static int      mad16_cdsel;
 static struct gameport gameport;
 static spinlock_t lock=SPIN_LOCK_UNLOCKED;
-static int      already_initialized;
 
 #define C928   1
 #define MOZART 2
@@ -313,19 +312,6 @@ static int __init detect_mad16(void)
 
 static int __init wss_init(struct address_info *hw_config)
 {
-       int ad_flags = 0;
-
-       /*
-        *    Verify the WSS parameters
-        */
-
-       if (check_region(hw_config->io_base, 8))
-       {
-               printk(KERN_ERR "MSS: I/O port conflict\n");
-               return 0;
-       }
-       if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
-               return 0;
        /*
         * Check if the IO port returns valid signature. The original MS Sound
         * system returns 0x04 while some cards (AudioTrix Pro for example)
@@ -338,31 +324,20 @@ static int __init wss_init(struct address_info *hw_config)
                DDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, inb(hw_config->io_base + 3)));
                return 0;
        }
-       if (hw_config->irq > 11)
-       {
-               printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
-               return 0;
-       }
-       if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
-       {
-               printk(KERN_ERR "MSS: Bad DMA %d\n", hw_config->dma);
-               return 0;
-       }
        /*
         * Check that DMA0 is not in use with a 8 bit board.
         */
-
        if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
        {
                printk("MSS: Can't use DMA0 with a 8 bit card/slot\n");
                return 0;
        }
-       if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
+       if (hw_config->irq > 9 && inb(hw_config->io_base + 3) & 0x80)
                printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
        return 1;
 }
 
-static int __init init_c930(struct address_info *hw_config)
+static void __init init_c930(struct address_info *hw_config, int base)
 {
        unsigned char cfg = 0;
 
@@ -376,25 +351,7 @@ static int __init init_c930(struct address_info *hw_config)
                   somewhere else. */
                cfg =  (cfg & 0x09) ^ 0x07;
        }
-
-       switch (hw_config->io_base)
-       {
-               case 0x530:
-                       cfg |= 0x00;
-                       break;
-               case 0xe80:
-                       cfg |= 0x10;
-                       break;
-               case 0xf40:
-                       cfg |= 0x20;
-                       break;
-               case 0x604:
-                       cfg |= 0x30;
-                       break;
-               default:
-                       printk(KERN_ERR "MAD16: Invalid codec port %x\n", hw_config->io_base);
-                       return 0;
-       }
+       cfg |= base << 4;
        mad_write(MC1_PORT, cfg);
 
        /* MC2 is CD configuration. Don't touch it. */
@@ -414,8 +371,6 @@ static int __init init_c930(struct address_info *hw_config)
        mad_write(MC6_PORT, 0x02);      /* Enable WSS, Disable MPU and SB */
        mad_write(MC7_PORT, 0xCB);
        mad_write(MC10_PORT, 0x11);
-
-       return wss_init(hw_config);
 }
 
 static int __init chip_detect(void)
@@ -508,20 +463,48 @@ static int __init chip_detect(void)
 static int __init probe_mad16(struct address_info *hw_config)
 {
        int i;
-       static int valid_ports[] = 
-       {
-               0x530, 0xe80, 0xf40, 0x604
-       };
        unsigned char tmp;
        unsigned char cs4231_mode = 0;
 
        int ad_flags = 0;
 
-       if (already_initialized)
-               return 0;
+       signed char bits;
+
+       static char     dma_bits[4] = {
+               1, 2, 0, 3
+       };
+
+       int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
+       int dma = hw_config->dma, dma2 = hw_config->dma2;
+       unsigned char dma2_bit = 0;
+       int base;
+       struct resource *ports;
 
        mad16_osp = hw_config->osp;
 
+       switch (hw_config->io_base) {
+       case 0x530:
+               base = 0;
+               break;
+       case 0xe80:
+               base = 1;
+               break;
+       case 0xf40:
+               base = 2;
+               break;
+       case 0x604:
+               base = 3;
+               break;
+       default:
+               printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
+               return 0;
+       }
+
+       if (dma != 0 && dma != 1 && dma != 3) {
+               printk(KERN_ERR "MSS: Bad DMA %d\n", dma);
+               return 0;
+       }
+
        /*
         *    Check that all ports return 0xff (bus float) when no password
         *      is written to the password register.
@@ -531,9 +514,44 @@ static int __init probe_mad16(struct address_info *hw_config)
        if (!chip_detect())
                return 0;
 
-       if (board_type == C930)
-               return init_c930(hw_config);
+       switch (hw_config->irq) {
+       case 7:
+               bits = 8;
+               break;
+       case 9:
+               bits = 0x10;
+               break;
+       case 10:
+               bits = 0x18;
+               break;
+       case 12:
+               bits = 0x20;
+               break;
+       case 5: /* Also IRQ5 is possible on C930 */
+               if (board_type == C930 || c924pnp) {
+                       bits = 0x28;
+                       break;
+               }
+       default:
+               printk(KERN_ERR "MAD16/Mozart: Bad IRQ %d\n", hw_config->irq);
+               return 0;
+       }
+
+       ports = request_region(hw_config->io_base + 4, 4, "ad1848");
+       if (!ports) {
+               printk(KERN_ERR "MSS: I/O port conflict\n");
+               return 0;
+       }
+       if (!request_region(hw_config->io_base, 4, "mad16 WSS config")) {
+               release_region(hw_config->io_base + 4, 4);
+               printk(KERN_ERR "MSS: I/O port conflict\n");
+               return 0;
+       }
 
+       if (board_type == C930) {
+               init_c930(hw_config, base);
+               goto got_it;
+       }
 
        for (i = 0xf8d; i <= 0xf93; i++) {
                if (!c924pnp)
@@ -547,20 +565,7 @@ static int __init probe_mad16(struct address_info *hw_config)
  */
 
        tmp = (mad_read(MC1_PORT) & 0x0f) | 0x80;       /* Enable WSS, Disable SB */
-
-       for (i = 0; i < 5; i++)
-       {
-               if (i > 3)      /* Not a valid port */
-               {
-                       printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
-                       return 0;
-               }
-               if (valid_ports[i] == hw_config->io_base)
-               {
-                       tmp |= i << 4;  /* WSS port select bits */
-                       break;
-               }
-       }
+       tmp |= base << 4;       /* WSS port select bits */
 
        /*
         * Set optional CD-ROM and joystick settings.
@@ -580,8 +585,8 @@ static int __init probe_mad16(struct address_info *hw_config)
                mad_write(MC5_PORT, 0x05);
                mad_write(MC6_PORT, 0x03);
        }
-       if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
-               return 0;
+       if (!ad1848_detect(ports, &ad_flags, mad16_osp))
+               goto fail;
 
        if (ad_flags & (AD_F_CS4231 | AD_F_CS4248))
                cs4231_mode = 0x02;     /* CS4248/CS4231 sync delay switch */
@@ -604,43 +609,19 @@ static int __init probe_mad16(struct address_info *hw_config)
                else
                        DDB(printk("port %03x after init = %02x\n", i-0x80, mad_read(i)));
        }
-       wss_init(hw_config);
 
-       return 1;
-}
+got_it:
+       ad_flags = 0;
+       if (!ad1848_detect(ports, &ad_flags, mad16_osp))
+               goto fail;
 
-static void __init attach_mad16(struct address_info *hw_config)
-{
-
-       static signed char     interrupt_bits[12] = {
-               -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
-       };
-       signed char bits;
-
-       static char     dma_bits[4] = {
-               1, 2, 0, 3
-       };
-
-       int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
-       int ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2;
-       unsigned char dma2_bit = 0;
-
-       already_initialized = 1;
-
-       if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
-               return;
+       if (!wss_init(hw_config))
+               goto fail;
 
        /*
         * Set the IRQ and DMA addresses.
         */
        
-       if (board_type == C930 || c924pnp)
-               interrupt_bits[5] = 0x28;       /* Also IRQ5 is possible on C930 */
-
-       bits = interrupt_bits[hw_config->irq];
-       if (bits == -1)
-               return;
-
        outb((bits | 0x40), config_port);
        if ((inb(version_port) & 0x40) == 0)
                printk(KERN_ERR "[IRQ Conflict?]\n");
@@ -675,27 +656,24 @@ static void __init attach_mad16(struct address_info *hw_config)
 
        outb((bits | dma_bits[dma] | dma2_bit), config_port);   /* Write IRQ+DMA setup */
 
-       hw_config->slots[0] = ad1848_init("mad16 WSS", hw_config->io_base + 4,
+       hw_config->slots[0] = ad1848_init("mad16 WSS", ports,
                                          hw_config->irq,
                                          dma,
                                          dma2, 0,
                                          hw_config->osp,
                                          THIS_MODULE);
-       request_region(hw_config->io_base, 4, "mad16 WSS config");
+       return 1;
+
+fail:
+       release_region(hw_config->io_base + 4, 4);
+       release_region(hw_config->io_base, 4);
+       return 0;
 }
 
 static int __init probe_mad16_mpu(struct address_info *hw_config)
 {
-       static int mpu_attached;
        unsigned char tmp;
 
-       if (!already_initialized)       /* The MSS port must be initialized first */
-               return 0;
-
-       if (mpu_attached)               /* Don't let them call this twice */
-               return 0;
-       mpu_attached = 1;
-
        if (board_type < C929)  /* Early chip. No MPU support. Just SB MIDI */
        {
 
@@ -732,8 +710,12 @@ static int __init probe_mad16_mpu(struct address_info *hw_config)
 
                mad_write(MC3_PORT, tmp | 0x04);
                hw_config->driver_use_1 = SB_MIDI_ONLY;
-               if (!sb_dsp_detect(hw_config, 0, 0, NULL))
+               if (!request_region(hw_config->io_base, 16, "soundblaster"))
+                       return 0;
+               if (!sb_dsp_detect(hw_config, 0, 0, NULL)) {
+                       release_region(hw_config->io_base, 16);
                        return 0;
+               }
 
                if (mad_read(MC1_PORT) & 0x20)
                        hw_config->io_base = 0x240;
@@ -1031,15 +1013,18 @@ static int __init init_mad16(void)
                printk(KERN_ERR "I/O, DMA and irq are mandatory\n");
                return -EINVAL;
        }
-       
-       if (!probe_mad16(&cfg))
+
+       if (!request_region(MC0_PORT, 12, "mad16"))
+               return -EBUSY;
+
+       if (!probe_mad16(&cfg)) {
+               release_region(MC0_PORT, 12);
                return -ENODEV;
+       }
 
        cfg_mpu.io_base = mpu_io;
        cfg_mpu.irq = mpu_irq;
 
-       attach_mad16(&cfg);
-
        found_mpu = probe_mad16_mpu(&cfg_mpu);
 
        if (joystick == 1) {
@@ -1067,6 +1052,7 @@ static void __exit cleanup_mad16(void)
                release_region(0x201, 1);
        }
        unload_mad16(&cfg);
+       release_region(MC0_PORT, 12);
 }
 
 module_init(init_mad16);
index 43ff543..bdc5bde 100644 (file)
@@ -6,7 +6,7 @@ void unload_uart401 (struct address_info *hw_config);
 irqreturn_t uart401intr (int irq, void *dev_id, struct pt_regs * dummy);
 
 /*     From mpu401.c */
-int probe_mpu401(struct address_info *hw_config);
+int probe_mpu401(struct address_info *hw_config, struct resource *ports);
 int attach_mpu401(struct address_info * hw_config, struct module *owner);
 void unload_mpu401(struct address_info *hw_info);
 
index 73148d2..3589480 100644 (file)
 #define DSPTOPC_BASED(w)       (((w) - DSP_BASE_ADDR) * 2)
 
 #ifdef SLOWIO
-#  undef outb
-#  undef inb
-#  define outb                 outb_p
-#  define inb                  inb_p
+#define msnd_outb                      outb_p
+#define msnd_inb                       inb_p
+#else
+#define msnd_outb                      outb
+#define msnd_inb                       inb
 #endif
 
 /* JobQueueStruct */
index eb345b6..7ebc5d3 100644 (file)
@@ -136,9 +136,9 @@ static void reset_record_queue(void)
 
        /* Critical section: bank 1 access */
        spin_lock_irqsave(&dev.lock, flags);
-       outb(HPBLKSEL_1, dev.io + HP_BLKS);
+       msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS);
        isa_memset_io(dev.base, 0, DAR_BUFF_SIZE * 3);
-       outb(HPBLKSEL_0, dev.io + HP_BLKS);
+       msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
        spin_unlock_irqrestore(&dev.lock, flags);
 
        for (n = 0, lpDAQ = dev.base + DARQ_DATA_BUFF; n < 3; ++n, lpDAQ += DAQDS__size) {
@@ -830,12 +830,12 @@ static __inline__ int pack_DARQ_to_DARF(register int bank)
 
        /* Read data from the head (unprotected bank 1 access okay
            since this is only called inside an interrupt) */
-       outb(HPBLKSEL_1, dev.io + HP_BLKS);
+       msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS);
        msnd_fifo_write(
                &dev.DARF,
                (char *)(dev.base + bank * DAR_BUFF_SIZE),
                size);
-       outb(HPBLKSEL_0, dev.io + HP_BLKS);
+       msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 
        return 1;
 }
@@ -1091,7 +1091,7 @@ static __inline__ void eval_dsp_msg(register WORD wMessage)
 static irqreturn_t intr(int irq, void *dev_id, struct pt_regs *regs)
 {
        /* Send ack to DSP */
-       inb(dev.io + HP_RXL);
+       msnd_inb(dev.io + HP_RXL);
 
        /* Evaluate queued DSP messages */
        while (isa_readw(dev.DSPQ + JQS_wTail) != isa_readw(dev.DSPQ + JQS_wHead)) {
@@ -1120,15 +1120,15 @@ static int reset_dsp(void)
 {
        int timeout = 100;
 
-       outb(HPDSPRESET_ON, dev.io + HP_DSPR);
+       msnd_outb(HPDSPRESET_ON, dev.io + HP_DSPR);
        mdelay(1);
 #ifndef MSND_CLASSIC
-       dev.info = inb(dev.io + HP_INFO);
+       dev.info = msnd_inb(dev.io + HP_INFO);
 #endif
-       outb(HPDSPRESET_OFF, dev.io + HP_DSPR);
+       msnd_outb(HPDSPRESET_OFF, dev.io + HP_DSPR);
        mdelay(1);
        while (timeout-- > 0) {
-               if (inb(dev.io + HP_CVR) == HP_CVR_DEF)
+               if (msnd_inb(dev.io + HP_CVR) == HP_CVR_DEF)
                        return 0;
                mdelay(1);
        }
@@ -1202,9 +1202,9 @@ static int init_sma(void)
        unsigned long flags;
 
 #ifdef MSND_CLASSIC
-       outb(dev.memid, dev.io + HP_MEMM);
+       msnd_outb(dev.memid, dev.io + HP_MEMM);
 #endif
-       outb(HPBLKSEL_0, dev.io + HP_BLKS);
+       msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
        if (initted) {
                mastVolLeft = isa_readw(dev.SMA + SMA_wCurrMastVolLeft);
                mastVolRight = isa_readw(dev.SMA + SMA_wCurrMastVolRight);
@@ -1214,9 +1214,9 @@ static int init_sma(void)
 
        /* Critical section: bank 1 access */
        spin_lock_irqsave(&dev.lock, flags);
-       outb(HPBLKSEL_1, dev.io + HP_BLKS);
+       msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS);
        isa_memset_io(dev.base, 0, 0x8000);
-       outb(HPBLKSEL_0, dev.io + HP_BLKS);
+       msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
        spin_unlock_irqrestore(&dev.lock, flags);
 
        dev.pwDSPQData = (dev.base + DSPQ_DATA_BUFF);
@@ -1289,7 +1289,7 @@ static int __init calibrate_adc(WORD srate)
 
 static int upload_dsp_code(void)
 {
-       outb(HPBLKSEL_0, dev.io + HP_BLKS);
+       msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 #ifndef HAVE_DSPCODEH
        INITCODESIZE = mod_firmware_load(INITCODEFILE, &INITCODE);
        if (!INITCODE) {
@@ -1326,9 +1326,9 @@ static int upload_dsp_code(void)
 #ifdef MSND_CLASSIC
 static void reset_proteus(void)
 {
-       outb(HPPRORESET_ON, dev.io + HP_PROR);
+       msnd_outb(HPPRORESET_ON, dev.io + HP_PROR);
        mdelay(TIME_PRO_RESET);
-       outb(HPPRORESET_OFF, dev.io + HP_PROR);
+       msnd_outb(HPPRORESET_OFF, dev.io + HP_PROR);
        mdelay(TIME_PRO_RESET_DONE);
 }
 #endif
@@ -1338,8 +1338,8 @@ static int initialize(void)
        int err, timeout;
 
 #ifdef MSND_CLASSIC
-       outb(HPWAITSTATE_0, dev.io + HP_WAIT);
-       outb(HPBITMODE_16, dev.io + HP_BITM);
+       msnd_outb(HPWAITSTATE_0, dev.io + HP_WAIT);
+       msnd_outb(HPBITMODE_16, dev.io + HP_BITM);
 
        reset_proteus();
 #endif
@@ -1455,9 +1455,9 @@ static void __exit unload_multisound(void)
 
 static int __init msnd_write_cfg(int cfg, int reg, int value)
 {
-       outb(reg, cfg);
-       outb(value, cfg + 1);
-       if (value != inb(cfg + 1)) {
+       msnd_outb(reg, cfg);
+       msnd_outb(value, cfg + 1);
+       if (value != msnd_inb(cfg + 1)) {
                printk(KERN_ERR LOGNAME ": msnd_write_cfg: I/O error\n");
                return -EIO;
        }
index b40611b..0242f90 100644 (file)
@@ -82,7 +82,6 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 /* -------------------debug macros -------------------------------------- */
 /* #undef VRC5477_AC97_DEBUG */
index 079e5fc..99f4ed6 100644 (file)
 static int sb_initialized;
 #endif
 
-static int kilroy_was_here;    /* Don't detect twice */
-static int mpu_initialized;
 static spinlock_t lock=SPIN_LOCK_UNLOCKED;
-static int *opl3sa_osp;
 
 static unsigned char opl3sa_read(int addr)
 {
@@ -106,26 +103,16 @@ static int __init opl3sa_detect(void)
  *     OPL3-SA
  */
 
-static int __init probe_opl3sa_wss(struct address_info *hw_config)
+static int __init probe_opl3sa_wss(struct address_info *hw_config, struct resource *ports)
 {
-       int ret;
        unsigned char tmp = 0x24;       /* WSS enable */
 
-       if (check_region(0xf86, 2))     /* Control port is busy */
-               return 0;
        /*
         * Check if the IO port returns valid signature. The original MS Sound
         * system returns 0x04 while some cards (OPL3-SA for example)
         * return 0x00.
         */
 
-       if (check_region(hw_config->io_base, 8))
-       {
-               printk(KERN_ERR "OPL3-SA: MSS I/O port conflict (%x)\n", hw_config->io_base);
-               return 0;
-       }
-       opl3sa_osp = hw_config->osp;
-
        if (!opl3sa_detect())
        {
                printk(KERN_ERR "OSS: OPL3-SA chip not found\n");
@@ -152,21 +139,16 @@ static int __init probe_opl3sa_wss(struct address_info *hw_config)
        }
 
        opl3sa_write(0x01, tmp);        /* WSS setup register */
-       kilroy_was_here = 1;
 
-       ret = probe_ms_sound(hw_config);
-       if (ret)
-               request_region(0xf86, 2, "OPL3-SA");
-
-       return ret;
+       return probe_ms_sound(hw_config, ports);
 }
 
-static void __init attach_opl3sa_wss(struct address_info *hw_config)
+static void __init attach_opl3sa_wss(struct address_info *hw_config, struct resource *ports)
 {
        int nm = num_mixers;
 
        /* FIXME */
-       attach_ms_sound(hw_config, THIS_MODULE);
+       attach_ms_sound(hw_config, ports, THIS_MODULE);
        if (num_mixers > nm)    /* A mixer was installed */
        {
                AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
@@ -183,14 +165,6 @@ static int __init probe_opl3sa_mpu(struct address_info *hw_config)
                -1, -1, -1, -1, -1, 1, -1, 2, -1, 3, 4
        };
 
-       if (!kilroy_was_here)
-               return 0;       /* OPL3-SA has not been detected earlier */
-
-       if (mpu_initialized)
-       {
-               DDB(printk("OPL3-SA: MPU mode already initialized\n"));
-               return 0;
-       }
        if (hw_config->irq > 10)
        {
                printk(KERN_ERR "OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq);
@@ -224,7 +198,6 @@ static int __init probe_opl3sa_mpu(struct address_info *hw_config)
 
        opl3sa_write(0x03, conf);
 
-       mpu_initialized = 1;
        hw_config->name = "OPL3-SA (MPU401)";
 
        return probe_uart401(hw_config, THIS_MODULE);
@@ -281,6 +254,7 @@ MODULE_PARM(mpu_irq,"i");
 
 static int __init init_opl3sa(void)
 {
+       struct resource *ports;
        if (io == -1 || irq == -1 || dma == -1) {
                printk(KERN_ERR "opl3sa: dma, irq and io must be set.\n");
                return -EINVAL;
@@ -294,12 +268,31 @@ static int __init init_opl3sa(void)
        cfg_mpu.io_base = mpu_io;
        cfg_mpu.irq = mpu_irq;
 
-       if (probe_opl3sa_wss(&cfg) == 0)
+       ports = request_region(io + 4, 4, "ad1848");
+       if (!ports)
+               return -EBUSY;
+
+       if (!request_region(0xf86, 2, "OPL3-SA"))/* Control port is busy */ {
+               release_region(io + 4, 4);
+               return 0;
+       }
+
+       if (!request_region(io, 4, "WSS config")) {
+               release_region(0x86, 2);
+               release_region(io + 4, 4);
+               return 0;
+       }
+
+       if (probe_opl3sa_wss(&cfg, ports) == 0) {
+               release_region(0xf86, 2);
+               release_region(io, 4);
+               release_region(io + 4, 4);
                return -ENODEV;
+       }
 
        found_mpu=probe_opl3sa_mpu(&cfg_mpu);
 
-       attach_opl3sa_wss(&cfg);
+       attach_opl3sa_wss(&cfg, ports);
        return 0;
 }
 
index 3df045d..c770137 100644 (file)
@@ -54,7 +54,7 @@ TODO:
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <asm/hardirq.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
index 1ab1eb1..e33a50e 100644 (file)
@@ -520,13 +520,6 @@ int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio, struct sb_
         */
        
        DDB(printk("sb_dsp_detect(%x) entered\n", hw_config->io_base));
-       if (check_region(hw_config->io_base, 16))
-       {
-#ifdef MODULE
-               printk(KERN_INFO "sb: I/O region in use.\n");
-#endif
-               return 0;
-       }
 
        devc->lock = SPIN_LOCK_UNLOCKED;
        devc->type = hw_config->card_subtype;
@@ -668,6 +661,7 @@ int sb_dsp_init(struct address_info *hw_config, struct module *owner)
        if (devc->base != hw_config->io_base)
        {
                DDB(printk("I/O port mismatch\n"));
+               release_region(devc->base, 16);
                return 0;
        }
        /*
@@ -689,6 +683,7 @@ int sb_dsp_init(struct address_info *hw_config, struct module *owner)
                if (request_irq(hw_config->irq, sbintr, i, "soundblaster", devc) < 0)
                {
                        printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq);
+                       release_region(devc->base, 16);
                        return 0;
                }
                devc->irq_ok = 0;
@@ -697,6 +692,7 @@ int sb_dsp_init(struct address_info *hw_config, struct module *owner)
                        if (!sb16_set_irq_hw(devc, devc->irq))  /* Unsupported IRQ */
                        {
                                free_irq(devc->irq, devc);
+                               release_region(devc->base, 16);
                                return 0;
                        }
                if ((devc->type == 0 || devc->type == MDL_ESS) &&
@@ -735,7 +731,6 @@ int sb_dsp_init(struct address_info *hw_config, struct module *owner)
                        }
                }
        }                       /* IRQ setup */
-       request_region(hw_config->io_base, 16, "soundblaster");
 
        last_sb = devc;
        
@@ -1224,17 +1219,22 @@ int probe_sbmpu(struct address_info *hw_config, struct module *owner)
 #if defined(CONFIG_SOUND_MPU401)
        if (devc->model == MDL_ESS)
        {
-               if (check_region(hw_config->io_base, 2))
-               {
+               struct resource *ports;
+               ports = request_region(hw_config->io_base, 2, "mpu401");
+               if (!ports) {
                        printk(KERN_ERR "sbmpu: I/O port conflict (%x)\n", hw_config->io_base);
                        return 0;
                }
-               if (!ess_midi_init(devc, hw_config))
+               if (!ess_midi_init(devc, hw_config)) {
+                       release_region(hw_config->io_base, 2);
                        return 0;
+               }
                hw_config->name = "ESS1xxx MPU";
                devc->midi_irq_cookie = NULL;
-               if (!probe_mpu401(hw_config))
+               if (!probe_mpu401(hw_config, ports)) {
+                       release_region(hw_config->io_base, 2);
                        return 0;
+               }
                attach_mpu401(hw_config, owner);
                if (last_sb->irq == -hw_config->irq)
                        last_sb->midi_irq_cookie=(void *)hw_config->slots[1];
index 1e31097..16cc9ab 100644 (file)
@@ -86,19 +86,31 @@ static int __init sb_cmd( int base, unsigned char val )
 
 static int __init probe_sgalaxy( struct address_info *ai )
 {
-       if ( check_region( ai->io_base, 8 ) ) {
+       struct resource *ports;
+       int n;
+
+       if (!request_region(ai->io_base, 4, "WSS config")) {
                printk(KERN_ERR "sgalaxy: WSS IO port 0x%03x not available\n", ai->io_base);
                return 0;
        }
-        
-       if ( ad1848_detect( ai->io_base+4, NULL, ai->osp ) )
-               return probe_ms_sound(ai);  /* The card is already active, check irq etc... */
 
-       if ( check_region( ai->ai_sgbase, 0x10 ) ) {
+       ports = request_region(ai->io_base + 4, 4, "ad1848");
+       if (!ports) {
+               printk(KERN_ERR "sgalaxy: WSS IO port 0x%03x not available\n", ai->io_base);
+               release_region(ai->io_base, 4);
+               return 0;
+       }
+
+       if (!request_region( ai->ai_sgbase, 0x10, "SoundGalaxy SB")) {
                printk(KERN_ERR "sgalaxy: SB IO port 0x%03x not available\n", ai->ai_sgbase);
+               release_region(ai->io_base + 4, 4);
+               release_region(ai->io_base, 4);
                return 0;
        }
         
+       if (ad1848_detect(ports, NULL, ai->osp))
+               goto out;  /* The card is already active, check irq etc... */
+        
        /* switch to MSS/WSS mode */
    
        sb_rst( ai->ai_sgbase );
@@ -108,16 +120,15 @@ static int __init probe_sgalaxy( struct address_info *ai )
 
        sleep( HZ/10 );
 
-       return probe_ms_sound(ai);
-}
+out:
+       if (!probe_ms_sound(ai, ports)) {
+               release_region(ai->io_base + 4, 4);
+               release_region(ai->io_base, 4);
+               release_region(ai->ai_sgbase, 0x10);
+               return 0;
+       }
 
-static void __init attach_sgalaxy( struct address_info *ai )
-{
-       int n;
-       
-       request_region( ai->ai_sgbase, 0x10, "SoundGalaxy SB" );
-       attach_ms_sound(ai, THIS_MODULE);
+       attach_ms_sound(ai, ports, THIS_MODULE);
        n=ai->slots[0];
        
        if (n!=-1 && audio_devs[n]->mixer_dev != -1 ) {
@@ -125,6 +136,7 @@ static void __init attach_sgalaxy( struct address_info *ai )
                AD1848_REROUTE( SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH );  /* FM+Wavetable*/
                AD1848_REROUTE( SOUND_MIXER_LINE3, SOUND_MIXER_CD );     /* CD */
        }
+       return 1;
 }
 
 static void __exit unload_sgalaxy( struct address_info *ai )
@@ -163,8 +175,6 @@ static int __init init_sgalaxy(void)
        if ( probe_sgalaxy(&cfg) == 0 )
                return -ENODEV;
 
-       attach_sgalaxy(&cfg);
-
        return 0;
 }
 
index 4846dc2..dee5a91 100644 (file)
@@ -70,6 +70,7 @@
 #include <linux/ac97_codec.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/init.h>
@@ -77,7 +78,6 @@
 #include <linux/smp_lock.h>
 #include <linux/wrapper.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_int.h>
index 37ffed1..13c3d79 100644 (file)
 
 #include "trix_boot.h"
 
-static int kilroy_was_here;    /* Don't detect twice */
-static int sb_initialized;
-static int mpu_initialized;
-
-static int *trix_osp;
-
 static int mpu;
 
 static int joystick;
@@ -82,20 +76,11 @@ static int trix_set_wss_port(struct address_info *hw_config)
 {
        unsigned char   addr_bits;
 
-       if (check_region(0x390, 2))
-       {
-               printk(KERN_ERR "AudioTrix: Config port I/O conflict\n");
-               return 0;
-       }
-       if (kilroy_was_here)    /* Already initialized */
-               return 0;
-
        if (trix_read(0x15) != 0x71)    /* No ASIC signature */
        {
                MDB(printk(KERN_ERR "No AudioTrix ASIC signature found\n"));
                return 0;
        }
-       kilroy_was_here = 1;
 
        /*
         * Reset some registers.
@@ -135,107 +120,114 @@ static int trix_set_wss_port(struct address_info *hw_config)
  *      AudioTrix Pro
  */
 
-static int __init probe_trix_wss(struct address_info *hw_config)
+static int __init init_trix_wss(struct address_info *hw_config)
 {
+       static unsigned char dma_bits[4] = {
+               1, 2, 0, 3
+       };
+       struct resource *ports;
+       int config_port = hw_config->io_base + 0;
+       int dma1 = hw_config->dma, dma2 = hw_config->dma2;
+       int old_num_mixers = num_mixers;
+       u8 config, bits;
        int ret;
+       switch(hw_config->irq) {
+       case 7:
+               bits = 8;
+               break;
+       case 9:
+               bits = 0x10;
+               break;
+       case 10:
+               bits = 0x18;
+               break;
+       case 11:
+               bits = 0x20;
+               break;
+       default:
+               printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq);
+               return 0;
+       }
+
+       switch (dma1) {
+       case 0:
+       case 1:
+       case 3:
+               break;
+       default:
+               printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", dma1);
+               return 0;
+       }
+
+       switch (dma2) {
+       case -1:
+       case 0:
+       case 1:
+       case 3:
+               break;
+       default:
+               printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", dma2);
+               return 0;
+       }
 
        /*
         * Check if the IO port returns valid signature. The original MS Sound
         * system returns 0x04 while some cards (AudioTrix Pro for example)
         * return 0x00.
         */
-       if (check_region(hw_config->io_base, 8))
-       {
+       ports = request_region(hw_config->io_base + 4, 4, "ad1848");
+       if (!ports) {
                printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
                return 0;
        }
-       trix_osp = hw_config->osp;
 
-       if (!trix_set_wss_port(hw_config))
+       if (!request_region(hw_config->io_base, 4, "MSS config")) {
+               printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
+               release_region(hw_config->io_base + 4, 4);
                return 0;
+       }
+
+       if (!trix_set_wss_port(hw_config))
+               goto fail;
 
-       if ((inb(hw_config->io_base + 3) & 0x3f) != 0x00)
+       config = inb(hw_config->io_base + 3);
+
+       if ((config & 0x3f) != 0x00)
        {
                MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x\n", hw_config->io_base));
-               return 0;
-       }
-       if (hw_config->irq > 11)
-       {
-               printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq);
-               return 0;
-       }
-       if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
-       {
-               printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", hw_config->dma);
-               return 0;
+               goto fail;
        }
-       if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
-               if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3)
-               {
-                         printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", hw_config->dma2);
-                         return 0;
-               }
+
        /*
         * Check that DMA0 is not in use with a 8 bit board.
         */
 
-       if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
+       if (dma1 == 0 && config & 0x80)
        {
                printk(KERN_ERR "AudioTrix: Can't use DMA0 with a 8 bit card slot\n");
-               return 0;
+               goto fail;
        }
-       if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
+       if (hw_config->irq > 9 && config & 0x80)
        {
                printk(KERN_ERR "AudioTrix: Can't use IRQ%d with a 8 bit card slot\n", hw_config->irq);
-               return 0;
-       }
-       ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
-
-       if (ret)
-       {
-               if(joystick==1)
-                       trix_write(0x15, 0x80);
-               request_region(0x390, 2, "AudioTrix");
+               goto fail;
        }
-       return ret;
-}
-
-static void __init attach_trix_wss(struct address_info *hw_config)
-{
-       static unsigned char interrupt_bits[12] = {
-               0, 0, 0, 0, 0, 0, 0, 0x08, 0, 0x10, 0x18, 0x20
-       };
-       char bits;
-
-       static unsigned char dma_bits[4] = {
-               1, 2, 0, 3
-       };
 
-       int config_port = hw_config->io_base + 0;
-       int dma1 = hw_config->dma, dma2 = hw_config->dma2;
-       int old_num_mixers = num_mixers;
+       ret = ad1848_detect(ports, NULL, hw_config->osp);
+       if (!ret)
+               goto fail;
 
-       trix_osp = hw_config->osp;
+       if (joystick==1)
+               trix_write(0x15, 0x80);
 
-       if (!kilroy_was_here)
-       {
-               DDB(printk("AudioTrix: Attach called but not probed yet???\n"));
-               return;
-       }
-       
        /*
         * Set the IRQ and DMA addresses.
         */
 
-       bits = interrupt_bits[hw_config->irq];
-       if (bits == 0)
-       {
-               printk("AudioTrix: Bad IRQ (%d)\n", hw_config->irq);
-               return;
-       }
        outb((bits | 0x40), config_port);
 
-       if (hw_config->dma2 == -1 || hw_config->dma2 == hw_config->dma)
+       if (dma2 == -1 || dma2 == dma1)
        {
                  bits |= dma_bits[dma1];
                  dma2 = dma1;
@@ -253,14 +245,13 @@ static void __init attach_trix_wss(struct address_info *hw_config)
 
        outb((bits), config_port);      /* Write IRQ+DMA setup */
 
-       hw_config->slots[0] = ad1848_init("AudioTrix Pro", hw_config->io_base + 4,
+       hw_config->slots[0] = ad1848_init("AudioTrix Pro", ports,
                                          hw_config->irq,
                                          dma1,
                                          dma2,
                                          0,
                                          hw_config->osp,
                                          THIS_MODULE);
-       request_region(hw_config->io_base, 4, "MSS config");
 
        if (num_mixers > old_num_mixers)        /* Mixer got installed */
        {
@@ -269,6 +260,12 @@ static void __init attach_trix_wss(struct address_info *hw_config)
                AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);           /* OPL4 */
                AD1848_REROUTE(SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM);        /* SB */
        }
+       return 1;
+
+fail:
+       release_region(hw_config->io_base, 4);
+       release_region(hw_config->io_base + 4, 4);
+       return 0;
 }
 
 static int __init probe_trix_sb(struct address_info *hw_config)
@@ -276,6 +273,8 @@ static int __init probe_trix_sb(struct address_info *hw_config)
 
        int tmp;
        unsigned char conf;
+       extern int sb_be_quiet;
+       int old_quiet;
        static signed char irq_translate[] = {
                -1, -1, -1, 0, 1, 2, -1, 3
        };
@@ -283,17 +282,6 @@ static int __init probe_trix_sb(struct address_info *hw_config)
        if (trix_boot_len == 0)
                return 0;       /* No boot code -> no fun */
 
-       if (!kilroy_was_here)
-               return 0;       /* AudioTrix Pro has not been detected earlier */
-
-       if (sb_initialized)
-               return 0;
-
-       if (check_region(hw_config->io_base, 16))
-       {
-               printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base);
-               return 0;
-       }
        if ((hw_config->io_base & 0xffffff8f) != 0x200)
                return 0;
 
@@ -307,6 +295,11 @@ static int __init probe_trix_sb(struct address_info *hw_config)
        if (tmp != 1 && tmp != 3)
                return 0;
 
+       if (!request_region(hw_config->io_base, 16, "soundblaster")) {
+               printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base);
+               return 0;
+       }
+
        conf = 0x84;            /* DMA and IRQ enable */
        conf |= hw_config->io_base & 0x70;      /* I/O address bits */
        conf |= irq_translate[hw_config->irq];
@@ -315,16 +308,12 @@ static int __init probe_trix_sb(struct address_info *hw_config)
        trix_write(0x1b, conf);
 
        download_boot(hw_config->io_base);
-       sb_initialized = 1;
 
        hw_config->name = "AudioTrix SB";
-       return sb_dsp_detect(hw_config, 0, 0, NULL);
-}
-
-static void __init attach_trix_sb(struct address_info *hw_config)
-{
-       extern int sb_be_quiet;
-       int old_quiet;
+       if (!sb_dsp_detect(hw_config, 0, 0, NULL)) {
+               release_region(hw_config->io_base, 16);
+               return 0;
+       }
 
        hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING;
 
@@ -335,6 +324,7 @@ static void __init attach_trix_sb(struct address_info *hw_config)
        sb_dsp_init(hw_config, THIS_MODULE);
 
        sb_be_quiet = old_quiet;
+       return 1;
 }
 
 static int __init probe_trix_mpu(struct address_info *hw_config)
@@ -344,21 +334,6 @@ static int __init probe_trix_mpu(struct address_info *hw_config)
                -1, -1, -1, 1, 2, 3, -1, 4, -1, 5
        };
 
-       if (!kilroy_was_here)
-       {
-               DDB(printk("Trix: WSS and SB modes must be initialized before MPU\n"));
-               return 0;       /* AudioTrix Pro has not been detected earlier */
-       }
-       if (!sb_initialized)
-       {
-               DDB(printk("Trix: SB mode must be initialized before MPU\n"));
-               return 0;
-       }
-       if (mpu_initialized)
-       {
-               DDB(printk("Trix: MPU mode already initialized\n"));
-               return 0;
-       }
        if (hw_config->irq > 9)
        {
                printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
@@ -389,7 +364,6 @@ static int __init probe_trix_mpu(struct address_info *hw_config)
 
        conf |= irq_bits[hw_config->irq] << 4;
        trix_write(0x19, (trix_read(0x19) & 0x83) | conf);
-       mpu_initialized = 1;
        hw_config->name = "AudioTrix Pro";
        return probe_uart401(hw_config, THIS_MODULE);
 }
@@ -485,9 +459,16 @@ static int __init init_trix(void)
                trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin",
                                                    (char **) &trix_boot);
        }
-       if (!probe_trix_wss(&cfg))
+
+       if (!request_region(0x390, 2, "AudioTrix")) {
+               printk(KERN_ERR "AudioTrix: Config port I/O conflict\n");
+               return -ENODEV;
+       }
+
+       if (!init_trix_wss(&cfg)) {
+               release_region(0x390, 2);
                return -ENODEV;
-       attach_trix_wss(&cfg);
+       }
 
        /*
         *    We must attach in the right order to get the firmware
@@ -496,8 +477,6 @@ static int __init init_trix(void)
 
        if (cfg2.io_base != -1) {
                sb = probe_trix_sb(&cfg2);
-               if (sb)
-                       attach_trix_sb(&cfg2);
        }
        
        if (cfg_mpu.io_base != -1)
index cfef277..f588cd6 100644 (file)
@@ -5,6 +5,7 @@
 
 snd-als4000-objs := als4000.o
 snd-atiixp-objs := atiixp.o
+snd-atiixp-modem-objs := atiixp_modem.o
 snd-azt3328-objs := azt3328.o
 snd-bt87x-objs := bt87x.o
 snd-cmipci-objs := cmipci.o
@@ -25,6 +26,7 @@ snd-via82xx-objs := via82xx.o
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_ALS4000) += snd-als4000.o
 obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o
+obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o
 obj-$(CONFIG_SND_AZT3328) += snd-azt3328.o
 obj-$(CONFIG_SND_BT87X) += snd-bt87x.o
 obj-$(CONFIG_SND_CMIPCI) += snd-cmipci.o
index fa75c06..24a9f6c 100644 (file)
 #define AC97_ID_CS4201         0x43525948
 #define AC97_ID_CS4205         0x43525958
 #define AC97_ID_CS_MASK                0xfffffff8      /* bit 0-2: rev */
+#define AC97_ID_ALC100         0x414c4300
 #define AC97_ID_ALC650         0x414c4720
+#define AC97_ID_ALC650D                0x414c4721
+#define AC97_ID_ALC650E                0x414c4722
+#define AC97_ID_ALC650F                0x414c4723
+#define AC97_ID_ALC655         0x414c4760
+#define AC97_ID_ALC658         0x414c4780
+#define AC97_ID_ALC850         0x414c4790
 #define AC97_ID_YMF753         0x594d4803
 #define AC97_ID_VT1616         0x49434551
 #define AC97_ID_CM9738         0x434d4941
index 3e78799..a619d72 100644 (file)
@@ -49,6 +49,7 @@ int patch_ad1981b(ac97_t * ac97);
 int patch_ad1985(ac97_t * ac97);
 int patch_alc650(ac97_t * ac97);
 int patch_alc655(ac97_t * ac97);
+int patch_alc850(ac97_t * ac97);
 int patch_cm9738(ac97_t * ac97);
 int patch_cm9739(ac97_t * ac97);
 int patch_vt1616(ac97_t * ac97);
index b0c6214..d33cd42 100644 (file)
@@ -30,8 +30,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Universal routines for AK4531 codec");
 MODULE_LICENSE("GPL");
 
-#define chip_t ak4531_t
-
 static void snd_ak4531_proc_init(snd_card_t * card, ak4531_t * ak4531);
 
 /*
@@ -89,7 +87,7 @@ static int snd_ak4531_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
        }
        ucontrol->value.integer.value[0] = val;
        return 0;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 static int snd_ak4531_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -113,7 +111,7 @@ static int snd_ak4531_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
        ak4531->write(ak4531, reg, ak4531->regs[reg] = val);
        spin_unlock_irqrestore(&ak4531->reg_lock, flags);
        return change;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 #define AK4531_DOUBLE(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -155,7 +153,7 @@ static int snd_ak4531_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
        ucontrol->value.integer.value[0] = left;
        ucontrol->value.integer.value[1] = right;
        return 0;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -192,7 +190,7 @@ static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
        }
        spin_unlock_irqrestore(&ak4531->reg_lock, flags);
        return change;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 #define AK4531_INPUT_SW(xname, xindex, reg1, reg2, left_shift, right_shift) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -225,7 +223,7 @@ static int snd_ak4531_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
        ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1;
        spin_unlock_irqrestore(&ak4531->reg_lock, flags);
        return 0;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -250,9 +248,7 @@ static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
        ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2);
        spin_unlock_irqrestore(&ak4531->reg_lock, flags);
        return change;
-}                                                                                                                                                                                                                                                                                                            
-
-#define AK4531_CONTROLS (sizeof(snd_ak4531_controls)/sizeof(snd_kcontrol_new_t))
+}
 
 static snd_kcontrol_new_t snd_ak4531_controls[] = {
 
@@ -315,14 +311,14 @@ static int snd_ak4531_free(ak4531_t *ak4531)
        if (ak4531) {
                if (ak4531->private_free)
                        ak4531->private_free(ak4531);
-               snd_magic_kfree(ak4531);
+               kfree(ak4531);
        }
        return 0;
 }
 
 static int snd_ak4531_dev_free(snd_device_t *device)
 {
-       ak4531_t *ak4531 = snd_magic_cast(ak4531_t, device->device_data, return -ENXIO);
+       ak4531_t *ak4531 = device->device_data;
        return snd_ak4531_free(ak4531);
 }
 
@@ -367,7 +363,7 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
        snd_assert(rak4531 != NULL, return -EINVAL);
        *rak4531 = NULL;
        snd_assert(card != NULL && _ak4531 != NULL, return -EINVAL);
-       ak4531 = snd_magic_kcalloc(ak4531_t, 0, GFP_KERNEL);
+       ak4531 = kcalloc(1, sizeof(*ak4531), GFP_KERNEL);
        if (ak4531 == NULL)
                return -ENOMEM;
        *ak4531 = *_ak4531;
@@ -385,7 +381,7 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
                        continue;
                ak4531->write(ak4531, idx, ak4531->regs[idx] = snd_ak4531_initial_map[idx]);    /* recording source is mixer */
        }
-       for (idx = 0; idx < AK4531_CONTROLS; idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(snd_ak4531_controls); idx++) {
                if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ak4531_controls[idx], ak4531))) < 0) {
                        snd_ak4531_free(ak4531);
                        return err;
@@ -411,7 +407,7 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
 static void snd_ak4531_proc_read(snd_info_entry_t *entry, 
                                 snd_info_buffer_t * buffer)
 {
-       ak4531_t *ak4531 = snd_magic_cast(ak4531_t, entry->private_data, return);
+       ak4531_t *ak4531 = entry->private_data;
 
        snd_iprintf(buffer, "Asahi Kasei AK4531\n\n");
        snd_iprintf(buffer, "Recording source   : %s\n"
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
new file mode 100644 (file)
index 0000000..bec2052
--- /dev/null
@@ -0,0 +1,1351 @@
+/*
+ *   ALSA driver for ATI IXP 150/200/250 AC97 modem controllers
+ *
+ *     Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute 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 <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+
+MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
+MODULE_DESCRIPTION("ATI IXP MC97 controller");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{ATI,IXP150/200/250}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;     /* Enable this card */
+static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000};
+static int boot_devs;
+
+module_param_array(index, int, boot_devs, 0444);
+MODULE_PARM_DESC(index, "Index value for ATI IXP controller.");
+module_param_array(id, charp, boot_devs, 0444);
+MODULE_PARM_DESC(id, "ID string for ATI IXP controller.");
+module_param_array(enable, bool, boot_devs, 0444);
+MODULE_PARM_DESC(enable, "Enable audio part of ATI IXP controller.");
+module_param_array(ac97_clock, int, boot_devs, 0444);
+MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
+
+
+/*
+ */
+
+#define ATI_REG_ISR                    0x00    /* interrupt source */
+#define  ATI_REG_ISR_MODEM_IN_XRUN     (1U<<0)
+#define  ATI_REG_ISR_MODEM_IN_STATUS   (1U<<1)
+#define  ATI_REG_ISR_MODEM_OUT1_XRUN   (1U<<2)
+#define  ATI_REG_ISR_MODEM_OUT1_STATUS (1U<<3)
+#define  ATI_REG_ISR_MODEM_OUT2_XRUN   (1U<<4)
+#define  ATI_REG_ISR_MODEM_OUT2_STATUS (1U<<5)
+#define  ATI_REG_ISR_MODEM_OUT3_XRUN   (1U<<6)
+#define  ATI_REG_ISR_MODEM_OUT3_STATUS (1U<<7)
+#define  ATI_REG_ISR_PHYS_INTR         (1U<<8)
+#define  ATI_REG_ISR_PHYS_MISMATCH     (1U<<9)
+#define  ATI_REG_ISR_CODEC0_NOT_READY  (1U<<10)
+#define  ATI_REG_ISR_CODEC1_NOT_READY  (1U<<11)
+#define  ATI_REG_ISR_CODEC2_NOT_READY  (1U<<12)
+#define  ATI_REG_ISR_NEW_FRAME         (1U<<13)
+#define  ATI_REG_ISR_MODEM_GPIO_DATA   (1U<<14)
+
+#define ATI_REG_IER                    0x04    /* interrupt enable */
+#define  ATI_REG_IER_MODEM_IN_XRUN_EN  (1U<<0)
+#define  ATI_REG_IER_MODEM_STATUS_EN   (1U<<1)
+#define  ATI_REG_IER_MODEM_OUT1_XRUN_EN        (1U<<2)
+#define  ATI_REG_IER_MODEM_OUT2_XRUN_EN        (1U<<4)
+#define  ATI_REG_IER_MODEM_OUT3_XRUN_EN        (1U<<6)
+#define  ATI_REG_IER_PHYS_INTR_EN      (1U<<8)
+#define  ATI_REG_IER_PHYS_MISMATCH_EN  (1U<<9)
+#define  ATI_REG_IER_CODEC0_INTR_EN    (1U<<10)
+#define  ATI_REG_IER_CODEC1_INTR_EN    (1U<<11)
+#define  ATI_REG_IER_CODEC2_INTR_EN    (1U<<12)
+#define  ATI_REG_IER_NEW_FRAME_EN      (1U<<13)        /* (RO */
+#define  ATI_REG_IER_MODEM_GPIO_DATA_EN        (1U<<14)        /* (WO) modem is running */
+#define  ATI_REG_IER_MODEM_SET_BUS_BUSY        (1U<<15)
+
+#define ATI_REG_CMD                    0x08    /* command */
+#define  ATI_REG_CMD_POWERDOWN (1U<<0)
+#define  ATI_REG_CMD_MODEM_RECEIVE_EN  (1U<<1) /* modem only */
+#define  ATI_REG_CMD_MODEM_SEND1_EN    (1U<<2) /* modem only */
+#define  ATI_REG_CMD_MODEM_SEND2_EN    (1U<<3) /* modem only */
+#define  ATI_REG_CMD_MODEM_SEND3_EN    (1U<<4) /* modem only */
+#define  ATI_REG_CMD_MODEM_STATUS_MEM  (1U<<5) /* modem only */
+#define  ATI_REG_CMD_MODEM_IN_DMA_EN   (1U<<8) /* modem only */
+#define  ATI_REG_CMD_MODEM_OUT_DMA1_EN (1U<<9) /* modem only */
+#define  ATI_REG_CMD_MODEM_OUT_DMA2_EN (1U<<10)        /* modem only */
+#define  ATI_REG_CMD_MODEM_OUT_DMA3_EN (1U<<11)        /* modem only */
+#define  ATI_REG_CMD_AUDIO_PRESENT     (1U<<20)
+#define  ATI_REG_CMD_MODEM_GPIO_THRU_DMA       (1U<<22)        /* modem only */
+#define  ATI_REG_CMD_LOOPBACK_EN       (1U<<23)
+#define  ATI_REG_CMD_PACKED_DIS                (1U<<24)
+#define  ATI_REG_CMD_BURST_EN          (1U<<25)
+#define  ATI_REG_CMD_PANIC_EN          (1U<<26)
+#define  ATI_REG_CMD_MODEM_PRESENT     (1U<<27)
+#define  ATI_REG_CMD_ACLINK_ACTIVE     (1U<<28)
+#define  ATI_REG_CMD_AC_SOFT_RESET     (1U<<29)
+#define  ATI_REG_CMD_AC_SYNC           (1U<<30)
+#define  ATI_REG_CMD_AC_RESET          (1U<<31)
+
+#define ATI_REG_PHYS_OUT_ADDR          0x0c
+#define  ATI_REG_PHYS_OUT_CODEC_MASK   (3U<<0)
+#define  ATI_REG_PHYS_OUT_RW           (1U<<2)
+#define  ATI_REG_PHYS_OUT_ADDR_EN      (1U<<8)
+#define  ATI_REG_PHYS_OUT_ADDR_SHIFT   9
+#define  ATI_REG_PHYS_OUT_DATA_SHIFT   16
+
+#define ATI_REG_PHYS_IN_ADDR           0x10
+#define  ATI_REG_PHYS_IN_READ_FLAG     (1U<<8)
+#define  ATI_REG_PHYS_IN_ADDR_SHIFT    9
+#define  ATI_REG_PHYS_IN_DATA_SHIFT    16
+
+#define ATI_REG_SLOTREQ                        0x14
+
+#define ATI_REG_COUNTER                        0x18
+#define  ATI_REG_COUNTER_SLOT          (3U<<0) /* slot # */
+#define  ATI_REG_COUNTER_BITCLOCK      (31U<<8)
+
+#define ATI_REG_IN_FIFO_THRESHOLD      0x1c
+
+#define ATI_REG_MODEM_IN_DMA_LINKPTR   0x20
+#define ATI_REG_MODEM_IN_DMA_DT_START  0x24    /* RO */
+#define ATI_REG_MODEM_IN_DMA_DT_NEXT   0x28    /* RO */
+#define ATI_REG_MODEM_IN_DMA_DT_CUR    0x2c    /* RO */
+#define ATI_REG_MODEM_IN_DMA_DT_SIZE   0x30
+#define ATI_REG_MODEM_OUT_FIFO         0x34    /* output threshold */
+#define  ATI_REG_MODEM_OUT1_DMA_THRESHOLD_MASK (0xf<<16)
+#define  ATI_REG_MODEM_OUT1_DMA_THRESHOLD_SHIFT        16
+#define ATI_REG_MODEM_OUT_DMA1_LINKPTR 0x38
+#define ATI_REG_MODEM_OUT_DMA2_LINKPTR 0x3c
+#define ATI_REG_MODEM_OUT_DMA3_LINKPTR 0x40
+#define ATI_REG_MODEM_OUT_DMA1_DT_START        0x44
+#define ATI_REG_MODEM_OUT_DMA1_DT_NEXT 0x48
+#define ATI_REG_MODEM_OUT_DMA1_DT_CUR  0x4c
+#define ATI_REG_MODEM_OUT_DMA2_DT_START        0x50
+#define ATI_REG_MODEM_OUT_DMA2_DT_NEXT 0x54
+#define ATI_REG_MODEM_OUT_DMA2_DT_CUR  0x58
+#define ATI_REG_MODEM_OUT_DMA3_DT_START        0x5c
+#define ATI_REG_MODEM_OUT_DMA3_DT_NEXT 0x60
+#define ATI_REG_MODEM_OUT_DMA3_DT_CUR  0x64
+#define ATI_REG_MODEM_OUT_DMA12_DT_SIZE        0x68
+#define ATI_REG_MODEM_OUT_DMA3_DT_SIZE 0x6c
+#define ATI_REG_MODEM_OUT_FIFO_USED     0x70
+#define ATI_REG_MODEM_OUT_GPIO         0x74
+#define  ATI_REG_MODEM_OUT_GPIO_EN        1
+#define  ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT 5
+#define ATI_REG_MODEM_IN_GPIO          0x78
+
+#define ATI_REG_MODEM_MIRROR           0x7c
+#define ATI_REG_AUDIO_MIRROR           0x80
+
+#define ATI_REG_MODEM_FIFO_FLUSH       0x88
+#define  ATI_REG_MODEM_FIFO_OUT1_FLUSH (1U<<0)
+#define  ATI_REG_MODEM_FIFO_OUT2_FLUSH (1U<<1)
+#define  ATI_REG_MODEM_FIFO_OUT3_FLUSH (1U<<2)
+#define  ATI_REG_MODEM_FIFO_IN_FLUSH   (1U<<3)
+
+/* LINKPTR */
+#define  ATI_REG_LINKPTR_EN            (1U<<0)
+
+#define ATI_MAX_DESCRIPTORS    256     /* max number of descriptor packets */
+
+
+/*
+ */
+
+typedef struct snd_atiixp atiixp_t;
+typedef struct snd_atiixp_dma atiixp_dma_t;
+typedef struct snd_atiixp_dma_ops atiixp_dma_ops_t;
+
+
+/*
+ * DMA packate descriptor
+ */
+
+typedef struct atiixp_dma_desc {
+       u32 addr;       /* DMA buffer address */
+       u16 status;     /* status bits */
+       u16 size;       /* size of the packet in dwords */
+       u32 next;       /* address of the next packet descriptor */
+} atiixp_dma_desc_t;
+
+/*
+ * stream enum
+ */
+enum { ATI_DMA_PLAYBACK, ATI_DMA_CAPTURE, NUM_ATI_DMAS }; /* DMAs */
+enum { ATI_PCM_OUT, ATI_PCM_IN, NUM_ATI_PCMS }; /* AC97 pcm slots */
+enum { ATI_PCMDEV_ANALOG, NUM_ATI_PCMDEVS }; /* pcm devices */
+
+#define NUM_ATI_CODECS 3
+
+
+/*
+ * constants and callbacks for each DMA type
+ */
+struct snd_atiixp_dma_ops {
+       int type;                       /* ATI_DMA_XXX */
+       unsigned int llp_offset;        /* LINKPTR offset */
+       unsigned int dt_cur;            /* DT_CUR offset */
+       void (*enable_dma)(atiixp_t *chip, int on);     /* called from open callback */
+       void (*enable_transfer)(atiixp_t *chip, int on); /* called from trigger (START/STOP) */
+       void (*flush_dma)(atiixp_t *chip);              /* called from trigger (STOP only) */
+};
+
+/*
+ * DMA stream
+ */
+struct snd_atiixp_dma {
+       const atiixp_dma_ops_t *ops;
+       struct snd_dma_buffer desc_buf;
+       snd_pcm_substream_t *substream; /* assigned PCM substream */
+       unsigned int buf_addr, buf_bytes;       /* DMA buffer address, bytes */
+       unsigned int period_bytes, periods;
+       int opened;
+       int running;
+       int pcm_open_flag;
+       int ac97_pcm_type;      /* index # of ac97_pcm to access, -1 = not used */
+};
+
+/*
+ * ATI IXP chip
+ */
+struct snd_atiixp {
+       snd_card_t *card;
+       struct pci_dev *pci;
+
+       struct resource *res;           /* memory i/o */
+       unsigned long addr;
+       void __iomem *remap_addr;
+       int irq;
+       
+       ac97_bus_t *ac97_bus;
+       ac97_t *ac97[NUM_ATI_CODECS];
+
+       spinlock_t reg_lock;
+       spinlock_t ac97_lock;
+
+       atiixp_dma_t dmas[NUM_ATI_DMAS];
+       struct ac97_pcm *pcms[NUM_ATI_PCMS];
+       snd_pcm_t *pcmdevs[NUM_ATI_PCMDEVS];
+
+       int max_channels;               /* max. channels for PCM out */
+
+       unsigned int codec_not_ready_bits;      /* for codec detection */
+
+       int spdif_over_aclink;          /* passed from the module option */
+       struct semaphore open_mutex;    /* playback open mutex */
+};
+
+
+/*
+ */
+static struct pci_device_id snd_atiixp_ids[] = {
+       { 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
+
+
+/*
+ * lowlevel functions
+ */
+
+/*
+ * update the bits of the given register.
+ * return 1 if the bits changed.
+ */
+static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
+                                unsigned int mask, unsigned int value)
+{
+       void __iomem *addr = chip->remap_addr + reg;
+       unsigned int data, old_data;
+       old_data = data = readl(addr);
+       data &= ~mask;
+       data |= value;
+       if (old_data == data)
+               return 0;
+       writel(data, addr);
+       return 1;
+}
+
+/*
+ * macros for easy use
+ */
+#define atiixp_write(chip,reg,value) \
+       writel(value, chip->remap_addr + ATI_REG_##reg)
+#define atiixp_read(chip,reg) \
+       readl(chip->remap_addr + ATI_REG_##reg)
+#define atiixp_update(chip,reg,mask,val) \
+       snd_atiixp_update_bits(chip, ATI_REG_##reg, mask, val)
+
+/* delay for one tick */
+#define do_delay() do { \
+       set_current_state(TASK_UNINTERRUPTIBLE); \
+       schedule_timeout(1); \
+} while (0)
+
+
+/*
+ * handling DMA packets
+ *
+ * we allocate a linear buffer for the DMA, and split it to  each packet.
+ * in a future version, a scatter-gather buffer should be implemented.
+ */
+
+#define ATI_DESC_LIST_SIZE \
+       PAGE_ALIGN(ATI_MAX_DESCRIPTORS * sizeof(atiixp_dma_desc_t))
+
+/*
+ * build packets ring for the given buffer size.
+ *
+ * IXP handles the buffer descriptors, which are connected as a linked
+ * list.  although we can change the list dynamically, in this version,
+ * a static RING of buffer descriptors is used.
+ *
+ * the ring is built in this function, and is set up to the hardware. 
+ */
+static int atiixp_build_dma_packets(atiixp_t *chip, atiixp_dma_t *dma,
+                                  snd_pcm_substream_t *substream,
+                                  unsigned int periods,
+                                  unsigned int period_bytes)
+{
+       unsigned int i;
+       u32 addr, desc_addr;
+       unsigned long flags;
+
+       if (periods > ATI_MAX_DESCRIPTORS)
+               return -ENOMEM;
+
+       if (dma->desc_buf.area == NULL) {
+               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+                                       ATI_DESC_LIST_SIZE, &dma->desc_buf) < 0)
+                       return -ENOMEM;
+               dma->period_bytes = dma->periods = 0; /* clear */
+       }
+
+       if (dma->periods == periods && dma->period_bytes == period_bytes)
+               return 0;
+
+       /* reset DMA before changing the descriptor table */
+       spin_lock_irqsave(&chip->reg_lock, flags);
+       writel(0, chip->remap_addr + dma->ops->llp_offset);
+       dma->ops->enable_dma(chip, 0);
+       dma->ops->enable_dma(chip, 1);
+       spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+       /* fill the entries */
+       addr = (u32)substream->runtime->dma_addr;
+       desc_addr = (u32)dma->desc_buf.addr;
+       for (i = 0; i < periods; i++) {
+               atiixp_dma_desc_t *desc = &((atiixp_dma_desc_t *)dma->desc_buf.area)[i];
+               desc->addr = cpu_to_le32(addr);
+               desc->status = 0;
+               desc->size = period_bytes >> 2; /* in dwords */
+               desc_addr += sizeof(atiixp_dma_desc_t);
+               if (i == periods - 1)
+                       desc->next = cpu_to_le32((u32)dma->desc_buf.addr);
+               else
+                       desc->next = cpu_to_le32(desc_addr);
+               addr += period_bytes;
+       }
+
+       writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN,
+              chip->remap_addr + dma->ops->llp_offset);
+
+       dma->period_bytes = period_bytes;
+       dma->periods = periods;
+
+       return 0;
+}
+
+/*
+ * remove the ring buffer and release it if assigned
+ */
+static void atiixp_clear_dma_packets(atiixp_t *chip, atiixp_dma_t *dma, snd_pcm_substream_t *substream)
+{
+       if (dma->desc_buf.area) {
+               writel(0, chip->remap_addr + dma->ops->llp_offset);
+               snd_dma_free_pages(&dma->desc_buf);
+               dma->desc_buf.area = NULL;
+       }
+}
+
+/*
+ * AC97 interface
+ */
+static int snd_atiixp_acquire_codec(atiixp_t *chip)
+{
+       int timeout = 1000;
+
+       while (atiixp_read(chip, PHYS_OUT_ADDR) & ATI_REG_PHYS_OUT_ADDR_EN) {
+               if (! timeout--) {
+                       snd_printk(KERN_WARNING "atiixp: codec acquire timeout\n");
+                       return -EBUSY;
+               }
+               udelay(1);
+       }
+       return 0;
+}
+
+static unsigned short snd_atiixp_codec_read(atiixp_t *chip, unsigned short codec, unsigned short reg)
+{
+       unsigned int data;
+       int timeout;
+
+       if (snd_atiixp_acquire_codec(chip) < 0)
+               return 0xffff;
+       data = (reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
+               ATI_REG_PHYS_OUT_ADDR_EN |
+               ATI_REG_PHYS_OUT_RW |
+               codec;
+       atiixp_write(chip, PHYS_OUT_ADDR, data);
+       if (snd_atiixp_acquire_codec(chip) < 0)
+               return 0xffff;
+       timeout = 1000;
+       do {
+               data = atiixp_read(chip, PHYS_IN_ADDR);
+               if (data & ATI_REG_PHYS_IN_READ_FLAG)
+                       return data >> ATI_REG_PHYS_IN_DATA_SHIFT;
+               udelay(1);
+       } while (--timeout);
+       /* time out may happen during reset */
+       if (reg < 0x7c)
+               snd_printk(KERN_WARNING "atiixp: codec read timeout (reg %x)\n", reg);
+       return 0xffff;
+}
+
+
+static void snd_atiixp_codec_write(atiixp_t *chip, unsigned short codec, unsigned short reg, unsigned short val)
+{
+       unsigned int data;
+    
+       if (snd_atiixp_acquire_codec(chip) < 0)
+               return;
+       data = ((unsigned int)val << ATI_REG_PHYS_OUT_DATA_SHIFT) |
+               ((unsigned int)reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
+               ATI_REG_PHYS_OUT_ADDR_EN | codec;
+       atiixp_write(chip, PHYS_OUT_ADDR, data);
+}
+
+
+static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg)
+{
+       atiixp_t *chip = ac97->private_data;
+       unsigned short data;
+       spin_lock(&chip->ac97_lock);
+       data = snd_atiixp_codec_read(chip, ac97->num, reg);
+       spin_unlock(&chip->ac97_lock);
+       return data;
+    
+}
+
+static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+{
+       atiixp_t *chip = ac97->private_data;
+       spin_lock(&chip->ac97_lock);
+       snd_atiixp_codec_write(chip, ac97->num, reg, val);
+       spin_unlock(&chip->ac97_lock);
+}
+
+/*
+ * reset AC link
+ */
+static int snd_atiixp_aclink_reset(atiixp_t *chip)
+{
+       int timeout;
+
+       /* reset powerdoewn */
+       if (atiixp_update(chip, CMD, ATI_REG_CMD_POWERDOWN, 0))
+               udelay(10);
+
+       /* perform a software reset */
+       atiixp_update(chip, CMD, ATI_REG_CMD_AC_SOFT_RESET, ATI_REG_CMD_AC_SOFT_RESET);
+       atiixp_read(chip, CMD);
+       udelay(10);
+       atiixp_update(chip, CMD, ATI_REG_CMD_AC_SOFT_RESET, 0);
+    
+       timeout = 10;
+       while (! (atiixp_read(chip, CMD) & ATI_REG_CMD_ACLINK_ACTIVE)) {
+               /* do a hard reset */
+               atiixp_update(chip, CMD, ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET,
+                             ATI_REG_CMD_AC_SYNC);
+               atiixp_read(chip, CMD);
+               do_delay();
+               atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET);
+               if (--timeout) {
+                       snd_printk(KERN_ERR "atiixp: codec reset timeout\n");
+                       break;
+               }
+       }
+
+       /* deassert RESET and assert SYNC to make sure */
+       atiixp_update(chip, CMD, ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET,
+                     ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_atiixp_aclink_down(atiixp_t *chip)
+{
+       // if (atiixp_read(chip, MODEM_MIRROR) & 0x1) /* modem running, too? */
+       //      return -EBUSY;
+       atiixp_update(chip, CMD,
+                    ATI_REG_CMD_POWERDOWN | ATI_REG_CMD_AC_RESET,
+                    ATI_REG_CMD_POWERDOWN);
+       return 0;
+}
+#endif
+
+/*
+ * auto-detection of codecs
+ *
+ * the IXP chip can generate interrupts for the non-existing codecs.
+ * NEW_FRAME interrupt is used to make sure that the interrupt is generated
+ * even if all three codecs are connected.
+ */
+
+#define ALL_CODEC_NOT_READY \
+           (ATI_REG_ISR_CODEC0_NOT_READY |\
+            ATI_REG_ISR_CODEC1_NOT_READY |\
+            ATI_REG_ISR_CODEC2_NOT_READY)
+#define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME)
+
+static int snd_atiixp_codec_detect(atiixp_t *chip)
+{
+       int timeout;
+
+       chip->codec_not_ready_bits = 0;
+       atiixp_write(chip, IER, CODEC_CHECK_BITS);
+       /* wait for the interrupts */
+       timeout = HZ / 10;
+       while (timeout-- > 0) {
+               do_delay();
+               if (chip->codec_not_ready_bits)
+                       break;
+       }
+       atiixp_write(chip, IER, 0); /* disable irqs */
+
+       if ((chip->codec_not_ready_bits & ALL_CODEC_NOT_READY) == ALL_CODEC_NOT_READY) {
+               snd_printk(KERN_ERR "atiixp: no codec detected!\n");
+               return -ENXIO;
+       }
+       return 0;
+}
+
+
+/*
+ * enable DMA and irqs
+ */
+static int snd_atiixp_chip_start(atiixp_t *chip)
+{
+       unsigned int reg;
+
+       /* set up spdif, enable burst mode */
+       reg = atiixp_read(chip, CMD);
+       reg |= ATI_REG_CMD_BURST_EN;
+       if(!(reg & ATI_REG_CMD_MODEM_PRESENT))
+               reg |= ATI_REG_CMD_MODEM_PRESENT;
+       atiixp_write(chip, CMD, reg);
+
+       /* clear all interrupt source */
+       atiixp_write(chip, ISR, 0xffffffff);
+       /* enable irqs */
+       atiixp_write(chip, IER,
+                    ATI_REG_IER_MODEM_STATUS_EN |
+                    ATI_REG_IER_MODEM_IN_XRUN_EN |
+                    ATI_REG_IER_MODEM_OUT1_XRUN_EN);
+       return 0;
+}
+
+
+/*
+ * disable DMA and IRQs
+ */
+static int snd_atiixp_chip_stop(atiixp_t *chip)
+{
+       /* clear interrupt source */
+       atiixp_write(chip, ISR, atiixp_read(chip, ISR));
+       /* disable irqs */
+       atiixp_write(chip, IER, 0);
+       return 0;
+}
+
+
+/*
+ * PCM section
+ */
+
+/*
+ * pointer callback simplly reads XXX_DMA_DT_CUR register as the current
+ * position.  when SG-buffer is implemented, the offset must be calculated
+ * correctly...
+ */
+static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream)
+{
+       atiixp_t *chip = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data;
+       unsigned int curptr;
+
+       spin_lock(&chip->reg_lock);
+       curptr = readl(chip->remap_addr + dma->ops->dt_cur);
+       if (curptr < dma->buf_addr) {
+               snd_printdd("curptr = %x, base = %x\n", curptr, dma->buf_addr);
+               curptr = 0;
+       } else {
+               curptr -= dma->buf_addr;
+               if (curptr >= dma->buf_bytes) {
+                       snd_printdd("curptr = %x, size = %x\n", curptr, dma->buf_bytes);
+                       curptr = 0;
+               }
+       }
+       spin_unlock(&chip->reg_lock);
+       return bytes_to_frames(runtime, curptr);
+}
+
+/*
+ * XRUN detected, and stop the PCM substream
+ */
+static void snd_atiixp_xrun_dma(atiixp_t *chip, atiixp_dma_t *dma)
+{
+       if (! dma->substream || ! dma->running)
+               return;
+       snd_printdd("atiixp: XRUN detected (DMA %d)\n", dma->ops->type);
+       snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN);
+}
+
+/*
+ * the period ack.  update the substream.
+ */
+static void snd_atiixp_update_dma(atiixp_t *chip, atiixp_dma_t *dma)
+{
+       if (! dma->substream || ! dma->running)
+               return;
+       snd_pcm_period_elapsed(dma->substream);
+}
+
+/* set BUS_BUSY interrupt bit if any DMA is running */
+/* call with spinlock held */
+static void snd_atiixp_check_bus_busy(atiixp_t *chip)
+{
+       unsigned int bus_busy;
+       if (atiixp_read(chip, CMD) & (ATI_REG_CMD_MODEM_SEND1_EN |
+                                     ATI_REG_CMD_MODEM_RECEIVE_EN))
+               bus_busy = ATI_REG_IER_MODEM_SET_BUS_BUSY;
+       else
+               bus_busy = 0;
+       atiixp_update(chip, IER, ATI_REG_IER_MODEM_SET_BUS_BUSY, bus_busy);
+}
+
+/* common trigger callback
+ * calling the lowlevel callbacks in it
+ */
+static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+{
+       atiixp_t *chip = snd_pcm_substream_chip(substream);
+       atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+       unsigned int reg = 0;
+       int i;
+
+       snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL);
+
+       if (cmd != SNDRV_PCM_TRIGGER_START && cmd != SNDRV_PCM_TRIGGER_STOP)
+               return -EINVAL;
+
+       spin_lock(&chip->reg_lock);
+
+       /* hook off/on: via GPIO_OUT */
+       for (i = 0; i < NUM_ATI_CODECS; i++) {
+               if (chip->ac97[i]) {
+                       reg = snd_ac97_read(chip->ac97[i], AC97_GPIO_STATUS);
+                       break;
+       }
+       }
+       if(cmd == SNDRV_PCM_TRIGGER_START)
+               reg |= AC97_GPIO_LINE1_OH;
+       else
+               reg &= ~AC97_GPIO_LINE1_OH;
+       reg = (reg << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN ;
+       atiixp_write(chip, MODEM_OUT_GPIO, reg);
+
+       if (cmd == SNDRV_PCM_TRIGGER_START) {
+               dma->ops->enable_transfer(chip, 1);
+               dma->running = 1;
+       } else {
+               dma->ops->enable_transfer(chip, 0);
+               dma->running = 0;
+       }
+       snd_atiixp_check_bus_busy(chip);
+       if (cmd == SNDRV_PCM_TRIGGER_STOP) {
+               dma->ops->flush_dma(chip);
+               snd_atiixp_check_bus_busy(chip);
+       }
+       spin_unlock(&chip->reg_lock);
+       return 0;
+}
+
+
+/*
+ * lowlevel callbacks for each DMA type
+ *
+ * every callback is supposed to be called in chip->reg_lock spinlock
+ */
+
+/* flush FIFO of analog OUT DMA */
+static void atiixp_out_flush_dma(atiixp_t *chip)
+{
+       atiixp_write(chip, MODEM_FIFO_FLUSH, ATI_REG_MODEM_FIFO_OUT1_FLUSH);
+}
+
+/* enable/disable analog OUT DMA */
+static void atiixp_out_enable_dma(atiixp_t *chip, int on)
+{
+       unsigned int data;
+       data = atiixp_read(chip, CMD);
+       if (on) {
+               if (data & ATI_REG_CMD_MODEM_OUT_DMA1_EN)
+                       return;
+               atiixp_out_flush_dma(chip);
+               data |= ATI_REG_CMD_MODEM_OUT_DMA1_EN;
+       } else
+               data &= ~ATI_REG_CMD_MODEM_OUT_DMA1_EN;
+       atiixp_write(chip, CMD, data);
+}
+
+/* start/stop transfer over OUT DMA */
+static void atiixp_out_enable_transfer(atiixp_t *chip, int on)
+{
+       atiixp_update(chip, CMD, ATI_REG_CMD_MODEM_SEND1_EN,
+                     on ? ATI_REG_CMD_MODEM_SEND1_EN : 0);
+}
+
+/* enable/disable analog IN DMA */
+static void atiixp_in_enable_dma(atiixp_t *chip, int on)
+{
+       atiixp_update(chip, CMD, ATI_REG_CMD_MODEM_IN_DMA_EN,
+                     on ? ATI_REG_CMD_MODEM_IN_DMA_EN : 0);
+}
+
+/* start/stop analog IN DMA */
+static void atiixp_in_enable_transfer(atiixp_t *chip, int on)
+{
+       if (on) {
+               unsigned int data = atiixp_read(chip, CMD);
+               if (! (data & ATI_REG_CMD_MODEM_RECEIVE_EN)) {
+                       data |= ATI_REG_CMD_MODEM_RECEIVE_EN;
+                       atiixp_write(chip, CMD, data);
+               }
+       } else
+               atiixp_update(chip, CMD, ATI_REG_CMD_MODEM_RECEIVE_EN, 0);
+}
+
+/* flush FIFO of analog IN DMA */
+static void atiixp_in_flush_dma(atiixp_t *chip)
+{
+       atiixp_write(chip, MODEM_FIFO_FLUSH, ATI_REG_MODEM_FIFO_IN_FLUSH);
+}
+
+/* set up slots and formats for analog OUT */
+static int snd_atiixp_playback_prepare(snd_pcm_substream_t *substream)
+{
+       atiixp_t *chip = snd_pcm_substream_chip(substream);
+       unsigned int data;
+
+       spin_lock_irq(&chip->reg_lock);
+       /* set output threshold */
+       data = atiixp_read(chip, MODEM_OUT_FIFO);
+       data &= ~ATI_REG_MODEM_OUT1_DMA_THRESHOLD_MASK;
+       data |= 0x04 << ATI_REG_MODEM_OUT1_DMA_THRESHOLD_SHIFT;
+       atiixp_write(chip, MODEM_OUT_FIFO, data);
+       spin_unlock_irq(&chip->reg_lock);
+       return 0;
+}
+
+/* set up slots and formats for analog IN */
+static int snd_atiixp_capture_prepare(snd_pcm_substream_t *substream)
+{
+       return 0;
+}
+
+/*
+ * hw_params - allocate the buffer and set up buffer descriptors
+ */
+static int snd_atiixp_pcm_hw_params(snd_pcm_substream_t *substream,
+                                  snd_pcm_hw_params_t *hw_params)
+{
+       atiixp_t *chip = snd_pcm_substream_chip(substream);
+       atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+       int err;
+       int i;
+
+       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+       if (err < 0)
+               return err;
+       dma->buf_addr = substream->runtime->dma_addr;
+       dma->buf_bytes = params_buffer_bytes(hw_params);
+
+       err = atiixp_build_dma_packets(chip, dma, substream,
+                                      params_periods(hw_params),
+                                      params_period_bytes(hw_params));
+       if (err < 0)
+               return err;
+
+       /* set up modem rate */
+       for (i = 0; i < NUM_ATI_CODECS; i++) {
+               if (! chip->ac97[i])
+                       continue;
+               snd_ac97_write(chip->ac97[i], AC97_LINE1_RATE, params_rate(hw_params));
+               snd_ac97_write(chip->ac97[i], AC97_LINE1_LEVEL, 0);
+       }
+
+       return err;
+}
+
+static int snd_atiixp_pcm_hw_free(snd_pcm_substream_t * substream)
+{
+       atiixp_t *chip = snd_pcm_substream_chip(substream);
+       atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+
+       atiixp_clear_dma_packets(chip, dma, substream);
+       snd_pcm_lib_free_pages(substream);
+       return 0;
+}
+
+
+/*
+ * pcm hardware definition, identical for all DMA types
+ */
+static snd_pcm_hardware_t snd_atiixp_pcm_hw =
+{
+       .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+                                SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                                SNDRV_PCM_INFO_MMAP_VALID),
+       .formats =              SNDRV_PCM_FMTBIT_S16_LE,
+       .rates =                SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_KNOT,
+       .rate_min =             8000,
+       .rate_max =             16000,
+       .channels_min =         2,
+       .channels_max =         2,
+       .buffer_bytes_max =     256 * 1024,
+       .period_bytes_min =     32,
+       .period_bytes_max =     128 * 1024,
+       .periods_min =          2,
+       .periods_max =          ATI_MAX_DESCRIPTORS,
+};
+
+static int snd_atiixp_pcm_open(snd_pcm_substream_t *substream, atiixp_dma_t *dma, int pcm_type)
+{
+       atiixp_t *chip = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       int err;
+       static unsigned int rates[] = { 8000,  9600, 12000, 16000 };
+       static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+               .count = ARRAY_SIZE(rates),
+               .list = rates,
+               .mask = 0,
+       };
+
+       snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL);
+
+       if (dma->opened)
+               return -EBUSY;
+       dma->substream = substream;
+       runtime->hw = snd_atiixp_pcm_hw;
+       dma->ac97_pcm_type = pcm_type;
+       if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates)) < 0)
+               return err;
+       if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+               return err;
+       runtime->private_data = dma;
+
+       /* enable DMA bits */
+       spin_lock_irq(&chip->reg_lock);
+       dma->ops->enable_dma(chip, 1);
+       spin_unlock_irq(&chip->reg_lock);
+       dma->opened = 1;
+
+       return 0;
+}
+
+static int snd_atiixp_pcm_close(snd_pcm_substream_t *substream, atiixp_dma_t *dma)
+{
+       atiixp_t *chip = snd_pcm_substream_chip(substream);
+       /* disable DMA bits */
+       snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL);
+       spin_lock_irq(&chip->reg_lock);
+       dma->ops->enable_dma(chip, 0);
+       spin_unlock_irq(&chip->reg_lock);
+       dma->substream = NULL;
+       dma->opened = 0;
+       return 0;
+}
+
+/*
+ */
+static int snd_atiixp_playback_open(snd_pcm_substream_t *substream)
+{
+       atiixp_t *chip = snd_pcm_substream_chip(substream);
+       int err;
+
+       down(&chip->open_mutex);
+       err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0);
+       up(&chip->open_mutex);
+       if (err < 0)
+               return err;
+       return 0;
+}
+
+static int snd_atiixp_playback_close(snd_pcm_substream_t *substream)
+{
+       atiixp_t *chip = snd_pcm_substream_chip(substream);
+       int err;
+       down(&chip->open_mutex);
+       err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]);
+       up(&chip->open_mutex);
+       return err;
+}
+
+static int snd_atiixp_capture_open(snd_pcm_substream_t *substream)
+{
+       atiixp_t *chip = snd_pcm_substream_chip(substream);
+       return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_CAPTURE], 1);
+}
+
+static int snd_atiixp_capture_close(snd_pcm_substream_t *substream)
+{
+       atiixp_t *chip = snd_pcm_substream_chip(substream);
+       return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_CAPTURE]);
+}
+
+
+/* AC97 playback */
+static snd_pcm_ops_t snd_atiixp_playback_ops = {
+       .open =         snd_atiixp_playback_open,
+       .close =        snd_atiixp_playback_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    snd_atiixp_pcm_hw_params,
+       .hw_free =      snd_atiixp_pcm_hw_free,
+       .prepare =      snd_atiixp_playback_prepare,
+       .trigger =      snd_atiixp_pcm_trigger,
+       .pointer =      snd_atiixp_pcm_pointer,
+};
+
+/* AC97 capture */
+static snd_pcm_ops_t snd_atiixp_capture_ops = {
+       .open =         snd_atiixp_capture_open,
+       .close =        snd_atiixp_capture_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    snd_atiixp_pcm_hw_params,
+       .hw_free =      snd_atiixp_pcm_hw_free,
+       .prepare =      snd_atiixp_capture_prepare,
+       .trigger =      snd_atiixp_pcm_trigger,
+       .pointer =      snd_atiixp_pcm_pointer,
+};
+
+static atiixp_dma_ops_t snd_atiixp_playback_dma_ops = {
+       .type = ATI_DMA_PLAYBACK,
+       .llp_offset = ATI_REG_MODEM_OUT_DMA1_LINKPTR,
+       .dt_cur = ATI_REG_MODEM_OUT_DMA1_DT_CUR,
+       .enable_dma = atiixp_out_enable_dma,
+       .enable_transfer = atiixp_out_enable_transfer,
+       .flush_dma = atiixp_out_flush_dma,
+};
+       
+static atiixp_dma_ops_t snd_atiixp_capture_dma_ops = {
+       .type = ATI_DMA_CAPTURE,
+       .llp_offset = ATI_REG_MODEM_IN_DMA_LINKPTR,
+       .dt_cur = ATI_REG_MODEM_IN_DMA_DT_CUR,
+       .enable_dma = atiixp_in_enable_dma,
+       .enable_transfer = atiixp_in_enable_transfer,
+       .flush_dma = atiixp_in_flush_dma,
+};
+
+static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
+{
+       snd_pcm_t *pcm;
+       int err;
+
+       /* initialize constants */
+       chip->dmas[ATI_DMA_PLAYBACK].ops = &snd_atiixp_playback_dma_ops;
+       chip->dmas[ATI_DMA_CAPTURE].ops = &snd_atiixp_capture_dma_ops;
+
+       /* PCM #0: analog I/O */
+       err = snd_pcm_new(chip->card, "ATI IXP MC97", ATI_PCMDEV_ANALOG, 1, 1, &pcm);
+       if (err < 0)
+               return err;
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_atiixp_playback_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_atiixp_capture_ops);
+       pcm->private_data = chip;
+       strcpy(pcm->name, "ATI IXP MC97");
+       chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm;
+
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                             snd_dma_pci_data(chip->pci), 64*1024, 128*1024);
+
+       return 0;
+}
+
+
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       atiixp_t *chip = dev_id;
+       unsigned int status;
+
+       status = atiixp_read(chip, ISR);
+
+       if (! status)
+               return IRQ_NONE;
+
+       /* process audio DMA */
+       if (status & ATI_REG_ISR_MODEM_OUT1_XRUN)
+               snd_atiixp_xrun_dma(chip,  &chip->dmas[ATI_DMA_PLAYBACK]);
+       else if (status & ATI_REG_ISR_MODEM_OUT1_STATUS)
+               snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_PLAYBACK]);
+       if (status & ATI_REG_ISR_MODEM_IN_XRUN)
+               snd_atiixp_xrun_dma(chip,  &chip->dmas[ATI_DMA_CAPTURE]);
+       else if (status & ATI_REG_ISR_MODEM_IN_STATUS)
+               snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_CAPTURE]);
+
+       /* for codec detection */
+       if (status & CODEC_CHECK_BITS) {
+               unsigned int detected;
+               detected = status & CODEC_CHECK_BITS;
+               spin_lock(&chip->reg_lock);
+               chip->codec_not_ready_bits |= detected;
+               atiixp_update(chip, IER, detected, 0); /* disable the detected irqs */
+               spin_unlock(&chip->reg_lock);
+       }
+
+       /* ack */
+       atiixp_write(chip, ISR, status);
+
+       return IRQ_HANDLED;
+}
+
+
+/*
+ * ac97 mixer section
+ */
+
+static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
+{
+       ac97_bus_t *pbus;
+       ac97_template_t ac97;
+       int i, err;
+       int codec_count;
+       static ac97_bus_ops_t ops = {
+               .write = snd_atiixp_ac97_write,
+               .read = snd_atiixp_ac97_read,
+       };
+       static unsigned int codec_skip[NUM_ATI_CODECS] = {
+               ATI_REG_ISR_CODEC0_NOT_READY,
+               ATI_REG_ISR_CODEC1_NOT_READY,
+               ATI_REG_ISR_CODEC2_NOT_READY,
+       };
+
+       if (snd_atiixp_codec_detect(chip) < 0)
+               return -ENXIO;
+
+       if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
+               return err;
+       pbus->clock = clock;
+       pbus->shared_type = AC97_SHARED_TYPE_ATIIXP;    /* shared with audio driver */
+       chip->ac97_bus = pbus;
+
+       codec_count = 0;
+       for (i = 0; i < NUM_ATI_CODECS; i++) {
+               if (chip->codec_not_ready_bits & codec_skip[i])
+                       continue;
+               memset(&ac97, 0, sizeof(ac97));
+               ac97.private_data = chip;
+               ac97.pci = chip->pci;
+               ac97.num = i;
+               ac97.scaps = AC97_SCAP_SKIP_AUDIO;
+               if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
+                       chip->ac97[i] = NULL; /* to be sure */
+                       snd_printdd("atiixp: codec %d not available for modem\n", i);
+                       continue;
+               }
+               codec_count++;
+       }
+
+       if (! codec_count) {
+               snd_printk(KERN_ERR "atiixp: no codec available\n");
+               return -ENODEV;
+       }
+
+       /* snd_ac97_tune_hardware(chip->ac97, ac97_quirks); */
+
+       return 0;
+}
+
+
+#ifdef CONFIG_PM
+/*
+ * power management
+ */
+static int snd_atiixp_suspend(snd_card_t *card, unsigned int state)
+{
+       atiixp_t *chip = card->pm_private_data;
+       int i;
+
+       for (i = 0; i < NUM_ATI_PCMDEVS; i++)
+               if (chip->pcmdevs[i])
+                       snd_pcm_suspend_all(chip->pcmdevs[i]);
+       for (i = 0; i < NUM_ATI_CODECS; i++)
+               if (chip->ac97[i])
+                       snd_ac97_suspend(chip->ac97[i]);
+       snd_atiixp_aclink_down(chip);
+       snd_atiixp_chip_stop(chip);
+
+       pci_set_power_state(chip->pci, 3);
+       pci_disable_device(chip->pci);
+       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+       return 0;
+}
+
+static int snd_atiixp_resume(snd_card_t *card, unsigned int state)
+{
+       atiixp_t *chip = card->pm_private_data;
+       int i;
+
+       pci_enable_device(chip->pci);
+       pci_set_power_state(chip->pci, 0);
+
+       snd_atiixp_aclink_reset(chip);
+       snd_atiixp_chip_start(chip);
+
+       for (i = 0; i < NUM_ATI_CODECS; i++)
+               if (chip->ac97[i])
+                       snd_ac97_resume(chip->ac97[i]);
+
+       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+       return 0;
+}
+#endif /* CONFIG_PM */
+
+
+/*
+ * proc interface for register dump
+ */
+
+static void snd_atiixp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+       atiixp_t *chip = entry->private_data;
+       int i;
+
+       for (i = 0; i < 256; i += 4)
+               snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i));
+}
+
+static void __devinit snd_atiixp_proc_init(atiixp_t *chip)
+{
+       snd_info_entry_t *entry;
+
+       if (! snd_card_proc_new(chip->card, "atiixp", &entry))
+               snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read);
+}
+
+
+
+/*
+ * destructor
+ */
+
+static int snd_atiixp_free(atiixp_t *chip)
+{
+       if (chip->irq < 0)
+               goto __hw_end;
+       snd_atiixp_chip_stop(chip);
+       synchronize_irq(chip->irq);
+      __hw_end:
+       if (chip->irq >= 0)
+               free_irq(chip->irq, (void *)chip);
+       if (chip->remap_addr)
+               iounmap(chip->remap_addr);
+       pci_release_regions(chip->pci);
+       kfree(chip);
+       return 0;
+}
+
+static int snd_atiixp_dev_free(snd_device_t *device)
+{
+       atiixp_t *chip = device->device_data;
+       return snd_atiixp_free(chip);
+}
+
+/*
+ * constructor for chip instance
+ */
+static int __devinit snd_atiixp_create(snd_card_t *card,
+                                     struct pci_dev *pci,
+                                     atiixp_t **r_chip)
+{
+       static snd_device_ops_t ops = {
+               .dev_free =     snd_atiixp_dev_free,
+       };
+       atiixp_t *chip;
+       int err;
+
+       if ((err = pci_enable_device(pci)) < 0)
+               return err;
+
+       chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+       if (chip == NULL)
+               return -ENOMEM;
+
+       spin_lock_init(&chip->reg_lock);
+       spin_lock_init(&chip->ac97_lock);
+       init_MUTEX(&chip->open_mutex);
+       chip->card = card;
+       chip->pci = pci;
+       chip->irq = -1;
+       if ((err = pci_request_regions(pci, "ATI IXP MC97")) < 0) {
+               kfree(chip);
+               return err;
+       }
+       chip->addr = pci_resource_start(pci, 0);
+       chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 0));
+       if (chip->remap_addr == 0) {
+               snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
+               snd_atiixp_free(chip);
+               return -EIO;
+       }
+
+       if (request_irq(pci->irq, snd_atiixp_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) {
+               snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+               snd_atiixp_free(chip);
+               return -EBUSY;
+       }
+       chip->irq = pci->irq;
+       pci_set_master(pci);
+       synchronize_irq(chip->irq);
+
+       if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+               snd_atiixp_free(chip);
+               return err;
+       }
+
+       snd_card_set_dev(card, &pci->dev);
+
+       *r_chip = chip;
+       return 0;
+}
+
+
+static int __devinit snd_atiixp_probe(struct pci_dev *pci,
+                                     const struct pci_device_id *pci_id)
+{
+       static int dev;
+       snd_card_t *card;
+       atiixp_t *chip;
+       unsigned char revision;
+       int err;
+
+       if (dev >= SNDRV_CARDS)
+               return -ENODEV;
+       if (!enable[dev]) {
+               dev++;
+               return -ENOENT;
+       }
+
+       card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+       if (card == NULL)
+               return -ENOMEM;
+
+       pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
+
+       strcpy(card->driver, "ATIIXP-MODEM");
+       strcpy(card->shortname, "ATI IXP Modem");
+       if ((err = snd_atiixp_create(card, pci, &chip)) < 0)
+               goto __error;
+
+       if ((err = snd_atiixp_aclink_reset(chip)) < 0)
+               goto __error;
+
+       if ((err = snd_atiixp_mixer_new(chip, ac97_clock[dev])) < 0)
+               goto __error;
+
+       if ((err = snd_atiixp_pcm_new(chip)) < 0)
+               goto __error;
+       
+       snd_atiixp_proc_init(chip);
+
+       snd_atiixp_chip_start(chip);
+
+       sprintf(card->longname, "%s rev %x at 0x%lx, irq %i",
+               card->shortname, revision, chip->addr, chip->irq);
+
+       snd_card_set_pm_callback(card, snd_atiixp_suspend, snd_atiixp_resume, chip);
+
+       if ((err = snd_card_register(card)) < 0)
+               goto __error;
+
+       pci_set_drvdata(pci, card);
+       dev++;
+       return 0;
+
+ __error:
+       snd_card_free(card);
+       return err;
+}
+
+static void __devexit snd_atiixp_remove(struct pci_dev *pci)
+{
+       snd_card_free(pci_get_drvdata(pci));
+       pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_driver driver = {
+       .name = "ATI IXP MC97 controller",
+       .id_table = snd_atiixp_ids,
+       .probe = snd_atiixp_probe,
+       .remove = __devexit_p(snd_atiixp_remove),
+       SND_PCI_PM_CALLBACKS
+};
+
+
+static int __init alsa_card_atiixp_init(void)
+{
+       return pci_module_init(&driver);
+}
+
+static void __exit alsa_card_atiixp_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_atiixp_init)
+module_exit(alsa_card_atiixp_exit)
index c4f9413..477b2d1 100644 (file)
 
 static int __devinit snd_vortex_mixer(vortex_t * vortex)
 {
-       ac97_bus_t bus, *pbus;
-       ac97_t ac97;
+       ac97_bus_t *pbus;
+       ac97_template_t ac97;
        int err;
+       static ac97_bus_ops_t ops = {
+               .write = vortex_codec_write,
+               .read = vortex_codec_read,
+       };
 
-       memset(&bus, 0, sizeof(bus));
-       bus.write = vortex_codec_write;
-       bus.read = vortex_codec_read;
-       if ((err = snd_ac97_bus(vortex->card, &bus, &pbus)) < 0)
+       if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0)
                return err;
        memset(&ac97, 0, sizeof(ac97));
        // Intialize AC97 codec stuff.
index 3027c35..c0c2346 100644 (file)
@@ -104,7 +104,7 @@ static int __devinit snd_vortex_midi(vortex_t * vortex)
                         ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
                return temp;
        }
-       mpu = snd_magic_cast(mpu401_t, rmidi->private_data, return -ENOMEM);
+       mpu = rmidi->private_data;
        mpu->cport = (unsigned long)(vortex->mmio + (VORTEX_MIDI_CMD >> 2));
 #endif
        vortex->rmidi = rmidi;
index 9c0700c..df915fa 100644 (file)
@@ -540,6 +540,12 @@ vortex_XtalkHw_SetGains(vortex_t * vortex, xtalk_gains_t const gains)
        }
 }
 
+static void
+vortex_XtalkHw_SetGainsAllChan(vortex_t * vortex)
+{
+       vortex_XtalkHw_SetGains(vortex, asXtalkGainsAllChan);
+}
+
 #if 0
 static void vortex_XtalkHw_GetGains(vortex_t * vortex, xtalk_gains_t gains)
 {
index 832f62f..0b8d7b6 100644 (file)
@@ -45,10 +45,9 @@ typedef short xtalk_instate_t[XTINST_SZ];
 typedef short xtalk_coefs_t[5][5];
 typedef short xtalk_state_t[5][4];
 
-extern xtalk_gains_t const asXtalkGainsAllChan;
-
 static void vortex_XtalkHw_SetGains(vortex_t * vortex,
                                    xtalk_gains_t const gains);
+static void vortex_XtalkHw_SetGainsAllChan(vortex_t * vortex);
 static void vortex_XtalkHw_SetSampleRate(vortex_t * vortex, int sr);
 static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex);
 static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex);
index 3eae4f2..52575f9 100644 (file)
@@ -22,8 +22,6 @@
 #ifndef __CS46XX_LIB_H__
 #define __CS46XX_LIB_H__
 
-#define chip_t cs46xx_t
-
 /*
  *  constants
  */
index 95fc96f..0bd4b33 100644 (file)
@@ -74,7 +74,7 @@ static int shadow_and_reallocate_code (cs46xx_t * chip,u32 * data,u32 size, u32
                            (mop_operands & WIDE_LADD_INSTR_MASK) == 0 &&
                            (mop_operands & WIDE_INSTR_MASK) != 0) {
                                wide_op = loval & 0x7f;
-                               for (j = 0;j < sizeof(wide_opcodes) / sizeof(wide_opcode_t); ++j) {
+                               for (j = 0;j < ARRAY_SIZE(wide_opcodes); ++j) {
                                        if (wide_opcodes[j] == wide_op) {
                                                /* need to reallocate instruction */
                                                address  = (hival & 0x00FFF) << 5;
@@ -462,7 +462,7 @@ symbol_entry_t * cs46xx_dsp_lookup_symbol_addr (cs46xx_t * chip, u32 address, in
 
 static void cs46xx_dsp_proc_symbol_table_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+       cs46xx_t *chip = entry->private_data;
        dsp_spos_instance_t * ins = chip->dsp_spos_instance;
        int i;
 
@@ -489,7 +489,7 @@ static void cs46xx_dsp_proc_symbol_table_read (snd_info_entry_t *entry, snd_info
 
 static void cs46xx_dsp_proc_modules_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+       cs46xx_t *chip = entry->private_data;
        dsp_spos_instance_t * ins = chip->dsp_spos_instance;
        int i,j;
 
@@ -511,7 +511,7 @@ static void cs46xx_dsp_proc_modules_read (snd_info_entry_t *entry, snd_info_buff
 
 static void cs46xx_dsp_proc_task_tree_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+       cs46xx_t *chip = entry->private_data;
        dsp_spos_instance_t * ins = chip->dsp_spos_instance;
        int i,j,col;
        unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
@@ -538,7 +538,7 @@ static void cs46xx_dsp_proc_task_tree_read (snd_info_entry_t *entry, snd_info_bu
 
 static void cs46xx_dsp_proc_scb_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+       cs46xx_t *chip = entry->private_data;
        dsp_spos_instance_t * ins = chip->dsp_spos_instance;
        int i;
 
@@ -570,7 +570,7 @@ static void cs46xx_dsp_proc_scb_read (snd_info_entry_t *entry, snd_info_buffer_t
 
 static void cs46xx_dsp_proc_parameter_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+       cs46xx_t *chip = entry->private_data;
        /*dsp_spos_instance_t * ins = chip->dsp_spos_instance; */
        unsigned int i,col = 0;
        unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
@@ -597,7 +597,7 @@ static void cs46xx_dsp_proc_parameter_dump_read (snd_info_entry_t *entry, snd_in
 
 static void cs46xx_dsp_proc_sample_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-       cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+       cs46xx_t *chip = entry->private_data;
        int i,col = 0;
        unsigned long dst = chip->region.idx[2].remap_addr;
 
@@ -1057,7 +1057,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
        
        int fifo_addr,fifo_span,valid_slots;
 
-       spos_control_block_t sposcb = {
+       static spos_control_block_t sposcb = {
                /* 0 */ HFG_TREE_SCB,HFG_STACK,
                /* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR,
                /* 2 */ DSP_SPOS_DC,0,
@@ -1110,18 +1110,18 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
   
        {
                /* create the null SCB */
-               generic_scb_t null_scb = {
+               static generic_scb_t null_scb = {
                        { 0, 0, 0, 0 },
                        { 0, 0, 0, 0, 0 },
                        NULL_SCB_ADDR, NULL_SCB_ADDR,
-                       null_algorithm->address, 0,
-                       0,0,0,
+                       0, 0, 0, 0, 0,
                        {
                                0,0,
                                0,0,
                        }
                };
 
+               null_scb.entry_point = null_algorithm->address;
                ins->the_null_scb = cs46xx_dsp_create_scb(chip, "nullSCB", (u32 *)&null_scb, NULL_SCB_ADDR);
                ins->the_null_scb->task_entry = null_algorithm;
                ins->the_null_scb->sub_list_ptr = ins->the_null_scb;
@@ -1132,7 +1132,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
 
        {
                /* setup foreground task tree */
-               task_tree_control_block_t fg_task_tree_hdr =  {
+               static task_tree_control_block_t fg_task_tree_hdr =  {
                        { FG_TASK_HEADER_ADDR | (DSP_SPOS_DC << 0x10),
                          DSP_SPOS_DC_DC,
                          DSP_SPOS_DC_DC,
@@ -1145,7 +1145,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
     
                        {
                                BG_TREE_SCB_ADDR,TIMINGMASTER_SCB_ADDR, 
-                               fg_task_tree_header_code->address,
+                               0,
                                FG_TASK_HEADER_ADDR + TCBData,                  
                        },
 
@@ -1158,7 +1158,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
                        },
 
                        {
-                               DSP_SPOS_DC,task_tree_thread->address,
+                               DSP_SPOS_DC,0,
                                DSP_SPOS_DC,DSP_SPOS_DC,
                                DSP_SPOS_DC,DSP_SPOS_DC,
                                DSP_SPOS_DC,DSP_SPOS_DC,
@@ -1200,13 +1200,15 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
                        }
                };
 
+               fg_task_tree_hdr.links.entry_point = fg_task_tree_header_code->address;
+               fg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
                cs46xx_dsp_create_task_tree(chip,"FGtaskTreeHdr",(u32 *)&fg_task_tree_hdr,FG_TASK_HEADER_ADDR,0x35);
        }
 
 
        {
                /* setup foreground task tree */
-               task_tree_control_block_t bg_task_tree_hdr =  {
+               static task_tree_control_block_t bg_task_tree_hdr =  {
                        { DSP_SPOS_DC_DC,
                          DSP_SPOS_DC_DC,
                          DSP_SPOS_DC_DC,
@@ -1219,7 +1221,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
     
                        {
                                NULL_SCB_ADDR,NULL_SCB_ADDR,  /* Set up the background to do nothing */
-                               task_tree_header_code->address,
+                               0,
                                BG_TREE_SCB_ADDR + TCBData,
                        },
 
@@ -1232,7 +1234,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
                        },
 
                        {
-                               DSP_SPOS_DC,task_tree_thread->address,
+                               DSP_SPOS_DC,0,
                                DSP_SPOS_DC,DSP_SPOS_DC,
                                DSP_SPOS_DC,DSP_SPOS_DC,
                                DSP_SPOS_DC,DSP_SPOS_DC,
@@ -1273,6 +1275,9 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
                                0,0
                        }
                };
+
+               bg_task_tree_hdr.links.entry_point = task_tree_header_code->address;
+               bg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
                cs46xx_dsp_create_task_tree(chip,"BGtaskTreeHdr",(u32 *)&bg_task_tree_hdr,BG_TREE_SCB_ADDR,0x35);
        }
 
@@ -1312,7 +1317,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
        if (!write_back_scb) goto _fail_end;
 
        {
-               mix2_ostream_spb_t mix2_ostream_spb = {
+               static mix2_ostream_spb_t mix2_ostream_spb = {
                        0x00020000,
                        0x0000ffff
                };
index c3975fb..580701e 100644 (file)
@@ -93,7 +93,7 @@ snd_emu10k1_synth_get_voice(emu10k1_t *hw)
        unsigned long flags;
        int i;
 
-       emu = snd_magic_cast(snd_emux_t, hw->synth, return -EINVAL);
+       emu = hw->synth;
 
        spin_lock_irqsave(&emu->voice_lock, flags);
        lookup_voices(emu, hw, best, 1); /* no OFF voices */
@@ -128,7 +128,7 @@ release_voice(snd_emux_voice_t *vp)
        int dcysusv;
        emu10k1_t *hw;
        
-       hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+       hw = vp->hw;
        dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
        snd_emu10k1_ptr_write(hw, DCYSUSM, vp->ch, dcysusv);
        dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease | DCYSUSV_CHANNELENABLE_MASK;
@@ -145,7 +145,7 @@ terminate_voice(snd_emux_voice_t *vp)
        emu10k1_t *hw;
        
        snd_assert(vp, return);
-       hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+       hw = vp->hw;
        snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
        if (vp->block) {
                emu10k1_memblk_t *emem;
@@ -163,7 +163,7 @@ free_voice(snd_emux_voice_t *vp)
 {
        emu10k1_t *hw;
        
-       hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+       hw = vp->hw;
        if (vp->ch >= 0) {
                snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00);
                snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
@@ -185,7 +185,7 @@ update_voice(snd_emux_voice_t *vp, int update)
 {
        emu10k1_t *hw;
        
-       hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+       hw = vp->hw;
        if (update & SNDRV_EMUX_UPDATE_VOLUME)
                snd_emu10k1_ptr_write(hw, IFATN_ATTENUATION, vp->ch, vp->avol);
        if (update & SNDRV_EMUX_UPDATE_PITCH)
@@ -282,7 +282,7 @@ get_voice(snd_emux_t *emu, snd_emux_port_t *port)
        best_voice_t best[V_END];
        int i;
 
-       hw = snd_magic_cast(emu10k1_t, emu->hw, return NULL);
+       hw = emu->hw;
 
        lookup_voices(emu, hw, best, 0);
        for (i = 0; i < V_END; i++) {
@@ -317,7 +317,7 @@ start_voice(snd_emux_voice_t *vp)
        emu10k1_t *hw;
        emu10k1_memblk_t *emem;
        
-       hw = snd_magic_cast(emu10k1_t, vp->hw, return -EINVAL);
+       hw = vp->hw;
        ch = vp->ch;
        snd_assert(ch >= 0, return -EINVAL);
        chan = vp->chan;
@@ -469,7 +469,7 @@ trigger_voice(snd_emux_voice_t *vp)
        emu10k1_t *hw;
        emu10k1_memblk_t *emem;
        
-       hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+       hw = vp->hw;
 
        emem = (emu10k1_memblk_t *)vp->block;
        if (! emem || emem->mapped_page < 0)
index 14bf206..4df668e 100644 (file)
@@ -44,7 +44,7 @@ snd_emu10k1_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp,
        unsigned int start_addr;
        emu10k1_t *emu;
 
-       emu = snd_magic_cast(emu10k1_t, rec->hw, return -ENXIO);
+       emu = rec->hw;
        snd_assert(sp != NULL, return -EINVAL);
        snd_assert(hdr != NULL, return -EINVAL);
 
@@ -210,7 +210,7 @@ snd_emu10k1_sample_free(snd_emux_t *rec, snd_sf_sample_t *sp,
 {
        emu10k1_t *emu;
 
-       emu = snd_magic_cast(emu10k1_t, rec->hw, return -ENXIO);
+       emu = rec->hw;
        snd_assert(sp != NULL, return -EINVAL);
        snd_assert(hdr != NULL, return -EINVAL);
 
index 9e562ae..2af8ffa 100644 (file)
@@ -85,9 +85,9 @@ int snd_emu10k1_synth_delete_device(snd_seq_device_t *dev)
        if (dev->driver_data == NULL)
                return 0; /* not registered actually */
 
-       emu = snd_magic_cast(snd_emux_t, dev->driver_data, return -EINVAL);
+       emu = dev->driver_data;
 
-       hw = snd_magic_cast(emu10k1_t, emu->hw, return -EINVAL);
+       hw = emu->hw;
        spin_lock_irqsave(&hw->voice_lock, flags);
        hw->synth = NULL;
        hw->get_synth_voice = NULL;
index 39d7e32..9fbbf6c 100644 (file)
@@ -34,8 +34,6 @@
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 
-#define chip_t emu10k1_t
-
 static void snd_emu10k1_pcm_interrupt(emu10k1_t *emu, emu10k1_voice_t *voice)
 {
        emu10k1_pcm_t *epcm;
@@ -354,7 +352,7 @@ static int snd_emu10k1_playback_hw_params(snd_pcm_substream_t * substream,
 {
        emu10k1_t *emu = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+       emu10k1_pcm_t *epcm = runtime->private_data;
        int err;
 
        if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0)
@@ -383,7 +381,7 @@ static int snd_emu10k1_playback_hw_free(snd_pcm_substream_t * substream)
 
        if (runtime->private_data == NULL)
                return 0;
-       epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+       epcm = runtime->private_data;
        if (epcm->extra) {
                snd_emu10k1_voice_free(epcm->emu, epcm->extra);
                epcm->extra = NULL;
@@ -409,7 +407,7 @@ static int snd_emu10k1_playback_prepare(snd_pcm_substream_t * substream)
 {
        emu10k1_t *emu = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+       emu10k1_pcm_t *epcm = runtime->private_data;
        unsigned int start_addr, end_addr;
 
        start_addr = epcm->start_addr;
@@ -443,7 +441,7 @@ static int snd_emu10k1_capture_prepare(snd_pcm_substream_t * substream)
 {
        emu10k1_t *emu = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+       emu10k1_pcm_t *epcm = runtime->private_data;
        int idx;
 
        snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
@@ -452,7 +450,11 @@ static int snd_emu10k1_capture_prepare(snd_pcm_substream_t * substream)
                snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
                break;
        case CAPTURE_EFX:
-               snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
+               if (emu->audigy) {
+                       snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0);
+                       snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0);
+               } else
+                       snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
                break;
        default:
                break;
@@ -565,12 +567,11 @@ static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
 {
        emu10k1_t *emu = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
-       unsigned long flags;
+       emu10k1_pcm_t *epcm = runtime->private_data;
        int result = 0;
 
        // printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
-       spin_lock_irqsave(&emu->reg_lock, flags);
+       spin_lock(&emu->reg_lock);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
                snd_emu10k1_playback_invalidate_cache(emu, epcm->extra);        /* do we need this? */
@@ -593,7 +594,7 @@ static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
                result = -EINVAL;
                break;
        }
-       spin_unlock_irqrestore(&emu->reg_lock, flags);
+       spin_unlock(&emu->reg_lock);
        return result;
 }
 
@@ -602,12 +603,11 @@ static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
 {
        emu10k1_t *emu = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
-       unsigned long flags;
+       emu10k1_pcm_t *epcm = runtime->private_data;
        int result = 0;
 
        // printk("trigger - emu10k1 = %p, cmd = %i, pointer = %i\n", emu, cmd, substream->ops->pointer(substream));
-       spin_lock_irqsave(&emu->reg_lock, flags);
+       spin_lock(&emu->reg_lock);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
                outl(epcm->capture_ipr, emu->port + IPR);
@@ -618,7 +618,11 @@ static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
                        snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
                        break;
                case CAPTURE_EFX:
-                       snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
+                       if (emu->audigy) {
+                               snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val);
+                               snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2);
+                       } else
+                               snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
                        break;
                default:        
                        break;
@@ -637,7 +641,11 @@ static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
                        snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
                        break;
                case CAPTURE_EFX:
-                       snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
+                       if (emu->audigy) {
+                               snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0);
+                               snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0);
+                       } else
+                               snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
                        break;
                default:
                        break;
@@ -646,7 +654,7 @@ static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
        default:
                result = -EINVAL;
        }
-       spin_unlock_irqrestore(&emu->reg_lock, flags);
+       spin_unlock(&emu->reg_lock);
        return result;
 }
 
@@ -654,7 +662,7 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(snd_pcm_substream_t * subs
 {
        emu10k1_t *emu = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+       emu10k1_pcm_t *epcm = runtime->private_data;
        unsigned int ptr;
 
        if (!epcm->running)
@@ -681,7 +689,7 @@ static snd_pcm_uframes_t snd_emu10k1_capture_pointer(snd_pcm_substream_t * subst
 {
        emu10k1_t *emu = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+       emu10k1_pcm_t *epcm = runtime->private_data;
        unsigned int ptr;
 
        if (!epcm->running)
@@ -767,10 +775,10 @@ static void snd_emu10k1_pcm_mixer_notify(emu10k1_t *emu, int idx, int activate)
 
 static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-       emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return);
+       emu10k1_pcm_t *epcm = runtime->private_data;
 
        if (epcm)
-               snd_magic_kfree(epcm);
+               kfree(epcm);
 }
 
 static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
@@ -781,7 +789,7 @@ static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
        snd_pcm_runtime_t *runtime = substream->runtime;
        int i, err;
 
-       epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+       epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
        if (epcm == NULL)
                return -ENOMEM;
        epcm->emu = emu;
@@ -791,11 +799,11 @@ static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
        runtime->private_free = snd_emu10k1_pcm_free_substream;
        runtime->hw = snd_emu10k1_playback;
        if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) {
-               snd_magic_kfree(epcm);
+               kfree(epcm);
                return err;
        }
        if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) {
-               snd_magic_kfree(epcm);
+               kfree(epcm);
                return err;
        }
        mix = &emu->pcm_mixer[substream->number];
@@ -826,7 +834,7 @@ static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream)
        snd_pcm_runtime_t *runtime = substream->runtime;
        emu10k1_pcm_t *epcm;
 
-       epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+       epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
        if (epcm == NULL)
                return -ENOMEM;
        epcm->emu = emu;
@@ -842,7 +850,7 @@ static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream)
        runtime->hw = snd_emu10k1_capture;
        emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt;
        emu->pcm_capture_substream = substream;
-       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates);
        return 0;
 }
@@ -862,7 +870,7 @@ static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream)
        emu10k1_pcm_t *epcm;
        snd_pcm_runtime_t *runtime = substream->runtime;
 
-       epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+       epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
        if (epcm == NULL)
                return -ENOMEM;
        epcm->emu = emu;
@@ -881,7 +889,7 @@ static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream)
        runtime->hw.channels_min = 1;
        emu->capture_mic_interrupt = snd_emu10k1_pcm_ac97mic_interrupt;
        emu->pcm_capture_mic_substream = substream;
-       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
        return 0;
 }
 
@@ -899,11 +907,10 @@ static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
        emu10k1_t *emu = snd_pcm_substream_chip(substream);
        emu10k1_pcm_t *epcm;
        snd_pcm_runtime_t *runtime = substream->runtime;
-       unsigned long flags;
        int nefx = emu->audigy ? 64 : 32;
        int idx;
 
-       epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+       epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
        if (epcm == NULL)
                return -ENOMEM;
        epcm->emu = emu;
@@ -919,7 +926,7 @@ static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
        runtime->hw = snd_emu10k1_capture;
        runtime->hw.rates = SNDRV_PCM_RATE_48000;
        runtime->hw.rate_min = runtime->hw.rate_max = 48000;
-       spin_lock_irqsave(&emu->reg_lock, flags);
+       spin_lock_irq(&emu->reg_lock);
        runtime->hw.channels_min = runtime->hw.channels_max = 0;
        for (idx = 0; idx < nefx; idx++) {
                if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
@@ -929,10 +936,10 @@ static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
        }
        epcm->capture_cr_val = emu->efx_voices_mask[0];
        epcm->capture_cr_val2 = emu->efx_voices_mask[1];
-       spin_unlock_irqrestore(&emu->reg_lock, flags);
+       spin_unlock_irq(&emu->reg_lock);
        emu->capture_efx_interrupt = snd_emu10k1_pcm_efx_interrupt;
        emu->pcm_capture_efx_substream = substream;
-       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
        return 0;
 }
 
@@ -970,7 +977,7 @@ static snd_pcm_ops_t snd_emu10k1_capture_ops = {
 
 static void snd_emu10k1_pcm_free(snd_pcm_t *pcm)
 {
-       emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+       emu10k1_t *emu = pcm->private_data;
        emu->pcm = NULL;
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1024,7 +1031,7 @@ static snd_pcm_ops_t snd_emu10k1_capture_mic_ops = {
 
 static void snd_emu10k1_pcm_mic_free(snd_pcm_t *pcm)
 {
-       emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+       emu10k1_t *emu = pcm->private_data;
        emu->pcm_mic = NULL;
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1070,21 +1077,19 @@ static int snd_emu10k1_pcm_efx_voices_mask_info(snd_kcontrol_t *kcontrol, snd_ct
 static int snd_emu10k1_pcm_efx_voices_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
        emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
-       unsigned long flags;
        int nefx = emu->audigy ? 64 : 32;
        int idx;
        
-       spin_lock_irqsave(&emu->reg_lock, flags);
+       spin_lock_irq(&emu->reg_lock);
        for (idx = 0; idx < nefx; idx++)
                ucontrol->value.integer.value[idx] = (emu->efx_voices_mask[idx / 32] & (1 << (idx % 32))) ? 1 : 0;
-       spin_unlock_irqrestore(&emu->reg_lock, flags);
+       spin_unlock_irq(&emu->reg_lock);
        return 0;
 }
 
 static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
        emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
-       unsigned long flags;
        unsigned int nval[2], bits;
        int nefx = emu->audigy ? 64 : 32;
        int change, idx;
@@ -1097,12 +1102,12 @@ static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ct
                }
        if (bits != 1 && bits != 2 && bits != 4 && bits != 8)
                return -EINVAL;
-       spin_lock_irqsave(&emu->reg_lock, flags);
+       spin_lock_irq(&emu->reg_lock);
        change = (nval[0] != emu->efx_voices_mask[0]) ||
                (nval[1] != emu->efx_voices_mask[1]);
        emu->efx_voices_mask[0] = nval[0];
        emu->efx_voices_mask[1] = nval[1];
-       spin_unlock_irqrestore(&emu->reg_lock, flags);
+       spin_unlock_irq(&emu->reg_lock);
        return change;
 }
 
@@ -1125,9 +1130,238 @@ static snd_pcm_ops_t snd_emu10k1_capture_efx_ops = {
        .pointer =              snd_emu10k1_capture_pointer,
 };
 
+
+/* EFX playback */
+
+#define INITIAL_TRAM_SHIFT     14
+#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1)
+
+static void snd_emu10k1_fx8010_playback_irq(emu10k1_t *emu, void *private_data)
+{
+       snd_pcm_substream_t *substream = private_data;
+       snd_pcm_period_elapsed(substream);
+}
+
+static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
+                                                  unsigned short *dst_right,
+                                                  unsigned short *src,
+                                                  unsigned int count,
+                                                  unsigned int tram_shift)
+{
+       // printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count);
+       if ((tram_shift & 1) == 0) {
+               while (count--) {
+                       *dst_left-- = *src++;
+                       *dst_right-- = *src++;
+               }
+       } else {
+               while (count--) {
+                       *dst_right-- = *src++;
+                       *dst_left-- = *src++;
+               }
+       }
+}
+
+static void fx8010_pb_trans_copy(snd_pcm_substream_t *substream,
+                                snd_pcm_indirect_t *rec, size_t bytes)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+       unsigned int tram_size = pcm->buffer_size;
+       unsigned short *src = (unsigned short *)(substream->runtime->dma_area + rec->sw_data);
+       unsigned int frames = bytes >> 2, count;
+       unsigned int tram_pos = pcm->tram_pos;
+       unsigned int tram_shift = pcm->tram_shift;
+
+       while (frames > tram_pos) {
+               count = tram_pos + 1;
+               snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
+                                                      (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
+                                                      src, count, tram_shift);
+               src += count * 2;
+               frames -= count;
+               tram_pos = (tram_size / 2) - 1;
+               tram_shift++;
+       }
+       snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
+                                              (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
+                                              src, frames, tram_shift++);
+       tram_pos -= frames;
+       pcm->tram_pos = tram_pos;
+       pcm->tram_shift = tram_shift;
+}
+
+static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+       snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy);
+       return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_hw_params(snd_pcm_substream_t * substream,
+                                                snd_pcm_hw_params_t * hw_params)
+{
+       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+}
+
+static int snd_emu10k1_fx8010_playback_hw_free(snd_pcm_substream_t * substream)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+       unsigned int i;
+
+       for (i = 0; i < pcm->channels; i++)
+               snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0);
+       snd_pcm_lib_free_pages(substream);
+       return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+       unsigned int i;
+       
+       // printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
+       memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec));
+       pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */
+       pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
+       pcm->tram_shift = 0;
+       snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_running, 0, 0);     /* reset */
+       snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);     /* reset */
+       snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_size, 0, runtime->buffer_size);
+       snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_ptr, 0, 0);         /* reset ptr number */
+       snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_count, 0, runtime->period_size);
+       snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_tmpcount, 0, runtime->period_size);
+       for (i = 0; i < pcm->channels; i++)
+               snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels));
+       return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream, int cmd)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+       int result = 0;
+
+       spin_lock(&emu->reg_lock);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               /* follow thru */
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+#ifdef EMU10K1_SET_AC3_IEC958
+       {
+               int i;
+               for (i = 0; i < 3; i++) {
+                       unsigned int bits;
+                       bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+                              SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
+                              0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA;
+                       snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits);
+               }
+       }
+#endif
+               result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq);
+               if (result < 0)
+                       goto __err;
+               snd_emu10k1_fx8010_playback_transfer(substream);        /* roll the ball */
+               snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL;
+               snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
+               pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
+               pcm->tram_shift = 0;
+               break;
+       default:
+               result = -EINVAL;
+               break;
+       }
+      __err:
+       spin_unlock(&emu->reg_lock);
+       return result;
+}
+
+static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t * substream)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+       size_t ptr; /* byte pointer */
+
+       if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0))
+               return 0;
+       ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0) << 2;
+       return snd_pcm_indirect_playback_pointer(substream, &pcm->pcm_rec, ptr);
+}
+
+static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
+{
+       .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+                                /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
+       .formats =              SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+       .rates =                SNDRV_PCM_RATE_48000,
+       .rate_min =             48000,
+       .rate_max =             48000,
+       .channels_min =         1,
+       .channels_max =         1,
+       .buffer_bytes_max =     (128*1024),
+       .period_bytes_min =     1024,
+       .period_bytes_max =     (128*1024),
+       .periods_min =          1,
+       .periods_max =          1024,
+       .fifo_size =            0,
+};
+
+static int snd_emu10k1_fx8010_playback_open(snd_pcm_substream_t * substream)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+       runtime->hw = snd_emu10k1_fx8010_playback;
+       runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels;
+       runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2;
+       spin_lock_irq(&emu->reg_lock);
+       if (pcm->valid == 0) {
+               spin_unlock_irq(&emu->reg_lock);
+               return -ENODEV;
+       }
+       pcm->opened = 1;
+       spin_unlock_irq(&emu->reg_lock);
+       return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+       spin_lock_irq(&emu->reg_lock);
+       pcm->opened = 0;
+       spin_unlock_irq(&emu->reg_lock);
+       return 0;
+}
+
+static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
+       .open =                 snd_emu10k1_fx8010_playback_open,
+       .close =                snd_emu10k1_fx8010_playback_close,
+       .ioctl =                snd_pcm_lib_ioctl,
+       .hw_params =            snd_emu10k1_fx8010_playback_hw_params,
+       .hw_free =              snd_emu10k1_fx8010_playback_hw_free,
+       .prepare =              snd_emu10k1_fx8010_playback_prepare,
+       .trigger =              snd_emu10k1_fx8010_playback_trigger,
+       .pointer =              snd_emu10k1_fx8010_playback_pointer,
+       .ack =                  snd_emu10k1_fx8010_playback_transfer,
+};
+
 static void snd_emu10k1_pcm_efx_free(snd_pcm_t *pcm)
 {
-       emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+       emu10k1_t *emu = pcm->private_data;
        emu->pcm_efx = NULL;
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1140,12 +1374,13 @@ int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm
        if (rpcm)
                *rpcm = NULL;
 
-       if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 0, 1, &pcm)) < 0)
+       if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0)
                return err;
 
        pcm->private_data = emu;
        pcm->private_free = snd_emu10k1_pcm_efx_free;
 
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
 
        pcm->info_flags = 0;
index 9582c31..994066c 100644 (file)
@@ -71,31 +71,32 @@ static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
 static void snd_emu10k1_proc_read(snd_info_entry_t *entry, 
                                  snd_info_buffer_t * buffer)
 {
-       static char *outputs[32] = {
-               /* 00 */ "PCM Left",
-               /* 01 */ "PCM Right",
-               /* 02 */ "PCM Surround Left",
-               /* 03 */ "PCM Surround Right",
-               /* 04 */ "MIDI Left",
-               /* 05 */ "MIDI Right",
-               /* 06 */ "PCM Center",
-               /* 07 */ "PCM LFE",
-               /* 08 */ "???",
-               /* 09 */ "???",
-               /* 10 */ "???",
-               /* 11 */ "???",
-               /* 12 */ "MIDI Reverb",
-               /* 13 */ "MIDI Chorus",
-               /* 14 */ "???",
+       /* FIXME - output names are in emufx.c too */
+       static char *creative_outs[32] = {
+               /* 00 */ "AC97 Left",
+               /* 01 */ "AC97 Right",
+               /* 02 */ "Optical IEC958 Left",
+               /* 03 */ "Optical IEC958 Right",
+               /* 04 */ "Center",
+               /* 05 */ "LFE",
+               /* 06 */ "Headphone Left",
+               /* 07 */ "Headphone Right",
+               /* 08 */ "Surround Left",
+               /* 09 */ "Surround Right",
+               /* 10 */ "PCM Capture Left",
+               /* 11 */ "PCM Capture Right",
+               /* 12 */ "MIC Capture",
+               /* 13 */ "AC97 Surround Left",
+               /* 14 */ "AC97 Surround Right",
                /* 15 */ "???",
                /* 16 */ "???",
-               /* 17 */ "???",
-               /* 18 */ "ADC Left / CDROM S/PDIF Left",
-               /* 19 */ "ADC Right / CDROM S/PDIF Right",
-               /* 20 */ "MIC / Zoom Video Left",
-               /* 21 */ "Zoom Video Right",
-               /* 22 */ "S/PDIF Left",
-               /* 23 */ "S/PDIF Right",
+               /* 17 */ "Analog Center",
+               /* 18 */ "Analog LFE",
+               /* 19 */ "???",
+               /* 20 */ "???",
+               /* 21 */ "???",
+               /* 22 */ "???",
+               /* 23 */ "???",
                /* 24 */ "???",
                /* 25 */ "???",
                /* 26 */ "???",
@@ -105,9 +106,78 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
                /* 30 */ "???",
                /* 31 */ "???"
        };
-       emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return);
+
+       static char *audigy_outs[64] = {
+               /* 00 */ "Digital Front Left",
+               /* 01 */ "Digital Front Right",
+               /* 02 */ "Digital Center",
+               /* 03 */ "Digital LEF",
+               /* 04 */ "Headphone Left",
+               /* 05 */ "Headphone Right",
+               /* 06 */ "Digital Rear Left",
+               /* 07 */ "Digital Rear Right",
+               /* 08 */ "Front Left",
+               /* 09 */ "Front Right",
+               /* 10 */ "Center",
+               /* 11 */ "LFE",
+               /* 12 */ "???",
+               /* 13 */ "???",
+               /* 14 */ "Rear Left",
+               /* 15 */ "Rear Right",
+               /* 16 */ "AC97 Front Left",
+               /* 17 */ "AC97 Front Right",
+               /* 18 */ "ADC Caputre Left",
+               /* 19 */ "ADC Capture Right",
+               /* 20 */ "???",
+               /* 21 */ "???",
+               /* 22 */ "???",
+               /* 23 */ "???",
+               /* 24 */ "???",
+               /* 25 */ "???",
+               /* 26 */ "???",
+               /* 27 */ "???",
+               /* 28 */ "???",
+               /* 29 */ "???",
+               /* 30 */ "???",
+               /* 31 */ "???",
+               /* 32 */ "???",
+               /* 33 */ "???",
+               /* 34 */ "???",
+               /* 35 */ "???",
+               /* 36 */ "???",
+               /* 37 */ "???",
+               /* 38 */ "???",
+               /* 39 */ "???",
+               /* 40 */ "???",
+               /* 41 */ "???",
+               /* 42 */ "???",
+               /* 43 */ "???",
+               /* 44 */ "???",
+               /* 45 */ "???",
+               /* 46 */ "???",
+               /* 47 */ "???",
+               /* 48 */ "???",
+               /* 49 */ "???",
+               /* 50 */ "???",
+               /* 51 */ "???",
+               /* 52 */ "???",
+               /* 53 */ "???",
+               /* 54 */ "???",
+               /* 55 */ "???",
+               /* 56 */ "???",
+               /* 57 */ "???",
+               /* 58 */ "???",
+               /* 59 */ "???",
+               /* 60 */ "???",
+               /* 61 */ "???",
+               /* 62 */ "???",
+               /* 33 */ "???"
+       };
+
+       emu10k1_t *emu = entry->private_data;
        unsigned int val;
        int nefx = emu->audigy ? 64 : 32;
+       char **outputs = emu->audigy ? audigy_outs : creative_outs;
        int idx;
        
        snd_iprintf(buffer, "EMU10K1\n\n");
@@ -117,7 +187,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
        snd_iprintf(buffer, "Card                  : %s\n",
                    emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative"));
        snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size);
-       snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", emu->fx8010.etram_pages.bytes);
+       snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes);
        snd_iprintf(buffer, "\n");
        if (emu->audigy) {
                snd_iprintf(buffer, "Effect Send Routing   : A=%i, B=%i, C=%i, D=%i\n",
@@ -135,7 +205,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
        snd_iprintf(buffer, "\nCaptured FX Outputs   :\n");
        for (idx = 0; idx < nefx; idx++) {
                if (emu->efx_voices_mask[idx/32] & (1 << (idx%32)))
-                       snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx%32]);
+                       snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx]);
        }
        snd_iprintf(buffer, "\nAll FX Outputs        :\n");
        for (idx = 0; idx < 32; idx++)
@@ -155,7 +225,7 @@ static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry,
                                        snd_info_buffer_t * buffer)
 {
        u32 pc;
-       emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return);
+       emu10k1_t *emu = entry->private_data;
 
        snd_iprintf(buffer, "FX8010 Instruction List '%s'\n", emu->fx8010.name);
        snd_iprintf(buffer, "  Code dump      :\n");
@@ -195,7 +265,7 @@ static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_
                                    unsigned long count, unsigned long pos)
 {
        long size;
-       emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return -ENXIO);
+       emu10k1_t *emu = entry->private_data;
        unsigned int offset;
        
        if (!strcmp(entry->name, "fx8010_tram_addr")) {
index 95f85d7..22d8e3d 100644 (file)
@@ -231,7 +231,7 @@ void snd_emu10k1_wait(emu10k1_t *emu, unsigned int wait)
 
 unsigned short snd_emu10k1_ac97_read(ac97_t *ac97, unsigned short reg)
 {
-       emu10k1_t *emu = snd_magic_cast(emu10k1_t, ac97->private_data, return -ENXIO);
+       emu10k1_t *emu = ac97->private_data;
        unsigned long flags;
        unsigned short val;
 
@@ -244,7 +244,7 @@ unsigned short snd_emu10k1_ac97_read(ac97_t *ac97, unsigned short reg)
 
 void snd_emu10k1_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short data)
 {
-       emu10k1_t *emu = snd_magic_cast(emu10k1_t, ac97->private_data, return);
+       emu10k1_t *emu = ac97->private_data;
        unsigned long flags;
 
        spin_lock_irqsave(&emu->emu_lock, flags);
index 17595a4..e960828 100644 (file)
@@ -32,7 +32,7 @@
 
 irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       emu10k1_t *emu = snd_magic_cast(emu10k1_t, dev_id, return IRQ_NONE);
+       emu10k1_t *emu = dev_id;
        unsigned int status, orig_status;
        int handled = 0;
 
index 90e6953..7a595f0 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <sound/driver.h>
+#include <linux/pci.h>
 #include <linux/time.h>
 #include <sound/core.h>
 #include <sound/emu10k1.h>
@@ -291,7 +292,7 @@ snd_util_memblk_t *
 snd_emu10k1_alloc_pages(emu10k1_t *emu, snd_pcm_substream_t *substream)
 {
        snd_pcm_runtime_t *runtime = substream->runtime;
-       struct snd_sg_buf *sgbuf = runtime->dma_private;
+       struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
        snd_util_memhdr_t *hdr;
        emu10k1_memblk_t *blk;
        int page, err, idx;
@@ -441,10 +442,11 @@ static int synth_alloc_pages(emu10k1_t *emu, emu10k1_memblk_t *blk)
        get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
        /* allocate kernel pages */
        for (page = first_page; page <= last_page; page++) {
-               if (snd_dma_alloc_pages(&emu->dma_dev, PAGE_SIZE, &dmab) < 0)
+               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci),
+                                       PAGE_SIZE, &dmab) < 0)
                        goto __fail;
                if (! is_valid_page(emu, dmab.addr)) {
-                       snd_dma_free_pages(&emu->dma_dev, &dmab);
+                       snd_dma_free_pages(&dmab);
                        goto __fail;
                }
                emu->page_addr_table[page] = dmab.addr;
@@ -459,7 +461,7 @@ __fail:
                dmab.area = emu->page_ptr_table[page];
                dmab.addr = emu->page_addr_table[page];
                dmab.bytes = PAGE_SIZE;
-               snd_dma_free_pages(&emu->dma_dev, &dmab);
+               snd_dma_free_pages(&dmab);
                emu->page_addr_table[page] = 0;
                emu->page_ptr_table[page] = NULL;
        }
@@ -476,13 +478,15 @@ static int synth_free_pages(emu10k1_t *emu, emu10k1_memblk_t *blk)
        struct snd_dma_buffer dmab;
 
        get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
+       dmab.dev.type = SNDRV_DMA_TYPE_DEV;
+       dmab.dev.dev = snd_dma_pci_data(emu->pci);
        for (page = first_page; page <= last_page; page++) {
                if (emu->page_ptr_table[page] == NULL)
                        continue;
                dmab.area = emu->page_ptr_table[page];
                dmab.addr = emu->page_addr_table[page];
                dmab.bytes = PAGE_SIZE;
-               snd_dma_free_pages(&emu->dma_dev, &dmab);
+               snd_dma_free_pages(&dmab);
                emu->page_addr_table[page] = 0;
                emu->page_ptr_table[page] = NULL;
        }
index 4a318a6..e601381 100644 (file)
@@ -33,7 +33,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 static void snd_ice1712_akm4xxx_lock(akm4xxx_t *ak, int chip)
 {
index c5670a1..a12a0b0 100644 (file)
                "{TerraTec,EWX 24/96},"\
                "{TerraTec,EWS 88MT},"\
                "{TerraTec,EWS 88D},"\
-               "{TerraTec,DMX 6Fire},"
+               "{TerraTec,DMX 6Fire},"\
+               "{TerraTec,Phase 88},"
 
 #define ICE1712_SUBDEVICE_EWX2496      0x3b153011
 #define ICE1712_SUBDEVICE_EWS88MT      0x3b151511
 #define ICE1712_SUBDEVICE_EWS88MT_NEW  0x3b152511
 #define ICE1712_SUBDEVICE_EWS88D       0x3b152b11
 #define ICE1712_SUBDEVICE_DMX6FIRE     0x3b153811
+#define ICE1712_SUBDEVICE_PHASE88      0x3b155111
 
 /* entry point */
 extern struct snd_ice1712_card_info snd_ice1712_ews_cards[];
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
new file mode 100644 (file)
index 0000000..25f827d
--- /dev/null
@@ -0,0 +1,849 @@
+/*
+ *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
+ *
+ *   Lowlevel functions for Pontis MS300
+ *
+ *     Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute 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 <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/info.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "pontis.h"
+
+/* I2C addresses */
+#define WM_DEV         0x34
+#define CS_DEV         0x20
+
+/* WM8776 registers */
+#define WM_HP_ATTEN_L          0x00    /* headphone left attenuation */
+#define WM_HP_ATTEN_R          0x01    /* headphone left attenuation */
+#define WM_HP_MASTER           0x02    /* headphone master (both channels), override LLR */
+#define WM_DAC_ATTEN_L         0x03    /* digital left attenuation */
+#define WM_DAC_ATTEN_R         0x04
+#define WM_DAC_MASTER          0x05
+#define WM_PHASE_SWAP          0x06    /* DAC phase swap */
+#define WM_DAC_CTRL1           0x07
+#define WM_DAC_MUTE            0x08
+#define WM_DAC_CTRL2           0x09
+#define WM_DAC_INT             0x0a
+#define WM_ADC_INT             0x0b
+#define WM_MASTER_CTRL         0x0c
+#define WM_POWERDOWN           0x0d
+#define WM_ADC_ATTEN_L         0x0e
+#define WM_ADC_ATTEN_R         0x0f
+#define WM_ALC_CTRL1           0x10
+#define WM_ALC_CTRL2           0x11
+#define WM_ALC_CTRL3           0x12
+#define WM_NOISE_GATE          0x13
+#define WM_LIMITER             0x14
+#define WM_ADC_MUX             0x15
+#define WM_OUT_MUX             0x16
+#define WM_RESET               0x17
+
+/*
+ * GPIO
+ */
+#define PONTIS_CS_CS           (1<<4)  /* CS */
+#define PONTIS_CS_CLK          (1<<5)  /* CLK */
+#define PONTIS_CS_RDATA                (1<<6)  /* CS8416 -> VT1720 */
+#define PONTIS_CS_WDATA                (1<<7)  /* VT1720 -> CS8416 */
+
+
+/*
+ * get the current register value of WM codec
+ */
+static unsigned short wm_get(ice1712_t *ice, int reg)
+{
+       reg <<= 1;
+       return ((unsigned short)ice->akm[0].images[reg] << 8) |
+               ice->akm[0].images[reg + 1];
+}
+
+/*
+ * set the register value of WM codec and remember it
+ */
+static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
+{
+       unsigned short cval;
+       cval = (reg << 9) | val;
+       snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
+}
+
+static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+{
+       wm_put_nocache(ice, reg, val);
+       reg <<= 1;
+       ice->akm[0].images[reg] = val >> 8;
+       ice->akm[0].images[reg + 1] = val;
+}
+
+/*
+ * DAC volume attenuation mixer control (-64dB to 0dB)
+ */
+
+#define DAC_0dB        0xff
+#define DAC_RES        128
+#define DAC_MIN        (DAC_0dB - DAC_RES)
+
+static int wm_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;   /* mute */
+       uinfo->value.integer.max = DAC_RES;     /* 0dB, 0.5dB step */
+       return 0;
+}
+
+static int wm_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned short val;
+       int i;
+
+       down(&ice->gpio_mutex);
+       for (i = 0; i < 2; i++) {
+               val = wm_get(ice, WM_DAC_ATTEN_L + i) & 0xff;
+               val = val > DAC_MIN ? (val - DAC_MIN) : 0;
+               ucontrol->value.integer.value[i] = val;
+       }
+       up(&ice->gpio_mutex);
+       return 0;
+}
+
+static int wm_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned short oval, nval;
+       int i, idx, change = 0;
+
+       down(&ice->gpio_mutex);
+       for (i = 0; i < 2; i++) {
+               nval = ucontrol->value.integer.value[i];
+               nval = (nval ? (nval + DAC_MIN) : 0) & 0xff;
+               idx = WM_DAC_ATTEN_L + i;
+               oval = wm_get(ice, idx) & 0xff;
+               if (oval != nval) {
+                       wm_put(ice, idx, nval);
+                       wm_put_nocache(ice, idx, nval | 0x100);
+                       change = 1;
+               }
+       }
+       up(&ice->gpio_mutex);
+       return change;
+}
+
+/*
+ * ADC gain mixer control (-64dB to 0dB)
+ */
+
+#define ADC_0dB        0xcf
+#define ADC_RES        128
+#define ADC_MIN        (ADC_0dB - ADC_RES)
+
+static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;   /* mute (-64dB) */
+       uinfo->value.integer.max = ADC_RES;     /* 0dB, 0.5dB step */
+       return 0;
+}
+
+static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned short val;
+       int i;
+
+       down(&ice->gpio_mutex);
+       for (i = 0; i < 2; i++) {
+               val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff;
+               val = val > ADC_MIN ? (val - ADC_MIN) : 0;
+               ucontrol->value.integer.value[i] = val;
+       }
+       up(&ice->gpio_mutex);
+       return 0;
+}
+
+static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned short ovol, nvol;
+       int i, idx, change = 0;
+
+       down(&ice->gpio_mutex);
+       for (i = 0; i < 2; i++) {
+               nvol = ucontrol->value.integer.value[i];
+               nvol = nvol ? (nvol + ADC_MIN) : 0;
+               idx  = WM_ADC_ATTEN_L + i;
+               ovol = wm_get(ice, idx) & 0xff;
+               if (ovol != nvol) {
+                       wm_put(ice, idx, nvol);
+                       change = 1;
+               }
+       }
+       up(&ice->gpio_mutex);
+       return change;
+}
+
+/*
+ * ADC input mux mixer control
+ */
+static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       int bit = kcontrol->private_value;
+
+       down(&ice->gpio_mutex);
+       ucontrol->value.integer.value[0] = (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0;
+       up(&ice->gpio_mutex);
+       return 0;
+}
+
+static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       int bit = kcontrol->private_value;
+       unsigned short oval, nval;
+       int change;
+
+       down(&ice->gpio_mutex);
+       nval = oval = wm_get(ice, WM_ADC_MUX);
+       if (ucontrol->value.integer.value[0])
+               nval |= (1 << bit);
+       else
+               nval &= ~(1 << bit);
+       change = nval != oval;
+       if (change) {
+               wm_put(ice, WM_ADC_MUX, nval);
+       }
+       up(&ice->gpio_mutex);
+       return 0;
+}
+
+/*
+ * Analog bypass (In -> Out)
+ */
+static int wm_bypass_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int wm_bypass_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+       down(&ice->gpio_mutex);
+       ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0;
+       up(&ice->gpio_mutex);
+       return 0;
+}
+
+static int wm_bypass_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned short val, oval;
+       int change = 0;
+
+       down(&ice->gpio_mutex);
+       val = oval = wm_get(ice, WM_OUT_MUX);
+       if (ucontrol->value.integer.value[0])
+               val |= 0x04;
+       else
+               val &= ~0x04;
+       if (val != oval) {
+               wm_put(ice, WM_OUT_MUX, val);
+               change = 1;
+       }
+       up(&ice->gpio_mutex);
+       return change;
+}
+
+/*
+ * Left/Right swap
+ */
+static int wm_chswap_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int wm_chswap_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+       down(&ice->gpio_mutex);
+       ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90;
+       up(&ice->gpio_mutex);
+       return 0;
+}
+
+static int wm_chswap_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned short val, oval;
+       int change = 0;
+
+       down(&ice->gpio_mutex);
+       oval = wm_get(ice, WM_DAC_CTRL1);
+       val = oval & 0x0f;
+       if (ucontrol->value.integer.value[0])
+               val |= 0x60;
+       else
+               val |= 0x90;
+       if (val != oval) {
+               wm_put(ice, WM_DAC_CTRL1, val);
+               wm_put_nocache(ice, WM_DAC_CTRL1, val);
+               change = 1;
+       }
+       up(&ice->gpio_mutex);
+       return change;
+}
+
+/*
+ * write data in the SPI mode
+ */
+static void set_gpio_bit(ice1712_t *ice, unsigned int bit, int val)
+{
+       unsigned int tmp = snd_ice1712_gpio_read(ice);
+       if (val)
+               tmp |= bit;
+       else
+               tmp &= ~bit;
+       snd_ice1712_gpio_write(ice, tmp);
+}
+
+static void spi_send_byte(ice1712_t *ice, unsigned char data)
+{
+       int i;
+       for (i = 0; i < 8; i++) {
+               set_gpio_bit(ice, PONTIS_CS_CLK, 0);
+               udelay(1);
+               set_gpio_bit(ice, PONTIS_CS_WDATA, data & 0x80);
+               udelay(1);
+               set_gpio_bit(ice, PONTIS_CS_CLK, 1);
+               udelay(1);
+               data <<= 1;
+       }
+}
+
+static unsigned int spi_read_byte(ice1712_t *ice)
+{
+       int i;
+       unsigned int val = 0;
+
+       for (i = 0; i < 8; i++) {
+               val <<= 1;
+               set_gpio_bit(ice, PONTIS_CS_CLK, 0);
+               udelay(1);
+               if (snd_ice1712_gpio_read(ice) & PONTIS_CS_RDATA)
+                       val |= 1;
+               udelay(1);
+               set_gpio_bit(ice, PONTIS_CS_CLK, 1);
+               udelay(1);
+       }
+       return val;
+}
+
+
+static void spi_write(ice1712_t *ice, unsigned int dev, unsigned int reg, unsigned int data)
+{
+       snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK);
+       snd_ice1712_gpio_set_mask(ice, ~(PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK));
+       set_gpio_bit(ice, PONTIS_CS_CS, 0);
+       spi_send_byte(ice, dev & ~1); /* WRITE */
+       spi_send_byte(ice, reg); /* MAP */
+       spi_send_byte(ice, data); /* DATA */
+       /* trigger */
+       set_gpio_bit(ice, PONTIS_CS_CS, 1);
+       udelay(1);
+       /* restore */
+       snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
+       snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+}
+
+static unsigned int spi_read(ice1712_t *ice, unsigned int dev, unsigned int reg)
+{
+       unsigned int val;
+       snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK);
+       snd_ice1712_gpio_set_mask(ice, ~(PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK));
+       set_gpio_bit(ice, PONTIS_CS_CS, 0);
+       spi_send_byte(ice, dev & ~1); /* WRITE */
+       spi_send_byte(ice, reg); /* MAP */
+       /* trigger */
+       set_gpio_bit(ice, PONTIS_CS_CS, 1);
+       udelay(1);
+       set_gpio_bit(ice, PONTIS_CS_CS, 0);
+       spi_send_byte(ice, dev | 1); /* READ */
+       val = spi_read_byte(ice);
+       /* trigger */
+       set_gpio_bit(ice, PONTIS_CS_CS, 1);
+       udelay(1);
+       /* restore */
+       snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
+       snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+       return val;
+}
+
+
+/*
+ * SPDIF input source
+ */
+static int cs_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       static char *texts[] = {
+               "Coax",         /* RXP0 */
+               "Optical",      /* RXP1 */
+               "CD",           /* RXP2 */
+       };
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 3;
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int cs_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+       down(&ice->gpio_mutex);
+       ucontrol->value.enumerated.item[0] = ice->gpio.saved[0];
+       up(&ice->gpio_mutex);
+       return 0;
+}
+
+static int cs_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned char val;
+       int change = 0;
+
+       down(&ice->gpio_mutex);
+       if (ucontrol->value.enumerated.item[0] != ice->gpio.saved[0]) {
+               ice->gpio.saved[0] = ucontrol->value.enumerated.item[0] & 3;
+               val = 0x80 | (ice->gpio.saved[0] << 3);
+               spi_write(ice, CS_DEV, 0x04, val);
+               change = 1;
+       }
+       up(&ice->gpio_mutex);
+       return 0;
+}
+
+
+/*
+ * GPIO controls
+ */
+static int pontis_gpio_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 0xffff; /* 16bit */
+       return 0;
+}
+
+static int pontis_gpio_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       down(&ice->gpio_mutex);
+       /* 4-7 reserved */
+       ucontrol->value.integer.value[0] = (~ice->gpio.write_mask & 0xffff) | 0x00f0;
+       up(&ice->gpio_mutex);
+       return 0;
+}
+       
+static int pontis_gpio_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned int val;
+       int changed;
+       down(&ice->gpio_mutex);
+       /* 4-7 reserved */
+       val = (~ucontrol->value.integer.value[0] & 0xffff) | 0x00f0;
+       changed = val != ice->gpio.write_mask;
+       ice->gpio.write_mask = val;
+       up(&ice->gpio_mutex);
+       return changed;
+}
+
+static int pontis_gpio_dir_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       down(&ice->gpio_mutex);
+       /* 4-7 reserved */
+       ucontrol->value.integer.value[0] = ice->gpio.direction & 0xff0f;
+       up(&ice->gpio_mutex);
+       return 0;
+}
+       
+static int pontis_gpio_dir_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned int val;
+       int changed;
+       down(&ice->gpio_mutex);
+       /* 4-7 reserved */
+       val = ucontrol->value.integer.value[0] & 0xff0f;
+       changed = (val != ice->gpio.direction);
+       ice->gpio.direction = val;
+       up(&ice->gpio_mutex);
+       return changed;
+}
+
+static int pontis_gpio_data_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       down(&ice->gpio_mutex);
+       snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+       snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
+       ucontrol->value.integer.value[0] = snd_ice1712_gpio_read(ice) & 0xffff;
+       up(&ice->gpio_mutex);
+       return 0;
+}
+
+static int pontis_gpio_data_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned int val, nval;
+       int changed = 0;
+       down(&ice->gpio_mutex);
+       snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+       snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
+       val = snd_ice1712_gpio_read(ice) & 0xffff;
+       nval = ucontrol->value.integer.value[0] & 0xffff;
+       if (val != nval) {
+               snd_ice1712_gpio_write(ice, nval);
+               changed = 1;
+       }
+       up(&ice->gpio_mutex);
+       return changed;
+}
+
+/*
+ * mixers
+ */
+
+static snd_kcontrol_new_t pontis_controls[] __devinitdata = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "PCM Playback Volume",
+               .info = wm_dac_vol_info,
+               .get = wm_dac_vol_get,
+               .put = wm_dac_vol_put,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Capture Volume",
+               .info = wm_adc_vol_info,
+               .get = wm_adc_vol_get,
+               .put = wm_adc_vol_put,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "CD Capture Switch",
+               .info = wm_adc_mux_info,
+               .get = wm_adc_mux_get,
+               .put = wm_adc_mux_put,
+               .private_value = 0,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Line Capture Switch",
+               .info = wm_adc_mux_info,
+               .get = wm_adc_mux_get,
+               .put = wm_adc_mux_put,
+               .private_value = 1,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Analog Bypass Switch",
+               .info = wm_bypass_info,
+               .get = wm_bypass_get,
+               .put = wm_bypass_put,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Swap Output Channels",
+               .info = wm_chswap_info,
+               .get = wm_chswap_get,
+               .put = wm_chswap_put,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "IEC958 Input Source",
+               .info = cs_source_info,
+               .get = cs_source_get,
+               .put = cs_source_put,
+       },
+       /* FIXME: which interface? */
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+               .name = "GPIO Mask",
+               .info = pontis_gpio_mask_info,
+               .get = pontis_gpio_mask_get,
+               .put = pontis_gpio_mask_put,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+               .name = "GPIO Direction",
+               .info = pontis_gpio_mask_info,
+               .get = pontis_gpio_dir_get,
+               .put = pontis_gpio_dir_put,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+               .name = "GPIO Data",
+               .info = pontis_gpio_mask_info,
+               .get = pontis_gpio_data_get,
+               .put = pontis_gpio_data_put,
+       },
+};
+
+
+/*
+ * WM codec registers
+ */
+static void wm_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+       ice1712_t *ice = (ice1712_t *)entry->private_data;
+       char line[64];
+       unsigned int reg, val;
+       down(&ice->gpio_mutex);
+       while (!snd_info_get_line(buffer, line, sizeof(line))) {
+               if (sscanf(line, "%x %x", &reg, &val) != 2)
+                       continue;
+               if (reg <= 0x17 && val <= 0xffff)
+                       wm_put(ice, reg, val);
+       }
+       up(&ice->gpio_mutex);
+}
+
+static void wm_proc_regs_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+       ice1712_t *ice = (ice1712_t *)entry->private_data;
+       int reg, val;
+
+       down(&ice->gpio_mutex);
+       for (reg = 0; reg <= 0x17; reg++) {
+               val = wm_get(ice, reg);
+               snd_iprintf(buffer, "%02x = %04x\n", reg, val);
+       }
+       up(&ice->gpio_mutex);
+}
+
+static void wm_proc_init(ice1712_t *ice)
+{
+       snd_info_entry_t *entry;
+       if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) {
+               snd_info_set_text_ops(entry, ice, 1024, wm_proc_regs_read);
+               entry->mode |= S_IWUSR;
+               entry->c.text.write_size = 1024;
+               entry->c.text.write = wm_proc_regs_write;
+       }
+}
+
+static void cs_proc_regs_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+       ice1712_t *ice = (ice1712_t *)entry->private_data;
+       int reg, val;
+
+       down(&ice->gpio_mutex);
+       for (reg = 0; reg <= 0x26; reg++) {
+               val = spi_read(ice, CS_DEV, reg);
+               snd_iprintf(buffer, "%02x = %02x\n", reg, val);
+       }
+       val = spi_read(ice, CS_DEV, 0x7f);
+       snd_iprintf(buffer, "%02x = %02x\n", 0x7f, val);
+       up(&ice->gpio_mutex);
+}
+
+static void cs_proc_init(ice1712_t *ice)
+{
+       snd_info_entry_t *entry;
+       if (! snd_card_proc_new(ice->card, "cs_codec", &entry)) {
+               snd_info_set_text_ops(entry, ice, 1024, cs_proc_regs_read);
+       }
+}
+
+
+static int __devinit pontis_add_controls(ice1712_t *ice)
+{
+       unsigned int i;
+       int err;
+
+       for (i = 0; i < ARRAY_SIZE(pontis_controls); i++) {
+               err = snd_ctl_add(ice->card, snd_ctl_new1(&pontis_controls[i], ice));
+               if (err < 0)
+                       return err;
+       }
+
+       wm_proc_init(ice);
+       cs_proc_init(ice);
+
+       return 0;
+}
+
+
+/*
+ * initialize the chip
+ */
+static int __devinit pontis_init(ice1712_t *ice)
+{
+       static unsigned short wm_inits[] = {
+               /* These come first to reduce init pop noise */
+               WM_ADC_MUX,     0x00c0, /* ADC mute */
+               WM_DAC_MUTE,    0x0001, /* DAC softmute */
+               WM_DAC_CTRL1,   0x0000, /* DAC mute */
+
+               WM_POWERDOWN,   0x0008, /* All power-up except HP */
+               WM_RESET,       0x0000, /* reset */
+       };
+       static unsigned short wm_inits2[] = {
+               WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */
+               WM_DAC_INT,     0x0022, /* I2S, normal polarity, 24bit */
+               WM_ADC_INT,     0x0022, /* I2S, normal polarity, 24bit */
+               WM_DAC_CTRL1,   0x0090, /* DAC L/R */
+               WM_OUT_MUX,     0x0001, /* OUT DAC */
+               WM_HP_ATTEN_L,  0x0179, /* HP 0dB */
+               WM_HP_ATTEN_R,  0x0179, /* HP 0dB */
+               WM_DAC_ATTEN_L, 0x0000, /* DAC 0dB */
+               WM_DAC_ATTEN_L, 0x0100, /* DAC 0dB */
+               WM_DAC_ATTEN_R, 0x0000, /* DAC 0dB */
+               WM_DAC_ATTEN_R, 0x0100, /* DAC 0dB */
+               // WM_DAC_MASTER,       0x0100, /* DAC master muted */
+               WM_PHASE_SWAP,  0x0000, /* phase normal */
+               WM_DAC_CTRL2,   0x0000, /* no deemphasis, no ZFLG */
+               WM_ADC_ATTEN_L, 0x0000, /* ADC muted */
+               WM_ADC_ATTEN_R, 0x0000, /* ADC muted */
+#if 0
+               WM_ALC_CTRL1,   0x007b, /* */
+               WM_ALC_CTRL2,   0x0000, /* */
+               WM_ALC_CTRL3,   0x0000, /* */
+               WM_NOISE_GATE,  0x0000, /* */
+#endif
+               WM_DAC_MUTE,    0x0000, /* DAC unmute */
+               WM_ADC_MUX,     0x0003, /* ADC unmute, both CD/Line On */
+       };
+       static unsigned char cs_inits[] = {
+               0x04,   0x80,   /* RUN, RXP0 */
+               0x05,   0x05,   /* slave, 24bit */
+               0x01,   0x00,
+               0x02,   0x00,
+               0x03,   0x00,
+       };
+       unsigned int i;
+
+       ice->vt1720 = 1;
+       ice->num_total_dacs = 2;
+       ice->num_total_adcs = 2;
+
+       /* to remeber the register values */
+       ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+       if (! ice->akm)
+               return -ENOMEM;
+       ice->akm_codecs = 1;
+
+       /* HACK - use this as the SPDIF source.
+        * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten
+        */
+       ice->gpio.saved[0] = 0;
+
+       /* initialize WM8776 codec */
+       for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2)
+               wm_put(ice, wm_inits[i], wm_inits[i+1]);
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout(1);
+       for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2)
+               wm_put(ice, wm_inits2[i], wm_inits2[i+1]);
+
+       /* initialize CS8416 codec */
+       /* assert PRST#; MT05 bit 7 */
+       outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));
+       mdelay(5);
+       /* deassert PRST# */
+       outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));
+
+       for (i = 0; i < ARRAY_SIZE(cs_inits); i += 2)
+               spi_write(ice, CS_DEV, cs_inits[i], cs_inits[i+1]);
+
+       return 0;
+}
+
+
+/*
+ * Pontis boards don't provide the EEPROM data at all.
+ * hence the driver needs to sets up it properly.
+ */
+
+static unsigned char pontis_eeprom[] __devinitdata = {
+       0x08,   /* SYSCONF: clock 256, mpu401, spdif-in/ADC, 1DAC */
+       0x80,   /* ACLINK: I2S */
+       0xf8,   /* I2S: vol, 96k, 24bit, 192k */
+       0xc3,   /* SPDIF: out-en, out-int, spdif-in */
+       0x07,   /* GPIO_DIR */
+       0x00,   /* GPIO_DIR1 */
+       0x00,   /* GPIO_DIR2 (ignored) */
+       0x0f,   /* GPIO_MASK (4-7 reserved for CS8416) */
+       0xff,   /* GPIO_MASK1 */
+       0x00,   /* GPIO_MASK2 (ignored) */
+       0x06,   /* GPIO_STATE (0-low, 1-high, 2-high) */
+       0x00,   /* GPIO_STATE1 */
+       0x00,   /* GPIO_STATE2 (ignored) */
+};
+
+/* entry point */
+struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = {
+       {
+               .subvendor = VT1720_SUBDEVICE_PONTIS_MS300,
+               .name = "Pontis MS300",
+               .model = "ms300",
+               .chip_init = pontis_init,
+               .build_controls = pontis_add_controls,
+               .eeprom_size = sizeof(pontis_eeprom),
+               .eeprom_data = pontis_eeprom,
+       },
+       { } /* terminator */
+};
diff --git a/sound/pci/ice1712/pontis.h b/sound/pci/ice1712/pontis.h
new file mode 100644 (file)
index 0000000..d0d1378
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __SOUND_PONTIS_H
+#define __SOUND_PONTIS_H
+
+/*
+ *   ALSA driver for VIA VT1724 (Envy24HT)
+ *
+ *   Lowlevel functions for Pontis MS300 boards
+ *
+ *     Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute 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
+ *
+ */      
+
+#define PONTIS_DEVICE_DESC            "{Pontis,MS300},"
+
+#define VT1720_SUBDEVICE_PONTIS_MS300  0x00020002      /* a dummy id for MS300 */
+
+extern struct snd_ice1712_card_info  snd_vt1720_pontis_cards[];
+
+#endif /* __SOUND_PONTIS_H */
diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
new file mode 100644 (file)
index 0000000..868f6fe
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *   ALSA driver for VT1720/VT1724 (Envy24PT/Envy24HT)
+ *
+ *   Lowlevel functions for VT1720-based motherboards
+ *
+ *     Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute 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 <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "vt1720_mobo.h"
+
+
+static int __devinit k8x800_init(ice1712_t *ice)
+{
+       ice->vt1720 = 1;
+
+       /* VT1616 codec */
+       ice->num_total_dacs = 6;
+       ice->num_total_adcs = 2;
+
+       /* WM8728 codec */
+       /* FIXME: TODO */
+
+       return 0;
+}
+
+static int __devinit k8x800_add_controls(ice1712_t *ice)
+{
+       /* FIXME: needs some quirks for VT1616? */
+       return 0;
+}
+
+/* EEPROM image */
+
+static unsigned char k8x800_eeprom[] __devinitdata = {
+       0x01,   /* SYSCONF: clock 256, 1ADC, 2DACs */
+       0x02,   /* ACLINK: ACLINK, packed */
+       0x00,   /* I2S: - */
+       0x00,   /* SPDIF: - */
+       0xff,   /* GPIO_DIR */
+       0xff,   /* GPIO_DIR1 */
+       0x00,   /* - */
+       0xff,   /* GPIO_MASK */
+       0xff,   /* GPIO_MASK1 */
+       0x00,   /* - */
+       0x00,   /* GPIO_STATE */
+       0x00,   /* GPIO_STATE1 */
+       0x00,   /* - */
+};
+
+
+/* entry point */
+struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
+       {
+               .subvendor = VT1720_SUBDEVICE_K8X800,
+               .name = "Albatron K8X800 Pro II",
+               .model = "k8x800",
+               .chip_init = k8x800_init,
+               .build_controls = k8x800_add_controls,
+               .eeprom_size = sizeof(k8x800_eeprom),
+               .eeprom_data = k8x800_eeprom,
+       },
+       {
+               .subvendor = VT1720_SUBDEVICE_ZNF3_150,
+               .name = "Chaintech ZNF3-150",
+               /* identical with k8x800 */
+               .chip_init = k8x800_init,
+               .build_controls = k8x800_add_controls,
+               .eeprom_size = sizeof(k8x800_eeprom),
+               .eeprom_data = k8x800_eeprom,
+       },
+       {
+               .subvendor = VT1720_SUBDEVICE_ZNF3_250,
+               .name = "Chaintech ZNF3-250",
+               /* identical with k8x800 */
+               .chip_init = k8x800_init,
+               .build_controls = k8x800_add_controls,
+               .eeprom_size = sizeof(k8x800_eeprom),
+               .eeprom_data = k8x800_eeprom,
+       },
+       { } /* terminator */
+};
+
diff --git a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h
new file mode 100644 (file)
index 0000000..552be2c
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef __SOUND_VT1720_MOBO_H
+#define __SOUND_VT1720_MOBO_H
+
+/*
+ *   ALSA driver for VT1720/VT1724 (Envy24PT/Envy24HT)
+ *
+ *   Lowlevel functions for VT1720-based motherboards
+ *
+ *     Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute 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
+ *
+ */      
+
+#define VT1720_MOBO_DEVICE_DESC        "{Albatron,K8X800 Pro II},"\
+                                      "{Chaintech,ZNF3-150},"\
+                                      "{Chaintech,ZNF3-250},"
+
+#define VT1720_SUBDEVICE_K8X800                0xf217052c
+#define VT1720_SUBDEVICE_ZNF3_150      0x0f2741f6
+#define VT1720_SUBDEVICE_ZNF3_250      0x0f2745f6
+
+extern struct snd_ice1712_card_info  snd_vt1720_mobo_cards[];
+
+#endif /* __SOUND_VT1720_MOBO_H */
index 573cdc0..2c2df37 100644 (file)
@@ -115,7 +115,6 @@ struct snd_mixart_mgr {
        snd_hwdep_t *hwdep;
        unsigned int board_type;      /* read from embedded once elf file is loaded, 250 = miXart8, 251 = with AES, 252 = with Cobranet */
 
-       struct snd_dma_device dma_dev;
        struct snd_dma_buffer flowinfo;
        struct snd_dma_buffer bufferinfo;
 
index fab3211..1f588ee 100644 (file)
@@ -379,7 +379,7 @@ void snd_mixart_msg_tasklet( unsigned long arg)
                                        snd_printk(KERN_ERR "tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n", mixart_msg_data[0]);
                                break;
                        default:
-                               snd_printdd("tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%d)\n",
+                               snd_printdd("tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
                                           msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size);
                                break;
                        }
@@ -403,7 +403,7 @@ void snd_mixart_msg_tasklet( unsigned long arg)
 
 irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, dev_id, return IRQ_NONE);
+       mixart_mgr_t *mgr = dev_id;
        int err;
        mixart_msg_t resp;
 
index 0c0215d..b6724c7 100644 (file)
@@ -146,7 +146,7 @@ static int mixart_load_elf(mixart_mgr_t *mgr, snd_hwdep_dsp_image_t *dsp )
 
 static int mixart_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
 {
-       mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, hw->private_data, return -ENXIO);
+       mixart_mgr_t *mgr = hw->private_data;
 
        strcpy(info->id, "miXart");
         info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX;
@@ -346,7 +346,7 @@ static int mixart_first_init(mixart_mgr_t *mgr)
 
 static int mixart_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
 {
-       mixart_mgr_t* mgr = snd_magic_cast(mixart_mgr_t, hw->private_data, return -ENXIO);
+       mixart_mgr_t* mgr = hw->private_data;
        int           err, card_index;
        u32           status_xilinx, status_elf, status_daught;
        u32           val;
index 592b979..39c1541 100644 (file)
@@ -31,8 +31,6 @@
 #include <sound/control.h>
 #include "mixart_mixer.h"
 
-#define chip_t mixart_t
-
 static u32 mixart_analog_level[256] = {
        0xc2c00000,             /* [000] -96.0 dB */
        0xc2bf0000,             /* [001] -95.5 dB */
index 3c79110..6fd58f1 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <sound/driver.h>
 #include <asm/io.h>
+#include <linux/pci.h>
 #include <linux/time.h>
 #include <sound/core.h>
 #include <sound/trident.h>
@@ -189,7 +190,7 @@ snd_trident_alloc_sg_pages(trident_t *trident, snd_pcm_substream_t *substream)
        snd_util_memblk_t *blk;
        snd_pcm_runtime_t *runtime = substream->runtime;
        int idx, page;
-       struct snd_sg_buf *sgbuf = runtime->dma_private;
+       struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 
        snd_assert(runtime->dma_bytes > 0 && runtime->dma_bytes <= SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL);
        hdr = trident->tlb.memhdr;
@@ -274,7 +275,7 @@ snd_trident_alloc_pages(trident_t *trident, snd_pcm_substream_t *substream)
 {
        snd_assert(trident != NULL, return NULL);
        snd_assert(substream != NULL, return NULL);
-       if (substream->dma_device.type == SNDRV_DMA_TYPE_DEV_SG)
+       if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_SG)
                return snd_trident_alloc_sg_pages(trident, substream);
        else
                return snd_trident_alloc_cont_pages(trident, substream);
@@ -367,10 +368,12 @@ static void clear_tlb(trident_t *trident, int page)
        set_silent_tlb(trident, page);
        if (ptr) {
                struct snd_dma_buffer dmab;
+               dmab.dev.type = SNDRV_DMA_TYPE_DEV;
+               dmab.dev.dev = snd_dma_pci_data(trident->pci);
                dmab.area = ptr;
                dmab.addr = addr;
                dmab.bytes = ALIGN_PAGE_SIZE;
-               snd_dma_free_pages(&trident->dma_dev, &dmab);
+               snd_dma_free_pages(&dmab);
        }
 }
 
@@ -412,10 +415,11 @@ static int synth_alloc_pages(trident_t *hw, snd_util_memblk_t *blk)
         * fortunately Trident page size and kernel PAGE_SIZE is identical!
         */
        for (page = first_page; page <= last_page; page++) {
-               if (snd_dma_alloc_pages(&hw->dma_dev, ALIGN_PAGE_SIZE, &dmab) < 0)
+               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(hw->pci),
+                                       ALIGN_PAGE_SIZE, &dmab) < 0)
                        goto __fail;
                if (! is_valid_page(dmab.addr)) {
-                       snd_dma_free_pages(&hw->dma_dev, &dmab);
+                       snd_dma_free_pages(&dmab);
                        goto __fail;
                }
                set_tlb_bus(hw, page, (unsigned long)dmab.area, dmab.addr);
index 8f9797d..72d36b1 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/io.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/pci.h>
 #include <sound/core.h>
 #include <sound/trident.h>
 #include <sound/seq_device.h>
@@ -506,7 +507,7 @@ static void sample_private1(trident_t * trident, snd_trident_voice_t * voice, un
 static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t * instr,
                                         char __user *data, long len, int atomic)
 {
-       trident_t *trident = snd_magic_cast(trident_t, private_data, return -ENXIO);
+       trident_t *trident = private_data;
        int size = instr->size;
        int shift = 0;
 
@@ -540,12 +541,12 @@ static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t
                instr->address.memory = memblk->offset;
        } else {
                struct snd_dma_buffer dmab;
-
-               if (snd_dma_alloc_pages(&trident->dma_dev, size, &dmab) < 0)
+               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
+                                       size, &dmab) < 0)
                        return -ENOMEM;
 
                if (copy_from_user(dmab.area, data, size)) {
-                       snd_dma_free_pages(&trident->dma_dev, &dmab);
+                       snd_dma_free_pages(&dmab);
                        return -EFAULT;
                }
                instr->address.ptr = dmab.area;
@@ -559,7 +560,7 @@ static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t
 static int snd_trident_simple_get_sample(void *private_data, simple_instrument_t * instr,
                                         char __user *data, long len, int atomic)
 {
-       //trident_t *trident = snd_magic_cast(trident_t, private_data, return -ENXIO);
+       //trident_t *trident = private_data;
        int size = instr->size;
        int shift = 0;
 
@@ -580,9 +581,14 @@ static int snd_trident_simple_get_sample(void *private_data, simple_instrument_t
 static int snd_trident_simple_remove_sample(void *private_data, simple_instrument_t * instr,
                                            int atomic)
 {
-       trident_t *trident = snd_magic_cast(trident_t, private_data, return -ENXIO);
+       trident_t *trident = private_data;
        int size = instr->size;
 
+       if (instr->format & SIMPLE_WAVE_16BIT)
+               size <<= 1;
+       if (instr->format & SIMPLE_WAVE_STEREO)
+               size <<= 1;
+
        if (trident->tlb.entries) {
                snd_util_memblk_t *memblk = (snd_util_memblk_t*)instr->address.ptr;
                if (memblk)
@@ -590,14 +596,15 @@ static int snd_trident_simple_remove_sample(void *private_data, simple_instrumen
                else
                        return -EFAULT;
        } else {
-               kfree(instr->address.ptr);
+               struct snd_dma_buffer dmab;
+               dmab.dev.type = SNDRV_DMA_TYPE_DEV;
+               dmab.dev.dev = snd_dma_pci_data(trident->pci);
+               dmab.area = instr->address.ptr;
+               dmab.addr = instr->address.memory;
+               dmab.bytes = size;
+               snd_dma_free_pages(&dmab);
        }
 
-       if (instr->format & SIMPLE_WAVE_16BIT)
-               size <<= 1;
-       if (instr->format & SIMPLE_WAVE_STEREO)
-               size <<= 1;
-
        trident->synth.current_size -= size;
        if (trident->synth.current_size < 0)    /* shouldn't need this check... */
                trident->synth.current_size = 0;
@@ -838,7 +845,7 @@ static void snd_trident_synth_instr_notify(void *private_data,
                                           int what)
 {
        int idx;
-       trident_t *trident = snd_magic_cast(trident_t, private_data, return);
+       trident_t *trident = private_data;
        snd_trident_voice_t *pvoice;
        unsigned long flags;
 
index b30c9d3..18478ae 100644 (file)
@@ -28,8 +28,8 @@ struct snd_vx222 {
        vx_core_t core;
 
        /* h/w config; for PLX and for DSP */
+       struct pci_dev *pci;
        unsigned long port[2];
-       struct resource *port_res[2];
 
        unsigned int regCDSP;   /* current CDSP register */
        unsigned int regCFG;    /* current CFG register */
index c9dfb2b..4c669cf 100644 (file)
@@ -27,8 +27,6 @@
 #include <asm/io.h>
 #include "vx222.h"
 
-#define chip_t vx_core_t
-
 
 static int vx2_reg_offset[VX_REG_MAX] = {
        [VX_ICR]    = 0x00,
index 2aa9042..0a954dc 100644 (file)
@@ -28,8 +28,6 @@
 #include <sound/asoundef.h>
 #include "pdaudiocf.h"
 
-#define chip_t pdacf_t
-
 
 /*
  * we use a vmalloc'ed (sg-)buffer
@@ -331,7 +329,7 @@ static snd_pcm_ops_t pdacf_pcm_capture_ops = {
  */
 static void snd_pdacf_pcm_free(snd_pcm_t *pcm)
 {
-       pdacf_t *chip = snd_magic_cast(pdacf_t, pcm->private_data, return);
+       pdacf_t *chip = pcm->private_data;
        chip->pcm = NULL;
 }
 
index e015800..f697a10 100644 (file)
@@ -69,13 +69,13 @@ static int snd_vxpocket_free(vx_core_t *chip)
                hw->card_list[vxp->index] = NULL;
        chip->card = NULL;
 
-       snd_magic_kfree(chip);
+       kfree(chip);
        return 0;
 }
 
 static int snd_vxpocket_dev_free(snd_device_t *device)
 {
-       vx_core_t *chip = snd_magic_cast(vx_core_t, device->device_data, return -ENXIO);
+       vx_core_t *chip = device->device_data;
        return snd_vxpocket_free(chip);
 }
 
@@ -121,7 +121,7 @@ dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw)
                return NULL;
 
        if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) {
-               snd_magic_kfree(chip);
+               kfree(chip);
                snd_card_free(card);
                return NULL;
        }
@@ -226,7 +226,7 @@ static int snd_vxpocket_assign_resources(vx_core_t *chip, int port, int irq)
  */
 void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link)
 {
-       vx_core_t *chip = snd_magic_cast(vx_core_t, link->priv, return);
+       vx_core_t *chip = link->priv;
 
        snd_printdd(KERN_DEBUG "vxpocket_detach called\n");
        /* Remove the interface data from the linked list */
@@ -263,7 +263,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 static void vxpocket_config(dev_link_t *link)
 {
        client_handle_t handle = link->handle;
-       vx_core_t *chip = snd_magic_cast(vx_core_t, link->priv, return);
+       vx_core_t *chip = link->priv;
        struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
        tuple_t tuple;
        cisparse_t parse;
index d46b2b7..aeaef3d 100644 (file)
@@ -25,8 +25,6 @@
 #include <sound/control.h>
 #include "vxpocket.h"
 
-#define chip_t vx_core_t
-
 #define MIC_LEVEL_MIN  0
 #define MIC_LEVEL_MAX  8
 
index c0e1fd0..2d6f0e1 100644 (file)
@@ -26,8 +26,6 @@
 #include <asm/io.h>
 #include "vxpocket.h"
 
-#define chip_t vx_core_t
-
 
 static int vxp_reg_offset[VX_REG_MAX] = {
        [VX_ICR]        = 0x00,         // ICR
index 1860cb9..ef6a655 100644 (file)
@@ -6,9 +6,12 @@ menu "ALSA PowerMac devices"
 comment "ALSA PowerMac requires I2C"
        depends on SND && I2C=n
 
+comment "ALSA PowerMac requires INPUT"
+       depends on SND && INPUT=n
+
 config SND_POWERMAC
        tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
-       depends on SND && I2C
+       depends on SND && I2C && INPUT
        select SND_PCM
 
 endmenu
index a0a4c20..4d95c65 100644 (file)
@@ -3,7 +3,7 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
 #
 
-snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o
+snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
index 5dd5a48..e052bd0 100644 (file)
@@ -29,8 +29,6 @@
 #include <sound/core.h>
 #include "pmac.h"
 
-#define chip_t pmac_t
-
 
 #ifdef CONFIG_ADB_CUDA
 #define PMAC_AMP_AVAIL
@@ -574,11 +572,22 @@ static snd_kcontrol_new_t snd_pmac_awacs_mixers[] __initdata = {
        AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
        AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
        AWACS_VOLUME("Capture Volume", 0, 4, 0),
-       AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+};
+
+/* FIXME: is this correct order?
+ * screamer (powerbook G3 pismo) seems to have different bits...
+ */
+static snd_kcontrol_new_t snd_pmac_awacs_mixers2[] __initdata = {
+       AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
        AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0),
 };
 
+static snd_kcontrol_new_t snd_pmac_screamer_mixers2[] __initdata = {
+       AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+       AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
+};
+
 static snd_kcontrol_new_t snd_pmac_awacs_master_sw __initdata =
 AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
 
@@ -602,8 +611,6 @@ static snd_kcontrol_new_t snd_pmac_awacs_speaker_sw __initdata =
 AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
 
 
-#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 /*
  * add new mixer elements to the card
  */
@@ -818,9 +825,17 @@ snd_pmac_awacs_init(pmac_t *chip)
         */
        strcpy(chip->card->mixername, "PowerMac AWACS");
 
-       if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_mixers),
+       if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
                                snd_pmac_awacs_mixers)) < 0)
                return err;
+       if (chip->model == PMAC_SCREAMER)
+               err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
+                                  snd_pmac_screamer_mixers2);
+       else
+               err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),
+                                  snd_pmac_awacs_mixers2);
+       if (err < 0)
+               return err;
        chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip);
        if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
                return err;
@@ -832,7 +847,7 @@ snd_pmac_awacs_init(pmac_t *chip)
                 * screamer registers.
                 * in this case, it seems the route C is not used.
                 */
-               if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_amp_vol),
+               if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
                                        snd_pmac_awacs_amp_vol)) < 0)
                        return err;
                /* overwrite */
@@ -846,7 +861,7 @@ snd_pmac_awacs_init(pmac_t *chip)
 #endif /* PMAC_AMP_AVAIL */
        {
                /* route A = headphone, route C = speaker */
-               if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_speaker_vol),
+               if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
                                        snd_pmac_awacs_speaker_vol)) < 0)
                        return err;
                chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip);
@@ -855,11 +870,11 @@ snd_pmac_awacs_init(pmac_t *chip)
        }
 
        if (chip->model == PMAC_SCREAMER) {
-               if ((err = build_mixers(chip, num_controls(snd_pmac_screamer_mic_boost),
+               if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost),
                                        snd_pmac_screamer_mic_boost)) < 0)
                        return err;
        } else {
-               if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_mic_boost),
+               if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
                                        snd_pmac_awacs_mic_boost)) < 0)
                        return err;
        }
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
new file mode 100644 (file)
index 0000000..c23f601
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Beep using pcm
+ *
+ * Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute 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 <sound/driver.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include "pmac.h"
+
+struct snd_pmac_beep {
+       int running;    /* boolean */
+       int volume;     /* mixer volume: 0-100 */
+       int volume_play;        /* currently playing volume */
+       int hz;
+       int nsamples;
+       short *buf;             /* allocated wave buffer */
+       unsigned long addr;     /* physical address of buffer */
+       struct input_dev dev;
+};
+
+/*
+ * stop beep if running
+ */
+void snd_pmac_beep_stop(pmac_t *chip)
+{
+       pmac_beep_t *beep = chip->beep;
+       if (beep && beep->running) {
+               beep->running = 0;
+               snd_pmac_beep_dma_stop(chip);
+       }
+}
+
+/*
+ * Stuff for outputting a beep.  The values range from -327 to +327
+ * so we can multiply by an amplitude in the range 0..100 to get a
+ * signed short value to put in the output buffer.
+ */
+static short beep_wform[256] = {
+       0,      40,     79,     117,    153,    187,    218,    245,
+       269,    288,    304,    316,    323,    327,    327,    324,
+       318,    310,    299,    288,    275,    262,    249,    236,
+       224,    213,    204,    196,    190,    186,    183,    182,
+       182,    183,    186,    189,    192,    196,    200,    203,
+       206,    208,    209,    209,    209,    207,    204,    201,
+       197,    193,    188,    183,    179,    174,    170,    166,
+       163,    161,    160,    159,    159,    160,    161,    162,
+       164,    166,    168,    169,    171,    171,    171,    170,
+       169,    167,    163,    159,    155,    150,    144,    139,
+       133,    128,    122,    117,    113,    110,    107,    105,
+       103,    103,    103,    103,    104,    104,    105,    105,
+       105,    103,    101,    97,     92,     86,     78,     68,
+       58,     45,     32,     18,     3,      -11,    -26,    -41,
+       -55,    -68,    -79,    -88,    -95,    -100,   -102,   -102,
+       -99,    -93,    -85,    -75,    -62,    -48,    -33,    -16,
+       0,      16,     33,     48,     62,     75,     85,     93,
+       99,     102,    102,    100,    95,     88,     79,     68,
+       55,     41,     26,     11,     -3,     -18,    -32,    -45,
+       -58,    -68,    -78,    -86,    -92,    -97,    -101,   -103,
+       -105,   -105,   -105,   -104,   -104,   -103,   -103,   -103,
+       -103,   -105,   -107,   -110,   -113,   -117,   -122,   -128,
+       -133,   -139,   -144,   -150,   -155,   -159,   -163,   -167,
+       -169,   -170,   -171,   -171,   -171,   -169,   -168,   -166,
+       -164,   -162,   -161,   -160,   -159,   -159,   -160,   -161,
+       -163,   -166,   -170,   -174,   -179,   -183,   -188,   -193,
+       -197,   -201,   -204,   -207,   -209,   -209,   -209,   -208,
+       -206,   -203,   -200,   -196,   -192,   -189,   -186,   -183,
+       -182,   -182,   -183,   -186,   -190,   -196,   -204,   -213,
+       -224,   -236,   -249,   -262,   -275,   -288,   -299,   -310,
+       -318,   -324,   -327,   -327,   -323,   -316,   -304,   -288,
+       -269,   -245,   -218,   -187,   -153,   -117,   -79,    -40,
+};
+
+#define BEEP_SRATE     22050   /* 22050 Hz sample rate */
+#define BEEP_BUFLEN    512
+#define BEEP_VOLUME    15      /* 0 - 100 */
+
+static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, unsigned int code, int hz)
+{
+       pmac_t *chip;
+       pmac_beep_t *beep;
+       unsigned long flags;
+       int beep_speed = 0;
+       int srate;
+       int period, ncycles, nsamples;
+       int i, j, f;
+       short *p;
+
+       if (type != EV_SND)
+               return -1;
+
+       switch (code) {
+       case SND_BELL: if (hz) hz = 1000;
+       case SND_TONE: break;
+       default: return -1;
+       }
+
+       chip = dev->private;
+       if (! chip || (beep = chip->beep) == NULL)
+               return -1;
+
+       if (! hz) {
+               spin_lock_irqsave(&chip->reg_lock, flags);
+               if (beep->running)
+                       snd_pmac_beep_stop(chip);
+               spin_unlock_irqrestore(&chip->reg_lock, flags);
+               return 0;
+       }
+
+       beep_speed = snd_pmac_rate_index(chip, &chip->playback, BEEP_SRATE);
+       srate = chip->freq_table[beep_speed];
+
+       if (hz <= srate / BEEP_BUFLEN || hz > srate / 2)
+               hz = 1000;
+
+       spin_lock_irqsave(&chip->reg_lock, flags);
+       if (chip->playback.running || chip->capture.running || beep->running) {
+               spin_unlock_irqrestore(&chip->reg_lock, flags);
+               return 0;
+       }
+       beep->running = 1;
+       spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+       if (hz == beep->hz && beep->volume == beep->volume_play) {
+               nsamples = beep->nsamples;
+       } else {
+               period = srate * 256 / hz;      /* fixed point */
+               ncycles = BEEP_BUFLEN * 256 / period;
+               nsamples = (period * ncycles) >> 8;
+               f = ncycles * 65536 / nsamples;
+               j = 0;
+               p = beep->buf;
+               for (i = 0; i < nsamples; ++i, p += 2) {
+                       p[0] = p[1] = beep_wform[j >> 8] * beep->volume;
+                       j = (j + f) & 0xffff;
+               }
+               beep->hz = hz;
+               beep->volume_play = beep->volume;
+               beep->nsamples = nsamples;
+       }
+
+       spin_lock_irqsave(&chip->reg_lock, flags);
+       snd_pmac_beep_dma_start(chip, beep->nsamples * 4, beep->addr, beep_speed);
+       spin_unlock_irqrestore(&chip->reg_lock, flags);
+       return 0;
+}
+
+/*
+ * beep volume mixer
+ */
+
+#define chip_t pmac_t
+
+static int snd_pmac_info_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 100;
+       return 0;
+}
+
+static int snd_pmac_get_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       pmac_t *chip = snd_kcontrol_chip(kcontrol);
+       snd_assert(chip->beep, return -ENXIO);
+       ucontrol->value.integer.value[0] = chip->beep->volume;
+       return 0;
+}
+
+static int snd_pmac_put_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       pmac_t *chip = snd_kcontrol_chip(kcontrol);
+       int oval;
+       snd_assert(chip->beep, return -ENXIO);
+       oval = chip->beep->volume;
+       chip->beep->volume = ucontrol->value.integer.value[0];
+       return oval != chip->beep->volume;
+}
+
+static snd_kcontrol_new_t snd_pmac_beep_mixer = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Beep Playback Volume",
+       .info = snd_pmac_info_beep,
+       .get = snd_pmac_get_beep,
+       .put = snd_pmac_put_beep,
+};
+
+/* Initialize beep stuff */
+int __init snd_pmac_attach_beep(pmac_t *chip)
+{
+       pmac_beep_t *beep;
+       int err;
+
+       beep = kmalloc(sizeof(*beep), GFP_KERNEL);
+       if (! beep)
+               return -ENOMEM;
+
+       memset(beep, 0, sizeof(*beep));
+       beep->buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
+       if (! beep->buf) {
+               kfree(beep);
+               return -ENOMEM;
+       }
+       beep->addr = virt_to_bus(beep->buf);
+
+       beep->dev.evbit[0] = BIT(EV_SND);
+       beep->dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+       beep->dev.event = snd_pmac_beep_event;
+       beep->dev.private = chip;
+
+       /* FIXME: set more better values */
+       beep->dev.name = "PowerMac Beep";
+       beep->dev.phys = "powermac/beep";
+       beep->dev.id.bustype = BUS_ADB;
+       beep->dev.id.vendor = 0x001f;
+       beep->dev.id.product = 0x0001;
+       beep->dev.id.version = 0x0100;
+
+       beep->volume = BEEP_VOLUME;
+       beep->running = 0;
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_beep_mixer, chip))) < 0) {
+               kfree(beep->buf);
+               kfree(beep);
+               return err;
+       }
+
+       chip->beep = beep;
+       input_register_device(&beep->dev);
+
+       return 0;
+}
+
+void snd_pmac_detach_beep(pmac_t *chip)
+{
+       if (chip->beep) {
+               input_unregister_device(&chip->beep->dev);
+               kfree(chip->beep->buf);
+               kfree(chip->beep);
+               chip->beep = NULL;
+       }
+}
index dc54946..3f837d9 100644 (file)
@@ -28,8 +28,6 @@
 #include "pmac.h"
 #include "burgundy.h"
 
-#define chip_t pmac_t
-
 
 /* Waits for busy flag to clear */
 inline static void
@@ -324,8 +322,6 @@ BURGUNDY_OUTPUT_SWITCH("Headphone Playback Switch", 0, BURGUNDY_OUTPUT_LEFT, BUR
 static snd_kcontrol_new_t snd_pmac_burgundy_speaker_sw __initdata = 
 BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN, 0, 0);
 
-#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 
 #ifdef PMAC_SUPPORT_AUTOMUTE
 /*
@@ -420,7 +416,7 @@ int __init snd_pmac_burgundy_init(pmac_t *chip)
         */
        strcpy(chip->card->mixername, "PowerMac Burgundy");
 
-       for (i = 0; i < num_controls(snd_pmac_burgundy_mixers); i++) {
+       for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) {
                if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
                        return err;
        }
index 0b48286..6629b6b 100644 (file)
@@ -28,8 +28,6 @@
 #include <sound/core.h>
 #include "pmac.h"
 
-#define chip_t pmac_t
-
 /* i2c address */
 #define DACA_I2C_ADDR  0x4d
 
@@ -217,8 +215,6 @@ static snd_kcontrol_new_t daca_mixers[] = {
        },
 };
 
-#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 
 #ifdef CONFIG_PMAC_PBOOK
 static void daca_resume(pmac_t *chip)
@@ -272,7 +268,7 @@ int __init snd_pmac_daca_init(pmac_t *chip)
         */
        strcpy(chip->card->mixername, "PowerMac DACA");
 
-       for (i = 0; i < num_controls(daca_mixers); i++) {
+       for (i = 0; i < ARRAY_SIZE(daca_mixers); i++) {
                if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&daca_mixers[i], chip))) < 0)
                        return err;
        }
index 155df15..0476d06 100644 (file)
@@ -39,7 +39,7 @@ int snd_emux_new(snd_emux_t **remu)
        snd_emux_t *emu;
 
        *remu = NULL;
-       emu = snd_magic_kcalloc(snd_emux_t, 0, GFP_KERNEL);
+       emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
        if (emu == NULL)
                return -ENOMEM;
 
@@ -77,7 +77,7 @@ int snd_emux_register(snd_emux_t *emu, snd_card_t *card, int index, char *name)
 
        emu->card = card;
        emu->name = snd_kmalloc_strdup(name, GFP_KERNEL);
-       emu->voices = snd_kcalloc(sizeof(snd_emux_voice_t) * emu->max_voices, GFP_KERNEL);
+       emu->voices = kcalloc(emu->max_voices, sizeof(snd_emux_voice_t), GFP_KERNEL);
        if (emu->voices == NULL)
                return -ENOMEM;
 
@@ -143,7 +143,7 @@ int snd_emux_free(snd_emux_t *emu)
        if (emu->name)
                kfree(emu->name);
 
-       snd_magic_kfree(emu);
+       kfree(emu);
        return 0;
 }
 
index f1a2af1..ec3fc1b 100644 (file)
@@ -278,7 +278,7 @@ void
 snd_emux_create_effect(snd_emux_port_t *p)
 {
        int i;
-       p->effect = snd_kcalloc(sizeof(snd_emux_effect_table_t) * p->chset.max_channels, GFP_KERNEL);
+       p->effect = kcalloc(p->chset.max_channels, sizeof(snd_emux_effect_table_t), GFP_KERNEL);
        if (p->effect) {
                for (i = 0; i < p->chset.max_channels; i++)
                        p->chset.channels[i].private = p->effect + i;
index e145148..4182b44 100644 (file)
@@ -104,7 +104,7 @@ snd_emux_hwdep_misc_mode(snd_emux_t *emu, void __user *arg)
 static int
 snd_emux_hwdep_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
-       snd_emux_t *emu = snd_magic_cast(snd_emux_t, hw->private_data, return -ENXIO);
+       snd_emux_t *emu = hw->private_data;
 
        switch (cmd) {
        case SNDRV_EMUX_IOCTL_VERSION:
index c49cf56..25edff9 100644 (file)
@@ -22,8 +22,6 @@
 #include "emux_voice.h"
 #include <sound/asoundef.h>
 
-#define NELEM(arr) (sizeof(arr)/sizeof((arr)[0]))
-
 /*
  * conversion from NRPN/control parameters to Emu8000 raw parameters
  */
@@ -214,8 +212,6 @@ static nrpn_conv_table awe_effects[] =
        {26, EMUX_FX_REVERB,            fx_reverb},
 };
 
-static int num_awe_effects = NELEM(awe_effects);
-
 
 /*
  * GS(SC88) NRPN effects; still experimental
@@ -281,8 +277,6 @@ static nrpn_conv_table gs_effects[] =
        {10, EMUX_FX_LFO1_DELAY, gs_vib_delay},
 };
 
-static int num_gs_effects = NELEM(gs_effects);
-
 
 /*
  * NRPN events
@@ -292,7 +286,7 @@ snd_emux_nrpn(void *p, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset)
 {
        snd_emux_port_t *port;
 
-       port = snd_magic_cast(snd_emux_port_t, p, return);
+       port = p;
        snd_assert(port != NULL, return);
        snd_assert(chan != NULL, return);
 
@@ -305,7 +299,7 @@ snd_emux_nrpn(void *p, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset)
                        chan->control[MIDI_CTL_LSB_DATA_ENTRY]; 
                val -= 8192;
                send_converted_effect
-                       (awe_effects, num_awe_effects,
+                       (awe_effects, ARRAY_SIZE(awe_effects),
                         port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],
                         val, EMUX_FX_FLAG_SET);
                return;
@@ -318,7 +312,7 @@ snd_emux_nrpn(void *p, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset)
                /* only MSB is valid */
                val = chan->control[MIDI_CTL_MSB_DATA_ENTRY];
                send_converted_effect
-                       (gs_effects, num_gs_effects,
+                       (gs_effects, ARRAY_SIZE(gs_effects),
                         port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],
                         val, EMUX_FX_FLAG_ADD);
                return;
@@ -362,12 +356,10 @@ static nrpn_conv_table xg_effects[] =
        {73, EMUX_FX_ENV2_ATTACK, xg_attack},
 };
 
-static int num_xg_effects = NELEM(xg_effects);
-
 int
 snd_emux_xg_control(snd_emux_port_t *port, snd_midi_channel_t *chan, int param)
 {
-       return send_converted_effect(xg_effects, num_xg_effects,
+       return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects),
                                     port, chan, param,
                                     chan->control[param],
                                     EMUX_FX_FLAG_ADD);
@@ -382,7 +374,7 @@ snd_emux_sysex(void *p, unsigned char *buf, int len, int parsed, snd_midi_channe
        snd_emux_port_t *port;
        snd_emux_t *emu;
 
-       port = snd_magic_cast(snd_emux_port_t, p, return);
+       port = p;
        snd_assert(port != NULL, return);
        snd_assert(chset != NULL, return);
        emu = port->emu;
index b67bb39..0f155d6 100644 (file)
@@ -36,7 +36,7 @@ snd_emux_proc_info_read(snd_info_entry_t *entry,
        snd_emux_t *emu;
        int i;
 
-       emu = snd_magic_cast(snd_emux_t, entry->private_data, return);
+       emu = entry->private_data;
        down(&emu->register_mutex);
        if (emu->name)
                snd_iprintf(buf, "Device: %s\n", emu->name);
index 973b4d6..4b91722 100644 (file)
@@ -146,14 +146,14 @@ snd_emux_create_port(snd_emux_t *emu, char *name,
        int i, type, cap;
 
        /* Allocate structures for this channel */
-       if ((p = snd_magic_kcalloc(snd_emux_port_t, 0, GFP_KERNEL)) == NULL) {
+       if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
                snd_printk("no memory\n");
                return NULL;
        }
-       p->chset.channels = snd_kcalloc(max_channels * sizeof(snd_midi_channel_t), GFP_KERNEL);
+       p->chset.channels = kcalloc(max_channels, sizeof(snd_midi_channel_t), GFP_KERNEL);
        if (p->chset.channels == NULL) {
                snd_printk("no memory\n");
-               snd_magic_kfree(p);
+               kfree(p);
                return NULL;
        }
        for (i = 0; i < max_channels; i++)
@@ -192,14 +192,14 @@ free_port(void *private_data)
 {
        snd_emux_port_t *p;
 
-       p = snd_magic_cast(snd_emux_port_t, private_data, return);
+       p = private_data;
        if (p) {
 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
                snd_emux_delete_effect(p);
 #endif
                if (p->chset.channels)
                        kfree(p->chset.channels);
-               snd_magic_kfree(p);
+               kfree(p);
        }
 }
 
@@ -257,7 +257,7 @@ snd_emux_event_input(snd_seq_event_t *ev, int direct, void *private_data,
 {
        snd_emux_port_t *port;
 
-       port = snd_magic_cast(snd_emux_port_t, private_data, return -EINVAL);
+       port = private_data;
        snd_assert(port != NULL && ev != NULL, return -EINVAL);
 
        snd_midi_process_event(&emux_ops, ev, &port->chset);
@@ -308,7 +308,7 @@ snd_emux_use(void *private_data, snd_seq_port_subscribe_t *info)
        snd_emux_port_t *p;
        snd_emux_t *emu;
 
-       p = snd_magic_cast(snd_emux_port_t, private_data, return -EINVAL);
+       p = private_data;
        snd_assert(p != NULL, return -EINVAL);
        emu = p->emu;
        snd_assert(emu != NULL, return -EINVAL);
@@ -329,7 +329,7 @@ snd_emux_unuse(void *private_data, snd_seq_port_subscribe_t *info)
        snd_emux_port_t *p;
        snd_emux_t *emu;
 
-       p = snd_magic_cast(snd_emux_port_t, private_data, return -EINVAL);
+       p = private_data;
        snd_assert(p != NULL, return -EINVAL);
        emu = p->emu;
        snd_assert(emu != NULL, return -EINVAL);
@@ -383,7 +383,7 @@ int snd_emux_init_virmidi(snd_emux_t *emu, snd_card_t *card)
        if (emu->midi_ports <= 0)
                return 0;
 
-       emu->vmidi = snd_kcalloc(sizeof(snd_rawmidi_t*) * emu->midi_ports, GFP_KERNEL);
+       emu->vmidi = kcalloc(emu->midi_ports, sizeof(snd_rawmidi_t*), GFP_KERNEL);
        if (emu->vmidi == NULL)
                return -ENOMEM;
 
@@ -392,7 +392,7 @@ int snd_emux_init_virmidi(snd_emux_t *emu, snd_card_t *card)
                snd_virmidi_dev_t *rdev;
                if (snd_virmidi_new(card, emu->midi_devidx + i, &rmidi) < 0)
                        goto __error;
-               rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, continue);
+               rdev = rmidi->private_data;
                sprintf(rmidi->name, "%s Synth MIDI", emu->name);
                rdev->seq_mode = SNDRV_VIRMIDI_SEQ_ATTACH;
                rdev->client = emu->client;
index 15c7f2d..0fe8cac 100644 (file)
@@ -61,7 +61,7 @@ snd_emux_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
        unsigned long flags;
        snd_emux_port_t *port;
 
-       port = snd_magic_cast(snd_emux_port_t, p, return);
+       port = p;
        snd_assert(port != NULL && chan != NULL, return);
 
        emu = port->emu;
@@ -160,7 +160,7 @@ snd_emux_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
        unsigned long flags;
        snd_emux_port_t *port;
 
-       port = snd_magic_cast(snd_emux_port_t, p, return);
+       port = p;
        snd_assert(port != NULL && chan != NULL, return);
 
        emu = port->emu;
@@ -201,7 +201,7 @@ snd_emux_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
  */
 void snd_emux_timer_callback(unsigned long data)
 {
-       snd_emux_t *emu = snd_magic_cast(snd_emux_t, (void*)data, return);
+       snd_emux_t *emu = (snd_emux_t*) data;
        snd_emux_voice_t *vp;
        int ch, do_again = 0;
 
@@ -238,7 +238,7 @@ snd_emux_key_press(void *p, int note, int vel, snd_midi_channel_t *chan)
        unsigned long flags;
        snd_emux_port_t *port;
 
-       port = snd_magic_cast(snd_emux_port_t, p, return);
+       port = p;
        snd_assert(port != NULL && chan != NULL, return);
 
        emu = port->emu;
@@ -322,7 +322,7 @@ snd_emux_control(void *p, int type, snd_midi_channel_t *chan)
 {
        snd_emux_port_t *port;
 
-       port = snd_magic_cast(snd_emux_port_t, p, return);
+       port = p;
        snd_assert(port != NULL && chan != NULL, return);
 
        switch (type) {
@@ -402,7 +402,7 @@ snd_emux_terminate_note(void *p, int note, snd_midi_channel_t *chan)
        snd_emux_t *emu;
        snd_emux_port_t *port;
 
-       port = snd_magic_cast(snd_emux_port_t, p, return);
+       port = p;
        snd_assert(port != NULL && chan != NULL, return);
 
        emu = port->emu;
index 8db2e2d..1616202 100644 (file)
@@ -64,15 +64,14 @@ static void snd_sf_clear(snd_sf_list_t *sflist);
 /*
  * lock access to sflist
  */
-static int
-lock_preset(snd_sf_list_t *sflist, int nonblock)
+static void
+lock_preset(snd_sf_list_t *sflist)
 {
-       if (nonblock) {
-               if (down_trylock(&sflist->presets_mutex))
-                       return -EBUSY;
-       } else 
-               down(&sflist->presets_mutex);
-       return 0;
+       unsigned long flags;
+       down(&sflist->presets_mutex);
+       spin_lock_irqsave(&sflist->lock, flags);
+       sflist->presets_locked = 1;
+       spin_unlock_irqrestore(&sflist->lock, flags);
 }
 
 
@@ -82,6 +81,10 @@ lock_preset(snd_sf_list_t *sflist, int nonblock)
 static void
 unlock_preset(snd_sf_list_t *sflist)
 {
+       unsigned long flags;
+       spin_lock_irqsave(&sflist->lock, flags);
+       sflist->presets_locked = 0;
+       spin_unlock_irqrestore(&sflist->lock, flags);
        up(&sflist->presets_mutex);
 }
 
@@ -143,7 +146,7 @@ snd_soundfont_load(snd_sf_list_t *sflist, const void __user *data, long count, i
 
        if (patch.type == SNDRV_SFNT_OPEN_PATCH) {
                /* grab sflist to open */
-               lock_preset(sflist, 0);
+               lock_preset(sflist);
                rc = open_patch(sflist, data, count, client);
                unlock_preset(sflist);
                return rc;
@@ -157,7 +160,7 @@ snd_soundfont_load(snd_sf_list_t *sflist, const void __user *data, long count, i
        }
        spin_unlock_irqrestore(&sflist->lock, flags);
 
-       lock_preset(sflist, 0);
+       lock_preset(sflist);
        rc = -EINVAL;
        switch (patch.type) {
        case SNDRV_SFNT_LOAD_INFO:
@@ -237,8 +240,10 @@ open_patch(snd_sf_list_t *sflist, const char __user *data, int count, int client
                return -ENOMEM;
        }
 
+       spin_lock_irqsave(&sflist->lock, flags);
        sflist->open_client = client;
        sflist->currsf = sf;
+       spin_unlock_irqrestore(&sflist->lock, flags);
 
        return 0;
 }
@@ -261,7 +266,7 @@ newsf(snd_sf_list_t *sflist, int type, char *name)
        }
 
        /* not found -- create a new one */
-       sf = (snd_soundfont_t*)snd_kcalloc(sizeof(*sf), GFP_KERNEL);
+       sf = kcalloc(1, sizeof(*sf), GFP_KERNEL);
        if (sf == NULL)
                return NULL;
        sf->id = sflist->fonts_size;
@@ -296,8 +301,12 @@ is_identical_font(snd_soundfont_t *sf, int type, unsigned char *name)
 static int
 close_patch(snd_sf_list_t *sflist)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&sflist->lock, flags);
        sflist->currsf = NULL;
        sflist->open_client = -1;
+       spin_unlock_irqrestore(&sflist->lock, flags);
 
        rebuild_presets(sflist);
 
@@ -337,7 +346,7 @@ sf_zone_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
 {
        snd_sf_zone_t *zp;
 
-       if ((zp = snd_kcalloc(sizeof(*zp), GFP_KERNEL)) == NULL)
+       if ((zp = kcalloc(1, sizeof(*zp), GFP_KERNEL)) == NULL)
                return NULL;
        zp->next = sf->zones;
        sf->zones = zp;
@@ -368,7 +377,7 @@ sf_sample_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
 {
        snd_sf_sample_t *sp;
 
-       if ((sp = snd_kcalloc(sizeof(*sp), GFP_KERNEL)) == NULL)
+       if ((sp = kcalloc(1, sizeof(*sp), GFP_KERNEL)) == NULL)
                return NULL;
 
        sp->next = sf->samples;
@@ -1090,7 +1099,7 @@ snd_soundfont_load_guspatch(snd_sf_list_t *sflist, const char __user *data,
                            long count, int client)
 {
        int rc;
-       lock_preset(sflist, 0);
+       lock_preset(sflist);
        rc = load_guspatch(sflist, data, count, client);
        unlock_preset(sflist);
        return rc;
@@ -1197,17 +1206,23 @@ snd_soundfont_search_zone(snd_sf_list_t *sflist, int *notep, int vel,
                          snd_sf_zone_t **table, int max_layers)
 {
        int nvoices;
+       unsigned long flags;
 
-       if (lock_preset(sflist, 1))
+       /* this function is supposed to be called atomically,
+        * so we check the lock.  if it's busy, just returns 0 to
+        * tell the caller the busy state
+        */
+       spin_lock_irqsave(&sflist->lock, flags);
+       if (sflist->presets_locked) {
+               spin_unlock_irqrestore(&sflist->lock, flags);
                return 0;
-
+       }
        nvoices = search_zones(sflist, notep, vel, preset, bank, table, max_layers, 0);
        if (! nvoices) {
                if (preset != def_preset || bank != def_bank)
                        nvoices = search_zones(sflist, notep, vel, def_preset, def_bank, table, max_layers, 0);
        }
-       unlock_preset(sflist);
-
+       spin_unlock_irqrestore(&sflist->lock, flags);
        return nvoices;
 }
 
@@ -1347,7 +1362,7 @@ snd_sf_new(snd_sf_callback_t *callback, snd_util_memhdr_t *hdr)
 {
        snd_sf_list_t *sflist;
 
-       if ((sflist = snd_kcalloc(sizeof(snd_sf_list_t), GFP_KERNEL)) == NULL)
+       if ((sflist = kcalloc(1, sizeof(*sflist), GFP_KERNEL)) == NULL)
                return NULL;
 
        init_MUTEX(&sflist->presets_mutex);
@@ -1371,7 +1386,7 @@ snd_sf_free(snd_sf_list_t *sflist)
        if (sflist == NULL)
                return;
        
-       lock_preset(sflist, 0);
+       lock_preset(sflist);
        if (sflist->callback.sample_reset)
                sflist->callback.sample_reset(sflist->callback.private_data);
        snd_sf_clear(sflist);
@@ -1387,7 +1402,7 @@ snd_sf_free(snd_sf_list_t *sflist)
 int
 snd_soundfont_remove_samples(snd_sf_list_t *sflist)
 {
-       lock_preset(sflist, 0);
+       lock_preset(sflist);
        if (sflist->callback.sample_reset)
                sflist->callback.sample_reset(sflist->callback.private_data);
        snd_sf_clear(sflist);
@@ -1407,8 +1422,7 @@ snd_soundfont_remove_unlocked(snd_sf_list_t *sflist)
        snd_sf_zone_t *zp, *nextzp;
        snd_sf_sample_t *sp, *nextsp;
 
-       if (lock_preset(sflist, 1))
-               return -EBUSY;
+       lock_preset(sflist);
 
        if (sflist->callback.sample_reset)
                sflist->callback.sample_reset(sflist->callback.private_data);
index 00679af..8b131a1 100644 (file)
@@ -38,7 +38,7 @@ snd_util_memhdr_new(int memsize)
 {
        snd_util_memhdr_t *hdr;
 
-       hdr = snd_kcalloc(sizeof(*hdr), GFP_KERNEL);
+       hdr = kcalloc(1, sizeof(*hdr), GFP_KERNEL);
        if (hdr == NULL)
                return NULL;
        hdr->size = memsize;
index b697649..934ead0 100644 (file)
@@ -11,5 +11,15 @@ config SND_USB_AUDIO
        help
          Say 'Y' or 'M' to include support for USB audio and USB MIDI devices.
 
+config SND_USB_USX2Y
+       tristate "Tascam US-122, US-224 and US-428 USB driver"
+       depends on SND && USB
+       select SND_HWDEP
+       select SND_RAWMIDI
+       select SND_PCM
+       help
+         Say 'Y' or 'M' to include support for Tascam USB Audio/MIDI 
+         interfaces or controllers US-122, US-224 and US-428.
+
 endmenu
 
index 6579582..2c1dc11 100644 (file)
@@ -2,7 +2,11 @@
 # Makefile for ALSA
 #
 
-snd-usb-audio-objs := usbaudio.o usbmixer.o usbmidi.o
+snd-usb-audio-objs := usbaudio.o usbmixer.o
+snd-usb-lib-objs := usbmidi.o
 
 # Toplevel Module Dependency
-obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o
+obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usb-lib.o
+obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-lib.o
+
+obj-$(CONFIG_SND) += usx2y/
index a2f1b56..96fd06e 100644 (file)
 #include <sound/rawmidi.h>
 #include "usbaudio.h"
 
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_DESCRIPTION("USB Audio/MIDI helper module");
+MODULE_LICENSE("Dual BSD/GPL");
+
+
 struct usb_ms_header_descriptor {
        __u8  bLength;
        __u8  bDescriptorType;
@@ -175,7 +180,7 @@ static void snd_usbmidi_input_packet(snd_usb_midi_in_endpoint_t* ep,
  */
 static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs)
 {
-       snd_usb_midi_in_endpoint_t* ep = snd_magic_cast(snd_usb_midi_in_endpoint_t, urb->context, return);
+       snd_usb_midi_in_endpoint_t* ep = urb->context;
 
        if (urb->status == 0) {
                uint8_t* buffer = (uint8_t*)ep->urb->transfer_buffer;
@@ -229,7 +234,7 @@ static void snd_usbmidi_in_midiman_complete(struct urb* urb, struct pt_regs *reg
 
 static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs)
 {
-       snd_usb_midi_out_endpoint_t* ep = snd_magic_cast(snd_usb_midi_out_endpoint_t, urb->context, return);
+       snd_usb_midi_out_endpoint_t* ep = urb->context;
 
        if (urb->status < 0) {
                if (snd_usbmidi_urb_error(urb->status) < 0)
@@ -393,7 +398,7 @@ static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
        int p;
        struct urb* urb = ep->urb;
        unsigned long flags;
-       
+
        spin_lock_irqsave(&ep->buffer_lock, flags);
        if (urb->status == -EINPROGRESS || ep->umidi->chip->shutdown) {
                spin_unlock_irqrestore(&ep->buffer_lock, flags);
@@ -417,14 +422,14 @@ static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
 
 static void snd_usbmidi_out_tasklet(unsigned long data)
 {
-       snd_usb_midi_out_endpoint_t* ep = snd_magic_cast(snd_usb_midi_out_endpoint_t, (void*)data, return);
-       
+       snd_usb_midi_out_endpoint_t* ep = (snd_usb_midi_out_endpoint_t *) data;
+
        snd_usbmidi_do_output(ep);
 }
 
 static int snd_usbmidi_output_open(snd_rawmidi_substream_t* substream)
 {
-       snd_usb_midi_t* umidi = snd_magic_cast(snd_usb_midi_t, substream->rmidi->private_data, return -ENXIO);
+       snd_usb_midi_t* umidi = substream->rmidi->private_data;
        usbmidi_out_port_t* port = NULL;
        int i, j;
 
@@ -503,7 +508,7 @@ static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
                        kfree(ep->urb->transfer_buffer);
                usb_free_urb(ep->urb);
        }
-       snd_magic_kfree(ep);
+       kfree(ep);
 }
 
 /*
@@ -571,7 +576,7 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
        int length;
 
        rep->in = NULL;
-       ep = snd_magic_kcalloc(snd_usb_midi_in_endpoint_t, 0, GFP_KERNEL);
+       ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
        if (!ep)
                return -ENOMEM;
        ep->umidi = umidi;
@@ -631,7 +636,7 @@ static void snd_usbmidi_out_endpoint_delete(snd_usb_midi_out_endpoint_t* ep)
                        kfree(ep->urb->transfer_buffer);
                usb_free_urb(ep->urb);
        }
-       snd_magic_kfree(ep);
+       kfree(ep);
 }
 
 /*
@@ -647,7 +652,7 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
        void* buffer;
 
        rep->out = NULL;
-       ep = snd_magic_kcalloc(snd_usb_midi_out_endpoint_t, 0, GFP_KERNEL);
+       ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
        if (!ep)
                return -ENOMEM;
        ep->umidi = umidi;
@@ -695,7 +700,7 @@ static void snd_usbmidi_free(snd_usb_midi_t* umidi)
                if (ep->in)
                        snd_usbmidi_in_endpoint_delete(ep->in);
        }
-       snd_magic_kfree(umidi);
+       kfree(umidi);
 }
 
 /*
@@ -718,7 +723,7 @@ void snd_usbmidi_disconnect(struct list_head* p, struct usb_driver *driver)
 
 static void snd_usbmidi_rawmidi_free(snd_rawmidi_t* rmidi)
 {
-       snd_usb_midi_t* umidi = snd_magic_cast(snd_usb_midi_t, rmidi->private_data, return);
+       snd_usb_midi_t* umidi = rmidi->private_data;
        snd_usbmidi_free(umidi);
 }
 
@@ -964,7 +969,7 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
  * If the endpoints aren't specified, use the first bulk endpoints in the
  * first alternate setting of the interface.
  */
-static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi, 
+static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
                                       snd_usb_midi_endpoint_info_t* endpoint)
 {
        struct usb_interface* intf;
@@ -998,7 +1003,7 @@ static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
 /*
  * Detects the endpoints and ports of Yamaha devices.
  */
-static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi, 
+static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi,
                                     snd_usb_midi_endpoint_info_t* endpoint)
 {
        struct usb_interface* intf;
@@ -1144,6 +1149,44 @@ static int snd_usbmidi_create_rawmidi(snd_usb_midi_t* umidi,
        return 0;
 }
 
+/*
+ * Temporarily stop input.
+ */
+void snd_usbmidi_input_stop(struct list_head* p)
+{
+       snd_usb_midi_t* umidi;
+       int i;
+
+       umidi = list_entry(p, snd_usb_midi_t, list);
+       for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
+               snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
+               if (ep->in)
+                       usb_unlink_urb(ep->in->urb);
+       }
+}
+
+static void snd_usbmidi_input_start_ep(snd_usb_midi_in_endpoint_t* ep)
+{
+       if (ep) {
+               struct urb* urb = ep->urb;
+               urb->dev = ep->umidi->chip->dev;
+               snd_usbmidi_submit_urb(urb, GFP_KERNEL);
+       }
+}
+
+/*
+ * Resume input after a call to snd_usbmidi_input_stop().
+ */
+void snd_usbmidi_input_start(struct list_head* p)
+{
+       snd_usb_midi_t* umidi;
+       int i;
+
+       umidi = list_entry(p, snd_usb_midi_t, list);
+       for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
+               snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
+}
+
 /*
  * Creates and registers everything needed for a MIDI streaming interface.
  */
@@ -1156,7 +1199,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
        int out_ports, in_ports;
        int i, err;
 
-       umidi = snd_magic_kcalloc(snd_usb_midi_t, 0, GFP_KERNEL);
+       umidi = kcalloc(1, sizeof(*umidi), GFP_KERNEL);
        if (!umidi)
                return -ENOMEM;
        umidi->chip = chip;
@@ -1189,7 +1232,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
                }
        }
        if (err < 0) {
-               snd_magic_kfree(umidi);
+               kfree(umidi);
                return err;
        }
 
@@ -1202,7 +1245,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
        }
        err = snd_usbmidi_create_rawmidi(umidi, out_ports, in_ports);
        if (err < 0) {
-               snd_magic_kfree(umidi);
+               kfree(umidi);
                return err;
        }
 
@@ -1219,8 +1262,11 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
        list_add(&umidi->list, &umidi->chip->midi_list);
 
        for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
-               if (umidi->endpoints[i].in)
-                       snd_usbmidi_submit_urb(umidi->endpoints[i].in->urb,
-                                              GFP_KERNEL);
+               snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
        return 0;
 }
+
+EXPORT_SYMBOL(snd_usb_create_midi_interface);
+EXPORT_SYMBOL(snd_usbmidi_input_stop);
+EXPORT_SYMBOL(snd_usbmidi_input_start);
+EXPORT_SYMBOL(snd_usbmidi_disconnect);
index 05c9756..f01947c 100644 (file)
@@ -32,7 +32,7 @@ struct usbmix_ctl_map {
        const struct usbmix_name_map *map;
        int ignore_ctl_error;
 };
-       
+
 /*
  * USB control mappers for SB Exitigy
  */
diff --git a/sound/usb/usx2y/Makefile b/sound/usb/usx2y/Makefile
new file mode 100644 (file)
index 0000000..97d2bf2
--- /dev/null
@@ -0,0 +1,3 @@
+snd-usb-usx2y-objs := usbusx2y.o usbusx2yaudio.o usX2Yhwdep.o
+
+obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-usx2y.o
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
new file mode 100644 (file)
index 0000000..e6717f3
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * Driver for Tascam US-X2Y USB soundcards
+ *
+ * FPGA Loader + ALSA Startup
+ *
+ * Copyright (c) 2003 by Karsten Wiese <annabellesgarden@yahoo.de>
+ *
+ *   This program is free software; you can redistribute 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 <sound/driver.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <sound/core.h>
+#include <sound/memalloc.h>
+#include <sound/pcm.h>
+#include <sound/hwdep.h>
+#include "usx2y.h"
+#include "usbusx2y.h"
+#include "usX2Yhwdep.h"
+
+
+static struct page * snd_us428ctls_vm_nopage(struct vm_area_struct *area, unsigned long address, int *type)
+{
+       unsigned long offset;
+       struct page * page;
+       void *vaddr;
+
+       snd_printdd("ENTER, start %lXh, ofs %lXh, pgoff %ld, addr %lXh\n",
+                  area->vm_start,
+                  address - area->vm_start,
+                  (address - area->vm_start) >> PAGE_SHIFT,
+                  address);
+       
+       offset = area->vm_pgoff << PAGE_SHIFT;
+       offset += address - area->vm_start;
+       snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM);
+       vaddr = (char*)((usX2Ydev_t*)area->vm_private_data)->us428ctls_sharedmem + offset;
+       page = virt_to_page(vaddr);
+       get_page(page);
+       snd_printdd( "vaddr=%p made us428ctls_vm_nopage() return %p; offset=%lX\n", vaddr, page, offset);
+
+       if (type)
+               *type = VM_FAULT_MINOR;
+
+       return page;
+}
+
+static struct vm_operations_struct us428ctls_vm_ops = {
+       .nopage = snd_us428ctls_vm_nopage,
+};
+
+static int snd_us428ctls_mmap(snd_hwdep_t * hw, struct file *filp, struct vm_area_struct *area)
+{
+       unsigned long   size = (unsigned long)(area->vm_end - area->vm_start);
+       usX2Ydev_t      *us428 = (usX2Ydev_t*)hw->private_data;
+
+       // FIXME this hwdep interface is used twice: fpga download and mmap for controlling Lights etc. Maybe better using 2 hwdep devs?
+       // so as long as the device isn't fully initialised yet we return -EBUSY here.
+       if (!(((usX2Ydev_t*)hw->private_data)->chip_status & USX2Y_STAT_CHIP_INIT))
+               return -EBUSY;
+
+       /* if userspace tries to mmap beyond end of our buffer, fail */ 
+        if (size > ((PAGE_SIZE - 1 + sizeof(us428ctls_sharedmem_t)) / PAGE_SIZE) * PAGE_SIZE) {
+               snd_printd( "%lu > %lu\n", size, (unsigned long)sizeof(us428ctls_sharedmem_t)); 
+                return -EINVAL;
+       }
+
+       if (!us428->us428ctls_sharedmem) {
+               init_waitqueue_head(&us428->us428ctls_wait_queue_head);
+               if(!(us428->us428ctls_sharedmem = snd_malloc_pages(sizeof(us428ctls_sharedmem_t), GFP_KERNEL)))
+                       return -ENOMEM;
+               memset(us428->us428ctls_sharedmem, -1, sizeof(us428ctls_sharedmem_t));
+               us428->us428ctls_sharedmem->CtlSnapShotLast = -2;
+       }
+       area->vm_ops = &us428ctls_vm_ops;
+       area->vm_flags |= VM_RESERVED;
+       area->vm_private_data = hw->private_data;
+       return 0;
+}
+
+static unsigned int snd_us428ctls_poll(snd_hwdep_t *hw, struct file *file, poll_table *wait)
+{
+       unsigned int    mask = 0;
+       usX2Ydev_t      *us428 = (usX2Ydev_t*)hw->private_data;
+       static unsigned LastN;
+
+       if (us428->chip_status & USX2Y_STAT_CHIP_HUP)
+               return POLLHUP;
+
+       poll_wait(file, &us428->us428ctls_wait_queue_head, wait);
+
+       down(&us428->open_mutex);
+       if (us428->us428ctls_sharedmem
+           && us428->us428ctls_sharedmem->CtlSnapShotLast != LastN) {
+               mask |= POLLIN;
+               LastN = us428->us428ctls_sharedmem->CtlSnapShotLast;
+       }
+       up(&us428->open_mutex);
+
+       return mask;
+}
+
+
+static int snd_usX2Y_hwdep_open(snd_hwdep_t *hw, struct file *file)
+{
+       return 0;
+}
+
+static int snd_usX2Y_hwdep_release(snd_hwdep_t *hw, struct file *file)
+{
+       return 0;
+}
+
+static int snd_usX2Y_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
+{
+       static char *type_ids[USX2Y_TYPE_NUMS] = {
+               [USX2Y_TYPE_122] = "us122",
+               [USX2Y_TYPE_224] = "us224",
+               [USX2Y_TYPE_428] = "us428",
+       };
+       int id = -1;
+
+       switch (((usX2Ydev_t*)hw->private_data)->chip.dev->descriptor.idProduct) {
+       case USB_ID_US122:
+               id = USX2Y_TYPE_122;
+               break;
+       case USB_ID_US224:
+               id = USX2Y_TYPE_224;
+               break;
+       case USB_ID_US428:
+               id = USX2Y_TYPE_428;
+               break;
+       }
+       if (0 > id)
+               return -ENODEV;
+       strcpy(info->id, type_ids[id]);
+       info->num_dsps = 2;             // 0: Prepad Data, 1: FPGA Code
+       if (((usX2Ydev_t*)hw->private_data)->chip_status & USX2Y_STAT_CHIP_INIT) 
+               info->chip_ready = 1;
+       info->version = USX2Y_DRIVER_VERSION; 
+       return 0;
+}
+
+
+static int usX2Y_create_usbmidi(snd_card_t* card )
+{
+       static snd_usb_midi_endpoint_info_t quirk_data_1 = {
+               .out_ep =0x06,
+               .in_ep = 0x06,
+               .out_cables =   0x001,
+               .in_cables =    0x001
+       };
+       static snd_usb_audio_quirk_t quirk_1 = {
+               .vendor_name =  "TASCAM",
+               .product_name = NAME_ALLCAPS,
+               .ifnum =        0,
+                       .type = QUIRK_MIDI_FIXED_ENDPOINT,
+               .data = &quirk_data_1
+       };
+       static snd_usb_midi_endpoint_info_t quirk_data_2 = {
+               .out_ep =0x06,
+               .in_ep = 0x06,
+               .out_cables =   0x003,
+               .in_cables =    0x003
+       };
+       static snd_usb_audio_quirk_t quirk_2 = {
+               .vendor_name =  "TASCAM",
+               .product_name = "US428",
+               .ifnum =        0,
+                       .type = QUIRK_MIDI_FIXED_ENDPOINT,
+               .data = &quirk_data_2
+       };
+       struct usb_device *dev = usX2Y(card)->chip.dev;
+       struct usb_interface *iface = usb_ifnum_to_if(dev, 0);
+       snd_usb_audio_quirk_t *quirk = dev->descriptor.idProduct == USB_ID_US428 ? &quirk_2 : &quirk_1;
+
+       snd_printdd("usX2Y_create_usbmidi \n");
+       return snd_usb_create_midi_interface(&usX2Y(card)->chip, iface, quirk);
+}
+
+static int usX2Y_create_alsa_devices(snd_card_t* card)
+{
+       int err;
+
+       do {
+               if ((err = usX2Y_create_usbmidi(card)) < 0) {
+                       snd_printk("usX2Y_create_alsa_devices: usX2Y_create_usbmidi error %i \n", err);
+                       break;
+               }
+               if ((err = usX2Y_audio_create(card)) < 0) 
+                       break;
+               if ((err = snd_card_register(card)) < 0)
+                       break;
+       } while (0);
+
+       return err;
+} 
+
+static int snd_usX2Y_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
+{
+       usX2Ydev_t *priv = hw->private_data;
+       int     lret, err = -EINVAL;
+       snd_printdd( "dsp_load %s\n", dsp->name);
+
+       if (access_ok(VERIFY_READ, dsp->image, dsp->length)) {
+               struct usb_device* dev = priv->chip.dev;
+               char *buf = kmalloc(dsp->length, GFP_KERNEL);
+               if (!buf)
+                       return -ENOMEM;
+               if (copy_from_user(buf, dsp->image, dsp->length)) {
+                       kfree(buf);
+                       return -EFAULT;
+               }
+               err = usb_set_interface(dev, 0, 1);
+               if (err)
+                       snd_printk("usb_set_interface error \n");
+               else
+                       err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6*HZ);
+               kfree(buf);
+       }
+       if (err)
+               return err;
+       if (dsp->index == 1) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(HZ/4);                 // give the device some time 
+               err = usX2Y_AsyncSeq04_init(priv);
+               if (err) {
+                       snd_printk("usX2Y_AsyncSeq04_init error \n");
+                       return err;
+               }
+               err = usX2Y_In04_init(priv);
+               if (err) {
+                       snd_printk("usX2Y_In04_init error \n");
+                       return err;
+               }
+               err = usX2Y_create_alsa_devices(hw->card);
+               if (err) {
+                       snd_printk("usX2Y_create_alsa_devices error %i \n", err);
+                       snd_card_free(hw->card);
+                       return err;
+               }
+               priv->chip_status |= USX2Y_STAT_CHIP_INIT; 
+               snd_printdd("%s: alsa all started\n", hw->name);
+       }
+       return err;
+}
+
+
+int usX2Y_hwdep_new(snd_card_t* card, struct usb_device* device)
+{
+       int err;
+       snd_hwdep_t *hw;
+
+       if ((err = snd_hwdep_new(card, SND_USX2Y_LOADER_ID, 0, &hw)) < 0)
+               return err;
+
+       hw->iface = SNDRV_HWDEP_IFACE_USX2Y;
+       hw->private_data = usX2Y(card);
+       hw->ops.open = snd_usX2Y_hwdep_open;
+       hw->ops.release = snd_usX2Y_hwdep_release;
+       hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status;
+       hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load;
+       hw->ops.mmap = snd_us428ctls_mmap;
+       hw->ops.poll = snd_us428ctls_poll;
+       hw->exclusive = 1;
+       sprintf(hw->name, "/proc/bus/usb/%03d/%03d", device->bus->busnum, device->devnum);
+       return 0;
+}
+
diff --git a/sound/usb/usx2y/usX2Yhwdep.h b/sound/usb/usx2y/usX2Yhwdep.h
new file mode 100644 (file)
index 0000000..d612a26
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef USX2YHWDEP_H
+#define USX2YHWDEP_H
+
+int usX2Y_hwdep_new(snd_card_t* card, struct usb_device* device);
+
+#endif
diff --git a/sound/usb/usx2y/usbus428ctldefs.h b/sound/usb/usx2y/usbus428ctldefs.h
new file mode 100644 (file)
index 0000000..6af1643
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *
+ * Copyright (c) 2003 by Karsten Wiese <annabellesgarden@yahoo.de>
+ *
+ *   This program is free software; you can redistribute 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
+ */
+
+enum E_In84{
+       eFader0 = 0,
+       eFader1,
+       eFader2,
+       eFader3,
+       eFader4,
+       eFader5,
+       eFader6,
+       eFader7,
+       eFaderM,
+       eTransport,
+       eModifier = 10,
+       eFilterSelect,
+       eSelect,
+       eMute,
+
+       eSwitch   = 15,
+       eWheelGain,
+       eWheelFreq,
+       eWheelQ,
+       eWheelPan,
+       eWheel    = 20
+};
+
+#define T_RECORD   1
+#define T_PLAY     2
+#define T_STOP     4
+#define T_F_FWD    8
+#define T_REW   0x10
+#define T_SOLO  0x20
+#define T_REC   0x40
+#define T_NULL  0x80
+
+
+struct us428_ctls{
+       unsigned char   Fader[9];
+       unsigned char   Transport;
+       unsigned char   Modifier;
+       unsigned char   FilterSelect;
+       unsigned char   Select;
+       unsigned char   Mute;
+       unsigned char   UNKNOWN;
+       unsigned char   Switch;      
+       unsigned char   Wheel[5];
+};
+
+typedef struct us428_ctls us428_ctls_t;
+
+typedef struct us428_setByte{
+       unsigned char Offset,
+               Value;
+}us428_setByte_t;
+
+enum {
+       eLT_Volume = 0,
+       eLT_Light
+};
+
+typedef struct usX2Y_volume {
+       unsigned char Channel,
+               LH,
+               LL,
+               RH,
+               RL;
+} usX2Y_volume_t;
+
+struct us428_lights{
+       us428_setByte_t Light[7];
+};
+typedef struct us428_lights us428_lights_t;
+
+typedef struct {
+       char type;
+       union {
+               usX2Y_volume_t  vol;
+               us428_lights_t  lights;
+       } val;
+} us428_p4out_t;
+
+#define N_us428_ctl_BUFS 16
+#define N_us428_p4out_BUFS 16
+struct us428ctls_sharedmem{
+       us428_ctls_t    CtlSnapShot[N_us428_ctl_BUFS];
+       int             CtlSnapShotDiffersAt[N_us428_ctl_BUFS];
+       int             CtlSnapShotLast, CtlSnapShotRed;
+       us428_p4out_t   p4out[N_us428_p4out_BUFS];
+       int             p4outLast, p4outSent;
+};
+typedef struct us428ctls_sharedmem us428ctls_sharedmem_t;
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
new file mode 100644 (file)
index 0000000..44a7381
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ * usbus428.c - ALSA USB US-428 Driver
+ *
+2004-07-13 Karsten Wiese
+       Version 0.7.1:
+       Don't sleep in START/STOP callbacks anymore.
+       us428 channels C/D not handled just for this version, sorry.
+
+2004-06-21 Karsten Wiese
+       Version 0.6.4:
+       Temporarely suspend midi input
+       to sanely call usb_set_interface() when setting format.
+
+2004-06-12 Karsten Wiese
+       Version 0.6.3:
+       Made it thus the following rule is enforced:
+       "All pcm substreams of one usX2Y have to operate at the same rate & format."
+
+2004-04-06 Karsten Wiese
+       Version 0.6.0:
+       Runs on 2.6.5 kernel without any "--with-debug=" things.
+       us224 reported running.
+
+2004-01-14 Karsten Wiese
+       Version 0.5.1:
+       Runs with 2.6.1 kernel.
+
+2003-12-30 Karsten Wiese
+       Version 0.4.1:
+       Fix 24Bit 4Channel capturing for the us428.
+
+2003-11-27 Karsten Wiese, Martin Langer
+       Version 0.4:
+       us122 support.
+       us224 could be tested by uncommenting the sections containing USB_ID_US224
+
+2003-11-03 Karsten Wiese
+       Version 0.3:
+       24Bit support. 
+       "arecord -D hw:1 -c 2 -r 48000 -M -f S24_3LE|aplay -D hw:1 -c 2 -r 48000 -M -f S24_3LE" works.
+
+2003-08-22 Karsten Wiese
+       Version 0.0.8:
+       Removed EZUSB Firmware. First Stage Firmwaredownload is now done by tascam-firmware downloader.
+       See:
+       http://usb-midi-fw.sourceforge.net/tascam-firmware.tar.gz
+
+2003-06-18 Karsten Wiese
+       Version 0.0.5:
+       changed to compile with kernel 2.4.21 and alsa 0.9.4
+
+2002-10-16 Karsten Wiese
+       Version 0.0.4:
+       compiles again with alsa-current.
+       USB_ISO_ASAP not used anymore (most of the time), instead
+       urb->start_frame is calculated here now, some calls inside usb-driver don't need to happen anymore.
+
+       To get the best out of this:
+       Disable APM-support in the kernel as APM-BIOS calls (once each second) hard disable interrupt for many precious milliseconds.
+       This helped me much on my slowish PII 400 & PIII 500.
+       ACPI yet untested but might cause the same bad behaviour.
+       Use a kernel with lowlatency and preemptiv patches applied.
+       To autoload snd-usb-midi append a line 
+               post-install snd-usb-us428 modprobe snd-usb-midi
+       to /etc/modules.conf.
+
+       known problems:
+       sliders, knobs, lights not yet handled except MASTER Volume slider.
+               "pcm -c 2" doesn't work. "pcm -c 2 -m direct_interleaved" does.
+       KDE3: "Enable full duplex operation" deadlocks.
+
+       
+2002-08-31 Karsten Wiese
+       Version 0.0.3: audio also simplex;
+       simplifying: iso urbs only 1 packet, melted structs.
+       ASYNC_UNLINK not used anymore: no more crashes so far.....
+       for alsa 0.9 rc3.
+
+2002-08-09 Karsten Wiese
+       Version 0.0.2: midi works with snd-usb-midi, audio (only fullduplex now) with i.e. bristol.
+       The firmware has been sniffed from win2k us-428 driver 3.09.
+
+ *   Copyright (c) 2002 Karsten Wiese
+ *
+ *   This program is free software; you can redistribute 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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+
+#include <sound/rawmidi.h>
+#include "usx2y.h"
+#include "usbusx2y.h"
+#include "usX2Yhwdep.h"
+
+
+
+MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
+MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.7.2");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
+static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static int boot_devs;
+
+module_param_array(index, int, boot_devs, 0444);
+MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS".");
+module_param_array(id, charp, boot_devs, 0444);
+MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS".");
+module_param_array(enable, bool, boot_devs, 0444);
+MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS".");
+
+
+static int snd_usX2Y_card_used[SNDRV_CARDS];
+
+static void usX2Y_usb_disconnect(struct usb_device* usb_device, void* ptr);
+static void snd_usX2Y_card_private_free(snd_card_t *card);
+
+/* 
+ * pipe 4 is used for switching the lamps, setting samplerate, volumes ....   
+ */
+static void i_usX2Y_Out04Int(struct urb* urb, struct pt_regs *regs)
+{
+#ifdef CONFIG_SND_DEBUG
+       if (urb->status) {
+               int             i;
+               usX2Ydev_t*     usX2Y = urb->context;
+               for (i = 0; i < 10 && usX2Y->AS04.urb[i] != urb; i++);
+               snd_printdd("i_usX2Y_Out04Int() urb %i status=%i\n", i, urb->status);
+       }
+#endif
+}
+
+static void i_usX2Y_In04Int(struct urb* urb, struct pt_regs *regs)
+{
+       int                     err = 0;
+       usX2Ydev_t              *usX2Y = urb->context;
+       us428ctls_sharedmem_t   *us428ctls = usX2Y->us428ctls_sharedmem;
+
+       usX2Y->In04IntCalls++;
+
+       if (urb->status) {
+               snd_printdd("Interrupt Pipe 4 came back with status=%i\n", urb->status);
+               return;
+       }
+
+       //      printk("%i:0x%02X ", 8, (int)((unsigned char*)usX2Y->In04Buf)[8]); Master volume shows 0 here if fader is at max during boot ?!?
+       if (us428ctls) {
+               int diff = -1;
+               if (-2 == us428ctls->CtlSnapShotLast) {
+                       diff = 0;
+                       memcpy(usX2Y->In04Last, usX2Y->In04Buf, sizeof(usX2Y->In04Last));
+                       us428ctls->CtlSnapShotLast = -1;
+               } else {
+                       int i;
+                       for (i = 0; i < 21; i++) {
+                               if (usX2Y->In04Last[i] != ((char*)usX2Y->In04Buf)[i]) {
+                                       if (diff < 0)
+                                               diff = i;
+                                       usX2Y->In04Last[i] = ((char*)usX2Y->In04Buf)[i];
+                               }
+                       }
+               }
+               if (0 <= diff) {
+                       int n = us428ctls->CtlSnapShotLast + 1;
+                       if (n >= N_us428_ctl_BUFS  ||  n < 0)
+                               n = 0;
+                       memcpy(us428ctls->CtlSnapShot + n, usX2Y->In04Buf, sizeof(us428ctls->CtlSnapShot[0]));
+                       us428ctls->CtlSnapShotDiffersAt[n] = diff;
+                       us428ctls->CtlSnapShotLast = n;
+                       wake_up(&usX2Y->us428ctls_wait_queue_head);
+               }
+       }
+       
+       
+       if (usX2Y->US04) {
+               if (0 == usX2Y->US04->submitted)
+                       do
+                               err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC);
+                       while (!err && usX2Y->US04->submitted < usX2Y->US04->len);
+       } else
+               if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) {
+                       if (us428ctls->p4outLast != us428ctls->p4outSent) {
+                               int j, send = us428ctls->p4outSent + 1;
+                               if (send >= N_us428_p4out_BUFS)
+                                       send = 0;
+                               for (j = 0; j < URBS_AsyncSeq  &&  !err; ++j)
+                                       if (0 == usX2Y->AS04.urb[j]->status) {
+                                               us428_p4out_t *p4out = us428ctls->p4out + send; // FIXME if more then 1 p4out is new, 1 gets lost.
+                                               usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->chip.dev,
+                                                                 usb_sndbulkpipe(usX2Y->chip.dev, 0x04), &p4out->val.vol, 
+                                                                 p4out->type == eLT_Light ? sizeof(us428_lights_t) : 5,
+                                                                 i_usX2Y_Out04Int, usX2Y);
+                                               err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC);
+                                               us428ctls->p4outSent = send;
+                                               break;
+                                       }
+                       }
+               }
+
+       if (err) {
+               snd_printk("In04Int() usb_submit_urb err=%i\n", err);
+       }
+
+       urb->dev = usX2Y->chip.dev;
+       usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+/*
+ * Prepare some urbs
+ */
+int usX2Y_AsyncSeq04_init(usX2Ydev_t* usX2Y)
+{
+       int     err = 0,
+               i;
+
+       if (NULL == (usX2Y->AS04.buffer = kmalloc(URB_DataLen_AsyncSeq*URBS_AsyncSeq, GFP_KERNEL))) {
+               err = -ENOMEM;
+       } else
+               for (i = 0; i < URBS_AsyncSeq; ++i) {
+                       if (NULL == (usX2Y->AS04.urb[i] = usb_alloc_urb(0, GFP_KERNEL))) {
+                               err = -ENOMEM;
+                               break;
+                       }
+                       usb_fill_bulk_urb(      usX2Y->AS04.urb[i], usX2Y->chip.dev,
+                                               usb_sndbulkpipe(usX2Y->chip.dev, 0x04),
+                                               usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0,
+                                               i_usX2Y_Out04Int, usX2Y
+                               );
+               }
+       return err;
+}
+
+int usX2Y_In04_init(usX2Ydev_t* usX2Y)
+{
+       int     err = 0;
+       if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL)))
+               return -ENOMEM;
+
+       if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) {
+               usb_free_urb(usX2Y->In04urb);
+               return -ENOMEM;
+       }
+        
+       init_waitqueue_head(&usX2Y->In04WaitQueue);
+       usb_fill_int_urb(usX2Y->In04urb, usX2Y->chip.dev, usb_rcvintpipe(usX2Y->chip.dev, 0x4),
+                        usX2Y->In04Buf, 21,
+                        i_usX2Y_In04Int, usX2Y,
+                        10);
+       err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
+       return err;
+}
+
+static void usX2Y_unlinkSeq(snd_usX2Y_AsyncSeq_t* S)
+{
+       int     i;
+       for (i = 0; i < URBS_AsyncSeq; ++i) {
+               if (S[i].urb) {
+                       usb_unlink_urb(S->urb[i]);
+                       usb_free_urb(S->urb[i]);
+                       S->urb[i] = NULL;
+               }
+       }
+       if (S->buffer)
+               kfree(S->buffer);
+}
+
+
+static struct usb_device_id snd_usX2Y_usb_id_table[] = {
+       {
+               .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+               .idVendor =     0x1604,
+               .idProduct =    USB_ID_US428 
+       },
+       {
+               .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+               .idVendor =     0x1604,
+               .idProduct =    USB_ID_US122 
+       },
+       {
+               .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+               .idVendor =     0x1604,
+               .idProduct =    USB_ID_US224
+       },
+       { /* terminator */ }
+};
+
+static snd_card_t* usX2Y_create_card(struct usb_device* device)
+{
+       int             dev;
+       snd_card_t*     card;
+       for (dev = 0; dev < SNDRV_CARDS; ++dev)
+               if (enable[dev] && !snd_usX2Y_card_used[dev])
+                       break;
+       if (dev >= SNDRV_CARDS)
+               return NULL;
+       card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(usX2Ydev_t));
+       if (!card)
+               return NULL;
+       snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1;
+       card->private_free = snd_usX2Y_card_private_free;
+       usX2Y(card)->chip.dev = device;
+       usX2Y(card)->chip.card = card;
+       init_MUTEX (&usX2Y(card)->open_mutex);
+       INIT_LIST_HEAD(&usX2Y(card)->chip.midi_list);
+       strcpy(card->driver, "USB "NAME_ALLCAPS"");
+       sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
+       sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)",
+               card->shortname, 
+               device->descriptor.idVendor, device->descriptor.idProduct,
+               0,//us428(card)->usbmidi.ifnum,
+               usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum
+               );
+       snd_card_set_dev(card, &device->dev);
+       return card;
+}
+
+
+static void* usX2Y_usb_probe(struct usb_device* device, struct usb_interface *intf, const struct usb_device_id* device_id)
+{
+       int             err;
+       snd_card_t*     card;
+       if (device->descriptor.idVendor != 0x1604 ||
+           (device->descriptor.idProduct != USB_ID_US122 &&
+            device->descriptor.idProduct != USB_ID_US224 &&
+            device->descriptor.idProduct != USB_ID_US428) ||
+           !(card = usX2Y_create_card(device)))
+               return NULL;
+       if ((err = usX2Y_hwdep_new(card, device)) < 0  ||
+           (err = snd_card_register(card)) < 0) {
+               snd_card_free(card);
+               return NULL;
+       }
+       return card;
+}
+
+/*
+ * new 2.5 USB kernel API
+ */
+static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       void *chip;
+       chip = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id);
+       if (chip) {
+               dev_set_drvdata(&intf->dev, chip);
+               return 0;
+       } else
+               return -EIO;
+}
+
+static void snd_usX2Y_disconnect(struct usb_interface *intf)
+{
+       usX2Y_usb_disconnect(interface_to_usbdev(intf),
+                                dev_get_drvdata(&intf->dev));
+}
+
+MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table);
+static struct usb_driver snd_usX2Y_usb_driver = {
+       .owner =        THIS_MODULE,
+       .name =         "snd-usb-usx2y",
+       .probe =        snd_usX2Y_probe,
+       .disconnect =   snd_usX2Y_disconnect,
+       .id_table =     snd_usX2Y_usb_id_table,
+};
+
+static void snd_usX2Y_card_private_free(snd_card_t *card)
+{
+       if (usX2Y(card)->In04Buf)
+               kfree(usX2Y(card)->In04Buf);
+       usb_free_urb(usX2Y(card)->In04urb);
+       if (usX2Y(card)->us428ctls_sharedmem)
+               snd_free_pages(usX2Y(card)->us428ctls_sharedmem, sizeof(*usX2Y(card)->us428ctls_sharedmem));
+       if (usX2Y(card)->chip.index >= 0  &&  usX2Y(card)->chip.index < SNDRV_CARDS)
+               snd_usX2Y_card_used[usX2Y(card)->chip.index] = 0;
+}
+
+/*
+ * Frees the device.
+ */
+static void usX2Y_usb_disconnect(struct usb_device* device, void* ptr)
+{
+       if (ptr) {
+               usX2Ydev_t* usX2Y = usX2Y((snd_card_t*)ptr);
+               struct list_head* p;
+               if (usX2Y->chip_status == USX2Y_STAT_CHIP_HUP)  // on 2.6.1 kernel snd_usbmidi_disconnect()
+                       return;                                 // calls us back. better leave :-) .
+               usX2Y->chip.shutdown = 1;
+               usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
+               usX2Y_unlinkSeq(&usX2Y->AS04);
+               usb_unlink_urb(usX2Y->In04urb);
+               snd_card_disconnect((snd_card_t*)ptr);
+               /* release the midi resources */
+               list_for_each(p, &usX2Y->chip.midi_list) {
+                       snd_usbmidi_disconnect(p, &snd_usX2Y_usb_driver);
+               }
+               if (usX2Y->us428ctls_sharedmem) 
+                       wake_up(&usX2Y->us428ctls_wait_queue_head);
+               snd_card_free_in_thread((snd_card_t*)ptr);
+       }
+}
+
+static int __init snd_usX2Y_module_init(void)
+{
+       return usb_register(&snd_usX2Y_usb_driver);
+}
+
+static void __exit snd_usX2Y_module_exit(void)
+{
+       usb_deregister(&snd_usX2Y_usb_driver);
+}
+
+module_init(snd_usX2Y_module_init)
+module_exit(snd_usX2Y_module_exit)
diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h
new file mode 100644 (file)
index 0000000..71883dc
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef USBUSX2Y_H
+#define USBUSX2Y_H
+#include "../usbaudio.h"
+#include "usbus428ctldefs.h" 
+
+#define NRURBS         2       /* */
+#define NRPACKS                1       /* FIXME: Currently only 1 works.
+                                  usb-frames/ms per urb: 1 and 2 are supported.
+                                  setting to 2 will PERHAPS make it easier for slow machines.
+                                  Jitter will be higher though.
+                                  On my PIII 500Mhz Laptop setting to 1 is the only way to go 
+                                  for PLAYING synths. i.e. Jack & Aeolus sound quit nicely 
+                                  at 4 periods 64 frames. 
+                               */
+
+#define URBS_AsyncSeq 10
+#define URB_DataLen_AsyncSeq 32
+typedef struct {
+       struct urb*     urb[URBS_AsyncSeq];
+       char*   buffer;
+} snd_usX2Y_AsyncSeq_t;
+
+typedef struct {
+       int     submitted;
+       int     len;
+       struct urb*     urb[0];
+} snd_usX2Y_urbSeq_t;
+
+typedef struct snd_usX2Y_substream snd_usX2Y_substream_t;
+
+typedef struct {
+       snd_usb_audio_t         chip;
+       int                     stride;
+       struct urb              *In04urb;
+       void                    *In04Buf;
+       char                    In04Last[24];
+       unsigned                In04IntCalls;
+       snd_usX2Y_urbSeq_t      *US04;
+       wait_queue_head_t       In04WaitQueue;
+       snd_usX2Y_AsyncSeq_t    AS04;
+       unsigned int            rate,
+                               format;
+       int                     refframes;
+       int                     chip_status;
+       struct semaphore        open_mutex;
+       us428ctls_sharedmem_t   *us428ctls_sharedmem;
+       wait_queue_head_t       us428ctls_wait_queue_head;
+       snd_usX2Y_substream_t   *substream[4];
+} usX2Ydev_t;
+
+
+#define usX2Y(c) ((usX2Ydev_t*)(c)->private_data)
+
+int usX2Y_audio_create(snd_card_t* card);
+
+int usX2Y_AsyncSeq04_init(usX2Ydev_t* usX2Y);
+int usX2Y_In04_init(usX2Ydev_t* usX2Y);
+
+#define NAME_ALLCAPS "US-X2Y"
+
+#endif
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
new file mode 100644 (file)
index 0000000..d860c73
--- /dev/null
@@ -0,0 +1,1027 @@
+/*
+ *   US-428 AUDIO
+
+ *   Copyright (c) 2002-2003 by Karsten Wiese
+ *   based on
+
+ *   (Tentative) USB Audio Driver for ALSA
+ *
+ *   Main and PCM part
+ *
+ *   Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
+ *
+ *   Many codes borrowed from audio.c by 
+ *         Alan Cox (alan@lxorguk.ukuu.org.uk)
+ *         Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *
+ *   This program is free software; you can redistribute 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 <sound/driver.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include "usx2y.h"
+#include "usbusx2y.h"
+
+
+struct snd_usX2Y_substream {
+       usX2Ydev_t      *usX2Y;
+       snd_pcm_substream_t *pcm_substream;
+
+       unsigned char           endpoint;               
+       unsigned int            datapipe;               /* the data i/o pipe */
+       unsigned int            maxpacksize;            /* max packet size in bytes */
+
+       char                    prepared,
+                               running,
+                               stalled;
+
+       int                     hwptr;                  /* free frame position in the buffer (only for playback) */
+       int                     hwptr_done;             /* processed frame position in the buffer */
+       int                     transfer_done;          /* processed frames since last period update */
+
+       struct urb              *urb[NRURBS];   /* data urb table */
+       int                     next_urb_complete;
+       struct urb              *completed_urb;
+       char                    *tmpbuf;                        /* temporary buffer for playback */
+       volatile int            submitted_urbs;
+       wait_queue_head_t       wait_queue;
+};
+
+
+
+
+
+
+static int usX2Y_urb_capt_retire(snd_usX2Y_substream_t *subs)
+{
+       struct urb      *urb = subs->completed_urb;
+       snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
+       unsigned char   *cp;
+       int             i, len, lens = 0, hwptr_done = subs->hwptr_done;
+       usX2Ydev_t      *usX2Y = subs->usX2Y;
+
+       for (i = 0; i < NRPACKS; i++) {
+               cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+               if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
+                       snd_printdd("activ frame status %i\n", urb->iso_frame_desc[i].status);
+                       return urb->iso_frame_desc[i].status;
+               }
+               len = urb->iso_frame_desc[i].actual_length / usX2Y->stride;
+               if (! len) {
+                       snd_printk("0 == len ERROR!\n");
+                       continue;
+               }
+
+               /* copy a data chunk */
+               if ((hwptr_done + len) > runtime->buffer_size) {
+                       int cnt = runtime->buffer_size - hwptr_done;
+                       int blen = cnt * usX2Y->stride;
+                       memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, blen);
+                       memcpy(runtime->dma_area, cp + blen, len * usX2Y->stride - blen);
+               } else {
+                       memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, len * usX2Y->stride);
+               }
+               lens += len;
+               if ((hwptr_done += len) >= runtime->buffer_size)
+                       hwptr_done -= runtime->buffer_size;
+       }
+
+       subs->hwptr_done = hwptr_done;
+       subs->transfer_done += lens;
+       /* update the pointer, call callback if necessary */
+       if (subs->transfer_done >= runtime->period_size) {
+               subs->transfer_done -= runtime->period_size;
+               snd_pcm_period_elapsed(subs->pcm_substream);
+       }
+       return 0;
+}
+/*
+ * prepare urb for playback data pipe
+ *
+ * we copy the data directly from the pcm buffer.
+ * the current position to be copied is held in hwptr field.
+ * since a urb can handle only a single linear buffer, if the total
+ * transferred area overflows the buffer boundary, we cannot send
+ * it directly from the buffer.  thus the data is once copied to
+ * a temporary buffer and urb points to that.
+ */
+static int usX2Y_urb_play_prepare(snd_usX2Y_substream_t *subs,
+                                 struct urb *cap_urb,
+                                 struct urb *urb)
+{
+       int count, counts, pack;
+       usX2Ydev_t* usX2Y = subs->usX2Y;
+       snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
+
+       count = 0;
+       for (pack = 0; pack < NRPACKS; pack++) {
+               /* calculate the size of a packet */
+               counts = cap_urb->iso_frame_desc[pack].actual_length / usX2Y->stride;
+               count += counts;
+               if (counts < 43 || counts > 50) {
+                       snd_printk("should not be here with counts=%i\n", counts);
+                       return -EPIPE;
+               }
+
+               /* set up descriptor */
+               urb->iso_frame_desc[pack].offset = pack ? urb->iso_frame_desc[pack - 1].offset + urb->iso_frame_desc[pack - 1].length : 0;
+               urb->iso_frame_desc[pack].length = counts * usX2Y->stride;
+       }
+       if (subs->hwptr + count > runtime->buffer_size) {
+               /* err, the transferred area goes over buffer boundary.
+                * copy the data to the temp buffer.
+                */
+               int len;
+               len = runtime->buffer_size - subs->hwptr;
+               urb->transfer_buffer = subs->tmpbuf;
+               memcpy(subs->tmpbuf, runtime->dma_area + subs->hwptr * usX2Y->stride, len * usX2Y->stride);
+               memcpy(subs->tmpbuf + len * usX2Y->stride, runtime->dma_area, (count - len) * usX2Y->stride);
+               subs->hwptr += count;
+               subs->hwptr -= runtime->buffer_size;
+       } else {
+               /* set the buffer pointer */
+               urb->transfer_buffer = runtime->dma_area + subs->hwptr * usX2Y->stride;
+               if ((subs->hwptr += count) >= runtime->buffer_size)
+                       subs->hwptr -= runtime->buffer_size;                    
+       }
+       urb->transfer_buffer_length = count * usX2Y->stride;
+       return 0;
+}
+
+/*
+ * process after playback data complete
+ *
+ * update the current position and call callback if a period is processed.
+ */
+inline static int usX2Y_urb_play_retire(snd_usX2Y_substream_t *subs, struct urb *urb)
+{
+       snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
+       int             len = (urb->iso_frame_desc[0].actual_length
+#if NRPACKS > 1
+                              + urb->iso_frame_desc[1].actual_length
+#endif
+                              ) / subs->usX2Y->stride;
+
+       subs->transfer_done += len;
+       subs->hwptr_done +=  len;
+       if (subs->hwptr_done >= runtime->buffer_size)
+               subs->hwptr_done -= runtime->buffer_size;
+       if (subs->transfer_done >= runtime->period_size) {
+               subs->transfer_done -= runtime->period_size;
+               snd_pcm_period_elapsed(subs->pcm_substream);
+       }
+       return 0;
+}
+
+inline static int usX2Y_urb_submit(snd_usX2Y_substream_t *subs, struct urb *urb, int frame)
+{
+       int err;
+       if (!urb)
+               return -ENODEV;
+       urb->start_frame = (frame + NRURBS*NRPACKS) & (1024 - 1);
+       urb->hcpriv = NULL;
+       urb->dev = subs->usX2Y->chip.dev; /* we need to set this at each time */
+       if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+               snd_printk("%i\n", err);
+               return err;
+       } else {
+               subs->submitted_urbs++;
+               if (subs->next_urb_complete < 0) 
+                       subs->next_urb_complete = 0;
+       }
+       return 0;
+}
+
+
+static inline int frame_distance(int from, int to)
+{
+       int distance = to - from;
+       if (distance < -512)
+               distance += 1024;
+       else
+               if (distance > 511)
+                       distance -= 1024;
+       return distance;
+}
+
+
+static void usX2Y_subs_set_next_urb_complete(snd_usX2Y_substream_t *subs)
+{
+       int next_urb_complete = subs->next_urb_complete + 1;
+       int distance;
+       if (next_urb_complete >= NRURBS)
+               next_urb_complete = 0;
+       distance = frame_distance(subs->completed_urb->start_frame,
+                                 subs->urb[next_urb_complete]->start_frame);
+       if (1 == distance) {
+               subs->next_urb_complete = next_urb_complete;
+       } else {
+               snd_printdd("distance %i not set_nuc %i %i %i \n", distance, subs->endpoint, next_urb_complete, subs->urb[next_urb_complete]->status);
+               subs->next_urb_complete = -1;
+       }
+}
+
+
+static inline void usX2Y_usbframe_complete(snd_usX2Y_substream_t *capsubs, snd_usX2Y_substream_t *playbacksubs, int frame)
+{
+       {
+               struct urb *urb;
+               if ((urb = playbacksubs->completed_urb)) {
+                       if (playbacksubs->prepared)
+                               usX2Y_urb_play_retire(playbacksubs, urb);
+                       usX2Y_subs_set_next_urb_complete(playbacksubs);
+               }
+               if (playbacksubs->running) {
+                       if (NULL == urb)
+                               urb = playbacksubs->urb[playbacksubs->next_urb_complete + 1];
+                       if (urb && 0 == usX2Y_urb_play_prepare(playbacksubs,
+                                                              capsubs->completed_urb,
+                                                              urb)) {
+                               if (usX2Y_urb_submit(playbacksubs, urb, frame) < 0)
+                                       return;
+                       } else
+                               snd_pcm_stop(playbacksubs->pcm_substream, SNDRV_PCM_STATE_XRUN);
+               }
+               playbacksubs->completed_urb = NULL;
+       }
+       if (capsubs->running)
+               usX2Y_urb_capt_retire(capsubs);
+       usX2Y_subs_set_next_urb_complete(capsubs);
+       if (capsubs->prepared)
+               usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame);
+       capsubs->completed_urb = NULL;
+}
+
+
+static void usX2Y_clients_stop(snd_usX2Y_substream_t *subs)
+{
+       usX2Ydev_t *usX2Y = subs->usX2Y;
+       int i;
+       for (i = 0; i < 4; i++) {
+               snd_usX2Y_substream_t *substream = usX2Y->substream[i];
+               if (substream && substream->running)
+                       snd_pcm_stop(substream->pcm_substream, SNDRV_PCM_STATE_XRUN);
+       }
+}
+
+
+static void i_usX2Y_urb_complete(struct urb *urb, struct pt_regs *regs)
+{
+       snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t*)urb->context;
+
+       subs->submitted_urbs--;
+       if (urb->status) {
+               snd_printk("ep=%i stalled with status=%i\n", subs->endpoint, urb->status);
+               subs->stalled = 1;
+               usX2Y_clients_stop(subs);
+               urb->status = 0;
+               return;
+       }
+       if (urb == subs->urb[subs->next_urb_complete]) {
+               subs->completed_urb = urb;
+       } else {
+               snd_printk("Sequence Error!(ep=%i;nuc=%i,frame=%i)\n",
+                          subs->endpoint, subs->next_urb_complete, urb->start_frame);
+               subs->stalled = 1;
+               usX2Y_clients_stop(subs);
+               return;
+       }
+       if (waitqueue_active(&subs->wait_queue))
+               wake_up(&subs->wait_queue);
+       {
+               snd_usX2Y_substream_t *capsubs = subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE],
+                       *playbacksubs = subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK];
+               if (capsubs->completed_urb &&
+                   (playbacksubs->completed_urb ||
+                    !playbacksubs->prepared ||
+                    (playbacksubs->prepared && (playbacksubs->next_urb_complete < 0 || // not started yet
+                                                frame_distance(capsubs->completed_urb->start_frame,
+                                                               playbacksubs->urb[playbacksubs->next_urb_complete]->start_frame)
+                                                > 0 ||                                 // other expected later
+                                                playbacksubs->stalled))))
+                       usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame);
+       }
+}
+
+
+static int usX2Y_urbs_capt_start(snd_usX2Y_substream_t *subs)
+{
+       int i, err;
+
+       for (i = 0; i < NRURBS; i++) {
+               unsigned long pack;
+               struct urb *urb = subs->urb[i];
+               urb->dev = subs->usX2Y->chip.dev;
+               urb->transfer_flags = URB_ISO_ASAP;
+               for (pack = 0; pack < NRPACKS; pack++) {
+                       urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack;
+                       urb->iso_frame_desc[pack].length = subs->maxpacksize;
+               }
+               urb->transfer_buffer_length = subs->maxpacksize * NRPACKS; 
+               if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+                       snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err);
+                       return -EPIPE;
+               } else {
+                       subs->submitted_urbs++;
+               }
+               urb->transfer_flags = 0;
+       }
+       subs->stalled = 0;
+       subs->next_urb_complete = 0;
+       subs->prepared = 1;
+       return 0;
+}
+
+/* 
+ *  wait until all urbs are processed.
+ */
+static int usX2Y_urbs_wait_clear(snd_usX2Y_substream_t *subs)
+{
+       int timeout = HZ;
+
+       do {
+               if (0 == subs->submitted_urbs)
+                       break;
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               snd_printdd("snd_usX2Y_urbs_wait_clear waiting\n");
+               schedule_timeout(1);
+       } while (--timeout > 0);
+       if (subs->submitted_urbs)
+               snd_printk(KERN_ERR "timeout: still %d active urbs..\n", subs->submitted_urbs);
+       return 0;
+}
+/*
+ * return the current pcm pointer.  just return the hwptr_done value.
+ */
+static snd_pcm_uframes_t snd_usX2Y_pcm_pointer(snd_pcm_substream_t *substream)
+{
+       snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)substream->runtime->private_data;
+       return subs->hwptr_done;
+}
+/*
+ * start/stop substream
+ */
+static int snd_usX2Y_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+{
+       snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)substream->runtime->private_data;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               snd_printdd("snd_usX2Y_pcm_trigger(START)\n");
+               if (subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE]->stalled)
+                       return -EPIPE;
+               else
+                       subs->running = 1;
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               snd_printdd("snd_usX2Y_pcm_trigger(STOP)\n");
+               subs->running = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+
+
+static void usX2Y_urb_release(struct urb** urb, int free_tb)
+{
+       if (*urb) {
+               if (free_tb)
+                       kfree((*urb)->transfer_buffer);
+               usb_free_urb(*urb);
+               *urb = NULL;
+       }
+}
+/*
+ * release a substream
+ */
+static void usX2Y_urbs_release(snd_usX2Y_substream_t *subs)
+{
+       int i;
+       snd_printdd("snd_usX2Y_urbs_release() %i\n", subs->endpoint);
+       usX2Y_urbs_wait_clear(subs);
+       for (i = 0; i < NRURBS; i++)
+               usX2Y_urb_release(subs->urb + i, subs != subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK]);
+
+       if (subs->tmpbuf) {
+               kfree(subs->tmpbuf);
+               subs->tmpbuf = NULL;
+       }
+}
+
+static void usX2Y_substream_prepare(snd_usX2Y_substream_t *subs)
+{
+       snd_printdd("usX2Y_substream_prepare() ep=%i urb0=%p urb1=%p\n", subs->endpoint, subs->urb[0], subs->urb[1]);
+       /* reset the pointer */
+       subs->hwptr = 0;
+       subs->hwptr_done = 0;
+       subs->transfer_done = 0;
+}
+
+
+/*
+ * initialize a substream's urbs
+ */
+static int usX2Y_urbs_allocate(snd_usX2Y_substream_t *subs)
+{
+       int i;
+       int is_playback = subs == subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK];
+       struct usb_device *dev = subs->usX2Y->chip.dev;
+
+       snd_assert(!subs->prepared, return 0);
+
+       if (is_playback) {      /* allocate a temporary buffer for playback */
+               subs->datapipe = usb_sndisocpipe(dev, subs->endpoint);
+               subs->maxpacksize = dev->epmaxpacketout[subs->endpoint];
+               if (NULL == subs->tmpbuf) {
+                       subs->tmpbuf = kcalloc(NRPACKS, subs->maxpacksize, GFP_KERNEL);
+                       if (NULL == subs->tmpbuf) {
+                               snd_printk(KERN_ERR "cannot malloc tmpbuf\n");
+                               return -ENOMEM;
+                       }
+               }
+       } else {
+               subs->datapipe = usb_rcvisocpipe(dev, subs->endpoint);
+               subs->maxpacksize = dev->epmaxpacketin[subs->endpoint];
+       }
+
+       /* allocate and initialize data urbs */
+       for (i = 0; i < NRURBS; i++) {
+               struct urb** purb = subs->urb + i;
+               if (*purb)
+                       continue;
+               *purb = usb_alloc_urb(NRPACKS, GFP_KERNEL);
+               if (NULL == *purb) {
+                       usX2Y_urbs_release(subs);
+                       return -ENOMEM;
+               }
+               if (!is_playback && !(*purb)->transfer_buffer) {
+                       /* allocate a capture buffer per urb */
+                       (*purb)->transfer_buffer = kmalloc(subs->maxpacksize*NRPACKS, GFP_KERNEL);
+                       if (NULL == (*purb)->transfer_buffer) {
+                               usX2Y_urbs_release(subs);
+                               return -ENOMEM;
+                       }
+               }
+               (*purb)->dev = dev;
+               (*purb)->pipe = subs->datapipe;
+               (*purb)->number_of_packets = NRPACKS;
+               (*purb)->context = subs;
+               (*purb)->interval = 1;
+               (*purb)->complete = snd_usb_complete_callback(i_usX2Y_urb_complete);
+       }
+       return 0;
+}
+
+static void i_usX2Y_04Int(struct urb* urb, struct pt_regs *regs)
+{
+       usX2Ydev_t*     usX2Y = urb->context;
+       
+       if (urb->status) {
+               snd_printk("snd_usX2Y_04Int() urb->status=%i\n", urb->status);
+               return;
+       }
+       if (0 == --usX2Y->US04->len)
+               wake_up(&usX2Y->In04WaitQueue);
+}
+/*
+ * allocate a buffer, setup samplerate
+ *
+ * so far we use a physically linear buffer although packetize transfer
+ * doesn't need a continuous area.
+ * if sg buffer is supported on the later version of alsa, we'll follow
+ * that.
+ */
+static struct s_c2
+{
+       char c1, c2;
+}
+       SetRate44100[] =
+{
+       { 0x14, 0x08},  // this line sets 44100, well actually a little less
+       { 0x18, 0x40},  // only tascam / frontier design knows the further lines .......
+       { 0x18, 0x42},
+       { 0x18, 0x45},
+       { 0x18, 0x46},
+       { 0x18, 0x48},
+       { 0x18, 0x4A},
+       { 0x18, 0x4C},
+       { 0x18, 0x4E},
+       { 0x18, 0x50},
+       { 0x18, 0x52},
+       { 0x18, 0x54},
+       { 0x18, 0x56},
+       { 0x18, 0x58},
+       { 0x18, 0x5A},
+       { 0x18, 0x5C},
+       { 0x18, 0x5E},
+       { 0x18, 0x60},
+       { 0x18, 0x62},
+       { 0x18, 0x64},
+       { 0x18, 0x66},
+       { 0x18, 0x68},
+       { 0x18, 0x6A},
+       { 0x18, 0x6C},
+       { 0x18, 0x6E},
+       { 0x18, 0x70},
+       { 0x18, 0x72},
+       { 0x18, 0x74},
+       { 0x18, 0x76},
+       { 0x18, 0x78},
+       { 0x18, 0x7A},
+       { 0x18, 0x7C},
+       { 0x18, 0x7E}
+};
+static struct s_c2 SetRate48000[] =
+{
+       { 0x14, 0x09},  // this line sets 48000, well actually a little less
+       { 0x18, 0x40},  // only tascam / frontier design knows the further lines .......
+       { 0x18, 0x42},
+       { 0x18, 0x45},
+       { 0x18, 0x46},
+       { 0x18, 0x48},
+       { 0x18, 0x4A},
+       { 0x18, 0x4C},
+       { 0x18, 0x4E},
+       { 0x18, 0x50},
+       { 0x18, 0x52},
+       { 0x18, 0x54},
+       { 0x18, 0x56},
+       { 0x18, 0x58},
+       { 0x18, 0x5A},
+       { 0x18, 0x5C},
+       { 0x18, 0x5E},
+       { 0x18, 0x60},
+       { 0x18, 0x62},
+       { 0x18, 0x64},
+       { 0x18, 0x66},
+       { 0x18, 0x68},
+       { 0x18, 0x6A},
+       { 0x18, 0x6C},
+       { 0x18, 0x6E},
+       { 0x18, 0x70},
+       { 0x18, 0x73},
+       { 0x18, 0x74},
+       { 0x18, 0x76},
+       { 0x18, 0x78},
+       { 0x18, 0x7A},
+       { 0x18, 0x7C},
+       { 0x18, 0x7E}
+};
+#define NOOF_SETRATE_URBS ARRAY_SIZE(SetRate48000)
+
+static int usX2Y_rate_set(usX2Ydev_t *usX2Y, int rate)
+{
+       int                     err = 0, i;
+       snd_usX2Y_urbSeq_t      *us = NULL;
+       int                     *usbdata = NULL;
+       DECLARE_WAITQUEUE(wait, current);
+       struct s_c2             *ra = rate == 48000 ? SetRate48000 : SetRate44100;
+
+       if (usX2Y->rate != rate) {
+               do {
+                       us = kmalloc(sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS, GFP_KERNEL);
+                       if (NULL == us) {
+                               err = -ENOMEM;
+                               break;
+                       }
+                       memset(us, 0, sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS); 
+                       usbdata = kmalloc(sizeof(int)*NOOF_SETRATE_URBS, GFP_KERNEL);
+                       if (NULL == usbdata) {
+                               err = -ENOMEM;
+                               break;
+                       }
+                       for (i = 0; i < NOOF_SETRATE_URBS; ++i) {
+                               if (NULL == (us->urb[i] = usb_alloc_urb(0, GFP_KERNEL))) {
+                                       err = -ENOMEM;
+                                       break;
+                               }
+                               ((char*)(usbdata + i))[0] = ra[i].c1;
+                               ((char*)(usbdata + i))[1] = ra[i].c2;
+                               usb_fill_bulk_urb(us->urb[i], usX2Y->chip.dev, usb_sndbulkpipe(usX2Y->chip.dev, 4),
+                                                 usbdata + i, 2, i_usX2Y_04Int, usX2Y);
+#ifdef OLD_USB
+                               us->urb[i]->transfer_flags = USB_QUEUE_BULK;
+#endif
+                       }
+                       if (err)
+                               break;
+
+                       add_wait_queue(&usX2Y->In04WaitQueue, &wait);
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       us->submitted = 0;
+                       us->len =       NOOF_SETRATE_URBS;
+                       usX2Y->US04 =   us;
+               
+                       do {
+                               signed long     timeout = schedule_timeout(HZ/2);
+                       
+                               if (signal_pending(current)) {
+                                       err = -ERESTARTSYS;
+                                       break;
+                               }
+                               if (0 == timeout) {
+                                       err = -ENODEV;
+                                       break;
+                               }
+                               usX2Y->rate = rate;
+                               usX2Y->refframes = rate == 48000 ? 47 : 44;
+                       } while (0);
+               
+                       remove_wait_queue(&usX2Y->In04WaitQueue, &wait);
+               } while (0);
+
+               if (us) {
+                       us->submitted = 2*NOOF_SETRATE_URBS;
+                       for (i = 0; i < NOOF_SETRATE_URBS; ++i) {
+                               usb_unlink_urb(us->urb[i]);
+                               usb_free_urb(us->urb[i]);
+                       }
+                       usX2Y->US04 = NULL;
+                       kfree(usbdata);
+                       kfree(us);
+               }
+       }
+
+       return err;
+}
+
+
+static int usX2Y_format_set(usX2Ydev_t *usX2Y, snd_pcm_format_t format)
+{
+       int alternate, unlink_err, err;
+       struct list_head* p;
+       if (format == SNDRV_PCM_FORMAT_S24_3LE) {
+               alternate = 2;
+               usX2Y->stride = 6;
+       } else {
+               alternate = 1;
+               usX2Y->stride = 4;
+       }
+       list_for_each(p, &usX2Y->chip.midi_list) {
+               snd_usbmidi_input_stop(p);
+       }
+       unlink_err = usb_unlink_urb(usX2Y->In04urb);
+       if ((err = usb_set_interface(usX2Y->chip.dev, 0, alternate))) {
+               snd_printk("usb_set_interface error \n");
+               return err;
+       }
+       if (0 == unlink_err) {
+               usX2Y->In04urb->dev = usX2Y->chip.dev;
+               err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
+       }
+       list_for_each(p, &usX2Y->chip.midi_list) {
+               snd_usbmidi_input_start(p);
+       }
+       usX2Y->format = format;
+       usX2Y->rate = 0;
+       return err;
+}
+
+
+static int snd_usX2Y_pcm_hw_params(snd_pcm_substream_t *substream,
+                                  snd_pcm_hw_params_t *hw_params)
+{
+       int                     err = 0;
+       unsigned int            rate = params_rate(hw_params);
+       snd_pcm_format_t        format = params_format(hw_params);
+       snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params);
+
+       {       // all pcm substreams off one usX2Y have to operate at the same rate & format
+               snd_card_t *card = substream->pstr->pcm->card;
+               struct list_head *list;
+               list_for_each(list, &card->devices) {
+                       snd_device_t *dev;
+                       snd_pcm_t *pcm;
+                       int s;
+                       dev = snd_device(list);
+                       if (dev->type != SNDRV_DEV_PCM)
+                               continue;
+                       pcm = dev->device_data;
+                       for (s = 0; s < 2; ++s) {
+                               snd_pcm_substream_t *test_substream;
+                               test_substream = pcm->streams[s].substream;
+                               if (test_substream && test_substream != substream  &&
+                                   test_substream->runtime &&
+                                   ((test_substream->runtime->format &&
+                                     test_substream->runtime->format != format) ||
+                                    (test_substream->runtime->rate &&
+                                     test_substream->runtime->rate != rate)))
+                                       return -EINVAL;
+                       }
+               }
+       }
+       if (0 > (err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)))) {
+               snd_printk("snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", substream, params_buffer_bytes(hw_params), err);
+               return err;
+       }
+       return 0;
+}
+
+/*
+ * free the buffer
+ */
+static int snd_usX2Y_pcm_hw_free(snd_pcm_substream_t *substream)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
+       snd_printdd("snd_usX2Y_hw_free(%p)\n", substream);
+
+       if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
+               snd_usX2Y_substream_t *cap_subs = subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE];
+               subs->prepared = 0;
+               usX2Y_urbs_release(subs);
+               if (!cap_subs->pcm_substream ||
+                   !cap_subs->pcm_substream->runtime ||
+                   !cap_subs->pcm_substream->runtime->status ||
+                   cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) {
+                       cap_subs->prepared = 0;
+                       usX2Y_urbs_release(cap_subs);
+               }
+       } else {
+               snd_usX2Y_substream_t *playback_subs = subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK];
+               if (!playback_subs->prepared) {
+                       subs->prepared = 0;
+                       usX2Y_urbs_release(subs);
+               }
+       }
+
+       return snd_pcm_lib_free_pages(substream);
+}
+/*
+ * prepare callback
+ *
+ * set format and initialize urbs
+ */
+static int snd_usX2Y_pcm_prepare(snd_pcm_substream_t *substream)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
+       snd_usX2Y_substream_t *capsubs = subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE];
+       int err = 0;
+       snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream);
+
+// Start hardware streams
+// SyncStream first....
+       if (! capsubs->prepared) {
+               if (subs->usX2Y->format != runtime->format)
+                       if ((err = usX2Y_format_set(subs->usX2Y, runtime->format)) < 0)
+                               return err;
+               if (subs->usX2Y->rate != runtime->rate)
+                       if ((err = usX2Y_rate_set(subs->usX2Y, runtime->rate)) < 0)
+                               return err;
+               snd_printdd("starting capture pipe for playpipe\n");
+               usX2Y_urbs_allocate(capsubs);
+               capsubs->completed_urb = NULL;
+               {
+                       DECLARE_WAITQUEUE(wait, current);
+                       add_wait_queue(&capsubs->wait_queue, &wait);
+                       if (0 <= (err = usX2Y_urbs_capt_start(capsubs))) {
+                               signed long timeout;
+                               set_current_state(TASK_INTERRUPTIBLE);
+                               timeout = schedule_timeout(HZ/4);
+                               if (signal_pending(current))
+                                       err = -ERESTARTSYS;
+                               else {
+                                       snd_printdd("%li\n", HZ/4 - timeout);
+                                       if (0 == timeout)
+                                               err = -EPIPE;
+                               }
+                       }
+                       remove_wait_queue(&capsubs->wait_queue, &wait);
+                       if (0 > err)
+                               return err;
+               }
+       }
+
+       if (subs != capsubs) {
+               int u;
+               if (!subs->prepared) {
+                       if ((err = usX2Y_urbs_allocate(subs)) < 0)
+                               return err;
+                       subs->prepared = 1;
+               }
+               while (subs->submitted_urbs)
+               for (u = 0; u < NRURBS; u++) {
+                       snd_printdd("%i\n", subs->urb[u]->status);
+                       while(subs->urb[u]->status  ||  NULL != subs->urb[u]->hcpriv) {
+                               signed long timeout;
+                               snd_printdd("ep=%i waiting for urb=%p status=%i hcpriv=%p\n",
+                                          subs->endpoint, subs->urb[u],
+                                          subs->urb[u]->status, subs->urb[u]->hcpriv);
+                               set_current_state(TASK_INTERRUPTIBLE);
+                               timeout = schedule_timeout(HZ/10);
+                               if (signal_pending(current)) {
+                                       return -ERESTARTSYS;
+                               }
+                       }
+               }
+               subs->completed_urb = NULL;
+               subs->next_urb_complete = -1;
+               subs->stalled = 0;
+       }
+
+       usX2Y_substream_prepare(subs);
+       return err;
+}
+
+static snd_pcm_hardware_t snd_usX2Y_2c =
+{
+       .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+                                SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                                SNDRV_PCM_INFO_MMAP_VALID),
+       .formats =                 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
+       .rates =                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+       .rate_min =                44100,
+       .rate_max =                48000,
+       .channels_min =            2,
+       .channels_max =            2,
+       .buffer_bytes_max =     (2*128*1024),
+       .period_bytes_min =     64,
+       .period_bytes_max =     (128*1024),
+       .periods_min =          2,
+       .periods_max =          1024,
+       .fifo_size =              0
+};
+
+
+
+static int snd_usX2Y_pcm_open(snd_pcm_substream_t *substream)
+{
+       snd_usX2Y_substream_t   *subs = ((snd_usX2Y_substream_t **)
+                                        snd_pcm_substream_chip(substream))[substream->stream];
+       snd_pcm_runtime_t       *runtime = substream->runtime;
+
+       runtime->hw = snd_usX2Y_2c;
+       runtime->private_data = subs;
+       subs->pcm_substream = substream;
+       snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000);
+       return 0;
+}
+
+
+
+static int snd_usX2Y_pcm_close(snd_pcm_substream_t *substream)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
+       int err = 0;
+
+       subs->pcm_substream = NULL;
+
+       return err;
+}
+
+
+static snd_pcm_ops_t snd_usX2Y_pcm_ops = 
+{
+       .open =         snd_usX2Y_pcm_open,
+       .close =        snd_usX2Y_pcm_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    snd_usX2Y_pcm_hw_params,
+       .hw_free =      snd_usX2Y_pcm_hw_free,
+       .prepare =      snd_usX2Y_pcm_prepare,
+       .trigger =      snd_usX2Y_pcm_trigger,
+       .pointer =      snd_usX2Y_pcm_pointer,
+};
+
+
+/*
+ * free a usb stream instance
+ */
+static void usX2Y_audio_stream_free(snd_usX2Y_substream_t **usX2Y_substream)
+{
+       if (NULL != usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]) {
+               kfree(usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]);
+               usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK] = NULL;
+       }
+       kfree(usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]);
+       usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE] = NULL;
+}
+
+static void snd_usX2Y_pcm_private_free(snd_pcm_t *pcm)
+{
+       snd_usX2Y_substream_t **usX2Y_stream = pcm->private_data;
+       if (usX2Y_stream) {
+               snd_pcm_lib_preallocate_free_for_all(pcm);
+               usX2Y_audio_stream_free(usX2Y_stream);
+       }
+}
+
+static int usX2Y_audio_stream_new(snd_card_t *card, int playback_endpoint, int capture_endpoint)
+{
+       snd_pcm_t *pcm;
+       int err, i;
+       snd_usX2Y_substream_t **usX2Y_substream =
+               usX2Y(card)->substream + 2 * usX2Y(card)->chip.pcm_devs;
+
+       for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
+            i <= SNDRV_PCM_STREAM_CAPTURE; ++i) {
+               usX2Y_substream[i] = kcalloc(1, sizeof(snd_usX2Y_substream_t), GFP_KERNEL);
+               if (NULL == usX2Y_substream[i]) {
+                       snd_printk(KERN_ERR "cannot malloc\n");
+                       return -ENOMEM;
+               }
+               init_waitqueue_head(&usX2Y_substream[i]->wait_queue);
+               usX2Y_substream[i]->usX2Y = usX2Y(card);
+       }
+
+       if (playback_endpoint)
+               usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint;
+       usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint;
+
+       err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usX2Y(card)->chip.pcm_devs,
+                         playback_endpoint ? 1 : 0, 1,
+                         &pcm);
+       if (err < 0) {
+               usX2Y_audio_stream_free(usX2Y_substream);
+               return err;
+       }
+
+       if (playback_endpoint)
+               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_pcm_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_pcm_ops);
+
+       pcm->private_data = usX2Y_substream;
+       pcm->private_free = snd_usX2Y_pcm_private_free;
+       pcm->info_flags = 0;
+
+       sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->chip.pcm_devs);
+
+       if ((playback_endpoint &&
+            0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+                                                    SNDRV_DMA_TYPE_CONTINUOUS,
+                                                    snd_dma_continuous_data(GFP_KERNEL),
+                                                    64*1024, 128*1024))) ||
+           0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+                                                    SNDRV_DMA_TYPE_CONTINUOUS,
+                                                    snd_dma_continuous_data(GFP_KERNEL),
+                                                    64*1024, 128*1024))) {
+               snd_usX2Y_pcm_private_free(pcm);
+               return err;
+       }
+       usX2Y(card)->chip.pcm_devs++;
+
+       return 0;
+}
+
+/*
+ * free the chip instance
+ *
+ * here we have to do not much, since pcm and controls are already freed
+ *
+ */
+static int snd_usX2Y_device_dev_free(snd_device_t *device)
+{
+       return 0;
+}
+
+
+/*
+ * create a chip instance and set its names.
+ */
+int usX2Y_audio_create(snd_card_t* card)
+{
+       int err = 0;
+       static snd_device_ops_t ops = {
+               .dev_free = snd_usX2Y_device_dev_free,
+       };
+       
+       INIT_LIST_HEAD(&usX2Y(card)->chip.pcm_list);
+
+       if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, usX2Y(card), &ops)) < 0) {
+//             snd_usX2Y_audio_free(usX2Y(card));
+               return err;
+       }
+
+       if (0 > (err = usX2Y_audio_stream_new(card, 0xA, 0x8)))
+               return err;
+       if (usX2Y(card)->chip.dev->descriptor.idProduct == USB_ID_US428)
+            if (0 > (err = usX2Y_audio_stream_new(card, 0, 0xA)))
+                    return err;
+       if (usX2Y(card)->chip.dev->descriptor.idProduct != USB_ID_US122)
+               err = usX2Y_rate_set(usX2Y(card), 44100);       // Lets us428 recognize output-volume settings, disturbs us122.
+       return err;
+}
diff --git a/sound/usb/usx2y/usx2y.h b/sound/usb/usx2y/usx2y.h
new file mode 100644 (file)
index 0000000..78457e7
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Driver for Tascam US-X2Y USB soundcards
+ *
+ * Copyright (c) 2003 by Karsten Wiese <annabellesgarden@yahoo.de>
+ *
+ *   This program is free software; you can redistribute 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 __SOUND_USX2Y_COMMON_H
+#define __SOUND_USX2Y_COMMON_H
+
+
+#define USX2Y_DRIVER_VERSION   0x0100  /* 0.1.0 */
+
+
+/* hwdep id string */
+#define SND_USX2Y_LOADER_ID            "USX2Y Loader"
+
+/* hardware type */
+enum {
+       USX2Y_TYPE_122,
+       USX2Y_TYPE_224,
+       USX2Y_TYPE_428,
+       USX2Y_TYPE_NUMS
+};
+
+#define USB_ID_US122 0x8007
+#define USB_ID_US224 0x8005
+#define USB_ID_US428 0x8001
+
+/* chip status */
+enum {
+       USX2Y_STAT_CHIP_INIT    = (1 << 0),     /* all operational */
+       USX2Y_STAT_CHIP_HUP     = (1 << 31),    /* all operational */
+};
+
+#endif /* __SOUND_USX2Y_COMMON_H */
index fe62659..965759f 100644 (file)
@@ -1,7 +1,7 @@
 
 obj-y := initramfs_data.o
 
-host-progs  := gen_init_cpio
+hostprogs-y  := gen_init_cpio
 
 clean-files := initramfs_data.cpio.gz